ARMLinux驱动RTC(实时时钟)驱动分析
时间:11-09
来源:互联网
点击:
下面是rtc_class_ops是RTC设备类在RTC驱动核心部分中定义的对RTC设备类进行操作的结构体,类似字符设备在驱动中的file_operations对字符设备进行操作的意思。该结构体被定义在rtc.h中,对RTC的操作主要有打开、关闭、设置或获取时间、设置或获取报警、设置节拍时间计数值等等,该结构体内接口函数的实现都在下面
static const struct rtc_class_ops s3c_rtcops = {.open = s3c_rtc_open,.release = s3c_rtc_release,.read_time = s3c_rtc_gettime,.set_time = s3c_rtc_settime,.irq_set_freq = s3c_rtc_setfreq,.irq_set_state = s3c_rtc_setpie,};RTC打开设备函数s3c_rtc_open()
static int s3c_rtc_open(struct device *dev){struct platform_device *pdev = to_platform_device(dev);//从平台设备中获取RTC设备类的数据struct rtc_device *rtc_dev = platform_get_drvdata(pdev);int ret;ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev);//申请中断if (ret) {dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);goto tick_err;}tick_err:return ret;}RTC TICK节拍时间中断服务程序
static irqreturn_t s3c_rtc_tickirq(int irq, void *id){struct rtc_device *rdev = id;rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);return IRQ_HANDLED;}RTC关闭设备函数s3c_rtc_release()
static void s3c_rtc_release(struct device *dev){struct platform_device *pdev = to_platform_device(dev);//从平台设备中获取RTC设备类的数据struct rtc_device *rtc_dev = platform_get_drvdata(pdev);/* do not clear AIE here, it may be needed for wake */s3c_rtc_setpie(dev, 0);//函数定义见下面free_irq(s3c_rtc_tickno, rtc_dev);}s3c_rtc_setpie()函数,该函数主要作用就是根据参数设置TICNT寄存器的最高位,参数为0,禁止使能,参数为1,使能
static int s3c_rtc_setpie(struct device *dev, int enabled){unsigned int tmp;pr_debug("%s: pie=%d\n", __func__, enabled);spin_lock_irq(&s3c_rtc_pie_lock);tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;//读取TICNT的值并将最高位清0if (enabled)tmp |= S3C2410_TICNT_ENABLE;writeb(tmp, s3c_rtc_base + S3C2410_TICNT);//写入计算后新的值spin_unlock_irq(&s3c_rtc_pie_lock);return 0;}下面两个函数是设置和读取BCD寄存器的时间,逻辑很简单,只是读取和设置相应寄存器的值
static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm){unsigned int have_retried = 0;void __iomem *base = s3c_rtc_base;retry_get_time:rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);rtc_tm->tm_mon = readb(base + S3C2410_RTCMON);rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC);/* the only way to work out wether the system was mid-update* when we read it is to check the second counter, and if it* is zero, then we re-try the entire read*/if (rtc_tm->tm_sec == 0 && !have_retried) {have_retried = 1;goto retry_get_time;}pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);rtc_tm->tm_year += 100;rtc_tm->tm_mon -= 1;return 0;}static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm){void __iomem *base = s3c_rtc_base;int year = tm->tm_year - 100;pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",tm->tm_year, tm->tm_mon, tm->tm_mday,tm->tm_hour, tm->tm_min, tm->tm_sec);/* we get around y2k by simply not supporting it */if (year < 0 || year >= 100) {dev_err(dev, "rtc only supports 100 years\n");return -EINVAL;}writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC);writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN);writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);writeb(bin2bcd(year), base + S3C2410_RTCYEAR);return 0;}到这里RTC驱动的计时功能实现,报警功能还没有完成。下面是这个驱动源代码
#include#include #include #include #include #include
ARMLinuxRTC实时时 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)