STM32F7xx —— 看门狗
看门狗:指定时间内不喂狗,就重启系统。
最简单的看门狗设计(喂狗就是指定时间内给寄存器写一个固定值)
// 初始化独立看门狗
// prer:分频数:0~7(只有低 3 位有效!)
// rlr:自动重装载值,0~0XFFF.
// 分频因子=4*2^prer.但最大值只能是 256!
// rlr:重装载寄存器值:低 11 位有效.
// 时间计算(大概):Tout=((4*2^prer)*rlr)/32 (ms).
static IWDG_HandleTypeDef iwdg_handle;
void WatchdogInit(void)
{iwdg_handle.Instance = IWDG;iwdg_handle.Init.Prescaler = 5;iwdg_handle.Init.Reload = 250;iwdg_handle.Init.Window = IWDG_WINDOW_DISABLE; // 关闭窗口功能HAL_IWDG_Init(&iwdg_handle);os_watchdog_lock = xSemaphoreCreateMutex();
}void WatchdogFeed(void)
{HAL_IWDG_Refresh(&iwdg_handle);
}
FreeRTOS看门狗设计(系统看门狗+任务看门狗)(其他操作系统也可以用这种思路)
任务看门狗:监控每个任务的活动状态,如果任务卡死,会导致系统重启。核心思想是使用计数,计数减为0后说明任务卡死。
TaskHandle_t os_watchdog_handle;// 互斥信号量
static SemaphoreHandle_t os_watchdog_lock;
#define WATCHDOG_LOCK() xSemaphoreTake(os_watchdog_lock, 100);
#define WATCHDOG_UNLOCK() xSemaphoreGive(os_watchdog_lock)#define WATCHDOG_CHECK_INTERVAL 100 // 100ms喂一次狗
#define WATCHDOG_POOL_SIZE (OS_PRIO_MAX + OS_PRIO_MAX - 1) // 任务池 2倍的任务-1typedef struct
{TaskHandle_t handle; // 任务句柄const char *name; // 任务看门狗名称uint16_t timeout; // 任务看门狗超时uint16_t time; // 任务看门狗计数uint8_t suspended; // 任务看门狗暂停
} watchdog_t;static watchdog_t watchdogs[WATCHDOG_POOL_SIZE];static void task_watchdog(void *params)
{int i;while(1){WatchdogFeed();for(i = 0; i < WATCHDOG_POOL_SIZE; ++i){if(0 == watchdogs[i].handle){continue;}if(!watchdogs[i].suspended && watchdogs[i].time){--(watchdogs[i].time);}if(!watchdogs[i].suspended && (0 == watchdogs[i].time)){printf("!!!!!!!!!!!!!!!! Watchdog %s timeout !!!!!!!!!!!!!!!!\n", watchdogs[i].name);while(1); // reset}}vTaskDelay(WATCHDOG_CHECK_INTERVAL);}
}// 初始化独立看门狗
// prer:分频数:0~7(只有低 3 位有效!)
// rlr:自动重装载值,0~0XFFF.
// 分频因子=4*2^prer.但最大值只能是 256!
// rlr:重装载寄存器值:低 11 位有效.
// 时间计算(大概):Tout=((4*2^prer)*rlr)/32 (ms).
static IWDG_HandleTypeDef iwdg_handle;
void WatchdogInit(void)
{iwdg_handle.Instance = IWDG;iwdg_handle.Init.Prescaler = 5;iwdg_handle.Init.Reload = 250;iwdg_handle.Init.Window = IWDG_WINDOW_DISABLE; // 关闭窗口功能HAL_IWDG_Init(&iwdg_handle);os_watchdog_lock = xSemaphoreCreateMutex();xTaskCreate((TaskFunction_t)task_watchdog,(const char* )"task_watchdog",(uint16_t )OS_WATCHDOG_STK_SIZE,(void* )NULL,(UBaseType_t )OS_PRIO_WATCHDOG,(TaskHandle_t* )&os_watchdog_handle);
}void WatchdogFeed(void)
{HAL_IWDG_Refresh(&iwdg_handle);
}//===============================================================================================================
// 任务看门狗注册
void WatchdogRegister(const char *name, uint16_t timeout)
{int i;TaskHandle_t handle = xTaskGetCurrentTaskHandle();WATCHDOG_LOCK();for(i = 0; i < WATCHDOG_POOL_SIZE; ++i){if (handle == watchdogs[i].handle){WATCHDOG_UNLOCK();return;}}for(i = 0; i < WATCHDOG_POOL_SIZE; ++i){if (0 == watchdogs[i].handle){watchdogs[i].handle = handle;watchdogs[i].name = name;watchdogs[i].timeout = (timeout + WATCHDOG_CHECK_INTERVAL - 1) / WATCHDOG_CHECK_INTERVAL;watchdogs[i].time = watchdogs[i].timeout;watchdogs[i].suspended = 0;break;}}WATCHDOG_UNLOCK();
}// 任务看门狗喂狗
void WatchdogKick(void)
{int i;TaskHandle_t handle = xTaskGetCurrentTaskHandle();for(i = 0; i < WATCHDOG_POOL_SIZE; ++i){if (handle == watchdogs[i].handle){WATCHDOG_LOCK();watchdogs[i].time = watchdogs[i].timeout;WATCHDOG_UNLOCK();break;}}
}// 任务看门狗暂停
void WatchdogSuspend(void)
{int i;TaskHandle_t handle = xTaskGetCurrentTaskHandle();for(i = 0; i < WATCHDOG_POOL_SIZE; ++i){if (handle == watchdogs[i].handle){WATCHDOG_LOCK();watchdogs[i].suspended = 1;WATCHDOG_UNLOCK();break;}}
}// 任务看门狗恢复
void WatchdogResume(void)
{int i;TaskHandle_t handle = xTaskGetCurrentTaskHandle();for(i = 0; i < WATCHDOG_POOL_SIZE; ++i){if (handle == watchdogs[i].handle){WATCHDOG_LOCK();watchdogs[i].time = watchdogs[i].timeout;watchdogs[i].suspended = 0;WATCHDOG_UNLOCK();break;}}
}