2. Linux SPI子系统架构:三层模型与数据结构关系图

Linux SPI子系统采用经典的分层架构设计,从上到下依次为:SPI设备驱动层、SPI核心层和SPI控制器驱动层。这种分层模型将协议细节、硬件操作与设备逻辑解耦,使得驱动开发人员只需关注自己所在层次的接口实现。

2.1 三层模型概述

每一层都有明确的职责边界和标准化的数据结构,层与层之间通过核心层提供的API进行交互。下表总结了各层的定位与核心数据结构:

层次 职责 核心数据结构 关键操作
SPI设备驱动层 实现具体SPI外设(如ADC、传感器、显示屏)的协议逻辑 struct spi_driver
struct spi_device
probe()、remove()、spi_write()、spi_read()、spi_sync()
SPI核心层 管理总线、设备与驱动匹配;提供统一的传输接口 struct spi_controller
struct spi_message
struct spi_transfer
spi_register_controller()、spi_alloc_device()、spi_async()
SPI控制器驱动层 直接操作SPI控制器硬件寄存器,完成底层时序与DMA传输 struct spi_controller(master/slave)
私有数据(如寄存器基址、时钟句柄)
transfer_one_message()、setup()、prepare_message()
关键理解:SPI核心层是整个子系统的“中枢神经系统”。设备驱动层通过核心层提交传输请求,核心层将请求排队并调度给控制器驱动层执行。控制器驱动层完成硬件操作后,通过核心层回调通知设备驱动层传输结果。

2.2 三层架构关系图

下面的SVG图展示了SPI子系统的三层模型以及各层之间的数据流与控制流关系:

Linux SPI子系统三层架构关系图 SPI设备驱动层 spi_driver → probe() / remove() spi_device → chip_select / max_speed_hz / mode spi_write() / spi_read() / spi_sync() / spi_async() SPI核心层 spi_controller → 总线管理 / 设备注册 / 驱动匹配 spi_message → 传输队列 / 完成回调 spi_transfer → tx_buf / rx_buf / len / speed_hz / delay_usecs SPI控制器驱动层 transfer_one_message() → 硬件FIFO / DMA操作 setup() → 时钟极性/相位/波特率配置 prepare_message() / unprepare_message() → 传输前准备/后清理 SPI控制器硬件(寄存器 / FIFO / DMA引擎 / GPIO片选) 数据流方向 ↑ 上传 / ↓ 下发 控制流方向 → 请求 → 调度 → 执行

2.3 核心数据结构关系图

SPI子系统的数据结构之间存在紧密的引用关系。理解这些关系是进行驱动调试和性能优化的前提。下面用SVG图展示主要数据结构之间的关联:

SPI子系统核心数据结构关系图 struct spi_controller bus_num / max_speed / mode_bits transfer_one_message / setup / prepare_message struct spi_device chip_select / max_speed_hz / mode controller → spi_controller struct spi_driver probe / remove / shutdown driver → struct device_driver struct spi_message transfers → list_head complete / context / status struct spi_transfer tx_buf / rx_buf / len speed_hz / delay_usecs / cs_change struct spi_board_info modalias / chip_select / max_speed_hz bus_num / mode / irq / platform_data controller->dev_list controller->queue spi_device->driver message->transfers spi_new_device(board_info) 说明:实线表示直接指针引用关系,虚线表示通过API函数创建的关联。 spi_message 包含一个或多个 spi_transfer,构成一次完整的SPI事务。

2.4 数据结构关键字段说明

以下表格列出了各数据结构中与驱动调试和性能优化最相关的字段:

数据结构 关键字段 说明 优化关注点
spi_controller max_speed_hz 控制器支持的最大SPI时钟频率 决定设备能否达到目标速率
mode_bits 支持的SPI模式位掩码(CPOL/CPHA/CS_HIGH等) 设备模式兼容性检查
transfer_one_message 底层传输回调函数指针 性能瓶颈常在此函数内部
spi_device chip_select 片选信号编号(硬件GPIO或内置片选) 片选切换延迟影响小数据包性能
max_speed_hz 该设备允许的最大时钟频率 不能超过控制器限制
mode SPI模式(0/1/2/3) 必须与设备数据手册一致
spi_message transfers 链表头,挂载多个spi_transfer 合并小transfer减少调度开销
complete 传输完成回调函数 异步传输的关键
status 传输结果状态码 调试时检查错误原因
spi_transfer tx_buf / rx_buf 发送/接收缓冲区指针 DMA要求缓冲区对齐和连续性
len 传输字节数 大长度传输需考虑DMA阈值
speed_hz 本次传输的时钟频率(可覆盖device设置) 动态调频优化功耗与速率

2.5 数据流与消息传递机制

SPI子系统的消息传递遵循“设备驱动→核心层→控制器驱动→硬件”的路径,具体流程如下:

  1. 设备驱动发起传输:调用 spi_sync()(同步)或 spi_async()(异步),构造 spi_message 并添加 spi_transfer。
  2. 核心层排队调度:核心层将 spi_message 加入控制器的传输队列,并通过 spi_queued_transfer 机制触发调度。
  3. 控制器驱动执行:控制器驱动的 transfer_one_message() 被调用,遍历 message 中的每个 transfer,调用硬件寄存器或DMA完成数据收发。
  4. 完成回调:每个 transfer 完成后,控制器驱动更新 message 状态;全部完成后调用 complete 回调通知设备驱动。
性能关键点:在步骤2中,核心层默认使用工作队列(workqueue)进行消息排队。对于高吞吐场景,可以配置控制器使用 SPI_CONTROLLER_MUST_TX 或 SPI_CONTROLLER_MUST_RX 标志来优化DMA传输路径。步骤3中,transfer_one_message() 的实现质量直接决定SPI总线的实际吞吐量。

2.6 设备驱动与控制器驱动的匹配过程

SPI设备的枚举与匹配有两种主要方式:

方式 触发时机 实现方法 适用场景
板级静态注册 内核启动时 通过 spi_board_info 数组调用 spi_register_board_info() 设备固定、不热插拔的嵌入式板卡
设备树匹配 设备树解析时 在设备树节点中定义 compatible 属性,驱动通过 of_match_table 匹配 现代ARM/ARM64平台,推荐方式
ACPI匹配 ACPI表解析时 通过 ACPI _HID 或 _CID 匹配 x86平台或支持ACPI的嵌入式系统
调试提示:当SPI设备驱动 probe() 未被调用时,首先检查设备树中 compatible 属性是否与驱动 of_match_table 完全一致(包括大小写)。其次确认 spi_controller 的 bus_num 与设备节点中 reg 属性(片选号)是否匹配。使用 ls /sys/bus/spi/devices/ 可以查看当前系统识别的SPI设备列表。