NXP

看门狗在嵌入式 Linux 中的应用

2019-07-12 13:34发布

By Toradex胡珊逢 1). 简介 在嵌入式领域中 Watchdog 看门狗通常被作为用于应对系统或者应用意外崩溃的有效手段。其可以在程序执行出错并无法恢复的情况下,自动重启应用甚至复位整个系统,从而使系统脱离宕机状态,恢复正常业务执行。这对于涉及到人身、财产安全的应用,显得极为重要。本文将基于NXP iMX6 嵌入式平台如何使用看门狗进行介绍,应对 Linux 系统或者应用程序意外崩溃。   本文所演示的iMX6平台来自于Toradex Colibri iMX6 计算机模块,iMX6芯片自带看门狗功能,其硬件和早期的 iMX2 一致,所以看门狗驱动仍然沿用 imx2-wdt。看门狗只支持单用户操作,即只能有一个实例来使用看门狗。因此在 Linux 系统中,用户可以选择由自己的应用直接使用看门狗,但只限于一个进程。看门狗只监控该应用,对于Linux 本身或者其他应用则无法在意外崩溃的情况下触发看门狗复位。或者使用 systemd (183以后的版本)来操作硬件看门狗,同时为用 systemd 所管理的单元提供软件逻辑看门狗。硬件看门狗主要应对 Linux 内核以及 systemd 自身的崩溃,软件逻辑看门狗则可以用于用户自己的应用,且不受数量限制。     2). 用户应用操作 ./ 首先在 U-Boot 中设置看门狗超时时间,这里设置为 60 秒。 ------------------------ setenv defargs $defargs imx2-wdt.timeout=60 saveenv ------------------------ ./ 编译完成后运行测试程序。 ------------------------ root@colibri-imx6:~# ./wdt-sample-app & [1] 627 ------------------------ ./ 终结该测试程序进程。当进程被终结后,看门狗仍旧保持运行,但是无法定时喂狗。因此,在60s 超时后,看门狗会复位系统。 ------------------------ root@colibri-imx6:~# kill 627 root@colibri-imx6:~# [ 45.964155] watchdog: watchdog0: watchdog did not stop!   [1]+ Terminated ./wdt-sample-app ------------------------ ./ 当模块由于看门狗复位时,可以从U-Boot 启动的串口日志发现复位的原因。 ------------------------ U-Boot 2016.11-2.8.5+g02735f4004 (Dec 28 2018 - 01:54:12 +0000) CPU: Freescale i.MX6DL rev1.1 at 792 MHz Reset cause: WDOG I2C: ready DRAM: 512 MiB ------------------------     3). Systemd 操作 a). 对于需要使用看门狗监控多个应用,可以使用 systemd 来操作。Systemd 提供硬件看门狗和软件看门狗支持。硬件看门狗用于监控 Linux 内核以及 systemd 自身的运行,一旦出现内核崩溃的情况,看门狗超时将触发系统复位。在 systemd 中使用硬件看门狗非常简单,只需要配置 /etc/systemd/system.conf 中的RuntimeWatchdogSec= 参数,将其设置超时时间即可。在规定时间如果没有喂狗,将触发复位。systemd 通常会在所设置时间的一半为间隔进行喂狗。ShutdownWatchdogSec= 则可以设置关机超时时间,如果系统在该时间内没有完成关机,也将系统复位。   ./ 为了触发内核崩溃的情况,我们需要开启内核调试的 MAGIC_SYSRQ 功能,该选项在 Toradex 默认的 Linux BSP 中是关闭的。打开后重新编译内核。 ------------------------ CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 CONFIG_DEBUG_KERNEL=y ------------------------ ./ 设置超时时间为60秒,RuntimeWatchdogSec=60。 启动查看系统日志,显示硬件看门狗超时时间被设置为1分钟。 ------------------------ root@colibri-imx6:/etc/systemd# dmesg|grep watchdog [ 3.137012] systemd[1]: Hardware watchdog 'imx2+ watchdog', version 0 [ 3.147564] systemd[1]: Set hardware watchdog to 1min. ------------------------ ./ 然后我们用下面命令触发内核崩溃。 ------------------------ echo c > /proc/sysrq-trigger ------------------------ ./ 一分钟以后,由于 systemd 没有对进行喂狗操作,系统将复位后重新启动。   b). 除了硬件看门狗外,sytemd 还提供软件看门狗,每个 systemd service 都可以使用。service 需要读取 WATCHDOG_USEC= 参数,确定看门狗超时时间,并在该时间范围内使用 sd_notify("WATCHDOG=1") 喂狗,同样喂狗的时间间隔为 WATCHDOG_USEC= 所设置的一半。   ./ 用户只要在对应的 systemd service 文件中设置 WatchdogSec= 参数即可,而 WATCHDOG_USEC= 将根据前面的参数自动被设置。在应用程序中以 WatchdogSec/2 的间隔调用 sd_notify 函数发送 "WATCHDOG=1"进行喂狗操作。例如 ------------------------ // Systemd servier 文件(/etc/systemd/system/test.service),用于启动用户应用 [Unit] Description=Watchdog Test service   [Service] ExecStart=/home/root/wdt-sw-test WatchdogSec=30s Restart=on-failure StartLimitInterval=5min StartLimitBurst=4 StartLimitAction=reboot   [Install] WantedBy=multi-user.target ------------------------   ./ 用户应用 wdt-sw-test.c,并定期执行喂狗操作(编译的时候需要使用 -lsystemd 链接 systemd 库文件)。 在应用初始化后需要通知 systemd 管理器本应用正常启动,sd_notify (0, "READY=1");。然后根据 WATCHDOG_USEC 变量设置喂狗间隔。在应用中我们将模拟一次超时喂狗,从而引起应用重启。   ./ 下面是运行日志。起初应用程序 wdt-sw-test 由 systemd 加载启动,PID=396,并以15s间隔喂狗(该时间源自WatchdogSec=30s)。当喂狗超时后,systemd 会发送信号 SIGABRT 终止该进程,并重启该应用,新 PID=647。 image001.png​ ./ 在 service 文件中,我们还配置了 StartLimitBurst 和 StartLimitInterval 以及 StartLimitAction 参数。这使得在 StartLimitInterval 时间内应用启动次数超过 StartLimitBurst 后,将不被允许再次启动,并触发 StartLimitAction 的操作。具体描述请参考 systemd.unit。     3). 总结 看门狗对于关键应用,以及大多数的一般应用来讲是一个很重要的功能,其能够应对 Linux系统或者应用崩溃的情况,避免用户设备处于失控的状态。当整个系统只有一个嵌入式设备作为决策控制单元时,对于关键的安全应用,根据单一故障准则,我们还建议引入辅助控制单元,例如额外的 MCU 等做同步监测,或者使用保险丝、热电偶等,当出现超限情况,能够执行紧急操作,从而进一步提高设备的安全性。