目录
一、内核自带LED驱动使能
二、内核自带LED驱动分析
三、内核自带LED驱动使用
在Linux内核中,已经自带了LED灯的驱动程序,使用的就是platform平台驱动,在使用之前,需要通过 make menuconfig 配置内核,使能LED灯的驱动
保存退出会在目录下的 .config 配置文件中多处 CONFIG_LEDS_GPIO=y 的宏,y 表示编译进内核,如果是 m 则表示编译成模块。完成后使用 make -j4 就能将新添加的LED驱动添加进内核了。这里有个搜索文件中某个内容的技巧:在 一般模式下(按ESC)输入 / ,再输入要搜索的内容,按下回车则会找到要查找的内容。
CONFIG_LEDS_GPIO 宏被定义后,在 /drivers/leds 目录下的 Makefile 中 leds-gpio.o 就会被添加进内核编译。
这里也有一个反向配置的方法,也就是我知道了要打开的宏名字,怎么在menuconfig中找到可以使能的配置项:
1、输入 make menuconfig
2、输入 /
3、输入要搜索的 宏(我这里搜索了(CONFIG_LEDS_GPIO ),按下回车,则会出现以下界面,再输入前面对应的标号 1,就会跳转到要配置的界面了
打开 /drivers/leds/leds-gpio.c,该文件就linux内核自带的LED驱动源文件,采用的就是使用设备树来匹配驱动跟设备的platform平台设备驱动。驱动会根据 of_gpio_leds_match 匹配表中的 compatible 值去匹配设备树中的节点,如果在设备中定义了对应的设备树节点,则 gpio_led_probe 函数就会得到执行
static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", },
{},
};
MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
static int gpio_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct gpio_leds_priv *priv;
int i, ret = 0;
if (pdata && pdata->num_leds) {
priv = devm_kzalloc(&pdev->dev,
sizeof_gpio_leds_priv(pdata->num_leds),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->num_leds = pdata->num_leds;
for (i = 0; i < priv->num_leds; i++) {
ret = create_gpio_led(&pdata->leds[i],
&priv->leds[i],
&pdev->dev, pdata->gpio_blink_set);
if (ret < 0) {
/* On failure: unwind the led creations */
for (i = i - 1; i >= 0; i--)
delete_gpio_led(&priv->leds[i]);
return ret;
}
}
} else {
priv = gpio_leds_create(pdev);
if (IS_ERR(priv))
return PTR_ERR(priv);
}
platform_set_drvdata(pdev, priv);
return 0;
}
static int gpio_led_remove(struct platform_device *pdev)
{
struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
int i;
for (i = 0; i < priv->num_leds; i++)
delete_gpio_led(&priv->leds[i]);
return 0;
}
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,
.remove = gpio_led_remove,
.driver = {
.name = "leds-gpio",
.of_match_table = of_gpio_leds_match,
},
};
/*同时完成了向内核注册和注销驱动的过程
*platform_driver_register(&led_driver)
*platform_driver_unregister(&led_driver)
*/
module_platform_driver(gpio_led_driver);
1、首先要将驱动编译进内核里面
2、如果有设备树下,根据绑定文档在.dts设备树中添加相应的设备树节点信息;
如果没有设备树时,就需要使用 platform_device_register 向总线注册LED灯设备
根据绑定文档,添加的LED设备树节点如下:
/*自行添加的Linux内核LED驱动*/
linux_leds {
compatible = "gpio-leds";
pinctrl-0 = <&pinctrl_gpio_leds>;/*pinctrl子系统*/
led0 {
label = "sysrun";
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
};
label:名字
gpios :gpio子系统
linux,default-trigger:表示默认触发方式,有如下几种可选:
- "backlight" - LED will act as a back-light, controlled by the framebuffersystem
- "default-on" - LED will turn on (but for leds-gpio see "default-state"property in Documentation/devicetree/bindings/gpio/led.txt)
- "heartbeat" - LED "double" flashes at a load average based rate
- "ide-disk" - LED indicates disk activity
- "timer" - LED flashes at a fixed, configurable rate
3、运行测试
输入如下命令,将设备树更新,重启开发板,此时led就会作为心跳灯循环快闪2次,满闪一次。同时在 /sys/devices/platform 目录下能看见添加的 linux_leds 节点
sudo cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb /home/denghengli/linux/tftp/ -f
如果想控制LED亮灭和修改LED灯的模式,可以通过修改 brightness 和 trigger 来实现