Linux应用开发笔记(八)SPI应用层开发及其框架

news2024/11/18 2:28:11

文章目录

  • 前言
  • 一、扩展SPI协议(Single/Dual/Quad/Octal SPI)
  • 二、SPi驱动框架
  • 三、SPI应用编程
    • 1. SPI相关数据结构与ioctl函数
    • 2. 基本函数


前言

  与IIC类似,SPI协议也是我们的老朋友了,这里依然不多作赘述,本文将介绍SPI的驱动框架和应用程序编写。

一、扩展SPI协议(Single/Dual/Quad/Octal SPI)

  为了适应更高速率的通讯需求,半导体厂商扩展SPI协议,主要发展出了Dual/Quad/Octal SPI协议,加上 标准SPI协议(Single SPI),这四种协议的主要区别是数据线的数量及通讯方式,具体见下表。

协议数据线数量及功能通讯方式
Single SPI(标准SPI)1根发送,1根接收全双工
Dual SPI(双线SPI)收发共用2根数据线半双工
Quad SPI(四线SPI)收发共用4根数据线半双工
Octal SPI(八线SPI)收发共用8根数据线半双工

  扩展的三种SPI协议都是半双工的通讯方式,也就是说它们的数据线是分时进行收发 数据的。例如,标准SPI(Single SPI)与双线SPI(Dual SPI)都是两根数据线,但标准SPI(Single SPI)的其中一根数据线只用来发送,另一根数据线只用来接收,即全双工;而双线SPI(Dual SPI)的两根线都具有收发功能,但在同一时刻只能是发送或者是接收,即半双工,但其主要针对SPI Flash,而不是所有SPI外设;四线SPI(Quad SPI)同样主要针对SPI Flash,其目标是在一个时钟周期内传输4个bit数据;Octal SPI(八线SPI)通同一时钟周期内能够传输更多的数据,从而实现了更高的传输速率,此外Octal SPI还引入了多种时钟模式,以支持不同的数据传输速率和时序要求。

  • SDR和DDR模式

  扩展的SPI协议还增加了SDR模式(单倍速率Single Data Rate)和DDR模式(双倍速率Double Data Rate)。例如在标准SPI协议的SDR模式下,只在SCK的单边沿进行数据传输,即一个SCK时钟只传输一位数据;而在它的DDR模式下,会在SCK的上升沿和下降沿都进行数据传输,即一个SCK时钟能传输两位数据,传输速率提高一倍。

二、SPi驱动框架

  • 用户空间

  对于用户而言,SPI驱动模型提供了一种方便、灵活的方式来与外部设备进行通信。用户无需深入了解底层硬件细节,只需通过SPI接口发送相应的指令和数据,即可实现对外部设备的控制或数据的读取。这种抽象化的接口使得用户能够更专注于应用层面的开发,提高了开发效率和便利性。例如,和 MTD 层交互以便把 SPI 接口的存储设备实现为某个文件系统,和TTY 子系统交互把 SPI 设备实现为一个 TTY 设备,和网络子系统交互以便把一个 SPI 设备实现为一个网络设备,等等。当然,如果是一个专有的 SPI 设备,我们也可以按设备的协议要求,实现自己的专有协议驱动。

  • 内核方面

  在内核层面,SPI驱动模型负责管理和控制SPI接口的工作。Linux内核中的SPI驱动架构通常分为三个层次:SPI核心层、SPI控制器驱动层和SPI设备驱动层。
   - SPI核心层(SPI通用接口层)是Linux的SPI核心部分,提供了核心数据结构的定义、SPI控制器驱动和设备驱动的注册、注销管理等API。其为硬件平台无关层,向下屏蔽了物理总线控制器的差异,定义了统一的访问策略和接口;其向上提供了统一的接口,以便SPI设备驱动通过总线控制器进行数据收发。
   - SPI控制器驱动层,每种处理器平台都有自己的控制器驱动,属于平台移植相关层。它的职责是为系统中每条SPI总线实现相应的读写方法。在物理上,每个SPI控制器可以连接若干个SPI从设备。
   - SPI设备驱动层则实现了与具体SPI设备的通信协议和数据交换机制。内核通过SPI驱动模型,为上层应用提供了统一的接口,使得应用能够通过SPI接口与底层硬件进行通信。同时,内核还负责处理SPI接口的中断和错误情况,确保数据传输的稳定性和可靠性。

  • 硬件方面

  在硬件方面,SPI驱动模型与具体的SPI控制器和从设备紧密相关。SPI控制器负责产生时钟信号、控制从设备的使能以及数据的发送和接收。从设备则根据SPI接口的协议进行数据的传输和处理。SPI驱动模型需要与这些硬件设备进行协同工作,确保数据的正确传输和设备的正常工作。在这里插入图片描述

三、SPI应用编程

1. SPI相关数据结构与ioctl函数

  编写应用程序需要使用到spi_ioc_transfer结构体,如下所示:

struct spi_ioc_transfer {
   __u64             tx_buf;     //发送数据缓存
   __u64             rx_buf;     //接收数据缓存

   __u32             len;        //数据长度
   __u32             speed_hz;   //通讯速率

   __u16             delay_usecs;    //两个spi_ioc_transfer之间的延时,微秒
   __u8              bits_per_word;  //数据长度
   __u8              cs_change;      //取消选中片选
   __u8              tx_nbits;       //单次数据宽度(多数据线模式)
   __u8              rx_nbits;       //单次数据宽度(多数据线模式)
   __u16             pad;
};

  在编写应用程序时还需要使用ioctl函数设置spi相关配置,其函数原型如下

 #include <sys/ioctl.h>

 int ioctl(int fd, unsigned long request, ...);

  其中对于终端request的值常用的有以下几种:

参数取值功能
SPI_IOC_RD_MODE32设置读取SPI模式(对应上文的SPI的四种模式的表格,SPI_MODE_x)
SPI_IOC_WR_MODE32设置写入SPI模式(对应上文的SPI的四种模式的表格,SPI_MODE_x)
SPI_IOC_RD_LSB_FIRST设置SPI读取数据模式(LSB先行返回1)
SPI_IOC_WR_LSB_FIRST设置SPI写入数据模式。(0:MSB,非0:LSB)
SPI_IOC_RD_BITS_PER_WORD设置SPI读取设备的字长
SPI_IOC_WR_BITS_PER_WORD设置SPI写入设备的字长
SPI_IOC_RD_MAX_SPEED_HZ设置读取SPI设备的最大通信频率
SPI_IOC_WR_MAX_SPEED_HZ设置写入SPI设备的最大通信速率
SPI_IOC_MESSAGE(N)一次进行双向/多次读写操作

2. 基本函数

  • 初始化
void spi_init(void)
{
    int ret = 0;
    //打开 SPI 设备
    fd = open(SPI_DEV_PATH, O_RDWR);
    if (fd < 0)
        printf("can't open %s\n",SPI_DEV_PATH);

    //spi mode 设置SPI 工作模式
    ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
    if (ret == -1)
        printf("can't set spi mode\n");

    //bits per word  设置一个字节的位数
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        printf("can't set bits per word\n");

    //max speed hz  设置SPI 最高工作频率
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        printf("can't set max speed hz\n");

    //打印
    printf("spi mode: 0x%x\n", mode);
    printf("bits per word: %d\n", bits);
    printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);
}
  • 数据传输
void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
   int ret;

   struct spi_ioc_transfer tr = {
       .tx_buf = (unsigned long)tx,	//发送缓冲区地址
       .rx_buf = (unsigned long)rx,	//接收缓冲区地址
       .len = len,				    //一次传输的数据长度
       .delay_usecs = delay,		//如果不为零则用于设置两次传输之间的时间延迟
       .speed_hz = speed,			//speed_hz,指定SPI通信的比特率
       .bits_per_word = bits,		//指定字节长度,既一个字节占用多少比特
       .tx_nbits = 1,					
       .rx_nbits = 1
   };

   ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
   
   if (ret < 1)

注:tx_nbits/rx_nbits 指定“写/读”数据宽度,SPI 支持1、2、4位宽度,如果没有特殊数据要求的话,一般设置为1或0(设置为0表示使用默认的宽度既宽度为1)。

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

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

相关文章

Flutter第八弹 构建拥有不同项的列表

目标&#xff1a;1&#xff09;项目中&#xff0c;数据源可能涉及不同的模版&#xff0c;显示不同类型的子项&#xff0c;类似RecycleView的itemType, 有多种类型&#xff0c;列表怎么显示&#xff1f; 2&#xff09;不同的数据源构建列表 一、创建不同的数据源 采用类似Rec…

韩顺平Java | C25 JDBC和连接池(上)

概述 JDBC概述&#xff1a;JDBC为访问不同数据库提供统一接口&#xff0c;为使用者屏蔽细节问题。Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统&#xff0c;从而完成对数据库的各种操作。 // 模拟代码 //JdbcInterface.java --Java规定的JDBC接口(方法) p…

Linux-文件系统理解(磁盘的物理与逻辑结构、什么是inode、OS如何管理磁盘)

一、磁盘 磁盘的物理结构 磁盘的本质是一个机械设备&#xff0c;可以存储大量的二进制信息&#xff0c;是实现数据存储的基础硬件设施&#xff0c;磁盘的盘片类似于光盘&#xff0c;不过盘片的两面都是可读可写可擦除的&#xff0c;每个盘面都有一个磁头&#xff0c;马达可以使…

keil无法查看外设寄存器(生成SFR文件)

1.前言 自从更新了keil&#xff0c;用的是越来越不顺手了&#xff0c;一会是cannot evaluate&#xff0c;一会是与强制与cubemx强制联系了&#xff0c;这次也是的&#xff08;地铁&#xff0c;老人&#xff0c;手机&#xff09;折腾了一下总是搞好了&#xff08;网上的解法只能…

安卓刷机fastboot分段传输

win10 fastboot 无法识别&#xff0c;驱动下载地址GitHub - xushuan/google_latest_usb_driver_windows 把inf文件更新到设备管理器驱动更新即可 问题 archive does not contain super_empty.img Sending vbmeta_a (4 KB) OKAY [ 0.117s] Writing …

Open CASCADE学习|实现Extrude功能

首先定义了一些基本的几何元素&#xff0c;如线、圆和平面&#xff0c;然后使用makeExtrudebydir函数来对一个面进行挤出操作。下面是详细过程&#xff1a; 定义Extrude函数&#xff1a;makeExtrudebydir函数接受一个TopoDS_Shape对象和一个gp_Vec对象作为参数。TopoDS_Shape是…

【vs2019】window10环境变量设置

【vs2019】window10环境变量设置 【先赞后看养成习惯】求关注点赞收藏&#x1f60a; 安装VS2019时建议默认安装地址&#xff0c;最好不要改动&#xff0c;不然容易出问题 以下是安装完VS2019后环境变量的设置情况&#xff0c;C:\Program Files (x86)\Microsoft Visual Studi…

【Unity添加远程桌面】使用Unity账号远程控制N台电脑

设置地址&#xff1a; URDP终极远程桌面&#xff1b;功能强大&#xff0c;足以让开发人员、设计师、建筑师、工程师等等随时随地完成工作或协助别人https://cloud-desktop.u3dcloud.cn/在网站登录自己的Unity 账号上去 下载安装被控端安装 保持登录 3.代码添加当前主机 "…

初探vercel托管项目

文章目录 第一步、注册与登录第二步、本地部署 在个人网站部署的助手vercel&#xff0c;支持 Github部署&#xff0c;只需简单操作&#xff0c;即可发布&#xff0c;方便快捷&#xff01; 第一步、注册与登录 进入vercel【官网】&#xff0c;在右上角 login on&#xff0c;可登…

【小迪安全2023】第23天:WEB攻防-Python考点CTF与CMS-SSTI模版注入PYC反编译

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

Linux 文件页反向映射

0. 引言 操作系统中与匿名页相对的是文件页&#xff0c;文件页的反向映射对比匿名页的反向映射更为简单。如果还不清楚匿名页反向映射逻辑的&#xff0c;请移步 匿名页反向映射 1. 文件页反向映射数据结构 struct file&#xff1a; 用户进程每open()一次文件&#xff0c;则会生…

微服务相关

1. 微服务主要七个模块 中央管理平台&#xff1a;生产者、消费者注册&#xff0c;服务发现&#xff0c;服务治理&#xff0c;调用关系生产者消费者权限管理流量管理自定义传输协议序列化反序列化 2. 中央管理平台 生产者A在中央管理平台注册后&#xff0c;中央管理平台会给他…

BLIP 算法阅读记录---一个许多多模态大语言模型的基本组件

论文地址&#xff1a;&#x1f608; 目录 一、环境配置以及数据集准备 数据集准备 数据集格式展示 环境配置&#xff0c;按照官网所述即可 二、一些调整 vit_base的预训练模型 远程debug的设置 Tokenizer初始化失败 读入网络图片的调整 三、训练过程 Image Encoder …

Kylin IPv4 setting config

Kylin IPv4 setting-CSDN博客 上次配置完重启又没了&#xff0c;永久需要修改配置文件 /etc/sysconfig/network-scripts ifcfg-ens33

langchain-chatchat指定一个或多个文件回答,不允许回答内容有其他文件内容,即屏蔽其他文件内容

1.找到langchain-chatchat中的knowledge_base_chat.py 2.knowledge_base_chat.py的api内容加上一个flie_name参数&#xff0c;即传过来你需要指定一个文件名称&#xff0c;或多个文件名称&#xff0c;同时也可以不指定&#xff0c;加上以下代码&#xff1a; flie_name: List …

腾讯云优惠券详细介绍及领券步骤详解

随着云计算技术的不断发展和普及&#xff0c;越来越多的企业和个人开始选择使用云服务来满足自身的需求。腾讯云作为国内领先的云服务提供商&#xff0c;以其稳定、高效、安全的服务赢得了广大用户的信赖。为了回馈广大用户&#xff0c;腾讯云经常推出各种优惠活动&#xff0c;…

linux下安装nacos2.2.0

1、获取下载地址并下载 1.1、打开nacos官网 1.2、找到对应版本&#xff0c;点进去 ## 1.3、复制地址 1.4下载 # 进入要安装的目录&#xff0c;cd /usr/local/src # 执行wget https://github.com/alibaba/nacos/releases/download/2.2.0/nacos-server-2.2.0.tar.gz2、 安装…

深入理解计算机网络分层结构

一、 为什么要分层&#xff1f; 计算机网络分层的主要目的是将复杂的网络通信过程分解为多个相互独立的层次&#xff0c;每个层次负责特定的功能。这样做有以下几个好处&#xff1a; 模块化设计&#xff1a;每个层次都有清晰定义的功能和接口&#xff0c;使得网络系统更易于设…

放弃powershell? 启动 sqlps!免杀| 红队攻防

0x00 前言 sql server 默认安装后&#xff0c;会发现有一个 sqlps.exe&#xff1a; 此文件本身自带微软签名&#xff1a; sqlps的功能&#xff0c;竟然是&#xff01;启动 powershell&#xff1f;&#xff1f;&#xff1f; 而且由于此文件无依赖&#xff0c;因此可以单独取出在…

刷题之Leetcode206题(超级详细)

206.反转链表 力扣题目链接(opens new window)https://leetcode.cn/problems/reverse-linked-list/ 题意&#xff1a;反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 思路 如果再定义一个新的链表&#xff0…