微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM-Linux驱动--RTC(实时时钟)驱动分析

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

时间:11-20 来源:互联网 点击:
硬件平台: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模块的电路图

3、RTC寄存器介绍

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

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

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

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

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

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

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

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

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

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中,如下

[cpp]view plaincopy

  1. structplatform_driver{
  2. int(*probe)(structplatform_device*);
  3. int(*remove)(structplatform_device*);
  4. void(*shutdown)(structplatform_device*);
  5. int(*suspend)(structplatform_device*,pm_message_tstate);
  6. int(*suspend_late)(structplatform_device*,pm_message_tstate);
  7. int(*resume_early)(structplatform_device*);
  8. int(*resume)(structplatform_device*);
  9. structpm_ext_ops*pm;
  10. structdevice_driverdriver;
  11. };

驱动中定义对应的结构体

[cpp]view plaincopy

  1. staticstructplatform_drivers3c2410_rtc_driver={
  2. .probe=s3c_rtc_probe,//RTC探测函数
  3. .remove=__devexit_p(s3c_rtc_remove),//RTC移除函数
  4. .driver={
  5. .name="s3c2410-rtc",
  6. .owner=THIS_MODULE,
  7. },
  8. };

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

[cpp]view plaincopy

  1. staticint__inits3c_rtc_init(void)
  2. {
  3. printk(banner);
  4. returnplatform_driver_register(&s3c2410_rtc_driver);
  5. }
  6. staticvoid__exits3c_rtc_exit(void)
  7. {
  8. platform_driver_unregister(&s3c2410_rtc_driver);
  9. }

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

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

[cpp]view plaincopy

  1. intplatform_driver_register(structplatform_driver*drv)
  2. {
  3. drv->driver.bus=&platform_bus_type;
  4. if(drv->probe)
  5. drv->driver.probe=platform_drv_probe;
  6. if(drv->remove)
  7. drv->driver.remove=platform_drv_remove;
  8. if(drv->shutdown)
  9. drv->driver.shutdown=platform_drv_shutdown;
  10. if(drv->suspend)
  11. drv->driver.suspend=platform_drv_suspend;
  12. if(drv->resume)
  13. drv->driver.resume=platform_drv_resume;
  14. if(drv->pm)
  15. drv->driver.pm=&drv->pm->base;
  16. returndriver_register(&drv->driver);//注册老的驱动
  17. }

[cpp]view plaincopy

  1. voidplatform_driver_unregister(structplatform_driver*drv)
  2. {
  3. driver_unregister(&drv->driver);
  4. }

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

probe函数接收到pla

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top