WWDG — 窗口看門狗


1、WWDG  簡介

  窗口看門狗通常被用來監測,由外部干擾或不可預見的邏輯條件造成的應用程序背離正常的運行序列而產生的軟件故障。除非遞減計數器的值在 T6 位變成 0 前被刷新,看門狗電路在達到預置的時間周期時,會產生一個 MCU 復位。如果在遞減計數器達到窗口寄存器值之前刷新控制寄存器中的 7 位遞減計數器值,也會產生 MCU 復位。這意味着必須在限定的時間窗口內刷新計數器。

  STM32 有兩個看門狗,一個是獨立看門狗,一個是窗口看門狗。我們知道獨立看門狗的工作原理就是一個遞減計數器不斷的往下遞減計數,當減到 0之前如果沒有喂狗的話,產生復位。窗口看門狗跟獨立看門狗一樣,也是一個遞減計數器不斷的往下遞減計數,當減到一個固定值 0X40 時還不喂狗的話,產生復位,這個值叫窗口的下限,是固定的值,不能改變。這個是跟獨立看門狗類似的地方,不同的地方是窗口看門狗的計數器的值在減到某一個數之前喂狗的話也會產生復位,這個值叫窗口的上限,上限值由用戶獨立設置。窗口看門狗計數器的值必須在上窗口和下窗口之間才可以喂狗,這就是窗口看門狗中窗口兩個字的含義。

RLR是重裝載寄存器,用來設置獨立看門狗的計數器的值。

TR是窗口看門狗的計數器的值,由用戶獨立設置,WR是窗口看門狗的上窗口值,由用戶獨立設置。

2、 WWDG功能框圖剖析

①窗口看門狗時鍾

  窗口看門狗時鍾來自 PCLK1,PCLK1 最大是 45M,由 RCC時鍾控制器開啟。

②計數器時鍾  

  計數器時鍾由 CK 計時器時鍾經過預分頻器分頻得到,分頻系數由配置寄存器 CFR的位 8:7 WDGTB[1:0]配置,可以是[0,1,2,3],其中 CK計時器時鍾=PCLK1/4096,除以 4096是手冊規定的,沒有為什么。所以計數器的時鍾 CNT_CK=PCLK1/4096/(2^WDGTB),這就可以算出計數器減一個數的時間 T= 1/CNT_CK = Tpclk1 * 4096 * (2^WDGTB)。

③計數器

  窗口看門狗的計數器是一個遞減計數器,共有 7 位,其值存在控制寄存器 CR 的位 6:0,即 T[6:0],當 7 個位全部為 1 時是 0X7F,這個是最大值,當遞減到 T6 位變成 0時,即從0X40 變為 0X3F時候,會產生看門狗復位。這個值 0X40 是看門狗能夠遞減到的最小值,所以計數器的值只能是:0X40~0X7F之間,實際上用來計數的是 T[5:0]。當遞減計數器遞減到 0X40 的時候,還不會馬上產生復位,如果使能了提前喚醒中斷:CFR 位 9 EWI 置 1,則產生提前喚醒中斷,如果真進入了這個中斷的話,就說明程序肯定是出問題了,那么在中斷服務程序里面我們就需要做最重要的工作,比如保存重要數據,或者報警等,這個中斷我們也叫它死前中斷。

④窗口值

  我們知道窗口看門狗必須在計數器的值在一個范圍內才可以喂狗,其中下窗口的值是固定的 0X40,上窗口的值可以改變,具體的由配置寄存器 CFR的位 6:0 W[6:0]設置。其值必須大於 0X40,如果小於或者等於 0X40就是失去了窗口的價值,而且也不能大於計數器的值,所以必須得小於 0X7F。那窗口值具體要設置成多大?這個得根據我們需要監控的程序的運行時間來決定。如果我們要監控的程序段 A運行的時間為 Ta,當執行完這段程序之后就要進行喂狗,如果在窗口時間內沒有喂狗的話,那程序就肯定是出問題了。一般計數器的值 TR設置成最大 0X7F,窗口值為 WR,計數器減一個數的時間為 T,那么時間:(TR-WR)*T應該稍微大於 Ta即可,這樣就能做到剛執行完程序段 A之后喂狗,起到監控的作用,這樣也就可以算出 WR的值是多少。

⑤計算看門狗超時時間

  這個圖來自數據手冊,從圖我們知道看門狗超時時間:Twwdg = Tpclk1 x 4096 x2^wdgtb x (T[5:0] + 1) ms,當 PCLK1 = 30MHZ時,WDGTB取不同的值時有最小和最大的超時時間,那這個最小和最大的超時時間該怎么理解,又是怎么算出來的?

  講起來有點繞,這里我稍微講解下 WDGTB=0 時是怎么算的。遞減計數器有 7位 T[6:0] ,當位 6 變為 0 的時候就會產生復位,實際上有效的計數位是 T[5:0],而且 T6 必須先設置為 1。如果T[5:0]=0 時,遞減計數器再減一次,就產生復位了,那這減一的時間就等於計數器的周期
=1/CNT_CK = Tpclk1 * 4096 * (2^WDGTB) = 1/30 * 4096 *2^0 = 136.53us,這個就是最短的超時時間。如果 T[5:0]全部裝滿為 1,即 63,當他減到 0X40變成 0X3F時,所需的時間就是最大的超時時間=113.7*2^5=136.53*64=8.74ms。同理,當 WDGTB等於 1/2/3 時,代入公式即可。

3、 怎么用 WWDG

  WWDG 一般被用來監測,由外部干擾或不可預見的邏輯條件造成的應用程序背離正常的運行序列而產生的軟件故障。比如一個程序段正常運行的時間是 50ms,在運行完這個段程序之后緊接着進行喂狗,如果在規定的時間窗口內還沒有喂狗,那就說明我們監控的程序出故障了,跑飛了,那么就會產生系統復位,讓程序重新運行。

4 、WWDG喂狗實驗  

硬件設計
1、WWDG一個
2、LED 兩個
WWDG屬於單片機內部資源,不需要外部電路,需要兩個 LED 來指示程序的運行狀態。

軟件設計

配置IWDG的超時時間為T,如果在T之內沒有及時喂狗的話,產生系統復位,並用LED燈的狀態變化來指示。

 

1-如何配置WWDG的超時時間T?
2-如果編寫喂狗函數?
3-在main函數里面的什么地方喂狗比較合適?
能不能在中斷函數里面喂狗?

 

 

//用於記錄看門狗 遞減計數器的值,方便喂狗函數直接使用
static uint8_t wwdg_cnt ;

/*
WWDG 配置函數 * tr :遞減計時器的值, 取值范圍為:0x7f~0x40,超出范圍會直接復位 * wr :窗口值,取值范圍為:0x7f~0x40 * prv:預分頻器值,取值可以是 * @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1(45MHz)/4096)/1 約10968Hz 91us * @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1(45MHz)/4096)/2 約5484Hz 182us * @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1(45MHz)/4096)/4 約2742Hz 364us * @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1(45MHz)/4096)/8 約1371Hz 728us * * 例:tr = 127(0x7f,tr的最大值) wr = 80(0x50, 0x40為最小wr最小值) prv = WWDG_Prescaler_8 * ~728 * (127-80) = 34.2ms < 刷新窗口 < ~728 * 64 = 46.6ms * 也就是說調用WWDG_Config進行這樣的配置,若在之后的34.2ms前喂狗,系統會復位,在46.6ms后沒有喂狗,系統也會復位。 * 需要在刷新窗口的時間內喂狗,系統才不會復位。 */ void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv) { wwdg_cnt = tr;//保存CNT配置,用在喂狗函數 // 開啟 WWDG 時鍾 RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // 設置預分頻器的值 WWDG_SetPrescaler( prv ); // 設置上窗口值 WWDG_SetWindowValue( wr ); // 設置計數器的值,使能WWDG WWDG_Enable(tr); // 清除提前喚醒中斷標志位 WWDG_ClearFlag(); // 配置WWDG中斷優先級 WWDG_NVIC_Config(); // 開WWDG 中斷 WWDG_EnableIT(); }

 

// 喂狗
void WWDG_Feed(void)
{
    // 喂狗,刷新遞減計數器的值,設置成最大WDG_CNT=0X7F
    WWDG_SetCounter( wwdg_cnt );
}
int main(void)
{
    uint8_t wwdg_tr, wwdg_wr;
    
    /* LED 端口初始化 */
    LED_GPIO_Config();
  
    // BLUE 藍色燈亮
    LED3(ON);
    Delay(0XFFFFFF);    
    
    // WWDG配置
    
/* WWDG 配置函數
 * tr :遞減計時器的值, 取值范圍為:0x7f~0x40,超出范圍會直接復位
 * wr :窗口值,取值范圍為:0x7f~0x40
 * prv:預分頻器值,取值可以是
 * @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1(45MHz)/4096)/1   
     約10968Hz 91us
 * @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1(45MHz)/4096)/2     
     約5484Hz    182us
 * @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1(45MHz)/4096)/4     
     約2742Hz    364us
 * @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1(45MHz)/4096)/8   
   約1371Hz    728us
 *      
 * 例:tr = 127(0x7f,tr的最大值)  
 *     wr = 80(0x50, 0x40為最小wr最小值)  
 *         prv =  WWDG_Prescaler_8
 * 窗口時間為728 * (127-80) = 34.2ms < 刷新窗口 < ~728 * 64 = 46.6ms
 * 也就是說調用WWDG_Config進行這樣的配置,若在之后的34.2ms前喂狗,
 * 系統會復位,在46.6ms后沒有喂狗,系統也會復位。
 * 需要在刷新窗口的時間內喂狗,系統才不會復位。    
*/    
    // 初始化WWDG:配置計數器初始值,配置上窗口值,啟動WWDG,使能提前喚醒中斷
    WWDG_Config(127,80,WWDG_Prescaler_8);    
    
    // 窗口值我們在初始化的時候設置成0X5F,這個值不會改變
    wwdg_wr = WWDG->CFR & 0X7F;
    
    while(1)
    {    
        // BLUE 藍色燈
        LED3(OFF);
        //-----------------------------------------------------
        // 這部分應該寫需要被WWDG監控的程序,這段程序運行的時間
        // 決定了窗口值應該設置成多大。
        //-----------------------------------------------------
        
        // 計時器值,初始化成最大0X7F,當開啟WWDG時候,這個值會不斷減小
        // 當計數器的值大於窗口值時喂狗的話,會復位,當計數器減少到0X40
        // 還沒有喂狗的話就非常非常危險了,計數器再減一次到了0X3F時就復位
        // 所以要當計數器的值在窗口值和0X40之間的時候喂狗,其中0X40是固定的。
        wwdg_tr = WWDG->CR & 0X7F;
        
        if( wwdg_tr < wwdg_wr )
        {
            // 喂狗,重新設置計數器的值為最大0X7F
            WWDG_Feed();
        }
    }
}

tr :遞減計時器的值, 取值范圍為:0x7f~0x40,超出范圍會直接復位。並進入下列中斷。

WWDG中斷服務程序,如果發生了此中斷,表示程序已經出現了故障,這是一個死前中斷。在此中斷服務程序中應該干最重要的事,比如保存重要的數據等。

void WWDG_IRQHandler(void)
{
    // 清除中斷標志位
    WWDG_ClearFlag();
    
    //黃燈亮,點亮LED只是示意性的操作,
    //真正使用的時候,這里應該是做最重要的事情
    LED_YELLOW; 
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM