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

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             

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

网站地图

Top