串行外设接口(SPI)是四线总线:MOSI、MISO、串行时钟SCK和片选CS。它常用于连接闪存、AD/DA转换器。主设备生成时钟和管理片选CS,速度可达80MB,远超I2C总线。
一、驱动程序架构
SPI设备在内核中表示为struct spi_device{},管理他们的驱动程序的实例是struct spi_driver{}。spi的拓扑结构如下图:

1. 设备spi_device{}结构
struct spi_device {
struct device dev;
struct spi_master *master; // 表示设备所连接的SPI控制器
u32 max_speed_hz; // 设备的最大时钟频率,可以在传输时用spi_transfer().speed_hz参数修改频率
u8 chip_select; //
u8 bits_per_word;
u16 mode; // 指定是LSB还是MSB,默认是MSB
int irq; //这代表中断号,应该将它传递给request_irq来接收此设备的中断。
[...];
int cs_gpio;
};
2. 驱动spi_driver{}结构
spi_driver{}结构体
struct spi_driver {
const struct spi_device_id *id_table;
struct device_driver driver;
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
int (*shutdown)(struct spi_device *spi);
};
// SPI可以修改CS状态、每字的位数、时钟,其probe函数如下
static int my_probe(struct spi_device *spi) {
int ret;
[...]
spi->mode = SPI_MODE_0;
spi->max_speed_hz = 20000000; // 设备的最大时钟数
spi->bits_per_word = 16; // 每个字的位数
ret = spi_setup(spi);
if (ret < 0) return ret;
[...] // 其他省略的内容
return ret;
}
可以获取对应的struct spi_device_id{}的指针,另外也支持void spi_set_drvdata(struct spi_device *, void *)和void *spi_get_drvdata(spi_device *spi)获取driverdata,使用示例如下:
struct mc33880 {
struct mutext lock;
u8 bar;
struct foo chip;
str

文章介绍了SPI接口的基本概念,包括其四线连接和常见应用。接着详细阐述了Linux内核中的SPI驱动程序架构,包括spi_device和spi_driver结构体,以及如何通过probe函数配置设备参数。文章还讨论了设备的注册、匹配和访问机制,如spi_message和spi_transfer结构体在SPI消息传输中的作用,同步和异步传输的实现。最后提到了用户模式下的SPI驱动程序spidev及其使用。
最低0.47元/天 解锁文章
1017

被折叠的 条评论
为什么被折叠?



