嵌入式开发实战:在Linux 5.x内核中构建SPI从设备系统
在嵌入式系统的互联世界里,SPI总线因其高速、全双工和简单的硬件接口而备受青睐。我们通常习惯于将主控SoC配置为SPI主设备,去驱动各种传感器、存储器和显示屏。然而,你是否设想过另一种场景:让你的嵌入式Linux设备“扮演”一个从设备,被动地响应另一个主控器的指令?这种SPI Slave模式的应用正逐渐在分布式传感节点、协处理器通信、固件升级网关等场景中崭露头角。对于已经熟悉了SPI主设备驱动的开发者而言,切换到从设备视角,在Linux 5.x内核下构建一个稳定可靠的SPI Slave系统,是一次充满挑战但又极具价值的深度探索。这不仅要求你透彻理解内核的SPI子系统框架,更需要你精准地操控设备树、内核配置以及硬件连接等每一个细节。本文将带你从零开始,手把手完成一次从概念到实战的完整构建。
1. 理解SPI Slave模式:不仅仅是角色的转换
在深入代码之前,我们必须从根本概念上厘清SPI主从模式的区别。这绝非简单的“主动发起”与“被动响应”所能概括,它涉及到通信哲学、硬件状态乃至软件框架的全面转变。
主设备 是总线上的“指挥家”。它掌控着时钟信号SCK的生成与节奏,通过片选信号CS来选择与哪一个从设备对话,并主动发起每一次数据传输的序章。其驱动程序的核心任务是组织spi_message和spi_transfer,然后将其提交给控制器驱动,最终由硬件完成时序输出和数据搬移。
从设备 则是总线上的“演奏者”。它不产生时钟,不发起通信,其一切行为都依赖于主设备发出的指令和时钟节拍。在硬件层面,这意味着SCK和CS引脚从输出模式变为了输入模式,设备必须时刻准备着在时钟边沿采样或输出数据。在软件层面,从设备驱动不再主动“发送”数据,而是“准备”数据,并设置好回调函数,等待主设备来“读取”。
一个常见的误解是认为Slave模式只是将Master模式的代码简单反转。实则不然。我们可以通过一个对比表格来直观感受其内核实现上的关键差异:
| 特性维度 | SPI Master 模式 | SPI Slave 模式 |
|---|---|---|
| 时钟控制 | 内部生成并输出SCK | 从外部输入SCK,需检测其边沿 |
| 片选控制 | 主动控制CS信号输出 | 检测外部输入的CS信号状态 |
| 传输发起 | 主动调用spi_async()等API发起 |
被动等待,由spi_slave_abort()或完成回调通知 |
| 内核等待机制 | wait_for_completion_timeout(),可设置超时 |
wait_for_completion_interruptible(),通常无限等待 |
| 数据传输视角 | “我要发送/接收这些数据” | “我的缓冲区已准备好,主设备随时可以来取” |
| 典型应用 | 连接外设(Flash, Sensor) | 作为协处理器、调试接口、数据桥接 |
提示:理解这种“被动性”是编写SPI Slave驱动的关键。你的驱动代码不再是命令的执行者,而是服务的提供者。
从Linux内核的抽象层次来看,无论是Master还是Slave,其核心数据结构都是st

&spm=1001.2101.3001.5002&articleId=152879640&d=1&t=3&u=597c6cb8df4f4b86a8d4b7eeed55276f)
212

被折叠的 条评论
为什么被折叠?



