Linux 驱动支持 SPI 协议的整体思路
在 Linux 中,支持 SPI 协议通常分为三层:底层 SPI 控制器驱动(实现 struct spi_controller,负责时钟、FIFO、DMA、片选等)、中间 SPI 核心层(提供总线/设备/驱动模型与消息队列)、上层 SPI 设备协议驱动(匹配具体外设,提供 probe/remove 与数据读写接口)。核心数据结构包括:struct spi_controller(主机/从机控制器)、struct spi_device(挂在某条总线上的从设备实例)、struct spi_driver(协议驱动)、struct spi_transfer(一次传输片段)、struct spi_message(由多个 transfer 组成的一次完整事务)。SPI 时序由 CPOL/CPHA 与 bits_per_word、speed_hz 等参数决定,传输为全双工,消息内片选可保持连续。现代内核还支持 Dual/Quad 等多线模式与 DMA 提升吞吐。
实现步骤
控制器驱动(主机侧)
设备树或板级描述(实例化从设备)
设备协议驱动(外设侧)
关键数据结构与传输要点
常用结构
传输与性能
最小示例骨架
设备树节点(示例)
&ecspi1 {
status = "okay";
mydev@1 {
compatible = "vendor,my-spi-dev";
reg = <1>; /* 片选号 */
spi-max-frequency = <20000000>;
spi-cpol = <0>;
spi-cpha = <0>;
spi-cs-high;
bits-per-word = <8>;
};
};
驱动骨架(示例)
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
static const struct of_device_id mydev_of_match[] = {
{ .compatible = "vendor,my-spi-dev" },
{}
};
MODULE_DEVICE_TABLE(of, mydev_of_match);
static int mydev_probe(struct spi_device *spi)
{
/* 读取设备树或平台数据配置,如 mode/speed/字长 */
spi->mode = SPI_MODE_0; /* 示例:CPOL=0, CPHA=0 */
spi->bits_per_word = 8;
spi_setup(spi);
/* TODO: 分配私有数据、初始化设备、可能用 regmap */
return 0;
}
static int mydev_remove(struct spi_device *spi)
{
/* TODO: 资源释放 */
return 0;
}
static struct spi_driver mydev_driver = {
.driver = {
.name = "my-spi-dev",
.of_match_table = mydev_of_match,
},
.probe = mydev_probe,
.remove = mydev_remove,
};
module_spi_driver(mydev_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Minimal SPI device driver example");
调试与常见问题