Xilinx-ZYNQ7000系列-學習筆記(2):私有看門狗(AWDT)的使用

qwer1030274531發表於2020-11-18

Xilinx-ZYNQ7000系列-學習筆記(2):私有看門狗(AWDT)的使用

一、WDT簡介

在嵌入式系統中,為了使系統在工作異常情況下能自動復位,一般都需要引入 看門狗程式,用來監測程式不至於“跑飛”。
看門狗其實就是一個可以在一定時間內被複位的  計數器。當看門狗啟動後,計數器開始自動計數,經過一定時間,如果沒有被複位,計數器清零就會對CPU產生一個復位訊號使  系統重啟(俗稱“被狗咬”)。系統正常執行時,需要在看門狗允許的時間間隔內對計數器  清零(俗稱“餵狗”),不讓復位訊號產生。
簡單的來說就是在執行程式之前給看門狗計數器賦一個初值(假設是1000),在程式開始執行時,看門狗計數器開始減少,1000->999->998……,這時候你需要進行計數器重置,假設在500的時候(時間由自己定,看你把餵狗程式加在哪裡),計數器會重新變為1000。如果不進行計數器重置使得計數器減到0,那麼看門狗程式啟動程式復位功能,系統進行復位。

二、看門狗種類

2.1 獨立看門狗

獨立看門狗有其內部自帶的時鐘驅動,即使主時鐘發生故障,它仍能夠正常工作。它的餵狗時間可以自由選擇,大多數情況下獨立看門狗用在對時間精度要求不是很高的地方。

優點:無須配置,上電即用。無法禁用,系統必須按時餵狗,系統恢復能力高。
缺點:無法靈活配置溢位時間,無法禁用,靈活性降低。

2.2 視窗看門狗

根據系統時鐘分頻得到需要的時鐘驅動,如果系統時鐘發生故障,那麼看門狗也無效。它的餵狗時間需要設定一個視窗值(小於裝載到計數器的初始值),在除了視窗值以外的時間不可以進行餵狗操作,大多數情況下視窗看門狗用在對時間精度要求較高的地方。

優點:時間精度的把握較好,可以固定在某一時間範圍內進行餵狗。
缺點:無法靈活配置溢位時間,超出視窗值的系統無法使用

2.3 私有看門狗與系統看門狗

此類看門狗一般是由CPU內部自帶,將一個晶片中的計數器作為看門狗,透過程式的初始化,寫入初值,設定溢位值,並啟動計數器,具體區別參考資料手冊

ug585-Zynq-7000-TRM.pdf

優點:可以透過程式改變溢位時間;可以隨時禁用
缺點:需要初始化;如果程式在初始化、啟動完成前跑飛或在禁用後跑飛,看門狗就無法復位系統,這樣看門狗的作用就沒有了,系統恢復能力降低。

三、看門狗的使用方法

3.1 私有看門狗與系統看門狗

每個Cortex-A9處理器都有自己私有的32位定時器和32位看門狗定時器,這兩個處理器共享一個全域性64位計數器,它們的頻率都為CPU頻率的1/2。而在系統級,有一個24位看門狗計時器和兩個16位三重計時器/計數器,系統級看門狗定時器的頻率為CPU頻率的1/4或1/6。
本文采用的是 私有看門狗,下圖為系統內部兩個看門狗所處位置以及關係圖。
在這裡插入圖片描述
私有看門狗

每個CPU均具有一個私有定時器(PT)及一個私有看門狗(AWDT),且只能由各自的CPU進行操作,因此稱為私有的。私有定時器及私有看門狗的主要特點如下:
• 32位計數單元歸零時將產生中斷訊號;
• 具有一個8位的時鐘分頻器;
• 可配置成單次觸發或自動裝載模式;
• 計數器的初始值可設。
私有看門狗只能對各自CPU本身進行監視,如監視CPU程式是否跑飛,但卻無法對另一個CPU進行監視,也無法對晶片內部鎖相環等關鍵時鐘環節進行監視,亦無法向PL或晶片外部輸出復位訊號,這些功能將由系統看門狗實現。

系統看門狗

不同於私有看門狗(AWDT),系統看門狗(SWDT)可監視更多的環節(如PS部分的鎖相環等),其功能也相對複雜,現將其特點總結如下:

  • 具有24位計數單元;
  • 時鐘輸入可選為內部CPU時鐘、內部PL側時鐘、外部引腳提供的時鐘;
  • 計數單元溢位時可產生的訊號有向PS發出中斷請求、向PS或PL或MIO發出復位訊號;
  • 溢位時間可設定為 32760 - 68719476736,時脈頻率為100 MHz時對應的時間為330us-687.2s;
  • 中斷請求訊號及復位訊號的脈寬可根據需要設定,中斷請求訊號脈寬可設為2-32個時鐘週期,復位訊號脈寬可設為2-256個時鐘週期, 系統看門狗整體結構圖如下:
    在這裡插入圖片描述

3.2 配置WDT程式

由於私有看門狗屬於PS端,所以在vivado環境中不需要對block塊進行設定。

PS :如果需要使用系統看門狗的話,使用PL時鐘則需要寫分頻verilog語句,使用MIO處則需要在block的ZYNQ硬體中選擇SWDT。

私有看門狗程式碼如下: hefei/

#include "xparameters.h"#include "xscuwdt.h"#include "xil_printf.h"#include <sleep.h>#include "stdio.h"#define WDT_DEVICE_ID		XPAR_SCUWDT_0_DEVICE_IDint watchdog(XScuWdt * WdtInstancePtr, u16 DeviceId,float number);XScuWdt Watchdog;		/* Cortex SCU Private WatchDog Timer Instance */int main(void){
	int Status;
	int Count = 0;
	Status = watchdog(&Watchdog, WDT_DEVICE_ID,10);
	if (Status != XST_SUCCESS) {
		xil_printf("start the watchdog timer fail!\r\n");
		return XST_FAILURE;
	}
	while (Count < 5) {
		sleep(1);
		Count++;
		printf("the second is %d \n",Count);
		//XScuWdt_RestartWdt(WdtInstancePtr);
	}
	xil_printf("the watchdog timer will restart the system \r\n");
	return XST_SUCCESS;}int watchdog(XScuWdt * WdtInstancePtr, u16 DeviceId,float number){
	int Status;
	XScuWdt_Config *ConfigPtr;
	u32 result;
	/*
	 * Initialize the SCU Private Wdt driver so that it is ready to use.
	 */
	 xil_printf("start the watchdog time``r successful! \r\n");
	ConfigPtr = XScuWdt_LookupConfig(DeviceId);
	/*
	 * This is where the virtual address would be used, this example
	 * uses physical address.
	 */
	Status = XScuWdt_CfgInitialize(WdtInstancePtr, ConfigPtr,
					ConfigPtr->BaseAddr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	/*
	 * Put the watchdog timer in watchdog mode.
	 */
	XScuWdt_SetWdMode(WdtInstancePtr);
	/*
	 * Load the watchdog counter register.
	 */
	result = (unsigned long)(333333333*number);
	XScuWdt_LoadWdt(WdtInstancePtr,result);
	/*
	 * Start the ScuWdt device.
	 */
	XScuWdt_Start(WdtInstancePtr);
	return XST_SUCCESS;}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071

程式碼解析:

  1. #include “xscuwdt.h”,呼叫系統看門狗的標頭檔案 ,其中包括看門狗的一些初始值配置、啟動、餵狗等函式,在使用看門狗前請務必呼叫此檔案。
  2. XScuWdt_LookupConfig,用來配置WDT的裝置ID號,ID號在#include "xparameters.h"中可以找到。
  3. XScuWdt_CfgInitialize,初始化WDT計數器。
  4. XScuWdt_SetWdMode,透過設定看門狗控制暫存器的WD模式位,將看門狗定時器置於看門狗模式。
  5. XScuWdt_LoadWdt,給WDT計數器裝初值,這裡我對此函式進行了封裝。已知CPU的時脈頻率為666.6666Mhz,即WDT的時脈頻率為333.33Mhz,可得倒數計時1s計數器需要配置的初值為333_333_333,對計數器賦的初值可以直接寫在number變數中(本文賦值為10s)。
  6. XScuWdt_Start,開啟看門狗計數器。
  7. XScuWdt_RestartWdt,計數器重置函式,俗稱“餵狗”,需要寫在看門狗復位程式之前的位置,確保系統不會進行復位。

下面的程式是對wdt進行測試:

	while (Count < 5) {
		sleep(1);
		Count++;
		printf("the second is %d \n",Count);
		XScuWdt_RestartWdt(WdtInstancePtr);
	}1234567
  • 做法一:給計數器賦初值為10s,在迴圈中啟動餵狗程式,程式會在5S後跳出迴圈,之後在10s後由於沒有餵狗功能,系統復位。

  • 做法二:同樣給計數器賦初值為10s,禁用餵狗程式,程式會直接在10s後進行系統復位。

做法一的系統在15s後進行復位,而做法二的系統卻在10s後進行復位,這告訴我們, XScuWdt_RestartWdt函式成功地“拖延”了系統復位5s,也就是說每迴圈一次,都給計數器重新賦值為10s,一共迴圈了5次正好5s,看門狗程式成功實現。

四、總結

透過學習watch dog timer程式,我學習到了計數器、系統復位等知識,並且能夠區分看門狗之間的區別,通常看門狗程式運用於要求較高的程式中,避免程式跑飛。使用看門狗時一定要清楚系統執行所需的時間,保證 系統執行時間<看門狗復位時間,否則會發生系統還沒有執行完就復位的情況,餵狗的時間節點一定要把握好,確保看門狗能夠發揮出最大作用。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2734953/,如需轉載,請註明出處,否則將追究法律責任。

相關文章