自定义 ARM Linux 开发板上的 LED 状态
大家都知道,目前世界上最火的
ARM Linux
开发板是树莓派(Raspberry Pi)
。得益于树莓派基金会几十年的细心打磨与苦心营造的社区环境,现在树莓派俨然成为了新手入门 Linux 的最佳选择。但是由于近些年行业产能降低,导致芯片价格居高不下,再加上国内某些商家恶意炒高价格,笔者于 2019 年首发 580 元购买的树莓派 4B 4G 版现在在市场上的价格高达 900 元。这一现象导致了不少开发者开始寻求其他树莓派替代品。
好吧,扯远了。进入正题吧。
起因
大家都知道,树莓派板子无论是哪一代,都配备了两颗 LED 灯来指示板子运行状态。红色的 LED 指示电源状态,而绿色 LED 则是在指示磁盘读写。而我手上的这块香橙派 Zero2,系统启动后只有绿色指示灯亮起,另外一颗红色 LED 则始终处于熄灭状态。
手动设置
先进入/sys/class/leds/red:power/
目录,查看brightness
:
cat brightness
# Output:
0
可以看到,当前亮度为 0,即关闭状态。手动打开之:
echo 1 | sudo tee brightness
可以看到板子上的红色 LED 亮起。 然后我们查看一下系统支持的触发器有哪些:
cat trigger
# Output:
[none] usb-gadget usb-host rfkill-any rfkill-none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock usbport mmc0 disk-activity disk-read disk-write ide-disk mtd nand-disk heartbeat cpu cpu0 cpu1 cpu2 cpu3 activity default-on panic mmc1 rc-feedback stmmac-0:01:link stmmac-0:01:1Gbps stmmac-0:01:100Mbps stmmac-0:01:10Mbps
可以看见,在 none 触发器的外面有一对方括号,表示当前选中。 由于笔者的板子 mmc 设备节点为/dev/mmcblk1
,所以这里选择 mmc1 触发器:
echo mmc1 | sudo tee trigger
随后可以看到板上的红色 LED 随机亮起,表示系统正在读写磁盘。
永久设置
虽然通过 sysfs 修改了 LED 触发器,但是该修改是一次性的,重启后就会被还原为 none。虽然可以通过自定义一个systemd
服务的方式来进行开机自动修改,但是在该服务启动之前 LED 的状态不会被改变。更重要的是,笔者更想搞清楚原理是什么。
大家都知道,Linux 系统通过设备树来获取系统总线上搭载的设备,并且根据它来匹配各类驱动程序。在x86
平台上,设备树由BIOS
生成,被称为ACPI table
;而在ARM
平台上,设备树由开发者手动编写,由 Bootloader(U-Boot 等等)加载到指定地址供系统使用,被称为Device Tree
(下文简称 DT)。
查看arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
,有这么一段代码:
leds {
compatible = "gpio-leds";
led-0 {
function = LED_FUNCTION_POWER;
color = <LED_COLOR_ID_RED>;
gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>;
/* PC12 */
};
led-1 {
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_GREEN>;
gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>;
/* PC13 */
default-state = "on";
};
};
可以看见,系统内的两颗 LED 都被定义于此,而红色 LED 被定义为 led-0。 经过查阅 Linux 内核文档,发现在相应的entry
下添加linux,default-trigger
property,即可设置触发器。于是编写mmc-led.dts
如下:
/dts-v1/; //指定DT版本为v1
/plugin/; //声明这是一个设备树插件
/ {
compatible = "allwinner,sun50i-h616"; //根compatible,用于匹配设备
fragment@0 {
target-path = "/leds/led-0"; //目标路径,我们要修改的是led-0的property
__overlay__ {
linux,default-trigger = "mmc1"; // 设置触发器为mmc1
};
};
};
编写完毕后,使用以下命令,应用之:
sudo orangepi-add-overlay mmc-led.dts
应用完毕后重启即可。