SPI 驱动框架和 I2C 类似:spi_driver 结构填 probe/remove,设备树 compatible 匹配;probe 里用 spi_write/spi_read/spi_sync 传输;用户态通过 /dev/spidevX.Y 访问,也可以封装成字符设备或 MTD(SPI Flash)。
本文概述
SPI 是 Linux 常用外设驱动,面试常考:spi_driver、spi_transfer、设备树、spidev。回答要给代码骨架和传输方式。
核心要点
SPI 驱动用 spi_driver,和 i2c_driver 框架类似
设备树里 compatible 匹配,reg 是片选号,spi-max-frequency 设速率
传输用 spi_sync(同步)或 spi_async(异步),spi_transfer 结构描述
用户态:/dev/spidevX.Y + ioctl,或封装成 MTD(Flash)/字符设备
SPI 是 4 线:CLK、MOSI、MISO、CS,全双工

面试官考察点
驱动开发基础题。面试官看你是否写过 SPI 驱动。重点听:spi_driver、spi_transfer、probe。
回答思路
给最小骨架,讲 probe 里做什么,传输函数。
参考回答
驱动骨架。
#include <linux/spi/spi.h>
static int flash_probe(struct spi_device *spi){
/* 读 Flash ID 验证 */
u8 tx[4] = {0x9F, 0, 0, 0};
u8 rx[4];
spi_write_then_read(spi, tx, 1, rx, 3);
/* 注册 MTD 设备 */
return 0;
}
static struct spi_driver flash_driver = {
.probe = flash_probe,
.remove = flash_remove,
.driver = {
.name = "spi_flash",
.of_match_table = flash_of_match,
},
};
module_spi_driver(flash_driver);
SPI 传输函数。
| 函数 | 作用 |
|---|---|
| spi_write(spi, buf, len) | 写 len 字节 |
| spi_read(spi, buf, len) | 读 len 字节 |
| spi_write_then_read(spi, tx, n_tx, rx, n_rx) | 先写命令再读数据 |
| spi_sync(spi, &msg) | 自定义传输(多个 transfer) |
| spi_async(spi, &msg, cb) | 异步传输,完成回调 |
spi_transfer 自定义传输。
struct spi_transfer t1 = { .tx_buf = cmd, .len = 4 };
struct spi_transfer t2 = { .rx_buf = data, .len = 256 };
struct spi_message msg;
spi_message_init(&msg);
spi_message_add_tail(&t1, &msg);
spi_message_add_tail(&t2, &msg);
spi_sync(spi, &msg);
设备树。
&spi1 {
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>; /* CS0 */
spi-max-frequency = <50000000>;
};
};
用户态访问。
spidev:通用 SPI 字符设备 /dev/spidevX.Y,ioctl 读写,适合调试;
MTD:SPI Flash 用 MTD 子系统,/dev/mtdblockX,可挂载 JFFS2/UBIFS;
自定义字符设备:封装成专用接口(如传感器驱动)。
注意。
SPI 速率不要超过器件最大值(看 datasheet);
SPI 模式(CPOL/CPHA)要和从设备匹配,设备树里 spi-cpol/spi-cpha;
多设备共享总线时 CS 要分别控制;
SPI 传输可能睡眠,不能在中断上下文调用。

扫码关注




























