Linux学习第40天:Linux SPI 驱动实验(一):乾坤大挪移

news2024/11/18 3:25:44

Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 


       主从工作方式完成数据交换,形象的说就是武侠中的乾坤大挪移。

        本章实验的最终目的就是驱动 I.MX6UALPHA 开发板上的 ICM-20608 这个 SPI 接口的六轴传感器,可以在应用程序中读取 ICM-20608的原始传感器数据。

        本章的思维导图如下:

一、Linux 下SPI驱动框架简介

        重点在SPI 设备驱动编写。


1、SPI主机驱动

        Linux 内核使用 spi_master 表示 SPI 主机驱动, spi_master 是个结构体:

315 struct spi_master {
316 struct device dev;
317
318 struct list_head list;
......
326 s16 bus_num;
327
328 /* chipselects will be integral to many controllers; some others
329 * might use board-specific GPIOs.
330 */
331 u16 num_chipselect;
332
333 /* some SPI controllers pose alignment requirements on DMAable
334 * buffers; let protocol drivers know about these requirements.
335 */
336 u16 dma_alignment;
337
338 /* spi_device.mode flags understood by this controller driver */
339 u16 mode_bits;
340
341 /* bitmask of supported bits_per_word for transfers */
342 u32 bits_per_word_mask;
......
347 /* limits on transfer speed */
348 u32 min_speed_hz;
349 u32 max_speed_hz;
350
351 /* other constraints relevant to this driver */
352 u16 flags;
359 /* lock and mutex for SPI bus locking */
360 spinlock_t bus_lock_spinlock;
361 struct mutex bus_lock_mutex;
362
363 /* flag indicating that the SPI bus is locked for exclusive use */
364 bool bus_lock_flag;
......
372 int (*setup)(struct spi_device *spi);
373
......
393 int (*transfer)(struct spi_device *spi,/*transfer 函数,和 i2c_algorithm 中的 master_xfer 函数一样,控制器数据传输函
数。*/
394 struct spi_message *mesg);/*transfer_one_message 函数,也用于 SPI 数据发送,用于发送一个 spi_message,
SPI 的数据会打包成 spi_message,然后以队列方式发送出去。*/
......
434 int (*transfer_one_message)(struct spi_master *master,
435 struct spi_message *mesg);
......
462 };

        SPI 主机驱动的核心就是申请 spi_master,然后初始化 spi_master,最后向 Linux 内核注册spi_master。

1)、spi_master 申请与释放

struct spi_master *spi_alloc_master(struct device *dev,
unsigned size)

dev:设备,一般是 platform_device 中的 dev 成员变量。
size: 私有数据大小,可以通过 spi_master_get_devdata 函数获取到这些私有数据。
返回值: 申请到的 spi_master。
        spi_master 的释放通过 spi_master_put 函数来完成,当我们删除一个 SPI 主机驱动的时候就
需要释放掉前面申请的 spi_master, spi_master_put 函数原型如下:

void spi_master_put(struct spi_master *master)

master:要释放的 spi_master。
 

2)、spi_master 的注册与注销

        当 spi_master 初始化完成以后就需要将其注册到 Linux 内核, spi_master 注册函数为
spi_register_master,函数原型如下:

int spi_register_master(struct spi_master *master)

master:要注册的 spi_master。
返回值: 0,成功;负值,失败。
        I.MX6U 的 SPI 主机驱动会采用 spi_bitbang_start 这个 API 函数来完成 spi_master 的注册,spi_bitbang_start 函数内部其实也是通过调用 spi_register_master 函数来完成 spi_master 的注册。
        如果要注销 spi_master 的话可以使用 spi_unregister_master 函数,此函数原型为:

void spi_unregister_master(struct spi_master *master)

        如果使用 spi_bitbang_start 注册 spi_master 的话就要使用 spi_bitbang_stop 来注销掉
spi_master。

2、SPI设备驱动

        Linux 内核使用 spi_driver 结构体来表示 spi 设备驱动。

180 struct spi_driver {
181 const struct spi_device_id *id_table;
182 int (*probe)(struct spi_device *spi);
183 int (*remove)(struct spi_device *spi);
184 void (*shutdown)(struct spi_device *spi);
185 struct device_driver driver;
186 };

spi_driver 初始化完成以后需要向 Linux 内核注册, spi_driver 注册函数为
spi_register_driver,函数原型如下:
 

int spi_register_driver(struct spi_driver *sdrv)

        注销 SPI 设备驱动以后也需要注销掉前面注册的 spi_driver,使用 spi_unregister_driver 函
数完成 spi_driver 的注销,函数原型如下:

void spi_unregister_driver(struct spi_driver *sdrv)

spi_driver 注册示例程序如下:

1 /* probe 函数 *//*第 1~36 行, spi_driver 结构体,需要 SPI 设备驱动人员编写,包括匹配表、 probe 函数等。
和 i2c_driver、 platform_driver 一样*/
2 static int xxx_probe(struct spi_device *spi)
3 {
4 /* 具体函数内容 */
5 return 0;
6 }
7 8
/* remove 函数 */
9 static int xxx_remove(struct spi_device *spi)
10 {
11 /* 具体函数内容 */
12 return 0;
13 }
14 /* 传统匹配方式 ID 列表 */
15 static const struct spi_device_id xxx_id[] = {
16 {"xxx", 0},
17 {}
18 };
19
20 /* 设备树匹配列表 */
21 static const struct of_device_id xxx_of_match[] = {
22 { .compatible = "xxx" },
23 { /* Sentinel */ }
24 };
25
26 /* SPI 驱动结构体 */
27 static struct spi_driver xxx_driver = {
28 .probe = xxx_probe,
29 .remove = xxx_remove,
30 .driver = {
31 .owner = THIS_MODULE,
32 .name = "xxx",
33 .of_match_table = xxx_of_match,
34 },
35 .id_table = xxx_id,
36 };
37
38 /* 驱动入口函数 */
39 static int __init xxx_init(void)/*第 39~42 行,在驱动入口函数中调用 spi_register_driver 来注册 spi_driver。*/
40 
41 return spi_register_driver(&xxx_driver);
42 }
43
44 /* 驱动出口函数 */
45 static void __exit xxx_exit(void)/*第 45~48 行,在驱动出口函数中调用 spi_unregister_driver 来注销 spi_driver。*/
46 {
47 spi_unregister_driver(&xxx_driver);
48 }
49
50 module_init(xxx_init);
51 module_exit(xxx_exit);

3、SPI设备和驱动匹配

        SPI 设备和驱动的匹配过程是由 SPI 总线来完成的,SPI总线为 spi_bus_type,定义在 drivers/spi/spi.c 文件中,内容如下:

131 struct bus_type spi_bus_type = {
132 .name = "spi",
133 .dev_groups = spi_dev_groups,
134 .match = spi_match_device,
135 .uevent = spi_uevent,
136 };

        SPI 设备和驱动的匹配函数为 spi_match_device,函数内容如下:

99 static int spi_match_device(struct device *dev,
struct device_driver *drv)
100 {
101 const struct spi_device *spi = to_spi_device(dev);
102 const struct spi_driver *sdrv = to_spi_driver(drv);
103
104 /* Attempt an OF style match */
105 if (of_driver_match_device(dev, drv))/*第 105 行, of_driver_match_device 函数用于完成设备树设备和驱动匹配。比较 SPI 设备节
点的 compatible 属性和 of_device_id 中的 compatible 属性是否相等,如果相当的话就表示 SPI 设
备和驱动匹配。*/
106 return 1;
107
108 /* Then try ACPI */
109 if (acpi_driver_match_device(dev, drv))/*acpi_driver_match_device 函数用于 ACPI 形式的匹配。*/
110 return 1;
111
112 if (sdrv->id_table)
113 return !!spi_match_id(sdrv->id_table, spi);/*spi_match_id 函数用于传统的、无设备树的 SPI 设备和驱动匹配过程。比较 SPI
设备名字和 spi_device_id 的 name 字段是否相等,相等的话就说明 SPI 设备和驱动匹配。*/
114
115 return strcmp(spi->modalias, drv->name) == 0;/*比较 spi_device 中 modalias 成员变量和 device_driver 中的 name 成员变量是否
相等*/
116 }

        以下内容将在下一节学习:

二、I.MX6U SPI主机驱动分析

三、SPI设备驱动编写流程

1、SPI设备信息描述

2、SPI设备数据收发处理流程

四、硬件原理图分析

五、实验程序编写

1、修改设备树

2、编写ICM20608驱动

3、编写测试APP

六、运行测试

1、编译驱动程序和测试APP

1)、编译驱动程序

2)、编译测试APP

2、运行测试

七、总结


本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。

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

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

相关文章

二十五、城市建成区结果制图——复杂图的制作

一、前言 有些时候看到一些参考文献中有些很复杂的图,例如多幅合并在一起,其实这种图本质上就是单一的图合并在一起,然后将其导出即可。 二、具体操作 其实对于制图必备要素的添加就不过多介绍,主要介绍有什么办法保持图形之间一致性,例如,其图例、指北针、比例尺统一…

着实不错的自适应大邻域搜索算法ALNS

文章目录 引言演进路线邻域搜索,NS变邻域搜素,VDNS大邻域搜索,LNS自适应大邻域搜索,ALNS 代码实现34个国内城市的TSP测试集XQF131 相关阅读 引言 之前介绍的差分进化算法和蚁群算法分别适用于求解连续优化问题和组合优化问题&…

Git基本概念和使用方式

Git 是一种版本控制系统,用于管理文件版本的变化。以下是其基本概念和使用方式: 仓库(repository):Git 存储代码的地方,可以理解为一个项目的文件夹。提交(commit):Git …

【OpenCV实现图像:用OpenCV图像处理技巧之白平衡算法2】

文章目录 概要Gray-world AlgotithmGround Truth Algorithm结论: 概要 随着数字图像处理技术的不断发展,白平衡算法成为了图像处理中一个关键的环节。白平衡的目标是校正图像中的颜色偏差,使得白色在图像中呈现真实的白色,从而提…

Linux之基础开发工具gdb调试器的使用(三)

文章目录 一、Linux调试器-gdb使用1、安装gdb2、背景3、Debug和release4、区分Debug和release 二、Linux调试器-gdb命令演示1、显示指定行之后的代码(自动记录最后一条指令)2、断点1、打印断点2、查看断点3、删除断点4、使能(禁用/开启&#…

统计分钟级别的视频在线用户数+列炸裂+repeat函数

统计分钟级别的视频在线用户数 1、原始数据如下: uid vid starttime endtime select aa as uid,v00l as vid,2023-10-25 12:00 as starttime,2023-10-2512:15 as endtime union select bb as uid,v002 as vid,2023-10-25 12:05 as starttime,2023-10-25 12:19 …

笔记:AI量化策略开发流程-基于BigQuant平台(二)

五、模型训练股票预测 完成了数据处理,接下来就可利用平台集成的各算法进行模型训练和模型预测啦。本文将详细介绍“模型训练”、“模型预测”两大模块操作、原理。 模型训练和模型预测是AI策略区别于传统量化策略的核心,我们通过模型训练模块利用训练…

为什么Android 手机这么慢?如何提高 Android 手机的运行速度

速印机(理想、荣大等)、复印机(夏普、东芝、理光、佳能、震旦等全系列)、打印机、扫描仪、传真机、多媒体教学一体机、交互式电子白板、报警器材、监控、竞业达监考设备及其它监考设备、听力考试设备、特种安防设备维护及维修。吴…

Linux必备:这十个流程图让你变的更强!

图是我们与信息联系并处理其重要性的绝佳方法;它们有助于传达关系和抽取信息,并使我们能够可视化概念。 从基本工作流程图到复杂的网络图,组织图,BPMN(业务过程模型和符号),UML图等等&#xff0…

面试10000次依然会问的【ThreadLocal】,你还不会?

ThreadLocal简介与基本概念 ThreadLocal,即线程局部变量,是Java语言中用于实现线程数据隔离的一个重要类。这种机制允许在多线程环境中,每个线程都有自己的变量副本,从而使得每个线程都可以独立地改变自己的副本,而不…

JDK1.8 新特性(一)【默认方法、静态方法和Lambda表达式】

前言 今天学习Java8 新特性,主要是之前在学习 Scala、JavaFX 中遇到一些 Lambda 表达式,感觉 lambda 表达式确实很简洁,很有必要学一学。 目录 前言 1、接口的默认方法与静态方法 编写接口 编写接口的实现类 测试 2、Lambda表达式&am…

YOLO目标检测——交通标志分类数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用:交通标志识别数据集在自动驾驶、交通安全监控、智能交通系统、驾驶员辅助系统和城市规划等领域都有广泛应用的潜力数据集说明:交通标志分类数据集,真实场景的高质量图片数据,数据场景丰富,含多场景白天黑…

Linux之gdb

gdb就是一个Linux的调试工具,类似与vs里面的调试 可执行程序也有格式,不是简单的二进制堆砌

PyCharm因安装了illuminated Cloud插件导致加载项目失败

打开Pycharm时会有弹窗提示: The license for Illuminated Cloud is invalid or has expired. All Illuminated Cloud features will be disabled. 这个弹窗会导致你加载项目一直失败,close project 也关不掉,我都是用任务管理器杀死进程的…

DevChat全能型AI编程助手,助你“以一敌三卷翻好友”

DevChat全能型AI编程助手,助你“以一敌三卷翻好友” 什么是DevChat,它能帮助我们做什么? DevChat是OpenAI的一个产品,它是一个可以进行编程相关对话的AI。这意味着你可以使用它来解决一些编程上的问题或者获取关于编程的建议。 …

Doris:读取Doris数据的N种方法

目录 1.MySQL Client 2.JDBC 3. 查询计划 4.Spark Doris Connector 5.Flink Doris Connector 1.MySQL Client Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL,用户可以通过各类客户端工具来访问 Doris。登录到doris服务器后&a…

基于SSM框架的高校试题管理系统

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

交换机工作原理

交换机工作原理 交换机功能:端口扩展(默认同一网络),如果只是两台设备进行通信,可以直接连接这两台设备而不用交换机,但如果设备较多,设备没有那么多接口,那么这个时候就需要交换机…

智慧水利整体解决方案:PPT全文43页,附下载

关键词:智慧水利发展前景,智慧水利解决方案,智慧水利建设方案,智慧水利平台系统 一、智慧水利建设背景 传统水利系统存在一些问题: 现有基础感知不能满足更高标准的水利管理需求;决策调度支撑能力亟需加强…

ztree结合hmap使用经验分享

项目背景 在建德封控拦截系统(Vue3antd2.x)为追求更快的地图初始化体验,在尝试了hmap2.5.0版本以及2.6.3版本后,由于这两个版本在现场电脑的初始化速度不够流畅,最终使用的是hmap2.1.3版本。同时由于布控选设备&#…