ARM 看门狗定时器
一、什么是看門狗、有什么用
(1) 看門狗定時器和普通的定時器并無本質區別。定時器可以設定一個時間,在這個時間完成之前定時器不斷計時,時間到的時候,定時器會復位 CPU(重啟系統)。
(2 )系統正常工作的時候當然不希望被重啟,但是系統受到干擾、極端環境等可能會產生異常工作或者不工作,這種狀態可能會造成不良影響(至少是不工作),此時解決方案就是重啟系統。
(3) 普通設備重啟不是問題,但是有些設備人工重啟存在困難。這時候我們希望系統能夠自己檢驗自己是否已經跑飛,并且在意識到自己跑飛的時候,可以很快的(幾個ms或者更短)自我重啟。這個功能就要靠看門狗定時器來實現。
(4) 典型應用的情景是:我們在應用程序中打開看門狗設備,初始化好給它一個時間,然后應用程序使用一個線程來喂狗,這個線程的執行時間安全短于看門狗的復位時間。當系統(或者應用程序)異常后,喂狗線程自然就不工作了,然后到時候看門狗就會復位。
(5) 補充:實戰中有時候為了絕對的可靠,我們并不會用 SoC 中自帶的看門狗,而是使用專門的外置的看門狗芯片來實現看門狗。
二、S5PV210 看門狗定時器的結構框圖
看門狗定時器使用的時鐘域及其頻率。
(1) PCLK_PSYS 經過兩級分頻后生成 WDT(watchdog timer)的時鐘周期,然后把要定的時間寫到 WTDAT 寄存器中,刷到 WTCNT 寄存器中去減 1,減到 0 時(定時時間到)產生復位信號或中斷信號。
(2) 典型應用中是配置為產生復位信號,我們應該在 WTCNT 寄存器減到 0 之前給 WTDAT 寄存器中重新寫值以喂狗。
(3) 注意,看門狗定時器的計數值無法自動裝載。在第一次使能看門狗之前,需要手動裝載看門狗定時器的計數值。
三、看門狗定時器的主要寄存器
1、WTCON
2、WTDAT
3、WTCNT
4、WTCLRINT
四、看門狗定時器的編程實踐
1、產生中斷信號
文件名:wdt.c
#include "stdio.h" #include "init.h"#define WTCON (0xE2700000) #define WTDAT (0xE2700004) #define WTCNT (0xE2700008) #define WTCLRINT (0xE270000C)#define rWTCON (*(volatile unsigned int *)WTCON) #define rWTDAT (*(volatile unsigned int *)WTDAT) #define rWTCNT (*(volatile unsigned int *)WTCNT) #define rWTCLRINT (*(volatile unsigned int *)WTCLRINT)unsigned int pow(unsigned int base, unsigned int exponent) {if (base == 2){return (0x1 << exponent);}else{unsigned int sum = 1, temp = 0;for (temp = 0; temp < exponent; temp++){sum *= base;}return sum;} }/*************************************************************************/#define BIT_LOCATION_WTCON_PRESCALER_VALUE (0xff << 8) #define BIT_WTCON_PRESCALER (pow(2,8))#define WTCON_FUNC_WDT_TIMER_ENABLE (0x1 << 5) #define WTCON_FUNC_WDT_TIMER_DISABLE (0x0 << 5)#define BIT_LOCATION_WTCON_CLOCK_SELECT (0b11 << 3) #define WTCON_FUNC_CLOCK_SELECT_16 (0b00 << 3) #define WTCON_FUNC_CLOCK_SELECT_32 (0b01 << 3) #define WTCON_FUNC_CLOCK_SELECT_64 (0b10 << 3) #define WTCON_FUNC_CLOCK_SELECT_128 (0b11 << 3)#define WTCON_FUNC_INTERRUPT_GENERATION_ENABLE (0x1 << 2) #define WTCON_FUNC_INTERRUPT_GENERATION_DISABLE (0x0 << 2)#define BIT_LOCATION_WTCON_RESET (0b1 << 0) #define WTCON_FUNC_RESET_ENABLE (0x1 << 0) #define WTCON_FUNC_RESET_DISABLE (0x0 << 0)//初始化 WDT 使之可以產生中斷 void wdt_init_interrupt(void) {//第一步,設置好預分頻器和分頻器,得到時鐘周期是 128 usrWTCON &= ~(BIT_LOCATION_WTCON_PRESCALER_VALUE);//t_watchdog = 1/( PCLK / (Prescaler value + 1) / Division_factor )rWTCON |= (65 * BIT_WTCON_PRESCALER); // 1MHZrWTCON &= ~(BIT_LOCATION_WTCON_CLOCK_SELECT);rWTCON |= (WTCON_FUNC_CLOCK_SELECT_128); // 1/128 MHZ, T = 128us//第二步,設置中斷和復位信號的使能或禁止rWTCON |= (WTCON_FUNC_INTERRUPT_GENERATION_ENABLE); // enable wdt interruptrWTCON &= ~(BIT_LOCATION_WTCON_RESET); rWTCON |= (WTCON_FUNC_RESET_DISABLE); //disable wdt reset//第三步,設置定時時間//WDT 定時計數個數,最終定時時間為這里的值 x 時鐘周期rWTDAT = 10000; //定時 1.28srWTCNT = 10000; //定時 1.28s//第四步,先把所有寄存器都設置好之后,再去打開看門狗rWTCON |= (WTCON_FUNC_WDT_TIMER_ENABLE); //enable wdt }//wdt 的中斷處理程序 void isr_wdt(void) {static int i = 0;//看門狗定時器時間到了,應該做的有意義的事情printf("wdt interrupt, i = %d...\r\n", i++);//清除中斷intc_clearVectaddr();rWTCLRINT = 1; }現象截圖:可以看到,wdt 中斷的時間確實是 1.28s左右發生一次。
2、產生復位信號
#include "stdio.h" #include "init.h"#define WTCON (0xE2700000) #define WTDAT (0xE2700004) #define WTCNT (0xE2700008) #define WTCLRINT (0xE270000C)#define rWTCON (*(volatile unsigned int *)WTCON) #define rWTDAT (*(volatile unsigned int *)WTDAT) #define rWTCNT (*(volatile unsigned int *)WTCNT) #define rWTCLRINT (*(volatile unsigned int *)WTCLRINT)unsigned int pow(unsigned int base, unsigned int exponent) {if (base == 2){return (0x1 << exponent);}else{unsigned int sum = 1, temp = 0;for (temp = 0; temp < exponent; temp++){sum *= base;}return sum;} }/*************************************************************************/#define BIT_LOCATION_WTCON_PRESCALER_VALUE (0xff << 8) #define BIT_WTCON_PRESCALER (pow(2,8))#define WTCON_FUNC_WDT_TIMER_ENABLE (0x1 << 5) #define WTCON_FUNC_WDT_TIMER_DISABLE (0x0 << 5)#define BIT_LOCATION_WTCON_CLOCK_SELECT (0b11 << 3) #define WTCON_FUNC_CLOCK_SELECT_16 (0b00 << 3) #define WTCON_FUNC_CLOCK_SELECT_32 (0b01 << 3) #define WTCON_FUNC_CLOCK_SELECT_64 (0b10 << 3) #define WTCON_FUNC_CLOCK_SELECT_128 (0b11 << 3)#define BIT_LOCATION_WTCON_INTERRUPT (0b1 << 2) #define WTCON_FUNC_INTERRUPT_GENERATION_ENABLE (0x1 << 2) #define WTCON_FUNC_INTERRUPT_GENERATION_DISABLE (0x0 << 2)#define BIT_LOCATION_WTCON_RESET (0b1 << 0) #define WTCON_FUNC_RESET_ENABLE (0x1 << 0) #define WTCON_FUNC_RESET_DISABLE (0x0 << 0)//初始化 WDT 使之可以產生中斷 void wdt_init_interrupt(void) {//第一步,設置好預分頻器和分頻器,得到時鐘周期是 128 usrWTCON &= ~(BIT_LOCATION_WTCON_PRESCALER_VALUE);//t_watchdog = 1/( PCLK / (Prescaler value + 1) / Division_factor )rWTCON |= (65 * BIT_WTCON_PRESCALER); // 1MHZrWTCON &= ~(BIT_LOCATION_WTCON_CLOCK_SELECT);rWTCON |= (WTCON_FUNC_CLOCK_SELECT_128); // 1/128 MHZ, T = 128us//第二步,設置中斷和復位信號的使能或禁止rWTCON &= ~(BIT_LOCATION_WTCON_INTERRUPT); rWTCON |= (WTCON_FUNC_INTERRUPT_GENERATION_DISABLE); // disable wdt interruptrWTCON &= ~(BIT_LOCATION_WTCON_RESET); rWTCON |= (WTCON_FUNC_RESET_ENABLE); //enable wdt reset//第三步,設置定時時間//WDT 定時計數個數,最終定時時間為這里的值 x 時鐘周期rWTDAT = 10000; //定時 1.28srWTCNT = 10000; //定時 1.28s//第四步,先把所有寄存器都設置好之后,再去打開看門狗rWTCON |= (WTCON_FUNC_WDT_TIMER_ENABLE); //enable wdt }//wdt 的中斷處理程序 void isr_wdt(void) {static int i = 0;//看門狗定時器時間到了,應該做的有意義的事情printf("wdt interrupt, i = %d...\r\n", i++);//清除中斷intc_clearVectaddr();rWTCLRINT = 1; }現象截圖:可以看到,定時1s之后,芯片就復位了,不會再打印信息。
源自朱友鵬老師.
總結
以上是生活随笔為你收集整理的ARM 看门狗定时器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数学建模之Python】11.炉温曲线
- 下一篇: 学术论文格式