在工业通信、电机控制等项目中,STM32F7 作为 SPI 从机应用广泛,但不少开发者遇到过数据转发不全、SPI OVERRUN 溢出错误等棘手问题。这类问题偶发难复现,看似是 DMA 或时序问题,实则暗藏芯片硬件勘误陷阱。本文基于 ST 官方 LAT1583 文档,结合 STM32F750 实测案例,从现象、排查、根源到解决方案,全流程拆解 SPI 从机通讯异常的核心原因,帮你彻底避坑。
资料获取:经验分享 | LAT1583 一例SPI从机通讯异常的分析
1. 问题现象:数据丢包 + 偶发溢出
某项目使用 STM32F750 作为 SPI 从机,主机通过 GPIO 电平触发从机 EXTI 中断,启动 / 停止 DMA 接收不定长数据。实际运行中频繁出现两个问题:
-
- 数据转发不全:主机下发的数据,从机转发时总是缺失部分字节;
- SPI OVERRUN 错误:调试发现 SPI 状态寄存器频繁报溢出错误,数据直接丢失。
初步排查 DMA 配置、SPI 时序、中断优先级,均未发现异常,问题偶发且无规律,严重影响项目稳定性。
2. 初步排查:卡在 Abort 函数的 “1 秒死锁”
梳理代码逻辑:主机拉低 GPIO 触发下降沿中断,从机调用HAL_SPI_Receive_DMA启动接收;主机拉高 GPIO 触发上升沿中断,从机调用HAL_SPI_Abort终止传输。
理论上 DMA 高速搬移不会导致溢出,但实测发现:上升沿中断中调用HAL_SPI_Abort时,偶尔会卡 1 秒以上。这段时间内若主机再次下发数据,从机无法响应新的下降沿中断,直接导致新一帧数据全部丢失,最终触发 OVERRUN 溢出。
3. 深层根源:芯片硬件勘误 ——BSY 位异常
跟踪HAL_SPI_Abort底层代码,发现卡顿源于SPI_EndRxTxTransaction函数 —— 该函数会循环等待 SPIBSY(忙)位清零。而查阅 STM32F7 勘误手册 ES0290,明确了硬件设计缺陷:
STM32F4/F7 系列 SPI 从机模式下,传输结束后,BSY位可能因 CPU 时钟与 SPI 时钟异步,偶尔异常置高且无法自动清零。
这意味着,当 SPI 传输完成后,硬件BSY位 stuck 在高电平,HAL_SPI_Abort会无限轮询等待,造成 1 秒以上死锁。死锁期间 SPI 外设仍在接收主机数据,FIFO 满后直接触发 OVERRUN 溢出,数据彻底丢失。
4. 解决方案:固件升级 + 超时规避
针对 BSY 位硬件缺陷,ST 官方和实操验证提供两种解决方案,优先推荐固件升级。
方案一:升级 STM32Cube FW_F7 固件(根治)
ST 从V1.16.2 版本开始,已修复该硬件缺陷:
- 底层驱动新增超时机制:若
BSY位超时(默认 1ms,可按 SPI 时钟调整)仍未清零,直接判定传输完成,避免死锁; - 超时时间按 1 字节传输周期计算,适配不同 SPI 时钟频率。
实操步骤:
- 打开 STM32CubeMX,升级 F7 固件包至 V1.16.2 及以上;
- 重新生成代码,编译下载即可,无需修改业务逻辑。
方案二:手动添加超时(临时规避)
若无法升级固件,可修改HAL_SPI_Abort底层代码,增加超时判断:
// 新增超时计数器,按SPI时钟计算1字节传输时间
uint32_t timeout = 1000; // 1ms超时
while ((__HAL_SPI_GET_FLAG(hsp, SPI_FLAG_BSY)) && (timeout-- > 0));
注意:超时时间需匹配 SPI 时钟,过短会误判,过长仍可能卡顿。
本次 SPI 从机通讯异常,核心是STM32F7 硬件 BSY 位缺陷,而非代码或时序问题。这类偶发异常,优先查阅芯片勘误手册,往往能快速定位根源。
避坑核心建议
- STM32F4/F7 系列 SPI 从机项目,务必升级固件至 V1.16.2+,根治 BSY 位死锁问题;
- 开发时避免依赖
BSY位判断传输结束,优先用RXNE(接收就绪)中断或 DMA 完成中断; - 涉及 SPI 从机高速通信时,提前查阅 ES0290 等勘误手册,规避硬件陷阱;
- 遇到偶发通讯异常,优先排查芯片硬件勘误,再排查代码时序。
293