Linux学习第30天:Linux 自带的 LED 灯驱动实验:驱动开发思维方式的转变势在必行

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


         学习嵌入式Linux驱动开发整整30天了。今天简单做一个小结。因为之前的主要工作是做ARM的裸机开发,所以接触Linux以后感觉很多东西都变了。不仅仅包括相关知识点的归纳,更重要的是思维方式的转变。做裸机开发的时候,在很多时候是要弄清楚最底层的逻辑才能进行代码的开发。而Linux则更像是站在一个更高的维度去思考,很细枝末叶的东西是不需要考虑的。相对裸机开发的维度来说,裸机开发后做Linux驱动开发更有点降维打击的感觉。但并不是说Linux驱动开发简单,而是说裸机开发对底层的要求可能会更高一些。以上仅仅是个人的一点自我感受。

        本节笔记主要学习Linux自带的LED驱动试验。主要内容包括驱动使能、简介、设备树节点编写及运行测试。其中驱动简介又包括LED灯驱动框架分析、module_platform_driver函数简介和gpio_led_probe函数简析。

一、Linux内核自带的LED灯驱动使能

        需要配置Linux内核,使能自带的LED驱动。使用make menuconfig打开Linux配置菜单。

        按照如下路径打开LED驱动配置项:

        Device Drivers

                LED Support(NEW_LEDS=[y])

                        LED Support for GPIO connected LEDs. 在此选项上按下“ Y”键,使此选项前面变为“ <*>”,

        重新编译 Linux 内核,然后使用新编译出来的 zImage 镜像启动开发板。

二、Linux内核自带LED驱动简介

1、LED灯驱动框架分析

obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o

236 static const struct of_device_id of_gpio_leds_match[] = {
237 { .compatible = "gpio-leds", },
238 {},
239 };

        LED 驱动的匹配表,此表只有一个匹配项, compatible 内容为“ gpio-leds”,因此设备树中的 LED 灯设备节点的 compatible 属性值也要为“ gpio-leds”,否则设备和驱动匹配不成功,驱动就没法工作。

static struct platform_driver gpio_led_driver = {
291 .probe = gpio_led_probe,
292 .remove = gpio_led_remove,
293 .driver = {
294 .name = "leds-gpio",
295 .of_match_table = of_gpio_leds_match,
296 },

        platform_driver 驱动结构体变量,可以看出, Linux 内核自带的 LED 驱动采用了 platform 框架。

module_platform_driver(gpio_led_driver);

        通过 module_platform_driver 函数向 Linux 内核注册 gpio_led_driver 这个 platform
驱动。

2、module_platform_driver函数简介

        module_platform_driver 定义在 include/linux/platform_device.h 文件中为一个,

        module_platform_driver 依赖 module_driver, module_driver 也是一个宏。

        module_platform_driver 函数的功能就是完成 platform 驱动的注册和删除

3、gpio_led_probe函数简析

269 priv = gpio_leds_create(pdev);
270 if (IS_ERR(priv))
271 return PTR_ERR(priv);

        如果使用设备树的话,使用 gpio_leds_create 函数从设备树中提取设备信息,获取到的 LED 灯 GPIO 信息保存在返回值中。

        在gpio_leds_create 函数中,调用 device_get_child_node_count 函数统计子节点数量,一般在在设备树中创建一个节点表示 LED 灯,然后在这个节点下面为每个 LED 灯创建一个子节点。因此子节点数量也是 LED 灯的数量。
 

device_for_each_child_node(dev, child) {

        遍历每个子节点,获取每个子节点的信息。

led.gpiod = devm_get_gpiod_from_child(dev, NULL, child);

        获取 LED 灯所使用的 GPIO 信息。

196 if (fwnode_property_present(child, "label")) {
197 fwnode_property_read_string(child, "label", &led.name);

        读取子节点 label 属性值,因为使用 label 属性作为 LED 的名字。

204 fwnode_property_read_string(child, "linux,default-trigger",
205 &led.default_trigger);

        获取“ linux,default-trigger”属性值,可以通过此属性设置某个 LED 灯在Linux 系统中的默认功能,比如作为系统心跳指示灯等等。

207 if (!fwnode_property_read_string(child, "default-state",
208 &state)) {
209 if (!strcmp(state, "keep"))
210 led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
211 else if (!strcmp(state, "on"))
212 led.default_state = LEDS_GPIO_DEFSTATE_ON;
213 else
214 led.default_state = LEDS_GPIO_DEFSTATE_OFF;
215 }

        获取“ default-state”属性值,也就是 LED 灯的默认状态属性。

220 ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
221 dev, NULL);

        调用 create_gpio_led 函数创建 LED 相关的 io,其实就是设置 LED 所使用的 io为输出之类的。 create_gpio_led 函数主要是初始化 led_dat 这个 gpio_led_data 结构体类型变量,led_dat 保存了 LED 的操作函数等内容。

        gpio_led_probe 函数主要功能就是获取 LED 灯的设备信息,然后根据这些信息来初始化对应的 IO,设置为输出等。     

三、设备树节点编写

        在编写设备节点的时候要注意以下几点:
①、创建一个节点表示 LED 灯设备,比如 dtsleds,如果板子上有多个 LED 灯的话每个 LED
灯都作为 dtsleds 的子节点。
②、 dtsleds 节点的 compatible 属性值一定要为“ gpio-leds”。
③、设置 label 属性,此属性为可选,每个子节点都有一个 label 属性, label 属性一般表示
LED 灯的名字,比如以颜色区分的话就是 red、 green 等等。
④、每个子节点必须要设置 gpios 属性值,表示此 LED 所使用的 GPIO 引脚!
⑤、可以设置“ linux,default-trigger”属性值,也就是设置 LED 灯的默认功能,比如:
backlight: LED 灯作为背光。
default-on: LED 灯打开
heartbeat: LED 灯作为心跳指示灯,可以作为系统运行提示灯。
ide-disk: LED 灯作为硬盘活动指示灯。
timer: LED 灯周期性闪烁,由定时器驱动,闪烁频率可以修改
⑥、可以设置“ default-state”属性值,可以设置为 on、 off 或 keep,为 on 的时候 LED 灯默
认打开,为 off 的话 LED 灯默认关闭,为 keep 的话 LED 灯保持当前模式。

1 dtsleds {
2 compatible = "gpio-leds";
3 4
led0 {
5 label = "red";
6 gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
7 default-state = "off";
8 };
9 };

四、运行测试

        启 动 开 发 板 , 启 动 以 后 查 看/sys/bus/platform/devices/dtsleds 这个目录是否存在。

进入到 leds 目录中,此目录中的内容如图所示:

        在 leds 目录下有一个名为“ red”子目录,这个子目录的名字就是我们在设备树中第 5 行设置的 label 属性值。

        输入如下命令打开 RED 这个 LED 灯:
echo 1 > /sys/class/leds/red/brightness //打开 LED0
        关闭 RED 这个 LED 灯的命令如下:
echo 0 > /sys/class/leds/red/brightness //关闭 LED0

        系统运行指示灯:

1 dtsleds {
2 compatible = "gpio-leds";
3 4
led0 {
5 label = "red";
6 gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
7 linux,default-trigger = "heartbeat";
8 default-state = "on";
9 };
10 };

        设置 LED0 作为系统指示灯,在 dtsleds 这个设备节点中加入“ linux,default-trigger”属性信息即可,属性值为“ heartbeat”。

五、总结

        本节笔记主要内容包括驱动使能、简介、设备树节点编写及运行测试。其中驱动简介又包括LED灯驱动框架分析、module_platform_driver函数简介和gpio_led_probe函数简析。


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何选择安全又可靠的文件数据同步软件?

数据实时同步价值体现在它能够确保数据在多个设备或系统之间实时更新和保持一致。这种技术可以应用于许多领域&#xff0c;如电子商务、社交媒体、金融服务等。在这些领域中&#xff0c;数据实时同步可以带来很多好处&#xff0c;如提高工作效率、减少数据不一致、提高用户体验…

【Verilog 教程】7.3 Verilog 串行 FIR 滤波器设计

串行 FIR 滤波器设计 设计说明 设计参数不变&#xff0c;与并行 FIR 滤波器参数一致。即&#xff0c;输入频率为 7.5 MHz 和 250 KHz 的正弦波混合信号&#xff0c;经过 FIR 滤波器后&#xff0c;高频信号 7.5MHz 被滤除&#xff0c;只保留 250KMHz 的信号。 输入频率&#x…

uniapp 省市区三级联动选择器

还有半个小时下班&#xff0c;总想着发点光亮照耀他人。IT技术这东西&#xff0c;尤其是UI方面的东西&#xff0c;于用户体验至关重要&#xff0c;想想最近使用uni-data-picker的丑陋页面&#xff0c;自己重构了这个功能&#xff0c;新加实现&#xff0c;效果图如下&#xff0c…

使用 Curl 和 DomCrawler 下载抖音视频链接并存储到指定文件夹

项目需求 假设我们需要从抖音平台上下载一些特定的视频&#xff0c;以便进行分析、编辑或其他用途。为了实现这个目标&#xff0c;我们需要编写一个爬虫程序来获取抖音视频的链接&#xff0c;并将其保存到本地文件夹中。 目标分析 在开始编写爬虫之前&#xff0c;我们需要了…

【Linux】配置JDKTomcat开发环境及MySQL安装和后端项目部署

目录 一、jdk安装配置 1. 传入资源 2. 解压 3. 配置 二、Tomcat安装 1. 解压开启 2. 开放端口 三、MySQL安装 1. 解压安装 2. 登入配置 四、后端部署 1. 数据库 2. 导入.war包 3. 修改端口 4.开启访问 一、jdk安装配置 打开虚拟机 Centos 登入账号&#xff…

MySQL -- 内置函数

MySQL – 内置函数 文章目录 MySQL -- 内置函数一、日期函数1.current_date()获取年月日2.current_time()获取时分秒3.current_timestamp() / now()获得时间戳4.date_add()在日期的基础上加日期5.date_sub()在日期的基础上减去日期6. datediff()计算两个日期之间相差多少天7.案…

inquirer.js——交互式命令行用户界面

一、什么是inquirer.js 1、inquirer.js是一个开源的交互式命令行用户界面&#xff08;CLI&#xff09;库&#xff0c;可以让你轻松地与用户进行交互&#xff0c;获取用户输入并做出相应的处理。它的主要功能是提供了一系列常用的命令行交互界面组件&#xff0c;例如input、con…

【Redis】高并发分布式结构服务器

文章目录 服务端高并发分布式结构名词基本概念评价指标1.单机架构缺点 2.应用数据分离架构应用服务集群架构读写分离/主从分离架构引入缓存-冷热分离架构分库分表&#xff08;垂直分库&#xff09;业务拆分⸺微服务 总结 服务端高并发分布式结构 名词基本概念 应⽤&#xff0…

Docker的安装、基础命令与项目部署

文章目录 前言一、docker安装与MySQL部署1.Linux环境下docker的安装&#xff08;1&#xff09;基于CentOS7&#xff08;2&#xff09;基于Ubuntu 二、docker基础1.常见命令&#xff08;1&#xff09;快速创建一个mysql容器&#xff08;MySQL得一键安装&#xff09;。&#xff0…

centos7 部署 Flink

1. 准备 安装的前提是虚拟机里已安装了jdk 去官网下载 Flink 所有版本下载地址&#xff1a;https://archive.apache.org/dist/flink/ 找到下图的安装包&#xff0c;下载即可 下载完后&#xff0c;将其上传至虚拟机的某个地方&#xff0c;本人将其放在 /home/flink/ 下 解压…

Learning to Segment Rigid Motions from Two Frames 代码复现

环境配置 https://github.com/gengshan-y/rigidmask 1.拉取代码 git clone https://github.com/gengshan-y/rigidmask.git cd rigidmask2.创建conda环境&#xff0c;修改rigidmask.yml name: rigidmask channels:- pytorch- pytorch3d- conda-forge- defaults dependencies…

java--构造器

1.构造器是什么样子 构造器分为无参构造(就相当于你有车子&#xff0c;但是里面是空的)和带参构造(就相当于你有车子&#xff0c;里面还有几个妹纸&#xff0c;你真该死啊) 2.构造器有什么特点 创建对象时&#xff0c;对象会去调用构造器。 3.构造器的常见应用场景 创建对象…

Maven进阶系列-继承和聚合

Maven进阶系列-继承和聚合 文章目录 Maven进阶系列-继承和聚合1. 继承2. 继承的作用2.1 在父工程中配置依赖的统一管理2.2 在父工程中声明自定义属性2.3 父工程中必须要继承的配置 3. 聚合4. 聚合的作用 1. 继承 Maven工程之间存在继承关系&#xff0c;例如工程B继承工程A&…

基于Qt QTreeView|QTreeWidget控件使用简单版

头文件解析: 这是一个C++代码文件,定义了一个名为MainWindow的类。以下是对每一句的详细解释: ```cpp #ifndef MAINWINDOW_H #define MAINWINDOW_H ``` 这是一个条件编译指令,用于避免头文件的重复包含。`MAINWINDOW_H`是一个宏定义,用于唯一标识这个头文件。 ```cpp #…

idea的设置

1.设置搜索encoding,所有编码都给换为utf-8 安装插件 eval-reset插件 https://www.yuque.com/huanlema-pjnah/okuh3c/lvaoxt#m1pdA 设置活动模板,idea有两种方式集成tomcat,一种是右上角config配置本地tomcat,一种是插件,如果使用插件集成,则在maven,pom.xml里面加上tomcat…

【TES720D】青翼科技基于复旦微的FMQL20S400全国产化ARM核心模

板卡概述 TES720D是一款基于上海复旦微电子FMQL20S400的全国产化核心模块。该核心模块将复旦微的FMQL20S400&#xff08;兼容FMQL10S400&#xff09;的最小系统集成在了一个50*70mm的核心板上&#xff0c;可以作为一个核心模块&#xff0c;进行功能性扩展&#xff0c;特别是用…

AI:49-基于深度学习的杂草识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌本专栏包含以下学习方向: 机器学习、深度学…

架构设计之大数据架构(Lambda架构、Kappa架构)

大数据架构 一. 大数据技术生态二. 大数据分层架构三. Lambda架构3.1 Lambda架构分解为三层3.2 优缺点3.3 实际案例 四. Kappa架构4.1 结构图4.2 优缺点4.3 实际案例 五. Lambda架构与Kappa架构对比 其它相关推荐&#xff1a; 系统架构之微服务架构 系统架构设计之微内核架构 鸿…

diffusers-Load adapters

https://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adaptershttps://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adapters 有几种训练技术可以个性化扩散模型&#xff0c;生成特定主题的图像或某些风格的图像。每种训练方法都会产…

zookeeper集群选举机制

Zookeeper选举机制——第一次启动 zookeeper集群三个重要的参数&#xff08;决定选举结果&#xff09; SID &#xff1a; 服务器 ID 。 用来唯一标识一台 ZooKeeper集群中的机器&#xff0c;每台机器不能重 &#xff0c; 和 myid 一致 。 ZXID &#xff1a;事务 ID 。 ZXID 是…
最新文章