天天看點

RTOS中如何使用看門狗 ---- 以RT-thread為例

  • 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。

RTOS中如何使用看門狗 ---- 以RT-thread為例

我們定義一個線程每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); // 自動初始化
           

效果如下:

RTOS中如何使用看門狗 ---- 以RT-thread為例

接下來屏蔽喂狗操作,可以看到看門狗起作用了,單片機不斷複位。

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,單片機就會重新開機。

RTOS中如何使用看門狗 ---- 以RT-thread為例

參考資料

  • STM32CubeMX系列教程15:看門狗(WDG)
  • 單片機看門狗定義及其作用分析
  • 如何在RTOS中使用看門狗定時器?
  • 第29章 FreeRTOS獨立看門狗監測任務執行狀态
  • M3 + MDK RTOS + 硬體看門狗 + 獨立看門狗 = 随機性當機
  • RTOS 與看門狗的親密合作
  • UC/OS-II,多任務喂狗實作
  • 對于使用嵌入式作業系統的工程如何使用看門狗
  • [讨論] 大家ucos裡面還用看門狗嗎?
  • 如何在RTOS中使用看門狗定時器?
  • freertos - 在多任務環境中,給看門狗提供的政策

繼續閱讀