-
When given the choice between being right or being kind, choose kind.
當你要在正确和善良之間做選擇的時候,選擇善良。
一、 在RTOS使用看門狗的政策
在由單片機構成的微型計算機系統中,由于單片機的工作常常會受到來自外界電磁場的幹擾,造成程式的跑飛,而陷入死循環,程式的正常運作被打斷,由單片機控制的系統無法繼續工作,會造成整個系統的陷入停滞狀态,發生不可預料的後果,是以出于對單片機運作狀态進行實時監測的考慮,便産生了一種專門用于監測單片機程式運作狀态的晶片,俗稱“看門狗”(watchdog)。”
看門狗通常是一個定時器,定時器定時到預定時間就會産生複位信号讓單片機複位。要想避免看門狗複位單片機,要及時“喂狗”(恢複定時器初始值),也就是說隻要程式能正常運作,就能及時喂狗,避免複位。反之,若程式跑飛,則無法及時喂狗,導緻單片機能夠複位,解決了程式跑飛的問題。
1.1、回顧裸機中看門狗的使用
通常在裸機中程式設計的時候,一般都是一個大循環,采用時間片的方式去執行各種形式的任務。通常選擇一個固定的時間片(比如每5ms)給看門狗喂狗,當然遇到一些可能會操作比較久的任務時,會追加一些額外的喂狗操作。
1.2、RTOS中使用看門狗
檢視了網上很多關于如何在RTOS中使用看門狗的政策,其實每種政策都有其使用場景,下面主要提到的幾種方式。
-
1、建立一個看門狗的定時任務,并将該任務定義為最低優先級。
這種方式需要保證看門狗定時器的溢出時間一般要足夠長,且單片機不是經常滿負荷運作。(保證CPU的使用權不是一直被高優先級的線程搶占)
-
2、建立一個看門狗的定時任務,并将該任務定義為最高優先級。
這種方式保證了喂狗的及時性,但是如果隻有低優先級的任務死了(經曆少,倒是沒遇到過),這種方式下的看門狗就起不到作用。
-
3、多任務監測實作思路
将看門狗“喂狗”置于最高優先級,每個任務(或者某幾個重要的任務)定時向看門狗任務法消息,如果看門狗任務在一定時間内收全其他任務發來的消息才喂狗。這保證了能夠監測盡量多的任務。
二、RT-thread&STM32 中使用看門狗
使用STM32CubeMX來配置STM32的内部看門狗,逾時時間為1000ms。

我們定義一個線程每200ms喂一次狗,優先級為RT_THREAD_PRIORITY_MAX-2。(這裡隻是舉例,任務多了得仔細考慮如何喂狗)
extern IWDG_HandleTypeDef hiwdg;
/* 200ms 喂一次看門狗 */
static void iwdg_control(void *parameter)
{
int i = 0;
while(1)
{
rt_thread_mdelay(200);
i++;
/* Refresh IWDG: reload counter */
HAL_IWDG_Refresh(&hiwdg);
rt_kprintf("第%d次喂狗\n",i);
}
}
static rt_thread_t iwdg_tid = RT_NULL;
int iwdg_init(void)
{
/* 建立電機線程*/
iwdg_tid = rt_thread_create("iwdg_thread", // 線程名字
iwdg_control, // 線程入口函數
RT_NULL, // 線程入口參數
512, // 堆棧大小,
RT_THREAD_PRIORITY_MAX-2, // 線程優先級
5); // 時間片長度
/* 如果獲得線程控制塊,啟動這個線程 */
if (iwdg_tid != RT_NULL)
rt_thread_startup(iwdg_tid);
return 0;
}
INIT_DEVICE_EXPORT(iwdg_init); // 自動初始化
效果如下:
接下來屏蔽喂狗操作,可以看到看門狗起作用了,單片機不斷複位。
extern IWDG_HandleTypeDef hiwdg;
/* 200ms 喂一次看門狗 */
static void iwdg_control(void *parameter)
{
int i = 0;
while(1)
{
rt_thread_mdelay(200);
i++;
rt_kprintf("第%d次200ms\n",i);
}
}
static rt_thread_t iwdg_tid = RT_NULL;
int iwdg_init(void)
{
/* 建立電機線程*/
iwdg_tid = rt_thread_create("iwdg_thread", // 線程名字
iwdg_control, // 線程入口函數
RT_NULL, // 線程入口參數
512, // 堆棧大小,
RT_THREAD_PRIORITY_MAX-2, // 線程優先級
5); // 時間片長度
/* 如果獲得線程控制塊,啟動這個線程 */
if (iwdg_tid != RT_NULL)
rt_thread_startup(iwdg_tid);
return 0;
}
INIT_DEVICE_EXPORT(iwdg_init); // 自動初始化
可以看到每5次200ms,單片機就會重新開機。
參考資料
- STM32CubeMX系列教程15:看門狗(WDG)
- 單片機看門狗定義及其作用分析
- 如何在RTOS中使用看門狗定時器?
- 第29章 FreeRTOS獨立看門狗監測任務執行狀态
- M3 + MDK RTOS + 硬體看門狗 + 獨立看門狗 = 随機性當機
- RTOS 與看門狗的親密合作
- UC/OS-II,多任務喂狗實作
- 對于使用嵌入式作業系統的工程如何使用看門狗
- [讨論] 大家ucos裡面還用看門狗嗎?
- 如何在RTOS中使用看門狗定時器?
- freertos - 在多任務環境中,給看門狗提供的政策