Linux驱动开发学习笔记【12】:Linux自带LED灯驱动

目录

一、内核自带LED驱动使能

二、内核自带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 目录下的 Makefileleds-gpio.o 就会被添加进内核编译。

这里也有一个反向配置的方法,也就是我知道了要打开的宏名字,怎么在menuconfig中找到可以使能的配置项:

1、输入 make menuconfig

2、输入 /

3、输入要搜索的 宏(我这里搜索了(CONFIG_LEDS_GPIO ),按下回车,则会出现以下界面,再输入前面对应的标号 1,就会跳转到要配置的界面了

二、内核自带LED驱动分析

打开 /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);

三、内核自带LED驱动使用

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:表示默认触发方式,有如下几种可选:

  1. "backlight" - LED will act as a back-light, controlled by the framebuffersystem
  2. "default-on" - LED will turn on (but for leds-gpio see "default-state"property in Documentation/devicetree/bindings/gpio/led.txt)
  3. "heartbeat" - LED "double" flashes at a load average based rate
  4. "ide-disk" - LED indicates disk activity
  5. "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灯的模式,可以通过修改 brightnesstrigger 来实现

猜你喜欢

转载自blog.csdn.net/m0_37845735/article/details/107328682