10.【NXP 号令者RT1052】开发——实战-RT 看门狗(RTWDOG)

10.【NXP 号令者RT1052】开发------实战-RT 看门狗(RTWDOG)

这一章,我们将向大家介绍如何使用 RT1052 的另外一个看门狗,RT 看门狗(WDOG3,以下简称RTWDOG)。在本章中,我们将使用按键 KEY_UP 来喂狗,通过 DS0 提示程序的运行状态。本章为如下几个部分:

10.1 RT1052 RT 看门狗简介

RT 看门狗(WDOG3)和前面介绍的普通看门狗(WDOG1 和 WDOG2)有一些区别:

  1. RT 看门狗计数器是向上计数的,普通看门狗是向下计数的;
  2. RT 看门狗支持窗口模式(类似STM32 的窗口看门狗),普通看门狗不支持;
  3. 在精度上面,RT 窗口看门狗的精度可以到 ns级别,而普通看门狗只有 0.5 秒的精度。所以,在需要精确控制复位时间或刷新窗口的时候,可以选择 RT 看门狗。

    由图可知,窗口看门狗的时钟可以从 4 个时钟源里面选择:BUS_CLK(150M)、LPO_CLK(32.768K)、INTCLK(32.768K)和 ERCLK(1M),通过复用器(MUX)选择,然后可以选择使用/不使用 256 分频器,最后进入 16 位的看门狗计数器,作为计数时钟。看门狗计数器有 2 个比较值,上方的是溢出时间比较值(TOVAL),下方的是窗口时间比较值(WIN),可以通过控制逻辑对看门狗计数器进行刷新(喂狗),以避免复位。具体的刷新时间.

    图中,如果使用窗口模式,则刷新(喂狗)时间必须在看门狗计数器的值大于等于 WIN,小于TOVAL 的时间段里面刷新。如果使用普通模式(非窗口模式),则只要看门狗计数器值小于 TOVAL,就可以刷新(喂狗)。

当在可刷新的时间之外刷新(喂狗),会导致 CPU 复位;同样,如果看门狗计数器达到或超过 TOVAL,也会导致 CPU 复位。

RT 看门狗超时时间由下列公式计算:

Trtwdog = \\dfrac{TOVAL}{Frtwdog}

其中:

  • Trtwdog:RT 看门狗超时时间,单位为 ms
  • Frtwdog:RT 看门狗时钟频率,单位为 kHz

Frtwdog 的时钟频率由 PRES 位决定,可选两种分频:256 分频(约 3.072 kHz)和 1 分频(约 0.128 kHz)。PRES 位设置对应的超时时间范围如下表所示(表中超时时间由公式计算得出):

PRES 看门狗超时(TOVAL <= 0x0001) 看门狗超时(TOVAL >= 0xFFFF)
0 约 0.3 ms 约 30.5 s
1 约 7.8 ms 约 763 s

说明:

  • 选择 256 分频时,系统源时钟(示例中)为 3.072 MHz,因此 RT 看门狗时钟约为 3.072 kHz。
  • 选择 1 分频时,系统源时钟仍为 3.072 MHz,因此 RT 看门狗时钟约为 0.128 kHz。

通过设置 PRES 位与 TOVAL 值,可以得到不同的超时时间,以满足不同系统需求。

接下来,我们介绍 RT 看门狗的 4 个寄存器。

32 位寄存器位定义(仅低 16 位有效)

位域 名称 访问 描述
15 WIN R/W 窗口模式使能 0 = 关闭 1 = 开启
14 FLG R/W1C 看门狗中断标志 0 = 无中断 1 = 已发生中断
13 CMD32EN R/W 32 位刷新/解锁命令支持 0 = 不支持 1 = 支持
12 PRES R/W 输入时钟 256 分频 0 = 不分频 1 = 256 分频
11 ULK RO 解锁状态 0 = 未解锁 1 = 已解锁
10 RCS RO 重新配置状态 0 = 失败 1 = 成功
9:8 CLK[1:0] R/W 时钟源选择 00 = BUS CLK 01 = LPO CLK (32.768 kHz,推荐) 10 = INTCLK 11 = ERCLK
7 EN R/W RTWDOG 使能 0 = 关闭 1 = 开启
6 UPDATE R/W 允许重新配置 0 = 禁止 1 = 允许(置 1 后需在 255 总线时钟周期内完成配置,150 MHz 时约 1.7 µs)
5 INT R/W 中断使能 0 = 禁止 1 = 使能(溢出或非法操作后先产生中断,255 总线时钟周期后强制复位 MCU,仅用于善后,不可喂狗

接下来,看 RT 看门狗的第二个寄存器:计数寄存器(CNT)

16 位只读/写寄存器(低 16 位有效)

功能 操作 数据 说明
1. 读当前计数器值 读寄存器 ------ 直接返回 RT 看门狗实时计数器值
2. 解锁 写序列 0xC5200xD928 两步解锁,完成后允许配置寄存器 若 CMD32EN=1,可一次写入 0xD928C520
3. 刷新(喂狗) 写序列 0xA6020xB480 两步清零计数器 若 CMD32EN=1,可一次写入 0xB480A602

注意

解锁后必须在 255 个总线周期(150 MHz 下约 1.7 µs)内完成全部配置,否则解锁失效。

接下来,我们看 RT 看门狗的第三个寄存器:溢出时间寄存器(TOVAL)

该寄存器决定了 RT 看门狗的溢出时间,低 16 位有效,最小值为 1(不能为 0!),最大值为 0XFFFF,当 RT 看门狗计数器(CNT)的值等于 TOVAL 时,将引起 CPU 复位。

RT 看门狗的第四个寄存器:窗口寄存器(WIN)

窗口寄存器(仅窗口模式有效)

  • 位宽:低 16 位有效
  • 取值范围 :1 -- 0xFFFF(不能为 0
  • 作用:设定允许刷新的时间窗口上限
  • 时间关系
    WIN ≤ Trefresh < TOVAL
    Trefresh 之外喂狗将立即触发 CPU 复位
  • 硬性约束WIN 必须小于 TOVAL

RT1052 RTWDOG 启用流程(使用 KEY_UP 按键喂狗)

1) 使能 RTWDOG 时钟
c 复制代码
CLOCK_EnableClock(kCLOCK_Wdog3);

注:RTWDOG_Init 内部已调用,用户无需重复操作。

2) 初始化 RTWDOG(超时值 & 窗口值)

函数原型:

c 复制代码
void RTWDOG_Init(RTWDOG_Type *base, const rtwdog_config_t *config);

配置结构体 rtwdog_config_t 关键成员:

成员 说明
enableRtwdog 设为 true 方能使能看门狗
clockSource 对应寄存器 CS 的 CLK[1:0],四选一时钟源
prescaler 256 分频或不分频
testMode 通常选 kRTWDOG_UserModeEnabled
enableWindowMode 是否启用窗口模式
windowValue 窗口值(启用窗口模式时有效)
timeoutValue 看门狗超时值

初始化示例:

c 复制代码
rtwdog_config_t rtwdog_config;
rtwdog_clock_prescaler_t prescal;
if(pscen==0)       prescal=kRTWDOG_ClockPrescalerDivide1;
else if(pscen==1)  prescal=kRTWDOG_ClockPrescalerDivide256;
delay_ms(10);
RTWDOG_GetDefaultConfig(&rtwdog_config);
rtwdog_config.testMode        =kRTWDOG_UserModeEnabled;
rtwdog_config.clockSource     =(rtwdog_clock_source_t)src;
rtwdog_config.prescaler       =prescal;
rtwdog_config.timeoutValue    =toval;
rtwdog_config.enableWindowMode=false;
rtwdog_config.enableInterrupt =false;
rtwdog_config.enableRtwdog    =true;
rtwdog_config.windowValue     =win;
RTWDOG_Init(RTWDOG,&rtwdog_config);
3) 喂狗
c 复制代码
static inline void RTWDOG_Refresh(RTWDOG_Type *base);
  • CMD32EN=1:一次性写入 0xB480A602
  • CMD32EN=0:分两次写入 0xB4800xA602
4) 中断使能与优先级(如需)
c 复制代码
RT1052_NVIC_SetPriority(RTWDOG_IRQn,4,0);
NVIC_EnableIRQ(RTWDOG_IRQn);
5) 中断服务函数
c 复制代码
void RTWDOG_IRQHandler(void)

中断内无法喂狗(255 总线周期 ≈ 1.7 µs 内无法完成刷新),仅做简短善后处理。


实验现象

  • DS0 常态常亮
  • 持续按键 KEY_UP 即喂狗,不会复位
  • 一旦超过 TOVAL 未喂狗,MCU 重启,DS0 熄灭一次

10.2 硬件设计

本实验用到的硬件资源有:

1) 指示灯 DS0

2) KEY_UP 按键

3) RT 看门狗

前面两个在之前都有介绍,RT 看门狗属于 RT1052 的内部资源,只需要软件设置好即可正常工作。我们通过 DS0 来指示是否产生了复位,通过 KEY_UP 按键来实现喂狗操作。

10.3 软件设计

这里,我们在之前的 WDOG1 看门狗实例内增添部分代码来实现这个实验。在 HARDWARE 文件夹下面新建一个 RTWDOG的文件夹,用来保存与看门狗相关的代码。然后打开工程,新建 rtwdog.c 和 rtwdog.h 两个文件,并保存在 RTWDOG 文件夹下,并将 RTWDOG 文件夹加入头文件包含路径。

同时记得导入对应的 FSLLIB库------ fsl_rtwdog.c

下面写 rtwdog.crtwdog.h代码

c 复制代码
#include "rtwdog.h"
#include "lpuart.h"
#include "delay.h"
#include "led.h"

rtwdog_config_t rtwdog_config;	//RTWDOG配置寄存器

//初始化RTWDOG
//presc: 分频值,0 不分频,1 256分频
//cnt:	计数值

// src : 时钟源选择.0,bus clock;1,LPO clock;2,INTCLK;3,ERCLK;
//       bus clock:150Mhz; LPO clock和INTCLK都是32.768Khz; ERCLK约500Khz 
//pscen: 分频器使能.0,不使能.1,使能固定256分频.
//toval: 看门狗计数器溢出最大值(cnt超过该值将产生复位).范围:0~65535
// win : 看门狗计数器窗口值.范围:0~65535,0表示不使用窗口模式.
//       注意:刷新CNT必须是在win≤刷新时≤toval,这个区间,否则将产生复位.
//溢出时间=(256^pscen)*toval/src;
//一般建议用
void MYRTWDOG_Init(u8 src,u8 pscen,u16 toval,u16 win)
{
    rtwdog_clock_prescaler_t prescal;
    
    CLOCK_EnableClock(kCLOCK_Wdog3);			    //使能RTWDOG
    
	//初始化RTWDOG
	if(pscen==0)prescal=kRTWDOG_ClockPrescalerDivide1;	//不分频
	else if(pscen==1)prescal=kRTWDOG_ClockPrescalerDivide256;//256分频
	
	delay_ms(10);									//切换时钟前要等待一段时间
    RTWDOG_GetDefaultConfig(&rtwdog_config);		//先使用默认参数配置RTWDOG
    rtwdog_config.testMode=kRTWDOG_UserModeEnabled;	//用户模式
    rtwdog_config.clockSource=(rtwdog_clock_source_t)src;//时钟源选择
    rtwdog_config.prescaler=prescal;				//分频
    rtwdog_config.timeoutValue=toval;			    //超时值
    rtwdog_config.enableWindowMode =false;			//关闭窗口功能
	rtwdog_config.enableInterrupt=false;			//关闭中断
    rtwdog_config.enableRtwdog=true;				//使能看门狗
    rtwdog_config.windowValue=win;                  //窗口值(默认上面关闭了窗口功能)
    RTWDOG_Init(RTWDOG,&rtwdog_config);				//初始化看门狗
    
	RT1052_NVIC_SetPriority(RTWDOG_IRQn,4,0);	    //抢占优先级4,子优先级0
    NVIC_EnableIRQ(RTWDOG_IRQn);				    //使能RTWDOG中断
}

//RTWDOG中断服务函数
void RTWDOG_IRQHandler(void)
{
    //FLG=1,产生了超时中断
    if((RTWDOG_GetStatusFlags(RTWDOG)&kRTWDOG_InterruptFlag)==kRTWDOG_InterruptFlag)
	{ 
		//无法在此处喂狗,只能做善后工作,且务必要短.
	}	
    RTWDOG_ClearStatusFlags(RTWDOG,kRTWDOG_InterruptFlag); //清除中断标志位
}

//喂狗
void RTWDOG_Feed(void)
{
	RTWDOG_Refresh(RTWDOG);
}

RTWDOG_IRQHandler 函数,是 RTWDOG 的中断服务函数,可以做一些善后工作,本章我们并没有用到。

RTWDOG_Feed函数,用于刷新RT看门狗计数器,即喂狗。就是对库函数RTWDOG_Refresh的简单封装。

RTWDOG_Init 函数,用于初始化 RTWDOG。该函数有 4 个参数:src 用于选择时钟源,一般我们选择 LPO_CLK;pscen 用于设置是否使用 256 分频,可根据自己的需要设置;toval 用于设置看门狗溢出时间,决定了多久需要喂狗一次;win 用于设置窗口值,当 win 设置为 0 时,不使用窗口模式。该函数的设置步骤,就是按我们前面介绍的 4 个步骤来设置的,该函数并没有使能 RGWDOG 的中断!

c 复制代码
#ifndef _RTWDOG_H
#define _RTWDOG_H
#include "sys.h"

void MYRTWDOG_Init(u8 src,u8 pscen,u16 toval,u16 win);
void RTWDOG_Feed(void);
#endif


下面写 main.c代码

c 复制代码
#include "sys.h"
#include "lpuart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdog.h"
#include "rtwdog.h"

int main(void)
{
    u8 key=0;
	MPU_Memory_Protection();    //初始化MPU
	RT1052_Clock_Init();	    //配置系统时钟
	DELAY_Init(600);		    //延时函数初始化
	LPUART1_Init(115200);       //初始化串口1
    RT1052_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//优先级分组4
#ifdef LED_DEBUG
	u8 led0sta=1,led1sta=1;     //LED0,LED1的当前状态
	LED_Init();				    //初始化LED
#endif
#ifdef KEY_DEBUG
	KEY_Init();                 //初始化KEY
#endif
#ifdef LPUART_DEBUG
    u8 len;					//接收数据长度
    u16 times=0;            //延时计数器
    LED0(0);					//先点亮红灯 
#endif
#ifdef EXTIX_DEBUG
    EXTIX_Init();			    //初始化外部中断
#endif
#ifdef WDOG_DEBUG
    WDOG1_Init(3,2);		    //初始化看门狗1,2秒溢出,提前1秒进入中断,方便喂狗
	LED0(0);               	    //先点亮LED灯
    delay_ms(300);				//延时300ms再初始化看门狗,LED0的变化"可见"
#endif
    LED_Init();				    //初始化LED 
    KEY_Init();                 //初始化KEY
    delay_ms(100);         	    //延时100ms再初始化看门狗,LED0的变化"可见"
	MYRTWDOG_Init(1,0,32768,0);	//初始化RT看门狗,1秒溢出,非窗口模式
	LED0(0);               	    //先点亮LED灯
    while(1)
    {
        key=KEY_Scan(0);
		if(key==WKUP_PRES)		//如果按键按下,则喂狗.
		{
			RTWDOG_Feed();
		} 
		delay_ms(10);
#ifdef WDOG_DEBUG
        LED0(1);				//关闭DS0,如不复位,DS0将一直处于关闭状态.
		delay_ms(100);
#endif
#ifdef EXTIX_DEBUG
        printf("Int example driver!\r\n");
		delay_ms(1000);
#endif
#ifdef KEY_DEBUG
        key=KEY_Scan(0); 		    //得到键值
        if(key)
        {	
            switch(key)
            {				 
                case WKUP_PRES:	//控制LED0,LED1互斥点亮
                    led1sta=!led1sta;
                    led0sta=!led1sta;
                    break;
                case KEY2_PRES:	//控制LED0翻转
                    led0sta=!led0sta;
                    break;
                case KEY1_PRES:	//控制LED1翻转	 
                    led1sta=!led1sta;
                    break;
                case KEY0_PRES:	//同时控制LED0,LED1翻转 
                    led0sta=!led0sta;
                    led1sta=!led1sta;
                    break;
            }
            LED0(led0sta);		//控制LED0状态
            LED1(led1sta);		//控制LED1状态
        }else delay_ms(10);
#endif // KEY_DEBUG
#ifdef LPUART_DEBUG
        if(LPUART_RX_STA&0x8000)
		{					   
			len=LPUART_RX_STA&0x3fff;//得到此次接收到的数据长度
			printf("\r\n发送的消息为:\r\n");
			LPUART_WriteBlocking(LPUART1,LPUART_RX_BUF,len);//发送接收到的数据
			printf("\r\n\r\n");//插入换行
			LPUART_RX_STA=0;
		}else
		{
			times++;
			if(times%5000==0)
			{
				printf("\r\nALIENTEK RT1052开发板 串口实验\r\n");
			}
			if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
			if(times%30==0)LED0_Toggle;//闪烁LED,提示系统正在运行.
			delay_ms(10);   
		}
#endif // LPUART_DEBUG
	}
}

该函数我们通过 RTWDOG_Init 函数初始化 RT 看门狗,设置其使用 LPO_CLK 时钟源,1秒溢出,不使用窗口模式。然后,点亮 DS0,并进入死循环。在死循环里面,我们必须不停的按 KEY_UP 按键,否则 1 秒钟以后,DS0 就会灭掉(灭的时间为 100ms 左右),表示发生了看门狗复位。

10.4 下载验证

将代码下载(仅 flexspi_debug_release 目标工程支持下载)到号令者 RT1052 后,可以看到DS0 亮了,然后如果我们不按 KEY_UP 按键,则 DS0 亮约 1 秒后,会发生看门狗复位,DS0 灭一会(约 100ms)后,又重新点亮,依次循环。如果我们不停的按 KEY_UP 按键(按下+松开),就可以看到 DS0 不再灭了,保持常亮,表示喂狗成功。

总结

RTWDOG(RT 看门狗)与普通 WDOG 的主要区别在于:RTWDOG 为向上计数、支持窗口模式且时钟可选分频,具备更高时间精度和严格的刷新时序(必须在 WIN ≤ CNT < TOVAL 区间内按特定写序列喂狗,且解锁后需在很短总线周期内完成配置),适合需要精确时序或窗口约束的场景;普通 WDOG 为向下计数、无窗口限制、超时粒度较粗(以 0.5 s 为步进),使用和刷新更简单,适合常规复位保护。

OK!谢谢大家!

相关推荐
-大头.2 小时前
Rust高级类型与零成本抽象实战
stm32·单片机·rust
Porco.w6 小时前
STM32 DMA
stm32·单片机·嵌入式硬件
BreezeJuvenile6 小时前
外设模块学习(17)——5V继电器模块(STM32)
stm32·单片机·嵌入式硬件·学习·5v继电器模块
GilgameshJSS6 小时前
STM32H743-ARM例程40-U_DISK_IAP
c语言·arm开发·stm32·单片机·嵌入式硬件
hazy1k8 小时前
51单片机基础-GPIO结构详解
stm32·单片机·嵌入式硬件·51单片机
集和诚JHCTECH8 小时前
专为严苛环境而生:高防护等级工业防水平板WPPC-H1520T(P)
人工智能·嵌入式硬件·平板
云山工作室9 小时前
基于协同过滤算法的话剧购票系统(论文+源码)
单片机·物联网·毕业设计·课程设计·毕设
辰哥单片机设计10 小时前
STM32项目分享:智能水产养殖系统
stm32·单片机·嵌入式硬件
一枝小雨10 小时前
【OTA专题】2 初级bootloader架构和基础工程移植
stm32·单片机·嵌入式·ota·bootloader·固件升级·加密升级