本文转载自:https://blog.csdn.net/u010444107/article/details/78328807

1)查看内核配置
wujun@wj-vBox:~/freescale/linux-imx$ cat arch/arm/configs/imx_v7_defconfig | grep LEDS
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_GPIO=y
已经开启了LED并且使能了几种触发模式:timer oneshot heartbeat backlight gpio

(2)设备树增加LED相关设定
wujun@wj-vBox:~/freescale/linux-imx$ vi arch/arm/boot/dts/imx6ul-14x14-evk.dts
leds {
compatible = “gpio-leds”;
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_leds>;

led0: user {
label = "user";
gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
default-state = "off";
};

led1: cpu {
label = "cpu";
gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
default-state = "on";
linux,default-trigger = "heartbeat";
};
};
1
2
3
4
5
6
7
8
9
10
11
12
13
pinctrl放在 &iomuxc下
pinctrl_leds: ledgrp {
fsl,pins = <
MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b0b0
MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b0b0

;
};

共设定两个灯,
一个是GPIO5 IO01 用户灯
一个是GPIO5 IO02 CPU心跳灯

(3)查找驱动
wujun@wj-vBox:~/freescale/linux-imxgrep−rn“gpio−leds”driversdrivers/leds/leds−gpio.c:237:.compatible=“gpio−leds”,,触发方式源码在trigger目录下wujun@wj−vBox: /freescale/linux−imx/drivers/ledsgrep−rn“gpio−leds”driversdrivers/leds/leds−gpio.c:237:.compatible=“gpio−leds”,,触发方式源码在trigger目录下wujun@wj−vBox: /freescale/linux−imx/drivers/leds ls trigger/
built-in.o ledtrig-cpu.c ledtrig-heartbeat.c ledtrig-timer.o
Kconfig ledtrig-cpu.o ledtrig-heartbeat.o ledtrig-transient.c
ledtrig-backlight.c ledtrig-default-on.c ledtrig-ide-disk.c ledtrig-transient.o
ledtrig-backlight.o ledtrig-default-on.o ledtrig-oneshot.c Makefile
ledtrig-camera.c ledtrig-gpio.c ledtrig-oneshot.o modules.builtin
ledtrig-camera.o ledtrig-gpio.o ledtrig-timer.c modules.order
这些的编译时通过内核配置项来确定的。

(4)启动系统
通过查看LED的trigger文件,就能知道当前LED支持的触发器和目前设定的触发器
root@imx6ulevk:~# cat /sys/class/leds/user/trigger
[none] rc-feedback nand-disk mmc0 mmc1 timer oneshot heartbeat backlight gpio
root@imx6ulevk:~# cat /sys/class/leds/cpu/trigger
none rc-feedback nand-disk mmc0 mmc1 timer oneshot [heartbeat] backlight gpio

user led没有设定trigger
cpu led设定为heartbeat trigger

设置触发器也很简单,使用echo将触发器名称写入trigger文件即可。
写入的字符串一定是trigger文件已经存在的,否则会提示参数非法。
这里将user灯也设定为心跳灯。
root@imx6ulevk:~# echo heartbeat > /sys/class/leds/user/trigger
此时user灯与cpu灯同时闪烁。不过不是同步的。

再次查看用户灯的触发方式
root@imx6ulevk:~# cat /sys/class/leds/user/trigger
none rc-feedback nand-disk mmc0 mmc1 timer oneshot [heartbeat] backlight gpio
已经设定成心跳灯了。

(5)心跳灯控制源码
因为比较好奇心跳灯闪的频率,查看了驱动源码。
wujun@wj-vBox:~/freescale/linux-imx/drivers/leds$ vi trigger/ledtrig-heartbeat.c
找到了控制闪灯时序的代码。

static void led_heartbeat_function(unsigned long data)
{
struct led_classdev led_cdev = (struct led_classdev ) data;
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
unsigned long brightness = LED_OFF;
unsigned long delay = 0;

if (unlikely(panic_heartbeats)) {
led_set_brightness(led_cdev, LED_OFF);
return;
}

/* acts like an actual heart beat -- ie thump-thump-pause... */
switch (heartbeat_data->phase) {
case 0:
/*
* The hyperbolic function below modifies the
* heartbeat period length in dependency of the
* current (1min) load. It goes through the points
* f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
*/
heartbeat_data->period = 300 +
(6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
heartbeat_data->period =
msecs_to_jiffies(heartbeat_data->period);
delay = msecs_to_jiffies(70);
heartbeat_data->phase++;
brightness = led_cdev->max_brightness;
break;
case 1:
delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
heartbeat_data->phase++;
break;
case 2:
delay = msecs_to_jiffies(70);
heartbeat_data->phase++;
brightness = led_cdev->max_brightness;
break;
default:
delay = heartbeat_data->period - heartbeat_data->period / 4 -
msecs_to_jiffies(70);
heartbeat_data->phase = 0;
break;
}

led_set_brightness_async(led_cdev, brightness);
mod_timer(&heartbeat_data->timer, jiffies + delay);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
}

代码比较简单,不过里面有个细节
/* acts like an actual heart beat – ie thump-thump-pause… */
这个意思是说,模拟人的心跳,从这点上看,写这段代码的工程师是具有追求极致的精神。心跳灯都要模拟心跳的频率。
另外一个点就是周期的计算方法。
/*
* The hyperbolic function below modifies the
* heartbeat period length in dependency of the
* current (1min) load. It goes through the points
* f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
*/
heartbeat_data->period = 300 +
(6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
从代码的意思上看,是根据当前的系统load来决定周期。
如果系统load是0,周期就是1260,其他类推。
300 + (6270 << 11) / (5 * 0) + (7 << 11) = 300 + 6270 / 7 = 300 + 960 = 1260;

其中FSHIFT可以从下面路径找到定义
wujun@wj-vBox:~/freescale/linux-imx/include/linux$ grep -rn “FSHIFT” .
./sched.h:153:#define FSHIFT 11 /* nr of bits of precision */
这个是因为linux内核避免使用浮点运算所以用整数来计算。

linux内核定义了unsigned long avenrun[3];三个长整型数据。
wujun@wj-vBox:~/freescale/linux-imx$ vi ./kernel/sched/proc.c +61
61 unsigned long avenrun[3];
在32位的cpu上,long对应的就是32bit,其中低11位用于存放负载的小数部分,高21位用于存放整数部分。
之所以是三个变量,是因为内核要记录cpu的load有三个变量,分别是1min,5min和15min。
运行top的时候能够看到这三个变量的值。
load average: 0.00, 0.02, 0.00

运行uptime也可以看到
wujun@wj-vBox:~/freescale/linux-imx$ uptime
11:44:08 up 21:23, 1 user, load average: 0.00, 0.02, 0.00

这三个值是从/proc/loadavg中获得的。
wujun@wj-vBox:~/freescale/linux-imx$ cat /proc/loadavg
0.00 0.02 0.00 1/167 5038

得出结论是在cpu load为0的情况下,闪灯周期是1260ms。
总共闪两次,每次亮70ms,两次亮之间的时间差是周期的1/4.
也就是在cpu load = 0情况下:
|70 | |70 |
| 415ms |
| 415ms | 415ms | 415ms | 415ms |

(6)最后用示波器看一下波形是否如预期。
因为GPIO的驱动能力有限,一般LED控制都是选择灌电流。这样逻辑上是反向的,低电平亮,高电平灭。
上图

imx6ul linux4.1.15 LED驱动配置及heartbeat源码分析【转】的更多相关文章

  1. Spring Boot从入门到精通(五)多数据源配置实现及源码分析

    多数据源配置在项目软件中是比较常见的开发需求,Spring和Spring Boot中对此都有相应的解决方案可供大家参考.在Spring Boot中,如MyBatis.JdbcTemplate以及Jpa ...

  2. (九)uboot配置编译、源码分析

    一.X210官方uboot配置编译实践1.找到官方移植好的uboot(BSP概念)(1)源头的源代码是uboot官网下载的.这个下载的源代码可能没有你当前使用的开发板的移植,甚至找不到当前开发板使用的 ...

  3. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  4. C++STL内存配置的设计思想与关键源码分析

    说明:我认为要读懂STL中allocator部分的源码,并汲取它的思想,至少以下几点知识你要了解:operator new和operator delete.handler函数以及一点模板知识.否则,下 ...

  5. Spring Boot JDBC:加载DataSource过程的源码分析及yml中DataSource的配置

    装载至:https://www.cnblogs.com/storml/p/8611388.html Spring Boot实现了自动加载DataSource及相关配置.当然,使用时加上@EnableA ...

  6. spring cloud EurekaClient 多网卡 ip 配置 和 源码分析(转)

    https://blog.csdn.net/qq_30062125/article/details/83856655 1.前言对于spring cloud,各个服务实例需要注册到Eureka注册中心. ...

  7. (转)Linux设备驱动之HID驱动 源码分析

    //Linux设备驱动之HID驱动 源码分析 http://blog.chinaunix.net/uid-20543183-id-1930836.html HID是Human Interface De ...

  8. Linux MMC 驱动子系统简述(源码剖析)

    1. Linux MMC 驱动子系统 块设备是Linux系统中的基础外设之一,而 MMC/SD 存储设备是一种典型的块设备.Linux内核设计了 MMC子系统,用于管理 MMC/SD 设备. MMC ...

  9. ABP源码分析二:ABP中配置的注册和初始化

    一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...

随机推荐

  1. struts2实现XML异步交互

    异步交互,在不用重新提交整个页面的情况下可以实现页面局部信息与服务器的交互.在编写异步交互时需要用到一个架包:dom4j,下载地址为:https://dom4j.github.io/ 下面通过例子说明 ...

  2. notepad使用列选

    列选有两种方法: 1.按住ALT + 鼠标从某点按住开始向下或向上拖动. 2.按住ALT+SHIFT+上下方向键. 列编辑: 1.ALT+C 2.插入相同文本还是自增数字

  3. 删除(unfork)github中某个库(repository)

    1.头像->your profile 2.点击某个想要删除的库,出现界面: 3.点击setting,鼠标滚动页面至末尾,出现页面: 4.点击delete this repository: OK!

  4. jQuery安装

    http://www.runoob.com/jquery/jquery-install.html 网页中添加jQuery: 方法一:可以从http://jquery.com/download/ 下载j ...

  5. 【Oozie学习之一】Oozie

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 CM5.4 一.简介Oozie由Cloudera公司贡献给A ...

  6. SVN && BeyondCompare

    [1]设置内容 (1)三个步骤对应设置内容 1.1 "D:\Beyond Compare 4\BCompare.exe" %base %mine /title1=%bname /t ...

  7. python 读csv格式的文件

    对于大多数的CSV 格式的数据读写问题,都可以使用csv 库 1. 直接读csv 以下是要操作的csv文件内容 import csv with open(r'C:\Temp\f.csv') as f: ...

  8. mysql的sql执行计划详解

    实际项目开发中,由于我们不知道实际查询的时候数据库里发生了什么事情,数据库软件是怎样扫描表.怎样使用索引的,因此,我们能感知到的就只有 sql语句运行的时间,在数据规模不大时,查询是瞬间的,因此,在写 ...

  9. flask 单个页面多个表单(单视图处理、多视图处理)

    单个页面多个表单 除了在单个表单上实现多个提交按钮,有时还需要在单个页面上创建多个表单.比如,在程序的主页上同时添加登录和注册表单.当在同一个页面上添加多个表单时,我们需要解决的问题是在视图函数中判断 ...

  10. JavaScript:原生JS实现Facebook实时消息抓捕

    基础知识准备: HTML5给我们提供了一个新的对象叫作:MutationObserver.为了兼容,还有WebKitMutationObserver.MozMutationObserver,挂靠在wi ...