Linux SPI Framework整体架构分析
1. SPI Framework
上一章我们讲解了SPI的物理模型和传输时序图,从这一章开始我们深入分析Linux SPI框架。整个框架如图:

看到这张图是不是蒙了?先别急,后面我们会慢慢讲解。你只需要记住,核心就分为三个层次:
- 第一层:设备驱动层(Device Driver),主要负责设备的功能,简单的理解就是跟 SoC 通信的设备
- 第二层:SPI Core 层,这是 Linux 提供的公共框架,负责管理每次的 SPI 通信请求
- 第三层:SPI Controller Driver,负责具体的 SoC 的 SPI 硬件
2. 三个核心对象
整个框架里面有三个核心对象,就是软件层抽象的物理世界。分别是 spi_controller、spi_device 和 spi_driver。其中:
spi_controller表示一台 SPI 主控制器spi_device表示挂在该控制器上的一个从设备spi_driver是对应的从设备的软件驱动
结构关系:

2.1 spi_controller
我们先来看 spi_controller,其在物理层对应 Master,源码位置在 include/linux/spi/spi.h:
1 | |
我们先不分析源码,先有个概念:它表示一个SPI控制器,SPI控制器就是 SoC 里面对应的能实现SPI通信的端口。比如一块 SoC 里面可能有 SPI0~SPI2 三个控制器,那么每一个就对应软件层的一个 spi_controller。主要负责产生时钟信号、控制片选CS、数据收发等。
2.2 spi_device
接着看 spi_device,对应从机设备。比如你有一个 IMU,那么在 SPI 控制框架中就被抽象成一个 spi_device 对象。源码位置在 include/linux/spi/spi.h:
1 | |
2.3 spi_driver
有了设备描述还不够,还需要对应的驱动代码,也就是 spi_driver,源码也在 include/linux/spi/spi.h:
1 | |
不同设备的 spi_driver 不一样,填充上面的结构体即可。
3. DTS 创建 spi_device
这个我们直接以一个实例感受:
1 | |
上面表示在 SPI0 控制器下面挂载了一个 IMU 从设备。其中:
reg = <0>:表示 CS 编号,这里就是 CS0spi-max-frequency:最大时钟频率,这里是 10MHzstatus:使能compatible:与驱动中spi_driver匹配
整个启动流程就是先解析设备树,把参数给到 SPI Controller Driver,创建 spi_device 后与对应的 spi_driver 进行匹配,匹配完成后执行 probe 函数。
4. SPI 数据传输流程
假设传感器驱动读取2字节:
1 | |
其中的 spi 表示 struct spi_device *spi 具体的设备。其构造了一个 spi_transfer,随后放入 spi_message,然后同步传输。其中 spi_message 表示一次完整的逻辑通信。接着,SPI Core 把消息交给对应 spi_controller,SPI Core 从 message 中取出 transfer,然后调用 transfer_one()。示意图如下:

5. 总结
好了,到这里我们就结束了。Linux SPI框架主要通过分层设计,将SPI设备驱动与SPI控制器硬件实现进行解耦。
整体分为三个部分:
- spi_driver:负责设备功能
- SPI Core:负责设备管理和数据调度
- spi_controller driver:负责控制具体的SPI硬件
当设备树创建SPI设备后,Linux通过 driver match 机制调用设备驱动 probe 函数,随后设备驱动通过SPI Core提供的接口完成数据传输。
6. 互动
- Linux 为什么需要 SPI Framework?
- 一个 SPI 设备从 DTS 到驱动 probe 的流程是什么?
- spi_controller、spi_device、spi_driver 三者是什么关系?
- 数据传输时,数据如何从设备驱动走到底层硬件?