当前位置: > 华清远见教育科技集团 > 嵌入式学习 > 讲师博文 > 关于AT91SAM3S4B 中看门狗分析一
关于AT91SAM3S4B 中看门狗分析一
时间:2016-12-14作者:华清远见

WDT看门狗基本原理

看门狗,又叫Watchdog Timer,是一个定时器电路,一般有一个输入,叫喂狗(kicking the dog or service the dog),一个输出到MCU的RST端。MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给WDT清零,如果超过规定的时间不喂狗(一般在程序跑飞时),WDT定时超过预先设定值,就会给出一个复位信号到MCU,使MCU重新开始工作。看门狗的作用就是防止程序发生死循环,或者叫程序跑飞。

在SAM3S系统中,用于看门狗的递减计数器是12位,可以计数的大周期为16s(慢速时钟,32.768Khz),其加载的值为慢速时钟的128分频。

图7-56给出WDT时钟模块寄存器控制逻辑:


图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\r",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.\r");
                wdt_get_status(WDT);//获取WDT状态寄存器
                wdt_restart(WDT);//看门狗复位
                puts("The watchdog timer was restarted.\r");
        }

在主程序中,初始化串口,打印相关信息,初始化看门狗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!\r");
                                        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将处于关闭状态。

发表评论
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)