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 函数是否被调用,以及设备树节点是否被正确解析 。

参考来源

相关推荐
hweiyu001 小时前
Linux命令:newgrp
linux·运维·服务器
凡人叶枫1 小时前
Effective C++ 条款15:在资源管理类中提供对原始资源的访问
linux·开发语言·c++·stm32·单片机
c238561 小时前
Vim 高阶实操技巧篇
linux·编辑器·vim
Plastic garden2 小时前
Linux下rsync + inotify 实时文件同步方案
linux·运维·服务器
c238562 小时前
Vim 零基础核心基础篇
linux·编辑器·vim
liulilittle2 小时前
删除 Inflight Bounds:为什么 KCC 放弃了 BDP 钳位
linux·网络·tcp/ip·计算机网络·信息与通信·tcp·通信
风吹落枫2 小时前
银河麒麟V10 P1左下角不显示时间问题解决
linux
江华森2 小时前
深入 Linux 性能调试 —— BPF 与 BCC 工具实战指南
linux·运维·服务器
qq_163135752 小时前
Linux 【06-cp命令超详细教程】
linux