RT-Thread SPI链式传输非法访问?揭秘致命陷阱!

环贸财神 2025-06-29 3843人围观

前言

一、

在与RT-Thread BSP的开发者沟通中,发现SPI设备驱动在轮询(Polling)模式下偶发出现非法访问异常(如图)

bf68f6ea-50ef-11f0-986f-92fbcf53809c.png

问题复现场景:

开发者仅需一次单消息传输,但未显式初始化struct rt_spi_message的next指针。

由于next未赋值为RT_NULL,链式传输时触发非法内存访问(next指向不可控地址)。

修复方案 :将next显式置空后,异常消失。

借此机会,本文将深入解析RT-Thread SPI驱动的链式传输机制,并探讨BSP对RT-Thread SPI接口的适配特点与优势。

RT-Thread SPI链式传输机制解析

二、

1.核心数据结构:struct rt_spi_message

RT-Thread通过struct rt_spi_message描述SPI传输操作,支持单条或多条消息链式传输。

关键成员next

1)若为NULL,表示当前为链式传输的最后一条消息。

2)若非NULL,需确保next指向的rt_spi_message已正确初始化。

3)未初始化next的后果链式传输时,驱动会尝试访问next指向的无效地址,导致非法访问异常。

在RT-Thread的官方wiki示例可以看到,在定义一个spi message时,需要操作next成员以便确认是否有下一条链式传输。如果没有需要赋值为NULL。在RT-Thread的wiki可以看到,在使用rt_spi_transfer_message 传输两条msg,在第二条msg的next赋值为RT_NULL代表结束。

bf94c27a-50ef-11f0-986f-92fbcf53809c.png

在RT-Thread组件SPI相关也对next进行了操作,并且做了相关注释说明

先楫BSP适配

三、

那么可能就有开发者问了,为什么别的BSP SPI驱动反而就没事了,可以在RT-Thread的主线看到,多数厂商(如STM32)的SPI驱动未处理next指针,仅支持单条消息传输,但链式传输时易因next未处理导致传输异常。

bfc2c940-50ef-11f0-986f-92fbcf53809c.png

而先楫BSP的SPI驱动严格按照RT-Thread规范实现链式传输逻辑,强制校验next指针。支持单条/链式传输,兼容复杂场景。

bff233b0-50ef-11f0-986f-92fbcf53809c.png

先楫BSP对DSPI和QSPI的支持

四、

不同与其他厂家的BSP,把SPI和QSPI分开两个驱动文件,先楫是集成在SPI驱动中,因为先楫SPI本身就是一个外设,可以支持SPI,DSPI,QSPI三种传输模式。

怎么开启这三种模式,可以通过menuconfig进入到对应的界面进行选择:分别是单线SPI,两线DSPI,四线QSPI。

c021c210-50ef-11f0-986f-92fbcf53809c.png

如果想在RT-Thread Studio操作,可以参考下图:

c033999a-50ef-11f0-986f-92fbcf53809c.png

需要注意的是:当使用四线QSPI时,对应的pinmu.c的SPI初始化需要加上QSPI的D2和D3初始化。

c04c1e2a-50ef-11f0-986f-92fbcf53809c.png

通过list device命令可看到:SPI0为单线SPI,SPI1为双线DSPI,SPI2为四线QSPI

c07f1df2-50ef-11f0-986f-92fbcf53809c.png

总结

五、

链式传输陷阱:未初始化next指针是SPI驱动异常的常见原因,开发者需严格遵循RT-Thread规范。

先楫BSP优势

1. 严格适配RT-Thread链式传输逻辑,避免非法访问。2. 集成SPI/DSPI/QSPI驱动,简化开发流程。

Powered By Z-BlogPHP