SPI驱动学习七(SPI_Slave_Mode驱动程序框架)

目录

  • 一、SPI_Slave_Mode驱动程序框架
    • 1. Master和Slave模式差别
      • 1.1 主设备 (Master)
      • 1.2 从设备 (Slave)
      • 1.3 示例
    • 2. SPI传输概述
      • 2.1 数据组织方式
      • 2.2 SPI控制器数据结构
    • 3. SPI Slave Mode数据传输过程
    • 4. 如何编写程序
      • 4.1 设备树
      • 4.2 内核相关
      • 4.3 简单的示例代码
        • 4.3.1 master和slave驱动示例
        • 4.3.2 master和slave使用示例
  • 二、SPI_Slave_Mode驱动程序源码解读(drivers/spi/spi-imx.c)
    • 1. 设备树
    • 2. 控制器驱动程序
      • 2.1 分配一个spi_controller
      • 2.2 设置spi_controller
      • 2.3 注册spi_controller
      • 2.4 硬件操作
    • 3. 设备驱动程序
      • 3.1 Master模式
      • 3.2 Slave模式

一、SPI_Slave_Mode驱动程序框架

  • 参考内核源码: Linux-5.x\drivers\spi\spi-imx.c
  • 注意:Linux 4.9的内核未支持SPI Slave Mode
  • 参考文档:《Linux_as_an_SPI_Slave_Handouts.pdf》

1. Master和Slave模式差别

  SPI(串行外设接口,Serial Peripheral Interface)是一种常用的同步串行通信协议,用于微控制器与各种外设(如传感器、存储器、显示器等)之间的通信。在 SPI 通信中,通常有两个角色:主设备(Master)和从设备(Slave)。这两者之间的区别如下:

1.1 主设备 (Master)

  • 定义:主设备负责控制 SPI 通信,生成时钟信号,并管理从设备的选择。

  • 功能

    • 时钟产生:主设备生成 SPI 时钟信号(SCK),并控制数据传输的速率。
    • 选择从设备:通过选择线(如 Chip Select,CS)选择与其通信的特定从设备。通常在传输数据前,主设备会将 CS 线拉低以使对应的从设备准备接收数据。
    • 数据发送和接收:主设备负责读取从设备发送的数据,并向从设备发送命令和数据。
  • 例子:微控制器通常充当主设备,与多个传感器或存储器从设备通信。

1.2 从设备 (Slave)

  • 定义:从设备被动地响应主设备的命令。它不会主动启动通信,而是等待主设备进行操作。

  • 功能

    • 响应主设备:从设备在主设备的指令下工作,并在主设备发送时钟信号时提供数据。
    • 数据接收和发送:从设备接收来自主设备的数据,并将其处理后,发送响应或数据回主设备。
  • 例子:传感器、EEPROM、LCD 显示屏等通常作为从设备,实现数据的接收和响应。

1.3 示例

以IMX6ULL为例,Master和Slave模式的异同如下图:

  • 初始化

    • 使用的SPI寄存器有所不同
    • 引脚有所不同:Master模式下SS、CLK引脚是输出引脚,Slave模式下这些引脚是输入引脚
  • 准备数据:都需要准备好要发送的数据,填充TX FIFO

  • 发起传输:Master模式下要主动发起传输,等待发送完成(等待中断)

  • 使能接收中断:Slave模式下无法主动发起传输,只能被动地等待,使能接收中断即可

  • 中断函数里:读取RXFIFO得到数据

  • 传输完成

  • 在这里插入图片描述

2. SPI传输概述

2.1 数据组织方式

  使用SPI传输时,最小的传输单位是"spi_transfer",对于一个设备,可以发起多个spi_transfer,这些spi_transfer,会放入一个spi_message里。
在这里插入图片描述
所以,反过来,SPI传输的流程是这样的:

  • 从spi_master的队列里取出每一个spi_message
    • 从spi_message的队列里取出一个spi_transfer
      • 处理spi_transfer

2.2 SPI控制器数据结构

  参考内核文件:include\linux\spi\spi.h,Linux中SPI控制器struct spi_controller,有两套传输方法:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/a3c374792e144463b6bb6113c558bbde.png

3. SPI Slave Mode数据传输过程

在这里插入图片描述

4. 如何编写程序

4.1 设备树

  • SPI控制器设备树节点中,需要添加一个空属性:spi-slave
  • 要模拟哪类slave设备?需要添加slave子节点,这是用来指定slave protocol
    在这里插入图片描述

4.2 内核相关

  • 新配置项:CONFIG_SPI_SLAVE

  • 设备树的解析:增加对spi-slaveslave子节点的解析

  • sysfs:新增加/sys/devices/.../CTLR/slave,对应SPI Slave handlers

  • 新API

    • spi_alloc_slave( )
    • spi_slave_abort( )
    • spi_controller_is_slave( )
  • 硬件设置不一样

    • master:SS、SCLK引脚是输出引脚
    • slave:SS、SCLK引脚是输入引脚
  • 传输时等待函数不一样

    • master:master主动发起spi传输,它可以指定超时时间,使用函数wait_for_completion_timeout() 进行等待
    • slave:slave只能被动等待传输,它无需指定超时时间,使用函数wait_for_completion_interruptible()进行等待 ,使用.slave_abort() 来取消等待

4.3 简单的示例代码

4.3.1 master和slave驱动示例

在这里插入图片描述

4.3.2 master和slave使用示例

  对于设置为spi master模式的spi控制器,下面接的是一个一个spi slave设备,我们编写各类spi slave driver,通过spi master的函数读写spi slave 设备。

  对于设置为spi slave模式的spi控制器,它是作为一个spi slave设备被其他单板的spi master设备来访问,它如何接收数据、如何提供数据?我们编写对应的spi slave handler。

  对于master和slave,有两个重要概念:

  • SPI Slave Driver:通过SPI Master控制器跟SPI Slave设备通信
  • SPI Slave Handler:通过SPI Slave控制器监听远端的SPI Master
    在这里插入图片描述

二、SPI_Slave_Mode驱动程序源码解读(drivers/spi/spi-imx.c)

1. 设备树

下图是摘自《Linux_as_an_SPI_Slave_Handouts.pdf》:
在这里插入图片描述

2. 控制器驱动程序

  在Linux 5.x版本中,SPI控制器的驱动程序仍然使用原理的名字:struct spi_master,但是它已经是一个宏:

#define spi_master			spi_controller

  这意味着它可以工作于master模式,也可以工作于slave模式。

2.1 分配一个spi_controller

在这里插入图片描述

2.2 设置spi_controller

  工作于slave模式时,跟master模式最大的差别就是如下函数不一样:

  • bitbang.txrx_bufs函数不一样
    • 在IMX6ULL中,这个函数为spi_imx_transfer,里面对master、slave模式分开处理
    • master模式:使用spi_imx_pio_transfer函数
    • slave模式:使用spi_imx_pio_transfer_slave函数
  • 增加了bitbang.master->slave_abort函数
    在这里插入图片描述
      不同厂家的SOC的SPI 驱动实现会有所不同,有的就不会用到bitbang;spi_bitbang 结构体定义了一种软件模拟SPI通信的方式,通过软件控制GPIO引脚来实现SPI通信所需的时序和信号。这种方法通常用于那些没有内置SPI硬件控制器的微控制器或系统上。

2.3 注册spi_controller

  无论是master模式,还是slave模式,注册函数时一样的:
在这里插入图片描述
  在spi_bitbang_start内部,会处理设备树中的子节点,创建并注册spi_device:

spi_bitbang_startspi_register_masterspi_register_controllerof_register_spi_devices

  对于master模式,设备树中的子节点对应真实的spi设备;但是对于slave模式,这些子节点只是用来选择对应的spi slave handler:就是使用哪个驱动来模拟spi slave设备,比如:
在这里插入图片描述

/* drivers/spi/spi-slave-time.c* SPI从机处理器,接收上一条SPI消息后报告系统运行时间** 该SPI从机处理器以二进制格式和网络字节顺序发送上一条SPI消息接收时间* 的两个32位无符号整数,分别表示自系统启动以来的秒数和小数秒数(以微秒为单位)。** 版权所有 (C) 2016-2017 Glider bvba** 本文件受 GNU 通用公共许可证条款和条件的约束。请参阅此存档主目录中的 "COPYING" 文件以获取更多详细信息。** 使用方法(假设 /dev/spidev2.0 对应远程系统上的 SPI 主设备):**   # spidev_test -D /dev/spidev2.0 -p dummy-8B*   spi 模式: 0x0*   每字的位数: 8*   最大速度: 500000 Hz (500 KHz)*   RX | 00 00 04 6d 00 09 5b bb ...*		^^^^^    ^^^^^^^^*		秒数    微秒数*/#include <linux/completion.h>
#include <linux/module.h>
#include <linux/sched/clock.h>
#include <linux/spi/spi.h>struct spi_slave_time_priv {struct spi_device *spi;struct completion finished;struct spi_transfer xfer;struct spi_message msg;__be32 buf[2];
};static int spi_slave_time_submit(struct spi_slave_time_priv *priv);/*** @brief SPI从机时间补偿函数* * 当SPI从机传输完成或者发生错误时,此函数被调用以处理相应的后续操作。主要功能包括检查上一次传输状态,* 并根据状态决定是否继续提交时间补偿处理或者终止并通知上层。* * @param arg 传递给此函数的参数,实际类型为struct spi_slave_time_priv*,用于访问SPI从机时间补偿相关的数据。*/
static void spi_slave_time_complete(void *arg)
{// 将参数转换为相应的结构体指针,以便访问私有数据struct spi_slave_time_priv *priv = arg;// 存储操作结果的变量int ret;// 检查上一次SPI从机消息的状态,如果存在错误,则不继续操作ret = priv->msg.status;if (ret)goto terminate;// 尝试提交下一次时间补偿处理,如果提交失败,则跳转到terminate块ret = spi_slave_time_submit(priv);if (ret)goto terminate;// 如果没有错误,正常返回return;terminate:// 当出现错误或者传输完成时,记录日志并通知上层处理已经完成dev_info(&priv->spi->dev, "Terminating\n");complete(&priv->finished);
}/*** 提交SPI从机时间同步请求** 该函数用于从SPI从机角度,向SPI主机请求时间同步。它会将本地时钟和剩余微秒封装成数据,* 并通过SPI异步传输的方式发送给SPI主机。时间同步对于需要在分布式系统中保持时间一致性的* 应用非常关键。** @param priv 指向SPI从机时间私有数据结构的指针,包含必要的传输数据和配置信息。* @return 返回spi_async调用的结果,如果失败则记录错误信息。*/
static int spi_slave_time_submit(struct spi_slave_time_priv *priv)
{// 剩余的微秒部分u32 rem_us;// 返回值int ret;// 时间戳,以纳秒为单位u64 ts;// 获取当前的本地时钟值,以纳秒为单位ts = local_clock();// 从纳秒转换到微秒,并将结果保存到rem_usrem_us = do_div(ts, 1000000000) / 1000;// 将纳秒和微秒部分分别转换为大端字节序,并存入缓冲区priv->buf[0] = cpu_to_be32(ts);priv->buf[1] = cpu_to_be32(rem_us);// 初始化SPI消息,只包含一个传输操作spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1);// 设置SPI消息的完成回调函数和上下文数据priv->msg.complete = spi_slave_time_complete;priv->msg.context = priv;// 异步发送SPI消息ret = spi_async(priv->spi, &priv->msg);// 如果发送失败,记录错误信息if (ret)dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret);return ret;
}/*** spi_slave_time_probe - SPI从机时间延迟自动探测函数* @spi: 指向SPI设备结构体的指针** 本函数用于在SPI从机模式下,自动探测和调整时间延迟参数,以确保SPI通信的正确性和稳定性。* 它通过分配私有数据空间,初始化必要的结构,然后提交一个SPI传输请求来进行时间延迟探测。* 若探测过程出错,则返回相应的错误码。** 返回: 0表示成功,负值表示遇到的相应错误。*/
static int spi_slave_time_probe(struct spi_device *spi)
{struct spi_slave_time_priv *priv;int ret;/* 分配内存用于存储私有数据,包括时间延迟探测所需的各种数据 */priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);if (!priv)return -ENOMEM;/* 初始化私有数据结构中的成员 */priv->spi = spi;init_completion(&priv->finished);priv->xfer.tx_buf = priv->buf;priv->xfer.len = sizeof(priv->buf);/* 提交SPI传输请求,进行时间延迟探测 */ret = spi_slave_time_submit(priv);if (ret)return ret;/* 将私有数据结构与SPI设备驱动模型数据关联,以便后续使用 */spi_set_drvdata(spi, priv);return 0;
}/*** 从SPI设备中移除slave定时器功能* * 本函数主要用于从SPI设备中移除slave定时器功能在一些情况下,可能需要* 中止当前的SPI传输操作,并确保所有相关的定时器处理已经完成此函数通过* 调用spi_slave_abort来尝试中止当前的SPI操作,并通过等待完成来确保所有* 相关的定时器处理已经结束这对于在设备移除或者重新配置时清理资源非常有用* * @param spi 指向SPI设备结构的指针该参数是必需的,用于标识需要进行操作的SPI设备* * @return 该函数返回0,表示执行成功这里不使用其他的返回值,因为当前的实现* 不需要区分更多的错误类型* * 注意:该函数假定传入的spi参数是非空的,并且spi所指向的设备已经正确初始化并* 具有slave定时器功能*/
static int spi_slave_time_remove(struct spi_device *spi)
{// 获取与SPI设备相关的私有数据struct spi_slave_time_priv *priv = spi_get_drvdata(spi);// 尝试中止当前的SPI操作spi_slave_abort(spi);// 等待直到所有定时器相关的操作完成wait_for_completion(&priv->finished);return 0;
}static struct spi_driver spi_slave_time_driver = {.driver = {.name	= "spi-slave-time",},.probe		= spi_slave_time_probe,.remove		= spi_slave_time_remove,
};
module_spi_driver(spi_slave_time_driver);MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
MODULE_DESCRIPTION("SPI slave reporting uptime at previous SPI message");
MODULE_LICENSE("GPL v2");

2.4 硬件操作

在这里插入图片描述

3. 设备驱动程序

3.1 Master模式

在这里插入图片描述

3.2 Slave模式

  参考代码:Linux-5.x\drivers\spi\spi-slave-time.c
在这里插入图片描述

  本文章参考了韦东山老师驱动大全部分笔记,其余内容为自己整理总结而来。水平有限,欢迎各位在评论区指导交流!!!😁😁😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1549412.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

K8S真正删除pod

假设k8s的某个命名空间如&#xff08;default&#xff09;有一个运行nginx 的pod&#xff0c;而这个pod是以kubectl run pod命令运行的 1.错误示范&#xff1a; kubectl delete pod nginx-2756690723-hllbp 结果显示这个pod 是删除了&#xff0c;但k8s很快自动创建新的pod,但是…

今日指数项目股票成交量对比功能

股票成交量对比功能 1. 股票成交量对比功能分析 1.1 模型示列 功能描述&#xff1a;统计A股大盘T日和T-1日成交量对比功能&#xff08;成交量为沪深两市成交量之和&#xff09; 1.2 接口示列 返回数据格式 服务路径&#xff1a;/api/quot/stock/tradeAmt 服务方法&#xf…

PCL uniform_sampling均匀采样抽稀

目录 一、概述二、代码三、结果 一、概述 均匀采样抽稀点云。 二、代码 uniform_sampling.cpp #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/keypoints/uniform_s…

[Admin] Things Need to Know

List View Bulk Actions Highlight: To take bulk actions on all of the available records in a list, you click the bulk action button without selecting any records.

利士策分享,攀登职场高峰:成功者的十大特质

利士策分享&#xff0c;攀登职场高峰&#xff1a;成功者的十大特质 在职场这个竞争激烈的舞台上&#xff0c;那些能够迅速崛起、实现职业辉煌的佼佼者&#xff0c;往往凭借一系列独特且鲜明的特质脱颖而出。以下是对这些特质的深入探讨&#xff1a; 第一章&#xff1a;高情商的…

怎么不用付费直接编辑pdf?5款pdf在线编辑器免费推荐给你!

在我们日常工作中&#xff0c;可能会经常需要直接编辑修改pdf内容&#xff0c;例如&#xff0c;在将文档发送给其它人之前&#xff0c;您可能需要进行一些修改&#xff1b;或者当扫描的文本出现错误时&#xff0c;您也需要进行修正。此时&#xff0c;如果有一款在线编辑器&…

黑神话悟空小西天

游戏里我们一开始就出现一个很可爱的小和尚&#xff0c;当脚步声传来&#xff0c;小和尚化身为一尊弥勒佛&#xff0c;而这尊弥勒佛的大小和位置都在说&#xff0c;这里没有弥勒佛的位置。 随后天命人进入一片雪地&#xff0c;遇到了赤尻马猴&#xff0c;打跑赤尻马猴&#xff…

从哪里下载高清解压视频素材?推荐五个优质素材资源网站

想制作吸引人的抖音小说推文&#xff0c;但不知道从哪里获取高清解压视频素材&#xff1f;今天就为大家推荐五个优秀的网站&#xff0c;帮助你轻松找到所需的素材&#xff0c;提升你的创作质量。 首先是蛙学网 作为国内顶级的短视频素材网站&#xff0c;蛙学网提供了丰富的4K高…

Transformer是不是BERT、GPT的妈?看完就知道了

Transformer变异衍生出来了两个超强悍的预训练模型 一、Transformer模型 Transformer是近年来深度学习领域中备受瞩目的模型之一&#xff0c;其核心思想是通过自注意力机制和位置编码来捕捉输入序列中的长距离依赖关系。 自注意力机制让模型在处理每个输入元素时能够关注到所有…

Proe 5.0资源百度网盘下载 附详细安装步骤

如大家所了解的&#xff0c;Proe又称作Pro/E&#xff0c;是比较常用的CAD/CAM/CAE软件之一&#xff0c;也是一款功能齐全的模具和产品设计三维的工具。 Proe在传统机械设计、家电设计以及模具设计方面&#xff0c;优势很突出。 首先&#xff0c;建模采用参数化设计&#xff0…

Qt/C++ 解决调用国密SM3,SM4加密解密字符串HEX,BASE64格式转换和PKCS5Padding字符串填充相关问题

项目中遇到了需要与JAVA WEB接口使用SM3,SM4加密数据对接的需求&#xff0c;于是简单了解了下SM3与SM4加密算法在C环境下的实现。并使用Qt/C还原了在线SM3国密加密工具和在线SM4国密加密解密工具网页的示例功能的实现 目录导读 前言SM3算法简介SM4算法简介 实现示例字符串HEX,B…

气膜影院:沉浸式观影体验的全新选择—轻空间

随着观影需求的不断提升&#xff0c;传统影院形式已经无法满足观众对更高沉浸感和视觉体验的追求。气膜影院作为一种新兴的观影场所&#xff0c;以其独特的球幕结构和先进的技术手段&#xff0c;为观众带来了全新的沉浸式视听体验。 全景沉浸式观影体验 气膜影院采用球幕设计&a…

Awcing 799. 最长连续不重复子序列

Awcing 799. 最长连续不重复子序列 解题思路: 让我们找到一个数组中&#xff0c;最长的 不包含重复的数 的连续区间的长度。 最优解是双指针算法&#xff1a; 我们用 c n t [ i ] cnt[i] cnt[i]记录 i i i 这个整数在区间内出现的次数。(因为每个数的大小为 1 0 5 10^5 105, …

赵长鹏今日获释,下一步会做什么?币安透露2024年加密货币牛市的投资策略!

中国时间2024年9月28日&#xff0c;加密货币行业的风云人物赵长鹏&#xff08;Changpeng Zhao&#xff0c;简称CZ&#xff09;终于从监狱获释。他因在担任币安首席执行官期间未能有效执行反洗钱(AML)计划而被判刑四个月。赵长鹏的获释引发了广泛关注&#xff0c;不仅因为他是全…

大语言模型知识点分享

1 目前主流的开源模型体系有哪些&#xff1f; Prefix Decoder 系列模型 核心点&#xff1a; 输入采用双向注意力机制&#xff0c;输出为单向注意力。双向注意力意味着输入的每个部分都可以关注到输入的所有其他部分&#xff0c;这在理解上下文时具有很强的优势。 代表模型&a…

python全栈开发《41.列表的clear函数》

1.clear的功能 一次性将当前列表中所有的数据清空。 2.clear的用法 target [1,2,3,4,5,6] target.clear() print(target) 运行结果&#xff1a; /Users/llq/PycharmProjects/pythonlearn/pythonlearn/python_list/bin/python /Users/llq/PycharmProjects/pythonlearn/python_l…

JavaEE: 探索网络世界的核心-IP协议

文章目录 IP 协议协议头格式IP 地址IP地址的数量限制解决IP不够用的问题 IP 地址的网段划分子网掩码ABCDE五类网络 特殊的 IP 地址 IP 协议 协议头格式 4位版本号: 只有两个取值,4(IPv4)和6(IPv6). IPv2,IPv5这些在实际中是没有的,可能是理论上/实验室中存在~ 4位首部长度: IP…

Redis集群的两种方式

1.Redis集群 1.1 搭建主从集群 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写的分离。一般情况下&#xff0c;主节点负责写操作&#xff0c;从节点负责读操作。而从节点如何得知数据呢&#xff…

Study-Oracle-10-ORALCE19C-RAC集群搭建(一)

一、硬件信息及配套软件 1、硬件设置 RAC集群虚拟机:CPU:2C、内存:10G、操作系统:50G Openfile数据存储:200G (10G*2) 2、网络设置 主机名公有地址私有地址VIP共享存储(SAN)rac1192.168.49.13110.10.10.20192.168.49.141192.168.49.130rac2192.168.49.13210.10.10.3…

产品管理 - 互联网产品(4): 交互设计

原型设计 原型是产品可视化的展示&#xff0c;包括了产品的信息架构、功有、内容、交互方式。目前业务普遍菜用了Axure作为原型设计工具。产品或交互人员通过对信息架构的梳理&#xff0c;确认界面内容区的划分&#xff0c;并通过交互方式呈现功能点。 原型分为线框图、低保真…