前言
在一些设备需要长时间稳定运行的场合中,看门狗功能可以说是必不可少的。但在一些低功耗设备中,硬件看门狗的启用又会增大设备的功耗。在实际的项目开发中,是否需要启用看门狗需要根据实际需求而定。大部分的MCU都带有看门狗计数器,HC32F460内置就有两个看门狗计数器,分别为专用的看门狗计数器(SWDT)和通用的看门狗计数器(WDT)。今天,我们主要就HC32F460来讲解下看门狗功能的使用。
一、看门狗是什么?
看门狗,又叫watchdog timer,是一个硬件计时电路,一般用来监测由软件故障导致的系统故障。在看门狗启动后,硬件计数器会开始计时,当计数溢出时,则会产生看门狗复位,使得MCU复位。在看门狗计数期间(产生看门狗复位信号之前),我们需要定时去刷新计数器(也就是我们常说的喂狗)。若是程序出现未知的逻辑错误导致程序跑飞或进入死循环,在设定的时间内没有及时喂狗,则会发生看门狗超时复位。因此,看门狗功能可以针对程序因一些潜在错误或外界恶劣环境等干扰导致的系统死机,在无人工干预情况下自动恢复系统工作状态。
二、看门狗的使用
在了解了看门狗的概念和功能后,下面还是一样,我们需要回到HC32F460的芯片用户手册,结合官方的DEMO来了解HC32F460看门狗功能的使用。
1.简介
首先是关于看门狗的简介,HC32F460有两个看门狗计数器,一种是计数时钟源为专用内部 RC(SWDTLRC:10KHz)的专用看门狗计数器(SWDT),另一种是计数时钟源为 PCLK3 的通用看门狗计数器(WDT)。这两种计数器的主要区别如下:
下面主要介绍SWDT的使用方法。
2.启动
从上面的表格中我们可以得知,看门狗的启动方式有两种,一种是硬件启动,一种是软件启动。SWDT专用看门狗计数器只支持硬件启动方式。硬件启动方式是指启动时从主闪存区域读取看门狗计数器的设定信息(ICG0 寄存器),计数器自动开始计数。
工程配置步骤如下:
在库函数配置文件ddl_config.h中打开宏定义
#define DDL_ICG_ENABLE (DDL_ON)
#define DDL_SWDT_ENABLE (DDL_ON)
工程中添加相关文件后,hc32f460_icg.h打开宏定义
#define ICG0_SWDT_HARDWARE_START (ICG_FUNCTION_ON)
WDT_CR寄存器主要用于配置看门狗时钟分频系数,计数周期,刷新区域等,配置如下
/*!< SWDT register config */
#define ICG0_SWDT_AUTS (SWDT_AUTO_START_AFTER_RESET)
#define ICG0_SWDT_ITS (SWDT_RESET_REQUEST)
#define ICG0_SWDT_PERI (SWDT_COUNT_UNDERFLOW_CYCLE_256)
#define ICG0_SWDT_CKS (SWDT_COUNT_SWDTCLK_DIV256)
#define ICG0_SWDT_WDPT (SWDT_0To100PCT)
#define ICG0_SWDT_SLTPOFF (SWDT_SPECIAL_MODE_COUNT_STOP)
WDT_CR寄存器说明
这样配置完成后,SWDT看门狗就可以正常启动了。
3.刷新看门狗计数器
看门狗启动后,我们需要在工程中新增一个任务,定时去刷新看门狗计数器。
刷新动作如图所示
库函数中也有相关的函数封装实现
/**
*******************************************************************************
** \brief SWDT refresh counter
**
** \param [in] None
**
** \retval Ok Process successfully done
**
******************************************************************************/
en_result_t SWDT_RefreshCounter(void)
{
en_result_t enRet = Ok;
M4_SWDT->RR = SWDT_REFRESH_START_KEY;
M4_SWDT->RR = SWDT_REFRESH_END_KEY_;
return enRet;
}
在工程中创建一个看门狗任务,用于定时进行看门狗计数器的刷新操作
/* 看门狗任务 */
rt_thread_init(&swdt_thread,
"swdt task",
swdt_task,
RT_NULL,
&swdt_stack,
sizeof(swdt_stack),
swdt_priority,
1000);
rt_thread_startup(&swdt_thread);
/**
* @brief 看门狗任务
*
* @details 看门狗计数周期为1/(10KHz/256(div))*256=6.5536(s)
*
* @param para
*/
static void swdt_task(void * para)
{
PRO_LOG(LOG_DEBUG, "Entry %s. \r\n", __func__);
while(1)
{
/* 重置计数器 */
SWDT_RefreshCounter();
rt_thread_delay(5000);
}
}
SWDT专用看门狗复位将 RMU_RSTF0.SWDRF 置位,我们可以根据这个标志位来判断是否看门狗复位信号产生。
RMU_GetResetCause(&stcRmuRstCause);
if (Set == stcRmuRstCause.enSwdt)
{
printf("RESET_SWDT_TRIGGER. \r\n");
}
else
{
printf("RESET_OTHER_TRIGGER\r\n");
}
RMU_ClrResetFlag();
总结
关于看门狗的使用,官方用户手册和例程介绍也较为详细(例程:icg\icg_swdt_reset_hw_startup),这里就不再提供源码。以上就是今天要讲的内容,若是有什么地方理解错误,也欢迎大家留言指出。