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

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

时间:11-20 来源:互联网 点击:

  1. _RTCCON_RTCEN,base+S3C2410_RTCCON);
  2. }
  3. if((readb(base+S3C2410_RTCCON)&S3C2410_RTCCON_CNTSEL)){
  4. dev_info(&pdev->dev,"removingRTCCON_CNTSEL\n");
  5. tmp=readb(base+S3C2410_RTCCON);
  6. writeb(tmp&~S3C2410_RTCCON_CNTSEL,base+S3C2410_RTCCON);//设置RTCCON第2位为0,设置BCD计数为混合BCD计数
  7. }
  8. if((readb(base+S3C2410_RTCCON)&S3C2410_RTCCON_CLKRST)){
  9. dev_info(&pdev->dev,"removingRTCCON_CLKRST\n");
  10. tmp=readb(base+S3C2410_RTCCON);
  11. writeb(tmp&~S3C2410_RTCCON_CLKRST,base+S3C2410_RTCCON);//RTC时钟计数器复位
  12. }
  13. }
  14. }

[cpp]view plaincopy

  1. staticints3c_rtc_setfreq(structdevice*dev,intfreq)//设定节拍时间计数值
  2. {
  3. unsignedinttmp;
  4. spin_lock_irq(&s3c_rtc_pie_lock);//获取自旋锁,对资源互斥访问
  5. tmp=readb(s3c_rtc_base+S3C2410_TICNT)&S3C2410_TICNT_ENABLE;//节拍时间使能有效
  6. tmp|=(128/freq)-1;
  7. writeb(tmp,s3c_rtc_base+S3C2410_TICNT);
  8. spin_unlock_irq(&s3c_rtc_pie_lock);//解锁
  9. return0;
  10. }

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

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

  1. staticconststructrtc_class_opss3c_rtcops={
  2. .open=s3c_rtc_open,
  3. .release=s3c_rtc_release,
  4. .read_time=s3c_rtc_gettime,
  5. .set_time=s3c_rtc_settime,
  6. .irq_set_freq=s3c_rtc_setfreq,
  7. .irq_set_state=s3c_rtc_setpie,
  8. };

RTC打开设备函数s3c_rtc_open()

  1. staticints3c_rtc_open(structdevice*dev)
  2. {
  3. structplatform_device*pdev=to_platform_device(dev);//从平台设备中获取RTC设备类的数据
  4. structrtc_device*rtc_dev=platform_get_drvdata(pdev);
  5. intret;
  6. ret=request_irq(s3c_rtc_tickno,s3c_rtc_tickirq,
  7. IRQF_DISABLED,"s3c2410-rtctick",rtc_dev);//申请中断
  8. if(ret){
  9. dev_err(dev,"IRQ%derror%d\n",s3c_rtc_tickno,ret);
  10. gototick_err;
  11. }
  12. tick_err:
  13. returnret;
  14. }

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

  1. staticirqreturn_ts3c_rtc_tickirq(intirq,void*id)
  2. {
  3. structrtc_device*rdev=id;
  4. rtc_update_irq(rdev,1,RTC_PF|RTC_IRQF);
  5. returnIRQ_HANDLED;
  6. }

RTC关闭设备函数s3c_rtc_release()

  1. staticvoids3c_rtc_release(structdevice*dev)
  2. {
  3. structplatform_device*pdev=to_platform_device(dev);//从平台设备中获取RTC设备类的数据
  4. structrtc_device*rtc_dev=platform_get_drvdata(pdev);
  5. /*donotclearAIEhere,itmaybeneededforwake*/
  6. s3c_rtc_setpie(dev,0);//函数定义见下面
  7. free_irq(s3c_rtc_tickno,rtc_dev);
  8. }

s3c_rtc_setpie()函数,该函数主要作用就是根据参数设置TICNT寄存器的最高位,参数为0,禁止使能,参数为1,使能

  1. staticints3c_rtc_setpie(structdevice*dev,intenabled)
  2. {
  3. unsignedinttmp;
  4. pr_debug("%s:pie=%d\n",__func__,enabled);
  5. spin_lock_irq(&s3c_rtc_pie_lock);
  6. tmp=readb(s3c_rtc_base+S3C2410_TICNT)&~S3C2410_TICNT_ENABLE;//读取TICNT的值并将最高位清0
  7. if(enabled)
  8. tmp|=S3C2410_TICNT_ENABLE;
  9. writeb(tmp,s3c_rtc_base+S3C2410_TICNT);//写入计算后新的值
  10. spin_unlock_irq(&s3c_rtc_pie_lock);
  11. return0;
  12. }

下面两个函数是设置和读取BCD寄存器的时间,逻辑很简单,只是读取和设置相应寄存器的值

  1. staticints3c_rtc_gettime(structdevice*dev,structrtc_time*rtc_tm)
  2. {
  3. unsignedinthave_retried=0;
  4. void__iomem*base=s3c_rtc_base;
  5. retry_get_time:
  6. rtc_tm->tm_min=readb(base+S3C2410_RTCMIN);
  7. rtc_tm->tm_hour=readb(base+S3C2410_RTCHOUR);
  8. rtc_tm->tm_mday=readb(base+S3C2410_RTCDATE);
  9. rtc_tm->tm_mon=readb(base+S3C2410_RTCMON);
  10. rtc_tm->tm_year=readb(base+S3C2410_RTCYEAR);
  11. rtc_tm->tm_sec=readb(base+S3C2410_RTCSEC);
  12. /*theonlywaytoworkoutwetherthesystemwasmid-update
  13. *whenwereaditistocheckthesecondcounter,andifit
  14. *iszero,thenwere-trytheentireread
  15. */
  16. if(rtc_tm->tm_sec==0&&!have_retried){
  17. have_retried=1;
  18. gotoretry_get_time;
  19. }
  20. pr_debug("readtime%02x.%02x.%02x%02x/%02x/%02x\n",
  21. rtc_tm->tm_year,rtc_tm->tm_mon,rtc_tm->tm_mday,
  22. rtc_tm->tm_hour,rtc_tm->tm_min,rtc_tm->tm_sec);
  23. rtc_tm->tm_sec=bcd2bin(rtc_tm->tm_sec);
  24. rtc_tm->tm_min=bcd2bin(rtc_tm->rtc_tm->tm_min=bcd2bin(rtc_tm->tm

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

网站地图

Top