1. 程式人生 > >uboot詳解——cpu內部,外部和軟體看門狗

uboot詳解——cpu內部,外部和軟體看門狗

uboot啟動時,當將cpu執行模式設定為管理模式後,就要關閉看門狗了,那麼看門狗是幹什麼的呢?

狗狗是我們的好朋友,有時候,一條好狗狗能夠救主人的性命,”看門狗“是cpu的“好朋友”,它也能夠在cpu出狀況的時候把它救活。

看門狗其實就是一個可以在一定時間內被複位的計數器,當看門狗啟動後,計數器開始自動計數,經過一定時間,cpu就會將這個計數器復位,如果沒有被複位,計數器溢位就會對CPU產生一個復位訊號使系統重啟,這個復位的操作就是“喂狗”。

看門狗就這樣兢兢業業的守著它的主人cpu,當cpu出狀況的時候,就不能喂狗了,看門狗餓了就知道cpu不正常工作了,然後傳送復位訊號讓cpu重新醒過來。

對於一些安裝在戶外的裝置,可以很直接的體現它的價值,比如運營商在荒郊野嶺安裝了好多基站,如果這裡的基站停止工作了,就需要派人去這個基站手動重啟了,有了看門狗以後,只要過一段時間沒有喂狗,看門狗就將系統重啟,節省了不少人力。

看門狗主要分三種:

1、內建在cpu內部的看門狗

此類看門狗一般是將一個晶片中的定時器來作為看門狗,通過程式的初始化,寫入初值,並啟動定時器。程式按時對定時器賦初值(或復位),以免它餓了。這種看門狗是可以被禁用的(只要停止這個定時器即可),好比對那隻要咬你的狗來個“葵花點穴手”。大部分CPU都內建看門狗,硬體原理可參考各晶片資料手冊。
優點:可以通過程式改變初始時間,也可以隨時禁用
缺點:

需要初始化,如果程式在初始化、啟動完成前跑飛或在禁用後跑飛,看門狗就無法復位系統,這樣看門狗的作用就沒有了,系統恢復能力降低。


2、獨立的看門狗晶片

這種看門狗主要有一個用於喂狗的引腳(一般與CPU的GPIO相連)和一個復位引腳(與系統的RESET引腳相連),如果沒有在一定時間內改變喂狗腳的電平,復位引腳就會改變狀態復位CPU。此類看門狗一上電就開始工作,無法禁用。現在常用的晶片有:CAT705/CAT706、IMP706等等,溢位時間在1.6秒左右。 硬體原理可以參考各晶片資料手冊和《基於Linux的嵌入式系統全程喂狗策略》。

優點:無須配置,上電即用。無法禁用,系統必須按時喂狗,系統恢復能力高。
缺點:

無法靈活配置溢位時間,無法禁用,靈活性降低。

3、軟體看門狗

這其實就是一個監控軟體,對於硬體上出的問題它還是無能為力的,它主要對一些重要的軟體進行監控。

一些重要的程式,必須讓它一直跑著;而且還要時時關心它的狀態——不能讓它出現死鎖現象。(當然,如果一個主程式會出現死鎖,肯定是設計或者程式設計上的失誤。首要做的事是Debug。)但如果時間緊迫可以用軟體看門狗,暫時應急。

 這種監控軟體執行不出現介面視窗,具有一定的隱蔽性;它定時判斷目標程序是否執行在當前系統中,如果沒有則啟動目標程序;判斷目標程序是否“無響應”,如果是則終止目標程序;如果目標程序“無響應”的次數超過一定的數量,則重啟整個系統。它的目的也是復位,但是它主要市復位程序,實在不行才復位CPU。


第二種和第三種看門狗,在這裡不作討論,下面將討論怎麼使用內建在cpu內部的看門狗。

因為是內建在cpu內部,所以從電路圖中就找不到看門狗的連線方式了,下面是看門狗的工作原理圖:

從圖中可以看出一下幾點:

1. 看門狗使用的輸入時鐘是PCLK,關於時鐘的知識將在後面進行詳細分析

2. 看門狗的配置涉及到三個暫存器:控制暫存器(WTCON),資料暫存器(WTDAT),計數暫存器(WTCNT)

3.看門狗先將PCLK時鐘進行預分頻 (prescaler),分頻的精度為0~255 (2的8次方-1 ,由WTCON的8-15位進行設定),預分頻後再除以一個分頻因子(division factor,由WTCON的4:3兩位進行設定,一共有4中選擇——16,32,64,128),有PCLK、prescaler和division factor三個變數以後,就可以計算出看門狗計數器遞減時間間隔:

t_watchdog:看門狗計數器遞減時間間隔,單位秒

PCLK:APB匯流排工作始終,單位HZ

prescaler value + 1:預分頻大小,因為從0開始,所以需要加一

division_factor:分頻因子,有4個檔——16,32,64,128

當開發板一上電的時候,系統時鐘是還沒有初始化的,所以PCKL的時鐘大小是和外部時鐘一樣的,cpu連線的外部晶振如下圖:

所以剛上電時,PCKL的大小12MHz,WTCON[15:8]設定為74,除數因子選擇16,通過上面公式可以計算出,看門狗控制器遞減時間間隔0.1毫秒。將WTCNT裡的值設定為0x2710(十進位制10000),那麼看門狗會每過一秒鐘產生一次超時。


我們來看看控制暫存器(WTCON),資料暫存器(WTDAT),計數暫存器(WTCNT)晶片手冊:


從上圖可以看到WTCON的預設狀態:

[0]=1 當看門狗計時器超時的時候,開啟發送reset訊號的功能

[2]=0 超時的時候不傳送中斷

[4:3]=00 預設分頻因子是1/16, division_factor=16

[5]=1 開啟看門狗計數器,看門狗會按照WTCNT中的初始值進行遞減,直到超時

[15:8]=0x80 換成十進位制是128, prescaler=128

因為剛開機的時候,PCLK=12M, prescaler=128, division_factor=16 , 所以可以計算出 t_watchdog=1/(12M/129/16)=(129*16)/(12000000)=0.000172s=0.172ms


上圖是WTDAT暫存器的晶片手冊,預設值是0x800, 十進位制是2048

上圖是計數器暫存器的晶片手冊,預設值也是0x800,十進位制是2048

所以剛上電的時候,看門狗的超時時間是:time_out=2048*0.000172=0.352252s 

0.352252s是如此的短暫,所以在開機的時候如果沒有關閉看門狗,它將每隔0.352252s就傳送一次reset訊號重啟cpu,不管uboot執行到哪個階段,都將被看門狗終止並重啟。

從上面可以得出結論,板子重啟時,必須儘早關閉看門狗,以便後面的程式碼順利執行

看門狗關閉以後,需要在什麼時候開啟呢?我們將會在後面分析uboot和核心程式碼的時候進行分析。


下面將使用一個例子演示對看門狗的操作。


Makefile

[plain]  view plain  copy
  1. watch_dog.bin:watch_dog.S    
  2.     arm-linux-gcc -g -c -o watch_dog.o watch_dog.S    
  3.     arm-linux-ld -Ttext 0x000 -g watch_dog.o -o watch_dog_elf    
  4.     arm-linux-objcopy -O binary -S watch_dog_elf watch_dog.bin    
  5.     
  6. clean:    
  7.     rm -rf watch_dog.bin *.o watch_dog_elf   

watch_dog.S

[plain]  view plain  copy
  1. @ 關閉看門狗實驗  
  2. .text  
  3. .global _start  
  4. _start:  
  5.   ldr r0, = 0x53000000                       @ WTCON暫存器地址載入到r0  
  6.   
  7.   mov r1, #0                                 @ r1 = 0  
  8.   
  9.   str r1, [r0]                               @ 將r1裡的值存到r0裡地址裡  

通過分析前面的暫存器的設定位可知,只要設定WTCON[5]為0即可,上述程式碼裡,直接將整個WTCON暫存器裡的位設定為0。


[plain]  view plain  copy
  1. @開啟看門狗實驗:  
  2. @watch_dog.S  
  3.   
  4.  .text  
  5.  .global _start  
  6.  _start:  
  7.         @ 設定看門狗控制暫存器  
  8.   
  9.   
  10.          ldr r0, =0x53000000                           @ 載入WTCON暫存器地址  
  11.   
  12.          @ 0x4a21 = [15:8]=74, [5]=1, [0]=1  
  13.   
  14.          ldr r1, =0x4a21                               @ 將0x4a21儲存到r1裡  
  15.   
  16.          str r1, [r0]                                  @ 將r1裡的值存入r0指向的地址  
  17.   
  18.          @ 設定看門狗計數暫存器,該暫存器的值在上電後被載入, 1秒超時  
  19.   
  20.          ldr r2, =0x53000008                           @ 載入WTCNT暫存器地址  
  21.   
  22.          ldr r3, =0x2710                               @ 將0x2710儲存到r1裡  
  23.   
  24.          str r3, [r2]                                  @ 將r3裡的值存入r2指向的地址  
  25.   
  26.   
  27.          bl led_on                                     @ 呼叫led_on程式碼  
  28.   
  29.    
  30.   
  31. loop:  
  32.   
  33.          b loop                                        @ 死迴圈  
  34.   
  35. led_on:  
  36.         ldr r0,=0x56000010    
  37.     mov r1,#0x15400    
  38.     str r1,[r0]    
  39.               
  40.     ldr r0,=0x56000014    
  41.     mov r1,#0x100    
  42.     str r1,[r0]    
  43.     mov pc,lr    

程式開始定義兩個常量地址,分別是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燈,將上述程式碼在linux下編譯完後,燒寫到NORFLASH裡可以看到每過1秒鐘,開發板的led燈就閃一下。


知識擴充套件

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

[plain]  view plain  copy
  1. @ 喂狗程式  
  2.   
  3. .text  
  4. .global _start  
  5.   
  6. feed_dog:  
  7.   
  8.            ldr r0, =WTCNT  
  9.   
  10.            ldr r1, =0x2710  
  11.   
  12.            str r1, [r0]  
  13.   
  14.            mov pc, lr  

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


總結:這篇文章講了看門狗的一些內容,包括看門狗的作用,看門狗的分類,看門狗的工作原理和在arm處理器中看門狗的 配置手冊,並根據手冊計算了看門狗的計時間隔和計時週期,最後用了一些例子演示了看門狗的操作過程。後面我們將繼續根據uboot啟動流程講解中斷相關的知識。




轉載請宣告!