如何在Linux设备树中定义由GPIO触发的板载电气继电器
方案1:使用内核原生GPIO继电器驱动(最匹配需求)
Linux 5.x内核自带gpio-relay专用平台驱动,匹配成功后会在/sys/class/relay/目录下生成独立的继电器控制节点,操作逻辑和你之前配置的GPIO LED完全一致,属于语义最匹配的实现方案。
对应的设备树配置结构如下,和你现有的LED配置格式几乎完全一致:
relay_controller { compatible = "gpio-relay"; relay1 { label = "relay1"; /* 替换为继电器实际连接的GPIO引脚定义,注意电平极性标识 */ gpios = <&gpio_bank pin_num GPIO_ACTIVE_HIGH>; /* 上电默认状态,可选值为on/off/keep,keep表示保持硬件上电默认电平 */ default-state = "off"; }; };
配置生效加载驱动后,可直接通过sysfs访问控制:
# ls /sys/class/relay/ relay1
控制时直接向/sys/class/relay/relay1/value节点写入0/1即可控制继电器断开/吸合,体感和操作LED没有区别。
注意:需要确保内核编译时开启了
CONFIG_GPIO_RELAY配置项,若该驱动被裁剪未加载,设备树的节点将无法匹配生成对应sysfs节点。
方案2:复用现有GPIO LED驱动(低改造成本备选)
如果当前内核没有启用gpio-relay驱动,也可以直接复用你已经验证可用的gpio-leds驱动完成继电器控制,只需要在现有的LED设备节点下增加对应配置即可:
led { compatible = "gpio-leds"; debug { label = "debug"; gpios = <&gpio_bank debug_led_pin GPIO_ACTIVE_HIGH>; default-state = "off"; }; /* 新增继电器节点 */ relay1 { label = "relay1"; gpios = <&gpio_bank relay_pin GPIO_ACTIVE_HIGH>; default-state = "off"; }; };
该配置生效后,会在/sys/class/leds/relay1路径下生成控制节点,通过写入brightness节点的值完成继电器控制。缺点是节点分类属于LED类,语义上不属于继电器设备范畴,仅适合临时验证场景使用。
方案3:通用GPIO sysfs控制
如果不需要专门的设备类节点,也可以通过GPIO hog配置把继电器对应的引脚声明为输出引脚,在/sys/class/gpio/路径下生成对应控制节点。但需要注意Linux 5.4之后内核已逐步废弃传统的gpio sysfs接口,新版本内核推荐使用GPIO字符设备的字符节点完成控制,sysfs节点需要额外打开CONFIG_GPIO_SYSFS配置才会生成,长期来看兼容性不如前两个方案。
配置注意事项
- 引脚极性匹配:如果硬件电路是低电平触发继电器吸合,需要将
gpios属性中的电平标识改为GPIO_ACTIVE_LOW,避免上电时GPIO电平不匹配导致继电器误动作。 - 默认状态安全:对于连接强电设备的继电器,建议将
default-state设为off,避免开发板上电瞬间触发继电器连接高风险负载。
内容的提问来源于stack exchange,提问作者Mr.Christer

