09.TMS570LC43入门指南——RTI看门狗
文章目录
一、简介
通过上一篇文章的学习,我们认识了 RTI
以及学会了使用 RTI
做定时中断。而本篇文章将继续介绍 RTI
中的另外一个功能——看门狗。
相信大家对这个名词并不陌生,看门狗经常出现在各种单片机中,用于判断程序是否在正常运行。而这个功能也被广泛用于各种系统中,其本质也还是一个定时器。
那么在 TMS570LC43
中也存在着不少看门狗,而 RTI
中的看门狗是比较常用的。我这样说是因为,其不止在 RTI
中存在看门狗,在 eQEP
中也存在针对于 eQEP
的看门狗。而相较于 eQEP
,本文所讲述的看门狗更为常用。另外,大家需要知道的是,看门狗在该芯片中简称为 DWD
。
那么通过本篇文章,你将学习到以下内容:
- 认识
DWD
的相关内容 - 学习使用
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
上述公式中,DWDPRLD
即 RTIDWDPRID
寄存器,即我们写入的预装载值。
那么,大家唯一不理解的可能就是对 RTIWDKEY
依次写入固定值就会发生重装载的这个问题。对于这个问题,需要看一下手册中对 RTIWDKEY
寄存器的描述,其中有这样一张表格:
上表展示了一个向 RTIWDKEY
写入值的示例。这里我简单总结一下,主要有以下几点:
- 先写入 E51A(H) 再写入 A35C(H) 才能产生重装载。
- 写入其他值会产生系统复位或
NMI
。
另外,需要注意,写入
RTIWDKEY
需要三个VCLK
时钟周期。
在我们实际生产生活中,也经常把这个重装载的过程称之为 喂狗。也只有我们在喂狗之后才能使得程序正常运行,否则会因为计数值递减到 0 而导致系统复位。
三、项目实现
通过前面的介绍,想必大家对 DWD
有了一定的了解,那么接下来将进行相关项目的实现。
首先需要知道的是,在本文中,项目将使用串口发送提示信息,并启用看门狗,通过触发按键实现“喂狗”的功能。
3.1 硬件部分
对于串口这里就不再赘述,使用的是默认的 SCI1
进行通信。
而按键在之前的文章中也有讲解到,使用按键 S3
,即对应 GIOB_4
。
其在开发板的位置如下所示:
如上图中橙色方框所示,分别为本文所用到的串口和按键。
3.2 软件部分
3.2.1 HALCoGen 配置
明确了外设,因此我们只需要初始化:串口(SCI1)
、按键(GIOB_4)
、RTI
。初始化 RTI
是因为 DWD
是 RTI
的一部分。那么具体初始化方式如下所示:
-
在
TMS570LC4357ZWT -> Driver Enable
中使能GIO
、SCI1
及RTI
驱动: -
在
SCI1 -> SCI Data Format
中进行以下设置: -
配置完上述功能后,即可生成程序。依旧使用快捷键
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)×213≈109us
当 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)×213≈447392us≈0.447s
因此,当我们即使把 DWDPRLD
设置为最大,得到的看门狗溢出时间也只有 0.447 秒,这对于我们实际程序而言并不够用,那么是否有解决方法呢?实际上是有的,我们可以减小时钟频率,即减小 RTLCLK
。有关改变时钟的操作,在我之前的文章中也有简单介绍,这里我粘贴出链接供大家参考:
如果点击无法进行跳转,可自行复制以下链接进行跳转:
- 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 进行详细的入门指导,欢迎读者关注!!!
目前暂时没有考虑整合的打算,所以各位读者如果需要看别的教程,可以点进 专栏 进行查找。在后续的更新中,将会逐步加入各个文章的链接,以便大家快速翻阅。另外源码会逐步开源。
欢迎广大读者提出问题以及修改意见,本人看到后会给予回应,欢迎留言,后续会逐步进行开源!!!
另外,由于文章是作者手打的文字,有些地方可能文字会出错,望谅解,也可私信联系我,我对其进行更改。
-
个人CSDN账号:刘梓谦_-CSDN博客
-
GitHub:Jiahao-Liu29 (github.com)