MS-RTOS 设备健康监控 HM

更新时间:
2023-11-30
下载文档

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,处理模式为记录到日志。

文档内容是否对您有所帮助?
有帮助
没帮助