浅析DSP28035的看门狗模块

背景

嵌入式系统通常会使用DSP来实现控制功能,比如开关电源的数字控制。试想如果DSP中程序出现Bug、崩溃、跑飞了怎么办?如果不及时处理,这对整个嵌入式系统的危害将是不可预料的。

在这里插入图片描述

这时,我们就需要DSP具有一种保护机制:检测程序是否正常运行,如果不正常,就要采取某种保护措施。

其实,不止DSP具有这种机制,大多数嵌入式系统的微处理器为了保证产品的可靠性,都具备这种功能。这种保护机制就是看门狗(Watch Dog)

接下来就来聊聊TI 的TMS320F28035 芯片。

工作原理

鉴于程序跑飞时,CPU已经不再受控制了。那么,看门狗(Watch Dog)肯定是要独立于CPU模块的,而事实上也确实如此,并且看门狗的时钟信号也是通过晶振时钟进行预分频得到的。这就保证了看门狗可以完全不受CPU的影响。

当CPU死机、跑飞、或者运行到一个不明的程序陷阱时,看门狗能识别到这种状况,并产生中断或者复位信号。复位信号将CPU复位,使得CPU重新开始运行;中断信号使得CPU进入中断服务子程序,执行一系列操作。

那么,关键的问题来了:看门狗如何判断CPU是否跑飞了?

其实原理很简单,看门狗嘛,通俗点,从狗狗的角度来看,当主人每日按时给自己狗粮时,主人肯定没问题;但是,如果有一天主人突然没有给它喂饭了,那肯定出问题了啊。

看门狗机制就是如此,CPU要定期向看门狗发送特定信号,表示程序工作正常。具体来讲,看门狗内部有一个8位计数器WDCNTR,每个看门狗时钟周期都会进行加一增计数,当计数溢出时就产生中断或者复位信号;在计数溢出之前,若看门狗接收到CPU发送的特定信号后,就会把计数器清零,重新开始计数,也就不会产生复位或者中断。

CPU发送特定信号给看门狗的这种动作,也就是俗称的“喂狗”。只有定时有效地“喂狗”,才能保证看门狗不会错误地发送复位或中断指令。

结构与寄存器

看门狗模块的结构图如下:

在这里插入图片描述

上面提到了特定信号,定时有效地喂狗,那什么是特定信号?,何为定时?何为有效

特定信号: 0x55+0xAA。

定时:在8位计数器溢出之前进行喂狗。

有效:当且仅当对WDKEY写入0x55 + 0xAA,才会清零计数器。

当计数器溢出时,根据工作模式,看门狗模块会产生复位信号中断信号,该信号是一个有效电平为低电平,脉冲宽度为512个晶振时钟周期OSCCLK的脉冲信号,注意不是系统时钟信号SYSCLKOUT

接下来,再看看与看门狗相关的寄存器。

  • SCSR: 系统控制状态寄存器。主要配置看门狗的模式,包括复位模式和中断模式

  • WDCNTR: 看门狗计数寄存器。8位计数器,(当外接10MHz晶振时,最大喂狗时间: 512 / 10 e 6 ∗ 255 ≈ 13 m s ) 512 / 10e^{6} * 255 \approx 13ms) 512/10e625513ms)​​

  • WDKEY: 看门狗键值寄存器。写入0x55 + 0xAA 计数器复位。

  • WDCR: 看门狗控制寄存器,。WDDIS看门狗屏蔽位,WDPS看门狗时钟预分配位。写入0x0068,关闭看门狗;写入0x0028 开启看门狗,复位后自动使能看门狗(所以在初始化之前,通常先要关闭看门狗,等一切配置好以后,才开启看门狗)

注意:看门狗的时钟WDCLK是晶振(10MHz,具体视硬件而定)频率经过512分频得到,而不是主频SYSCLKOUT

代码

#include "DSP28x_Project.h"       // Device Header file and Examples Include File

int flg_ServiceDog = 0;           // 喂狗标志,这里选择不喂狗
long int loop_cnt = 0;            // 主循环次数
long int wake_cnt = 0;            // 看门狗中断次数


// 看门狗中断服务子函数
__interrupt void wakeint_isr(void)
{
    wake_cnt++;
    // 允许ACK位,准备迎接下一个看门狗中断;看门狗属于 PIE group 1
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}


/**
 * main.c
 */
int main(void)
{
    InitSysCtrl();       // 系统控制初始化,关闭看门狗,使能外设时钟等
    DINT;                // 关闭CPU级总中断
    InitPieCtrl();       // 初始化外设中断扩展配置
    IER = 0x0000;        // 清除CPU级中断使能位,标志位
    IFR = 0x0000;
    InitPieVectTable();  // 初始化中断外设向量表,并使能PIE控制器

    //********************* code start here ****************************//
    EALLOW;
    PieVectTable.WAKEINT = &wakeint_isr;    // 加载看门狗中断服务子程序入口地址到中断向量表
    EDIS;

    EALLOW;
    SysCtrlRegs.SCSR = 0X0002;              // 设置看门狗工作模式,中断模式: 0x0002 ,复位模式: 0x0000
    EDIS;

    PieCtrlRegs.PIEIER1.bit.INTx8 = 1;      // 使能看门狗外设中断,看门狗中断是group1 第8位
    IER |= 0x0001;      // 使能CPU级 group 1
    
    EINT;               // 前面关了,这里开启CPU总中断
    
    ServiceDog();       // 喂狗,清零看门狗计数器 
    EALLOW;
    SysCtrlRegs.WDCR = 0x0028;     // 开启看门狗模块
    EDIS;

    while(1)
    {
        loop_cnt++;
        if(flg_ServiceDog)  // flg_ServiceDog = 0 ,不喂狗
        {
            ServiceDog();   // 喂狗,该函数在官方提供,其实就是向WDKEY写0x0055 + 0x00AA
        }
    }
    //********************* code end here ******************************//
}

实验结果

将CCS编写的程序通过仿真器,编译、烧写到开发板,然后Debug,全速仿真运行,菜单面板【Window->show view->expressions】添加表示式,并查看表达式的值,选中连续刷新,即可看到,在不喂狗的情况下,就会触发看门狗中断,进入中断服务子程序,实时增加wake_cnt的值。

在这里插入图片描述

总结

看门狗非常简单,但却非常实用,是嵌入式系统微处理器必备的一种保护机制。另外,代码中涉及到PIE模块,该模块是28035关于外设中断的一些配置,主要包括中断的开启,关闭,清除,以及中断服务子函数地址的管理等。

  • 7
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rob月初

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值