SPI驱动(二) -- SPI驱动程序模型
文章目录
- 参考资料:
- 一、SPI驱动重要数据结构
- 1.1 SPI控制器数据结构
- 1.2 SPI设备数据结构
- 1.3 SPI驱动数据结构
- 二、SPI 驱动框架
- 2.1 SPI控制器驱动程序
- 2.2 SPI设备驱动程序
- 三、总结
参考资料:
- 内核头文件:
include\linux\spi\spi.h
一、SPI驱动重要数据结构
如下图,SPI 子系统中包含有 SPI控制器和SPI设备两类硬件。内核对此抽象出了三个数据结构:
spi_master:用来表示一个SPI控制器;spi_device:用来表示一个SPI设备;spi_driver:与SPI设备对应的SPI驱动。

1.1 SPI控制器数据结构
spi_master结构中最重要的成员是transfer函数指针,由它实现SPI控制器的数据传输功能。
struct spi_master {struct device dev;struct list_head list;u32 slave;s16 bus_num; //第几条总线u16 num_chipselect; //支持的片选引脚个数u16 dma_alignment;u16 mode_bits; //SPI控制器支持的工作模式u32 bits_per_word_mask; //一次传输几位
#define SPI_BPW_MASK(bits) BIT((bits) - 1)
#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0U : (BIT(bits) - 1))
#define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1))/* 最大/最小传输速率 */u32 min_speed_hz;u32 max_speed_hz;/* other constraints relevant to this driver */u16 flags;
#define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */
#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */
#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
#define SPI_MASTER_MUST_RX BIT(3) /* requires rx */
#define SPI_MASTER_MUST_TX BIT(4) /* requires tx *//* lock and mutex for SPI bus locking */spinlock_t bus_lock_spinlock;struct mutex bus_lock_mutex;/* flag indicating that the SPI bus is locked for exclusive use */bool bus_lock_flag;/*设置spi总线工作模式,频率等*/int (*setup)(struct spi_device *spi);/*spi 传输方法*/int (*transfer)(struct spi_device *spi,struct spi_message *mesg);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;struct task_struct *kworker_task;struct kthread_work pump_messages;spinlock_t queue_lock;struct list_head queue;struct spi_message *cur_msg; bool idling; //空闲bool busy; //忙bool running; //运行中bool rt;bool auto_runtime_pm;bool cur_msg_prepared;bool cur_msg_mapped;struct completion xfer_completion;size_t max_dma_len;int (*prepare_transfer_hardware)(struct spi_master *master);int (*transfer_one_message)(struct spi_master *master,struct spi_message *mesg);int (*unprepare_transfer_hardware)(struct spi_master *master);int (*prepare_message)(struct spi_master *master,struct spi_message *message);int (*unprepare_message)(struct spi_master *master,struct spi_message *message);void (*set_cs)(struct spi_device *spi, bool enable);int (*transfer_one)(struct spi_master *master, struct spi_device *spi,struct spi_transfer *transfer);void (*handle_err)(struct spi_master *master,struct spi_message *message);/* gpio chip select */int *cs_gpios;/* statistics */struct spi_statistics statistics;/* DMA channels for use with core dmaengine helpers */struct dma_chan *dma_tx;struct dma_chan *dma_rx;/* dummy data for full duplex devices */void *dummy_rx;void *dummy_tx;
};
1.2 SPI设备数据结构
spi_device结构体里面记录有设备的片选引脚、频率、挂在哪个SPI控制器下面等信息。
struct spi_device {struct device dev;struct spi_master *master; //设备挂在的对应控制器u32 max_speed_hz; //该设备能支持的SPI时钟最大值u8 chip_select; //是这个spi_master下的第几个设备u8 bits_per_word; //每次传输的位数,bits_per_word是可以大于32的,也就是每次SPI传输可能会发送多于32位的数据,这适用于DMA突发传输u16 mode; //工作模式
#define SPI_CPHA 0x01 /* 在第1个周期采样,在第2个周期采样? */
#define SPI_CPOL 0x02 /* 平时时钟极性 */
#define SPI_MODE_0 (0|0) /* (original MicroWire) */
#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* 一般来说片选引脚时低电平有效,SPI_CS_HIGH表示高电平有效 */
#define SPI_LSB_FIRST 0x08 /* 一般来说先传输MSB(最高位),SPI_LSB_FIRST表示先传LSB(最低位),很多SPI控制器并不支持SPI_LSB_FIRST */
#define SPI_3WIRE 0x10 /* SO、SI共用一条线 */
#define SPI_LOOP 0x20 /* 回环模式,就是SO、SI连接在一起 */
#define SPI_NO_CS 0x40 /* 只有一个SPI设备,没有片选信号,也不需要片选信号 */
#define SPI_READY 0x80 /* SPI从设备可以拉低信号,表示暂停、表示未就绪 */
#define SPI_TX_DUAL 0x100 /* 发送数据时有2条信号线 */
#define SPI_TX_QUAD 0x200 /* 发送数据时有4条信号线 */
#define SPI_RX_DUAL 0x400 /* 接收数据时有2条信号线 */
#define SPI_RX_QUAD 0x800 /* 接收数据时有4条信号线 */
#define SPI_SLAVE_MODE 0x1000 /* enabled spi slave mode */int irq;void *controller_state;void *controller_data;char modalias[SPI_NAME_SIZE];int cs_gpio; //这是可选项,也可以把spi_device的片选引脚记录在这里/* the statistics */struct spi_statistics statistics;
};
1.3 SPI驱动数据结构
spi_driver 结构体是”SPI总线设备驱动模型”中的一部分。
struct spi_driver {const struct spi_device_id *id_table;int (*probe)(struct spi_device *spi);int (*remove)(struct spi_device *spi);void (*shutdown)(struct spi_device *spi);struct device_driver driver;
};
二、SPI 驱动框架
SPI 子系统中包含有 SPI控制器和SPI设备两类硬件。对应就有SPI控制器驱动和SPI设备驱动,SPI控制器驱动提供SPI的传输能力。SPI设备驱动提供对SPI设备的访问能力,它知道怎么访问这个设备,知道这个设备的数据含义是什么, 它会调用SPI控制器的函数来收发数据。
2.1 SPI控制器驱动程序
SPI控制器的驱动程序可以基于"平台总线设备驱动"模型来实现:
- 在设备树里描述SPI控制器的硬件信息,在设备树子节点里描述挂在下面的SPI设备的信息
- 在
platform_driver中提供一个probe函数- 它会注册一个
spi_master - 还会解析设备树子节点,创建
spi_device结构体
- 它会注册一个
2.2 SPI设备驱动程序
跟"平台总线设备驱动模型"类似,Linux中也有一个"SPI总线设备驱动模型":
- 左边是
spi_driver,使用C文件实现,里面有id_table表示能支持哪些SPI设备,有probe函数 - 右边是
spi_device,用来描述SPI设备,比如它的片选引脚、频率- 可以来自设备树:比如由SPI控制器驱动程序解析设备树后创建、注册
spi_device - 可以来自C文件:比如使用
spi_register_board_info创建、注册spi_device
- 可以来自设备树:比如由SPI控制器驱动程序解析设备树后创建、注册
SPI驱动模型:
右边”平台总线设备驱动模型”,左边“SPI总线设备驱动模型”。

三、总结
本文描述了SPI驱动程序模型。
相关文章:
SPI驱动(二) -- SPI驱动程序模型
文章目录 参考资料:一、SPI驱动重要数据结构1.1 SPI控制器数据结构1.2 SPI设备数据结构1.3 SPI驱动数据结构 二、SPI 驱动框架2.1 SPI控制器驱动程序2.2 SPI设备驱动程序 三、总结 参考资料: 内核头文件:include\linux\spi\spi.h 一、SPI驱…...
【无标题】FrmImport
文章目录 前言一、问题描述二、解决方案三、软件开发(源码)四、项目展示五、资源链接 前言 我能抽象出整个世界,但是我不能抽象你。 想让你成为私有常量,这样外部函数就无法访问你。 又想让你成为全局常量,这样在我的…...
深入浅出 Go 语言:协程(Goroutine)详解
深入浅出 Go 语言:协程(Goroutine)详解 引言 Go 语言的协程(goroutine)是其并发模型的核心特性之一。协程允许你轻松地编写并发代码,而不需要复杂的线程管理和锁机制。通过协程,你可以同时执行多个任务,并…...
vLLM代码推理Qwen2-VL多模态
由于近期代码微调以及测试都是在远程服务器上,因此LLamafactory-cli webui 以及vLLM的ui均无法使用,因此不断寻求解决方案,我提供一个解决方案,LLamafactory微调完成的模型需要合并为一个完整模型后再使用vLLM进行代码推理测试微调…...
DNS云解析有什么独特之处?
在数字化浪潮中,每一次网页点击、视频加载或在线交易背后,都依赖着域名系统(DNS)的高效运转。传统DNS架构的局限性(如单点故障、延迟高、安全脆弱)在云计算时代被彻底颠覆,DNS云解析作为新一代解…...
视频流畅播放相关因素
视频播放的流畅度是一个综合性问题,涉及从视频文件本身到硬件性能、网络环境、软件优化等多个环节。以下是影响流畅度的关键因素及优化建议: 一、视频文件本身 1. 分辨率与帧率 1.问题:高分辨率(如4K)或高帧率&#…...
Python实现一个类似MybatisPlus的简易SQL注解
文章目录 前言实现思路定义一个类然后开始手撸这个微型框架根据字符串获取到所定义的DTO类构建返回结果装饰器解析字符串,获得变量SQL字符串拼接 使用装饰器 前言 在实际开发中,根据业务拼接SQL所需要考虑的内容太多了。于是,有没有一种办法…...
linux一些使用技巧
linux一些使用技巧 文件名称和路径的提取切换用户执行当前脚本一行演示单引号与双引号的使用curl命令仅输出响应头信息,不输出body体文件名称和路径的提取 文件路径为 /tmp/tkgup/test.sh 方式获取文件名获取文件路径获取文件全路径方式一basename ${file}dirname ${file}real…...
小模型和小数据可以实现AGI吗
小模型和小数据很难实现真正的 通用人工智能(AGI, Artificial General Intelligence),但在特定任务或受限环境下,可以通过高效的算法和优化方法实现“近似 AGI” 的能力。 1. 为什么小模型小数据难以实现 AGI? AGI 需…...
io学习----->文件io
思维导图: 一.文件io的概念 文件IO:指程序和文件系统之间的数据交互 特点: 1.不存在缓冲区,访问速度慢 2.不可以移植,依赖于操作系统 3.可以访问不同的文件类型(软连接,块设备等) 4.文件IO属于系统调…...
kubernetes介绍
文章目录 kubernetes概述kubernetes组件kubernetes概念 kubernetes概述 kubernetes,是一个全新的基于容器技术的分布式架构领先方案,是Google开源的的容器编排工具。 kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定…...
如何高效准备PostgreSQL认证考试?
高效准备 PostgreSQL 中级认证考试,可从知识储备、技能提升、模拟考试等方面入手,以下是具体建议: 深入学习理论知识 系统学习核心知识:依据考试大纲,对 PostgreSQL 的体系结构、数据类型、SQL 语言、事务处理、存储过…...
如何使用Briefing打造私有视频会议系统结合内网穿透异地远程连接
文章目录 前言1.关于briefing2.本地部署briefing3.使用briefing4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定briefing公网地址 前言 在这个‘云’字当道的时代,远程办公、异地恋已经成了生活常态。视频聊天自然也就成了日常操作。但一不小心,…...
XHR请求解密:抓取动态生成数据的方法
在如今动态页面大行其道的时代,传统的静态页面爬虫已无法满足数据采集需求。尤其是在目标网站通过XHR(XMLHttpRequest)动态加载数据的情况下,如何精准解密XHR请求、捕获动态生成的数据成为关键技术难题。本文将深入剖析XHR请求解密…...
坐标变换介绍与机器人九点标定的原理
【备注】本文的C#代码在下面链接中可以下载:Opencv的C#九点标定代码资源-CSDN文库 https://download.csdn.net/download/qq_34047402/90452336 一、坐标变换的介绍 1.绕原点旋转的坐标变换 一个点(x,y)绕原点旋转u度,其旋转后的坐标(x1,y1)如何计算? 2.绕任意点的坐标变…...
串口调试助手Alien v5.198新版发布
v5.198 更改点: 1.增加USB打印机支持 2.支持特殊波特率/自定义波特率 3.支持窗口透明调整 4.支持接收框文本左/中/右对齐,粗体字,自动换行 5.支持接收时间戳 6.HEX接收自动换行 7.支持文本颜色主题 8.支持文本字体修改 9.增加菜单/增状态栏显示当前接口 下载 alien_v5.198.7z …...
解锁Android RemoteViews:跨进程UI更新的奥秘
一、RemoteViews 简介 在 Android 开发的广阔领域中,RemoteViews 是一个独特且重要的概念,它为开发者提供了一种在其他进程中显示视图结构的有效方式。从本质上讲,RemoteViews 并非传统意义上在当前应用进程内直接渲染和操作的 View…...
编译可以在Android手机上运行的ffmpeg程序
下载代码 git clone gitgithub.com:FFmpeg/FFmpeg.git git checkout n7.0建立build目录 mkdir build cd build创建build.sh脚本 vim build.sh这段脚本的主要功能是配置和编译 FFmpeg,使其能够在 Android 平台上运行,通过设置不同的架构和 API 级别&am…...
Verilog学习方法—基础入门篇(一)
前言: 在FPGA开发中,Verilog HDL(硬件描述语言)是工程师必须掌握的一项基础技能。它不仅用于描述数字电路,还广泛应用于FPGA的逻辑设计与验证。对于初学者来说,掌握Verilog的核心概念和基本语法࿰…...
本地jar包添加到 maven
进入到 你的 maven bin文件夹下 执行cmd ,然后执行命令 mvn install:install-file -Dfilepath/to/your/artifact.jar -DgroupIdyour.group.id -DartifactIdyour-artifact-id -Dversion1.0 -Dpackagingjar 替换path/to/your/artifact.jar为你的JAR文件路径…...
基于NVIDIA Jetson Nano的无人机边缘AI系统:从架构设计到自主跟踪实战
1. 项目概述:当无人机遇上边缘AI大脑几年前,当我第一次把一块NVIDIA Jetson Nano塞进一架450轴距的无人机机架里,看着它仅凭机载摄像头就识别出前方的障碍物并自主绕开时,那种兴奋感至今记忆犹新。这不仅仅是给无人机加了个“眼睛…...
3分钟搞定B站视频下载:免费解锁4K大会员高清视频的完整教程
3分钟搞定B站视频下载:免费解锁4K大会员高清视频的完整教程 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 你是否曾为无法…...
实战复盘:我们如何定位并彻底解决Spring Gateway的‘262144字节’缓冲区限制问题
深度解析:Spring Gateway缓冲区限制问题的工程化解决方案 1. 问题背景与现象分析 去年夏天,我们的电商平台在促销活动期间突然遭遇了一系列诡异的API请求失败。前端团队报告称,部分包含大型商品列表的JSON请求在通过Spring Cloud Gateway时被…...
华为擎云L420变身MCU开发主力机:VSCode + Cortex-Debug + 自编译工具链玩转雅特力AT32
华为擎云L420打造高效MCU开发环境:VSCodeCortex-Debug全流程实战 在嵌入式开发领域,效率工具的选择往往能决定项目的成败。当国产化浪潮席卷技术圈,越来越多的开发者开始尝试在纯国产硬件上构建完整的工作流。华为擎云L420作为一款基于ARM架构…...
在 Elasticsearch 中使用带有确定性护栏的 Agentic AI 搜索,以实现安全的查询执行
作者:来自 Elastic Alexander Marquardt, Honza Krl 及 Taylor Roy 当 LLM 直接生成查询时, Agentic AI 搜索系统通常会失败。了解确定性护栏和控制平面架构如何通过 Elasticsearch 实现安全、可靠且受治理的查询执行。 刚接触 Elasticsearch࿱…...
Hi3516DV300鸿蒙时钟应用开发:从环境搭建到驱动调试全流程
1. 项目概述:从零到一,在Hi3516DV300上跑通一个鸿蒙时钟最近在捣鼓OpenHarmony,手头正好有一块海思的Hi3516DV300开发板。这块板子性能不错,带屏显,很适合做点有意思的应用。我琢磨着,与其跑个现成的Demo&a…...
AI行业的“隐形赛道”:AI伦理与合规人才缺口到底有多大
一、AI狂飙下的“隐形刚需”:被忽视的伦理与合规赛道当软件测试从业者还在为功能测试、性能测试的技术迭代焦头烂额时,AI行业的另一股暗流正汹涌袭来——伦理与合规人才的缺口,正成为制约AI产业可持续发展的隐形瓶颈。从ChatGPT引发生成式AI热…...
轻松管理AD域:一款基于.NET的Web工具推荐
轻松管理AD域:一款基于.NET的Web工具推荐 【下载地址】AD域管理Web版工具 本资源提供了一个基于微软官方文档,使用.NET技术开发的Web AD域管理工具。该工具采用简单的HTML和一般处理程序(Generic Handler)来实现,旨在为…...
通过curl命令在无SDK环境中测试Taotoken接口连通性
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过curl命令在无SDK环境中测试Taotoken接口连通性 在服务器管理、持续集成流水线或轻量级容器环境中,你可能需要在没有…...
共享内存概述
共享内存,就是在内存里开辟一块公共空间,多个进程可以同时映射到自己的虚拟地址空间,大家直接读写同一块物理内存。是 Linux 进程间通信 IPC 最快 的一种方式。1️⃣创建共享内存空间2️⃣映射到自己的进程3️⃣strcpy写数据4️⃣断开与共享内…...
