全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 接口/总线/驱动 >

SPI通用接口层介绍

时间:2023-07-25 10:52

人气:

作者:admin

标签: 接口层 

导读:SPI 通用接口层 SPI 通用接口层把具体的 SPI 设备的协议驱动和 SPI 控制器驱动连接在一起。 负责 SPI 系统与 Linux 设备模型相关的初始化工作。 为协议驱动和控制器驱动提供一系列的标准...

SPI 通用接口层

  1. SPI 通用接口层把具体的 SPI 设备的协议驱动和 SPI 控制器驱动连接在一起。
  2. 负责 SPI 系统与 Linux 设备模型相关的初始化工作。
  3. 为协议驱动和控制器驱动提供一系列的标准接口 API 及其数据结构。
  4. SPI 设备、SPI 协议驱动、SPI 控制器的数据抽象
  5. 协助数据传输而定义的数据结构

kernel-4.14/drivers/spi/spi.c

static int __init spi_init(void)
{
 int status;

 buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
 if (!buf) {
  status = -ENOMEM;
  goto err0;
 }
        
  // 创建 /sys/bus/spi 节点
 status = bus_register(&spi_bus_type);
 if (status < 0)
  goto err1;

  //创建 /sys/class/spi_master 节点
 status = class_register(&spi_master_class);
 if (status < 0)
  goto err2;

 if (IS_ENABLED(CONFIG_SPI_SLAVE)) {
  status = class_register(&spi_slave_class);
  if (status < 0)
   goto err3;
 }
        ......
}

在这里创建了 SPI 总线,创建 /sys/bus/spi 节点和 /sys/class/spi_master 节点。

重要数据结构:

spi_device
spi_driver
spi_board_info
spi_controller/spi_master
spi_transfer
spi_message

重要 API

spi_message_init
spi_message_add_tail
spi_sync
spi_async
spi_write
spi_read

接下来详细解析结构体和API,只讲解重点部分,完整解析请参考官方文档

https://www.kernel.org/doc/html/v4.14//driver-api/spi.html

只有熟悉每个结构体存储的是什么东西,才能真正搞懂 SPI 模块。

spi_master/spi_controller:描述一个 spi 主机设备

struct spi_master {
  //Linux 驱动模型中的设备
 struct device dev;

  //此 spi_master 设备在全局 spi_master 链表中的节点
 struct list_head list;

  //此 spi_master 编号
 s16   bus_num;

  //此 spi_master 支持的片选信号数量
 u16   num_chipselect;

  //dma 地址对齐
 u16   dma_alignment;

  //此 spi_master 支持传输的 mode
 u16   mode_bits;
 u32   bits_per_word_mask;
 /* limits on transfer speed */
 u32   min_speed_hz;
 u32   max_speed_hz;

 /* other constraints relevant to this driver */
 u16   flags;

 /* lock and mutex for SPI bus locking */
 spinlock_t  bus_lock_spinlock;//总线自旋锁
 struct mutex  bus_lock_mutex;//总线互斥锁

  //总线是否处于 lock 状态
 bool   bus_lock_flag;

  //准备传输,设置传输的参数
 int   (*setup)(struct spi_device *spi);

  //传输数据
 int   (*transfer)(struct spi_device *spi,
     struct spi_message *mesg);
  // 设备 release 时的清除工作
 void   (*cleanup)(struct spi_device *spi);

 bool   (*can_dma)(struct spi_master *master,
        struct spi_device *spi,
        struct spi_transfer *xfer);

 bool   queued;//是否采用系统的序列化传输
 struct kthread_worker kworker;//序列化传输时的线程 worker
 struct task_struct *kworker_task;//序列化传输的线程
 struct kthread_work pump_messages;//序列化传输时的处理函数
 spinlock_t  queue_lock;//序列化传输时的queue_lock
 struct list_head queue;//序列化传输时的 msg 队列头
 struct spi_message *cur_msg;//序列化传输时当前的 msg
 bool   idling;
 bool   busy;//序列化传输时线程是否处于busy状态
 bool   running;//序列化传输时线程是否在运行
 bool   rt;//是否实时传输
  ......

 int (*prepare_transfer_hardware)(struct spi_master *master);

  //一个 msg 的传输实现
 int (*transfer_one_message)(struct spi_master *master,
        struct spi_message *mesg);
  ......

 /* gpio chip select */
 int   *cs_gpios;
  ......
};

spi_device:描述一个 spi 从机设备

struct spi_device {
  //Linux驱动模型中的设备
 struct device  dev;
 struct spi_master *master;//设备所连接的 spi 主机设备
 u32   max_speed_hz;//该设备最大传输速率
 u8   chip_select;//CS片选信号编号
 u8   bits_per_word;//每次传输长度
 u16   mode;//传输模式
 ......
 int   irq;//软件中断号
 void   *controller_state;//控制器状态
 void   *controller_data;//控制参数
 char   modalias[SPI_NAME_SIZE];//设备名称
  //CS 片选信号对应的 GPIO number
 int   cs_gpio;  /* chip select gpio */

 /* the statistics */
 struct spi_statistics statistics;
};

spi_driver:描述一个 spi 设备驱动

struct spi_driver {
  //此driver所支持的 spi 设备 list
 const struct spi_device_id *id_table;
 int   (*probe)(struct spi_device *spi);
 int   (*remove)(struct spi_device *spi);
  //系统 shutdown 时的回调函数
 void   (*shutdown)(struct spi_device *spi);
 struct device_driver driver;
};

spi_board_info:描述一个 spi 从机设备板级信息,无设备树时使用

struct spi_board_info {
  //设备名称
 char  modalias[SPI_NAME_SIZE];
 const void *platform_data;//设备的平台数据
 void  *controller_data;//设备的控制器数据
 int  irq;//设备的中断号
 u32  max_speed_hz;//设备支持的最大速率
 u16  bus_num;//设备连接的 spi 总线编号
 u16  chip_select;//设备连接的 CS 信号编号
 u16  mode;//设备使用的传输 mode
};

spi_transfer:描述 spi 传输的具体数据

struct spi_transfer {

 const void *tx_buf;//spi_transfer 的发送 buf
 void  *rx_buf;//spi_transfer 的接收 buf
 unsigned len;//spi_transfer 发送和接收的长度

 dma_addr_t tx_dma;//tx_buf 对应的 dma 地址
 dma_addr_t rx_dma;//rx_buf 对应的 dma 地址
 struct sg_table tx_sg;
 struct sg_table rx_sg;

  //spi_transfer传输完成后是否要改变 CS 片选信号
 unsigned cs_change:1;
 unsigned tx_nbits:3;
 unsigned rx_nbits:3;
  ......
 u8  bits_per_word;//spi_transfer 中一个 word 占的bits
 u16  delay_usecs;//两个 spi_transfer 直接的等待延迟
 u32  speed_hz;//spi_transfer 的传输速率

 struct list_head transfer_list;//spi_transfer挂载到的 message 节点
};

spi_message:描述一次 spi 传输的信息

struct spi_message {
  //挂载在此 msg 上的 transfer 链表头
 struct list_head transfers;
  //此 msg 需要通信的 spi 从机设备
 struct spi_device *spi;
  //所使用的地址是否是 dma 地址
 unsigned  is_dma_mapped:1;

 //msg 发送完成后的处理函数
 void   (*complete)(void *context);
 void   *context;//complete函数的参数
 unsigned  frame_length;
 unsigned  actual_length;//此 msg 实际成功发送的字节数
 int   status;//此 msg 的发送状态,0:成功,负数,失败

 struct list_head queue;//此 msg 在所有 msg 中的链表节点
 void   *state;//此 msg 的私有数据
};
温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信