關(guān)于獨(dú)立看門狗的一點(diǎn)經(jīng)驗(yàn)
2023/4/4 10:20:21??????點(diǎn)擊:
stm32基本都內(nèi)置兩種看門狗(另外還有外置的看門狗芯片),窗口看門狗和獨(dú)立看門狗,兩種看門狗的使用方法和應(yīng)用場(chǎng)景各不相同。今天,我們主要講一講最常用的獨(dú)立看門狗(工作這么多年,沒(méi)見誰(shuí)用過(guò)窗口看門狗,這種估計(jì)在時(shí)序嚴(yán)格的場(chǎng)合會(huì)用上)。
所謂看門狗,外形雖然不像(一堆電子電路,肯定不像),但行為真的狗,還是一條瘋狗。為啥這么說(shuō)呢?
這只狗一定要在規(guī)定以內(nèi)的時(shí)間(這個(gè)時(shí)間自己設(shè)置)喂食,超出一點(diǎn)都不行,否則就咬人(復(fù)位整個(gè)程序,讓你的人生重新來(lái)過(guò))
但是,瘋狗用的好,就是一條專業(yè)的好狗,比誰(shuí)都敬業(yè)(雖然會(huì)有點(diǎn)飄哈,因此喂狗的時(shí)間不能卡太死,需要有充足的余量)。所以,絕大部分產(chǎn)品都會(huì)用上看門狗,以防意外情況發(fā)生,可以有重頭再來(lái)的機(jī)會(huì)。
但喂狗也有方法,不能隨便喂,不然狗的行為就不專業(yè)了(該復(fù)位的時(shí)候不復(fù)位)。所以需要專業(yè)的調(diào)教。
比如,喂狗的地方一般只有一個(gè)地方,并且是一定會(huì)執(zhí)行的。
裸機(jī)時(shí),一般放主循環(huán)while(1)里面定時(shí)執(zhí)行(沒(méi)必要太頻繁)。
RTOS時(shí),一般放在優(yōu)先級(jí)最低的任務(wù)中執(zhí)行,或者空閑任務(wù)中(使用鉤子函數(shù))。
千萬(wàn)千萬(wàn)不要在中斷處理程序中喂狗,因?yàn)榭赡苣愕闹鞒绦蛞呀?jīng)跑死,中斷還好好的運(yùn)行呢(如果要用中斷觸發(fā),可以在中斷處理程序中只設(shè)置一個(gè)變量標(biāo)志位,然后在另外位置判斷標(biāo)志位決定是否喂狗)。
但是看門狗只是一個(gè)預(yù)防措施,而不是一個(gè)正常行為,因此開發(fā)過(guò)程中,一定要關(guān)注看門狗是否出現(xiàn)復(fù)位現(xiàn)象,只要出現(xiàn)一次,都要揪出問(wèn)題的根本原因,否則到了市場(chǎng)上一定會(huì)復(fù)位的。
引起程序復(fù)位的原因有很多種,比如上電、掉電,那么如何看是否由看門狗引起的呢?有個(gè)寄存器是可以看到具體原因的,比如stm32f1 (其他的可以自己查手冊(cè))。
1 hw_cpu_reset_flag_t hw_cpu_reset_get(void)
2 {
3 hw_cpu_reset_flag_t temp = {.value = 0};// 自定義的一個(gè)結(jié)構(gòu)變量,方便使用
4
5 if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
6 {
7 temp.flag.power = 1;
8 }
9 if(RCC_GetFlagStatus(RCC_FLAG_LPWRRST)!= RESET)
10 {
11 temp.flag.low_power = 1;
12 }
13 if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
14 {
15 temp.flag.pin_reset = 1;
16 }
17 if(RCC_GetFlagStatus(RCC_FLAG_SFTRST)!= RESET)
18 {
19 temp.flag.software_reset = 1;
20 }
21 if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
22 {
23 temp.flag.independent_dog = 1;
24 }
25 if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST)!= RESET)
26 {
27 temp.flag.window_dog = 1;
28 }
29
30 RCC_ClearFlag();//清除RCC中復(fù)位標(biāo)志
31
32 return temp;
33 }
另外,在調(diào)試過(guò)程中,我們可以一開始就禁用看門狗(一般在調(diào)試寄存器中)比如 :
DBGMCU_Config (DBGMCU_IWDG_STOP, ENABLE);
需要注意的是,即使在在線調(diào)試環(huán)境下,一旦全速運(yùn)行,如果程序喂狗不及時(shí),仍然會(huì)引起復(fù)位(這也是我們希望的,可以在調(diào)試過(guò)程中發(fā)現(xiàn)喂狗是否有問(wèn)題)《代碼調(diào)著調(diào)著就失聯(lián)了???》
如果我們的代碼已經(jīng)下載到單片機(jī),但又沒(méi)用設(shè)置該位,如果你采用魚鷹之前介紹的抓現(xiàn)場(chǎng)環(huán)境的方法(關(guān)鍵字 顛覆認(rèn)知),那么也可能會(huì)引起看門狗的復(fù)位,因此我們既可以在寄存器界面手動(dòng)設(shè)置(看你手速快不快,能不能在復(fù)位前設(shè)置),也可以通過(guò) *.ini 文件設(shè)置該寄存器完成(建議使用該方法,不用拼手速,哈哈)
*.ini 禁用看門狗:
1 _WWORD (0xE0042004, 0x100); // 注意該代碼會(huì)將其它位清零。可以采用下面這種方式
2 //
3 DEFINE int temp;
4 temp = _RWORD (0xE0042004); // CSR address
5 temp |= 0x100;
所謂獨(dú)立(Independent watchdog),就是該看門狗有獨(dú)立的時(shí)鐘源供看門狗使用,VIP專屬。這樣即使程序跑飛,或者主時(shí)鐘掛掉,照樣運(yùn)行。但是精度嘛,你懂的(VIP用戶一般比較飄)。
所謂看門狗,外形雖然不像(一堆電子電路,肯定不像),但行為真的狗,還是一條瘋狗。為啥這么說(shuō)呢?
這只狗一定要在規(guī)定以內(nèi)的時(shí)間(這個(gè)時(shí)間自己設(shè)置)喂食,超出一點(diǎn)都不行,否則就咬人(復(fù)位整個(gè)程序,讓你的人生重新來(lái)過(guò))
但是,瘋狗用的好,就是一條專業(yè)的好狗,比誰(shuí)都敬業(yè)(雖然會(huì)有點(diǎn)飄哈,因此喂狗的時(shí)間不能卡太死,需要有充足的余量)。所以,絕大部分產(chǎn)品都會(huì)用上看門狗,以防意外情況發(fā)生,可以有重頭再來(lái)的機(jī)會(huì)。
但喂狗也有方法,不能隨便喂,不然狗的行為就不專業(yè)了(該復(fù)位的時(shí)候不復(fù)位)。所以需要專業(yè)的調(diào)教。
比如,喂狗的地方一般只有一個(gè)地方,并且是一定會(huì)執(zhí)行的。
裸機(jī)時(shí),一般放主循環(huán)while(1)里面定時(shí)執(zhí)行(沒(méi)必要太頻繁)。
RTOS時(shí),一般放在優(yōu)先級(jí)最低的任務(wù)中執(zhí)行,或者空閑任務(wù)中(使用鉤子函數(shù))。
千萬(wàn)千萬(wàn)不要在中斷處理程序中喂狗,因?yàn)榭赡苣愕闹鞒绦蛞呀?jīng)跑死,中斷還好好的運(yùn)行呢(如果要用中斷觸發(fā),可以在中斷處理程序中只設(shè)置一個(gè)變量標(biāo)志位,然后在另外位置判斷標(biāo)志位決定是否喂狗)。
但是看門狗只是一個(gè)預(yù)防措施,而不是一個(gè)正常行為,因此開發(fā)過(guò)程中,一定要關(guān)注看門狗是否出現(xiàn)復(fù)位現(xiàn)象,只要出現(xiàn)一次,都要揪出問(wèn)題的根本原因,否則到了市場(chǎng)上一定會(huì)復(fù)位的。
引起程序復(fù)位的原因有很多種,比如上電、掉電,那么如何看是否由看門狗引起的呢?有個(gè)寄存器是可以看到具體原因的,比如stm32f1 (其他的可以自己查手冊(cè))。
代碼實(shí)現(xiàn):
1 hw_cpu_reset_flag_t hw_cpu_reset_get(void)
2 {
3 hw_cpu_reset_flag_t temp = {.value = 0};// 自定義的一個(gè)結(jié)構(gòu)變量,方便使用
4
5 if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
6 {
7 temp.flag.power = 1;
8 }
9 if(RCC_GetFlagStatus(RCC_FLAG_LPWRRST)!= RESET)
10 {
11 temp.flag.low_power = 1;
12 }
13 if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
14 {
15 temp.flag.pin_reset = 1;
16 }
17 if(RCC_GetFlagStatus(RCC_FLAG_SFTRST)!= RESET)
18 {
19 temp.flag.software_reset = 1;
20 }
21 if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
22 {
23 temp.flag.independent_dog = 1;
24 }
25 if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST)!= RESET)
26 {
27 temp.flag.window_dog = 1;
28 }
29
30 RCC_ClearFlag();//清除RCC中復(fù)位標(biāo)志
31
32 return temp;
33 }
另外,在調(diào)試過(guò)程中,我們可以一開始就禁用看門狗(一般在調(diào)試寄存器中)比如 :
DBGMCU_Config (DBGMCU_IWDG_STOP, ENABLE);
需要注意的是,即使在在線調(diào)試環(huán)境下,一旦全速運(yùn)行,如果程序喂狗不及時(shí),仍然會(huì)引起復(fù)位(這也是我們希望的,可以在調(diào)試過(guò)程中發(fā)現(xiàn)喂狗是否有問(wèn)題)《代碼調(diào)著調(diào)著就失聯(lián)了???》
如果我們的代碼已經(jīng)下載到單片機(jī),但又沒(méi)用設(shè)置該位,如果你采用魚鷹之前介紹的抓現(xiàn)場(chǎng)環(huán)境的方法(關(guān)鍵字 顛覆認(rèn)知),那么也可能會(huì)引起看門狗的復(fù)位,因此我們既可以在寄存器界面手動(dòng)設(shè)置(看你手速快不快,能不能在復(fù)位前設(shè)置),也可以通過(guò) *.ini 文件設(shè)置該寄存器完成(建議使用該方法,不用拼手速,哈哈)
*.ini 禁用看門狗:
1 _WWORD (0xE0042004, 0x100); // 注意該代碼會(huì)將其它位清零。可以采用下面這種方式
2 //
3 DEFINE int temp;
4 temp = _RWORD (0xE0042004); // CSR address
5 temp |= 0x100;
6 _WWORD (0xE0042004, temp);
- 上一篇:雁蕩山之旅(致青春 至實(shí)邦 快樂(lè)起航 共登高峰) 2023/4/10
- 下一篇:詳解二極管限幅電路 2023/3/27