STM32F407跑FreeRTOS,SPI DMA传ADC数据偶尔丢一包,快被搞疯了
板子是STM32F407+FreeRTOS,SPI2用DMA从外部ADC(AD7606)读8通道数据,10ms一帧。现在批量500台里有十几台,运行几个小时后偶尔丢一整包,DMA完成中断进了但接收buffer后半段全是0。试过把DMA buffer改成32字节对齐、加大栈、把SPI中断优先级调到最高,都没根治。示波器看CS和SCLK时序正常,怀疑是DMA和CPU抢总线或者cache一致性问题,但F407没有D-Cache啊。产线等着出货,头大。有没有兄弟踩过类似的坑?是不是我中断里直接喂看门狗导致的临界区问题?
回答(3)
F407没D-Cache,别往那想。丢后半段全是0、DMA完成中断还进了,典型是DMA传输中途被打断或SPI时钟被掐。先查两点:1)AD7606的CONVST/BUSY和SPI2 CS是不是共用DMA请求或同一定时器通道,10ms节拍任务里有没有跟DMA启动抢跑,把DMA启动放定时器回调里、别在任务里软触发;2)看SPI2->CR2的TXEIE/RXNEIE有没有误开,DMA模式下SPI中断和DMA完成中断抢同一个流会清标志。再就是中断里别直接喂狗,改成任务喂。直接看手册DMA流仲裁那节最快,SPI2_RX用DMA1_Stream3别和别的外设复用。
F407没D-Cache,先排除这个。DMA完成中断进了但buffer后半段全0,八成是DMA传输被提前截断或SPI时钟停摆。直接看手册RM0090的SPI2 DMA章节最快。
排查点:
1. 重点查AD7606的CONVST/BUSY时序——批量十几台出问题,典型的器件批次差异或BUSY毛刺,用示波器同时抓BUSY和CS,看BUSY下降沿和DMA启动有没有错位。
2. SPI2的DMA请求靠SPI_CR2的TXDMAEN/RXDMAEN,确认DMA完成中断里有没有清SPI2->DR残留,或者上一次DMA没彻底停就重配,导致通道被抢占。
3. 中断里喂看门狗本身不致命,但如果喂狗函数里有临界区或调用了RTOS API,可能拉长中断延迟,让SPI DMA时钟间隙超时。把喂狗挪到任务里试。
先抓BUSY波形,大概率是AD7606那侧的问题。
兄弟,F407没D-Cache,别往那想。DMA完成中断进了但后半段全0,我第一反应是DMA传输长度或外设请求被提前掐断——重点查SPI2的DMA通道配置和ADC的CS/转换时序配合。
排查点:1)确认SPI2_RX的DMA是循环还是单次,单次模式下每帧要重新装NDTR,装的时候如果上一帧DMA还没真正结束就重装,后半段就丢了;2)AD7606是并行还是SPI模式?SPI模式下BUSY拉低后要等够转换时间再读,读太快后半通道数据没出来;3)中断里喂狗没问题,但别在DMA完成中断里做长操作,把处理丢给任务。
另外十几台才出,建议查电源和SPI时钟相位,个别板子器件批次差异也会这样。