一、前言
最近因為項目產品硬件設計有問題,導致設計的一款產品把硬件電源開關,以及硬件系統復位功能去掉了。更嚴重的是,這產品已經開始生產了,硬件已經無法修改,所以軟件必須上看門狗,否則設備死機或是異常后就只能拆設備拔電池復位了。
我們使用的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區的數據就被清除掉了。
將變量定義到IRAM2分區可以使用下面這種方式指定地址:
uint8_t myVariable? __attribute__((at(0x20000FFC)))??;
五、結尾
針對普冉PY32F030 MCU,如果要使用獨立看門狗,需要注意幾點:
1.最好是在燒錄的時候就直接配置啟動硬件看門狗
2.不要使用RTC作為休眠喚醒源進行喂狗
3.最好預留一個IRAM分區,以備不時之需
有些坑,沒踩之前并不知道這是一個坑,對于做嵌入式應用軟件的工程師而言,他并不知道芯片設計上會存在什么樣的缺陷。
如果一顆芯片,價格比別人便宜很多倍,那么在使用的時候就需要特別注意了,為啥它可以做到這么便宜?是不是哪里有坑我們不清楚?就算時間再緊急,最好也要小批量試產之后才能批量使用。
審核編輯:黃飛
?
評論
查看更多