STM32 QSPI接口GD/W25Qxx配置简要
- 🥕阅读推荐有关介绍QSPI协议内容比较全面和详细的文章:《STM32F7QSPI学习笔记——读写N25Q128》
- 📝本篇会具体涉及介绍Winbond(华邦)和GD(兆易创新) NOR flash相关型号指令差异。由于网络上可以搜索到很多相关QSPI相关知识内容,不对QSPI通讯内容做深度解析。
- 🔖首先确保所使用的STM32型号,硬件上是否支持QSPI功能。
- 由于GD25QXX和对应的W25Qxx 芯片型号较多,芯片出厂,默认状态寄存器关键位存在差异,在没有进行状态寄存器关键位做配置的情况下。两者的驱动代码不能互为通用,代码上可以通过型号辨别,以及对状态寄存器关键位的使能配置,可以整合为一套通用的驱动代码。
- 🌿QSPI支持三种工作模式:间接模式、状态轮询模式和内存映射模式:
- 间接模式:使用QSPI寄存器执行全部操作。
- 状态轮询模式:周期性读取外部FLASH状态寄存器,当标志位置1时会产生中断(如擦除或烧写完成,产生中断)。
- 内存映射模式:外部FLASH映射到微控制器地址空间,从而系统将其视作内部存储器进行访问。
在间接模式下也可以切换为内存映射模式进行访问,切换过程需要重新对QSPI外设进行复位和重新初始化QSPI操作,代码操作比较麻烦,好处就是提升了读取访问速度。如果需要进行擦除或编程操作,还需要切换为间接模式下进行。
- QUADSPI 功能框图(见STM32H750参考手册)
图中BK2只有在双闪存模式下才需要。
-
4线SPI结构框图
-
🧲QSPI通讯序列
- QUADSPI 通过命令与 FLASH 通信 每条命令包括指令、地址、交替字节、空指令和数据这 五个阶段 任一阶段均可跳过,但至少要包含指令、地址、交替字节或数据阶段之一。
- nCS 在每条指令开始前下降,在每条指令完成后再次上升
-
🌟对于这5个阶段的通讯内容,从STM32软件代码配置上的来说,包含了对QUADSPI 通信配置寄存器 (QUADSPI_CCR)的配置方法和要素。
-
STM32H7 QUADSPI 通信配置寄存器 (QUADSPI_CCR)
-
📄对应的相关初始化代码:
static HAL_StatusTypeDef QSPI_SendCommand(uint32_t instruction,
uint32_t address,
uint32_t addressMode,
uint32_t addressSize,
uint32_t dummyCycles,
uint32_t nbData,
uint32_t dataMode,
uint32_t siooMode)
{
QSPI_CommandTypeDef sCommand = {
0};
sCommand.Instruction = instruction;//指令段:填写指令
/*
QSPI_INSTRUCTION_NONE
QSPI_INSTRUCTION_1_LINE
QSPI_INSTRUCTION_2_LINES
QSPI_INSTRUCTION_4_LINES
*/
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;//指令模式:在指令段使用几条线传输该指令参数:0 - 4线
sCommand.Address = address;//地址段:填写地址
/*
QSPI_ADDRESS_NONE
QSPI_ADDRESS_1_LINE
QSPI_ADDRESS_2_LINES
QSPI_ADDRESS_4_LINES
*/
sCommand.AddressMode = addressMode;//地址模式:在地址段使用几条数据线传输该地址参数:0-4线
/*
小于或等于16MB容量选择QSPI_ADDRESS_24_BITS,大于16MB选择QSPI_ADDRESS_32_BITS
QSPI_ADDRESS_8_BITS
QSPI_ADDRESS_16_BITS
QSPI_ADDRESS_24_BITS
QSPI_ADDRESS_32_BITS
*/
sCommand.AddressSize = addressSize;//地址长度
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;//交替字节模式,一般不使用
/*
GD25Q64型号:
Quad Output Fast Read (6BH)指令:8个空指令周期
Quad I/O Fast Read (EBH)指令: 6个空指令周期
具体参数查看对应Nor flash手册
*/
sCommand.DummyCycles = dummyCycles;//空指令周期,具体参数查看对应Nor flash手册
sCommand.NbData = nbData;//数据长度
/*
QSPI_DATA_NONE
QSPI_DATA_1_LINE
QSPI_DATA_2_LINES
QSPI_DATA_4_LINES
具体使用,查看对应Nor flash手册,对应指令
*/
sCommand.DataMode = dataMode;//数据模式,在数据传输段,用几条数据线传输数据
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;//SDR单闪存模式,不启用。
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
/*
若 DMODE = 00,对应上面的sCommand.DataMode=QSPI_DATA_NONE则跳过数据阶段。
QSPI_SIOO_INST_EVERY_CMD 在每个事务中发送指令
QSPI_SIOO_INST_ONLY_FIRST_CMD 仅为第一条命令发送指令
*/
sCommand.SIOOMode = siooMode; //在DMODE = 00,该参数设置无效。
Status = HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
return Status;
}
- 🌿指令段:指令模式,传输指令一般为:
QSPI_INSTRUCTION_1_LINE
。也就是使用一条数据线来传输指令
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;//需要用一条数据线来传输指令
- 🌿地址段:地址模式,传输地址指令一般为:
QSPI_ADDRESS_NONE
(不需要地址)、QSPI_ADDRESS_1_LINE
(需要使用一条数据线用来传输地址指令)两种。
sCommand.AddressMode = QSPI_ADDRESS_NONE;//无需地址
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;//需要一条数据线来传输地址指令
QSPI_ADDRESS_NONE
(不需要地址)情况:读写Nor flash内部状态寄存器操作。
- 🌿地址段:地址长度一般为:
QSPI_ADDRESS_24_BITS
(访问低于或等于16MB容量地址上的所有数据)、QSPI_ADDRESS_32_BITS
(间接模式下可访问等于或大于32MB容量的地址所有数据:范围2^32 = 4GB。需要注意QUADSPI 采用内存映射模式下,即使 FLASH 容量更大,寻址空间也无法超过 256MB。)
- 🔖32 位寻址下, Flash 容量最高可达 4GB,在内存映射模式下的可寻址空间限制为 256MB。 如果 DFM = 1,DDR双闪存模式,FSIZE 表示两个 Flash 容量的总和:512MB。
s_command.AddressSize = QSPI_ADDRESS_24_BITS; // 24位地址
s_command.AddressSize = QSPI_ADDRESS_32_BITS; // 32位地址
对于通讯的整个过程,只需要留意3个状态:WIP(BUSY)用于查看擦除/编程操作是否正在进行、QE用于使能4线模式(Quad)和WREN写使能位其实和WIP位对应,该位决定接下来是否可以进行编程、擦写操作。
- 📜GD25Q64读写测试:
- 📜W25Q64读写测试:
- 基于QSPI片外flash下载算法实现的片外启动APP程序:
📗 NOR FLASH 存储器介绍
- 🍁Winbond(华邦)W25Q64存储器功能控制结构图
- GD(兆易创新)GD25Q64
- 内存空间结构: 一页(Page)256字节,4K(4096 字节)为一个扇区(Sector),16个扇区为1块(Block),容量为8M字节,共有128个块,2048 个扇区。
- 支持页编程。每页大小由256字节组成,每页的256字节用一次页编程指令即可完成。
- 擦除指令通用: 16页(1个扇区4K)、32K、64K、全片擦除操作。
两者常规操作指令互为通用。在QE位都配置为使能状态情况下,除了在读取厂商ID有差异外,读取数据功能函数通用。测试了基于W25QXX制作的片外QSPI下载算法文件都可以兼容GD25XX使用。(前提是下载算法中没有对应闪存厂商ID校验,芯片相关状态寄存器位没有写保护)
🌼Nor Flash操作流程
- 写入操作时:
写入操作前,必须先进行写使能位.
每个数据位只能由1改写为0,不能由0改写为1
写入数据前必须先擦除,擦除后,所有数据位变为1。.(删除目录实际上是填充0xff)
擦除必须按最小擦除单元进行(一个扇区:4kb)
连续写入多字节时,最多写入一页(256字节)的数据,超过页尾位置的数据,会回到页首覆盖写入
写入操作结束后,芯片进入忙状态,不响应新的读写操作
- 读取操作时:
直接调用读取时序,快速读取(Fast Read Quad I/O (EBh)),需要QE=1,可以不需要使能
Write Enable (WREN) (06H)
,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取.
📘Nor flash状态寄存器介绍
- 🌿winbond(华邦)W25QXX状态寄存器访问指令
- 📄具体状态寄存器位说明
📘 GD25QXX状态寄存器
- 🌿GD(兆易创新)GD25QXX状态寄存器总表:
🔰状态寄存器差异化说明
- 🌿QE位:该位属于非易失性(non-volatile),数据在断电后仍然能够保持的特性。一旦该位配置位1,将一直保持其状态,不会因断电丢失。
- 🔖winbond(华邦)W25QXX,该位出厂默认状态是根据芯片具体型号决定该位默认状态是否为
1
- When the QE bit is set to a 0 state (factory default for part numbers with ordering options “
IM
”&“JM
”).- When the QE bit is set to a 1 (factory fixed default for part numbers with ordering options “
IQ
” & “JQ
”),
- 🔖GD(兆易创新)GD25Qxx,该位出厂默认状态是
0
,如需要使用QSPI 模式,必须先将该位配置为1才行。
- ✨QE位的使能,对于QSPI 4线Quad访问方式尤为重要。
📘指令介绍
-
🌿winbond(华邦)W25Q64指令:
-
🌿GD(兆易创新)GD25Q64指令集
- 🌾不同容量的nor flash型号,指令数量会有所不同,容量超过16MB型号,其指令会有所增加。
🛠状态寄存器配置
- 🌿状态寄存器1,QE位配置流程说明
👉针对GD(兆易创新)GD25Q64,经测试,如需修改QE位,需要通过使用读取状态寄存器1(0x01)的命令,然后写2个字节数据(S0-S7、S8-S16),进行修改。
- 🔖个人测试时,如果单独写状态寄存器2(0x31)的QE位,会写入不成功。目前不知道是什么原因。相同的函数针对W25Q64单独写QE位使能没有问题。
- QE位是否配置成功,可以通过读状态寄存器(0x35),查询状态寄存器2的QE位。
-
Write Status Register (WRSR) (01H or 31H or 11H)
The Write Status Register (WRSR) command allows new values to be written to the Status Register. Before it can be accepted, a Write Enable (WREN) command must previously have been executed. After the Write Enable (WREN)
command has been decoded and executed, the device sets the Write Enable Latch (WEL).
The Write Status Register (WRSR) command has no effect on S15, S10, S1 and S0 of the Status Register. For command code of “01H” / “31H” / “11H”, the Status Register bits S7~S0 / S15~S8 / S23~S16 would be written. CS# must be driven high after the eighth bit of the data byte has been latched in. Otherwise, the Write Status Register (WRSR) command is not executed. As soon as CS# is driven high, the self-timed Write Status Register cycle (whose duration is tW) is initiated. While the Write Status Register cycle is in progress, the Status Register may still be read to check the value of the Write In Progress (WIP) bit. The Write In Progress (WIP) bit is 1 during the self-timed Write Status Register cycle, and is 0 when it is completed. When the cycle is completed, the Write Enable Latch (WEL) is reset.
The Write Status Register (WRSR) command allows the user to change the values of the Block Protect (BP4, BP3, BP2, BP1, and BP0) bits, to define the size of the area that is to be treated as read-only. The Write Status Register (WRSR) command also allows the user to set or reset the Status Register Protect (SRP1 and SRP0) bits in accordance with the Write Protect (WP#) signal. The Status Register Protect (SRP1 and SRP0) bits and Write Protect (WP#) signal allow the device to be put in the Hardware Protected Mode. The Write Status Register (WRSR) command is not executed once the Hardware Protected Mode is entered -
🧬 时序图:
-
🌿读状态寄存器代码实现:
int qspi_flash_read_status1(uint8_t *status) {
//读状态寄存器1
QSPI_CommandTypeDef command;
command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
command.AddressSize = QSPI_ADDRESS_24_BITS;
command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
command.DdrMode = QSPI_DDR_MODE_DISABLE;
command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
command.Instruction = READ_STATUS_REG_CMD; //0x05,读取:S7-S0
command.AddressMode = QSPI_ADDRESS_NONE;
command.DataMode = QSPI_DATA_1_LINE;
command.DummyCycles = 0;
command.NbData = 1;//1个字节
if (HAL_QSPI_Command(&hqspi