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!