MCU看門狗使用注意事項

2023-11-29 09:00:17

前言

最近因為專案產品硬體設計有問題,導致設計的一款產品把硬體電源開關以及硬體系統復位功能去掉了。更嚴重的是,這產品已經開始生產了,硬體已經無法修改,所以軟體必須上看門狗,否則裝置宕機或是異常後就只能拆裝置拔電池復位了。

我們使用的MCU是普冉的PY32F030,這顆晶片在低功耗應用場景下,使用看門狗會有很多的問題和缺陷,需要非常注意,稍有不慎,就會出問題。

關於看門狗在低功耗場景下的應用,幾個問題點可以提前思考一下:

  1. 看門狗是在中斷中喂狗還是在主程式中喂狗比較好?
  2. ​看門狗初始化可以放到時鐘初始化之前麼?
  3. 如果時鐘死掉了,看門狗還能正常工作麼?
  4. 低功耗深度休眠後還需要喂狗麼?如果需要,要怎麼設計?使用什麼喚醒裝置喂狗?
  5. 軟體獨立看門狗與硬體獨立看門狗它們有什麼區別?
  6. 在看門狗初始化之前系統異常了會怎樣?
  7. 選項位元組裡開啟硬體看門狗與軟體程式碼開啟有什麼區別?
  8. 如果異常不可避免,有沒一個地方可以快取裝置狀態,系統異常復位後狀態不被清除

(一)看門狗分類

看門狗的分類,根據實現方式的不同,可以分為軟體看門狗和硬體看門狗:

  • 軟體看門狗:通過軟體實現的一種機制,通常由系統中的軟體來設定和管理
  • 硬體看門狗: 嵌入在處理器或晶片中的專用硬體模組

根據使用方式的不同,又可以區分為獨立看門狗和視窗看門狗

  • 獨立看門狗: 獨立看門狗通常用於監控整個系統的執行狀態,而不特定於某個任務或程序,當系統故障,死鎖,無響應的時候,應用程式無法進行正常喂狗,看門狗超時從而產生復位。

  • 視窗看門狗: 視窗看門狗更專注於監控特定任務或程序的執行狀態,並在特定的時間視窗內完成。比如在某個任務中,它的執行時間要求非常高,可以使用視窗看門狗,它有一個時間視窗,如果太早喂狗和太晚喂狗,都會產生異常,正因為它喂狗時間有個時間視窗,所以才叫視窗看門狗。

我使用的普冉PY32F030系列MCU,它是32位元Cortex-M0+的核心,裡面帶有一個獨立看門狗IWDG和一個視窗看門狗WWDG。

其中,獨立看門狗和視窗看門狗,還有軟體和硬體的區別,主要差異是在看門狗的啟動方式上不同。下面我們的介紹,主要針對獨立看門狗。

(二)啟動看門狗

看門狗的啟動有多種方式:

  • 通過介面設定啟動
  • 直接設定暫存器啟動
  • 設定選項位元組啟動

(1)通過介面設定

這裡可以直接參考官方sample進行初始化:

    IWDG_HandleTypeDef   IwdgHandle;
HAL_Init();
/*##-3- Configure & Start the IWDG peripheral #########################################*/
IwdgHandle.Instance = IWDG;
IwdgHandle.Init.Prescaler = IWDG_PRESCALER_32;//T=1MS
IwdgHandle.Init.Reload = (1000); //1ms*1000=1s
IwdgHandle.Init.Window = IWDG_WINDOW_DISABLE;
if(HAL_IWDG_Init(&IwdgHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}

這裡需要特別注意,因為IWDG是依賴於LSI時鐘的,也就是在HAL_IWDG_Init 函數呼叫之前,必須先開啟LSI時鐘。

官方給的sample中,是在HAL_Init()中把LSI時鐘開啟了。當你把上面這段程式碼移植到你自己工程上,如果你LSI沒有開啟,或者是在HAL_IWDG_Init後面才開LSI時鐘,你呼叫HAL_IWDG_Init就會一直失敗,系統一直ERROR,整個MCU會啟動不了。

(2)通過暫存器直接設定

直接往 IWDG_SR,IWDG_RLR,IWDG_KR三個暫存器地址寫入對應的引數,使能IWDG

void init_wtd(void)
{
volatileu int32_t *IWDG_KR_ADDR = (volatileuint32_t *)0x40003000UL;
volatileu int32_t *IWDG_PR_ADDR = (volatileuint32_t *)0x40003004UL;
volatileu int32_t *IWDG_RLR_ADDR = (volatileuint32_t *)0x40003008UL;

*IWDG_KR_ADDR = 0x5555;
*IWDG_PR_ADDR = 0x03;
*IWDG_RLR_ADDR = 0xF40;
}

實際IWDG是有四個暫存器,還有一個IWDG_PR,它與前面一樣,如果不初始化時鐘,看門狗會啟動不了,就算是設定了,看門狗也是不會啟動。

如果要使能時鐘,可以新增時鐘設定語句:

SET_BIT(RCC->CSR, RCC_CSR_LSION);

直接設定暫存器有一個好處,就是在boot中, 因為對程式碼量要求比較高,可以比較精簡的實現功能

(3)通過選項位元組設定

MCU上內部有一個小的flash,裡面有個FLASH user option,在這裡面可以設定MCU的一些設定引數

 這個引數是可以通過燒錄器在燒錄的時候就把引數設定進去,對於已經燒錄的裝置,可以通過寫選項位元組的方式把IWDG_SW置位或是清零。

void Option_config_NRST_to_gpio_hwwdg(void)
{
FLASH_OBProgramInitTypeDef OBInitCfg;

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

/* 初始化flash擦寫時間引數 */
HAL_FLASH_Init(FLASH_PROGRAM_ERASE_CLOCK_8MHZ);

/* 獲取option bytes資料 */
HAL_FLASHEx_OBGetConfig(&OBInitCfg);

//設定Nreset為GPIO
if(((OBInitCfg.USERConfig & OB_RESET_MODE_GPIO) != OB_RESET_MODE_GPIO)||((OBInitCfg.USERConfig & OB_IWDG_SW) == OB_IWDG_SW))
{
/* 修改 USER(RESET , WWDG, IWDG) 設定值 , 注意一定要3個一起設定*/
OBInitCfg.OptionType = OPTIONBYTE_USER;
MODIFY_REG(OBInitCfg.USERConfig, (OB_RESET_MODE_GPIO|OB_WWDG_SW|OB_IWDG_SW), (OB_RESET_MODE_GPIO | OB_WWDG_SW | OB_IWDG_HW));
/* 啟動option byte程式設計 */
HAL_FLASHEx_OBProgram(&OBInitCfg);

/* 產生一個復位,option byte裝載 */
HAL_FLASH_OB_Launch();
}
}

通過選項位元組設定了硬體看門狗之後,晶片會自動開啟LSI時鐘,這個時候,軟體要關閉LSI時鐘是關閉不了的。

軟體獨立看門狗與硬體獨立看門狗的區別

  1. 軟體獨立看門狗通過軟體初始化,可以通過關閉時鐘的方式把它關閉了
  2. 如果在裝置上電到看門狗初始化之前系統異常了,看門狗是不生效的,這種情況比較多的出現在軟體初始化的時候異常卡死。
  3. 硬體獨立看門狗通過燒錄器燒錄的時候設定,或者是通過軟體程式,修改選項位元組裡面引數進行修改
  4. 硬體獨立看門狗一但設定上,它從上電的時候就會開始生效,停止不了,除非重新修改設定項引數。
  5. 硬體獨立看門狗開啟之後,LSI時鐘會自動開啟,並且關閉不了。

(三)休眠喚醒喂狗

在低功耗裝置中,MCU更加多的時候是在深度睡眠的模式,以達到省功耗的目的。在深度休眠模式下,看門狗還是在正常執行的。

也就是說,在深度休眠模式下,還是需要定時喚醒裝置進行喂狗,喂完狗之後,裝置再重新進入休眠。

(1)常規方式

官方補充檔案上有介紹,在PY32F030、PY32F003、PY32F002A系列上,在休眠前,需要進行下面幾個操作:

  1. 關閉非喚醒源中斷
  2. 關閉系統滴答 HAL_SuspendTick();
  3. 保證RTC穩定 while(RTC->DIVL<2);

實際在使用的時候,我們比較常用的方式是,使用RTC的秒中斷,在休眠的時候,每秒喚醒一下裝置,然後進行喂狗操作,最後再休眠下去。

(2)異常情況

實際測試的時候發現,在普冉030使用RTC喚醒喂狗的方式,隨著時間的推移,裝置會出現異常導致看門狗復位。

我們升級五百臺裝置,24小時內,會有幾臺裝置偶爾出現該問題,36小時後,大部分的裝置基本上都會出現這個異常。

普冉官方的解釋是,它們RTC作為喚醒源確實是會存在這個問題,沒有好的解決方案,只能是改用LPTIM來做喚醒源。出現這類問題的根本原因是如果休眠的stop指令與喚醒源中斷同一時間觸發,那麼他們晶片就會掛死。

實際使用的時候,使用LPTIM的方式,還是會存在上面的內容,只是出現的概率會比較低而已。

(3)補救方案

上面的異常情況,是裝置在產線上才發現的,那要怎麼解?客戶肯定也是接受不了這種頻繁重啟的情況,特別是在低功耗裝置上。

最後的方式是將RAM進行分割區,分出一個IRAM2區,將一些狀態位儲存在IRAM2區,該區啟動的時候不進行初始化,看門狗復位的時候,該區的資料也不會被清除掉。

如果是檢測到看門狗異常導致的復位,可以通過儲存在狀態位資訊恢復到復位前的狀態。

 使用IRAM2區不初始化的方式需要注意一點:如果程式分為boot和app兩個部分,需要在boot和app上同時設定該區域,否則可能在boot執行階段,IRAM2區的資料就被清除掉了。

結尾

針對普冉PY32F030 MCU,如果要使用獨立看門狗,需要注意幾點:

  1. 最好是在燒錄的時候就直接設定啟動硬體看門狗
  2. 不要使用RTC作為休眠喚醒源進行喂狗
  3. 最好預留一個IRAM分割區,以備不時之需

有些坑,沒踩之前並不知道這是一個坑,對於做嵌入式應用軟體的工程師而言,他並不知道晶片設計上會存在什麼樣的缺陷。

如果一顆晶片,價格比別人便宜很多倍,那麼在使用的時候就需要特別注意了,為啥它可以做到這麼便宜?是不是哪裡有坑我們不清楚?就算時間再緊急,最好也要小批次試產之後才能批次使用。

 

---------------------------End---------------------------
如需獲取更多內容
請關注 liwen01 公眾號