问题:如何实现多任务下,存在一个或者多个任务异常时,触发看门狗。
环境:STM32F407VET6,IWDG,FreeRTOS。
思路:任务内部进行对事件组操作,看门狗任务来维护事件组,当超过设定的最大喂狗时间还没有喂狗的话,程序会重启。
辅助代码:
typedef struct __BIT32
{
uint8_t bit0:1;
uint8_t bit1:1;
uint8_t bit2:1;
uint8_t bit3:1;
uint8_t bit4:1;
uint8_t bit5:1;
uint8_t bit6:1;
uint8_t bit7:1;
uint8_t bit8:1;
uint8_t bit9:1;
uint8_t bit10:1;
uint8_t bit11:1;
uint8_t bit12:1;
uint8_t bit13:1;
uint8_t bit14:1;
uint8_t bit15:1;
uint8_t bit16:1;
uint8_t bit17:1;
uint8_t bit18:1;
uint8_t bit19:1;
uint8_t bit20:1;
uint8_t bit21:1;
uint8_t bit22:1;
uint8_t bit23:1;
uint8_t bit24:1;
uint8_t bit25:1;
uint8_t bit26:1;
uint8_t bit27:1;
uint8_t bit28:1;
uint8_t bit29:1;
uint8_t bit30:1;
uint8_t bit31:1;
}BIT32;
typedef union __UINT32_BT
{
BIT32 Bit;
uint32_t uStatus;
}UINT32_BT;
// 事件
EventGroupHandle_t EventGroupHandler;
// 事件标志位
#define EVENTBIT0 (1 << 0)
#define EVENTBIT1 (1 << 1)
#define EVENTBIT2 (1 << 2)
#define EVENTBIT3 (1 << 3)
#define EVENTBIT4 (1 << 4)
#define EVENTBIT5 (1 << 5)
#define EVENTBIT6 (1 << 6)
#define EVENTBIT7 (1 << 7)
#define EVENTBIT8 (1 << 8)
#define EVENTBIT9 (1 << 9)
#define EVENTBIT10 (1 << 10)
#define EVENTBIT11 (1 << 11)
#define EVENTBIT12 (1 << 12)
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 256
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
EventGroupHandler = xEventGroupCreate(); // 创建事件组
__CreateOutputIoTask(); // 创建TASK1任务 需要看门狗监护
__CreateIwdgEventGroup(); // 创建看门狗任务 独立看门狗
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
void xSystemTaskCreate(void)
{
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4 抢占优先级0-15 响应优先级0
xSystemTaskCreate();//创建系统任务
}
看门狗任务:
/*任务优先级*/
#define IWDG_TASK_PRIO 3 // 该值越大优先级越高
/*任务堆栈大小*/
#define IWDG_STK_SIZE 128
/*任务句柄*/
TaskHandle_t IwdgTask_Handler;
/*任务函数*/
void IwdgTask(void *pvParameters);
void IwdgTask(void *pvParameters)
{
UINT32_BT EventBit32;
EventBit32.uStatus = 0;
//
// 需要增加独立看门狗初始化
// 例如: ST_IWDG_Init(4,400);
//
// 设置需要等待的事件 这里只等待一个事件 可以根据自己的实际情况来选择是否开启等待事件
EventBit32.Bit.bit1 = 1; // 任务1
//EventBit32.Bit.bit2 = 1; // 任务2
//EventBit32.Bit.bit3 = 1; // 任务3
//EventBit32.Bit.bit4 = 1; // 任务4
//EventBit32.Bit.bit5 = 1; // 任务5
//EventBit32.Bit.bit6 = 1; // 任务6
for(;;)
{
if(EventGroupHandler != NULL)
{
// 这里需要注意
// 因为 xEventGroupWaitBits采用的是等待所有事件,
// 所以xEventGroupWaitBits函数会阻塞等待所有事件都被xEventGroupSetBits()过。
xEventGroupWaitBits( (EventGroupHandle_t) EventGroupHandler,
( EventBits_t) (EventBit32.uStatus), // 需要等待的事件
( BaseType_t ) pdTRUE, // 等待后 清零
( BaseType_t ) pdTRUE, // 等待所有事件
( TickType_t ) portMAX_DELAY );
//
// 需要增加喂狗处理
// 例如: iwdgFeed(); // 所有线程运行正常 开始喂狗
//
}
vTaskDelay(100); //延时100ms,也就是100个时钟节拍
}
}
void __CreateIwdgEventGroup(void)
{
taskENTER_CRITICAL(); //关中断
xTaskCreate((TaskFunction_t )IwdgTask, //任务函数
(const char* )"IwdgTask", //任务名称
(uint16_t )IWDG_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )IWDG_TASK_PRIO, //任务优先级
(TaskHandle_t* )&IwdgTask_Handler); //任务句柄
taskEXIT_CRITICAL(); //开中断
}
需要监护的任务
任务1:
/*任务优先级*/
#define TASK1_PRIO 3 // 该值越大优先级越高
/*任务堆栈大小*/
#define TASK1_STK_SIZE 128
/*任务句柄*/
TaskHandle_t Task1_Handler;
/*任务函数*/
void Task1(void *pvParameters);
static void __SetEventGruopBit1(void)
{
if(EventGroupHandler != NULL)
{
// 设置事件组Bit1
xEventGroupSetBits(EventGroupHandler,EVENTBIT1);
}
}
void Task1(void *pvParameters)
{
for(;;)
{
__SetEventGruopBit1();// 设置事件组Bit1
vTaskDelay(50); //延时50ms,也就是50个时钟节拍
}
}
void __CreateOutputIoTask(void)
{
taskENTER_CRITICAL(); //关中断
xTaskCreate((TaskFunction_t )Task1, //任务函数
(const char* )"Task1", //任务名称
(uint16_t )TASK1_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )TASK1_PRIO, //任务优先级
(TaskHandle_t* )&Task1_Handler); //任务句柄
taskEXIT_CRITICAL(); //开中断
}