S3C2410的RTC驱动分析
扫描二维码
随时随地手机看文章
S3C2410 RTC(Real Time Clock)简介
实时时钟(RTC)单元可以在系统电源关半闭的情况下依靠备用电池工作。RTC可以通过使用STRB/LDDRB这两个ARM指令向CPU传递8位数据(BCD码)。数据包括秒、分、小时、日期、天、月、和年。RTC单元依靠一个外部的32.768kHZ的石晶,也可以执行报警功能。
特性
BCD码:秒、分、时、日期、天、月和年
润年产生器
报警功能:报警中断,或者从power-off状态唤醒。
移除了2000年的问题
独立的电源引角:RTCVDD
为RTOS内核时间Tick time支持毫秒Tick time中断。
Round reset 功能。
RTC操作
润年产生器
润年产生器可以判断每个月的最后一天是28、29、30还是31,计算的基础是BCDDATA、 BCDMON和BCDYEAR中的数据。这一块在考虑最后一天的时候还考虑至了润年的情况,一个8位的计数器只能表示2个BCD数字,所以他汉有决定一个以“00”为结尾的年是不是润年。例如,他不能在1900和2000中分辨。为了解决这个问题,在S3C2410的RTC模块中用了硬线逻辑去支持2000这个润年,注意1900不是润年,而2000是润年,
读/写寄存器
RTCCON寄存器的Bit 0 必须被置高,这样是为了写RTC模块的BCD寄存器。为了显示秒、分、时、日期、月年,CPU应该分别读取 BCDSEC、BCDMNIN、BCDHOUR、BCDDAY、BCDDATE、BCDMON和BCDYEAR寄存器中内容。然而在读这多个寄存器的时候会产生一秒变化是可能的,例如,当用户从BCDYEAR一直读到BCDMIN的时候,结果假定是 2059 (Year), 12 (Month), 31 (Date), 23 (Hour) and 59 (Minute). 当用户读BCDSEC寄存器,值的范围是1到时59,这没有问题, 但是当值为0秒时,年、月、日期、时和分可能已经变成了2060(Year), 1(Month), 1 (Date), 0 (Hour) and 0 (Minute) ,这是因为一秒的变化已经发生了,在这种情况下,用户应该在BCDSEC是0的进修重新读BCDYEAR到BCDSEC。
备用电池操作
RTC逻辑可以用备用电池驱动,它可以通过RTCVDD管角向RTC模块供电,即使系统电源关掉了。当系统是关的时候,CPU和RTC逻辑的接口应该是阻塞的,备用电池仅仅驱动振荡电路和BCD计数器去减少电源消耗。
报警功能
RTC在power-off模式或者正常操作模式时可以在一指定的时间产生一个报警信号。在正常操作模式下,报警中断(ALMINT)被激活,在power-off模式下,电源管理唤醒信号(PMWKUP)和ALMINT一起被激活。RTC报警寄存器(RTCALM)决定报警的enable/disable状态和报警时间设定的条件。
TICK TIME中断
RTC TICK TIME被用于中断请求。TICNT寄存器有一个中断使能位和中断的计数值。当计数值到达0时TICK TIME中断。所以中断的周期如下:
周期= (n+1 ) /128 秒
n:Tick time计数值(1~127)
这个RTC time tick可以被用于实时操作系统(RTOS)内核 time tick。如果time tick通过RTC time tick产生,那么RTOS的时间相关的功能就需要总是与实时时间同步。
ROUND RESET 功能
Rund reset功能可以通过RTC round reset寄存器(RTCRST)来执行。 The round boundary (30, 40, or 50 sec.) of the second carry generation can be selected, and the second value is rounded to zero in the round reset. For example, when the current time is 23:37:47 and the round boundary is selected to 40 sec, the round reset changes the current time to 23:38:00.
NOTE
All RTC registers have to be accessed for each byte unit using the STRB and LDRB instructions or char type pointer.
平台设备的注册
.../arch/arm/plat-s3c24xx/devs.c
/* RTC */
static struct resource s3c_rtc_resource[] = {
// 占用的IO内存范围
[0] = {
.start = S3C24XX_PA_RTC,
.end = S3C24XX_PA_RTC + 0xff,
.flags = IORESOURCE_MEM,
},
// RTC Alarm Interrupt
[1] = {
.start = IRQ_RTC,
.end = IRQ_RTC,
.flags = IORESOURCE_IRQ,
},
// RTC Tick time interrupt.
[2] = {
.start = IRQ_TICK,
.end = IRQ_TICK,
.flags = IORESOURCE_IRQ
}
};
// 平台设备结构。
struct platform_device s3c_device_rtc = {
.name = "s3c2410-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_rtc_resource),
.resource = s3c_rtc_resource,
};
EXPORT_SYMBOL(s3c_device_rtc);
通过 platform_add_devices被注册。
static void __init qt2410_machine_init(void)
{
...
// 注册平台设备.
platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
...
}
平台驱动
在.../drivers/rtc/Makefile中与我们有关的项有
obj-$(CONFIG_RTC_LIB) += rtc-lib.o
obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
rtc-core-y := class.o interface.o
rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
其中rtc-lib.c :提供了一些时间格式相互转化的函数。hctosys.c:在启动时初始化系统时间。RTC核心文件:class.c interface.c rtc-dev.c:字符设备的注册和用户层文件操作函数接口。 rtc-proc.c rtc-sysfs.crtc-s3c.o:S3C2410 RTC的芯片平台驱动。