一LED子系统框架分析

Posted 卍一十二画卍

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一LED子系统框架分析相关的知识,希望对你有一定的参考价值。

个人主页:董哥聊技术
我是董哥,嵌入式领域新星创作者
创作理念:专注分享高质量嵌入式文章,让大家读有所得!

文章目录

1、前言

我们学习嵌入式,无论是C51STM32或者是ARM,都是从点灯开始的,点灯在嵌入式中的地位等同于Hello World在各大语言中的地位!

虽然LED功能简单,但是其麻雀虽小,五脏俱全,在学习Linux驱动开发的过程中,学习LED子系统,往往也能够起到牵一发而动全身的作用,也更有益于大家熟悉驱动开发的框架!

 

2、LED裸机处理

我们在学习Linux驱动框架的时候,第一步要做的就是去掉子系统的面纱,先弄明白裸机处理的流程!

有嵌入式经验的朋友,对LED的裸机在清楚不过了,上面是LED的硬件电路,通常一端接到VCC,一端接到GPIO,当GPIO拉低时,LED亮;当GPIO拉高时,LED灭。

在这里裸机我们不过多了解了,目的在于窥探LED子系统

 

3、LED子系统框架

框架是什么?

框架是一个规范,为我们开发者增加限制的同时,也是为了更好的开发新的程序,新的功能,其目的主要是:将不变的成分剥离开来,固化进框架,让开发者做最少的事情!

框架所处的位置,正如上图所示,由下往上看:

  • Hardware:我们的硬件设备,指的是LED
  • 硬件驱动层:是直接操作硬件的实现,用于驱动硬件,实现相应的功能,并且将硬件设备注册进框架之中。
  • 核心层:将LED进行统一管理,向下提供注册接口,向上提供统一访问接口,方便用户访问
  • 用户层:用户通过指定的文件节点,能够直接控制LED的亮灭。

 

4、LED子系统目录结构及核心文件

了解完LED子系统框架之后,我们来分析一下其相关的目录结构!

ketnel
│   └── driver
│   │   └── leds
│   │   │   ├──	Makefile
│   │   │   ├──	led-core.c
│   │   │   ├──	led-gpio.c
│   │   │   ├──	led-class.c
│   │   │   ├──	led-triggers.c
│   │   │   ├──	......
│   │   │   └── trigger
│   │   │   │   ├── ledtrig-cpu.c
│   │   │   │   ├── ledtrig-heartbeat.c
│   │   │   │   ├── .......

上面即为LED子系统的目录结构,其主要核心文件有:

  • led-gpio.c:直接控制硬件设备,并且将其硬件设备注册进入LED驱动框架
  • led-core.c:核心层实现,抽象软件实现的相关功能,如闪烁,亮度设置等等,并管理LED设备
  • led-class.c:定义用户访问的相关接口
  • led-triggers.cLED出发功能的抽象
  • ledtrig-cpu.c:将LED作为CPU
  • ledtrig-heartbeat.c:将LED作为心跳灯

 

5、sysfs目录结构

在上面,我们了解了LinuxLED子系统相关的几个重要文件,那么该子系统在嵌入式设备的sysfs中的具体表现又是如何的呢?

5.1 确保LED子系统打开

我们如果在内核中打开了LED子系统目录下的Makefile文件,也就是kernel/drivers/leds/Makefile,我们看到

# SPDX-License-Identifier: GPL-2.0

# LED Core
obj-$(CONFIG_NEW_LEDS)			+= led-core.o
obj-$(CONFIG_LEDS_CLASS)		+= led-class.o
obj-$(CONFIG_LEDS_CLASS_FLASH)	+= led-class-flash.o
obj-$(CONFIG_LEDS_TRIGGERS)		+= led-triggers.o

......

我们必须在内核的配置中,通过 make menuconfig打开LED的相关配置,才支持LED相关功能。

 

5.2 查看sysfs文件结构

我们在开发板中输入ls /sys/class/leds/可以查看LED子系统生成的文件信息

/sys/class/leds下的目录对应的LED灯设备
cpu开发板的心跳灯
redPro开发板RGB灯的红色
greenPro开发板RGB灯的绿色
bluePro开发板RGB灯的蓝色
mmc0:SD卡指示灯(出厂镜像默认没有启用)

根据打开配置的不同,生成不同的文件节点

 

查看一下CPU节点的信息

#在开发板上有cpu目录,可在开发板上执行如下命令查看
ls /sys/class/leds/cpu

相关属性文件有:brightnessmax_brightnesstrigger

  • max_brightness文件:表示LED灯的最大亮度值。
  • brightness文件:表示当前LED灯的亮度值,它的可取 值范围为[0~max_brightness],一些LED设备不支持多级亮度,直接以非0值来 表示LED为点亮状态,0值表示灭状态。
  • trigger文件:则指示了LED灯的触发方式,查看该文件的内容时,该文件会 列出它的所有可用触方式,而当前使用的触发方式会以“[]”符号括起。

常见的触 发方式如下表所示:

触发方式说明
none无触发方式
disk-activity硬盘活动
nand-disknand flash活动
mtdmtd设备活动
timer定时器
heartbeat系统心跳

writing , waiting … 😃

点赞+关注,永远不迷路

9x25 LED 驱动框架分析 2016.07.13

9x25 LED 驱动框架分析 2016.07.13


进入内核 make menuconfig
输入 /led 回车搜索到
│ Location: │
│ -> Device Drivers │
│ -> LED Support (NEW_LEDS [=y])
进入LED Support发现有这一项 []LED Support for GPIO connected LEDs
在内核搜索该字符串 grep "LED Support for GPIO connected LEDs" * -nR
搜索到 drivers/leds/Kconfig:166: tristate "LED Support for GPIO connected LEDs"
打开 Kconfig查看,里面这样描述
config LEDS_GPIO
tristate "LED Support for GPIO connected LEDs"
depends on LEDS_CLASS
depends on GENERIC_GPIO
help
This option enables support for the LEDs connected to GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines. The LEDs must be
defined as platform devices and/or OpenFirmware platform devices.
The code to use these bindings can be selected below.
接着在内核搜索 grep "LEDS_GPIO" * -nR
搜索到 drivers/leds/Makefile:25:obj-$(CONFIG_LEDS_GPIO)
进入makefile 查看 发现内核会编译该文件
25 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
分析 leds-gpip.c
gpio_led_init(void)
platform_driver_register(&gpio_led_driver); //说明内核把led当作平台设备来处理,并注册进平台总线

分析gpio_led_driver
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,
.remove = __devexit_p(gpio_led_remove),
.driver = {
.name = "leds-gpio",
.owner = THIS_MODULE,
.of_match_table = of_gpio_leds_match,
},
};
//从结构体的类型struct platform_driver可知,这属于平台驱动
//该平台驱动名字“leds-gpio”,那么还有个平台设备 名字应该也为“leds-gpio”
在内核搜索“leds-gpio”
Leds.c (archarmmach-at91): .name = "leds-gpio",
进入分析 leds.c
static struct platform_device at91_gpio_leds_device = {
.name = "leds-gpio",
.id = -1,
.dev.platform_data = &led_data,
};
//从结构体的类型struct platform_device可知,这属于平台设备
at91_gpio_leds(struct gpio_led *leds, int nr)
{
led_data.leds = leds;
led_data.num_leds = nr;
platform_device_register(&at91_gpio_leds_device);
}
//at91_gpio_leds,提供了一个注册led的函数入口,他里面调用platform_device_register(&at91_gpio_leds_device);
//但是at91_gpio_leds_device这个结构体只是提供了平台设备的名字,不对应实际的led设备,所以at91_gpio_leds需要我们传入一个
//led实际设备的数据结构,和led的个数
在内核搜索at91_gpio_leds
发现调用者非常多,我暂时就取archarmmach-at91Board-stamp9g20.c分析
/*
* LEDs
*/
static struct gpio_led portuxg20_leds[] = {
{
.name = "LED2",
.gpio = AT91_PIN_PC5,
.default_trigger = "none",
}, {
.name = "LED3",
.gpio = AT91_PIN_PC4,
.default_trigger = "none",
}, {
.name = "LED4",
.gpio = AT91_PIN_PC10,
.default_trigger = "heartbeat",
}
};

static void __init portuxg20_board_init(void)
{
/* LEDs */
at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));
}

仿照该文件写一个led驱动

#include <linux/types.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>

#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/irq.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <mach/hardware.h>
#include <mach/board.h>
#include <mach/gpio.h>

#include "generic.h"

/*配置led 引脚 lsh 2016.07.13*/
static struct gpio_led bdth_leds[] = {
{ /* led1 心跳闪烁*/
.name = "led1",
.gpio = AT91_PIN_PB14,
.active_low = 1,
.default_trigger = "heartbeat",
},
{ /* led2 */
.name = "led2",
.gpio = AT91_PIN_PB15,
.active_low = 1,
.default_trigger = "none",
},
{ /* led3 */
.name = "led3",
.gpio = AT91_PIN_PB12,
.active_low = 1,
.default_trigger = "none",
},
};
static int __init bdth_leds_init(void)
{
at91_gpio_leds(bdth_leds, ARRAY_SIZE(bdth_leds));
}
static int __exit bdth_leds_exit(void)
{
printk(KERN_ERR "cannot del led devices ! :bdth lsh 2016.07.13 ");

}
module_init(bdth_leds_init);
module_exit(bdth_leds_exit);
MODULE_LICENSE("GPL");


测试:
make menuconfig里面配置,如下
Device Driversà[*]LED Supportà[*]LED class support
[*]LED support for GPIO connected LEDS
[*]LED Trigger support
[*]LED heartbeat trigger

测试下led1,如下
led1,是配置的心跳功能,他会自己闪烁

测试下led2,如下
# echo 1 > /sys/class/leds/led2/brightness
led2会亮。
继续测试
# echo 0 > /sys/class/leds/led2/brightness
led2会灭掉。

led3同理


































































































































































以上是关于一LED子系统框架分析的主要内容,如果未能解决你的问题,请参考以下文章

一LED子系统框架分析

STM32学习笔记 一基于STM32F103C8T6最小系统板和STM32CubeMX实现板载LED灯循环闪烁

stm32开发笔记:stm32系列的GPIO基本功能之输出驱动LED灯输入按键KEY以及Demo

stm32开发笔记:stm32系列的GPIO基本功能之输出驱动LED灯输入按键KEY以及Demo

STM32的LED驱动程序

小结-stm32 驱动LED灯