S3C2410的RTC驅(qū)動(dòng)分析
S3C2410 RTC(Real Time Clock)簡(jiǎn)介
實(shí)時(shí)時(shí)鐘(RTC)單元可以在系統(tǒng)電源關(guān)半閉的情況下依靠備用電池工作。RTC可以通過(guò)使用STRB/LDDRB這兩個(gè)ARM指令向CPU傳遞8位數(shù)據(jù)(BCD碼)。數(shù)據(jù)包括秒、分、小時(shí)、日期、天、月、和年。RTC單元依靠一個(gè)外部的32.768kHZ的石晶,也可以執(zhí)行報(bào)警功能。
特性
BCD碼:秒、分、時(shí)、日期、天、月和年
潤(rùn)年產(chǎn)生器
報(bào)警功能:報(bào)警中斷,或者從power-off狀態(tài)喚醒。
移除了2000年的問(wèn)題
獨(dú)立的電源引角:RTCVDD
為RTOS內(nèi)核時(shí)間Tick time支持毫秒Tick time中斷。
Round reset 功能。
RTC操作
潤(rùn)年產(chǎn)生器
潤(rùn)年產(chǎn)生器可以判斷每個(gè)月的最后一天是28、29、30還是31,計(jì)算的基礎(chǔ)是BCDDATA、 BCDMON和BCDYEAR中的數(shù)據(jù)。這一塊在考慮最后一天的時(shí)候還考慮至了潤(rùn)年的情況,一個(gè)8位的計(jì)數(shù)器只能表示2個(gè)BCD數(shù)字,所以他漢有決定一個(gè)以“00”為結(jié)尾的年是不是潤(rùn)年。例如,他不能在1900和2000中分辨。為了解決這個(gè)問(wèn)題,在S3C2410的RTC模塊中用了硬線(xiàn)邏輯去支持2000這個(gè)潤(rùn)年,注意1900不是潤(rùn)年,而2000是潤(rùn)年,
讀/寫(xiě)寄存器
RTCCON寄存器的Bit 0 必須被置高,這樣是為了寫(xiě)RTC模塊的BCD寄存器。為了顯示秒、分、時(shí)、日期、月年,CPU應(yīng)該分別讀取 BCDSEC、BCDMNIN、BCDHOUR、BCDDAY、BCDDATE、BCDMON和BCDYEAR寄存器中內(nèi)容。然而在讀這多個(gè)寄存器的時(shí)候會(huì)產(chǎn)生一秒變化是可能的,例如,當(dāng)用戶(hù)從BCDYEAR一直讀到BCDMIN的時(shí)候,結(jié)果假定是 2059 (Year), 12 (Month), 31 (Date), 23 (Hour) and 59 (Minute). 當(dāng)用戶(hù)讀BCDSEC寄存器,值的范圍是1到時(shí)59,這沒(méi)有問(wèn)題, 但是當(dāng)值為0秒時(shí),年、月、日期、時(shí)和分可能已經(jīng)變成了2060(Year), 1(Month), 1 (Date), 0 (Hour) and 0 (Minute) ,這是因?yàn)橐幻氲淖兓呀?jīng)發(fā)生了,在這種情況下,用戶(hù)應(yīng)該在BCDSEC是0的進(jìn)修重新讀BCDYEAR到BCDSEC。
備用電池操作
RTC邏輯可以用備用電池驅(qū)動(dòng),它可以通過(guò)RTCVDD管角向RTC模塊供電,即使系統(tǒng)電源關(guān)掉了。當(dāng)系統(tǒng)是關(guān)的時(shí)候,CPU和RTC邏輯的接口應(yīng)該是阻塞的,備用電池僅僅驅(qū)動(dòng)振蕩電路和BCD計(jì)數(shù)器去減少電源消耗。
報(bào)警功能
RTC在power-off模式或者正常操作模式時(shí)可以在一指定的時(shí)間產(chǎn)生一個(gè)報(bào)警信號(hào)。在正常操作模式下,報(bào)警中斷(ALMINT)被激活,在power-off模式下,電源管理喚醒信號(hào)(PMWKUP)和ALMINT一起被激活。RTC報(bào)警寄存器(RTCALM)決定報(bào)警的enable/disable狀態(tài)和報(bào)警時(shí)間設(shè)定的條件。
TICK TIME中斷
RTC TICK TIME被用于中斷請(qǐng)求。TICNT寄存器有一個(gè)中斷使能位和中斷的計(jì)數(shù)值。當(dāng)計(jì)數(shù)值到達(dá)0時(shí)TICK TIME中斷。所以中斷的周期如下:
周期= (n+1 ) /128 秒
n:Tick time計(jì)數(shù)值(1~127)
這個(gè)RTC time tick可以被用于實(shí)時(shí)操作系統(tǒng)(RTOS)內(nèi)核 time tick。如果time tick通過(guò)RTC time tick產(chǎn)生,那么RTOS的時(shí)間相關(guān)的功能就需要總是與實(shí)時(shí)時(shí)間同步。
ROUND RESET 功能
Rund reset功能可以通過(guò)RTC round reset寄存器(RTCRST)來(lái)執(zhí)行。 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.
平臺(tái)設(shè)備的注冊(cè)
.../arch/arm/plat-s3c24xx/devs.c
/* RTC */
static struct resource s3c_rtc_resource[] = {
// 占用的IO內(nèi)存范圍
[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
}
};
// 平臺(tái)設(shè)備結(jié)構(gòu)。
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);
通過(guò) platform_add_devices被注冊(cè)。
static void __init qt2410_machine_init(void)
{
...
// 注冊(cè)平臺(tái)設(shè)備.
platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
...
}
平臺(tái)驅(qū)動(dòng)
在.../drivers/rtc/Makefile中與我們有關(guān)的項(xiàng)有
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 :提供了一些時(shí)間格式相互轉(zhuǎn)化的函數(shù)。hctosys.c:在啟動(dòng)時(shí)初始化系統(tǒng)時(shí)間。RTC核心文件:class.c interface.c rtc-dev.c:字符設(shè)備的注冊(cè)和用戶(hù)層文件操作函數(shù)接口。 rtc-proc.c rtc-sysfs.crtc-s3c.o:S3C2410 RTC的芯片平臺(tái)驅(qū)動(dòng)。