Linux SPI从机驱动开发要点

在 Linux 系统中,SPI 从机(Slave)驱动的开发主要围绕 spi_driver 结构体展开,通过设备树进行硬件资源配置,并使用 spi_transfer 和 spi_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_transfer 和 spi_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-cpol 和 spi-cpha 模式配置是否正确 。
    • 大数据误码 :考虑启用 DMA 传输(在控制器支持且设备树中配置 dmas 属性)以减轻 CPU 负载,提升稳定性 。
    • 驱动未加载 :使用 dmesg | grep spi 查看内核日志,确认驱动 probe 函数是否被调用,以及设备树节点是否被正确解析 。

参考来源

相关推荐
Apipi*1 分钟前
30天速通Linux 第六章信号及信号处理
linux·运维·信号处理
天启HTTP1 小时前
爬虫防封核心原理:IP轮换机制与风控规避逻辑
linux·服务器·网络·爬虫·tcp/ip
广州浮点FLOATLIC3 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
BLUcoding4 小时前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom
AIgorithmGEEK4 小时前
[Linux]从手写报头到内核套路:序列化、反序列化与自定义协议全链路
linux·运维·服务器·网络·序列化·反序列化
Nil2084 小时前
leetcode 139单词拆分
linux·运维·服务器
Starry-sky(jing)4 小时前
BUG: unable to handle kernel paging request 完整排查:dmesg 四要素与三路定罪
linux·运维·服务器·内核·排障
mounter6254 小时前
从硬件互连到操作系统变革:CXL 技术演进与 Linux 内核工程挑战
linux·运维·服务器
xh didida5 小时前
Linux -- 基础IO
linux·服务器·开发语言·c++
zly35006 小时前
centos7 mount设备挂载 /dev/sda1/硬盘挂载
linux·运维·服务器