首页主机资讯Linux驱动如何支持SPI协议

Linux驱动如何支持SPI协议

时间2025-12-04 10:42:05发布访客分类主机资讯浏览1006
导读:Linux 驱动支持 SPI 协议的整体思路 在 Linux 中,支持 SPI 协议通常分为三层:底层 SPI 控制器驱动(实现 struct spi_controller,负责时钟、FIFO、DMA、片选等)、中间 SPI 核心层(提供总...

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/CPHAbits_per_word、speed_hz 等参数决定,传输为全双工,消息内片选可保持连续。现代内核还支持 Dual/Quad 等多线模式与 DMA 提升吞吐。

实现步骤

  • 控制器驱动(主机侧)

    • 定义并初始化 spi_controller,设置能力标志(如 SPI_MASTER_HALF_DUPLEX、支持的字长掩码、最大/最小速率等)。
    • 实现关键回调:setup(按从设备的 mode/speed/字长配置寄存器)、transfer_one / transfer_one_message(发起一次或整条消息的传输)、可选的 can_dma、以及 prepare_message / unprepare_messageprepare_transfer_hardware / unprepare_transfer_hardwareset_cs(片选控制,若控制器无硬件片选则使用 GPIO)。
    • 若使用 GPIO 片选,在控制器中准备 cs_gpios 并在 set_cs 中驱动;也可在设备树中声明片选 GPIO 并由核心或控制器解析使用。
    • 注册控制器:分配并注册 spi_master,使其出现在 SPI 总线上,等待设备匹配与消息调度。
  • 设备树或板级描述(实例化从设备)

    • 设备树方式(推荐):在 SPI 控制器节点下声明从设备子节点,至少包含 compatible、reg(片选号),并按需设置 spi-max-frequency、spi-cpol、spi-cpha、spi-cs-high、bits-per-word 等属性;内核会据此创建 spi_device 并与驱动匹配。
    • 旧式板级方式:在板级代码中填充 spi_board_info 并通过 spi_register_board_info 注册,控制器注册时会扫描并创建对应的 spi_device
  • 设备协议驱动(外设侧)

    • 定义 spi_driver,用 of_match_table 匹配设备树 compatible,实现 probe/remove
    • 在 probe 中完成设备私有数据分配、寄存器/参数初始化,并可选择使用 Regmap API 简化寄存器访问(尤其多寄存器外设)。
    • 数据通信遵循“消息-片段”模型:构造一个或多个 spi_transfer(设置 tx_buf/rx_buf、len、speed_hz、bits_per_word、delay_usecs、cs_change、tx_nbits/rx_nbits 等),用 spi_message_init + spi_message_add_tail 组装,最后通过 spi_sync(同步)或 spi_async(异步回调)提交;必要时在消息间保持 CS 连续以满足时序。

关键数据结构与传输要点

  • 常用结构

    • spi_device:包含 bus_num、chip_select、mode(CPOL/CPHA)、bits_per_word、max_speed_hz 等,代表挂接在总线上的具体从设备。
    • spi_transfer:一次单向(或半双工)数据片段,支持 tx_buf/rx_buf、len、speed_hz、bits_per_word、delay_usecs、cs_change、tx_nbits/rx_nbits(支持 单线/双线/四线)。
    • spi_message:由多个 transfer 组成,片选在消息期间可保持,适合一次事务内的多段时序拼接。
  • 传输与性能

    • 短小数据可用 PIO(如 spi_sync),大数据或高吞吐建议启用 DMA 与消息队列(线程化)以降低 CPU 占用。
    • 多线模式:通过 tx_nbits/rx_nbits 选择 DUAL/QUAD 传输(部分控制器/Flash 支持),显著提升带宽。

最小示例骨架

  • 设备树节点(示例)

    &
    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");
        
    

调试与常见问题

  • 确认控制器与设备绑定:检查 /sys/bus/spi/devices//sys/bus/spi/drivers/,以及 dmesg 中 probe 输出。
  • 片选与 GPIO:若 cs-gpios 未正确配置,可能导致片选不生效;可在控制器中实现 set_cs 或在设备树显式声明片选 GPIO。
  • 时序与速率:核对 spi-cpol/spi-cpha、spi-max-frequency、bits-per-word 是否与器件手册一致;必要时在 transfer 中设置 delay_usecs 满足建立/保持时间。
  • 传输模式:只读事务仍需提供 tx_buf(可指向 dummy 缓冲区);全双工下 rx_buf 会收到同时钟移出的数据。
  • 性能优化:长传输启用 DMA 与消息队列;多线器件使用 DUAL/QUAD 模式提升吞吐。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: Linux驱动如何支持SPI协议
本文地址: https://pptw.com/jishu/763314.html
怎样配置Debian SFTP端口转发 Linux驱动中如何优化功耗

游客 回复需填写必要信息