![由于设备树而加载模块后运行脚本](https://linux22.com/image/151876/%E7%94%B1%E4%BA%8E%E8%AE%BE%E5%A4%87%E6%A0%91%E8%80%8C%E5%8A%A0%E8%BD%BD%E6%A8%A1%E5%9D%97%E5%90%8E%E8%BF%90%E8%A1%8C%E8%84%9A%E6%9C%AC.png)
我为什么要这个?
我使用 pwm-ir-tx 内核模块从嵌入式设备发送红外信号。然而,当pwm内核模块在引导过程中加载时,该引脚处于高电平。我需要大约 10 秒左右的时间才能用 lirc irsend 信号将其设置为低电平。如果 IR-LED 仅用于 PWM 模式而不是永久开启,原则上您可以“过载”IR-LED 以使其更亮。然而,启动过程中的 10 秒破坏了这一策略。
到目前为止我的系统在做什么(例如正在运行的内容、DT-Overlay 文件等)?
我使用 Armbian 并修改了主线内核中的 pwm-ir-tx 驱动程序,以便保证发送后的状态为低(将占空比设置为 0,当只是禁用设备上的 pwm 通道时,它是随机的 1 或 0 )。
我正在使用设备树覆盖层来激活 pwm 和 pwm-ir-tx。
/dts-v1/;
/plugin/;
/ {
compatible = "allwinner,sun4i-a10";
fragment@0 {
target = <&pwm>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_pin>, <&pwm1_pin>;
status = "okay";
};
};
fragment@1 {
target-path = "/";
__overlay__ {
pwm-ir-transmitter {
compatible = "pwm-ir-tx";
pwms = <&pwm 0 0 0>;
};
};
};
};
当我启动时,pwm-sun4i 模块和 pwm-ir-tx 被加载,并且 /dev/lircx 字符设备可供使用。为了关闭 LED,我使用单元条目“After=lircd.service”启用了 systemd 服务“lircd-out”,这会关闭 LED,但它会在启动过程后运行大约 10 秒。
将 DT Overlay 中的模块设置为“禁用”并随后使用 modprobe 加载它们不起作用(不在 sysfs 中创建 pwm 或 rc 设备,或 /dev/lircx 字符设备)。也许因为这些模块是内置的(即在 .config 文件中配置为“Y”,而不是“M”),但我必须承认我的理解仍然有点模糊。
什么是理想的?
能够控制 pwm-sun4i 和 pwm-ir-tx 模块的加载,从而能够在加载 pwm-sun4i 后运行脚本,将 pwm 引脚设置为低电平,然后加载 pwm-ir-tx。但正如我提到的,当我手动加载这些模块时,sysfs 无法访问它们。
或者,我可以将fragment@0 中的参数传递给pwm,将其设置为低。但我不知道如何实现,也没有在 pwm-sun4i.c 的代码中看到任何允许这样做的内容。我不想修改内核源代码以保持其与更新兼容。
有什么建议么?
答案1
创建一个 udev 规则来匹配它。
不必“在加载模块后”运行脚本 - 它处理特定设备,因此最好“在检测到设备后”运行它。没关系如何检测到该设备;只要内核将其报告为“新”设备,它就可以工作。
也就是说,模块就像设备一样存在于 /sys 中,这意味着它们也可以触发 udev 规则,甚至为它们生成 systemd .device 单元。
例如,要在 pwm-sun4i 加载后立即触发服务,请使用以下 udev 规则:
ACTION=="add", SUBSYSTEM=="module", KERNEL=="pwl-sun4i", \
TAG+="systemd", ENV{SYSTEMD_WANTS}+="fixup-pwl.service"
要运行简单的一次性命令:
ACTION=="add", SUBSYSTEM=="module", KERNEL=="pwl-sun4i", RUN+="/etc/fix-pwl.sh"