目录
1.主函数流程
2.初始化串口终端
3.定时器/计数器初始化
3.1 配置定时器/计数器1为看门狗模式
3.2 设置周期/64位
3.3 使能看门狗定时器
4.打印串口终端信息
5.主循环
5.1 等待输入字符
5.2 复位看门狗定时器"喂狗"
1.主函数流程
此程序的作用是实现看门狗功能,使用定时器1。用于在程序运行过程中出现错误或陷入死循环等异常情况下复位程序。此程序设定看门狗超时时间为5s。程序运行后在5s内输入任意字符,程序会持续运行,否则系统将复位。主函数如下:
int main(void)
{
// 初始化串口终端 使用串口2
UARTStdioInit();
// 定时器 / 计数器初始化
TimerWatchDogInit();
// 打印串口终端信息
UARTPuts("
Tronlong WatchDog Application......
", -2);
UARTPuts("System is Reset!
", -2);
UARTPuts("If not any character inputs in every 5 seconds, I will reset......
", -2);
// 主循环
for(;;)
{
// 等待输入字符
UARTPutc(UARTGetc());
// 复位看门狗定时器 “喂狗”
TimerWatchdogReactivate(SOC_TMR_1_REGS);
}
}
2.初始化串口终端
UARTStdioInit函数初始化串口终端,使用串口2,细节参考这里:
C6748_UART_EDMA
3.定时器/计数器初始化
TimerWatchDogInit函数对定时器/计数器进行初始化,该函数如下:
void TimerWatchDogInit(void)
{
// 配置 定时器 / 计数器 1 为 看门狗模式
TimerConfigure(SOC_TMR_1_REGS, TMR_CFG_64BIT_WATCHDOG);
// 设置周期 64位
TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER12, TMR_PERIOD_LSB32);
TimerPeriodSet(SOC_TMR_1_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);
// 使能看门狗定时器
TimerWatchdogActivate(SOC_TMR_1_REGS);
}
3.1 配置定时器/计数器1为看门狗模式
TimerConfigure函数配置定时器,定时器可以配置为64位模式、32位chained/unchained模式、看门狗模式。定时器时钟可以是外部输入,也可以采用内部时钟输入。调用该API,定时器的计数器(the Timer counters)将会被清零(be cleared),两个定时器将解除复位状态(are disabled from Reset),当使能两个定时器时,它们将会开始计数。该API如下:
void TimerConfigure(unsigned int baseAddr, unsigned int config)
{
/*
** Set the timer control register. This will only affect the clock
** selection bits. All other fields will be reset and the timer counting
** will be disabled.
*/
HWREG(baseAddr + TMR_TCR) = (config & (TMR_TCR_CLKSRC12 | TMR_TCR_CLKSRC34));
/* Clear the Timer Counters */
HWREG(baseAddr + TMR_TIM12) = 0x0;
HWREG(baseAddr + TMR_TIM34) = 0x0;
/* Clear the TIMMODE bits and Reset bits */
HWREG(baseAddr + TMR_TGCR) &= ~( TMR_TGCR_TIMMODE | TMR_TGCR_TIM34RS |
TMR_TGCR_TIM12RS);
/*
** Select the timer mode and disable the timer module from Reset
** Timer Plus features are enabled.
*/
HWREG(baseAddr + TMR_TGCR) |= (config &
(TMR_TGCR_TIMMODE | TMR_TGCR_TIM34RS |
TMR_TGCR_TIM12RS | TMR_TGCR_PLUSEN));
}
函数首先设置定时器控制器寄存器TCR(timer control register)的CLKSRC12位,这里设为0,使用内部时钟源(internal clock),定时器1内部时钟来源于PLL旁路时钟AUXCLK,即晶振时钟24MHz。可参考这里的
TimerConfigure函数说明:
C6748_GPIO_KEY_TIMER_EventCombine
接着,函数清除64位定时器计数器的高32位计数器TIM34和低32位计数器TIM12,将其设为0。
(指南P1397)
最后,函数设置TGCR(timer global control register)的TIMMODE、TIM34RS、TIM12RS、PLUSEN位,在设置之前要先清除TIMMODE、TIM34RS、TIM12RS位。这里程序将TIMMODE位设为2h,即定时器处于看门狗模式。将TIM34RS和TIM12RS位均设为1,则Timer12和Timer34为非复位状态(not in reset)。然后,看门狗定时器会进入initial state。
(指南P1410)
(指南P1397)
3.2 设置周期/64位
TimerPeriodSet函数设置指定定时器(specified timers)的周期值,该API如下:
void TimerPeriodSet(unsigned int baseAddr, unsigned int timer,
unsigned int period)
{
if(TMR_TIMER12 & timer)
{
/* Write the period for Timer12 */
HWREG(baseAddr + TMR_PRD12) = period;
}
if(TMR_TIMER34 & timer)
{
/* Write the period for Timer34 */
HWREG(baseAddr + TMR_PRD34) = period;
}
}
这里程序设置PRD12值为0x07270E00(120000000),即Timer12的周期值为120000000;设置PRD34值为0,即Timer34的周期值为0。则64位定时器周期值为120000000。因为定时器1时钟来自晶振,为24MHz,故看门狗定时器周期为T=计数周期*(1/24MHz)=120000000/24000000s=5s,即5秒。
3.3 使能看门狗定时器
TimerWatchdogActivate函数首先设置看门狗定时器控制器寄存器WDTCR(watchdog timer control register)的WDEN位为1,使能看门狗定时器;清除WDFLAG标志(看门狗time-out发生标志)为0;并将密钥A5C6写往WDKEY字段(field)。完成该步后,看门狗进入pre-active状态。
然后该函数将密钥DA7E写往WDKEY位,看门狗将进入active状态。该API如下:
void TimerWatchdogActivate(unsigned int baseAddr)
{
/* Enable the watchdog timer. Write the keys in the order */
HWREG(baseAddr + TMR_WDTCR) = ((TMR_WDTCR_WDEN | TMR_WDTCR_WDFLAG) |
(WDT_KEY_PRE_ACTIVE << TMR_WDTCR_WDKEY_SHIFT));
HWREG(baseAddr + TMR_WDTCR) = ((HWREG(baseAddr + TMR_WDTCR) &
(~TMR_WDTCR_WDKEY)) |
(WDT_KEY_ACTIVE << TMR_WDTCR_WDKEY_SHIFT));
}
(指南P1411)
4.打印串口终端信息
UARTPuts函数参考这里:
C6748_I2C
5.主循环
5.1 等待输入字符
在主循环中,程序等待串口2(UART_CONSOLE_BASE)输入字符,
UARTGetc函数参考这里:
C6748_SPI_FLASH
5.2 复位看门狗定时器"喂狗"
当串口2在5s内接收到输入字符后,程序将会对定时器1(timer1)执行喂狗操作。
TimerWatchdogReactivate函数先将密钥A5C6写往WDCTR的WDKEY位,看门狗定时器(这里是定时器1)将进入Service state,然后再将密钥(key)DA7E写往WDKEY,看门狗定时器将回到active state,同时定时器计数器被清零。该API如下:
void TimerWatchdogReactivate(unsigned int baseAddr)
{
/* Write the first keys in the order. This order shall not change */
HWREG(baseAddr + TMR_WDTCR) = ((HWREG(baseAddr + TMR_WDTCR) &
(~TMR_WDTCR_WDKEY)) |
(WDT_KEY_PRE_ACTIVE << TMR_WDTCR_WDKEY_SHIFT));
HWREG(baseAddr + TMR_WDTCR) = ((HWREG(baseAddr + TMR_WDTCR) &
(~TMR_WDTCR_WDKEY)) |
(WDT_KEY_ACTIVE << TMR_WDTCR_WDKEY_SHIFT));
}
如果在5秒内串口2(UART2)没收到字符,则看门狗将对CPU进行复位。