09.TMS570LC43入门指南——RTI看门狗

09.TMS570LC43入门指南——RTI看门狗


一、简介

通过上一篇文章的学习,我们认识了 RTI 以及学会了使用 RTI 做定时中断。而本篇文章将继续介绍 RTI 中的另外一个功能——看门狗

相信大家对这个名词并不陌生,看门狗经常出现在各种单片机中,用于判断程序是否在正常运行。而这个功能也被广泛用于各种系统中,其本质也还是一个定时器。

那么在 TMS570LC43 中也存在着不少看门狗,而 RTI 中的看门狗是比较常用的。我这样说是因为,其不止在 RTI 中存在看门狗,在 eQEP 中也存在针对于 eQEP 的看门狗。而相较于 eQEP,本文所讲述的看门狗更为常用。另外,大家需要知道的是,看门狗在该芯片中简称为 DWD

那么通过本篇文章,你将学习到以下内容:

  1. 认识 DWD 的相关内容
  2. 学习使用 DWD

首先,需要明确我所使用的开发环境:

  • Windows 10 x64
  • TMS570LC43开发板

二、认识 DWD

RTI 中,拥有两个看门狗,一个是看门狗 (DWD),另一个是窗口看门狗 (DWWD)。在本文中主要对 DWD 进行介绍,后续可能会对 DWWD 进行补充,欢迎各位大佬关注专栏!!!

2.1 DWD结构

DWD 是一个可选的安全诊断,它可以检测失控的 CPU 并产生复位或 NMI (不可屏蔽中断)响应。在可编程周期结束后,或者没有将正确的数值写入 RTIWDKEY 寄存器时,它会使系统复位或产生 NMI

其结构示意如下图所示:

在这里插入图片描述

如上图所示,产生逻辑上的复位有两个影响因素。一个是 RTIDWDCNTR 寄存器向下计数到 0,另一个是写入 RTIWDKEY 寄存器的值比较失败。

而当 RTIWDKEY 寄存器中的值比较成功以后,会触发 DWD 重新计数的信号,使得 RTIDWDCNTR 寄存器再次从 RTIDWDPRLD 寄存器中的预加载值开始递减计数。

2.2 DWD原理

首先,我们需要知道的是,DWD 默认情况下是被禁止的。而如果要使用 DWD,需要向 RTIDWDCTRL 寄存器中写入一个 32-bit 的值,该值具体可阅读相应寄存器。

注意: DWD 开启后,除非系统复位或上电复位,否则无法关闭。

如果向 RTIWDKEY 寄存器中先写入 0xE51A 后写入 0xA35C,则会将 RTIDWDPRLD 寄存器中的值重新写入到 RTI 向下计数寄存器,即 RTIDWDCNTR。而如果写入了一个不正确的数或向下计数寄存器递减到 0时,会立即产生看门狗复位或 NMI

当设备处于挂起模式(停止调试模式)时,RTIDWDCNTR 寄存器会保持其进入挂起模式时的值。

另外,RTIDWDCNTR 寄存器的计数值将随着 RTICLK 时钟周期依次递减。

下图为 DWD 操作示意图:

在这里插入图片描述

这里需要知道的是,向下计数寄存器 (RTIDWDCNTR) 是 25-bit,而看门狗预加载寄存器 (RTIDWDPRLD) 为 13-bit。因此,在向 RTIDWDCNTR 寄存器加载值的时候需要将 RTIDWDPRLD 的预加载值左移 13 位。

那么接下来我们看这张图,当我们 设置预加载值 (set DWD Preload) 的时候,向下计数器 (DWD Down Counter) 同时会被设置,而设置的值为 预加载值左移 13 位 得到的。随后我们 使能看门狗 (enable DWD),此时向下计数器开始运行,我们在运行的时候 依次写入 0xE51A 和 0xA35C 则会使得向下计数器重新从预加载值开始计数。值得注意的是,一定要依次按顺序写入,当我们第二次写入的值是 0xA35C 的时候,就会立即产生重装载的行为。最后,如果我们在向下计数的过程中不写入任何值,当向下计数器递减到 0 后会产生复位或 NMI

RTIDWDCNTR 的溢出时间可以通过以下公式计算得到:
t e x p = ( D W D P R L D + 1 ) × 2 13 R T I C L K 其中 D W D P R L D = 0...4095 \begin{matrix} {\Large texp = \frac{\left(DWDPRLD + 1 \right) \times 2^{13}} {RTICLK}} & 其中 DWDPRLD=0...4095 \end{matrix} texp=RTICLK(DWDPRLD+1)×213其中DWDPRLD=0...4095
上述公式中,DWDPRLDRTIDWDPRID 寄存器,即我们写入的预装载值。

那么,大家唯一不理解的可能就是对 RTIWDKEY 依次写入固定值就会发生重装载的这个问题。对于这个问题,需要看一下手册中对 RTIWDKEY 寄存器的描述,其中有这样一张表格:

在这里插入图片描述

上表展示了一个向 RTIWDKEY 写入值的示例。这里我简单总结一下,主要有以下几点:

  1. 先写入 E51A(H) 再写入 A35C(H) 才能产生重装载。
  2. 写入其他值会产生系统复位或 NMI

另外,需要注意,写入 RTIWDKEY 需要三个 VCLK 时钟周期。

在我们实际生产生活中,也经常把这个重装载的过程称之为 喂狗。也只有我们在喂狗之后才能使得程序正常运行,否则会因为计数值递减到 0 而导致系统复位。


三、项目实现

通过前面的介绍,想必大家对 DWD 有了一定的了解,那么接下来将进行相关项目的实现。

首先需要知道的是,在本文中,项目将使用串口发送提示信息,并启用看门狗,通过触发按键实现“喂狗”的功能

3.1 硬件部分

对于串口这里就不再赘述,使用的是默认的 SCI1 进行通信。

而按键在之前的文章中也有讲解到,使用按键 S3,即对应 GIOB_4

其在开发板的位置如下所示:

在这里插入图片描述

如上图中橙色方框所示,分别为本文所用到的串口和按键。

3.2 软件部分

3.2.1 HALCoGen 配置

明确了外设,因此我们只需要初始化:串口(SCI1)、按键(GIOB_4)RTI。初始化 RTI 是因为 DWDRTI 的一部分。那么具体初始化方式如下所示:

  1. TMS570LC4357ZWT -> Driver Enable 中使能 GIOSCI1RTI 驱动:

    在这里插入图片描述

  2. SCI1 -> SCI Data Format 中进行以下设置:

    在这里插入图片描述

  3. 配置完上述功能后,即可生成程序。依旧使用快捷键 F5 或依次点击 File -> Generate Code

3.2.2 CCS 配置

生成文件后,依旧在 CCS 中进行编写逻辑代码操作。还是先找到我们的 HL_sys_main.c 文件。这里我给出我写的示例代码:

/* USER CODE BEGIN (0) */
/* USER CODE END */

/* Include Files */

#include "HL_sys_common.h"

/* USER CODE BEGIN (1) */
#include "HL_system.h"

#include "HL_sci.h"
#include "HL_gio.h"
#include "HL_rti.h"

#include <stdio.h>
#include <string.h>
/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
#define SCI_REG         sciREG1                         // 定义 sci 端口寄存器

#define KEY1            gioGetBit(gioPORTB, 4)

void        sci_Printf  (char *format, ...);
/* USER CODE END */

int main(void)
{
/* USER CODE BEGIN (3) */
    gioInit();                                                  // gio 初始化
    sciInit();                                                  // sci 初始化

    dwdInit(rtiREG1, 4095);                                     // dwd 初始化

    sci_Printf("DWD test Start...\r\n");

    dwdCounterEnable(rtiREG1);                                  // dwd 使能

    while (1) {
        if (KEY1 == 0) {
            sci_Printf("KEY1 press...\r\n");
            dwdReset(rtiREG1);
        }
    }
/* USER CODE END */

    return 0;
}


/* USER CODE BEGIN (4) */
/*
 * @brief       : 自定义SCI printf 函数
 * @param       : 字符串,可实现类似于 printf 的参数输入
 * @return      : void
 * @author      : Liu Jiahao
 * @date        : 2024-03-26
 * @version     : v1.1
 * @copyright   : Copyright By Liu Jiahao, All Rights Reserved
 */
void sci_Printf(char *format, ...)
{
    uint16 i;
    va_list listdata;
    uint8 sci_TxBuff[100];

    va_start(listdata, format);
    vsprintf((char *)sci_TxBuff, format, listdata);
    va_end(listdata);

    for (i = 0; i < strlen((const char*)sci_TxBuff); i++) {
        while ((SCI_REG->FLR & 0x04U) == 4U);
        sciSendByte(SCI_REG, sci_TxBuff[i]);
    }
}
/* USER CODE END */

在上述代码的初始化部分中,对 DWD 的初始化如下所示:

dwdInit(rtiREG1, 4095);                                     // dwd 初始化

这里我们设置了预加载值最大,其实可以通过我在本文 2.2 DWD原理 章节中所讲到的公式进行计算。

我们系统的 RTICLK 时钟为 75MHz,带入公式进行计算。

DWDPRLD 最小,即为 0 时:
t e x p = ( 0 + 1 ) × 2 13 75 ≈ 109 u s texp = \frac {\left(0 + 1 \right) \times 2^{13}} {75} \approx 109us texp=75(0+1)×213109us
DWDPRLD 最大,即为 4095 时:
t e x p = ( 4095 + 1 ) × 2 13 75 ≈ 447392 u s ≈ 0.447 s texp = \frac {\left(4095 + 1 \right) \times 2^{13}} {75} \approx 447392us \approx 0.447 s texp=75(4095+1)×213447392us0.447s
因此,当我们即使把 DWDPRLD 设置为最大,得到的看门狗溢出时间也只有 0.447 秒,这对于我们实际程序而言并不够用,那么是否有解决方法呢?实际上是有的,我们可以减小时钟频率,即减小 RTLCLK。有关改变时钟的操作,在我之前的文章中也有简单介绍,这里我粘贴出链接供大家参考:

07.TMS570LC43入门指南——时钟-CSDN博客

如果点击无法进行跳转,可自行复制以下链接进行跳转:

  • https://blog.csdn.net/liujiahao_/article/details/140863407

其他代码中的部分内容我在这里就不做过多解释了。

除此之外,我们还需要修改 HL_sys_startup.c 文件,以下是我修改的部分(其余并未提到的部分不做修改):

void _c_int00(void)
{
	register resetSource_t rstSrc;
/* USER CODE BEGIN (5) */
/* USER CODE END */

    /* Initialize Core Registers to avoid CCM Error */
    _coreInitRegisters_();
	
    /* Initialize Stack Pointers */
    _coreInitStackPointer_();

    /* Reset handler: the following instructions read from the system exception status register
     * to identify the cause of the CPU reset.
     */
	rstSrc = getResetSource();
    
    /* 增加以下内容 */
	if (rstSrc == WATCHDOG_RESET)
	    rstSrc = EXT_RESET;
    
    switch(rstSrc)
    {
            .......
    }
    ......

这里增加上述代码的原因是,我们如果没有及时“喂狗”而造成系统复位,可系统复位之后会获取复位原因,并且在 WATCHDOG_RESET 分支中并没有任何对内存、系统、vim 等的初始化。这也就导致了系统最终会进入异常中断,此时我们只有通过按下开发板上的 RST 按钮才能使得系统正常复位运行。因此,这里我对 rstSrc 进行修改,使得系统能够正常复位后初始化。

有关 HL_sys_startup.c 文件,后续可能会抽时间专门写一篇介绍的文章。欢迎各位大佬点赞、关注。但作为熟悉的“鸽王”程序“猿”,不能确保下一次什么时候更新,大家敬请期待。

3.2.3 运行结果

我们通过串口助手链接开发板,当我们持续按下按键的时候,会持续输出 KEY1 press...,而没有按键按下,系统则会一直重启,并打印 DWD test Start...。具体效果如下所示:

在这里插入图片描述

另外,在本文中,RTICLK 默认使用的最高 75MHz,因此留给我们喂狗的时间很短,所以按键触发就没有做延时消抖处理,大家在实际工作中可按需求调整频率。


四、写在最后

本文介绍了 TMS570LC43上的 RTI 看门狗以及其使用方法。希望能够对大家的学习提供一点帮助。

在后续的文章中,将继续对 TMS570LC43x 进行详细的入门指导,欢迎读者关注!!!

目前暂时没有考虑整合的打算,所以各位读者如果需要看别的教程,可以点进 专栏 进行查找。在后续的更新中,将会逐步加入各个文章的链接,以便大家快速翻阅。另外源码会逐步开源。

欢迎广大读者提出问题以及修改意见,本人看到后会给予回应,欢迎留言,后续会逐步进行开源!!!
另外,由于文章是作者手打的文字,有些地方可能文字会出错,望谅解,也可私信联系我,我对其进行更改。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值