1. Linux 内核 SPI 驱动概述
SPI(Serial Peripheral Interface)是嵌入式系统中最常用的同步串行通信协议之一,从传感器、Flash存储到显示屏都会用到这个看似简单却暗藏玄机的四线制接口。作为一名在嵌入式领域摸爬滚打十年的老司机,我至今记得第一次调试SPI驱动时,那个因为时钟相位设置错误导致传感器数据全乱的深夜。
Linux内核中的SPI子系统就像一位沉默的交通警察,它不仅要管理主机控制器与设备之间的数据流动,还要协调DMA、中断和GPIO等资源。与用户空间直接打交道的/dev/spidev接口背后,是层层封装的spi_controller、spi_device和spi_transfer等核心数据结构,它们构成了Linux SPI驱动的骨架。
2. SPI 驱动架构解析
2.1 内核SPI子系统组成
Linux内核的SPI实现采用典型的分层架构:
code复制用户空间
-----------------------------------------
| /dev/spidevX | sysfs | debugfs | netlink
-----------------------------------------
内核空间
| SPI设备驱动层 (e.g. mcp251x, ads7846)
-----------------------------------------
| SPI核心层 (drivers/spi/spi.c)
-----------------------------------------
| SPI控制器驱动层 (e.g. spi-bcm2835)
-----------------------------------------
硬件层
| SoC SPI控制器 | 外设芯片
核心层提供的struct spi_controller抽象了硬件控制器的操作,包括transfer_one_message等关键回调函数。以树莓派常用的bcm2835驱动为例,其内部实现了DMA和中断两种传输模式,通过dma_map_single将用户缓冲区映射到DMA地址空间。
2.2 关键数据结构解剖
- spi_device: 代表一个
