1.RTCRTC(Real-TimeClock)实时时钟。RTCRTC是集成电路,通常称为时钟芯片。在嵌入式系统中,RTC通常用于提供可靠的系统时间,包括时、分、秒、年、月、日等,要求在系统关机(通常由备用电源供电)时仍能正常工作电池)。它周围不需要太多的辅助电路。通常,它只需要一个高精度的32.768kHz晶振、电阻电容等,就具有闹钟功能。.2.Exynos4412RTC本文主要以Cortex-A9soc为例,讲解RTC的使用。1.特点实时时钟(RTC)单元可由备用电池供电,因此即使系统电源关闭也能继续运行。RTC可以通过STRB/LDRB指令向CPU发送8位BCD码数据。这些BCD数据包括秒、分、小时、日期、星期几、月份和年份。RTC单元由外部32.768kHz晶振提供时钟。RTC具有定时报警功能。其功能描述如下:1--时钟数据采用BCD码。2--自动处理闰年年月日的能力。3——具有告警功能,当系统处于关机状态时,可以产生告警中断。4——带独立电源输入。5--提供毫秒级时钟中断,可作为嵌入式操作系统的内核时钟。2.RTCBlockRTC框图RTC在Linux中主要实现了两个功能,系统掉电后的时间日期保持和时间日期报警(类似于定时器)。“1)时间和日期保持功能:”主要由RTC实时时钟控制寄存器RTCCON控制,节拍时间中断由节拍时间计数寄存器TICNT产生,实现与时钟相关的时间和实时同步实时操作系统功能。时间和日期的运算其实就是BCD码的运算,而BCD码是由一系列寄存器组成(BCD秒寄存器BCDSEC,BCD分寄存器BCDMIN,BCD小时寄存器BCDHOUR,BCD日期寄存器BCDDATE,BCD日注册BCDDAY,BCD月注册BCDMON,BCD年注册BCDYEAR)。“2)闹钟功能:”RTC闹钟控制寄存器RTCALM主要用于功能使能控制,产生闹钟中断。闹钟时间和日期的设置也是对一系列寄存器进行操作(闹钟秒数据寄存器ALMSEC、闹钟分钟数据寄存器ALMMIN、闹钟小时数据寄存器ALMHOUR、闹钟日期数据寄存器ALMDATE、闹钟月份数据寄存器ALMMON、闹钟年数据寄存器ALMYEAR)。《3)闰年生成器》可以根据BCDDAY、BCDMON、BCDEEAR的值自动计算出闰年。3.备用电池备用电池可以驱动RTC逻辑。即使系统电源关闭,电池也可通过RTCVDD引脚备份到RTC模块。如果系统关闭,您应该阻止CPU和RTC逻辑。为了降低功耗,备用电池单独驱动振荡电路和BCD计数器。4、报警[alarm]功能RTC在掉电模式或正常运行模式下执行时可以产生一个ALARM_INT和ALARM_WK信号。在正常工作模式下,它会产生ALARM_INT。在掉电模式下,它发出ALARM_WK和ALARM_INT信号。RTC闹钟寄存器(RTCALM)确定闹钟启用/禁用状态以及闹钟时间设置的条件。5.晶体振荡器32.768kHzX-Tal连接示例晶体振荡器时钟频率为32.768kHz。XT_RTC_I32.768kHzRTC振荡器时钟输入XT_RTC_O32.768kHzRTC振荡器时钟输出XRTCCLKO32.768kHzRTC振荡器时钟输出,该信号默认禁用。可以通过设置寄存器RTCCON的CLKOUTEN字段为1使能。引脚连接图:从电路图中可以看出,只连接了RTC振荡器时钟输入引脚XT_RTC_I。3、寄存器1.RTC寄存器组:寄存器组2.INTP设置相应位为1清除中断。3、RTCCONRTCCON1.RTCCON寄存器由10位组成,如CTLEN控制BCDSEL读/写使能,CNTSEL、CLKRST、TICKSEL、TICEN用于测试,CLKOUTEN用于RTC时钟输出控制。2.CTLEN位控制CPU和RTC之间的所有接口。因此,您应该在RTC控件中将其设置为“1”,以启用系统复位后写入数据的例程。为防止无意中写入BCD计数器寄存器,应在关闭电源前将CTLEN位清零。3.CLKRST是2^15^时钟分频器的计数器复位。在设置RTC时钟之前,应重置215时钟分频器以实现准确的RTC操作。四、RTC操作1、设置时间《例:》我们要设置当前时间为“2020年11月11日,15:24:50”。1)首先打开RTC控制使能,即设置RTCCON[0]为1;2)然后将时间对应的BCD格式值设置到相应的寄存器中,BCDYEAR、BCDMON、BCDDAY、BCDHOUR、BCDMIN、BCDSEC;3)设置RTCCON[0]为0,防止误操作修改时间;4)如果我们要访问当前时间,可以直接读取寄存器BCDYEAR、BCDMON、BCDDAY、BCDHOUR、BCDMIN、BCDSEC。voidrtc_init(void){RTCCON=1;//开启RTC控制写入功能RTC.BCDYEAR=0x20;//2020年11月11日15:24:50。以BCD码格式写入RTC.BCDMON=0x11;RTC.BCDDAY=0x11;RTC.BCDHOUR=0x15;RTC.BCDMIN=0x24;RTC.BCDSEC=0x50;RTCCON=0;//关闭RTC控制写功能}2.运行节拍定时器TICNNTICNTTRTC定时器是一个递增计数器,并且触发定时中断。TICNT寄存器包含32位目标计数值,CURTICCNT寄存器包含32位当前滴答计数。如果当前滴答计数达到TICNT中指定的目标值,则会发生定时中断。每秒计数的次数由RTCCON[7:4],即TICCKSEL位决定:TICCKSEL是因为我们的晶振频率也是32768,为了计数方便,我们将RTCCON[7:4]设置为0,tick定时器需要设置RTCCON[8]位1:TICEN代码如下:RTCCON=RTCCON&(~(0xf<<4))|(1<<8);TICCNT=32768;3、操作ALARM闹钟RTCALMRTCALM寄存器,控制闹钟功能的激活和闹钟时间。请注意,RTCALM寄存器将在掉电模式下生成ALARM_INT和ALARM_WK信号,但在正常模式下仅生成ALARM_INT信号。将ALMEN[6]设置为1以生成ALARM_INT和ALARM_WK信号。《例子:》比如我们要在每小时25分58秒产生一个中断信号,那么我们需要将RTCALM[1]、RTCALM[0]设置为1,将RTCALM[6]设置为1来使能闹钟功能,然后将BCD格式的时间设置到寄存器ALMSEC和ALMMIN中。代码如下:RTCALM.ALM=(1<<6)|(1<<0)|(1<<1);//使能位:MINEN,SECENRTCALM.SEC=0x58;RTCALM.MIN=0x25;//每小时25:58产生一个中断。闹钟功能设置闹钟时间寄存器如下:寄存器操作采用BCD格式。5.完整代码实现滴答定时器和闹钟会产生内部中断信号,所以我们必须对这两个中断信号进行中断相关的初始化,并在中断处理函数中添加相应的处理代码。中断号参考datasheet9.2.2GICInterruptTablertc中断号中断初始化的寄存器配置可以参考《11. 从0开始学ARM-基于Exynos4412中断详解、key程序编写》不同的是key接的是一级中断控制器,但是两者rtc的中断不是。需要设置清除中断的寄存器如下:"Ticktimerclearinterrupt:"RTCINTP=RTCINTP|(1<<0);//清除GIC中断标志ICDICPR.ICDICPR2=ICDICPR.ICDICPR2|(0x1<<13);//清除cpu中断标志CPU0.ICCEOIR=CPU0.ICCEEOIR&(~(0x3ff))|irq_num;"alarmtimerclearinterrupt:"RTCINTP=RTCINTP|(1<<1);//清除GIC中断标志ICDICPR。ICDICPR2=ICDICPR.ICDICPR2|(0x1<<12);//清除cpu中断标志CPU0.ICCEOIR=CPU0.ICCEOIR&(~(0x3ff))|irq_num;"滴答定时器中断初始化:"voidrtc_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中断}“报警初始化”voidrtc_alarm(void){RTCALM.ALM=(1<<6)|(1<<0)|(1<<1);RTCALM.SEC=0x58;RTCALM.MIN=0x25;//每小时25:58产生一次中断ICDDCR=1;//开启分发器//开启分发器对应的中断ICDISER.ICDISER2=ICDISER.ICDISER2|(0x1<<12);//选择CPU接口ICDIPTR.ICDIPTR19=ICDIPTR.ICDIPTR19&(~(0xff<<0))|(0x1<<0);CPU0.ICCPMR=255;//中断屏蔽优先CPU0.ICCICR=1;//使CPU中断}"Interrupthandler"voiddo_irq(void){staticinta=1;intirq_num;irq_num=CPU0.ICCIAR&0x3ff;//获取中断号switch(irq_num){case57://keyprintf("intheirq_handler\n");//清除GPIO中断标志EXT_INT41_PEND=EXT_INT41_PEND|((0x1<<1));//清除GIC中断标志ICDICPR.ICDICPR1=ICDICPR.ICDICPR1|(0x1<<25);break;case76:printf("inthealarminterrupt!\n");RTCINTP=RTCINTP|(1<<1);//清除GIC中断标志ICDICPR.ICDICPR2=ICDICPR.ICDICPR2|(0x1<<12);break;case77:printf("intheticinterrupt!\n");RTCINTP=RTCINTP|(1<<0);//清除GIC中断标志ICDICPR.ICDICPR2=ICDICPR.ICDICPR2|(0x1<<13);break;}//清除cpu中断标志CPU0.ICCEOIR=CPU0.ICCEOIR&(~(0x3ff))|irq_num;}"Othercodes:"voidrtc_init(void){RTCCON=1;//开启RTC控制写入功能RTC.BCDYEAR=0x20;//2020年11月11日,15:24:50。WriteRTC.BCDMON=0x11;RTC.BCDDAY=0x11;RTC.BCDHOUR=0x15;RTC.BCDMIN=0x24;RTC.BCDSEC=0x50;RTCCON=0;//关闭RTC控制写函数}intmain(void){rtc_init();rtc_alarm();rtc_tic();//每秒打印如下当前时间while(1){printf("%x-%x-%x%x:%x:%x\n";,RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);delay_ms(1000);}}
