MS-RTOS 设备健康监控 HM
本章将介绍 MS-RTOS 设备健康监控 HM 的实现。
设备健康监控实现
设备健康监控可以使用硬件看门狗或软件健康监控实现。
类型 | 介绍 |
---|---|
硬件看门狗 | 打开硬件看门狗设备的 APP 都需要周期性及时喂狗,否则 CPU 重启,主要用于提高系统的整体可靠性 |
软件健康监控 | 打开健康监控设备的 APP 都需要周期性及时喂狗,否则调用 BSP 自定义的异常处理逻辑(如重启应用),主要用于在 APP 卡死时能及时重启 APP |
硬件看门狗
msrtos_base_sdk/libmsrtos/src/driver/ms_drv_wdg.h
头文件定义了硬件看门狗驱动和应用规范:
// 喂狗 IO 命令
#define MS_WDG_CMD_FEED _MS_IO('d', 'f')
// 获得 dead line 时间
#define MS_WDG_CMD_GET_DEAD_LINE _MS_IOR('d', 'd', ms_tick_t)
// 硬件看门狗驱动
typedef struct {
// 启动硬件看门狗
void (*start)(void);
// 喂狗
void (*feed)(void);
// dead line 时间(tick 单位)
ms_tick_t dead_line;
} const ms_wdg_drv_t;
// 注册系统的硬件看门狗驱动
ms_err_t ms_wdg_drv_register(void);
// 创建硬件看门狗设备
ms_err_t ms_wdg_dev_register(const char *path, ms_wdg_drv_t *drv);
硬件看门狗驱动
// 启动硬件看门狗
static void __stm32_wdg_start(void)
{
// do something
}
// 喂狗
static void __stm32_wdg_feed(void)
{
// do something
}
// 硬件看门狗驱动
static ms_wdg_drv_t __stm32_wdg_drv = {
.start = __stm32_wdg_start,
.feed = __stm32_wdg_feed,
.dead_line = BSP_CFG_WDG_DEADLINE,
};
// 获得硬件看门狗驱动
ms_wdg_drv_t *stm32_wdg_drv(void)
{
return &__stm32_wdg_drv;
}
// 启动线程
static void boot_thread(ms_ptr_t arg)
{
/* ... */
// 注册系统的硬件看门狗驱动
ms_wdg_drv_register();
// 创建硬件看门狗设备
ms_wdg_dev_register("/dev/wdg", stm32_wdg_drv());
/* ... */
}
APP 使用硬件看门狗
#include <ms_rtos.h>
static int wdg_fd;
int main(int argc, char *argv[])
{
wdg_fd = ms_io_open("/dev/wdg", O_RDWR, 0666);
while (1) {
ms_io_ioctl(wdg_fd, MS_WDG_CMD_FEED, MS_NULL);
// do something
ms_io_ioctl(wdg_fd, MS_WDG_CMD_FEED, MS_NULL);
// do something
}
ms_io_close(wdg_fd);
return 0;
}
如果某个 APP 在打开看门狗后未及时喂狗,在 CPU 重启之前,会输出类似下面的语句:
Will reset by hardware watch dog! pid_set=0xe, feed_set=0xa!
其中 pid_set 记录打开硬件看门狗的进程 PID,每个 bit 位代表一个进程(根据进程号移位得到);feed_set 记录本周期已喂狗的进程。在这个示例中,可以看到,打开进程和喂狗进程不相等,PID 为 1、2、3 的进程打开了看门狗,而只有 PID 为 1、3 的进程在规定时间内喂狗,所以因为 PID 为 2 的进程未喂狗,导致系统重启。
软件健康监控
msrtos_base_sdk/libmsrtos/src/driver/ms_drv_hm.h
头文件定义了软件健康监控设备使用规范:
// 健康异常处理模式
typedef ms_uint8_t ms_hm_handle_mode_t;
// 记录到日志
#define MS_HM_HANDLE_MODE_LOG 0U
// 重启 APP
#define MS_HM_HANDLE_MODE_RESTART_APP 1U
// 杀死 APP
#define MS_HM_HANDLE_MODE_KILL_APP 2U
// 重启机器
#define MS_HM_HANDLE_MODE_REBOOT 3U
// 关机
#define MS_HM_HANDLE_MODE_SHUTDOWN 4U
// 喂狗 IO 命令
#define MS_HM_CMD_FEED _MS_IO('h', 'f')
// 获得 dead line 时间
#define MS_HM_CMD_GET_DEAD_LINE _MS_IOR('h', 'd', ms_tick_t)
// 设置 dead line 时间
#define MS_HM_CMD_SET_DEAD_LINE _MS_IOW('h', 'd', ms_tick_t)
// 获得健康异常时的处理模式
#define MS_HM_CMD_GET_HANDLE_MODE _MS_IOR('h', 'm', ms_hm_handle_mode_t)
// 设置健康异常时的处理模式
#define MS_HM_CMD_SET_HANDLE_MODE _MS_IOW('h', 'm', ms_hm_handle_mode_t)
// 注册软件健康监控驱动
ms_err_t ms_hm_drv_register(void);
// 注册软件健康监控设备
ms_err_t ms_hm_dev_register(const char *path);
BSP 自定义健康异常处理逻辑
// 响应健康监控的通知事件
void ms_bsp_hm_notify(ms_pid_t pid, ms_hm_handle_mode_t mode)
{
if (pid == MS_PID_KERN) {
ms_log_crash("Kernel is abnormal!\n");
ms_rtos_reboot();
} else {
char name[64];
ms_process_name(pid, name, sizeof(name));
ms_log_crash("Application %s is abnormal!\n", name);
switch (mode) {
case MS_HM_HANDLE_MODE_LOG:
break;
case MS_HM_HANDLE_MODE_RESTART_APP:
ms_process_kill(pid);
ms_thread_yield();
ms_app_start("ms-boot-param.dtb", name, MS_NULL);
break;
case MS_HM_HANDLE_MODE_KILL_APP:
ms_process_kill(pid);
break;
case MS_HM_HANDLE_MODE_REBOOT:
ms_rtos_reboot();
break;
case MS_HM_HANDLE_MODE_SHUTDOWN:
ms_rtos_shutdown();
break;
}
}
}
// 启动线程
static void boot_thread(ms_ptr_t arg)
{
/* ... */
// 注册软件健康监控驱动
ms_hm_drv_register();
// 注册软件健康监控设备
ms_hm_dev_register("/dev/hm");
/* ... */
}
APP 使用软件健康监控设备
#include <ms_rtos.h>
static int hm_fd;
int main(int argc, char *argv[])
{
hm_fd = ms_io_open("/dev/hm", O_RDWR, 0666);
// 设置截至时间为 5s
ms_io_ioctl(hm_fd, MS_HM_CMD_SET_DEAD_LINE, 5 * ms_time_get());
// 设置处理模式为重启 APP
ms_io_ioctl(hm_fd, MS_HM_CMD_SET_HANDLE_MODE, MS_HM_HANDLE_MODE_RESTART_APP);
while (1) {
ms_io_ioctl(hm_fd, MS_HM_CMD_FEED, MS_NULL);
// do something
ms_io_ioctl(hm_fd, MS_HM_CMD_FEED, MS_NULL);
// do something
}
ms_io_close(hm_fd);
return 0;
}
健康监控默认截至时间为 10s,处理模式为记录到日志。