一、前言
最近因?yàn)轫?xiàng)目產(chǎn)品硬件設(shè)計(jì)有問題,導(dǎo)致設(shè)計(jì)的一款產(chǎn)品把硬件電源開關(guān),以及硬件系統(tǒng)復(fù)位功能去掉了。更嚴(yán)重的是,這產(chǎn)品已經(jīng)開始生產(chǎn)了,硬件已經(jīng)無法修改,所以軟件必須上看門狗,否則設(shè)備死機(jī)或是異常后就只能拆設(shè)備拔電池復(fù)位了。
我們使用的MCU是普冉的PY32F030,這顆芯片在低功耗應(yīng)用場景下,使用看門狗會(huì)有很多的問題和缺陷,需要非常注意,稍有不慎,就會(huì)出問題。
關(guān)于看門狗在低功耗場景下的應(yīng)用,幾個(gè)問題點(diǎn)可以提前思考一下:
1.看門狗是在中斷中喂狗還是在主程序中喂狗比較好?
2.看門狗初始化可以放到時(shí)鐘初始化之前么?
3.如果時(shí)鐘死掉了,看門狗還能正常工作么?
4.低功耗深度休眠后還需要喂狗么?如果需要,要怎么設(shè)計(jì)?使用什么喚醒設(shè)備喂狗?
5.軟件獨(dú)立看門狗與硬件獨(dú)立看門狗它們有什么區(qū)別?
6.在看門狗初始化之前系統(tǒng)異常了會(huì)怎樣?
7.選項(xiàng)字節(jié)里開啟硬件看門狗與軟件代碼開啟有什么區(qū)別?
8.如果異常不可避免,有沒有一個(gè)地方可以緩存設(shè)備狀態(tài),系統(tǒng)異常復(fù)位后狀態(tài)不被清除?
二、看門狗分類
看門狗的分類,根據(jù)實(shí)現(xiàn)方式的不同,可以分為軟件看門狗和硬件看門狗:
軟件看門狗:通過軟件實(shí)現(xiàn)的一種機(jī)制,通常由系統(tǒng)中的軟件來設(shè)置和管理
硬件看門狗: 嵌入在處理器或芯片中的專用硬件模塊
根據(jù)使用方式的不同,又可以區(qū)分為獨(dú)立看門狗和窗口看門狗:
獨(dú)立看門狗: 獨(dú)立看門狗通常用于監(jiān)控整個(gè)系統(tǒng)的運(yùn)行狀態(tài),而不特定于某個(gè)任務(wù)或進(jìn)程,當(dāng)系統(tǒng)故障,死鎖,無響應(yīng)的時(shí)候,應(yīng)用程序無法進(jìn)行正常喂狗,看門狗超時(shí)從而產(chǎn)生復(fù)位。
窗口看門狗: 窗口看門狗更專注于監(jiān)控特定任務(wù)或進(jìn)程的運(yùn)行狀態(tài),并在特定的時(shí)間窗口內(nèi)完成。比如在某個(gè)任務(wù)中,它的執(zhí)行時(shí)間要求非常高,可以使用窗口看門狗,它有一個(gè)時(shí)間窗口,如果太早喂狗和太晚喂狗,都會(huì)產(chǎn)生異常,正因?yàn)樗构窌r(shí)間有個(gè)時(shí)間窗口,所以才叫窗口看門狗。
我使用的普冉PY32F030系列MCU,它是32位Cortex-M0+的內(nèi)核,里面帶有一個(gè)獨(dú)立看門狗IWDG和一個(gè)窗口看門狗WWDG。
其中,獨(dú)立看門狗和窗口看門狗,還有軟件和硬件的區(qū)別,主要差異是在看門狗的啟動(dòng)方式上不同。下面我們的介紹,主要針對獨(dú)立看門狗。
三、啟動(dòng)看門狗
看門狗的啟動(dòng)有多種方式:
通過接口設(shè)置啟動(dòng)
直接設(shè)置寄存器啟動(dòng)
設(shè)置選項(xiàng)字節(jié)啟動(dòng)
1、通過接口設(shè)置
這里可以直接參考官方sample進(jìn)行初始化:
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(); ? ?}
這里需要特別注意,因?yàn)镮WDG是依賴于LSI時(shí)鐘的,也就是在HAL_IWDG_Init 函數(shù)調(diào)用之前,必須先打開LSI時(shí)鐘。
官方給的sample中,是在HAL_Init()中把LSI時(shí)鐘打開了。當(dāng)你把上面這段代碼移植到你自己工程上,如果你LSI沒有開啟,或者是在HAL_IWDG_Init后面才開LSI時(shí)鐘,你調(diào)用HAL_IWDG_Init就會(huì)一直失敗,系統(tǒng)一直ERROR,整個(gè)MCU會(huì)啟動(dòng)不了。
2、通過寄存器直接設(shè)置
直接往 IWDG_SR,IWDG_RLR,IWDG_KR三個(gè)寄存器地址寫入對應(yīng)的參數(shù),使能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; }
實(shí)際IWDG是有四個(gè)寄存器,還有一個(gè)IWDG_PR,它與前面一樣,如果不初始化時(shí)鐘,看門狗會(huì)啟動(dòng)不了,就算是設(shè)置了,看門狗也是不會(huì)啟動(dòng)。
如果要使能時(shí)鐘,可以添加時(shí)鐘設(shè)置語句:
SET_BIT(RCC->CSR, RCC_CSR_LSION);
直接設(shè)置寄存器有一個(gè)好處,就是在boot中, 因?yàn)閷Υa量要求比較高,可以比較精簡的實(shí)現(xiàn)功能。
3、通過選項(xiàng)字節(jié)配置
MCU上內(nèi)部有一個(gè)小的flash,里面有個(gè)FLASH user option,在這里面可以設(shè)置MCU的一些配置參數(shù)。
這個(gè)參數(shù)是可以通過燒錄器在燒錄的時(shí)候就把參數(shù)配置進(jìn)去,對于已經(jīng)燒錄的設(shè)備,可以通過寫選項(xiàng)字節(jié)的方式把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擦寫時(shí)間參數(shù) */ HAL_FLASH_Init(FLASH_PROGRAM_ERASE_CLOCK_8MHZ); /* 獲取option bytes數(shù)據(jù) */ 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個(gè)一起配置*/ 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)); /* 啟動(dòng)option byte編程 */ HAL_FLASHEx_OBProgram(&OBInitCfg); /* 產(chǎn)生一個(gè)復(fù)位,option byte裝載 */ HAL_FLASH_OB_Launch(); } }
通過選項(xiàng)字節(jié)配置了硬件看門狗之后,芯片會(huì)自動(dòng)開啟LSI時(shí)鐘,這個(gè)時(shí)候,軟件要關(guān)閉LSI時(shí)鐘是關(guān)閉不了的。
軟件獨(dú)立看門狗與硬件獨(dú)立看門狗的區(qū)別:
1.軟件獨(dú)立看門狗通過軟件初始化,可以通過關(guān)閉時(shí)鐘的方式把它關(guān)閉了。
2.如果在設(shè)備上電到看門狗初始化之前系統(tǒng)異常了,看門狗是不生效的,這種情況比較多的出現(xiàn)在軟件初始化的時(shí)候異常卡死。
3.硬件獨(dú)立看門狗通過燒錄器燒錄的時(shí)候配置,或者是通過軟件程序,修改選項(xiàng)字節(jié)里面參數(shù)進(jìn)行修改。
4.硬件獨(dú)立看門狗一但配置上,它從上電的時(shí)候就會(huì)開始生效,停止不了,除非重新修改配置項(xiàng)參數(shù)。
5.硬件獨(dú)立看門狗開啟之后,LSI時(shí)鐘會(huì)自動(dòng)開啟,并且關(guān)閉不了。
四、休眠喚醒喂狗
在低功耗設(shè)備中,MCU更加多的時(shí)候是在深度睡眠的模式,以達(dá)到省功耗的目的。在深度休眠模式下,看門狗還是在正常運(yùn)行的。
也就是說,在深度休眠模式下,還是需要定時(shí)喚醒設(shè)備進(jìn)行喂狗,喂完狗之后,設(shè)備再重新進(jìn)入休眠。
1、常規(guī)方式
官方補(bǔ)充文檔上有介紹,在PY32F030、PY32F003、PY32F002A系列上,在休眠前,需要進(jìn)行下面幾個(gè)操作:
1.關(guān)閉非喚醒源中斷
2.關(guān)閉系統(tǒng)滴答 HAL_SuspendTick();
3.保證RTC穩(wěn)定 while(RTC->DIVL<2);
實(shí)際在使用的時(shí)候,我們比較常用的方式是,使用RTC的秒中斷,在休眠的時(shí)候,每秒喚醒一下設(shè)備,然后進(jìn)行喂狗操作,最后再休眠下去。
2、異常情況
實(shí)際測試的時(shí)候發(fā)現(xiàn),在普冉030使用RTC喚醒喂狗的方式,隨著時(shí)間的推移,設(shè)備會(huì)出現(xiàn)異常導(dǎo)致看門狗復(fù)位。
我們升級五百臺(tái)設(shè)備,24小時(shí)內(nèi),會(huì)有幾臺(tái)設(shè)備偶爾出現(xiàn)該問題,36小時(shí)后,大部分的設(shè)備基本上都會(huì)出現(xiàn)這個(gè)異常。
普冉官方的解釋是,它們RTC作為喚醒源確實(shí)是會(huì)存在這個(gè)問題,沒有好的解決方案,只能是改用LPTIM來做喚醒源。出現(xiàn)這類問題的根本原因是如果休眠的stop指令與喚醒源中斷同一時(shí)間觸發(fā),那么他們芯片就會(huì)掛死。
實(shí)際使用的時(shí)候,使用LPTIM的方式,還是會(huì)存在上面的內(nèi)容,只是出現(xiàn)的概率會(huì)比較低而已。
3、補(bǔ)救方案
上面的異常情況,是設(shè)備在產(chǎn)線上才發(fā)現(xiàn)的,那要怎么解?客戶肯定也是接受不了這種頻繁重啟的情況,特別是在低功耗設(shè)備上。
最后的方式是將RAM進(jìn)行分區(qū),分出一個(gè)IRAM2區(qū),將一些狀態(tài)位保存在IRAM2區(qū),該區(qū)啟動(dòng)的時(shí)候不進(jìn)行初始化,看門狗復(fù)位的時(shí)候,該區(qū)的數(shù)據(jù)也不會(huì)被清除掉。
如果是檢測到看門狗異常導(dǎo)致的復(fù)位,可以通過保存在狀態(tài)位信息恢復(fù)到復(fù)位前的狀態(tài)。
使用IRAM2區(qū)不初始化的方式需要注意一點(diǎn):如果程序分為boot和app兩個(gè)部分,需要在boot和app上同時(shí)設(shè)置該區(qū)域,否則可能在boot運(yùn)行階段,IRAM2區(qū)的數(shù)據(jù)就被清除掉了。
將變量定義到IRAM2分區(qū)可以使用下面這種方式指定地址:
uint8_t myVariable? __attribute__((at(0x20000FFC)))??;
五、結(jié)尾
針對普冉PY32F030 MCU,如果要使用獨(dú)立看門狗,需要注意幾點(diǎn):
1.最好是在燒錄的時(shí)候就直接配置啟動(dòng)硬件看門狗
2.不要使用RTC作為休眠喚醒源進(jìn)行喂狗
3.最好預(yù)留一個(gè)IRAM分區(qū),以備不時(shí)之需
有些坑,沒踩之前并不知道這是一個(gè)坑,對于做嵌入式應(yīng)用軟件的工程師而言,他并不知道芯片設(shè)計(jì)上會(huì)存在什么樣的缺陷。
如果一顆芯片,價(jià)格比別人便宜很多倍,那么在使用的時(shí)候就需要特別注意了,為啥它可以做到這么便宜?是不是哪里有坑我們不清楚?就算時(shí)間再緊急,最好也要小批量試產(chǎn)之后才能批量使用。
審核編輯:黃飛
?
評論
查看更多