1. 前言
限于作者能力水平,本文可能存在的谬误,因此而给读者带来的损失,作者不做任何承诺。
2. 背景
要在S5P4418的开发板上,驱动一个LED灯,用作系统工作状态的心跳灯,内核版本为 Linux 3.4.y。LED灯的硬件设计为:
GPIOC17连接到LED灯:拉低GPIO,灯变亮,拉高GPIO,灯熄灭。
3. 实现
初始的想法是,通过workqueue
或timer
定期控制GPIO电平状态,从而控制连接到GPIO的LED的亮灭。按这个思路,需要实现一个完整的驱动,但经过摸索后发现,内核已经为我们提供了类似的驱动,我们只需要做简单的适配就可以了。经过斟酌,我们选用了heartbeat
算法的LED驱动,其使用workqueue
实现其功能。接下来我们看如何适配该驱动到我们的LED硬件。
3.1 LED灯驱动GPIOC17平台适配
由于GPIOC17是具备复用功能,首先我们要将它配置成工作在GPIO模式。修改文件arch/arm/plat-s5p4418/nanopi2/include/cfg_gpio.h
#define PAD_GPIOC17 (PAD_MODE_OUT | PAD_FUNC_ALT1 |
PAD_LEVEL_LOW | PAD_PULL_OFF |
PAD_STRENGTH_0)
3.2 创建GPIO LED驱动设备对象
GPIO LED驱动实现在文件drivers/leds/leds-gpio.c
,使用该驱动,要创建一个该驱动的设备对象。修改文件arch/arm/plat-s5p4418/nanopi2/device.c
:
#if defined(CONFIG_LEDS_GPIO)
#include <linux/leds.h>
static struct gpio_led board_leds[] = {
{
.name = "led1",
.gpio = (PAD_GPIO_B + 12),
.active_low = 1,
.default_trigger = "heartbeat",
}, {
.name = "led2",
.gpio = (PAD_GPIO_B + 11),
.active_low = 1,
.default_trigger = "none",
}, { /* 添加作为系统心跳灯的GPIO LED */
.name = "led3", /* 名称 */
.gpio = (PAD_GPIO_C + 17), /* 指定灯控制GPIOC */
.active_low = 1, /* 低电平点亮灯 */
/* 灯的控制算法,可以有更多选择。参看 drivers/leds/trigger 目录 */
.default_trigger = "heartbeat",
},
};
static struct gpio_led_platform_data gpio_led_pdata = {
.num_leds = ARRAY_SIZE(board_leds),
.leds = board_leds,
};
/* 添加作为系统心跳灯的GPIO LED驱动设备对象 */
static struct platform_device gpio_led_device = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &gpio_led_pdata,
},
};
#endif
当然,使用内核GPIO LED灯驱动的前提是,开启配置项CONFIG_LEDS_GPIO
。