Linux SPI Framework整体架构分析

1. SPI Framework

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

看到这张图是不是蒙了?先别急,后面我们会慢慢讲解。你只需要记住,核心就分为三个层次:

  • 第一层:设备驱动层(Device Driver),主要负责设备的功能,简单的理解就是跟 SoC 通信的设备
  • 第二层:SPI Core 层,这是 Linux 提供的公共框架,负责管理每次的 SPI 通信请求
  • 第三层:SPI Controller Driver,负责具体的 SoC 的 SPI 硬件

2. 三个核心对象

整个框架里面有三个核心对象,就是软件层抽象的物理世界。分别是 spi_controllerspi_devicespi_driver。其中:

  • spi_controller 表示一台 SPI 主控制器
  • spi_device 表示挂在该控制器上的一个从设备
  • spi_driver 是对应的从设备的软件驱动

结构关系:

2.1 spi_controller

我们先来看 spi_controller,其在物理层对应 Master,源码位置在 include/linux/spi/spi.h

1
2
3
4
5
6
7
struct spi_controller {
struct device dev; /* 内嵌的设备结构体,用于挂载到设备模型 */

int (*transfer)(...); /* 批量传输:一次可发起多个 spi_message */

int (*transfer_one)(...); /* 单次传输:一次只处理一个 spi_message */
};

我们先不分析源码,先有个概念:它表示一个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
4
5
6
7
8
9
10
11
12
struct spi_device {
struct device dev; /* 内嵌的设备结构体,用于挂载到设备模型 */

struct spi_controller *controller; /* 指向所属的 SPI 主控制器 */

u32 max_speed_hz; /* 该从设备支持的最大通信时钟频率 (Hz) */

u8 mode; /* SPI 工作模式 (CPOL/CPHA 组合,如 MODE0~3) */

u8 chip_select; /* 片选信号编号 (对应主控制器上的第几个 CS 引脚) */

};

2.3 spi_driver

有了设备描述还不够,还需要对应的驱动代码,也就是 spi_driver,源码也在 include/linux/spi/spi.h

1
2
3
4
5
6
7
struct spi_driver {
const struct spi_device_id *id_table; /* 支持的设备ID表,用于与 spi_device 匹配 */
int (*probe)(struct spi_device *spi); /* 设备匹配成功后调用的探测函数 */
int (*remove)(struct spi_device *spi); /* 设备移除时调用的清理函数 */
void (*shutdown)(struct spi_device *spi); /* 系统关机时调用的回调 */
struct device_driver driver; /* 内嵌的通用设备驱动结构体 */
};

不同设备的 spi_driver 不一样,填充上面的结构体即可。


3. DTS 创建 spi_device

这个我们直接以一个实例感受:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spi0 {

status = "okay";


imu@0 {

compatible = "invensense,icm42688";


reg = <0>;


spi-max-frequency = <10000000>;

};
};

上面表示在 SPI0 控制器下面挂载了一个 IMU 从设备。其中:

  • reg = <0>:表示 CS 编号,这里就是 CS0
  • spi-max-frequency:最大时钟频率,这里是 10MHz
  • status:使能
  • compatible:与驱动中 spi_driver 匹配

整个启动流程就是先解析设备树,把参数给到 SPI Controller Driver,创建 spi_device 后与对应的 spi_driver 进行匹配,匹配完成后执行 probe 函数。


4. SPI 数据传输流程

假设传感器驱动读取2字节:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spi_read(spi, rx_buf, 2);

static inline int
spi_read(struct spi_device *spi, void *buf, size_t len)
{
/* 构造一个 spi_transfer 描述本次传输 */
struct spi_transfer t = {
.rx_buf = buf, /* 接收缓冲区,存放从设备发来的数据 */
.len = len, /* 本次传输的字节数 */
};

/* 发起同步传输:阻塞等待传输完成,最后一个参数表示 transfer 个数 */
return spi_sync_transfer(spi, &t, 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. 互动

  1. Linux 为什么需要 SPI Framework?
  2. 一个 SPI 设备从 DTS 到驱动 probe 的流程是什么?
  3. spi_controller、spi_device、spi_driver 三者是什么关系?
  4. 数据传输时,数据如何从设备驱动走到底层硬件?

Linux SPI Framework整体架构分析
https://cj0510.github.io/2026/08/01/Linux Kernel/SPI/Linux SPI整体架构/
作者
CJ1018
发布于
2026年8月1日
许可协议
CC BY-NC-SA 4.0