0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SPI通用接口层介绍

麦辣鸡腿堡 来源:嵌入式Linux系统开发 作者:嵌入式Linux系统开 2023-07-25 10:52 次阅读

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 的私有数据
};
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SPI
    SPI
    +关注

    关注

    17

    文章

    1615

    浏览量

    89600
  • 接口层
    +关注

    关注

    0

    文章

    2

    浏览量

    984
收藏 人收藏

    评论

    相关推荐

    SPI接口硬件设计介绍

    SPI(Serial Peripheral interface)串行外围设备接口。是微控制器和外围IC(如传感器、 ADC、 DAC、移位寄存器、 SRAM等)之间使用最广泛的接口之一。SPI
    发表于 09-15 15:45 652次阅读
    <b class='flag-5'>SPI</b><b class='flag-5'>接口</b>硬件设计<b class='flag-5'>介绍</b>

    SPI协议及固件库

    》[正点原子]STM32F4开发指南-库函数版本_V1.2[ST]《STM32F4xx中文参考手册》SPI协议及总线协议介绍W25Q128产品数据手册SPI协议介绍
    发表于 08-20 08:00

    SPI协议的作用介绍

    目录SPI协议简介SPI物理SPI协议SPI协议简介SP
    发表于 02-17 07:02

    SPI接口的工作原理

    MAX7456随屏显示(OSD)发生器具有SPI™兼容接口,本应用笔记介绍SPI接口的工作原理,文中还包含在微控制器内逐位模拟
    发表于 07-27 23:24 1.4w次阅读
    <b class='flag-5'>SPI</b><b class='flag-5'>接口</b>的工作原理

    SPI接口总线介绍

    SPI接口总线介绍 SPI 可以作为主、从器件工作,并可在同一总线上支持多个主、从器件。SPI 主要使用3 个信号。(1)主输出、从
    发表于 11-24 08:41 4636次阅读
    <b class='flag-5'>SPI</b><b class='flag-5'>接口</b>总线<b class='flag-5'>介绍</b>

    一种通用SPI接口的FPGA设计与实现

    SPI 串行总线是一种常用的标准接口,其使用简单方便而且占用系统资源少,应用相当广泛。本文将介绍一种新的通用SPI 总线的FPGA 实现方
    发表于 09-09 11:58 67次下载
    一种<b class='flag-5'>通用</b><b class='flag-5'>SPI</b><b class='flag-5'>接口</b>的FPGA设计与实现

    满足物联网高速通信需求的SPI接口WiFi模块介绍

    系统总线速率的四分之一,远远高于UART、GPIO等接口,在高速通信中得到广泛应用。针对各类应用中的高速通信需求,SKYLAB推出了多款支持SPI接口的WiFi模块。本篇SKYLAB君将为大家
    的头像 发表于 04-16 10:26 2.3w次阅读

    重点介绍常用的4线SPI接口

    SPI 是一种同步、全双工、主从式接口。来自主机或从机的数据在时钟上升沿或下降沿同步。主机和从机可以同时传输数据。SPI 接口可以是3线式或4线式。
    的头像 发表于 11-13 16:45 1.9w次阅读
    重点<b class='flag-5'>介绍</b>常用的4线<b class='flag-5'>SPI</b><b class='flag-5'>接口</b>

    Firefly-RK328-SPI接口介绍

    SPI是一种高速的,全双工,同步串行通信接口,用于连接微控制器、传感器、存储设备等,本文以指纹识别模块为例简单介绍SPI使用。
    的头像 发表于 11-25 10:26 1672次阅读
    Firefly-RK328-<b class='flag-5'>SPI</b><b class='flag-5'>接口</b><b class='flag-5'>介绍</b>

    Firefly-RK3128--SPI接口介绍

    SPI是一种高速的,全双工,同步串行通信接口,用于连接微控制器、传感器、存储设备等,本文以指纹识别模块为例简单介绍SPI使用。
    的头像 发表于 11-28 16:32 2428次阅读
    Firefly-RK3128--<b class='flag-5'>SPI</b><b class='flag-5'>接口</b><b class='flag-5'>介绍</b>

    STM32CubeMX-HAL库的SPI接口使用

    本文主要介绍STM32的SPI接口、cubeMX软件配置SPI接口和分析SPI相关代码。
    发表于 02-08 15:27 10次下载
    STM32CubeMX-HAL库的<b class='flag-5'>SPI</b><b class='flag-5'>接口</b>使用

    4线SPI接口的简要介绍

    串行外设接口SPI)是微控制器和外设IC之间使用最广泛的接口之一,如传感器、ADC、DAC、移位寄存器、SRAM等。SPI 是一个基于同步、全双工主从的
    的头像 发表于 10-24 14:52 1.1w次阅读
    4线<b class='flag-5'>SPI</b><b class='flag-5'>接口</b>的简要<b class='flag-5'>介绍</b>

    常用的4线SPI接口介绍

    外设接口SPI)是微控制器和外围 IC(如传感器、ADC、DAC、 移位寄存器、SRAM等)之间使用最广泛的接口之一。
    的头像 发表于 10-25 09:06 3500次阅读

    SPI接口介绍

    电子发烧友网站提供《SPI接口介绍.pdf》资料免费下载
    发表于 10-13 10:49 0次下载
    <b class='flag-5'>SPI</b><b class='flag-5'>接口</b><b class='flag-5'>介绍</b>

    SPI接口的相关介绍

    SPI和IIC接口一样是非常常见的开发板接口,但与IIC相比,SPI设计了一种二进制流的交互方式,拥有更快的传输速度,它可以在任何两个嵌入式设备之间交换消息,ELF1开发板也是通过
    的头像 发表于 12-06 15:49 666次阅读
    <b class='flag-5'>SPI</b><b class='flag-5'>接口</b>的相关<b class='flag-5'>介绍</b>