图7-56 WDT时钟模块寄存器
SAM3S4B复位后,WDV的值为0xfff,允许外部复位,默认情况下,看门狗是处于运行状态,如果用户没有使能看门狗,就需要禁止看门狗,否则需要定时“喂狗”。
看门狗模式寄存器WDT_MR只能写一次,之后,复位后重新加载定时器。
在正常情况下,用户定期向WDT_CR的WDRSTT位置1,重载看门狗定时器。WDRSTT置位后,计数器从WDT_MR重新加载,并重新启动。慢速时钟128分频器也被复位及重新启动。WDT_CR是写保护寄存器,若预设值不正确,对WDT_CR的操作无效,如果发生计数器益处,且WDR_MR的WDRSTEN为1,产生“wdt_fault”,WDT_SR的WDUNF置位。
为防止软件死锁,在0和WDD之间重新加载看门狗,WDD在看门狗模式下WDT_MR中定义。
如果试图在WDV和WDD之间重启看门狗定时器,将会导致看门狗错误,即使看门狗被禁止。这将导致WDT_SR中的WDERR位被修改,wdt_fault生效。若WDD不小于WDV的值时,上述功能是无效的,看门狗定时器允许在0和WDV之间重新启动,不产生错误,芯片缺省的复位状态时WDV=WDD。
如果WDFIFN=1,WDRSTEN=0,则WDUNF(看门狗溢出)和WDERR(看门狗错误)置位,触发中断;如果WDFIFN=1,WDRSTEN=1,则触发wdt_fault,复位,WDERR,WDUNF被清零。
如果复位已经产生,读WDT_SR寄存器,状态复位,中断被清楚,此时wdt_fault无效,执行WDT_MR写操作,将重新加载计数器,是CPU复位。
在调试和空闲状态,WDT_MR中的WDIDLEHLT和WDDBGHLT置位,看门狗计数器停止运行。
表7-18控制寄存器
偏移 | 寄存器功能 | 名称 | 权限 | 复位值 |
0x00 | 控制寄存器 | WDT_CR | 只写 | - |
0x04 | 模式寄存器 | WDT_MR | 只读一次 | 0x3FFF_2FFF |
0x08 | 状态寄存器 | WDT_SR | 只读 | 0x0000_0000 |
WDT看门狗软件设计与分析
定义看门的结构体
typedefstruct {
WoReg WDT_CR; /*控制寄存器 */
RwReg WDT_MR; /*模式寄存器 */
RoReg WDT_SR; /*WDT 状态寄存器 */
} Wdt;
获取看门狗的定时时间程序:
uint32_t wdt_get_timeout_value(uint32_t ul_us, uint32_t ul_sclk)
{
uint32_t max, min;
//3000*1000 属于3.9 ~16000*1000之间//min = 128 * 1000000 / ul_sclk;//3000*1000
min = WDT_SLCK_DIV * 1000000 / ul_sclk;
max = min * WDT_MAX_VALUE;//max = min * 4095;
if ((ul_us< min) || (ul_us> max)) {
return WDT_INVALID_ARGUMENT;
}
return WDT_MR_WDV(ul_us / min);//ul_us/min=768=256*3;
}
看门狗初始化程序:
voidwdt_init(Wdt *p_wdt, uint32_t ul_mode, uint16_t us_counter,
uint16_t us_delta)
{
p_wdt->WDT_MR=ul_mode| WDT_MR_WDV(us_counter) | WDT_MR_WDD(us_delta);
// ul_mode|0x300|(0x300<<16);
printf("p_wdt->WDT_MR= %x",p_wdt->WDT_MR);
}
喂狗程序:
voidwdt_restart(Wdt *p_wdt)
{
p_wdt->WDT_CR = WDT_KEY_PASSWORD | WDT_CR_WDRSTT;// 0x5a000000 |1
}
获取看门狗寄存器状态程序:
uint32_t wdt_get_status(Wdt *p_wdt)
{
returnp_wdt->WDT_SR;
}
获取看门狗定时器溢出时间程序:
uint32_t wdt_get_us_timeout_period(Wdt *p_wdt, uint32_t ul_sclk)
{
return WDT_MR_WDV(p_wdt->WDT_MR) * WDT_SLCK_DIV / ul_sclk * 1000000;
}
看门狗中断处理函数:
voidWDT_Handler(void)
{
gpio_set_pin_high(LED2_GPIO);//关闭LED2
gpio_set_pin_low(LED1_GPIO);//打开LED1;
puts("Enter watchdog interrupt.");
wdt_get_status(WDT);//获取WDT状态寄存器
wdt_restart(WDT);//看门狗复位
puts("The watchdog timer was restarted.");
}
在主程序中,初始化串口,打印相关信息,初始化看门狗3S为溢出,产生中断的时间,初始化按键BUTTON2,LED灯。
int main(void)
{
Uart *p_uart=(Uart *)0x400e0600;//串口地址定义
uint32_t wdt_mode, timeout_value;
/* 系统初始化 */
sysclk_init();
//此处不能禁止看门狗,因为WDT->WDT_MR只能进行一次写操作,禁止操作意味着写进去的数值为0,此后写入的数据溢出时无效
pio_configure_group(PINS_UART0_PIO,PINS_UART0,PINS_UART0_FLAGS);
configure_console(); //串口配置
SysTick_Config(sysclk_get_cpu_hz() / 1000);//系统systick,1ms中断
timeout_value = wdt_get_timeout_value(WDT_PERIOD * 1000,
BOARD_FREQ_SLCK_XTAL);//看门狗溢出时间为3S=0X300
if (timeout_value == WDT_INVALID_ARGUMENT) {
while (1) {//中断中的处理
}
}
/* 配置 WDT 触发中断.*/
wdt_mode = WDT_MR_WDFIEN |/*使能WDT看门狗出错中断. */
WDT_MR_WDRPROC |/* WDT出错处理. */
WDT_MR_WDDBGHLT |/* WDT 停止与调试状态. */
WDT_MR_WDIDLEHLT;/* WDT 进入空闲状态. */
wdt_init(WDT, wdt_mode, timeout_value, timeout_value);//初始化看门狗
printf("timeout_period=%d",(int)wdt_get_us_timeout_period(WDT, BOARD_FREQ_SLCK_XTAL));
/*配置和使能看门狗中断. */
NVIC_DisableIRQ(WDT_IRQn);
NVIC_ClearPendingIRQ(WDT_IRQn);
NVIC_SetPriority(WDT_IRQn, 0);
NVIC_EnableIRQ(WDT_IRQn);
//配置LED灯,
gpio_configure_pin(LED1_GPIO, LED0_FLAGS);
gpio_configure_pin(LED2_GPIO, LED1_FLAGS);
gpio_set_pin_high(LED1_GPIO);
pmc_enable_periph_clk(ID_PIOA);
//按键2配置
gpio_configure_pin(BUTTON_2, BUTTON_INPUT);//add by luyj 2013.6.8
while(1)
{
/* 在指定时间启动看门狗. */
if (g_b_systick_event == true) {
g_b_systick_event = false;
if ((g_ul_ms_ticks% WDT_RESTART_PERIOD)==0) {
printf("2s"); // 2s打印一次,提示该喂狗了,此时按键喂狗,
}
}
if (pio_get(PIOA, PIO_TYPE_PIO_INPUT, PIO_PA0) == 0)
{
mdelay(100);
if (pio_get(PIOA, PIO_TYPE_PIO_INPUT, PIO_PA0) == 0)
{
printf("PUSH BUTTON 2!");
wdt_restart(WDT);//喂狗,
gpio_set_pin_low(LED2_GPIO); //LED2亮
gpio_set_pin_high(LED1_GPIO);//LED1灭
}
}
}
}
将程序下载入传感板,运行程序,看门狗中断时,LED1被点亮,LED2被关闭,认为看门狗溢出,同时如果调试串口打开(115200,无校验,数据位8bit,停止位1bit),可以看到打印信息。
喂狗可以通过按键操作,按下K2,表示喂狗,当喂狗时,LED1被关闭,LED2被点亮,在3秒内及时喂狗,则不触发看门狗中断,LED1将处于关闭状态。
本文出自 “嵌入式学习天地” 博客,出自http://farsight.blog.51cto.com/1821374/1344030