1. 程式人生 > >Exynos4412裸機開發 —— RTC 實時時鐘單元

Exynos4412裸機開發 —— RTC 實時時鐘單元

      RTC(Real-Time Clock) 實時時鐘。RTC是積體電路,通常稱為時鐘晶片。在一個嵌入式系統中,通常採用RTC來提供可靠的系統時間,包括時分秒和年月日等,而且要求在系統處於關機狀態下它也能正常工作(通常採用後備電池供電)。它的外圍也不需要太多的輔助電路,典型的就是隻需要一個高精度的32.768kHz 晶體和電阻電容等。

一、RTC 控制器

        實時時鐘(RTC)單元可以通過備用電池供電,因此,即使系統電源關閉,它也可以繼續工作。RTC可以通過STRB/LDRB 指令將8位BCD碼資料送至CPU。這些BCD資料包括秒、分、時、日期、星期、月和年。RTC單元通過一個外部的32.768kHz 晶振提供時鐘。RTC具有定時報警的功能。

        其功能說明如下:

1 -- 時鐘資料採用BCD編碼。

2 -- 能夠對閏年的年月日進行自動處理。

3 -- 具有告警功能,當系統處於關機狀態時,能產生警告中斷。

4 -- 具有獨立的電源輸入。

5 -- 提供毫秒級時鐘中斷,該中斷可以用於作為嵌入式作業系統的核心時鐘。

二、RTC 控制器暫存器詳解

1 、Time Tick Generator 

下面是示例程式:

標頭檔案定義:

/**********************************RTC independ register********************************/
#define		RTCINTP			__REG(0X10070030)
#define		RTCCON			__REG(0X10070040)
#define		TICCNT			__REG(0X10070044)
#define		CURTICCNT		__REG(0X10070090)

typedef struct {
				unsigned int ALM;
				unsigned int SEC;
				unsigned int MIN;
				unsigned int HOUR;
				unsigned int DAY;
				unsigned int MON;
				unsigned int YEAR;
}rtclam;

#define		RTCALM (* (volatile rtclam *)0X10070050)


typedef	struct {

				unsigned int BCDSEC;
				unsigned int BCDMIN;
				unsigned int BCDHOUR;
				unsigned int BCDWEEK;
				unsigned int BCDDAY;
				unsigned int BCDMON;
				unsigned int BCDYEAR;
}rtcbcd;
#define 	RTC (* (volatile rtcbcd *)0X10070070)

C程式如下:

#include "exynos_4412.h"

void mydelay_ms(int time)
{
	int i, j;
	while(time--)
	{
		for (i = 0; i < 5; i++)
			for (j = 0; j < 514; j++);
	}
}
//*(volatile unsigned int *)(0x11000c20) = 0;
/*
 *  裸機程式碼,不同於LINUX 應用層, 一定加迴圈控制
 */
void do_irq(void)
{
	static int a = 1;
	int irq_num;
	irq_num = CPU0.ICCIAR&0x3ff;  //獲取中斷號
	switch(irq_num)
	{
	case 57:
		printf("in the irq_handler\n");
			EXT_INT41_PEND = EXT_INT41_PEND |((0x1 << 1)); //清GPIO中斷標誌位
			ICDICPR.ICDICPR1 = ICDICPR.ICDICPR1 | (0x1 << 25); //清GIC中斷標誌位
		break;
	case 76:
		printf("in the alarm interrupt!\n");
		RTCINTP	 = RTCINTP | (1 << 1);
		ICDICPR.ICDICPR2 = ICDICPR.ICDICPR2 | (0x1 << 12); //清GIC中斷標誌位
		break;
	case 77:
			printf("in the tic interrupt!\n");
			RTCINTP	 = RTCINTP | (1 << 0);
			ICDICPR.ICDICPR2 = ICDICPR.ICDICPR2 | (0x1 << 13); //清GIC中斷標誌位
			break;
	}
	CPU0.ICCEOIR = CPU0.ICCEOIR&(~(0x3ff))|irq_num; //清cpu中斷標誌位
}
void rtc_init(void)
{
	RTCCON = 1;
	RTC.BCDYEAR = 0x16;
	RTC.BCDMON = 0x2;
	RTC.BCDDAY = 0x25;
	RTC.BCDHOUR = 0x15;
	RTC.BCDMIN = 0x24;
	RTC.BCDSEC = 0x50;
	RTCCON = 0;
}
void rtc_tic(void)
{
	RTCCON = RTCCON & (~(0xf << 4)) | (1 << 8);
	TICCNT = 32768;

	ICDDCR = 1;  //使能分配器
	ICDISER.ICDISER2 = ICDISER.ICDISER2 | (0x1 << 13); //使能相應中斷到分配器
	ICDIPTR.ICDIPTR19 = ICDIPTR.ICDIPTR19 & (~(0xff << 8))|(0x1 << 8); //選擇CPU介面
	CPU0.ICCPMR = 255; //中斷遮蔽優先順序
	CPU0.ICCICR = 1;   //使能中斷到CPU
}
void rtc_alarm(void)
{
	RTCALM.ALM = (1 << 6)|(1 << 0);
	RTCALM.SEC = 0x58;
	ICDDCR = 1;  //使能分配器
	ICDISER.ICDISER2 = ICDISER.ICDISER2 | (0x1 << 12); //使能相應中斷到分配器
	ICDIPTR.ICDIPTR19 = ICDIPTR.ICDIPTR19 & (~(0xff << 0))|(0x1 << 0); //選擇CPU介面
	CPU0.ICCPMR = 255; //中斷遮蔽優先順序
	CPU0.ICCICR = 1;   //使能中斷到CPU
}
int main (void)
{
	rtc_init();
	rtc_alarm();
	rtc_tic();
	while(1)
	{
		printf("%x %x %x %x %x BCDSEC = %x\n",RTC.BCDYEAR,
		RTC.BCDMON,
		RTC.BCDDAY,
		RTC.BCDHOUR,
		RTC.BCDMIN,RTC.BCDSEC);
		mydelay_ms(1000);

	}
   return 0;
}

執行結果如下:

16 2 5 15 24 BCDSEC = 50
in the tic interrupt!
16 2 5 15 24 BCDSEC = 51
in the tic interrupt!
16 2 5 15 24 BCDSEC = 52
in the tic interrupt!
16 2 5 15 24 BCDSEC = 53
16 2 5 15 24 BCDSEC = 53
16 2 5 15 24 BCDSEC = 54
in the tic interrupt!
16 2 5 15 24 BCDSEC = 55
in the tic interrupt!
16 2 5 15 24 BCDSEC = 56
in the tic interrupt!
in the alarm interrupt!
16 2 5 15 24 BCDSEC = 58
in the tic interrupt!
16 2 5 15 24 BCDSEC = 59
in the tic interrupt!
16 2 5 15 25 BCDSEC = 0
in the tic interrupt!
16 2 5 15 25 BCDSEC = 1
in the tic interrupt!
16 2 5 15 25 BCDSEC = 2
in the tic interrupt!
16 2 5 15 25 BCDSEC = 3
in the tic interrupt!
16 2 5 15 25 BCDSEC = 4
in the tic interrupt!
16 2 5 15 25 BCDSEC = 5
in the tic interrupt!