天天看點

S3C2440看門狗

本文系本站原創,歡迎轉載! 轉載請注明出處:

http://blog.csdn.net/mr_raptor/article/details/6555704

相信大家都看過中國移動前些時間做的一個廣告,從城市到山村,到青藏高原,在哪兒都有中國移動的網絡,到哪兒都能打電話,由此可以聯想到中國移動在全國有無數個信号基站,很多基站建設在環境比較惡劣的地方,我們來思考一個問題?假如,有一天某個基站出了問題不能正常工作了,毫無疑問,移動的從業人員會帶各種檢測裝置去進行修理,如果是出現非硬體故障(如使用者電話服務突然巨增,造成繁忙當機或電磁幹擾造成CPU運作出錯等),導緻基站伺服器出現異常當機,從業人員隻需要進行一個操作,重新開機一下即可。如果該基站安裝在青藏高原上,這樣一次上去,成本是很大的。退一步講,這種情況雖然成本很高,但是還是可以修複的,如果這種情況出現在月球探測器身上,問題就更嚴重了。是以針對這種特殊情況的裝置,我們期待有一種裝置能夠在機器出現非正常情況下進行自動重新開機來恢複工作狀态,使用看門狗定時器就可以完美解決這個問題了。

看門狗WatchDog的名字形象的描述了它的工作原理,看門狗每隔一段時間(比如:3個小時)它就會饑餓,每次饑餓時都叫,如果不想讓它叫,隻要我們保證在3個小時内喂狗一次就行。是以我們要及時的對看門狗控制器執行喂狗操作。

看門狗定時器内部有一個遞減計數器,當該計數器遞減為0的時候,就會自動重新開機控制器(如下圖所示),如果我們寫有這樣的程式,該程式在定時器計數器遞減為0之前,将其遞減計數器重新設定一下(喂狗),那麼就不會産生重新開機操作。假如機器裝置出現異常情況下如當機,CPU執行出錯,程式跑飛等情況,CPU就會陷入非正常的執行流程,就不會去執行重置計數器的程式,當計數器遞減為0時,會産生複位控制器信号,機器就會重新啟動,恢複正常執行流程。這樣的設計原理就解決了很多環境惡劣的情況下,對伺服器進行重新開機的任務。上面的重置倒計數的操作通常叫做“喂狗”。

(1)用于解決遠端控制器在出現電磁幹擾,噪聲,系統錯誤等外界條件造成的系統當機等不正常運作的問題

(2)它不僅可以産生複位信号,還可以通過設定,産生定時的中斷信号

看門狗定時器從單片機時代就開始廣泛使用,是嵌入式産品中的一大特色,很明顯上述用途如果我們都用不到,就沒有必要打開看門狗的功能,在miniOS作業系統裡我們不使用它來定時産生中斷,也不用它來自動重新開機異常的開發闆(因為出現異常的可能性幾乎可以忽略),因為實作miniOs的第一步就是關閉看門狗,在開始裸闆驅動之前,先來了解S3C2440 看門狗定時器。

S3C2440看門狗

圖2-43 S3C2440看門狗定時器工作原理

名詞解釋:

PCLK(Peripherals Clock): APB(Advanced Peripherals  Bus)進階外圍裝置總線上外設的工作時鐘頻率,它主要為開發闆上的外圍低速裝置提供工作時鐘,如序列槽,I2C等,

8-bit Prescaler:8位分頻器,由程式來控制對PCLK進行分頻,它由WTCON寄存器來控制設定。

MUX:多路複合器,它支援多種時鐘源,通過設定它來選擇一種時鐘頻率,看門狗控制器裡會産生四種時鐘頻率,分别是1/16,1/32,1/64,1/128的已分頻時鐘,可以通過WTCON寄存器第3,4位進行選擇設定。

WTCNT:看門狗遞減寄存器,一旦看門狗使能,WTCNT裡的資料(由WTDAT寄存器在使能之前設定)就開始在輸入時鐘頻率下遞減。

Interrupt:中斷信号,由WTCON寄存器的第2位控制是否産生中斷信号。

Reset Signal Generator:Reset信号産生器,預設情況下當遞減寄存器裡的倒計數為0時,會産生通過Reset信号産生器産生Reset信号,讓控制器重新開機,可以由WTCON寄存器的第0位進行設定。

當看門狗使能時,外圍時鐘PCLK為看門狗定時器的輸入時鐘,MINI2440在沒有開啟時鐘時,采用外部晶振(又叫高頻振蕩器,它每秒鐘産生固定頻率時鐘)提供的12MHz輸入時鐘頻率,PCLK首先進入8位分頻器Prescaler,其對PCLK進行分頻,可以了解為對PCLK的除法運算,這樣PCLK的時鐘頻率就變成PCLK/Prescaler value,其中分頻器Prescaler的值可以在一定範圍内自定義,然後經過分頻的時鐘經過除數因子選擇器,這是在分頻器的基礎上再次對時鐘信号進行降頻,通過除數因子選擇器,選擇一個除數因子,然後經過MUX複合器,這時輸入時鐘變成PCLK/ Prescaler value/除數因子,得到我們想要的輸入時鐘, 每個時鐘周期都會将看門狗定時計數器WTCNT裡的值減1,當計數器WTCNT裡的值變為0時開始執行逾時操作,首先,判斷看門狗控制寄存器裡bit2 WTCON[2]設定情況,如果為1則産生中斷信号,引起系統中斷,如果為0不做任何操作,進入複位信号産生器,如果WTCON[0]位為1,則産生控制器複位信号,否則不做任何操作。每次逾時操作之後,看門狗WTCON會自動加載看門狗資料寄存器WTDAT裡的使用者設定值,繼續執行遞減操作。

表2-5看門狗定時器控制寄存器 (WTCON)

寄存器名 位址 是否讀寫 描述 複位預設值
WTCON 0X53000000 R/W 看門狗定時器控制寄存器 0x8021
WTCON 描述 初始值
Prescaler value [15:8] 8位分頻器預設值,有效範圍0~255(28 - 1) 0x80
Reserved [7:6] 保留,正常情況下必須為00 00
Watchdog timer [5]

看門狗定時器使能位

0 = 無效,1 = 有效

1
Clock select [4:3]

選擇除數因子來決定輸入時鐘

00 = 16,01 = 32

10 = 64,11 = 128

00
Interrupt generation [2]

中斷使能位

0 = 無效,1 = 有效

Reserved [1] 保留,正常情況下該位必須為0
Reset enable/disable [0]

複位使能位

1:看門狗定時器逾時,發出CPU複位信号

0:看門狗定時器複位無效

1

表2-6看門狗定時器資料寄存器 (WTDAT)

寄存器名 位址 是否讀寫 描述 複位預設值
WTDAT 0x53000004 R/W 看門狗定時器資料寄存器 0x8000
WTDAT 描述 初始值
Count Reload value [15:0] 該值在逾時後,自動載入計數寄存器 0x8000

注:WTDAT寄存器用于指定計數寄存器的初始值,也就是它的逾時時間,系統上電之後硬體自動的将0x8000的初始值載入到WTCNT裡,在發生了第一次逾時操作時,WTDAT的值才會載入到WTCNT寄存器。

表2-7看門狗定時器計數寄存器 (WTCNT)

寄存器名 位址 是否讀寫 描述 複位預設值
WTCNT 0x53000008 R/W 看門狗定時器計數寄存器 0x8000
WTCNT 描述 初始值
Count value [15:0] 看門狗定時器的目前計數值 0x8000

通過對上面寄存器描述分析,可以得出以下結論:

l  通過設定WTCON[5]來設定看門狗定時器的使能

l  在開啟看門狗定時器後,通過設定WTCON[15:8]和[4:3]位來設定看門狗控制器的工作時鐘頻率,具體看門狗的遞減時間間隔可以通過下面的公式算出:

t_watchdog  = 1/( PCLK / (Prescaler value + 1) / Division_factor )

注: t_watchdog:看門狗控制器遞減時間間隔(機關秒)

     PCLK:APB總線工作時鐘(機關Hz)

     Prescaler value: 8位分頻器預設值

     Division_factor:除數因子

l  通過設定WTCON[2] 和WTCON[0]位,來使能産生中斷和複位信号

l  通過設定WTDAT來設定計數值

MINI2440在沒有初始化系統時鐘時,整個開發闆由一個12MHz的外部晶振提供頻率,PCLK工作頻率也是12MHz,WTCON[15:8]設定為74,除數因子選擇16,通過上面公式可以計算出,看門狗控制器遞減時間間隔0.1毫秒。将WTCNT裡的值設定為0x2710(十進制10000),那麼看門狗會每過一秒鐘産生一次逾時。

; 關閉看門狗實驗

ldr r0, = 0x53000000                       ; WTCON寄存器位址加載到r0

mov r1, #0                                        ; r1 = 0

str r1, [r0]                                         ; 将r1裡的值存到r0裡位址裡

通過分析前面的寄存器的設定位可知,隻要設定WTCON[5]為0即可,上述代碼裡,直接将整個WTCON寄存器裡的位設定為0。

開啟看門狗實驗:

WTCON               EQU          0x53000000        ; 看門狗控制寄存器

WTCNT               EQU          0x53000008        ; 看門狗計數寄存器

         AREA  WATCHDOG_ENABLE,CODE,READONLY

         ENTRY

           ; 設定看門狗控制寄存器

           ldr r0, =WTCON                                      ; 加載WTCON寄存器位址

         ; 0x4a21 = [15:8]=74, [5]=1, [0]=1

         ldr r1, =0x4a21                               ; 将0x4a21儲存到r1裡

         str r1, [r0]                                        ; 将r1裡的值存入r0指向的位址

         ; 設定看門狗計數寄存器,該寄存器的值在上電後被加載, 1秒逾時

         ldr r2, = WTCNT                            ; 加載WTCNT寄存器位址

           ldr r3, =0x2710                               ; 将0x2710儲存到r1裡

         str r3, [r2]                                                ; 将r3裡的值存入r2指向的位址

           IMPORT led_on                             ; 引入led_on符号

         bl led_on                                         ; 調用led_on代碼

loop

           B loop                                             ; 死循環

         END

程式開始定義兩個常量位址,分别是WTCON,WTCNT的位址,ENRTY後面是程式的正文部分,首先通過ldr指令加載WTCON的位址到r0裡,将0x4a21這個數加載到r1裡,0x4a21是我們通過設定WTCON [15:8]=74 [7:6]=0,[5]=1,[4:1]=0, [0]=1得到的16進制數,将其值存入到r0位址裡,這樣WTCON裡就是我們設定各位的值,然後同樣道理再将0x2710存到WTCNT資料寄存器裡,設定資料寄存器的值為0x2710。

為了看到看門狗的重新開機效果,我們加入了一個小程式,用來點亮led燈,将上述代碼在ADS下編譯完後,通過H-JTAG燒寫到NORFLASH裡可以看到每過1秒鐘,開發闆的led燈就閃一下。

知識擴充

開啟了看門狗之後,控制器會定時的複位,為了防止不停的複位,就要進行“喂狗”操作,喂狗操作相對比較簡單,隻要在WTCNT裡的計數減為0之前,将其值重置一個非0的數值即可,看下面的函數:feed_dog(該代碼僅供讀者參考,CD光牒源碼中沒有給出具體例子)

; 喂狗程式

feed_dog

           ldr r0, =WTCNT

           ldr r1, =0x2710

           str r1, [r0]

           mov pc, lr

喂狗程式對喂狗的時機必須要合适,否則在定時器還沒來得及發生中斷調用watchdog已經逾時了,也将引起系統複位重新開機,通常系統裡會開啟另外一個時鐘來為整個系統服務,它會定時的“告知”系統,在看門狗定時器逾時之前,自動的調用喂狗程式。