说明:本文记录stm32看门狗的多线程监控方法,线程是rtos中的称呼,这里可以理解为各个独立循环执行的中断。这里介绍的方法可以监控多个循环当某个循环死机、卡死时都可触发看门狗复位。
测试平台:STM32F334C8T6
#ifndef __IWDG_H__
#define __IWDG_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#define WDG_START_EN (1) // 看门狗:1 开启,0 关闭
#define IWDG_TICK uwTick // 看门狗时钟源,这里采用 stm32的全局定时变量,默认是 1 khz,即1ms数据 +1;
#define IWDG_REFRESH_TICK_TIME (400) // 看门狗喂狗间隔时间,单位 ms
// 定义需要监护的线程或中断
#define WDG_REF_HRTIM1 0
#define WDG_REF_TIME2 1
#define WDG_REF_TIME3 2
#define WDG_REF_COUNT 3
extern uint8_t iwdg_ref_d[WDG_REF_COUNT];
void MX_IWDG_Init(void);
void wdg_refresh(void);
#ifdef __cplusplus
}
#endif
#endif /* __IWDG_H__ */
//看门狗复位时间: Tout = (Prescaler * Reload) / LSIRC(看门狗时钟) = (4 * 4095)/40k = 409.5 ms
//使用说明:
//step1:调用 MX_IWDG_Init() 完成初始化;
//step2:在看门狗监护循环中调用看门狗监控喂狗函数 wdg_refresh() 注意调用间隔时间不要超过看门狗复位时间。
//step3:在各个需要喂狗的地方清零看门狗标志,如: iwdg_ref_d[WDG_REF_TIME2] = 0;
uint8_t iwdg_ref_d[WDG_REF_COUNT] = {0}; // 看门狗监护变量,需要监护几个地方(线程)在头文件处定义;
uint32_t iwdg_count = 0;
uint32_t wdg_refresh_Last_time = 0;
IWDG_HandleTypeDef hiwdg;
/* IWDG init function */
void MX_IWDG_Init(void)
{
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_8;
hiwdg.Init.Window = 4095;
hiwdg.Init.Reload = 4095;
if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
{
Error_Handler();
}
}
//看门狗喂狗
void wdg_refresh(void)
{
if (IWDG_TICK - wdg_refresh_Last_time > IWDG_REFRESH_TICK_TIME)
{
wdg_refresh_Last_time = IWDG_TICK;
uint8_t wdg_r = 0;
for (int var = 0; var < WDG_REF_COUNT; ++var) //检查监护线程的喂狗状态
{
wdg_r = iwdg_ref_d[var] + wdg_r;
}
if (wdg_r == 0) //如果每个线程都有喂狗,那 wdg_r 应该为 0
{
#if WDG_START_EN
HAL_IWDG_Refresh(&hiwdg); // 喂狗
#endif
for (int var = 0; var < WDG_REF_COUNT; ++var) // 初始化看门狗线程管理值
{
iwdg_ref_d[var] = 1;
}
++iwdg_count;
}
}
}