> 文章列表 > itop-3568 开发板系统编程学习笔记(18)LED 应用编程

itop-3568 开发板系统编程学习笔记(18)LED 应用编程

itop-3568 开发板系统编程学习笔记(18)LED 应用编程

【北京迅为】嵌入式学习之Linux系统编程篇 https://www.bilibili.com/video/BV1zV411e7Cy/ 个人学习笔记

文章目录

  • 应用层操作 LED 的两种方式
  • sysfs 方式控制 LED
    • 控制方法
    • 原理简介
  • 编写 LED 应用程序

应用层操作 LED 的两种方式

应用层操作底层硬件有两种方法,分别是:

  1. 通过 /dev 目录下的设备节点来控制设备
  2. 通过 sysfs 文件系统控制设备

这两种方法之前的笔记都有提及,第一种方法是直接写 led 的驱动,定义一个新的字符设备或者杂项设备,然后在应用层操作 /dev 下的设备节点;第二种方法使用了 sysfs 文件系统,部分简单设备(如 LED、GPIO)的驱动在实现时会将设备的一些属性导出到用户空间 sysfs 文件系统,用户可以直接在用户层访问和修改这些设备的属性数据。

sysfs 方式控制 LED

控制方法

下面介绍如何使用 sysfs 方式控制 LED,在命令行终端进入 /sys/class/leds 目录,

在这里插入图片描述

该目录下的 work 即为 iTOP-3568 开发板上的 LED 接口,这是一个目录文件,进入该目录,会出现多个文件,

在这里插入图片描述

brightness 表示 LED 的亮度,可取范围为 0 ~ max_brightness(不过 iTOP-3568 的 LED 不支持亮度调节,brightness 非 0 表示灯亮,0 表示灯灭)
max_brightness 即 LED 设备最大亮度,该属性只读
trigger 表示 LED 灯的触发方式,可取值包括:none(无触发)、disk-activity(硬盘活动触发)、nand-disk(nand flash 活动触发)、mdt(mtd 设备活动触发)、timer(定时器触发)和 heartbeat(系统心跳触发)

亮灯操作:

echo 1 > brightness

灭灯操作:

echo 0 > birghtness

让 LED 闪烁:

echo tiemr > trigger

虽然上面提到 trigger 可以有很多种类型,但我所用的开发板系统只支持 none 和 timer 两种触发方式。


原理简介

sysfs 下的 LED 设备在内核中属于 LED 子系统驱动框架,LED 子系统实际就是一个 leds 类,用户层可以通过 sysfs 文件系统对 LED 进行控制。

LED 子系统驱动源码在 kernel/drivers/leds/ 目录下的 led-gpio.c 中( led-class.c 和 led-core.c 两个文件也很重要),要让系统支持 LED 子系统,需要在内核配置中打开这三个文件的编译,在 kernel/drivers/leds/Makefile 中可以查看这三个文件的配置名:

在这里插入图片描述

然后在内核配置中将它们打开(其中 CONFIG_NEW_LEDS 在打开 LED Support 后就固定打开了,即第一行 LED Support)

在这里插入图片描述

以下是 CONFIG_LEDS_GPIO 的帮助信息,

在这里插入图片描述

从上面的帮助信息,我们可以得知:向 sysfs 添加 leds 设备的前提是平台设备文件或者设备树里有 leds 的配置信息。

iTOP-3568 使用的是设备树,打开相应的设备树文件,可以看到 leds 节点,LED 子设备的匹配值为 "gpio-leds"(在 led-gpio.c 中定义了 compatible 属性),节点 leds 下的 work 子节点对应的便是开发板 sysfs 下的 work 目录,该节点下定义了 gpios 等属性。

在这里插入图片描述

根据原理图可以得知:iTOP-3568 开发板的 LED 对应的 IO 接口为 GPIO0_B7,与设备树里的 gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;对应。设备树里的 gpio 属性是 sysfs 点灯的关键。

在这里插入图片描述

LED 子系统的驱动和设备配置完成后,我们就能在开发板 /sys/class/leds 目录下操作 LED 设备了。

编写 LED 应用程序

上面只提到了如何在命令行操作 LED,下面介绍一下如何在应用程序中操作 /sys/class/leds 下的 LED 设备。

程序代码:

参考原教程

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define LED_BRIGHTNESS "/sys/class/leds/work/brightness"
#define LED_TRIGGER    "/sys/class/leds/work/trigger"int main(int argc, char** argv)
{int fd1, fd2;int ret = 0;// 判断输入的参数if(argc != 3){printf("The right format: ./app <LED_BRIGHTNESS> <LED_TRIGGER>\\n");return 0;}// 打开 LED_BRIGHTNESS 文件fd1 = open(LED_BRIGHTNESS, O_RDWR);if(fd1 < 0){printf("%s open failed.\\n", LED_BRIGHTNESS);return 0;}printf("%s open successfully.\\n", LED_BRIGHTNESS);// 打开 LED_TRIGGER 文件fd2 = open(LED_TRIGGER, O_RDWR);if(fd2 < 0){printf("%s open failed.\\n", LED_TRIGGER);return 0;}printf("%s open successfully.\\n", LED_TRIGGER);// 操作 LED 亮灭if(!strcmp(argv[1], "on")){write(fd1, "1", 1);}else if(!strcmp(argv[1], "off")){write(fd1, "0", 1);}else // 无效参数{printf("ERROR: LED_BRIGHTNESS is invalid.\\n");}// 操作 LED 触发方式if(!strcmp(argv[2], "none")){write(fd2, "none", 4);}else if(!strcmp(argv[2], "timer")){write(fd2, "timer", 5);}else // 无效参数{printf("ERROR: LED_TRIGGER is invalid.\\n");}// 关闭设备文件close(fd1);close(fd2);return 0;
}

测试结果:

在这里插入图片描述

此时开发板上的 LED 开始规律性闪烁(实物就不展示了)。

个人认为,操作 sysfs 最简单的方式应该是直接使用系统调用,如 system("echo 1 > /sys/class/leds/work/brightness");

赞一把