1.什麼是定時器(timer)
定時器/計數器作為SoC的外設,主要用來實作定時執行代碼的功能。
定時器可以讓SoC在執行主程式的同時,可以(通過定時器)具有計時功能,到了一定時間(計時結束)後,定時器會産生中斷提醒CPU,CPU會去進行中斷并執行定時器中斷的ISR。進而去執行預先設定好的事件。
定時時間是由2個東西共同決定的:一個是TCNT中的計數值,一個是時鐘周期。
定時器内部有1個寄存器TCNT,計時開始時我們會把一個總的計數值(譬如說300)放入TCNT寄存器中,然後每隔一個時鐘周期(假設為1ms)TCNT中的值會自動減1(硬體自動完成,不需要CPU軟體去幹預),直到TCNT中減為0的時候,TCNT就會觸發定時器中斷。
2.S5PV210中的定時器
PWM定時器:
這種是最常用的,像簡單單片機(譬如51單片機)中的定時器也是這類,一般SoC中産生PWM信号都是靠這個定時器子產品的。
系統定時器:
系統定時器稱為systick,系統定時器也是用來産生固定時間間隔(TCNT×時鐘周期)信号的。
一般做作業系統移植的時候,這裡不會由我們自己來做,一般原廠提供的基礎移植部分就已經包含了。
看門狗定時器:
看門狗定時器可以選擇發出複位信号複位CPU,在實踐中應用很多,尤其是工業領域(環境複雜、幹擾多)機器容易出問題,此時一般都會用看門狗來進行系統複位。
實時時鐘RTC(real time clock):
定時器關注的是時間段(而不是時間點),定時器計時從開啟定時器的那一刻開始,到定的時間段結束為止産生中斷;RTC中工作用的是時間點(xx年x月x日x時x分x秒星期x)。
RTC和定時器的差別,就相當于是鐘表和鬧鐘的差別。
3.看門狗定時器
結構框圖:

幾個主要寄存器:
WTCON :
WTDAT :
WTCNT:
WTCLRINT:
4.代碼實作
#define WTCON (0xE2700000)
#define WTDAT (0xE2700004)
#define WTCNT (0xE2700008)
#define WTCLRINT (0xE270000C)
#define rWTCON (*(volatile unsigned int *)WTCON)
#define rWTDAT (*(volatile unsigned int *)WTDAT)
#define rWTCNT (*(volatile unsigned int *)WTCNT)
#define rWTCLRINT (*(volatile unsigned int *)WTCLRINT)
// 初始化WDT使之可以産生中斷
void wdt_init_interrupt(void)
{
// 第一步,設定好預分頻器和分頻器,得到時鐘周期是128us
rWTCON &= ~(0xff<<8);
rWTCON |= (65<<8); // 1MHz
rWTCON &= ~(3<<3);
rWTCON |= (3<<3); // 1/128 MHz, T = 128us
// 第二步,設定中斷和複位信号的使能或禁止
rWTCON |= (1<<2); // enable wdt interrupt
rWTCON &= ~(1<<0); // disable wdt reset
// 第三步,設定定時時間
// WDT定時計數個數,最終定時時間為這裡的值×時鐘周期
//rWTDAT = 10000; // 定時1.28s
//rWTCNT = 10000; // 定時1.28s
// 其實WTDAT中的值不會自動刷到WTCNT中去,如果不顯式設定WTCON中的值,它的值就是
// 預設值,然後以這個預設值開始計數,是以這個時間比較久。如果我們自己顯式的
// 設定了WTCNT和WTDAT一樣的值,則第一次的定時值就和後面的一樣了。
rWTDAT = 1000; // 定時0.128s
//rWTCNT = 1000; // 定時0.128s
// 第四步,先把所有寄存器都設定好之後,再去開看門狗
rWTCON |= (1<<5); // enable wdt
}
// wdt的中斷處理程式
void isr_wdt(void)
{
static int i = 0;
// 看門狗定時器時間到了時候應該做的有意義的事情
printf("wdt interrupt, i = %d...", i++);
// 清中斷
intc_clearvectaddr();
rWTCLRINT = 1;
}