同一SPI总线挂载两个SPI设备时写入输出异常问题排查
问题
在树莓派的同一SPI总线上连接了两个设备,二者共用同一自定义设备驱动,该驱动将它们作为两个独立的杂项设备暴露给用户空间,支持简单的寄存器写入操作。
在用户空间程序中,我打开了这两个设备文件并执行IOCTL操作,遇到了异常:当向第一个设备执行1000次写入后,立即向第二个设备执行几次写入,尽管使用了独立的片选(CS)引脚,第二个设备似乎接收到了原本要发给第一个设备的数据。设备驱动中使用spi_sync()执行SPI写入。
现提出以下技术疑问:
spi_sync()的行为:根据文档,spi_sync()是同步函数,这是否意味着执行写入的内核线程仅在数据完全在SPI总线上传输完成后才返回?- IOCTL的行为:当用户程序调用IOCTL执行SPI写入操作时,是会阻塞直到设备驱动完成SPI传输,还是在将用户数据复制到内核空间后立即返回?
- 不同进程的并发写入:若另一个用户空间程序同时向第二个设备写入,是否会导致SPI总线上的传输交错?SPI核心是否会正确处理每个传输的片选(CS)断言以确保数据完整性?
回答
1. spi_sync()的行为
是的,spi_sync()是同步阻塞调用。它会将SPI传输请求提交给SPI核心,之后一直等待,直到整个传输流程彻底完成——包括数据全部发送至总线、对应片选引脚恢复默认状态,才会从内核函数返回。执行该调用的内核线程会在整个过程中处于阻塞状态,不会提前返回。
2. IOCTL的行为
这完全取决于自定义驱动中IOCTL处理函数的实现逻辑:
- 如果驱动在IOCTL处理过程中直接调用了
spi_sync(),那么用户空间的IOCTL调用会一直阻塞,直到spi_sync()完成整个SPI传输才会返回。 - 如果驱动是把传输请求放入后台队列做异步处理,那IOCTL可能在完成用户数据复制后就立刻返回。
结合你遇到的问题来看,你的驱动大概率是同步实现,IOCTL会阻塞到传输完成。
3. 不同进程的并发写入
SPI核心本身会对同一SPI总线的传输请求做串行化处理——同一时间总线上只会有一个传输在进行,不会出现传输交错的情况。并且每个传输对应的片选引脚会被正确断言和释放:传输开始前断言目标设备的CS引脚,传输完成后立即释放,确保数据只会被目标设备接收。
但需要注意:如果你的自定义驱动没有正确将每个杂项设备绑定到对应的SPI设备结构体(即每个设备对应独立的struct spi_device,且带有各自的CS配置),SPI核心可能无法正确切换CS引脚,这会直接导致数据发错设备——这很可能是你当前遇到问题的核心原因。
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

