嵌入式开发工程师点亮一个LED灯,就类似软件工程师实现一个hello world程序。ELF 1开发板主控板上有红、绿、黄三个LED小灯,核心板有一个LED心跳灯。在Linux系统点亮一个LED方法很多,比如在驱动中通过操作相关引脚的寄存器实现,也可以借助Linux中Pinctrl子系统和GPIO子系统实现,Pinctrl子系统主要根据设备树中引脚配置信息配置IOMUX,GPIO子系统则主要是提供控制GPIO的API。本节直接使用Linux系统中自带的gpio-leds驱动实现,gpio-leds通过调用Pinctrl子系统和GPIO子系统实现LED灯的控制。 硬件原理 在主控板原理图中找到LED_R、LED_G、LED_Y三个小灯:
并通过LED_R,LED_G,LED_Y网络号找到对应的具体GPIO引脚及其球号:
IOMUX配置 从上图可以看出LED_R连接到了连接器的60脚,LED_G连到了64脚,LED_Y连接到了30脚。接下来我们需要找到这几个引脚在软件上的信号名称。我们需要打开资料包中的ELF 1开发板资料包\05-硬件资料\05-4 管脚分配表找到30、60、64引脚的信号名称。
可以看到连接器的30引脚信号名称为UART1_CTS_B;60引脚的信号名称为JTAG_MOD;64引脚的信号名称为GPIO1_IO00。 因为需要使用这几个引脚控制led,所以我们需要把它们复用成GPIO功能,在arch/arm/boot/dts/imx6ul-pinfunc.h中找到它们的宏定义,分别如下:
然后打开设备树文件arch/arm/boot/dts/imx6ull-elf1-emmc.dts,在&iomuxc节点下添加子节点pinctrl_leds0: pinctrl_leds0:leds0grp { fsl,pins = < MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x10b0 MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x10b0 MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0x10b0 >; }; 效果如下:
注意:在IOMUX配置环节,一定要确保一个引脚只被复用为一个功能,如果同一个引脚在其他地方被复用成另一个功能,很可能影响到我们期望的功能。 设备节点配置 在设备树中添加完IOMUX配置相关代码之后,接下来在设备树中添加供GPIO子系统使用的相关的配置。在根节点的backlight节点上边,添加子节点leds: leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_leds0 >; status = "okay"; led1{ lable = "led1"; gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; default-state = "off"; }; led2{ lable = "led2"; gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; default-state = "on"; }; led3{ lable = "led3"; gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; default-state = "on"; }; }; 注意:一定要在根节点下添加,效果如下:
leds的compatible属性值为“gpio-leds”,用于驱动匹配。 pinctrl-names属性值为“default”,定义了pincrtl的名字为“default” pinctrl-0的属性值为<&pinctrl_leds0>,就是引用了之前在IOMUX中定义的pinctrl_leds0也就是说,在此处对IOMUX的配置进行了引用,类似函数的调用。 status属性值设置为“okay”,表示LED设备可用。 接下来三个子节点,分别对应三个具体LED灯。 子节点的lable标签属性是可选的,可有可无。 gpios属性值指定了具体的GPIO引脚以及引脚的极性配置。 如: gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; 指定是GPIO1_IO18引脚,极性是GPIO_ACTIVE_LOW,就是指高电平点亮还是低电平点亮,需要根据具体电路配合使用。 default-state属性值设置了LED初始默认状态。 配置LED驱动编译进内核 首先使用ElfBoard的配置文件配置编译选项: elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ make imx6ull_elf1_defconfig 然后在源码根目录下使用make menuconfig命令,搜索LEDS_GPIO,看到LEDS_GPIO [=y]说明此驱动已经编译进内核: elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ make menuconfig
编译测试 编译内核和设备树: elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ ./build.sh 编译完成后,使用scp命令将编译生成的zImage和imx6ull-elf-emmc.dtb下载到ElfBoard的/run/media/mmcblk1p1路径下: elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ scp arch/arm/boot/zImage root\@172.16.0.175:/run/media/mmcblk1p1/ elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ scp arch/arm/boot/dts/imx6ull-elf1\-emmc.dtb root@172.16.0.175:/run/media/mmcblk1p1/
进行sync操作后重启开发板:
重启后可以看到开发板上的绿色和黄色LED为点亮状态。在设备树中led2和led3的default-state属性配置为on,所以这两个led默认是打开的状态。 接下来我们可以对这3个led进行控制: 一、查看节点,可以看到在/sys/class/leds下已经生成了我们配置的3个led root@ELF1:~# ls /sys/class/leds/ led1 led2 led3 mmc0:: mmc1::
二、控制LED1亮 root@ELF1:~# echo 1 > /sys/class/leds/led1/brightness
三、控制LED1灭 root@ELF1:~# echo 0 > /sys/class/leds/led1/brightness
四、设置LED1为心跳灯 root@ELF1:~# cat /sys/class/leds/led1/trigger
默认led1的触发器为none,现在我们把它改为heartbeat,就可以实现心跳灯的效果。 root@ELF1:~# echo heartbeat > /sys/class/leds/led1/trigger |