概述
SDK内置组件系统监控是系统内尤为重要的一个组件,它负责监视控制加入监控队列里的每一个任务,以防有任务出现异常情况,避免因异常未及时处理而造成的损失。本组件以硬件看门狗为基础,在此基础之上实现了对多个任务同时进行监控的监控策略,以此来保证系统正常稳定的运行。
该组件源代码包括ci110x_task_monitor.c、ci110x_task_monitor.h、ci110x_task_monitor_test.c三个文件组成,其中ci110x_task_monitor.c、ci110x_task_monitor.h我们已经实现了相关监控策略和外部调用接口,ci110x_task_monitor_test.c中是一份示例代码告诉使用者如何加入监控队列,如何实时对任务进行监控。
ci110x_task_monitor.c
1 /** 2 * @file ci110x_task_monitor.c 3 * @brief 系统监控组件 4 * 5 * 负责监视控制加入监控队列里的每一个任务,以防有任务出现异常情况, 6 * 避免因异常未及时处理而造成的损失。 7 * 8 * @version 0.1 9 * @date 2019-04-02 10 * 11 * @copyright Copyright (c) 2019 Chipintelli Technology Co., Ltd. 12 * 13 */ 14 15 #include "ci110x_task_monitor.h" 16 17 /*调节任务优先级开关*/ 18 #define ADJUST_TASK_PRIORITY_EN (1) 19 /*监控任务的个数,最大为23*/ 20 #define MONITOR_TAST_MAX_COUNT (23)/* 范围:0 - 23 根据实际情况合理设置*/ 21 /*监控周期(单位:MS)*/ 22 #define MONITOR_PERIOD (1000) 23 24 typedef struct 25 { 26 uint8_t id; 27 uint8_t flg; 28 uint8_t priority; 29 uint32_t time; 30 uint32_t last_time; 31 #if ADJUST_TASK_PRIORITY_EN 32 TaskHandle_t handle; 33 #endif 34 }monitor_t; 35 36 static monitor_t monitor_list[MONITOR_TAST_MAX_COUNT]; 37 static EventGroupHandle_t eventgroup = NULL; 38 static uint8_t monitor_count = 0; 39 40 typedef void (*func)(void); 41 func iwdg_callback = NULL; 42 43 /** 44 * @brief 监控事件组创建函数 45 * 46 * @param call_back 系统异常复位前的回调函数 47 */ 48 void monitor_creat(void (*call_back)(void)) 49 { 50 /*创建事件标志组*/ 51 eventgroup = xEventGroupCreate(); 52 if(NULL == eventgroup) 53 { 54 /*事件标志组创建失败*/ 55 ci_logdebug(LOG_USER,"xEventGroupCreate Failed "); 56 } 57 ci_logdebug(LOG_USER,"xEventGroupCreate Success "); 58 iwdg_callback = call_back; 59 } 60 61 /** 62 * @brief 任务加入监控队列 63 * 64 * @param id 分配给任务的监控ID 65 * @param time_ms 每次上报运行状态的最大时间间隔 66 * @param handle 任务句柄(用来调节任务优先级) 67 */ 68 void join_monitor(uint8_t* id,uint32_t time_ms, TaskHandle_t handle) 69 { 70 if(monitor_count > MONITOR_TAST_MAX_COUNT) 71 { 72 ci_logdebug(LOG_USER,"已经达到监控任务的最大个数. "); 73 } 74 /*给加入监控的任务编号,对应事件组的某个bit*/ 75 *id = monitor_count; 76 /* 保存任务属性 */ 77 monitor_list[monitor_count].id = monitor_count; 78 monitor_list[monitor_count].time = time_ms; 79 #if ADJUST_TASK_PRIORITY_EN 80 monitor_list[monitor_count].handle = handle; 81 #endif 82 /*准备下个加入监控任务的编号*/ 83 monitor_count++; 84 ci_logdebug(LOG_USER,"已经监控 %d 个任务. ",monitor_count); 85 } 86 87 /** 88 * @brief 被监控任务状态上报函数 89 * 90 * @param id 任务的监控ID 91 */ 92 void task_alive(uint8_t id) 93 { 94 xEventGroupSetBits(eventgroup, (0x1 << id)); 95 } 96 97 /** 98 * @brief 监控任务函数 99 * 100 * @param pvparameters 任务参数 101 */ 102 void task_monitor(void *pvparameters) 103 { 104 /* 计算事件组的所有有效位 */ 105 uint32_t bit_all = (uint32_t)pow(2,monitor_count + 1) - 1; 106 EventBits_t bit_rev; 107 108 /* 打开IWDG的复位配置 */ 109 Scu_Iwdg_RstSys_Config(); 110 /* 配置IWDG并启动 */ 111 iwdg_init_t init; 112 init.irq = iwdg_irqen_enable; 113 init.res = iwdg_resen_enable; 114 init.count = (MONITOR_PERIOD + 500) * (get_apb_clk()/1000); 115 iwdg_init(IWDG,init); 116 iwdg_open(IWDG); 117 ci_logdebug(LOG_USER,"IWDG init ok. "); 118 119 for(;;) 120 { 121 /* 等待所有任务发来事件标志 */ 122 bit_rev = xEventGroupWaitBits(eventgroup,/* 事件标志组句柄 */ 123 bit_all,/* 等待TASK_BIT_ALL被设置 */ 124 pdTRUE,/* 退出前TASK_BIT_ALL被清除*/ 125 pdTRUE,/* 等待TASK_BIT_ALL都被设置*/ 126 pdMS_TO_TICKS(MONITOR_PERIOD));/* 等待延迟时间 */ 127 xEventGroupClearBits(eventgroup,bit_all); 128 /*监控任务正常,喂狗*/ 129 iwdg_feed(IWDG); 130 ci_logdebug(LOG_USER,"IWDG feed ok. "); 131 /* 判断任务是否正常喂狗 */ 132 for (int i = 0; i < monitor_count; i++) 133 { 134 /* 该bit有没有被设置 */ 135 if((bit_rev & (0x1 << monitor_list[i].id)) != (0x1 << monitor_list[i].id)) 136 { 137 monitor_list[i].last_time += MONITOR_PERIOD; 138 if(monitor_list[i].last_time >= monitor_list[i].time) 139 { 140 if(monitor_list[i].flg == 0) 141 { 142 ci_logdebug(LOG_USER,"task id is :%d ",monitor_list[i].id); 143 #if ADJUST_TASK_PRIORITY_EN 144 ci_logdebug(LOG_USER,"调整任务优先级 "); 145 /*存储任务优先级*/ 146 monitor_list[i].priority = uxTaskPriorityGet(monitor_list[i].handle); 147 if(configMAX_PRIORITIES >= (monitor_list[i].priority + 1)) 148 { 149 /*临时修改任务优先级*/ 150 vTaskPrioritySet(monitor_list[i].handle,monitor_list[i].priority + 1); 151 #endif 152 } 153 monitor_list[i].flg = 1; 154 } 155 else 156 { 157 ci_logdebug(LOG_USER,"task id is :%d ",monitor_list[i].id); 158 if(NULL != iwdg_callback) 159 { 160 iwdg_callback(); 161 } 162 ci_logdebug(LOG_USER,"系统复位 "); 163 /* 任务死掉,复位系统 */ 164 Scu_SoftwareRst_System(); 165 while(1); 166 } 167 } 168 } 169 else 170 { 171 ci_logdebug(LOG_USER,"%d:该bit以及被设置 ",monitor_list[i].id); 172 monitor_list[i].last_time = 0; 173 if(monitor_list[i].flg == 1) 174 { 175 ci_logdebug(LOG_USER,"task id is :%d ",monitor_list[i].id); 176 #if ADJUST_TASK_PRIORITY_EN 177 ci_logdebug(LOG_USER,"还原任务优先级 "); 178 /*还原任务优先级*/ 179 vTaskPrioritySet(monitor_list[i].handle, monitor_list[i].priority); 180 #endif 181 monitor_list[i].flg = 0; 182 } 183 } 184 } 185 } 186 }
ci110x_task_monitor.h
/** * @file ci110x_task_monitor.h * @brief 系统监控组件 * * 负责监视控制加入监控队列里的每一个任务,以防有任务出现异常情况, * 避免因异常未及时处理而造成的损失。 * * @version 0.1 * @date 2019-04-02 * * @copyright Copyright (c) 2019 Chipintelli Technology Co., Ltd. * */ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "ci110x_iwdg.h" #include "ci110x_scu.h" #include "sdk_default_config.h" #include "ci_log.h" #include <math.h> /** * @addtogroup sys_monitor * @{ */ #ifdef __cplusplus extern "C" { #endif void monitor_creat(void (*call_back)(void)); void join_monitor(uint8_t* id,uint32_t time_ms, TaskHandle_t handle); void task_alive(uint8_t id); void task_monitor(void *pvparameters); #ifdef __cplusplus } #endif /** * @} */
-
相关宏配置说明如下:
/*调节任务优先级开关*/
-
相关API接口如下:
函数 | 描述 |
---|---|
monitor_creat | 监控事件组创建函数 |
join_monitor | 任务加入监控函数 |
task_alive | 被监控任务上报函数 |
task_monitor | 监控任务函数 |
使用示例:
#include "ci110x_task_monitor.h" uint8_t vTask_test1_id,vTask_test2_id,vTask_test3_id; void vTask_test1(void *pvParameters) { int count = 0; for(;;) { vTaskDelay(pdMS_TO_TICKS(500)); count++; task_alive(vTask_test1_id); } } void vTask_test2(void *pvParameters) { int count = 0; for(;;) { vTaskDelay(pdMS_TO_TICKS(4000)); count++; task_alive(vTask_test2_id); } } void vTask_test3(void *pvParameters) { int count = 0; for(;;) { vTaskDelay(pdMS_TO_TICKS(12000)); count++; task_alive(vTask_test3_id); } } void call_back(void) { mprintf("call back func "); } void iwdg_test(void) { monitor_creat(call_back); TaskHandle_t task1_handle = NULL,task2_handle = NULL,task3_handle = NULL; xTaskCreate(vTask_test1,"vTask_test1",256,NULL,1,&task1_handle); join_monitor(&vTask_test1_id,1000,task1_handle); xTaskCreate(vTask_test2,"vTask_test2",256,NULL,2,&task2_handle); join_monitor(&vTask_test2_id,5000,task2_handle); xTaskCreate(vTask_test3,"vTask_test3",256,NULL,3,&task3_handle); join_monitor(&vTask_test3_id,10000,task3_handle); xTaskCreate(task_monitor,"task_monitor",256,NULL,4,NULL); }
常见问题