前言,和 Watchdog 電路的初相遇:

話說,其實筆者大學念的是物理系,研究所念的還是物理。來搞這些電路或是 Firmware 單晶片軟體大家會不會覺得很奇怪呀?😬

其實一點也不奇怪,一流的物理實驗,當然那些實驗儀器都不可能是現成的。都是教授自己根據實驗需求設計,慢慢建構出來的。所以只要是走實驗物理方向的物理系老師或學生,除了物理理論的本業外,會點基本電路跟電腦儀器控制這些其實也算是基本功。真空技術,各種的實驗方法跟感測器的熟悉,這些其實也是實驗物理裡面基本的素養。就這樣,自然當從研究所畢業後,就誤打誤撞的跑去一家半導體設備商磨練跟工作。

剛畢業,第一次在那家設備商接觸到非常龐大的商用半導體機台,真的是和在學校自己所組的那種簡陋的實驗器材,一個是天,一個是地的那種差別。(真的是很大的震撼教育!) 真的是讓剛畢業的我,眼界大開呀!💪

真的是超級興奮的啦!剛畢業的年輕小伙子,薪水不重要,但是求知慾超級旺盛的呀!於是花了幾乎半年,很仔細的一片一片的研究了其中所有的電路,跟控制系統。不得不好好大力稱讚一下,這個設計的人真的是很有一套,整個的控制系統架構設計得非常漂亮,真的讓年輕小伙子有如入劉姥姥的大觀園啊,收穫良多。

那時候的某一天,在研究我們家一塊很重要的介面板的時候,那塊介面板的核心是一顆 8051 單晶片微處理器。有注意到旁邊電路圖旁邊有一些由 NE555 計時器所組成的電路。電路圖把它標示為 WatchDog 電路。第一次看到這個字,啥?? Watch Dog???? 查了翻譯,「看門狗」????? 這個用555 IC 兜出來是什麼鬼???  看門的一隻狗!! 🤪

我們的電路圖 Drawing 上面是有解釋的,仔細研究了一下,上面說 NE555 IC 跟外面的電容,形成了一個單穩態的計時器。當時間到的時候,555計時器觸發,輸出端剛好接在 8051 的 Reset 腳位,這會造成 8051 整個被重置。然後 8051 上有一隻 DIO 腳位輸出,可以用來重置 555 IC 的單穩態電路。

啥???Drawing上面的說明就只有這樣,這樣為什麼這樣會被叫做「看門狗」呀???還是百思不得其解!!

 

最後,想破頭後終於瞭解了,原來關鍵在軟體啊!!!

555 IC 是個計時器,譬如說上面的電容充電到某個程度觸發了輸出就會造成 8051 被 RESET。為了預防 8051 不要被 RESET,所以軟體裡面一段時間就要從DIO送訊號出來,控制讓電容器接地放電。這樣就永遠不會觸發 8051 被 RESET 囉。

這樣看起來似乎很無聊厚,可是是有用途的。一旦哪天 8051 單晶片因為某種原因突然當掉囉,裏頭的程式突然掛掉不運作了。這時候 555 計時器的電容充電到特定電壓(時間)後,因為沒人去讓電容接地放電,所以最後就會觸發 RESET 8051 的動作。就像電腦被重開機一樣,所以最後當掉的軟體又重頭來過,一切又恢復正常運作。

原來這就是「看門狗」啊,就像是一隻狗在電腦旁邊,隨時監看電腦有沒有正常在運作。當發現電腦不動囉,停掉囉,就立刻給它電腦主機上面的 RESET 按鈕給它按下去,這樣整個電腦就又重頭回來,重新工作囉。

頓悟後,那時覺得這樣的電路真的是妙不可言啊。好聰明的作法,所以這是一種重要的容錯設計,當單晶片微處理器突然當掉的時候,立刻自動地把它救回來的重要設計。

在我們家機台內部,偶而會有機會有非常強烈的電磁波干擾,常常有機會把這片上面的 8051 打昏囉。所以這樣看門狗的電路設計是非常必要的。

就這樣,我和 Watchdog 電路的初相遇。

 

Watchdog 的組成

所以看門狗就是一個接在 CPU Reset 腳位的計時器,當它開始計時時 CPU 裡面的軟體要不斷的送訊號出來重置這個計時器。否則計時器時間到了,計時器會反過來 Reset CPU,讓 CPU重頭來過。

CPU 送訊號出來,有點像是心跳 (Heartbeat) 當心跳沒了,計時器計時時間到了會跑過來按 CPU 的 Reset 紐,來拯救這個已經沒有心跳訊號的 CPU。

所以組成的元件就是很簡單的一個硬體計時器而已。

 

ATmega328 的 Watchdog

初識 ArduIno ,一開始還不曉得,後來慢慢瞭解了發現它的微處理內部居然內建 Watchdog 電路,看到下巴都快掉下來了。果然時代不一樣了啊,進步如此神速。當年的 Watchdog 是要自己在外面自己製作的,現在一個不到一百塊台幣的單晶片微處理器,居然是內建的!

既然內建了,我們來徹底研究一下如何使用吧!

要暸解 ATmega 的內建 Watchdog 看門狗功能,從這一張圖開始

Watchdog timer.png

 

這張圖告訴我們, ATmega 內建的 Watchdog 計時器是用 128kHz 的振盪器來提供時脈, WDP0, WDP1, WDP2, WDP3 這四個訊號控制了除頻器的頻率選擇,亦即其實就是控制 Watchdog 的計時時間選擇。

WATCHDOG RESET 訊號就是我們之前在講的,在 Watchdog 計時器的計時未結束前,一定要送個 RESET 訊號來告訴 Watchdog 計時器我還活著,請重新計時。

ATmega 的設計其實蠻有彈性的,當 Watchdog 計時器沒收到軟體來的 WATCHDOG RESET 訊號,最後超過計時時間開始動作的時候。就像之前筆者所介紹的,一般而言通常是要求 MCU RESET 來重置整個處理器。但是這裡可以看到,透過設定 WDE (Watchdog Enable)WDIE (Watchdog Interrupt Enable) 也可以不要重置處理器,而是產生一個 INTERRUPT 的中斷訊號來執行特定的中斷處理程式,這樣的設計讓 Watchdog 的用途又更大了。

所以,設定如下所示

WDT Configuration.png

要啟動 CUP RESET 功能,讓 WDE (Watchdog Enable) 為 1

要啟動 Interrupt 中斷功能,讓 WDIE (Watchdog Interrupt Enable) 為 1

要同時啟動 CPU RESET 且 Interrupt 中斷功能,則讓兩個同時為 1,這時候會先產生一個中斷讓程式去收尾,等中斷完畢後 CPU RESET

WDTON (Watchdog ON) 這是一個叫做 Fuse 的設定。 Fuse 是 AVR 系列單晶片的一種特殊設計,有點像單晶片裡的機器設定。透過寫入不同的值可以無視內部軟體而直接控制整個單晶片的行為。

這裡 WDTON 的這個 Fuse,只要寫入 0 就會強制使用 Watchdog 且是 CPU Reset 的模式,無視 WDE 及 WDIE

 

整個 Watchdog 的控制在,WDTCSR (Watchdog Timer Control Register) 這個暫存器中。

WDTCSR.png

WDIF (Watchdog Interrupt Flag):

這個 bit 當 Watchdog 計時結束被觸發,且在 Interrupt 的中斷模式時則會被設成 1 ,當對應的中斷被執行時則恢復成0

 

WDIE (Watchdog Interrupt Enable):

如前所述,選擇讓 Watchdog Timer 使用 中斷 Interrupt 模式

 

WDCE (Watchdog Change Enable):

這個 bit 用來控制 Watchdog 可以不可以改變狀態。 原廠的 datasheet 是說,當你設定 WDE (Watchdog Enable) 企圖關掉 Wtachdog CPU RESET 模式時,這個 bit 要先設成 1,否則不給你改變狀態。 (奇怪的設計)

 

WDE (Watchdog Enable):

前面也有說了, 1 的話開啟 Watchdog CPU RESET 的模式, 0 的話則關掉。

 

WDP3..0 (Watchdog Timer Prescalar):

用來設定選擇 Watchdog Timer 的計時時間,一共有下列的這些選擇,最短 16ms ,最長 8 秒

WDT Prescale Select.png

WDT Prescale Select2.png

介紹完畢!

 

程式簡介

有了前面的這些介紹,應該對ATmega 的 Watchdog 很有概念囉!

接下來來看一下 Arduino IDE

很奇怪的是,不知道是不是因為 Watchdog 觀念比較深,一般大眾其實對容錯的應用機會很少的原因,Arduino 的官網對 Watchdog 的介紹幾乎沒有。透過 google 了一些資料,發現大家都偷偷地使用 Atmel 官方所發布的 Watchdog 函式庫。

所幸, Arduino 的 IDE 雖然看不到這個函式庫,但是好像是內建的,可以被 include 進來的。

所以,

#include <avr/wdt.h> 把 Atmel 原廠 Watchdog 函式庫包進來使用吧。

這個原廠的 Watchdog 函式庫的使用其實很簡單,就三個函數。

wdt_enable(timer-time)   用來設定 watchdog 計時器的計時時間並啟動 watchdog 計時器開始運作。預設只有 CPU RESET 模式,沒有中斷模式。

timer-time 是 timer 的計時時間,必須是下列的關鍵字:

WDTO_15MS, 計時 15ms

WDTO_30MS, 計時 30ms

WDTO_60MS, 計時 60ms

WDTO_120MS, 計時 120ms

WDTO_250MS, 計時 250ms

WDTO_500MS, 計時 500ms

WDTO_1S, 計時 1000ms

WDTO_2S, 計時 2000ms

WDTO_4S, 計時 4000ms

WDTO_8S, 計時 8000ms

 

wdt_reset()   用來重置 watchdog 計時器的計時,當軟體一段時間沒有送這個訊號出去重置計時器,最後計時器計時結束,CPU被 Reset 或產生中斷來執行中斷函式。

wdt_disable()   用來關閉 watchdog 的運作。

 

程式只是測試用途,所以寫得很簡單。

Arduino CPU Reset 時會執行 Setup() 一次,所以裡面包了一個 Serial.println("Reseting...")  只要終端機看到這行字就知道 Arduino 的 CPU 被 reset 囉。

Pin2 這隻腳位被設定為採用CPU內建的上拉電阻,然後外面用一條線將這個 Pin 接地,所以平常是 Low 的狀態。接線一拔掉因為內建的上拉電阻,所以會自動變成 High。

Watchdog 計時器設定為 1 秒。

 

Loop() 裡面,

先讓 Arduino 內建Pin13 的那顆 LED 改變狀態,閃爍一下。

等個 0.5秒,然後檢查 Pin2 是不是線沒有被拔掉 (Low)? 是的話就 Reset Watchdog,否則就不 Reset ,讓 Watchdog 自己去時間到, RESET CPU 囉

 

測試影片

很精準的,只要 Pin2 的線一拔掉, Watchdog 收不到軟體來的 Reset 心跳,就跑去 Reset CPU 囉!

可以看到 Reseting 的訊息不斷出現。

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Frank Lin(@ohiyooo)分享的貼文

 

 

原始程式碼列表

 

//
//  Watchdog Test
//     Frank Lin  2021.07.11
//


#include <avr/wdt.h>

// Function:
// wdt_enable(timeout), to enable watchdog with specific timer time
//   timeout = enum
//   WDTO_15MS,    15 mS
//   WDTO_30MS,    30 mS
//   WDTO_60MS,    60 mS
//   WDTO_120MS,  120 mS
//   WDTO_250MS,  250 mS
//   WDTO_500MS,  500 mS
//   WDTO_1S,    1000 mS
//   WDTO_2S,    2000 mS
//   WDTO_4S,    4000 mS
//   WDTO_8S,    8000 mS
//
// wdt_disable(), stop watchdog timer
//
// wdt_reset(), kick watchdog
//


#define      LED_Pin 13
#define   button_Pin  2


int LED_Toggle = 0 ;

void setup() {
 pinMode(LED_Pin, OUTPUT);
 pinMode(button_Pin, INPUT_PULLUP);
 Serial.begin(9600);
 Serial.println("Reseting...");

 wdt_enable(WDTO_1S);

}

void loop() {
  
 LED_Toggle = !LED_Toggle;
 if (LED_Toggle)
    digitalWrite(LED_Pin, HIGH);
 else
    digitalWrite(LED_Pin, LOW);
 delay(500);
 if (digitalRead(button_Pin)==LOW)
 {
    wdt_reset();                      // kick watchdog
    Serial.println("kick...");
 }
}



arrow
arrow

    ohiyooo2 發表在 痞客邦 留言(0) 人氣()