ARM-Linux驱动--RTC(实时时钟)驱动分析

硬件平台:FL2440(S3C2440)

内核版本:Linux 2.6.28

主机平台:Ubuntu 11.04

内核版本:Linux 2.6.39

交叉编译器版本:arm-linux-gcc 3.4.1

原创作品,转载请标明出处http://blog.csdn.net/yming0221/article/details/6584285

1、实时时钟概述

实时时钟(RTC)单元可以在断电的情况下使用纽扣电池继续计时工作。RTC使用STRB/LDRB ARM操作传输二进制码十进制数的8位数据给CPU。其中的数据包括秒、分、时、日期、天、月、年的时间信息。可以执行报警功能。

2、实时时钟操作

下面是RTC模块的电路图

ARM-Linux驱动--RTC(实时时钟)驱动分析_第1张图片

3、RTC寄存器介绍

实时时钟控制寄存器(RTCCON)-REAL TIME CLOCK CONTROL REGISTER


ARM-Linux驱动--RTC(实时时钟)驱动分析_第2张图片

节拍时间计数寄存器(TICNT)-TICK TIME COUNT REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第3张图片

RTC报警控制寄存器(RTCALM)-RTC ALARM CONTROL REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第4张图片

报警秒数寄存器(ALMSEC)-ALARM SECOND DATA REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第5张图片

报警分钟计数寄存器(ALMMIN)-ALARM MIN DATA REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第6张图片

报警小时数据寄存器(ALMHOUR)-ALARM HOUR DATA REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第7张图片

报警日期数据寄存器(ALMDATE)-ALARM DATE DATA REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第8张图片

报警月数数据寄存器(ALMMON)-ALARM MON DATA REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第9张图片

报警年数数据寄存器(ALMYEAR)-ALARM YEAR DATA REGISTER

ARM-Linux驱动--RTC(实时时钟)驱动分析_第10张图片

BCD数据寄存器的格式和报警寄存器结构相同,只是对应的地址不同。

BCD秒寄存器(BCDSEC)-BCD SECOND REGISTER 地址:0x57000070(L)0x57000073(B)

BCD分寄存器(BCDMIN)-BCD MINUTE REGISTER 地址:0x57000074(L)0x57000077(B)

BCD小时寄存器(BCDHOUR)-BCD HOUR REGISTER 地址:0x57000078(L)0x5700007B(B)

BCD日期寄存器(BCDDATE)-BCD DATE REGISTER 地址:0x5700007C(L)0x5700007F(B)

BCD日寄存器(BCDDAY)-BCD DAY REGISTER 地址:0x57000080(L)0x57000083(B)

BCD月寄存器(BCDMON)-BCD MONTH REGISTER 地址:0x57000084(L)0x57000087(B)

BCD年寄存器(BCDYEAR)-BCD YEAR REGISTER 地址:0x57000088(L)0x5700008B(B)

4、驱动实例分析

为了使驱动更容易理解,现在这个RTC驱动只完成了计时功能,没有添加相应的报警功能,也没有添加电源管理的功能,缺少的功能今后完善。

下面先总体了解驱动:

首先是RTC驱动的结构体,在/include/linux/platform_device.h中,如下

驱动中定义对应的结构体

下面是驱动中驱动的初始化和退出函数

platform_driver_register()和platform_driver_unregister()函数在/drivers/base/platform.c中实现的。

可以看出,platform_driver_register()函数的作用就是为platform_driver中的driver中的probe、remove等提供接口函数

接下来是RTC平台驱动探测函数s3c_rtc_probe,下面函数定义的时候使用了__devinit的作用是使编译器优化代码,将其放在和是的内存位置,减少内存占用和提高内核效率。

probe函数接收到plarform_device这个参数后,就需要从中提取出需要的信息。它一般会通过调用内核提供的platform_get_resource和platform_get_irq等函数来获得相关信息。如通过platform_get_resource获得设备的起始地址后,可以对其进行request_mem_region和ioremap等操作,以便应用程序对其进行操作。通过platform_get_irq得到设备的中断号以后,就可以调用request_irq函数来向系统申请中断。这些操作在设备驱动程序中一般都要完成。

下面是/include/linux/ioport.h中struct resource结构体定义
这是dev_set_drvdata()的函数定义:

接下来是在s3c_rtc_probe()函数用到的两个函数s3c_rtc_enable()和s3c_rtc_setfreq()

接下来是RTC设备类的操作。

下面是rtc_class_ops是RTC设备类在RTC驱动核心部分中定义的对RTC设备类进行操作的结构体,类似字符设备在驱动中的file_operations对字符设备进行操作的意思。该结构体被定义在rtc.h中,对RTC的操作主要有打开、关闭、设置或获取时间、设置或获取报警、设置节拍时间计数值等等,该结构体内接口函数的实现都在下面

RTC打开设备函数s3c_rtc_open()

RTC TICK节拍时间中断服务程序

RTC关闭设备函数s3c_rtc_release()

s3c_rtc_setpie()函数,该函数主要作用就是根据参数设置TICNT寄存器的最高位,参数为0,禁止使能,参数为1,使能
下面两个函数是设置和读取BCD寄存器的时间,逻辑很简单,只是读取和设置相应寄存器的值

到这里RTC驱动的计时功能实现,报警功能还没有完成。下面是这个驱动源代码


Makefile文件


make后在目录下生成rtc.ko驱动,利用NFS挂在到目标板,insmod rtc.ko驱动就可以加载,执行hwclock命令,查看是否可以读取硬件的RTC。










你可能感兴趣的:(linux)