ARM32开发--WDGT看门狗

发布于:2024-06-16 ⋅ 阅读:(20) ⋅ 点赞:(0)

知不足而奋进 望远山而前行


目录

文章目录

前言

目标

内容

什么是看门狗

ARM中的看门狗

独立看门狗定时器

窗口看门狗定时器

独立看门狗FWDGT

初始化配置

喂狗

完整代码

窗口看门狗WWDGT

初始化配置

喂狗

完整代码

注意

总结


前言

嵌入式系统在如今的科技发展中扮演着越来越重要的角色,而其中保障系统稳定性与可靠性的机制显得尤为关键。本文将深入探讨看门狗(Watchdog)的概念、工作原理以及在 ARM 架构下的两种主要类型:独立看门狗和窗口看门狗。通过学习本文,您将对嵌入式系统中的看门狗有更深入的了解,从而提升系统的稳定性与可靠性。


目标

  • 了解什么是看门狗
  • 了解看门狗工作原理
  • 了解ARM的独立看门狗和窗口看门狗
  • 掌握看门狗初始化和喂狗

内容

什么是看门狗

看门狗(Watchdog)是一种用于监视系统运行情况的硬件设备,本质就是一个倒计时计数器。它能定时检测系统是否正常运行,并在系统出现故障或者卡死时自动重启系统,从而保证系统的稳定性和可靠性。

其基本原理是定期接收来自主控芯片的"喂狗信号",如果在规定的时间内没有接收到信号,硬件看门狗将会

触发系统复位,重新启动整个系统。

硬件看门狗特别适合用于远程或无人值守的系统设备中,它能确保系统在出现故障时及时自动重启减少停机时间并提高系统的可用性。这在一些关键的嵌入式系统、服务器、网络设备等领域非常重要。

看门狗(Watchdog)在嵌入式系统中起着至关重要的作用,它通常是一种硬件计时器或计数器,用于监控系统的运行情况。其作用和重要性包括以下几个方面:

  1. 系统健壮性和稳定性: 看门狗能够监控系统的运行状态,一旦系统出现故障、死锁或意外情况,可以通过重启系统来恢复正常运行,确保系统的稳定性和可靠性。
  2. 防止死锁和程序错误: 当程序发生死循环、意外暂停或其他异常情况时,看门狗可以检测到系统无响应的状态并执行重启操作,从而防止系统永久性死锁。
  3. 系统保护和数据完整性: 通过定期喂狗操作,可以确保系统在正常运行期间不会因软件或硬件故障而丢失关键数据,从而保护系统的数据完整性和稳定性。
  4. 实时系统保障: 对于实时系统而言,看门狗可以帮助确保系统在规定的时间内完成任务,若任务未能及时完成,可以执行重启操作以确保系统的实时性能。

看门狗在嵌入式系统中的作用和重要性体现在提高系统的稳定性、保护数据完整性、预防死锁和程序错误、保障实时系统性能等方面。它是确保嵌入式系统安全可靠运行的重要保障手段之一。

ARM中的看门狗

独立看门狗定时器

有独立时钟源(IRC32K)。即使主时钟失效,FWDGT依然能保持正常工作状态,适用于需要独立环境且对计时精度要求不高的场合。

当内部向下计数器的计数值达到0,独立看门狗会产生一个系统复位。使能独立看门狗的寄存器写保护功能可以避免寄存器的值被意外的配置篡改。

窗口看门狗定时器

用来监测由软件故障导致的系统故障。窗口看门狗定时器开启后,7位向下递减计数器值逐渐减小。计数值达到0x3F时会产生系统复位(CNT[6]位被清0)。在计数器计数值达到窗口寄存器值之前,计数器的更新也会产生复位。因此软件需要在给定的区间内更新计数器。窗口看门狗定时器在计数器计数值达到0x40会产生一个提前唤醒标志,如果使能中断将会产生中断。窗口看门狗定时器时钟是由APB1时钟预分频而来。窗口看门狗定时器适用于需要精确计时的场合。

独立看门狗FWDGT

free watchdog timer

初始化配置
static void wtd_config() {
    rcu_osci_on(RCU_IRC32K);
    
    while( SUCCESS != rcu_osci_stab_wait(RCU_IRC32K) ){  }
    
    fwdgt_config( 1000,  FWDGT_PSC_DIV64);
    
    fwdgt_enable();
}

/* confiure FWDGT counter clock: 32KHz(IRC32K) / 64 = 0.5 KHz */

独立看门狗计数时钟计算:

  • 独立看门狗具备独立晶振:32KHZ
  • FWDGT_PSC_DIVx: x为分频系数,意思是降低晶振频率。例如为64时,32khz/64 = 0.5khz = 500hz,表示的是1秒钟计数500次。
  • fwdgt_config(2 * 500, FWDGT_PSC_DIV64); 中的第一个参数就是计数值,通过分频我们可以知道1秒钟计数500次,那么我要设置为n秒,就需要 n*500的计数值。
喂狗
fwdgt_counter_reload();
完整代码

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart0.h"


void Usart0_on_recv(uint8_t* data, uint32_t len) {
    printf("recv: %s\r\n", data);
}

static void wtd_config() {
    fwdgt_config(2 * 500, FWDGT_PSC_DIV64);
    fwdgt_enable();
}

int main(void)
{
    systick_config();
    Usart0_init();

    wtd_config();

    printf("start\r\n");
    while(1) {

        delay_1ms(960); // 重启
        // delay_1ms(450); // 正常
        /* reed dog */
        fwdgt_counter_reload();
    }
}

窗口看门狗WWDGT

初始化配置
static void wtd_config() {
    rcu_periph_clock_enable(RCU_WWDGT);
    /*
     *  System clock up to 168Mhz, PCLK1=42MHz 
     *  set WWDGT clock = (PCLK1 (42MHz)/4096)/4 = 2563.5Hz (0.39ms)  
     *  set counter value to 127
     *  set window value to 80
     *  refresh window is: 0.39ms * (127-80)  < refresh window <  0.39ms * (127-0x3F) 
     */
    wwdgt_config(127, 80, WWDGT_CFG_PSC_DIV4);
    wwdgt_enable();
}

wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)配置的是窗口时间,计算窗口时间是需要注意几个参数的含义。

  • counter表示计数值,取值为0x00 - 0x7F
  • window表示窗口值,取值为0x00 - 0x7F
  • 窗口区间的初始值最小为0x3F
  • 窗口计数是递减的,因此是 (counter - 初始值) 为最大时间计数,(counter - 窗口区间值)为最小时间计数
  • 一个时钟计数,通过 主频/4096可以得到计数值,4096为12位向下计数器组成。
  • 窗口计数器通过分频,得到一个时钟计数,主频/4096/分频系数
喂狗
完整代码

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart0.h"

void Usart0_on_recv(uint8_t* data, uint32_t len) {
    printf("recv: %s\r\n", data);
    
	if(data[0] == 0x04){
		// 模拟卡死操作
		while(1);
	}
}

static void wtd_config() {
    rcu_periph_clock_enable(RCU_WWDGT);
    /*
     *  System clock up to 168Mhz, PCLK1=42MHz 
     *  set WWDGT clock = (PCLK1 (60MHz)/4096)/4 = 2563.5Hz (0.39ms)   
     *  set counter value to 127
     *  set window value to 80
     *  
     
	窗口开始时间-> (counter - window) * 1次计数耗时 =  (127 - 80) * 0.39ms = 18.33ms
	窗口结束时间-> (counter - 	 0x3F) * 1次计数耗时 = (127 - 63) * 0.39ms = 24.96ms
	
	需要在窗口时间内喂狗, 否则会触发重启
	18.33ms < duration < 24.96ms
    
     */
    wwdgt_config(127, 80, WWDGT_CFG_PSC_DIV4);
    wwdgt_enable();
}

int main(void)
{
    systick_config();
    Usart0_init();

    wtd_config();

    printf("start\r\n");
    while(1) {
    	// 18.33ms < 安全期 < 24.96ms
        //    delay_1ms(18);
        delay_1ms(22); // 可以
        //    delay_1ms(26);
        /* update WWDGT counter */
        wwdgt_counter_update(127);
    }
}

注意

如果计算得到的窗口期和真实的运行结果不一致,要考虑system_gd32f4xx.c里配置的系统时钟是否是168M,即打开该文件,找到__SYSTEM_CLOCK_168M_PLL_8M_HXTAL,释放其注释,保持打开状态。

参考文档:GD32F4标准外设库🌟🌟🌟


总结

本文系统地介绍了看门狗(Watchdog)在嵌入式系统中的重要作用及其工作原理。首先,我们了解了看门狗的基本概念,它是一种硬件设备,用于监视系统运行情况,并在系统故障时自动重启系统,以确保系统的稳定性和可靠性。接着,我们深入探讨了看门狗的作用和重要性,包括提高系统的稳定性、防止死锁和程序错误、保护数据完整性以及保障实时系统性能等方面。随后,针对 ARM 架构,我们详细介绍了两种主要类型的看门狗:独立看门狗和窗口看门狗,并分别给出了其初始化配置和喂狗的方法。通过本文的学习,读者将能够更好地理解看门狗在嵌入式系统中的重要性,进而提高系统的稳定性和可靠性。