2. Linux SPI子系统架构:三层模型与数据结构关系图
Linux SPI子系统采用经典的分层架构设计,从上到下依次为:SPI设备驱动层、SPI核心层和SPI控制器驱动层。这种分层模型将协议细节、硬件操作与设备逻辑解耦,使得驱动开发人员只需关注自己所在层次的接口实现。
2.1 三层模型概述
每一层都有明确的职责边界和标准化的数据结构,层与层之间通过核心层提供的API进行交互。下表总结了各层的定位与核心数据结构:
| 层次 | 职责 | 核心数据结构 | 关键操作 |
|---|---|---|---|
| SPI设备驱动层 | 实现具体SPI外设(如ADC、传感器、显示屏)的协议逻辑 | struct spi_driverstruct spi_device |
probe()、remove()、spi_write()、spi_read()、spi_sync() |
| SPI核心层 | 管理总线、设备与驱动匹配;提供统一的传输接口 | struct spi_controllerstruct spi_messagestruct 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子系统的三层模型以及各层之间的数据流与控制流关系:
2.3 核心数据结构关系图
SPI子系统的数据结构之间存在紧密的引用关系。理解这些关系是进行驱动调试和性能优化的前提。下面用SVG图展示主要数据结构之间的关联:
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子系统的消息传递遵循“设备驱动→核心层→控制器驱动→硬件”的路径,具体流程如下:
- 设备驱动发起传输:调用
spi_sync()(同步)或spi_async()(异步),构造spi_message并添加spi_transfer。 - 核心层排队调度:核心层将
spi_message加入控制器的传输队列,并通过spi_queued_transfer机制触发调度。 - 控制器驱动执行:控制器驱动的
transfer_one_message()被调用,遍历 message 中的每个 transfer,调用硬件寄存器或DMA完成数据收发。 - 完成回调:每个 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设备列表。