S3C2440上RTC时钟驱动开发实例讲解.docx
- 文档编号:3046947
- 上传时间:2022-11-17
- 格式:DOCX
- 页数:27
- 大小:101.79KB
S3C2440上RTC时钟驱动开发实例讲解.docx
《S3C2440上RTC时钟驱动开发实例讲解.docx》由会员分享,可在线阅读,更多相关《S3C2440上RTC时钟驱动开发实例讲解.docx(27页珍藏版)》请在冰豆网上搜索。
S3C2440上RTC时钟驱动开发实例讲解
S3C2440上RTC时钟驱动开发实例讲解
一、开发环境
∙主 机:
VMWare--Fedora9
∙开发板:
Mini2440--64MBNand,Kernel:
2.6.30.4
∙编译器:
arm-linux-gcc-4.3.2
二、相关概念
1、平台设备:
通常在Linux中,把SoC系统中集成的独立外设单元(如:
I2C、IIS、RTC、看门狗等)都被当作平台设备来处理。
在Linux中用platform_device结构体来描述一个平台设备,在2.6.30.4内核中定义在:
include/linux/platform_device.h中,如下:
structplatform_device{
constchar *name; //设备名称
int id;
structdevice dev;
u32 num_resources; //设备使用各类资源的数量
structresource *resource; //设备使用的资源
structplatform_device_id *id_entry;
};
现在你不必深入理解这个结构体,只要知道在Linux中是用这个结构体来定义一些平台设备的。
比如在:
arch/arm/plat-s3c24xx/devs.c中就定义了很多平台设备,下面我就只贴出RTC这一种的:
/*RTC*/
staticstructresources3c_rtc_resource[]={ //定义了RTC平台设备使用的资源,这些资源在驱动中都会用到
[0]={ //IO端口资源范围
.start=S3C24XX_PA_RTC,
.end=S3C24XX_PA_RTC+0xff,
.flags=IORESOURCE_MEM,
},
[1]={ //RTC报警中断资源
.start=IRQ_RTC,
.end=IRQ_RTC,
.flags=IORESOURCE_IRQ,
},
[2]={ //TICK节拍时间中断资源
.start=IRQ_TICK,
.end=IRQ_TICK,
.flags=IORESOURCE_IRQ
}
};
structplatform_devices3c_device_rtc={ //定义了RTC平台设备
.name ="s3c2410-rtc", //设备名称
.id =-1,
.num_resources =ARRAY_SIZE(s3c_rtc_resource),//资源数量
.resource =s3c_rtc_resource, //引用上面定义的资源
};
EXPORT_SYMBOL(s3c_device_rtc);
好了,定义了平台设备,那系统是怎么来使用他的呢?
我们打开:
arch/arm/mach-s3c2440/mach-smdk2440.c这个ARM2440平台的系统入口文件,可以看到在系统初始化函数smdk2440_machine_init中是使用platform_add_devices这个函数将一些平台设备添加到系统中的,如下:
(至于系统是如何实现添加平台设备的,这里我们不必研究,这些Linux系统都已经做好了的,我们要研究的是后面平台设备的驱动是如何实现的)
staticstructplatform_device*smdk2440_devices[]__initdata={
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
&s3c_device_rtc, //这里我们添加上RTC平台设备,默认是没添加的
}; //平台设备列表,也就是说我们要使用一个新的平台设备要先在上面定义,然后加到这个列表中,最后到驱动层去实现该设备的驱动
staticvoid__initsmdk2440_machine_init(void)
{
s3c24xx_fb_set_platdata(&smdk2440_fb_info);
s3c_i2c0_set_platdata(NULL);
//将上面列表中的平台设备添加到系统总线中
platform_add_devices(smdk2440_devices,ARRAY_SIZE(smdk2440_devices));
smdk_machine_init();
}
2、平台设备驱动:
这里所讲的平台设备驱动是指具体的某种平台设备的驱动,比如上面讲的RTC平台设备,这里就是指RTC平台设备驱动。
在Linux中,系统还为平台设备定义了平台驱动结构体platform_driver,就好比系统为字符设备定义了file_operations一样,但不要把平台设备跟字符设备、块设备、网络设备搞成了并列的概念,因平台设备也可以是字符设备等其他设备。
注意:
在被定义为平台设备的字符设备的驱动中,除了要实现字符设备驱动中file_operations的open、release、read、write等接口函数外,还要实现平台设备驱动中platform_driver的probe、remove、suspend、resume等接口函数。
好了,在我们搞明白上面这些后,下面我们就来具体详细分析讲解RTC平台设备的驱动现实。
三、实例讲解
1、RTC在Linux中的整体结构:
就个人理解,RTC在Linux中整体结构分为两个部分。
第一个是部分就是上面所讲的作为平台设备被挂接到系统总线中,这里我把他叫做设备层(呵呵,可能不是很准确的叫法);第二部分就是驱动部分,这里叫做驱动层。
在Linux中要使一个驱动在不同的平台中都能够使用似乎是不可能的,所以我们先看2.6.30.4内核驱动中的RTC部分是单独的一个文件夹,在文件夹中包含了很多不同体系结构的RTC驱动,当然也有S3C2440的RTC驱动,然而在这些驱动中他们都使用了一组文件里面的方法,那么这组文件就是RTC的核心(注意这里的核心不是指对RTC硬件的操作,指的是对RTC操作的方法。
对硬件寄存器的操作还是在具体的驱动中)。
好了,我们还是用图来说明这种关系吧!
!
2、RTC硬件原理图分析:
以下是S3C2440AL内部集成的RTC模块结构图和一个外部的晶振接口图
我们从S3C2440内部RTC模块结构图和数据手册得知,RTC在Linux中主要实现两种功能,分别是系统掉电后的时间日期维持和时间日期报警(类似定时器功能)。
①、时间日期维持功能:
主要是由RTC实时时钟控制寄存器RTCCON进行功能的使能控制,由节拍时间计数寄存器TICNT来产生节拍时间中断来实现实时操作系统功能相关的时间和实时同步。
其中对时间日期的操作实际上是对BCD码操作,而BCD码则是由一系列的寄存器组成(BCD秒寄存器BCDSEC、BCD分寄存器BCDMIN、BCD小时寄存器BCDHOUR、BCD日期寄存器BCDDATE、BCD日寄存器BCDDAY、BCD月寄存器BCDMON、BCD年寄存器BCDYEAR)。
②、报警功能:
主要由RTC报警控制寄存器RTCALM进行功能使能控制,并产生报警中断。
报警时间日期的设置也是对一系列的寄存器进行操作(报警秒数据寄存器ALMSEC、报警分钟数据寄存器ALMMIN、报警小时数据寄存器ALMHOUR、报警日期数据寄存器ALMDATE、报警月数据寄存器ALMMON、报警年数据寄存器ALMYEAR)。
3、RTC驱动实现步骤(建立驱动文件my2440_rtc.c):
注意:
在每步中,为了让代码逻辑更加有条理和容易理解,就没有考虑代码的顺序,比如函数要先定义后调用。
如果要编译此代码,请严格按照C语言的规范来调整代码的顺序。
①、依然是驱动程序的最基本结构:
RTC驱动的初始化和退出部分及其他,如下:
#include
#include
#include
#include
#include
/*RTC平台驱动结构体,平台驱动结构体定义在platform_device.h中,该结构体内的接口函数在第②、④步中实现*/
staticstructplatform_driverrtc_driver=
{
.probe =rtc_probe,/*RTC探测函数,在第②步中实现*/
.remove =__devexit_p(rtc_remove),/*RTC移除函数,在第④步实现,为何使用__devexit_p,在该函数实现的地方再讲*/
.suspend=rtc_suspend,/*RTC挂起函数,在第④步中实现*/
.resume =rtc_resume,/*RTC恢复函数,在第④步中实现*/
.driver =
{
/*注意这里的名称一定要和系统中定义平台设备的地方一致,这样才能把平台设备与该平台设备的驱动关联起来*/
.name ="s3c2410-rtc",
.owner =THIS_MODULE,
},
};
staticint__initrtc_init(void)
{
/*将RTC注册成平台设备驱动*/
returnplatform_driver_register(&rtc_driver);
}
staticvoid__exitrtc_exit(void)
{
/*注销RTC平台设备驱动*/
platform_driver_unregister(&rtc_driver);
}
module_init(rtc_init);
module_exit(rtc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HuangGang");
MODULE_DESCRIPTION("My2440RTCdriver");
②、RTC平台驱动结构中探测函数rtc_probe的实现。
探测就意味着在系统总线中去检测设备的存在,然后获取设备有用的相关资源信息,以便我们使用这些信息。
代码如下:
#include
#include
#include
#include
#include
/*定义了一个用来保存RTC的IO端口占用的IO空间和经过虚拟映射后的内存地址*/
staticstructresource*rtc_mem;
staticvoid__iomem*rtc_base;
/*定义了两个变量来保存RTC报警中断
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- S3C2440 RTC 时钟 驱动 开发 实例 讲解