最近在做低功耗項目時,遇到了看門狗不好處理的問題。在 ST 的各系列 MCU 中,看門狗應該算是使用配置起來最簡單的一個外設了。我們通常僅需要配置很少的配置項,但是,一旦要配合低功耗模式則配置就比較麻煩了。MCU 中有兩隻狗,一隻叫 Independent watchdog (IWDG);另一隻叫 System window watchdog (WWDG)。下面是這兩隻狗的簡單介紹!
IWDG
IWDG 基本就等同於我們獨立使用的看門狗芯片。最適合那些要求看門狗作爲一個完全獨立的進程在主應用程序之外運行,但時間精度約束較低的應用程序。獨立的看門狗(IWDG)由其自己的專用低速時鐘(LSI)提供時鐘。因此即使主時鐘發生故障,IWDG 仍然可以保持活動狀態。下面是 IWDG 的框圖:
對預分頻寄存器(IWDG_PR)、重裝寄存器(IWDG_RLR)和窗口寄存器(IWDG_WINR)的寫訪問受到保護。要修改它們,用戶必須首先在密鑰寄存器(IWDG_KR)中寫入代碼 0x00005555
。寫入其他任意值,寄存器訪問將再次受到保護。例如,在配置完成 IWDG 後,正常的餵狗操作就會導致寄存器訪問將再次受到保護。
IWDG_KR
當在密鑰寄存器(IWDG_KR)中寫入值 0x0000CCCC
時,計數器開始從 IWDG_RLR 的重置值開始計數。當到達計數值 (0x000) 的時,將生成一個復位信號 (IWDG 復位)。只要在密鑰寄存器(IWDG_KR)中寫入值 0x0000AAAA
,就會在計數器中重新加載 IWDG_RLR 值,並防止產生 IWDG 復位。這就意味着,看門狗一旦啓動將不能被停止,除非 MCU 復位!
IWDG_RLR
重裝寄存器(IWDG_RLR)是一個 12 位的寄存器,最大值爲 0xFFF,裏面裝着要刷新到計數器的值,這個值的大小決定着獨立看門狗的溢出時間。超時時間 Tout = ( 4 * 2^prv ) * rlv / LSI
,單位毫秒;prv:預分頻寄存器值;rlv:重裝值,LSI 取 32(單位 kHz)(注意:不同芯片 LSI 不同,有的是 40)。 下面是不同配置下的超時時間範圍:
計數器
獨立看門狗的計數器是一個 IWDG 內部的 12 位的遞減計數器,用戶無法訪問,最大值爲 0xFFF(與重裝寄存器對應)。當計數器減到 0 時,會產生一個復位信號 IWDG 復位。如果在計數器減到 0 之前刷新了計數器的值(在密鑰寄存器(IWDG_KR)中寫入鍵值 0x0000AAAA
)的話,就不會產生復位信號,重新刷新計數器值的這個動作我們俗稱 餵狗。
窗口選項
通過在窗口寄存器(IWDG_WINR)中設置適當的窗口,IWDG 也可以用作窗口看門狗。如果在計數器大於窗口寄存器(IWDG_WINR)中存儲的值的同時執行重載操作,則會提供復位。用的比較少,這裏不再多說。
配置
以下是 IWDG 的寄存器配置序列(不啓用窗口選項時):
- 通過在密鑰寄存器(IWDG_KR)中寫入
0x0000CCCC
來啓用 IWDG - 通過在密鑰寄存器(IWDG_KR)中寫入
0x00005555
來啓用寄存器訪問 - 通過在預分頻寄存器(IWDG PR)中設置時鐘分頻值( 0 到 7 (看門狗對應的庫文件中有定義好的宏值))
- 寫入重載寄存器(IWDG_RLR)
- 等待寄存器被更新(IWDG SR = 0x00000000)
- 通過在 IWDG_KR 中寫入
0x0000AAAA
,IWDG 就會自動使用 IWDG_RLR 重裝 IWDG 內部的計數器,以防止看門狗復位
WWDG
窗口看門狗通常被用來監測由外部干擾或不可預見的邏輯條件造成的應用程序背離正常的運行序列而產生的軟件故障。除非遞減計數器的值在 T6 位變成 0 前被刷新,看門狗電路在達到預置的時間週期時,會產生一個 MCU 復位。如果在遞減計數器達到窗口寄存器值之前刷新控制寄存器中的 7 位遞減計數器值,也會產生 MCU 復位。這意味着必須在限定的時間窗口內刷新計數器。
WWDG 最適合那些要求看門狗在精確計時窗口起作用的應用程序。WWDG 時鐘是預先從 APB 時鐘中分頻出來的,並且有一個可配置的時間窗口,可以通過編程來檢測異常的晚期或早期應用程序行爲。
看門狗總是在復位後關閉。它是通過在 WWDG_CR 寄存器中設置 WDGA 位來啓用的,除非進行復位,否則不能再次禁用它。
項目中並不使用 WWDG,這裏就不過多介紹了!
調試模式
當 MCU 進入調試模式並使內核暫停止時,根據 DBG 模塊中的配置位,以上兩隻狗要麼繼續正常工作,要麼停止。試想,調試中我們暫停程序執行後,就不能執行餵狗語句,如果看門狗不暫停,系統就會重啓!我們就可以通過以下配置來使的暫停程序執行時,看門狗也暫停。
- DBG_IWDG_STOP: 內核暫停時,IWDG 計數器停止運行
- 0:即使內核暫停,IWDG 仍然運行。上電覆位默認值!
- 1:內核暫停,IWDG 也暫停運行。注意:通常我們使用調試工具進行調試時,調試工具會默認配置該項爲 1。
- DBG_WWDG_STOP: 內核暫停時,WWDG 計數器停止運行
- 0:即使內核暫停,WWDG 仍然運行上電覆位默認值!。
- 1:內核暫停,WWDG 也暫停運行。注意:通常我們使用調試工具進行調試時,調試工具會默認配置該項爲 1。
注意:
- 這裏容易造成調試模式下看門狗暫停不用餵狗錯覺!即使是在調試模式下,不餵狗仍然會產生看門狗復位。看門狗暫停的配置是指,我們在調試下暫停運行的時候(例如遇到斷點的暫停),此時的看門狗也跟着暫停,這樣就會不導致復位了。
- 在使用中發現,當使用 Jlink 仿真器進入調試模式時,Jlink 會自動配置以上的位,ST-Link 則不會自動配置。
- 在使用中發現,當正常調試退出 Jlink 的調試模式時,以上設置並不會被清除!
FLASH 選項中的配置
在 MCU 的 FLASH 部分,有專門的一塊區域:Option bytes,如下圖所示:
這部分的配置選項主要用來讓用戶根據自己的需求配置 MCU 的一些默認行爲,其中就有關於 看門狗的配置。
- IWDG_SW: 看門狗模式選擇
- 0:硬件獨立看門狗。看門狗在開機時自動啓用。就等同於使用獨立的看門狗芯片。
- 1:軟件獨立看門狗。軟件配置之後纔會啓動。默認值!
- IWDG_STDBY: 配置獨立的看門狗計數器在待機模式(Standby mode)下凍結
- 0: 凍結
- 1: 不凍結,待機模式下仍然運行。
- IWDG_STOP: 配置獨立的看門狗計數器在停止模式(Stop mode)下凍結
- 0: 凍結
- 1: 不凍結,待機模式下仍然運行。
通過以上配置我們可以發現,低功耗的看門狗的配置只針對於待機模式(Standby mode)和停止模式(Stop mode)。
低功耗
通過上面的介紹不難看出,看門狗一旦被啓用,將無法停止。那麼,在低功耗下,我們將面臨一個問題:低功耗下程序暫停,無法餵狗將導致看門狗復位!通過上面的介紹,我們大體可以看到幾種方法:
- 使用外部獨立看門狗代替 MCU 內部看門狗。簡單粗暴!但是,外部狗時間一般比較短。例如,我的項目中,喚醒週期最短 16 秒,一般的狗只有幾秒。
- 在待機模式(Standby mode)和停止模式(Stop mode)模式下,可以通過配置來凍結看門狗。但是這不適應與其他低功耗模式!
- 進入低功耗之前利用復位關閉看麼狗,然後根據 RCC 中 CSR 寄存器中的復位類型以及自己的標誌來做相應的處理。具體流程如下:
- 進入低功耗:
- 保存需要的狀態以及運行中的一些狀態(因爲要復位,復位後所有變量將被清空)
- 復位(看門狗自動被關閉),根據 RCC 中 CSR 寄存器中的復位類型以及自己記錄的標誌來決定是否需要進入低功耗還是正常運行
- 如果決定進入低功耗,則需要在進入前修改記錄的狀態;如果是正常運行,則需要配置開啓看門狗
- 退出低功耗:
- 無論何種方式喚醒的 MCU,重新開啓看門狗
- 進入低功耗:
- 使用 RTC 週期性喚醒 MCU,然後餵狗後接着進入低功耗,只在必要的時間才執行實際功能。
其實,上面說了這麼多基本就是一點,STM32 中,低功耗之下的看門狗並沒有太完美的處理辦法!
參考
- RM0351.pdf