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

    文章

    1866

    浏览量

    99733
  • 接口层
    +关注

    关注

    0

    文章

    2

    浏览量

    1073
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    SPI接口硬件设计介绍

    SPI(Serial Peripheral interface)串行外围设备接口。是微控制器和外围IC(如传感器、 ADC、 DAC、移位寄存器、 SRAM等)之间使用最广泛的接口之一。SPI
    发表于 09-15 15:45 3452次阅读
    <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

    基于PC/104 总线与CPLD 的SPI 接口设计

    本文根据SPI 同步串行接口的通信协议,介绍了在CPLD 中利用VHDL 语言实现PC/104 总线扩展SPI 接口的设计原理和编程思想。
    发表于 05-30 09:28 41次下载

    SPI接口的工作原理

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

    SPI接口总线介绍

    SPI接口总线介绍 SPI 可以作为主、从器件工作,并可在同一总线上支持多个主、从器件。SPI 主要使用3 个信号。(1)主输出、从
    发表于 11-24 08:41 5112次阅读
    <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设计与实现

    Firefly-RK328-SPI接口介绍

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

    《STM32从零开始学习历程》——SPI协议

    》[正点原子]STM32F4开发指南-库函数版本_V1.2[ST]《STM32F4xx中文参考手册》SPI协议及总线协议介绍W25Q128产品数据手册协议介绍
    发表于 12-22 19:36 11次下载
    《STM32从零开始学习历程》——<b class='flag-5'>SPI</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>使用

    SPI接口简介

    串行外设接口(SPI)是微控制器和外围IC(如传感器、ADC、DAC、移位寄存器、SRAM等)之间使用较广泛的接口之一。本文先简要说明SPI接口
    的头像 发表于 06-17 09:13 8170次阅读
    <b class='flag-5'>SPI</b><b class='flag-5'>接口</b>简介

    SPI控制器驱动功能介绍

    和相应的设备进行正确的数据交换 向通用接口提供接口,使得上层的协议驱动可以通过通用接口
    的头像 发表于 07-25 10:58 2609次阅读
    <b class='flag-5'>SPI</b>控制器驱动<b class='flag-5'>层</b>功能<b class='flag-5'>介绍</b>

    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 2207次阅读
    <b class='flag-5'>SPI</b><b class='flag-5'>接口</b>的相关<b class='flag-5'>介绍</b>