详情参见教材206页~208页
我们的LED是基于 GPIO的,为此,内核有两个对应的驱动程序,分别时GPIO驱动和LED驱动,基于GPIO的LED的驱动调用了GPIO驱动导出的函数,这一节我们并不关心GPIO的驱动(后面会有详细说明)。关于LED驱动,内核文档Documentation/leds/leds-class.txt有简单的描述,它实现了一个leds类,通过sysfs的接口才对LED进行控制,所以它并没有使用字符设备驱动的框架。驱动代码的实现qing参见Linux3.14/drivers/leds/leds-gpio.c。
既然驱动已经实现了,那么我们要怎么来让他工作起来呢?首先要配置内核,确保驱动被选配了。再内核源码下进行make ARCH=arm menuconfig命令,按照下面的选项进行选择。
Device Driver --->
[*] LED Support --->
<*> LED Class Support
<*> LED Support for GPIO connected LEDs
[*] LED Trigger support --->
选好配置后,保存,使用下面的命令重新编译内核,然后复制到TFTP服务器指定的目录下。
配置好后添加设备树节点
vim arch/arm/boot/dts/exynos4412-fs4412.dts
compatible属性为gpio-leds,可以和LED驱动匹配。每个节点中的label是出现在sys目录下的子目录名字。gpios则制定了该LED所连接的GPIO口,第三个值为0表示高电平点亮LED灯,为1表示低电平点亮LED灯。default-state属性的值为off,则表示默认情况下LED灯是熄灭的,为on则默认点亮。修正好后使用下面的命令编译设设备树,然后复制到指定目录。
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- dtbs
cp arch/arm/boot/dts/exynos4412-fs4412.dtb ../../tftpboot/
重启开发板,使用下面的命令看到对应的设备目录
[root@farsight ]# ls -l /sys/class/leds/
total 0
lrwxrwxrwx 1 0 0 0 Jan 1 00:00 fs4412-led2 -> ../../devices/fs4412_leds.3/leds/fs4412-led2
lrwxrwxrwx 1 0 0 0 Jan 1 00:00 fs4412-led3 -> ../../devices/fs4412_leds.3/leds/fs4412-led3
lrwxrwxrwx 1 0 0 0 Jan 1 00:00 fs4412-led4 -> ../../devices/fs4412_leds.3/leds/fs4412-led4
lrwxrwxrwx 1 0 0 0 Jan 1 00:00 fs4412-led5 -> ../../devices/fs4412_leds.3/leds/fs4412-led5
lrwxrwxrwx 1 0 0 0 Jan 1 00:00 mmc0:: -> ../../devices/12530000.sdhci/leds/mmc0::
fs4412-led2、fs4412-led3、fs4412-led4、fs4412-led5分别对应了4个LED灯,在每个目录下都有一个brightness文件,通过该文件可以获取LED当前的亮度,通过写该文件可以修改LED灯的亮度。因为这些LED灯饰连接在GPIO端口上面所以亮度只有0和1,0是熄灭,1是点亮
如下
[root@farsight ]# cat /sys/class/leds/fs4412-led2/brightness
0
[root@farsight ]# echo "1" > /sys/class/leds/fs4412-led2/brightness
当然也可以编写一个应用程序来控制LED灯的亮灭,应用测试代码如下
“程序源码/examples/ex1”
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define LED_DEV_PATH "/sys/class/leds/led%d/brightness"
#define ON 1
#define OFF 0
int fs4412_set_led(unsigned int lednum, unsigned int mode)
{
int fd;
int ret;
char devpath[128];
char *on = "1\n";
char *off = "0\n";
char *m = NULL;
snprintf(devpath, sizeof(devpath), LED_DEV_PATH, lednum);
fd = open(devpath, O_WRONLY);
if (fd == -1) {
perror("fsled->open");
return -1;
}
if (mode == ON)
m = on;
else
m = off;
ret = write(fd, m, strlen(m));
if (ret == -1) {
perror("fsled->write");
close(fd);
return -1;
}
close(fd);
return 0;
}
int main(int argc, char *argv[])
{
unsigned int lednum = 2;
while (1) {
fs4412_set_led(lednum, ON);
usleep(500000);
fs4412_set_led(lednum, OFF);
usleep(500000);
lednum++;
if (lednum > 5)
lednum = 2;
}
}
led子系统(一)
在Linux系统中为了更好的管理LED设备,设计了LED系统,基于LED子系统编写驱动非常简单。
一 LED子系统
在Linux内核源码树下的drivers/leds目录下有以下文件:
led-class.c : 提供了注册led设备的函数接口以及用户空间操作LED设备属性文件
led-core.c : 提供了一些LED亮度和闪烁的函数接口
led-triggers.c : 提供了对trigger触发器的操作函数接口
这些文件构成了led子系统框架。
在Linux源码树下的drivers/leds/trigger目录下可以看到Linux内核提供的触发器驱动,常用的触发器有: