SPI与QSPI通信协议详解:从时序基础到TI QSPI模块实战配置

发布时间:2026/7/26 6:34:22

SPI与QSPI通信协议详解:从时序基础到TI QSPI模块实战配置 1. 从单车道到四车道SPI与QSPI的核心差异与演进逻辑在嵌入式开发的世界里SPISerial Peripheral Interface就像一条经典的单车道或双车道乡村公路简单、直接足以连接路边的几个小村庄外设。但当你的系统需要从一个大仓库如外部Flash快速搬运海量货物数据时这条老路的带宽就捉襟见肘了。这时QSPIQuad SPI应运而生它本质上是对SPI协议的扩展将数据线从1条MOSI/MISO或2条半双工拓宽到了4条相当于将乡村公路升级为四车道高速公路数据传输的吞吐量得以成倍提升。很多人容易混淆SPI、QSPI和QPI。简单来说SPI是基础协议QSPI特指使用4条数据线进行数据传输的SPI变体通常用于读取操作以提升读取带宽而QPIQuad Peripheral Interface有时被某些芯片厂商用来指代一种更复杂的、命令、地址、数据都使用4线传输的模式但QSPI是更通用和标准的术语。我们讨论的QSPI其核心价值在于内存映射Memory-Mapped模式。在此模式下外部QSPI Flash存储器的内容可以直接映射到处理器的地址空间CPU可以像访问内部RAM一样使用加载Load和存储Store指令直接读写外部Flash无需复杂的底层驱动这为快速启动XIP, Execute In Place和高效数据访问提供了硬件基础。德州仪器TI的MibSPIMulti-buffered SPI和QSPI模块是工业级MCU/MPU中的典型实现。MibSPI在标准SPI基础上增加了多缓冲机制支持更复杂的数据流管理和DMA集成而QSPI模块则专为高速连接外部串行Flash优化。理解它们的时序、模式与寄存器配置是确保通信稳定性和挖掘性能潜力的关键。本文将深入这两者的内部机制特别是结合TI的文档拆解那些时序图背后的含义以及如何通过配置寄存器来驾驭它们。2. 时序基础CPOL与CPHA构成的四种通信模式SPI通信的基石是时钟极性CPOL, Clock Polarity和时钟相位CPHA, Clock Phase。这两个参数的组合定义了数据在时钟线的哪个边沿被采样捕获和哪个边沿被更新输出。这是所有SPI主从设备必须对齐的“暗号”。CPOL (Clock Polarity)定义SPICLK时钟线在空闲状态即传输间隙CS无效时的电平。CPOL 0: 时钟空闲时为低电平。CPOL 1: 时钟空闲时为高电平。CPHA (Clock Phase)定义数据采样的时钟边沿。CPHA 0: 数据在第一个时钟边沿被采样。对于CPOL0第一个边沿是上升沿对于CPOL1第一个边沿是下降沿。数据输出则在对应的另一个边沿。CPHA 1: 数据在第二个时钟边沿被采样。输出则在第一个边沿。由此产生四种模式通常称为Mode 0, 1, 2, 3。TI文档中特别指出其QSPI模块的Mode 1和Mode 2不被支持应避免使用。因此我们重点关注Mode 0和Mode 3这也是最常用的两种模式。模式0 (CPOL0, CPHA0)时钟空闲为低。数据在时钟的上升沿被采样捕获。数据在时钟的下降沿被更新输出。这是最常见、最经典的SPI模式适用于绝大多数SPI Flash、传感器和ADC等器件。模式3 (CPOL1, CPHA1)时钟空闲为高。数据在时钟的下降沿被采样。数据在时钟的上升沿被更新。当总线上存在电平转换器或特定电平要求时可能会用到此模式。注意主从设备的CPOL和CPHA必须完全一致否则通信必然失败。在调试通信问题时首先应使用逻辑分析仪或示波器抓取SPICLK、MOSI、MISO的波形核对时钟极性与相位是否符合从设备数据手册的要求。一个常见的误区是只关注模式编号而不理解其背后的边沿关系。3. 主从模式下的引脚角色与时序参数深度解析SPI通信是主从架构。主设备Master发起并控制整个通信过程产生时钟信号SPICLK从设备Slave响应主设备的命令和数据。引脚的角色在主从模式下是完全相反的。3.1 主模式Master Mode引脚行为当MCU的SPI模块配置为主模式时SPICLK (输出)主设备产生并驱动时钟信号。时钟的频率、极性和相位均由主设备配置。SPISIMO (输出)主设备输出数据到从设备Master Out Slave In。SPISOMI (输入)主设备接收从设备发来的数据Slave Out Master In。SPISCS[7:0] (输出)片选信号由主设备驱动。每个从设备通常独占一个片选线主设备通过拉低对应从设备的片选线来选中它。TI的MibSPI支持最多8个硬件片选。SPIENA (输入)这是一个可选的“从设备就绪”信号。在某些高速或流控场景下从设备可以通过拉低此信号告知主设备“我已准备好接收/发送数据”。主设备在SPIENA为有效电平前不应启动时钟。这在TI的4引脚带SPIENA和5引脚配置中会用到。主模式时序关键点 根据TI文档图23-172至23-175主设备驱动时序的核心在于建立时间Setup Time和保持时间Hold Time的满足。虽然文档没有给出具体纳秒值这取决于具体芯片的电气特性但其时序图揭示了通用规则片选建立主设备在开始产生SPICLK之前需要提前将SPISCS拉低假设低有效。这个提前量tCSS确保从设备在时钟到来前已稳定被选中。数据输出主设备在SPICLK的有效边沿根据CPHA决定是第一个还是第二个边沿之前就需要在SPISIMO上准备好稳定的数据以满足从设备对数据建立时间的要求。数据采样主设备在SPICLK的有效边沿之后会采样SPISOMI上的数据。主设备内部需要保证在采样点数据已经稳定了一段时间从设备的输出保持时间。片选保持在最后一个时钟边沿结束后主设备需要保持SPISCS为低电平一段时间tCSH然后再拉高以确保最后一个数据位被完整处理。3.2 从模式Slave Mode引脚行为当MCU的SPI模块配置为从模式时引脚角色反转SPICLK (输入)接收主设备提供的时钟信号。从设备必须适应主设备设置的时钟频率和模式。SPISIMO (输入)接收主设备发来的数据。SPISOMI (输出)向主设备发送数据。SPISCS (输入)接收主设备的片选信号。只有在此信号有效时从设备才会响应SPICLK并驱动SPISOMI。SPIENA (输出)从设备通过此引脚向主设备指示其状态。例如当从设备如一个慢速ADC转换未完成或缓冲区未就绪时可以拉高SPIENA主设备检测到后会等待。从模式时序关键点 从设备的时序约束更为严格因为它必须响应主设备的时钟。文档图23-176至23-179描述了从设备的时序。片选有效到输出使能从设备在检测到SPISCS有效后需要在规定时间内使能其SPISOMI输出驱动器从高阻态切换到驱动状态这个时间称为输出使能时间tOE。数据输出延迟从设备在SPICLK的有效边沿根据CPHA之后需要在一定时间内tDO将有效数据放到SPISOMI线上以满足主设备的采样保持时间。SPIENA行为这是一个重要的流控机制。文档中提到在4引脚带SPIENA配置下从设备在将新数据写入其发送移位寄存器TX Shift Register时会驱动SPIENA为有效低电平。在接收完最后一位后从设备会取消断言deassertSPIENA。ENABLE_HIGHZ位SPIINT0.24控制SPIENA取消断言后的状态0为推挽输出高电平1则为高阻态由上拉/下拉电阻决定。实操心得在设计自定义SPI从设备如FPGA或CPLD实现时必须严格按照目标主控芯片的时序要求来设计。特别是t_SU数据建立时间和t_HD数据保持时间这两个参数。如果从设备响应太慢可能导致主设备采样到错误数据。使用逻辑分析仪同时抓取主设备的SPICLK和从设备的SPISOMI可以清晰测量出从设备的输出延迟是否在容限之内。4. QSPI模块架构与双端口访问机制TI的QSPI模块设计精妙它并非一个简单的四线SPI控制器而是一个为高效访问串行Flash量身定制的、具备双端口访问能力的专用模块。理解其架构是正确配置和使用的关键。4.1 模块组成SFI_MM_IF 与 SPI_CORE如文档图24-2所示QSPI模块由两大核心部分组成SFI_MM_IF (Serial Flash Interface Memory-Mapped Interface)功能这是面向串行Flash存储器的“快捷通道”。它内置了一个状态机SFI Translator能够根据用户预先配置好的命令格式如读命令码、地址字节数、 dummy cycles等自动将CPU的内存访问读/写请求转换成一整套符合SPI Flash协议的时序波形。优点极大简化了软件操作。开发者只需像读写内存一样访问特定的地址范围如0xE0000000起始硬件会自动完成复杂的SPI事务无需手动拼装命令、地址和数据。限制此端口仅用于与外部SPI Flash进行数据读写不能用于访问Flash内部的配置寄存器、状态寄存器或执行特殊的擦除命令。SPI_CORE (SPI Core)功能这是通用SPI控制器核心。它提供了最基础、最灵活的SPI控制能力可以生成任意格式的SPI帧用于与任何SPI设备通信包括Flash。操作方式通过配置端口地址如0xC0800000起始访问其一系列寄存器SPI_CMD_REG,SPI_DATA_REG等软件需要手动设置命令、写入数据、触发传输、轮询状态或等待中断。用途用于初始化Flash、查询状态、发送擦除命令、写入数据通过SFI_MM_IF写入前需先擦除等所有SFI_MM_IF不支持的精细操作。QSPI_SPI_SWITCH_REG[0] MMPT_S位是连接这两个世界的开关。MMPT_S 0配置端口连接到SPI_CORE。此时软件通过配置端口操作SPI_CORE进行通用SPI通信或Flash的精细控制。MMPT_S 1内存映射端口连接到SPI_CORE。此时CPU对内存映射地址范围的访问会经由SFI_MM_IF转换后通过SPI_CORE发送到外部Flash。这是实现XIP原地执行的关键配置。4.2 工作流程示例读取Flash数据假设我们要从QSPI Flash的0x1000地址读取256字节数据到内部RAM。初始化与配置通过配置端口MMPT_S0配置SPI_CORE的时钟分频器SPI_CLOCK_CNTRL_REG设置通信速率。配置SPI模式、数据延迟等SPI_DC_REG。通过SPI_CORE向Flash发送“写使能”命令0x06。通过SPI_CORE查询Flash状态寄存器等待擦除/写入操作完成。关键步骤配置SFI_MM_IF的SPI_SETUP0_REG假设使用CS0RCMD 0xEB (假设Flash的快速四线读命令码是0xEB)。NUM_A_BYTES 3 (24位地址3字节)。NUM_D_BYTES 1 (快速读模式需要1个dummy cycle)。READ_TYPE 2 (配置为四线读模式)。切换至内存映射模式MMPT_S1。执行内存读取CPU直接访问volatile uint8_t *qspi_flash_addr (volatile uint8_t *)0xE0000000; uint8_t buffer[256]; for(int i 0; i 256; i) { buffer[i] qspi_flash_addr[0x1000 i]; // CPU发起读操作 }当CPU执行qspi_flash_addr[0x1000]这条加载指令时硬件自动完成以下操作 a. 拉低对应的片选线如qspi1_cs[0]。 b. 通过qspi1_d[0]发送命令字节0xEB。 c. 通过qspi1_d[0]发送3字节地址0x001000。 d. 插入1个dummy clock cycle不传输数据。 e. 从qspi1_d[3:0]四条线上并行读取数据每个时钟周期4位即半字节高效传回CPU。 f. 读取完成后拉高片选。这个过程完全由硬件自动完成软件无需干预SPI时序细节效率极高。5. 核心寄存器配置详解与实战编程寄存器是软件与QSPI硬件对话的窗口。错误配置是导致通信失败的最常见原因。下面我们深入几个最关键的寄存器。5.1 时钟控制QSPI_SPI_CLOCK_CNTRL_REG这个寄存器控制着SPI通信的“心跳”。DCLK_DIV [15:0]时钟分频因子。qspi1_sclk的频率由QSPI_FCLK模块功能时钟分频得到。计算公式为qspi1_sclk QSPI_FCLK / (DCLK_DIV 1)。示例若QSPI_FCLK 100 MHz需要产生10 MHz的SPI时钟则DCLK_DIV (100 / 10) - 1 9。CLKEN [31]SPI时钟使能位。这是一个巨坑文档明确指出只有在CLKEN1时写入SPI_CMD_REG启动传输的命令才会被执行。如果忘记使能此位无论你怎么写命令寄存器总线都不会有任何动静。最佳实践是在模块初始化时最后再设置此位为1。5.2 数据与控制命令核心QSPI_SPI_CMD_REG这是发起任何SPI传输的“点火开关”。CMD [18:16]命令字段。定义本次操作的类型。0x0: 保留无效命令可用于提前终止帧传输。0x1:仅接收。从外部设备读取数据数据从qspi1_d[1]对于非双/四线模式或相应数据线输入。0x2:仅发送。向外部设备写入数据数据从qspi1_d[0]输出。0x3:发送后接收全双工。同时进行发送和接收。0x4: 保留。0x5:仅接收四线模式。0x6:仅发送四线模式。0x7:发送后接收四线模式。注意文档特别强调QSPI不支持“直通”模式即把输入数据直接送到输出。这意味着你不能通过设置CMD0x1来同时实现读和写。如果需要先写命令再读数据必须分两次操作先CMD0x2发送命令再CMD0x1读取数据。FLEN [11:0]帧长度Frame Length。定义一帧中包含多少个字Word。注意在双线或四线读模式下传输的字数必须是偶数。WLEN [25:19]字长度Word Length。定义每个字的位数范围1-128位。这个配置决定了数据在SPI_DATA_REGx寄存器组中的对齐方式。关键规则写入SPI_DATA_REG组的数据必须是右对齐的。例如要发送一个8位数据0xA5设置WLEN0x78位然后将0xA5写入QSPI_SPI_DATA_REG[7:0]。SPI_DATA_REG[31:8]的值会被忽略。对于更长的数据比如40位数据0x123456789A需要设置WLEN0x2740位。那么低32位0x56789A写入QSPI_SPI_DATA_REG高8位0x12写入QSPI_SPI_DATA_REG_1[7:0]。WIRQ [14] / FIRQ [15]字完成中断使能 / 帧完成中断使能。设置为1时分别在每个字传输完成或整帧传输完成时在满足中断使能条件下产生中断。5.3 数据寄存器组QSPI_SPI_DATA_REG_3到QSPI_SPI_DATA_REG这四个寄存器共同构成一个128位的移位寄存器。数据移入移出都是MSB优先。QSPI_SPI_DATA_REG_3: 对应移位寄存器的位[127:96]最高32位。QSPI_SPI_DATA_REG_2: 对应位[95:64]。QSPI_SPI_DATA_REG_1: 对应位[63:32]。QSPI_SPI_DATA_REG: 对应位[31:0]最低32位。读取数据时硬件会自动将接收到的数据填充到这个寄存器组软件读取即可。写入数据时软件必须按照WLEN指定的长度将数据右对齐地写入相应的寄存器位置。5.4 设备配置寄存器QSPI_SPI_DC_REG此寄存器为每个片选CS0-CS3独立配置通信参数。CSPi [4*i3]片选极性。控制对应片选信号的有效电平。0 低电平有效1 高电平有效。CKPHi [4i2] / CKPi [4i1]共同决定该片选对应的SPI时钟模式见前文表24-1。记住Mode 1和2不被支持。DDi [4*i0]数据延迟。定义在片选有效后延迟多少个qspi1_sclk周期才开始输出数据。范围0-3。这对于某些需要较长时间从休眠中唤醒或准备数据的从设备非常有用。5.5 串行Flash接口配置QSPI_SPI_SETUP0_REG~QSPI_SPI_SETUP3_REG这四个寄存器分别对应四个片选用于定义连接在该片选上的SPI Flash的读/写命令格式。这是SFI_MM_IF能自动操作的关键。RCMD [7:0]/WCMD [23:16]读/写命令字节。例如标准SPI Flash的页编程命令0x02四线快速读命令0xEB。NUM_A_BYTES [9:8]地址字节数。1-4字节取决于Flash容量24位或32位地址。NUM_D_BYTES [11:10]Dummy字节数。在快速读Fast Read模式下发送地址后需要插入几个额外的时钟周期不传输数据供Flash内部准备数据通常为1或2个字节周期。READ_TYPE [13:12]读类型。0 单线读1 双线读2 四线读。此配置必须与Flash支持的模式及物理连接匹配。6. 实战配置流程与避坑指南下面以一个典型的场景为例配置TI AM335x处理器的QSPI模块以四线模式连接一颗Winbond W25Q128JV SPI Flash并实现内存映射读取。6.1 初始化配置流程引脚复用配置首先通过PinMux工具或寄存器将用到QSPI的引脚qspi1_sclk,qspi1_cs0,qspi1_d[3:0]功能设置为QSPI模式并配置上拉/下拉电阻通常数据线配置上拉。时钟与电源使能确保PRCM电源与时钟管理模块为QSPI模块提供了功能时钟QSPI_FCLK和接口时钟。软件初始化通过配置端口MMPT_S0 a.复位模块如果存在软复位位。 b.配置QSPI_SPI_DC_REG * 设置CSP00CS0低有效。 * 设置CKPH00,CKP00SPI Mode 0。 * 设置DD00无数据延迟可根据Flash要求调整。 c.配置QSPI_SPI_CLOCK_CNTRL_REG * 计算并设置DCLK_DIV得到目标SPI时钟例如初始化为较低速率如5MHz用于初始化。 *先不要设置CLKEN1。 d.通过SPI_CORE初始化Flash * 使用CMD0x2发送命令发送0xABRelease Power-down或0x660x99Enable Reset / Reset Device命令唤醒或复位Flash。 * 发送0x06Write Enable命令。 * 发送0x01Write Status Register命令配置状态寄存器将QEQuad Enable位设置为1使能四线输出模式。这一步至关重要否则四线读无法工作。* 轮询状态寄存器等待写操作完成。 e.配置SFI_MM_IF寄存器 * 配置QSPI_SPI_SETUP0_REG *RCMD 0xEB(W25Q128JV的四线快速读命令)。 *NUM_A_BYTES 3(24位地址)。 *NUM_D_BYTES 1(该Flash在0xEB命令下需要8个dummy clocks即1个字节)。 *READ_TYPE 2(四线读)。 f.使能时钟并切换模式 * 设置QSPI_SPI_CLOCK_CNTRL_REG.CLKEN 1。 * 设置QSPI_SPI_SWITCH_REG.MMPT_S 1切换到内存映射模式。内存映射访问现在你可以通过指针访问0xE0000000开始的地址来读取Flash了。如果需要更高的读取速度可以回到步骤3c通过QSPI_SPI_CLOCK_CNTRL_REG提高SPI时钟频率例如升至50MHz。6.2 常见问题排查与调试技巧问题通信完全无波形。检查1时钟使能。确认QSPI_SPI_CLOCK_CNTRL_REG.CLKEN位已设置为1。这是最容易被忽略的一步。检查2引脚复用。使用寄存器查看工具或示波器确认相关引脚已正确配置为QSPI功能而非GPIO或其他功能。检查3片选信号。确认CSPi极性配置正确并且主程序确实发起了传输写CMD寄存器。用示波器测量片选引脚是否有跳变。问题有时钟和片选但数据线无输出或数据错误。检查1SPI模式。用示波器对比SPICLK和MOSI或D0的波形。确认CPOL和CPHA与从设备要求一致。Mode 0是最常见的。检查2Flash的QE位。如果进行四线读操作必须确保Flash状态寄存器的QE位已被正确使能。许多四线读失败都是因为这个位没开。可以通过SPI_CORE发送读状态寄存器命令0x05来验证。检查3命令、地址、数据对齐。确认发送的命令、地址字节是否符合Flash数据手册要求。在通过SPI_CORE手动发送时确保数据已按WLEN要求右对齐写入DATA_REG。检查4Dummy Cycles。在快速读模式下dummy cycles的数量必须配置正确。参考Flash数据手册NUM_D_BYTES或NUM_D_BITS的设置必须匹配。问题内存映射读取失败读回全0xFF或错误数据。检查1MMPT_S开关。确认在访问内存映射区域前已设置QSPI_SPI_SWITCH_REG.MMPT_S 1。检查2SPI_SETUP寄存器。仔细核对RCMD、NUM_A_BYTES、NUM_D_BYTES、READ_TYPE是否与当前连接的Flash型号完全匹配。一个字节的错误都会导致序列不对。检查3地址映射。确认CPU访问的地址是否正确偏移到了Flash的物理地址。例如访问0xE0001000对应的是Flash的0x1000地址。检查4Cache与MMU。在启用Cache或MMU的系统中确保为QSPI的内存映射区域如0xE0000000配置了正确的属性通常为非缓存、非缓冲、设备内存类型以防止预取或乱序访问导致问题。调试利器逻辑分析仪投资一个支持SPI协议解码的逻辑分析仪如Saleae是极佳选择。它可以同步捕获SCLK、CS、D0-D3所有信号并自动解码出字节甚至命令让你直观地看到通信序列是否正确数据内容是什么极大提升调试效率。最后务必反复阅读你所使用的具体芯片的勘误表Errata。有些芯片的QSPI模块在特定频率、特定模式下可能存在已知问题官方会给出解决方案或替代方案。例如某些型号在极高时钟频率下使用内存映射模式可能需要特殊的配置序列。这些信息是稳定性的最后一道保险。

相关新闻