/** * @file ci110x_task_monitor.c * @brief 系统监控组件 * * 负责监视控制加入监控队列里的每一个任务,以防有任务出现异常情况, * 避免因异常未及时处理而造成的损失。 * * @version 0.1 * @date 2019-04-02 * * @copyright Copyright (c) 2019 Chipintelli Technology Co., Ltd. * */ #include "ci110x_task_monitor.h" /*监控任务的个数,最大为23*/ #define MONITOR_TAST_MAX_COUNT (23)/* 范围:0 - 23 根据实际情况合理设置*/ /*监控周期(单位:MS)*/ #define MONITOR_PERIOD (1000) typedef struct { uint8_t state; uint8_t id; uint8_t flag; uint8_t priority; uint32_t time; uint32_t last_time; TaskHandle_t handle; }monitor_t; static monitor_t join_monitor_list[MONITOR_TAST_MAX_COUNT]; static uint8_t join_monitor_count = 0; static EventGroupHandle_t eventgroup = NULL; typedef void (*func)(void); func iwdg_callback = NULL; /** * @brief 监控事件组创建函数 * * @param call_back 系统异常复位前的回调函数 */ void monitor_creat(void (*call_back)(void)) { /*创建事件标志组*/ eventgroup = xEventGroupCreate(); if(NULL == eventgroup) { /*事件标志组创建失败*/ ci_logdebug(LOG_SYS_MONITOR,"xEventGroupCreate Failed "); } ci_logdebug(LOG_SYS_MONITOR,"xEventGroupCreate Success "); iwdg_callback = call_back; } /** * @brief 任务加入监控队列 * * @param id 分配给任务的监控ID * @param time_ms 每次上报运行状态的最大时间间隔 * @param handle 任务句柄(用来调节任务优先级) */ void join_monitor(uint8_t* id,uint32_t time_ms, TaskHandle_t handle) { if(join_monitor_count > MONITOR_TAST_MAX_COUNT) { ci_logdebug(LOG_SYS_MONITOR,"已经达到监控任务的最大个数. "); CI_ASSERT(0,"已经达到监控任务的最大个数. "); } for(int i = 0;i < join_monitor_count;i++) { if(0 == join_monitor_list[i].state) { *id = join_monitor_list[i].id; join_monitor_list[i].state = 1; join_monitor_list[i].flag = 0; join_monitor_list[i].time = time_ms; join_monitor_list[i].handle = handle; return; } } /*给加入监控的任务编号,对应事件组的某个bit*/ *id = join_monitor_count; /* 保存任务属性 */ join_monitor_list[join_monitor_count].state = 1; join_monitor_list[join_monitor_count].flag = 0; join_monitor_list[join_monitor_count].id = join_monitor_count; join_monitor_list[join_monitor_count].time = time_ms; join_monitor_list[join_monitor_count].handle = handle; /*准备下个加入监控任务的编号*/ join_monitor_count++; ci_logdebug(LOG_SYS_MONITOR,"已经监控 %d 个任务. ",join_monitor_count); } /** * @brief 任务退出监控队列 * * @param id 分配给任务的监控ID */ void exit_monitor(uint8_t id) { join_monitor_list[id].state = 0; } /** * @brief 被监控任务状态上报函数 * * @param id 任务的监控ID */ void task_alive(uint8_t id) { xEventGroupSetBits(eventgroup, (0x1 << id)); } /** * @brief 监控任务函数 * * @param pvparameters 任务参数 */ void task_monitor(void *pvparameters) { /* 计算事件组的所有有效位 */ uint32_t bit_all; EventBits_t bit_rev; /* 打开IWDG的时钟 */ Scu_SetDeviceGate(HAL_IWDG_BASE,ENABLE); /* 打开IWDG的复位配置 */ Scu_Iwdg_RstSys_Config(); /* 配置IWDG并启动 */ iwdg_init_t init; init.irq = iwdg_irqen_enable; init.res = iwdg_resen_enable; init.count = (2 * MONITOR_PERIOD) * ((get_ipcore_clk()/0x10)/1000); iwdg_init(IWDG,init); iwdg_open(IWDG); ci_logdebug(LOG_SYS_MONITOR,"IWDG init ok. "); for(;;) { bit_all = (uint32_t)pow(2,join_monitor_count + 1) - 1; /* 等待所有任务发来事件标志 */ bit_rev = xEventGroupWaitBits(eventgroup,/* 事件标志组句柄 */ bit_all,/* 等待TASK_BIT_ALL被设置 */ pdTRUE,/* 退出前TASK_BIT_ALL被清除*/ pdTRUE,/* 等待TASK_BIT_ALL都被设置*/ pdMS_TO_TICKS(MONITOR_PERIOD));/* 等待延迟时间 */ xEventGroupClearBits(eventgroup,bit_all); /*监控任务正常,喂狗*/ iwdg_feed(IWDG); ci_logdebug(LOG_SYS_MONITOR,"IWDG feed ok. "); /* 判断任务是否正常喂狗 */ for (int i = 0; i < join_monitor_count; i++) { if(join_monitor_list[i].state) { /* 该bit有没有被设置 */ if((bit_rev & (0x1 << join_monitor_list[i].id)) != (0x1 << join_monitor_list[i].id)) { join_monitor_list[i].last_time += MONITOR_PERIOD; if(join_monitor_list[i].last_time >= join_monitor_list[i].time) { ci_logdebug(LOG_SYS_MONITOR,"task flag is :%d ",join_monitor_list[i].flag); if(join_monitor_list[i].flag == 0) { ci_logdebug(LOG_SYS_MONITOR,"task id is :%d ",join_monitor_list[i].id); if(join_monitor_list[i].handle != NULL) { ci_logdebug(LOG_SYS_MONITOR,"调整任务优先级 "); /*存储任务优先级*/ join_monitor_list[i].priority = uxTaskPriorityGet(join_monitor_list[i].handle); if(configMAX_PRIORITIES >= (join_monitor_list[i].priority + 1)) { /*临时修改任务优先级*/ vTaskPrioritySet(join_monitor_list[i].handle,join_monitor_list[i].priority + 1); } } ci_logdebug(LOG_SYS_MONITOR,"task handle is :0x%x ",join_monitor_list[i].handle ); join_monitor_list[i].last_time = 0; join_monitor_list[i].flag = 1; } else { ci_loginfo(LOG_SYS_MONITOR,"task id is :%d ",join_monitor_list[i].id); if(NULL != iwdg_callback) { iwdg_callback(); } ci_loginfo(LOG_SYS_MONITOR,"系统复位 "); //FIXME:防止打印未完成而复位 ci_loginfo(LOG_SYS_MONITOR, "---------------------------------- "); ci_loginfo(LOG_SYS_MONITOR, "---------------------------------- "); ci_loginfo(LOG_SYS_MONITOR, "---------------------------------- "); ci_loginfo(LOG_SYS_MONITOR, "---------------------------------- "); ci_loginfo(LOG_SYS_MONITOR, "---------------------------------- "); ci_loginfo(LOG_SYS_MONITOR, "---------------------------------- "); /* 任务死掉,复位系统 */ Scu_SoftwareRst_System(); while(1); } } } else { ci_logdebug(LOG_SYS_MONITOR,"%d:该bit已经被设置 ",join_monitor_list[i].id); join_monitor_list[i].last_time = 0; if(join_monitor_list[i].flag == 1) { ci_logdebug(LOG_SYS_MONITOR,"task id is :%d ",join_monitor_list[i].id); if(join_monitor_list[i].handle) { ci_logdebug(LOG_SYS_MONITOR,"还原任务优先级 "); /*还原任务优先级*/ vTaskPrioritySet(join_monitor_list[i].handle, join_monitor_list[i].priority); } join_monitor_list[i].flag = 0; } } } } } }