嵌入式Linux系统SPI驱动移植专题详解(3000+字图文实战指南)
一、SPI通信原理与嵌入式系统架构
1.1 SPI总线基础
SPI(Serial Peripheral Interface) 是一种高速全双工同步串行通信协议,采用主从架构(图1)。其核心特点包括:
- 四线制通信:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)
- 时钟极性(CPOL)与相位(CPHA):定义数据采样边沿
- 多从机支持:通过片选信号扩展设备
图1:典型SPI总线拓扑
1.2 SPI通信4种模式
SPI通信采用主从模式,通常由一个主设备和一个或多个从设备组成,支持四种通信模式,这些模式通过时钟极性(CPOL)和时钟相位(CPHA)的不同组合来实现。以下是SPI通信的四种模式及其特点:
一、模式0(CPOL=0,CPHA=0)
- 时钟极性(CPOL):0,表示时钟信号空闲时为低电平。
- 时钟相位(CPHA):0,表示数据在时钟信号的上升沿采样。
- 特点:在此模式下,当SPI总线空闲时,时钟信号(SCK)为低电平。数据在SCK的上升沿被采样,并在下降沿保持。这种模式是SPI通信中最常用的一种。
二、模式1(CPOL=0,CPHA=1)
- 时钟极性(CPOL):0,表示时钟信号空闲时为低电平。
- 时钟相位(CPHA):1,表示数据在时钟信号的下降沿采样。
- 特点:与模式0相似,当SPI总线空闲时,时钟信号(SCK)为低电平。但数据采样发生在SCK的下降沿,并在上升沿保持。这种模式在某些特定应用场景下可能会使用到。
三、模式2(CPOL=1,CPHA=0)
- 时钟极性(CPOL):1,表示时钟信号空闲时为高电平。
- 时钟相位(CPHA):0,表示数据在时钟信号的上升沿采样(但需注意,第一个上升沿通常不采样)。
- 特点:在此模式下,当SPI总线空闲时,时钟信号(SCK)为高电平。数据采样发生在SCK的上升沿(但通常是在第二个上升沿开始采样,因为第一个上升沿用于稳定通信),并在上升沿保持(或说是在采样后的整个时钟周期内保持)。这种模式在某些需要改变时钟空闲状态的场景中可能会使用到。
四、模式3(CPOL=1,CPHA=1)
- 时钟极性(CPOL):1,表示时钟信号空闲时为高电平。
- 时钟相位(CPHA):1,表示数据在时钟信号的下降沿采样。
- 特点:与模式2相似,当SPI总线空闲时,时钟信号(SCK)为高电平。但数据采样发生在SCK的下降沿(通常是在第二个下降沿开始采样),并在下降沿保持(或说是在采样后的整个时钟周期内保持)。这种模式在某些需要特殊时钟相位和极性的应用场景下可能会使用到。
1.3 嵌入式Linux驱动架构
嵌入式Linux驱动采用分层架构(图2):
应用层
↓
VFS(虚拟文件系统)
↓
字符设备/SPI子系统
↓
硬件抽象层(HAL)
↓
物理硬件层
图2:Linux 内核层次结构
图3 SPI驱动结构
二、Linux SPI驱动设计解析
2.1 驱动框架组成
struct spi_driver {
const struct spi_device_id *id_table;
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
void (*shutdown)(struct spi_device *spi);
struct device_driver driver;
};
2.2 关键数据结构
- spi_master: 控制器抽象