Linux学习第29天:设备树下的 platform 驱动编写:举步维艰,那就脚踏实地,一步一个脚印,慢慢来。

news2025/7/18 21:50:19

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


       同志们,学习到现在,是不是有点懵逼的感觉。感觉该学的都学了,又感觉啥都没学会。就这样懵逼的状态进入到下一节的学习。这就是题目中我讲的举步维艰的状态了吧。起码这是我学习到现在的一个状态吧。但是既然下决心要攻克它,就不要轻言放弃。因为黎明往往就在黑夜的后面。这也是学习一种技能必须要经历的一个过程。脚底实地,按照计划,一节一节来,争取尽可能多的吸收每天学到的新的知识点。就这样一步一个脚印的走下去,不急躁,不冒进,相信终会有柳暗花明的一天。一起加油,同志们!!!

        本篇笔记主要学习设备树下platform驱动开发相关知识,主要包括相关的基础知识、硬件原理图以及驱动开发的过程。其中驱动开发的过程有设备树的修改、驱动开发及APP开发、编译及运行测试。其中驱动开发作为本节的重点内容。    

一、设备树下的platform驱动简介

        编写设备树下的platform驱动时应注意的问题:

1.在设备树中创建设备节点

        设置好compatible属性的值。

2.注意兼容属性

       关键字: of_match_table

1 static const struct of_device_id leds_of_match[] = {
2 { .compatible = "atkalpha-gpioled" }, /* 兼容属性 */
3 { /* Sentinel */ }
4 };
5
6 MODULE_DEVICE_TABLE(of, leds_of_match);
7
8 static struct platform_driver leds_platform_driver = {
9 .driver = {
10 .name = "imx6ul-led",
11 .of_match_table = leds_of_match,
12 },

        第 1~4 行,of_device_id 表,也就是驱动的兼容表,是一个数组,每个数组元素为 of_device_id类型。每个数组元素都是一个兼容属性,表示兼容的设备,一个驱动可以跟多个设备匹配。

        第 3 行是一个空元素,在编写 of_device_id 的时候最后一个元素一定要为空

        第 6 行, 通过 MODULE_DEVICE_TABLE 声明一下 leds_of_match 这个设备匹配表。

        第 11 行,设置 platform_driver 中的 of_match_table 匹配表为上面创建的 leds_of_match。

3.编写platform驱动

二、硬件原理图分析

三、试验程序编写

1.修改设备树文件

1 pinctrl_led: ledgrp {
2 fsl,pins = <
3 MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */
4 >;
5 };

2.platform驱动程序编写

114 /*
115 * @description : flatform 驱动的 probe 函数,当驱动与
116 * 设备匹配以后此函数就会执行
117 * @param - dev : platform 设备
118 * @return : 0,成功;其他负值,失败
119 */
120 static int led_probe(struct platform_device *dev)
121 {
122 printk("led driver and device was matched!\r\n");
123 /* 1、设置设备号 */
124 if (leddev.major) {
125 leddev.devid = MKDEV(leddev.major, 0);
126 register_chrdev_region(leddev.devid, LEDDEV_CNT,
LEDDEV_NAME);
127 } else {
128 alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT,
LEDDEV_NAME);
129 leddev.major = MAJOR(leddev.devid);
130 }
131
132 /* 2、注册设备 */
133 cdev_init(&leddev.cdev, &led_fops);
134 cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);
135
136 /* 3、创建类 */
137 leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);
138 if (IS_ERR(leddev.class)) {
139 return PTR_ERR(leddev.class);
140 }
141
142 /* 4、创建设备 */
143 leddev.device = device_create(leddev.class, NULL, leddev.devid,
NULL, LEDDEV_NAME);
144 if (IS_ERR(leddev.device)) {
145 return PTR_ERR(leddev.device);
146 }
147
148 /* 5、初始化 IO */
149 leddev.node = of_find_node_by_path("/gpioled");
150 if (leddev.node == NULL){
151 printk("gpioled node nost find!\r\n");
152 return -EINVAL;
153 }
154
155 leddev.led0 = of_get_named_gpio(leddev.node, "led-gpio", 0);
156 if (leddev.led0 < 0) {
157 printk("can't get led-gpio\r\n");
158 return -EINVAL;
159 }
160
161 gpio_request(leddev.led0, "led0");
162 gpio_direction_output(leddev.led0, 1); /*设置为输出,默认高电平 */
163 return 0;
164 }

        platform 驱动的 probe 函数,当设备树中的设备节点与驱动之间匹配成功以后此函数就会执行,原来在驱动加载函数里面做的工作现在全部放到 probe 函数里面完成。

166 /*
167 * @description : remove 函数,移除 platform 驱动的时候此函数会执行
168 * @param - dev : platform 设备
169 * @return : 0,成功;其他负值,失败
170 */
171 static int led_remove(struct platform_device *dev)
172 {
173 gpio_set_value(leddev.led0, 1); /* 卸载驱动的时候关闭 LED */
174
175 cdev_del(&leddev.cdev); /* 删除 cdev */

        remove 函数,当卸载 platform 驱动的时候此函数就会执行。在此函数里面
释放内存、注销字符设备等,也就是将原来驱动卸载函数里面的工作全部都放到 remove 函数中
完成。

182 /* 匹配列表 */
183 static const struct of_device_id led_of_match[] = {
184 { .compatible = "atkalpha-gpioled" },
185 { /* Sentinel */ }
186 };

匹配表
 

188 /* platform 驱动结构体 */
189 static struct platform_driver led_driver = {
190 .driver = {
191 .name = "imx6ul-led", /* 驱动名字,用于和设备匹配 */
192 .of_match_table = led_of_match, /* 设备树匹配表 */
193 },
194 .probe = led_probe,
195 .remove = led_remove,
196 };

        platform_driver 驱动结构体, 191 行设置这个 platform 驱动的名字为“ imx6ulled”,因此,当驱动加载成功以后就会在/sys/bus/platform/drivers/目录下存在一个名为“ imx6uled”的文件。 第 192 行设置 of_match_table 为上面的 led_of_match。

198 /*
199 * @description : 驱动模块加载函数
200 * @param : 无
201 * @return : 无
202 */
203 static int __init leddriver_init(void)
204 {
205 return platform_driver_register(&led_driver);
206 }

        驱动模块加载函数,在此函数里面通过 platform_driver_register 向 Linux 内
核注册 led_driver 驱动。

208 /*
209 * @description : 驱动模块卸载函数
210 * @param : 无
211 * @return : 无
212 */
213 static void __exit leddriver_exit(void)
214 {
215 platform_driver_unregister(&led_driver);
216 }
217

        驱动模块卸载函数,在此函数里面通过 platform_driver_unregister 从 Linux内核卸载 led_driver 驱动。

3.编写测试APP

和上次使用同样的即可。

四、运行测试

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

obj-m := leddriver.o

输入如下命令编译出驱动模块文件:
make -j32
编译成功以后就会生成一个名为“ leddriver.o”的驱动模块文件。

测试 APP 直接使用上一章的 ledApp 这个测试软件即可。
 

2.运行测试

depmod //第一次加载驱动的时候需要运行此命令
modprobe leddriver.ko //加载驱动模块

        驱动模块加载完成以后到/sys/bus/platform/drivers/目录下查看驱动是否存在,我们在leddriver.c 中设置 led_driver (platform_driver 类型)的 name 字段为“ imx6ul-led”,因此会在
/sys/bus/platform/drivers/目录下存在名为“ imx6ul-led”这个文件,结果如图 所示:

        同理,在/sys/bus/platform/devices/目录下也存在 led 的设备文件,也就是设备树中 gpioled 这个节点,如图 所示:

驱动和模块都存在,当驱动和设备匹配成功以后就会输出如图所示一行语句:

驱动和设备匹配成功以后就可以测试 LED 灯驱动了,输入如下命令打开 LED 灯:
./ledApp /dev/dtsplatled 1 //打开 LED 灯
在输入如下命令关闭 LED 灯:
./ledApp /dev/dtsplatled 0 //关闭 LED 灯
观察一下 LED 灯能否打开和关闭,如果可以的话就说明驱动工作正常,如果要卸载驱动的
话输入如下命令即可:
rmmod leddriver.ko
 

五、总结

        本篇笔记主要学习设备树下platform驱动开发相关知识,主要包括相关的基础知识、硬件原理图以及驱动开发的过程。其中驱动开发作为本节的重点内容。


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

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

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

相关文章

Spring源码分析篇一 @Autowired 是怎样完成注入的?究竟是byType还是byName亦两者皆有

1. 五种不同场景下 Autowired 的使用 第一种情况 上下文中只有一个同类型的bean 配置类 package org.example.bean;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class FruitCo…

06、Caused by: java.nio.charset.MalformedInputException: Input length = 1

目录 问题&#xff1a;原因&#xff1a;解决方法&#xff1a; 问题&#xff1a; Caused by: java.nio.charset.MalformedInputException: Input length 1 原因&#xff1a; 应该是中文有哪些文字导致的。 yml 编码格式出错 解决方法&#xff1a; 直接这里把GBK改成 utf-8…

做抖音短视频会经历哪些阶段?

今天来聊聊那些在抖音做大的老板&#xff0c;从开始到后期经历的四个阶段&#xff0c;以及每个阶段的工作重心 1、0—1的阶段 0—1的起步阶段是整个阶段最有难度的一环&#xff0c;很多人对0到1的认知是有错误的&#xff0c;以为爆过几条视频就已经进阶了 想要实现0-1的突破…

使用 Docker 部署高可用 MongoDB 分片集群

使用 Docker 部署 MongoDB 集群 Mongodb 集群搭建 mongodb 集群搭建的方式有三种&#xff1a; 主从备份&#xff08;Master - Slave&#xff09;模式&#xff0c;或者叫主从复制模式。副本集&#xff08;Replica Set&#xff09;模式。分片&#xff08;Sharding&#xff09;…

装备制造行业云MES解决方案

一、装备制造行业发展现状&#xff1a; 机械制造业主要是通过对金属原材料物理形状的改变、加工组装进而成为产品。机械制造业生产的主要特点是&#xff1a;离散为主、流程为辅、装配为重点。 工业生产基本上分为两大方式&#xff1a; 1.离散型&#xff1a;离散型是指以一个…

智能问答进阶之路:RAG(大模型检索增强生成)框架详解与实战,融合检索与生成助力智能系统更上层楼

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

市场洗牌,全新一代MiniLED背光技术大放异彩

MiniLED背光是一种采用微小尺寸LED灯珠作为背光源的技术。相比传统的LED背光&#xff0c;MiniLED采用更小的LED尺寸&#xff08;通常在100微米至200微米之间&#xff09;&#xff0c;使得显示屏幕的亮度和对比度得以大幅提升。MiniLED背光技术作为显示行业的新宠儿&#xff0c;…

外汇天眼:3大假投资诈骗手法公开,助你识破假券商及黑平台!

去年以来物价持续上涨&#xff0c;不少人的薪水涨幅却不如预期&#xff0c;导致资产实质缩水。 面对生活成本不断增加&#xff0c;愈来愈多人意识到投资的重要性&#xff0c;并且开始寻找各种获利的渠道与机会。 与此同时&#xff0c;诈骗集团也利用人们想赚钱的心理&#xff0…

家用小型洗衣机哪款性价比高?好用不贵内衣洗衣机测评

很多人在休息的时候&#xff0c;都会抽出一些时间来清洗自己的衣物&#xff0c;但是他们忽略了一个问题&#xff0c;内裤不能和平时穿的外套一起用洗衣机清洗&#xff0c;主要原因是一般的洗衣机不能把内衣清洗干净&#xff0c;而且如果和平时穿的外套一起洗的话&#xff0c;内…

【嵌入式项目应用】__用于搭建调试输出、建立时间系统的嵌入式框架“Zorb Framework”

目录 一、什么是Zorb&#xff1f; 二、嵌入式环境搭建 三、调试输出 四、实现断言 五、建立时间系统 六、结束语 (*&#xffe3;︶&#xffe3;)创作不易&#xff01;期待你们的 点赞、收藏和评论喔。 一、什么是Zorb&#xff1f; Zorb Framework是一个基于面向对象的思…

visinextek的sdk编译

编译sdk 1、修改编译链路径 cd customer-rel/board/package/mk/ vi common.mksudo echo ‘PATH“/home/johan/share/vs839/vs-linux/x86-arm/gcc-linaro-7.5.0-aarch64-linux-gnu/bin:$PATH”’ >> /etc/profile source /etc/profile 2、bypass DSP 编译&#xff0c;…

Leetcode循环队列

这道题十分考验我们对队列的理解。 文章目录 队列的介绍队列的实现进入正题 队列的介绍 队列是一种只允许在一段进行插入&#xff0c;在另一端进行删除的数据操作的特殊线性结构&#xff0c;&#xff0c;因此决定了他具有先入先出的特点&#xff0c;其中进行插入操作的一段叫做…

MFC打开控制台的常用方式

工程项目中&#xff0c;想打开控制台的&#xff0c;简单打印日志 &#xff08;1&#xff09;依次打开&#xff1a; 项目配置属性——>生成事件——>后期生成事件&#xff1a;命令行 &#xff08;2&#xff09;输入&#xff1a; editbin /SUBSYSTEM:CONSOLE $(OUTDIR)\$…

pppoe拨号案例

R3服务端 interface LoopBack0 ip address 1.1.1.1 255.255.255.255 aaa local-user test password cipher admin local-user test service-type ppp ip pool test network 100.0.0.0 mask 255.255.255.0 interface Virtual-Template0 ppp authentication-mode chap remote …

【设计模式】第23节:行为型模式之“策略模式”

一、简介 策略模式&#xff1a;定义一族算法类&#xff0c;将每个算法分别封装起来&#xff0c;让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端&#xff08;这里的客户端代指使用算法的代码&#xff09;。 二、适用场景 动态选择算法多种类似的行为 …

CondConv 动态卷积学习笔记 (附代码)

论文地址:https://arxiv.org/abs/1904.04971 代码地址&#xff1a;https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet/condconv 1.是什么&#xff1f; CondConv是一种条件参数卷积&#xff0c;也称为动态卷积&#xff0c;它是一种即插即用的模块&…

数据结构之集合框架

1.Java集合框架的定义 Java 集合框架 Java Collection Framework &#xff0c;又被称为容器 container &#xff0c;是定义在 java.util 包下的一组接口 interfaces和其实现类 classes 。 其主要表现为将多个元素 element 置于一个单元中&#xff0c;用于对这些元素进行…

向上管理中的沟通技巧

一. 背景 我们要弄清楚两个问题为什么要向上管理呢&#xff0c;向上管理主要是要做什么呢&#xff1f; 首先&#xff0c;第一个问题为什么要向上管理&#xff1f;向上管理的本质是为了同时给公司、上司和自己带来最好的结果&#xff0c;并有意识地配合和改变工作方法&#xf…

iPhone连不上Wi-Fi?看完这篇文章你就知道了!

大家在使用苹果手机的过程中有没有遇到过这样的情况&#xff1a;手机突然连接不上Wi-Fi&#xff0c;或者连接了也根本使用不了。遇到上述情况请不要着急&#xff0c;iphone连不上wifi是由很多种原因导致的。那么&#xff0c;iPhone连接不上Wi-Fi时该怎么办呢&#xff1f; 我们…

测试可用的安防视频分析软件:烟火检测、车型检测、玩手机打电话检测、厨帽检测、抽烟检测、人员入侵检测

下载地址&#xff1a;https://pan.baidu.com/s/1R1MvD_KQ3uB-0KL_N3is-w?pwdwa33 随着AI、大数据、云计算和边缘计算等技术的迅猛发展&#xff0c;我国的视频监控市场正处于全新的阶段。借助AI深度学习技术的进步&#xff0c;现代化的安防视频监控系统通过边缘计算设备上的AI识…