1. Linux内核SPI子系统架构解析
作为一名在嵌入式领域摸爬滚打十年的老司机,今天想和大家深入聊聊Linux内核中那个既基础又关键的SPI子系统。每次在调试SPI设备时,总能看到新人对着dmesg输出发懵,其实只要理解了这套架构的设计哲学,90%的问题都能迎刃而解。
SPI(Serial Peripheral Interface)作为嵌入式系统中最常用的同步串行通信协议,其内核实现堪称"麻雀虽小五脏俱全"。从应用层的设备驱动到硬件寄存器操作,整个子系统通过分层设计实现了惊人的灵活性和扩展性。在实际项目中,我见过有人用SPI驱动TFT屏幕、FLASH存储器甚至音频编解码器,这种通用性正是得益于良好的架构设计。
2. SPI子系统核心架构拆解
2.1 三层架构设计
内核中的SPI实现采用了经典的三层架构:
code复制应用层设备驱动 → 核心层 → 控制器驱动
↓
硬件抽象层
这种设计最妙的地方在于隔离了硬件差异。去年我在移植某款国产MCU的SPI驱动时,只需要实现控制器层的钩子函数,上层的MTD设备驱动完全不用修改就能直接使用。
核心层主要包含以下几个关键组件:
- spi_master:表征物理SPI控制器
- spi_device:描述连接的SPI从设备
- spi_transfer/spi_message:数据传输的载体
2.2 关键数据结构解析
先看spi_master这个结构体,它就像SPI控制器的"身份证":
c复制struct spi_master {
struct device dev;
u16 bus_num;
u16 num_chipselect;
int (*transfer)(struct spi_device *spi, struct spi_message *mesg);
/* 其他操作函数指针 */
};
这里特别要注意的是transfer函数指针,它相当于控制器的"心脏"。我在调试Rockchip平台的SPI时,就是因为这个回调函数没有正确处理DMA映射导致数据校验失败。
spi_device则描述了从设备的特性:
c复制struct spi_device {
