ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:25.56KB ,
资源ID:22437679      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/22437679.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(RTC驱动Word下载.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

RTC驱动Word下载.docx

1、= THIS_MODULE,;static int _init rtc_init(void)/*将RTC注册成平台设备驱动*/return platform_driver_register(&rtc_driver);static void _exit rtc_exit(void)/*注销RTC平台设备驱动*/platform_driver_unregister(&module_init(rtc_init);module_exit(rtc_exit);MODULE_LICENSE(GPL);MODULE_AUTHOR(Huang GangMODULE_DESCRIPTION(My2440 RTC

2、 driver2、 RTC平台驱动结构中探测函数rtc_probe的实现。探测就意味着在系统总线中去检测设备的存在,然后获取设备有用的相关资源信息,以便我们使用这些信息。代码如下:asm/irq.hasm/io.hlinux/rtc.hlinux/ioport.hplat/regs-rtc.h/*定义了一个用来保存RTC的IO端口占用的IO空间和经过虚拟映射后的内存地址*/static struct resource *rtc_mem;static void _iomem *rtc_base;/*定义了两个变量来保存RTC报警中断号和TICK节拍时间中断号,NO_IRQ宏定义在irq.h中*/

3、static int rtc_alarmno = NO_IRQ;static int rtc_tickno = NO_IRQ;/*申明并初始化一个自旋锁rtc_pie_lock,对RTC资源进行互斥访问*/static DEFINE_SPINLOCK(rtc_pie_lock)/*RTC平台驱动探测函数,注意这里为什么要使用一个_devinit,也到rtc_remove实现的地方一起讲*/static int _devinit rtc_probe(struct platform_device *pdev)int ret;struct rtc_device *rtc; /*定义一个RTC设备类,

4、rtc_device定义在rtc.h中*/struct resource *res; /*定义一个资源,用来保存获取的RTC的资源*/*在系统定义的RTC平台设备中获取RTC报警中断号 platform_get_irq定义在platform_device.h中*/rtc_alarmno = platform_get_irq(pdev, 0);if (rtc_alarmno dev, no irq for alarmnreturn -ENOENT;/在系统定义的RTC平台设备中获取TICK节拍时间中断号rtc_tickno = platform_get_irq(pdev, 1);if (rtc_

5、tickno start, res-end - res-start + 1, pdev-name);if (rtc_mem = NULL) failed to reserve memory regionnret = -ENOENT;goto err_nores;/*将RTC的IO端口占用的这段IO空间映射到内存的虚拟地址,ioremap定义在io.h中。 注意:IO空间要映射后才能使用,以后对虚拟地址的操作就是对IO空间的操作,*/rtc_base = ioremap(res-start + 1);if (rtc_base = NULL) failed ioremap()nret = -EIN

6、VAL;goto err_nomap;/*好了,通过上面的步骤已经将RTC的资源都准备好了,下面就开始使用啦*/*这两个函数开始对RTC寄存器操作,定义都在下面*/rtc_enable(pdev, 1); /*对RTC的实时时钟控制寄存器RTCCON进行操作(功能是初始化或者使能RTC)*/rtc_setfreq(&dev, 1);/*对RTC的节拍时间计数寄存器TICNT的0-6位进行操作,即:节拍时间计数值的设定*/*device_init_wakeup该函数定义在pm_wakeup.h中,定义如下:static inline void device_init_wakeup(struct

7、device *dev, int val)dev-power.can_wakeup = dev-power.should_wakeup = !val;显然这个函数是让驱动支持电源管理的,这里只要知道,can_wakeup为1时表明这个设备可以被唤醒,设备驱动为了支持Linux中的电源管理,有责任调用device_init_wakeup()来初始化can_wakeup,而should_wakeup则是在设备的电源状态发生变化的时候被device_may_wakeup()用来测试,测试它该不该变化,因此can_wakeup表明的是一种能力,而should_wakeup表明的是有了这种能力以后去不去

8、做某件事。好了,我们没有必要深入研究电源管理的内容了,要不就扯远了,电源管理以后再讲*/device_init_wakeup(&/*将RTC注册为RTC设备类,RTC设备类在RTC驱动核心部分中由系统定义好的, 注意rtcops这个参数是一个结构体,该结构体的作用和里面的接口函数实现在第步中。 rtc_device_register函数在rtc.h中定义,在drivers/rtc/class.c中实现*/rtc = rtc_device_register(my2440, &dev, &rtcops, THIS_MODULE);if (IS_ERR(rtc) cannot attach rtcn

9、ret = PTR_ERR(rtc);goto err_nortc;/*设置RTC节拍时间计数寄存器TICNT的节拍时间计数值的用户最大相对值, 这里你可能不理解这句,没关系,等你看到rtc_setfreq函数实现后自然就明白了*/rtc-max_user_freq = 128;/*将RTC设备类的数据传递给系统平台设备。 platform_set_drvdata是定义在platform_device.h的宏,如下: #define platform_set_drvdata(_dev,data)dev_set_drvdata(&(_dev)-dev, (data) 而dev_set_drvda

10、ta又被定义在include/linux/device.h中,如下:static inline void dev_set_drvdata (struct device *dev, void *data)driver_data = data;*/platform_set_drvdata(pdev, rtc);return 0;/以下是上面错误处理的跳转点err_nortc:rtc_enable(pdev, 0);iounmap(rtc_base);err_nomap:release_resource(rtc_mem);err_nores:return ret;/*该函数主要是初始化或者使能RTC

11、,以下RTC的各种寄存器的宏定义在arch/arm/plat-s3c/include/plat/regs-rtc.h中,各寄存器的用途和设置请参考S3C2440数据手册的第十七章实时时钟部分*/static void rtc_enable(struct platform_device *pdev, int flag)unsigned int tmp;/*RTC的实时时钟控制寄存器RTCCON共有4个位,各位的初始值均为0,根据数据手册介绍第0位(即:RCTEN位) 可以控制CPU和RTC之间的所有接口(即RTC使能功能),所以在系统复位后应该将RTCCON寄存器的第0为置为1; 在关闭电源前,

12、又应该将该位清零,以避免无意的写RTC寄存器*/if (!flag) /*当flag=0时(即属于关闭电源前的情况),RTCCON寄存器清零第一位*/tmp = readb(rtc_base + S3C2410_RTCCON); /*读取RTCCON寄存器的值*/* tmp & S3C2410_RTCCON_RTCEN = 0 即屏蔽RTC使能*/writeb(tmp & S3C2410_RTCCON_RTCEN, rtc_base + S3C2410_RTCCON);tmp = readb(rtc_base + S3C2410_TICNT); /*读取TICNT寄存器的值*/ S3C2410

13、_TICNT_ENABLE后第7位为0,即屏蔽节拍时间中断使能*/ S3C2410_TICNT_ENABLE, rtc_base + S3C2410_TICNT); else /*当flag!=0时(即属于系统复位后的情况),使能RTC*/if (readb(rtc_base + S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) = 0)dev_info(&rtc disabled, re-enablingnwriteb(tmp | S3C2410_RTCCON_RTCEN, rtc_base + S3C2410_RTCCON); S3C2410_RTCCON_C

14、NTSEL)removing RTCCON_CNTSELn S3C2410_RTCCON_CNTSEL, rtc_base + S3C2410_RTCCON); S3C2410_RTCCON_CLKRST)removing RTCCON_CLKRSTn S3C2410_RTCCON_CLKRST, rtc_base + S3C2410_RTCCON);/*该函数主要是对RTC的节拍时间计数寄存器TICNT的0-6位进行操作,即:节拍时间计数值的设定*/static int rtc_setfreq(struct device *dev, int freq)is_power_of_2(freq)

15、/*对freq的值进行检查*/return -EINVAL;spin_lock_irq(&rtc_pie_lock); /*获取自旋锁保护临界区资源*/*读取节拍时间计数寄存器TICNT的值*/tmp = readb(rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;/*看数据手册得知,节拍时间计数值的范围是1-127, 还记得在rtc_enable函数中设置的rtc-max_user_freq=128吗?所以这里要减1*/tmp |= (128 / freq) - 1;*将经运算后值写入节拍时间计数寄存器TICNT中,这里主要是改变TICNT的

16、第0-6位的值*/writeb(tmp, rtc_base + S3C2410_TICNT);spin_unlock_irq(&/*释放自旋锁,即解锁*/3、 RTC设备类的操作。在这一步中,才是对RTC硬件的各种寄存器进行操作,代码如下:linux/interrupt.hlinux/bcd.h/*rtc_class_ops是RTC设备类在RTC驱动核心部分中定义的对RTC设备类进行操作的结构体,类似字符设备在驱动中的file_operations对字符设备进行操作的意思。该结构体被定义在rtc.h中,对RTC的操作主要有打开、关闭、设置或获取时间、设置或获取报警、设置节拍时间计数值等等,该结

17、构体内接口函数的实现都在下面*/static const struct rtc_class_ops rtcops = .open= rtc_open,.release = rtc_release,.irq_set_freq= rtc_setfreq, /*在第步中已实现*/.irq_set_state= rtc_setpie,.read_time= rtc_gettime,.set_time= rtc_settime,.read_alarm= rtc_getalarm,.set_alarm= rtc_setalarm,/*RTC设备类打开接口函数*/static int rtc_open(st

18、ruct device *dev)/*这里主要的目的是从系统平台设备中获取RTC设备类的数据,和RTC探测函数rtc_probe中 的platform_set_drvdata(pdev, rtc)的操作刚好相反。这些都定义在platform_device.h中*/struct platform_device *pdev = to_platform_device(dev);struct rtc_device *rtc_dev = platform_get_drvdata(pdev);/*申请RTC报警中断服务,中断号rtc_alarmno在RTC探测函数rtc_probe中已经获取得, 这里使用

19、的是快速中断:IRQF_DISABLED。中断服务程序为:rtc_alarmirq,将RTC设备类rtc_dev做参数传递过去了*/ret = request_irq(rtc_alarmno, rtc_alarmirq, IRQF_DISABLED, my2440-rtc alarm, rtc_dev);if (ret) dev_err(dev, IRQ%d error %dn, rtc_alarmno, ret);/*同上面一样,这里申请的是RTC的TICK节拍时间中断服务,服务程序是:rtc_tickirq*/ret = request_irq(rtc_tickno, rtc_tickir

20、q, IRQF_DISABLED, my2440-rtc tick, rtc_tickno, ret);goto tick_err;tick_err:/*错误处理,注意出现错误后也要释放掉已经申请成功的中断*/free_irq(rtc_alarmno, rtc_dev);/*RTC报警中断服务程序*/static irqreturn_t rtc_alarmirq(int irq, void *argv)struct rtc_device *rdev = argv; /*接收申请中断时传递过来的rtc_dev参数*/*当报警中断到来的时候,去设定RTC中报警的相关信息,具体设定的方法,RTC核心 部分已经在rtc_update_irq接口函数中实现,函数定义实现在interface.c中*/rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);return IRQ_HANDLED;/*RTC的TICK节拍时间中断服务*/static irqreturn_t rtc_tickirq(int irq, void *argv)/*节拍时间中断到来的时候,去设定RTC中节拍时间的相关信息,具体设定的方法,RTC核心rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);return IRQ_HA

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1