QSPI协议
QSPI是Queued SPI(队列串行外围接口)的缩写,是由摩托罗拉公司推出的SPI协议的一个扩展,比SPI应用更加广泛,现在的FLASH、SRAM等存储器大多支持QSPI协议——QSPI是一种专用的通信接口,可连接单、双或四线SPI存储器
QSPI在SPI协议的基础上增加了队列传输机制。
STM32将Queued SPI协议接口实现为QUADSPI接口。QSPI的实现和SPI基本相似,有部分不同点,在下面列出。
物理连接
QSPI是标准的四信号线SPI,MCU与外设之间由六根线连接:NSS、IO0、IO1、IO2、IO3、SCLK,其中IO0-3是数据线;NSS又称CS,是片选信号线;SCLK又称SCK,是SPI/QSPI的同步时钟线
通信规则
读写命令
有且仅有一条数据线工作
读写数据
四条数据线同时工作
读写地址位时四条数据线发送不同的地址,从机自行分辨,引导向各自的地址;读写具体数据时根据对应的地址读写
STM32F1中的SPI特性
- 三线全双工同步传输
- 双线/三线单工同步传输
- 8位/16位传输帧格式选择
- 主从操作、支持多主模式
- 8个主模式波特率分频系数(最高可达$f_{PCLK}/2$)
- 硬件/软件可调的SS(CS片选信号)管理
- 相关底层配置可编程
- 可触发中断的发送/接收标志
- SPI总线忙碌标志位
- 支持硬件CRC校验
- 支持DMA
STM32F4中的SPI实现
特性
支持SPI的TI模式(主要是片选信号差异,用于TI系的IC)
支持F1的全部功能
与F1的功能基本一致,满足SPI接口的使用需要
硬件实现
- 寄存器配置SPI设置
- 波特率发生器配置SCLK
- MOSI、MISO通过移位寄存器进行收发数据,接收数据即将数据从移位寄存器中复制到RxFIFO;发送数据即将数据放入TxFIFO后送入移位寄存器
- 主控制逻辑电路和通信控制电路调配相关收发过程
HAL库实现
直接将收发数据封装为库函数
STM32F7中的SPI特点
支持F4的所有功能
可调传输帧格式4位到16位(对应原来的8位/16位传输帧格式选择)
具有DMA功能的两个32位内置Rx、Tx FIFO缓存
STM32H7中的SPI实现
特性
- 支持F7的所有功能
- 数据帧格式大小可从4位到32位
- 双时钟域,外设内核时钟可以独立于PCLK
- 更高的主频,8个主模式波特率预分频器(没有改动),主从模式频率均最高可达内核频率的1/2($f_{FCLK}/2$)
- 保护配置和设置
- 数据之间的最小延时、SS与数据流之间的最小延时均可调
- 底层配置可编程,支持SS信号极性、时序可编程和MISOxMOSI交互功能
- 可调节的主器件接收器采样时间
- 配备停止模式(不向外设IP提供时钟)
- 具有停止模式下从器件发送/接收功能和低功耗唤醒功能
- 可编程的FIFO阈值(数据打包)
- 可编程的传输数据量
- 具有DMA功能的Rx、Tx FIFO容量扩大到16x8位或8x8位且可选
- 从模式下,下溢条件可配置,支持级联循环缓冲区
H7的SPI控制器比之前版本的控制器自由度更高(但大部分情况下用不上)
硬件实现
与之前的SPI控制器基本相同,但多了双时钟域的功能块:时钟寄存器控制时钟发生器工作,可以由SPI_PCLK或SPI_KER_CK提供时钟,SPI_KER_CK时钟直接提供给时钟发生器,进而用于SCK或MCK
软件配置
- 在CubeMX中根据外设IC配置GPIO复用和SPI相关设定
- CubeMX会使能外设时钟、配置SPI模式、地址、速率等参数并使能SPI外设;模式设定与f4设定基本类似,可参考【STM32F4外设配置速查总线协议部分】
- 编写对应外设IC的驱动程序
- 设置检验程序,上电后检验驱动程序及外设连接情况
- 编写应用程序
STM32F7/H7中的QSPI实现
QUADSPI主要用于控制SPI FLASH器件(只要满足QSPI时序就可以控制其他器件),工作在以下三种模式:
- 间接模式:使用QUADSPI寄存器执行全部操作
- 状态轮询模式:周期性轮询外部FLASH状态寄存器,如果为1(擦除/烧写完毕)则引发中断
- 内存映射模式:外部FLASH映射到MCU片上SRAM地址空间,系统将其视作内部FLASH存储器进行操作(内部FLASH只读)
特别地,采用双闪存模式时,将同时访问两个QSPI FLASH,吞吐量和容量*2
特性
- 双闪存模式:并行访问两块FLASH,同时收发8位数据
- 支持SDR和DDR模式
- 集成接收/发送FIFO
- 允许8、16、32位数据访问
- 间接模式下可使用DMA
- 可使能的FIFO溢出、超时、操作完成、访问错误中断(异常)
硬件实现
可以实现单线、双线、四线SPI功能
与SPI控制器的不同点主要在于:FIFO和外设寄存器直接接入AHB总线
双闪存模式下,外设引脚复用可选择一个CS信号线或两个CS信号线
其他内容可参考MCU数据手册
软件配置
- 基本配置同上
外部SPI FLASH驱动代码如下,与上面的代码差别不大
1 | /* W25Q256.h文件的函数声明 */ |
- 配置QSPI
这里写的驱动代码是纯HAL库函数实现,外设IC是W25Q64 8MB大小
w25q64.h
1 |
|
w25q64.c
1 |
|
可以看到,使用HAL库函数调用QSPI执行简单读写的基本方式是【QSPI传输配置】——【发送相关命令】——【读取回复】——【执行操作】——【等待接收完毕】
简单读写一般采用下面的方式:
1 | QSPI_Status=QSPI_W25Qxx_ReadBuffer(W25Qxx_ReadBuffer,W25Qxx_TestAddr,W25Qxx_NumByteToTest);//读取数据 |
在软件中加入
1 | QSPI_Status = QSPI_W25Qxx_MemoryMappedMode(); |
即可在各模式之间切换,应当注意:内存映射模式下,SPI FLASH只读,使用以下指令进行读取
1 | memcpy(W25Qxx_ReadBuffer,(uint8_t *)W25Qxx_Mem_Addr+W25Qxx_TestAddr,W25Qxx_NumByteToTest); |
如果需要开启DMA,在.c文件中加入MDMA相关配置即可,如下所示
1 | MDMA_HandleTypeDef QSPI_MDMA_Handle;//定义MDMA句柄 |
MDMA中断下,收发数据的应用层接口不变
1 | QSPI_Status=QSPI_W25Qxx_WriteBuffer(W25Qxx_WriteBuffer,W25Qxx_TestAddr,W25Qxx_NumByteToTest);//写入数据 |
HAL库的QSPI使用总结
- 间接模式下,使用QSPI与使用其他外设一样,通过寄存器配置,与SPI的使用方法大同小异
- 自动轮询模式下,通过查询SPI FLASH的状态寄存器来使用,当读取/写入完成后轮询得到器件空闲,即可进行新一轮写入,可以配合MDMA使用,让其自动写入,CPU在中间还能做其他任务,轮询得到可以继续写入后再向buffer中填充写入数据或读取buffer中数据。可以使用掩码功能来匹配状态位
- 内存映射模式下,将SPI FLASH视为STM32的片上FLASH,可以利用这个功能在片外SPI FLASH中存储程序。读取时使用指针即可,但SPI FLASH只读
W25Qxx系列SPI FLASH特性
详见芯片手册
- 支持标准摩托罗拉SPI协议
- 支持双线/四线SPI,通过写入IC内部的控制寄存器相关控制位,可将WP和Hold引脚作为IO2、IO3使用
相关指令如下
1 | //写保护 |
四字节地址模式:使用该模式可以访问到W25Q256的所有空间,对于容量小于等于16MB的SPI FLASH并不需要开启此模式(仅W25Q256可用此模式)