Jan 19, 2024
本文阅读量次【LED子系统深度剖析】一、开篇词|Linux驱动开发新手必读 # 1、前言 # 大家好,我是董哥!
俗话说:“万丈高楼平地起”,对于我们刚学习Linux驱动开发的小伙伴,Linux驱动开发的基础至关重要,无论我们是学习51单片机、STM32还是ARM,点灯的地位还是毋庸置疑的。
在Linux驱动开发的学习过程中,点灯对于大多数人来说,对着教程照葫芦画瓢,还是能快速点亮一颗LED灯的,但是你真的明白,一颗小小LED灯的背后,到底执行了哪些动作吗,Linux内核是如何管理的呢?
今天,作为在芯片原厂工作的我,有义务带着大家,深入扒一扒LED子系统的工作原理!
总结系列文章,花费时间较长,希望大家尊重原创!
2、LED子系统开发详细介绍 # 该系列文章整体预览如下:
3、LED子系统开发文章汇总 # 为了方便大家快速找到文章,这里按照学习流程进行汇总,点击即可访问!
章节 内容 1、开篇词 1. 文章总览 2、LED子系统框架分析 2.1 裸机处理 2.2 LED子系统框架 2.3 目录结构及核心文件 3、硬件驱动层详解 3.1 gpio_led_probe分析 3.2 gpio_leds_create分析 3.3 create_gpio_led分析 3.4 数据结构之间的关系,以及实现流程 4、核心层——led-class.c详解 4.1 leds_init分析 4.2 leds_class_dev_pm_ops分析 4.3 led_groups分析 4.4 led class的注册注销分析 5、核心层——led-core.c详解 5.1 led_init_core分析 5.2 led_timer_function分析 5.3 set_brightness_delayed分析 5.4 代码实现流程分析 6、核心层——led-triggers.c详解 6.1 触发器设置相关函数分析 6.2 触发器注册注销函数分析 6.3 闪烁功能相关函数分析 6.4 调用流程分析 7、触发器的实现 7.1 触发器介绍 7.2 heartbeat触发器的注册注销流程 7.
...
Jan 19, 2024
本文阅读量次【LED子系统深度剖析】二、LED子系统框架分析 # 1、前言 # 我们学习嵌入式,无论是C51、STM32或者是ARM,都是从点灯开始的,点灯在嵌入式中的地位等同于Hello World在各大语言中的地位!
虽然LED功能简单,但是其麻雀虽小,五脏俱全,在学习Linux驱动开发的过程中,学习LED子系统,往往也能够起到牵一发而动全身的作用,也更有益于大家熟悉驱动开发的框架!
2、LED裸机处理 # 我们在学习Linux驱动框架的时候,第一步要做的就是去掉子系统的面纱,先弄明白裸机处理的流程!
有嵌入式经验的朋友,对LED的裸机在清楚不过了,上面是LED的硬件电路,通常一端接到VCC,一端接到GPIO,当GPIO拉低时,LED亮;当GPIO拉高时,LED灭。
在这里裸机我们不过多了解了,目的在于窥探LED子系统。
3、LED子系统框架 # 框架是什么?
框架是一个规范,为我们开发者增加限制的同时,也是为了更好的开发新的程序,新的功能,其目的主要是:将不变的成分剥离开来,固化进框架,让开发者做最少的事情!
框架所处的位置,正如上图所示,由下往上看:
Hardware:我们的硬件设备,指的是LED 硬件驱动层:是直接操作硬件的实现,用于驱动硬件,实现相应的功能,并且将硬件设备注册进框架之中。 核心层:将LED进行统一管理,提供注册,注销,管理LED等相关接口,起到呈上启下的作用,方便上层调用。 用户层:用户通过sysfs文件系统中对应的文件节点,能够直接控制LED的亮灭。 4、LED子系统目录结构及核心文件 # 了解完LED子系统框架之后,我们来分析一下其相关的目录结构!
ketnel │ └── driver │ │ └── leds │ │ │ ├── Makefile │ │ │ ├── led-core.c │ │ │ ├── led-gpio.c │ │ │ ├── led-class.c │ │ │ ├── led-triggers.c │ │ │ ├── ...... │ │ │ └── trigger │ │ │ │ ├── ledtrig-cpu.
...
Jan 19, 2024
本文阅读量次【LED子系统深度剖析】三、硬件驱动层详解 # 上篇文章我们了解了子系统的框架,下面我们来分析驱动框架中每层的实现以及作用。
在LED子系统中,硬件驱动层相关文件在包括:kernel/drivers/leds/ 目录下,其主要的函数有:led-gpio.c、led-xxx.c,其中led-gpio.c为通用的平台驱动程序,led-xxx.c为不同厂家提供的平台驱动程序。
我们在这里主要分析led-gpio.c
1、gpio_led_probe分析 # 打开该文件,直接找到加载驱动的入口函数gpio_led_probe
1.1 相关数据结构 # 1.1.1 gpio_led_platform_data # struct gpio_led_platform_data { int num_leds; const struct gpio_led *leds; #define GPIO_LED_NO_BLINK_LOW 0 /* No blink GPIO state low */ #define GPIO_LED_NO_BLINK_HIGH 1 /* No blink GPIO state high */ #define GPIO_LED_BLINK 2 /* Please, blink */ gpio_blink_set_t gpio_blink_set; }; 结构体名称:gpio_led_platform_data
文件位置:include/linux/leds.h
主要作用:LED的平台数据,用于对LED硬件设备的统一管理
这个结构体用于父节点向子节点传递的数据时使用
1.1.2 gpio_leds_priv # struct gpio_leds_priv { int num_leds; struct gpio_led_data leds[]; }; 结构体名称:gpio_leds_priv
...
Jan 19, 2024
本文阅读量次【LED子系统深度剖析】四、核心层详解(一) # 1、前言 # 上篇文章我们了解了子系统的硬件驱动层,下面我们来分析驱动框架中核心层的实现以及作用。
在LED子系统框架中,核心层包括几个部分:核心层的实现部分(led-core.c)、sysfs文件节点创建(led-class.c)、触发功能实现(led-triggers.c、driver/leds/triggers/led-xxx.c)
其中,触发功能部分较为独立,我们暂且先不去分析。
我们先从led-class.c文件开始分析
2、leds_init分析 # 该函数其主要是为了创建LED设备文件节点,方便用户通过节点直接访问。
该文件,我们直接拉下底部,我们直接看入口函数:leds_init
2.1 相关数据结构 # 2.1.1 class # /** * struct class - device classes * @name: Name of the class. * @owner: The module owner. * @class_groups: Default attributes of this class. * @dev_groups: Default attributes of the devices that belong to the class. * @dev_kobj: The kobject that represents this class and links it into the hierarchy. * @dev_uevent: Called when a device is added, removed from this class, or a * few other things that generate uevents to add the environment * variables.
...
Jan 19, 2024
本文阅读量次【LED子系统深度剖析】五、核心层详解(二) # 1、前言 # 上篇文章我们了解了子系统的核心层led-class.c,下面我们来分析驱动框架中核心层的led-core.c实现以及作用。
我们接着从led-core.c文件开始分析
2、led_init_core分析 # 上一篇文章,我们知道在将leds_classdev注册进入子系统后,会调用led_init_core函数,初始化核心层,下面我们以led_init_core该函数为突破口分析。
2.1 相关数据结构 # 2.1.1 work_struct # struct work_struct { atomic_long_t data; struct list_head entry; work_func_t func; #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif }; 结构体名称:work_struct
文件位置:include/linux/workqueue.h.h
主要作用:定义一个工作队列,包括了工作项的状态和数据,以及处理工作项的函数指针,用于实现异步执行任务的功能。在工作队列中,每个工作项都是一个work_struct结构体的实例,通过将工作项添加到工作队列中,可以实现后台执行任务的功能。
2.1.2 timer_list # struct timer_list { /* * All fields that change during normal runtime grouped to the * same cacheline */ struct hlist_node entry; unsigned long expires; void (*function)(struct timer_list *); u32 flags; #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif }; 结构体名称:work_struct
...
Jan 19, 2024
本文阅读量次我的圈子: 高级工程师聚集地 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 亲爱的读者,你好: 感谢你对我的专栏的关注和支持,我很高兴能和你分享我的知识和经验。如果你喜欢我的内容,想要阅读更多的精彩技术文章,可以扫码加入我的社群。
欢迎关注【嵌入式艺术】,董哥原创!
Jan 19, 2024
本文阅读量次我的圈子: 高级工程师聚集地 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 亲爱的读者,你好: 感谢你对我的专栏的关注和支持,我很高兴能和你分享我的知识和经验。如果你喜欢我的内容,想要阅读更多的精彩技术文章,可以扫码加入我的社群。
欢迎关注【嵌入式艺术】,董哥原创!
Jan 19, 2024
本文阅读量次我的圈子: 高级工程师聚集地 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 亲爱的读者,你好: 感谢你对我的专栏的关注和支持,我很高兴能和你分享我的知识和经验。如果你喜欢我的内容,想要阅读更多的精彩技术文章,可以扫码加入我的社群。
欢迎关注【嵌入式艺术】,董哥原创!
Jan 19, 2024
本文阅读量次我的圈子: 高级工程师聚集地 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 亲爱的读者,你好: 感谢你对我的专栏的关注和支持,我很高兴能和你分享我的知识和经验。如果你喜欢我的内容,想要阅读更多的精彩技术文章,可以扫码加入我的社群。
欢迎关注【嵌入式艺术】,董哥原创!
Jan 19, 2024
本文阅读量次我的圈子: 高级工程师聚集地 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 亲爱的读者,你好: 感谢你对我的专栏的关注和支持,我很高兴能和你分享我的知识和经验。如果你喜欢我的内容,想要阅读更多的精彩技术文章,可以扫码加入我的社群。
欢迎关注【嵌入式艺术】,董哥原创!