系统环境
软件平台
硬件需求
RV-STAR开发板
看门狗定时器实际上一个计数器,在计数溢出时会产生一个复位信号,正常情况下首先给看门狗定时器设置一个超时时间,然后程序在超时时间内定期对定时器进行重载操作(也叫做“喂狗”操作),从而避免正常程序发生复位。
当系统发生意料之外的故障使得软件跑飞,看门狗定时器无法被按时重载时,看门狗硬件就会产生一个系统复位,让系统重新运行,从而达到恢复功能的效果。
独立看门狗定时器(FWDGT)具有独立的时钟源(IRC40K)。因此就算主时钟失效的,它仍然能保持工作状态,这适用于需要独立环境且对计时精度要求不高的场合。
当内部向下计数器的值达到0,独立看门狗会产生一个复位。使能独立看门狗的寄存器写保护功能可以避免寄存器的值被意外的配置篡改。
主要特性:
自由运行的12位向下计数器
如果看门狗定时器被使能,那么当向下计数器的值达到0时产生系统复位;
独立时钟源,独立看门狗定时器在主时钟故障时仍能工作;
独立看门狗定时器硬件控制位,可以用来控制是否在上电时自动启动看门狗定时器;
可以配置独立看门狗定时器在调试模式下选择停止还是继续工作。
实验部分
FWDGT实验的思路如下:
首先对系统进行初始化操作,然后让红色的LED点亮50ms(用于指示系统发生了复位),接着将FWDGT的超时时间设置为1000ms(非精确),然后在主函数中每间隔900ms做一次FWDGT计数器重载防止其复位,并且用绿色LED状态切换表示程序正在运行(FWDGT没有复位)。
同时用KEY_WKUP按键连线的中断线来模拟一个软件故障,当该按键被按下时触发中断服务,在该中断服务程序中写入一个点亮蓝色LED并进入while(1)的死循环来模拟软件跑飞,不能返回主程序。这样FWDGT计数器不能及时被重载,当计数值到0时,发生FWDGT复位,在系统复位后,通过点亮红色LED来指示FWDGT发生。
完整的实现代码如下:
#include "nuclei_sdk_hal.h"
uint32_t millis(void);
uint32_t start = 0;
uint32_t now = 0;
int main()
{
/* enable IRC40K */
rcu_osci_on(RCU_IRC40K);
/* wait till IRC40K is ready */
while (SUCCESS != rcu_osci_stab_wait(RCU_IRC40K)) ;
/* confiure FWDGT counter clock: 40KHz(IRC40K) / 64 = 0.625 KHz */
fwdgt_config(625, FWDGT_PSC_DIV64);
/* after 1 seconds to generate a reset */
fwdgt_enable();
gd_rvstar_led_init(LED1);
gd_rvstar_led_init(LED2);
gd_rvstar_led_init(LED3);
gd_rvstar_led_on(LED3);
delay_1ms(50);
gd_rvstar_led_off(LED3);
start = millis();
gd_rvstar_key_init(KEY_WAKEUP, KEY_MODE_EXTI);
__enable_irq();
while (1) {
now = millis();
if (now - start >= 900) {
fwdgt_counter_reload();
start = now;
}
/* toggle green led */
gd_rvstar_led_toggle(LED1);
delay_1ms(100);
}
}
void EXTI0_IRQHandler(void)
{
if (RESET != exti_interrupt_flag_get(WAKEUP_KEY_EXTI_LINE)) {
if (RESET == gd_rvstar_key_state_get(KEY_WAKEUP)) {
gd_rvstar_led_off(LED1);
gd_rvstar_led_on(LED2);
while (1);
}
}
/* clear EXTI lines pending flag */
exti_interrupt_flag_clear(WAKEUP_KEY_EXTI_LINE);
}
/**
* \brief Returns the number of milliseconds since the board began running the current program.
*
* \return Number of milliseconds since the program started (uint32_t)
*/
uint32_t millis(void)
{
return (uint32_t)(SysTimer_GetLoadValue() * (4000.F / SystemCoreClock));
}
在IDE中创建工程,将上述代码编译上传到开发板,可以观察到,开发板的板载LED短暂闪了下红色后,开始进入持续的绿色快速闪烁状态,当按下WKUP按键后,LED开始亮蓝色,持续不到1s后,又闪了下红色后然后进入持续的绿色快速闪烁状态,说明看门狗起到了作用使系统发生了复位。
实验源码:
https://github.com/Nuclei-Software/nuclei-board-labs/tree/master/rvstar/wdgt/fwdgt_key_int