Linux SPI从机驱动开发要点

在 Linux 系统中,SPI 从机(Slave)驱动的开发主要围绕 spi_driver 结构体展开,通过设备树进行硬件资源配置,并使用 spi_transferspi_message 进行数据传输 。

一、SPI 从机驱动核心框架

一个标准的 SPI 设备驱动包含以下核心结构:

c 复制代码
#include <linux/spi/spi.h>

static const struct of_device_id my_spi_of_match[] = {
    { .compatible = "vendor,my-spi-device" },
    {},
};
MODULE_DEVICE_TABLE(of, my_spi_of_match);

static int my_spi_probe(struct spi_device *spi)
{
    // 1. 获取设备树配置
    // 2. 初始化设备私有数据结构
    // 3. 配置 SPI 参数(模式、频率等)
    // 4. 注册字符设备或其它内核接口
    printk(KERN_INFO "My SPI device probed successfully.
");
    return 0;
}

static void my_spi_remove(struct spi_device *spi)
{
    // 清理资源
    printk(KERN_INFO "My SPI device removed.
");
}

static struct spi_driver my_spi_driver = {
    .driver = {
        .name = "my_spi_device",
        .of_match_table = my_spi_of_match,
        .owner = THIS_MODULE,
    },
    .probe = my_spi_probe,
    .remove = my_spi_remove,
};

module_spi_driver(my_spi_driver);

二、设备树节点配置

在硬件平台的设备树源文件(.dts)中,需要为 SPI 从机设备添加节点,该节点必须挂载在对应的 SPI 控制器(主机)节点之下 。

dts 复制代码
&spi0 { /* 假设这是 SPI 控制器节点 */
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;

    my_spi_device@0 {
        compatible = "vendor,my-spi-device"; // 必须与驱动中的匹配表一致
        reg = <0>; // 片选信号编号
        spi-max-frequency = <10000000>; // 最大通信频率
        spi-cpol; // 可选:时钟极性高
        spi-cpha; // 可选:时钟相位第二个边沿采样
        // 其它 GPIO、中断等配置
        interrupt-parent = <&gpio0>;
        interrupts = <5 IRQ_TYPE_EDGE_RISING>;
    };
};

三、SPI 数据传输模型

Linux SPI 核心层使用 spi_transferspi_message 来组织一次或多次数据传输 。

数据结构 描述 关键成员
struct spi_transfer 描述一次单/双向数据传输 .tx_buf, .rx_buf, .len, .delay_usecs, .speed_hz
struct spi_message 多个 spi_transfer 的集合,原子执行 .transfers (链表), .actual_length

同步数据传输示例:

c 复制代码
int spi_send_receive(struct spi_device *spi, u8 *tx_data, u8 *rx_data, int len)
{
    int ret;
    struct spi_transfer t = {
        .tx_buf = tx_data,
        .rx_buf = rx_data,
        .len = len,
        .delay_usecs = 10, // 传输间延时
        .speed_hz = spi->max_speed_hz, // 可覆盖默认速度
    };
    struct spi_message m;

    spi_message_init(&m);
    spi_message_add_tail(&t, &m);
    ret = spi_sync(spi, &m); // 同步调用,阻塞等待完成

    if (ret < 0) {
        dev_err(&spi->dev, "SPI transfer failed: %d
", ret);
    } else {
        // 成功,实际传输长度在 m.actual_length
    }
    return ret;
}

四、关键配置与调试

  1. 内核配置 :确保内核已启用 SPI 子系统及对应控制器驱动。

    bash 复制代码
    Device Drivers  --->
        [*] SPI support  --->
            <*>   Your SoC SPI controller driver (e.g., ARM SoC SPI)
  2. 用户空间测试 :使用 spidev_test 工具(内核源码 tools/spi/ 目录下)进行快速验证 。

    bash 复制代码
    # 编译
    makeC /path/to/kernel/source tools/spi
    # 测试,假设 /dev/spidev0.0 为你的设备
    ./spidev_test -D /dev/spidev0.0 -v
  3. 常见问题排查

    • 时钟不稳/无响应 :检查设备树中 spi-max-frequency 是否超出从机支持范围,确认 spi-cpolspi-cpha 模式配置是否正确 。
    • 大数据误码 :考虑启用 DMA 传输(在控制器支持且设备树中配置 dmas 属性)以减轻 CPU 负载,提升稳定性 。
    • 驱动未加载 :使用 dmesg | grep spi 查看内核日志,确认驱动 probe 函数是否被调用,以及设备树节点是否被正确解析 。

参考来源

相关推荐
HLC++11 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室12 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy15 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕16 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫17 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生17 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1118 小时前
linux基础IO
linux·运维·服务器
BelongPanda20 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯21 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983421 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器