rtc
一、RTCRTC(Real-Time Clock) 实时时钟。

RTC

RTC是集成电路,常日称为时钟芯片。在一个嵌入式系统中,常日采取RTC来供应可靠的系统韶光,包括时分秒和年月日等,而且哀求在系统处于关机状态下它也能正常事情(常日采取后备电池供电)。它的外围也不须要太多的赞助电路,范例的便是只须要一个高精度的32.768kHz 晶体和电阻电容等,并且具有闹钟的功能。。
二、Exynos 4412 RTC本篇紧张以Cortex-A9 soc为例讲解RTC的利用方法。
1. 特性实时时钟(RTC)单元可以通过备用电池供电,因此,纵然系统电源关闭,它也可以连续事情。RTC可以通过STRB/LDRB 指令将8位BCD码数据送至CPU。这些BCD数据包括秒、分、时、日期、星期、月和年。RTC单元通过一个外部的32.768kHz 晶振供应时钟。RTC具有定时报警的功能。
其功能解释如下:
1 -- 时钟数据采取BCD编码。
2 -- 能够对闰年的年月日进行自动处理。
3 -- 具有告警功能,当系统处于关机状态时,能产生警告中断。
4 -- 具有独立的电源输入。
5 -- 供应毫秒级时钟中断,该中断可以用于作为嵌入式操作系统的内核时钟。
2. RTC BlockRTC Block Diagram
RTC在Linux中紧张实现两种功能,分别是系统掉电后的韶光日期坚持和韶光日期报警(类似定时器)。
1)韶光日期坚持功能: 紧张是由RTC实时时钟掌握寄存器RTCCON进行功能的使能掌握,由节拍韶光计数寄存器TICNT来产生节拍韶光中断来实现实时操作系统功能干系的韶光和实时同步。个中对韶光日期的操作实际上是对BCD码操作,而BCD码则是由一系列的寄存器组成(BCD秒寄存器BCDSEC、BCD分寄存器BCDMIN、BCD小时寄存器BCDHOUR、BCD日期寄存器BCDDATE、BCD日寄存器BCDDAY、BCD月寄存器BCDMON、BCD年寄存器BCDYEAR)。
2)报警功能: 紧张由RTC报警掌握寄存器RTC ALM进行功能使能掌握,并产生报警中断。报警韶光日期的设置也是对一系列的寄存器进行操作(报警秒数据寄存器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.768 kHz X-Tal Connection Example
晶振时钟频率 32.768 kHz。
XT_RTC_I 32.768 kHz RTC振荡器时钟输入XT_RTC_O 32.768 kHz RTC振荡器时钟输出XRTCCLKO 32.768 kHz RTC振荡器时钟输出,此旗子暗记默认关闭。可以通过设置寄存器RTCCON的CLKOUTEN字段为1来启用它。
引脚连接图:
引脚连接图
由电路图可知,只连接了RTC振荡器时钟输入引脚XT_RTC_I 。
三、寄存器1. RTC寄存器组:寄存器组
2. INTPINTP
设置对应的bit为1就可以打消中断。
3. RTCCONRTCCON寄存器由10位组成,如掌握BCD SEL读/写启用的CTLEN, CNTSEL、CLKRST、TICKSEL、TICEN用于测试,CLKOUTEN用于RTC时钟输出掌握。CTLEN位掌握CPU和RTC之间的所有接口。因此,您该当在RTC控件中将其设置为“1”,在系统重置后启用数据写入的例程。为了防止无意中写入BCD计数器寄存器,该当关闭电源前将CTLEN位打消为0。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. 操作滴答定时器TICNT
TICNT
RTC计时器是一个递增计数器,并引发计时中断。TICNT寄存器包含32位目标计数值,并且CURTICCNT寄存器包含32位当前计时计数。如果当前滴答数达到TICNT中指定的目标值时,计时中断发生。
一秒钟计数的次数,由RTCCON[7:4]即TICCKSEL位决定:
TICCKSEL
由于我们的晶振频率也是32768,为方便计数,以是我们设置RTCCON[7:4]为0,开启滴答计时器须要设置RTCCON[8]位1:
TICEN
代码如下:
RTCCON=RTCCON&(~(0xf<<4))|(1<<8);TICCNT=32768;3. 操作ALARM闹钟RTCALM
RTCALM
RTCALM寄存器掌握报警功能的启用和报警韶光。请把稳,RTCALM寄存器在断电模式下将同时天生ALARM_INT和ALARM_WK旗子暗记,但在正常模式下仅天生ALARM_INT旗子暗记。设置ALMEN[6]为1以产生ALARM_INT和ALARM_WK旗子暗记。
举例:
比如我们想每个小时的25分58秒产生一个中断旗子暗记,那我们须要设置RTCALM[1]、RTCALM[0]为1,同时设置RTCALM[6]位1以开启alarm功能,然后将BCD格式的韶光设置到寄存器ALMSEC、ALMMIN。
代码如下:
RTCALM.ALM=(1<<6)|(1<<0)|(1<<1);//使能bite:MINEN、SECENRTCALM.SEC=0x58;RTCALM.MIN=0x25;//每小时25:58产生一次中断
alarm功能设置闹钟韶光寄存器如下:
ALMSEC
ALMMIN
ALMHOUR
ALMDAY
ALMMON
ALMYEAR
寄存器操作,采取BCD格式。
五、完全代码实现滴答计时器和alarm闹钟会产生内部中断旗子暗记,以是我们必须给这两个中断旗子暗记进行中断干系的初始化,并在中断处理函数中增加相应的处理代码。
中断号参考datasheet 9.2.2 GIC Interrupt Table
rtc中断号
关于中断的初始化的寄存器配置,我们可以参考《11. 从0开始学ARM-基于Exynos4412中断详解、key程序编写》
差异是,key连接在了第一级中断掌握器,而rtc的这两个中断则没有。 清中断须要设置的寄存器如下:
滴答计时器清中断:
RTCINTP=RTCINTP|(1<<0);//清GIC中断标志位ICDICPR.ICDICPR2=ICDICPR.ICDICPR2|(0x1<<13);//清cpu中断标志位CPU0.ICCEOIR=CPU0.ICCEOIR&(~(0x3ff))|irq_num;
alarm计时器清中断:
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}
alarm初始化
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}
中断处理函数
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;}
其他代码:
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掌握写功能}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);}}
更多 ARM Linux干货,请关注 一口Linux









