跳转至

Quad SPI存储器接口SFC

  • 最大支持{128M-BIT SPI NOR FLASH}
  • 所有读写数据操作都{只支持Word操作}
  • 支持外置Flash控制命令
    • 读取ID和MID
    • 读写状态寄存器
    • 写入使能和禁止
    • Flash读
      • 标准模式
      • 双线IO模式
      • 四线IO模式
    • Flash页编程
      • 标准页写
      • 四线页写
      • 支持4~256任意word长度的页写
    • Flash擦除
      • Sector擦除
      • Block擦除(32K/64K)
      • 全芯片擦除
    • 编程(擦除)挂起和恢复
    • Deep Power-Down模式进入及恢复

注意事项

注意

部分型号SPI NOR FLASH默认Quad Enable (QE) bit为0,需要先置1才能使用Quad SPI功能。

示例代码

dev_sfc.c
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "main.h"

static uint32_t SFC_ReadID(uint32_t *id)
{
    uint32_t res;

    SFC->CFG &= ~SFC_CFG_CMDTYPE_Msk;
    SFC->CFG |= (1 << SFC_CFG_CMDWREN_Pos) |
                (3 << SFC_CFG_CMDTYPE_Pos);
    SFC->CMD = 0x90;

    SFC->GO = 1;
    while(SFC->GO);
    SFC->CFG &= ~SFC_CFG_WREN_Msk;

    *id = SFC->DATA;
    if(SFC->IF & SFC_IF_ERR_Msk)
        res = SFC_RES_ERR;
    else if(SFC->IF & SFC_IF_TO_Msk)
        res = SFC_RES_TO;
    else
        res = SFC_RES_OK;

    return res;
}

static uint32_t SFC_ReadStatusRegister(uint8_t status_reg,uint8_t *data)
{
    uint32_t res;

    SFC->CFG &= ~SFC_CFG_CMDTYPE_Msk;
    SFC->CFG |= (1 << SFC_CFG_CMDWREN_Pos) |
                (1 << SFC_CFG_CMDTYPE_Pos);
    SFC->CMD = status_reg;

    SFC->GO = 1;
    while(SFC->GO);
    SFC->CFG &= ~SFC_CFG_WREN_Msk;

    *data = SFC->DATA;

    if(SFC->IF & SFC_IF_ERR_Msk)
        res = SFC_RES_ERR;
    else if(SFC->IF & SFC_IF_TO_Msk)
        res = SFC_RES_TO;
    else
        res = SFC_RES_OK;

    return res;
}

static uint32_t SFC_WriteStatusRegister(uint8_t status_reg,uint8_t status_reg1)
{
    uint32_t res;

    SFC->CFG &= ~SFC_CFG_CMDTYPE_Msk;
    SFC->CFG |= (1 << SFC_CFG_WREN_Pos) | //write enable
                (1 << SFC_CFG_CMDWREN_Pos) |
                (6 << SFC_CFG_CMDTYPE_Pos);
    SFC->CMD = 0x01;

    SFC->DATA = (status_reg1 << 8) | status_reg;

    SFC->GO = 1;
    while(SFC->GO);
    SFC->CFG &= ~SFC_CFG_WREN_Msk;

    if(SFC->IF & SFC_IF_ERR_Msk)
        res = SFC_RES_ERR;
    else if(SFC->IF & SFC_IF_TO_Msk)
        res = SFC_RES_TO;
    else
        res = SFC_RES_OK;

    return res;
}

static uint32_t SFC_Enable_QuadSPI(void)
{
    uint32_t res;

    uint8_t status_reg;
    uint8_t status_reg1;

    res = SFC_ReadStatusRegister(0x05,&status_reg);
    if(res != SFC_RES_OK)
        return res;
    res = SFC_ReadStatusRegister(0x35 ,&status_reg1);
    if(res != SFC_RES_OK)
        return res;

    status_reg1 |= (1 << 1); //enable QuadSPI

    res = SFC_WriteStatusRegister(status_reg,status_reg1);
    return res;
}

void SFC_Config(uint8_t width)
{
    SFC_InitStructure SFC_initStruct;

    PORT_Init(PORTD, PIN5, PORTD_PIN5_FSPI_SCLK, 0);
    PORT_Init(PORTD, PIN6, PORTD_PIN6_FSPI_SSEL, 0);
    PORT_Init(PORTD, PIN8, PORTD_PIN8_FSPI_MOSI, 1);
    PORT_Init(PORTD, PIN7, PORTD_PIN7_FSPI_MISO, 1);
    PORT_Init(PORTD, PIN3, PORTD_PIN3_FSPI_DATA2, 1);
    PORT_Init(PORTD, PIN4, PORTD_PIN4_FSPI_DATA3, 1);

    switch (width)
    {
    case 1:
    default:
        SFC_initStruct.ClkDiv = SFC_CLKDIV_2;
        SFC_initStruct.Cmd_Read = 0x03;
        SFC_initStruct.Width_Read = SFC_RDWIDTH_1;
        SFC_initStruct.Cmd_PageProgram = 0x02;
        SFC_initStruct.Width_PageProgram = SFC_PPWIDTH_1;
        break;

    case 2:
        SFC_initStruct.ClkDiv = SFC_CLKDIV_2;
        SFC_initStruct.Cmd_Read = 0xBB;
        SFC_initStruct.Width_Read = SFC_RDWIDTH_2;
        SFC_initStruct.Cmd_PageProgram = 0x02;
        SFC_initStruct.Width_PageProgram = SFC_PPWIDTH_1;
        break;

    case 4:
        SFC_initStruct.ClkDiv = SFC_CLKDIV_4;
        SFC_initStruct.Cmd_Read = 0xEB;
        SFC_initStruct.Width_Read = SFC_RDWIDTH_4;
        SFC_initStruct.Cmd_PageProgram = 0x32;
        SFC_initStruct.Width_PageProgram = SFC_PPWIDTH_4;
        break;
    }

    SFC_Init(&SFC_initStruct);

    SFC_Enable_QuadSPI();
}