你了解linux RTC 驱动模型?.doc
《你了解linux RTC 驱动模型?.doc》由会员分享,可在线阅读,更多相关《你了解linux RTC 驱动模型?.doc(14页珍藏版)》请在三一办公上搜索。
1、你了解linux RTC 驱动模型?RTC(real time clock)实时时钟,主要作用是给Linux系统提供时间。RTC因为是电池供电的,所以掉电后时间不丢失。Linux内核把RTC用作“离线”的时间与日期维护器。当Linux内核启动时,它从RTC中读取时间与日期,作为基准值。在运行期间内核完全抛开RTC,以软件的形式维护系统的当前时间与日期,并在需要时将时间回写RTC芯片。另外如果RTC提供了IRQ中断并且可以定时,那么RTC还可以作为内核睡眠时唤醒内核的闹钟。应用程序可以用RTC提供的周期中断做一些周期的任务。linux有两种rtc驱动的接口,一个是老的接口,专门用在PC机上的。另
2、外一钟新接口是基于linux设备驱动程序的。这个新的接口创建了一个RTC驱动模型,实现了RTC的大部分基本功能。而底层驱动无须考虑一些功能的实现,只需将自己注册的RTC核心中,其他工作由RTC核心来完成。下面分析RTC新接口的驱动模型。一. 驱动模型结构 与RTC核心有关的文件有: /drivers/rtc/class.c 这个文件向linux设备模型核心注册了一个类RTC,然后向驱动程序提供了注册/注销接口 /drivers/rtc/rtc-dev.c 这个文件定义了基本的设备文件操作函数,如:open,read等 /drivers/rtc/interface.c 顾名思义,这个文件主要提供
3、了用户程序与RTC驱动的接口函数,用户程序一般通过ioctl与RTC驱动交互,这里定义了每个ioctl命令需要调用的函数 /drivers/rtc/rtc-sysfs.c 与sysfs有关 /drivers/rtc/rtc-proc.c 与proc文件系统有关 /include/linux/rtc.h 定义了与RTC有关的数据结构RTC驱动模型结构如下图:二. 基本数据结构 1. struct rtc_device 结构cppview plaincopystructrtc_devicestructdevicedev;structmodule*owner;intid;charnameRTC_DE
4、VICE_NAME_SIZE;conststructrtc_class_ops*ops;structmutexops_lock;structcdevchar_dev;unsignedlongflags;unsignedlongirq_data;spinlock_tirq_lock;wait_queue_head_tirq_queue;structfasync_struct*async_queue;structrtc_task*irq_task;spinlock_tirq_task_lock;intirq_freq;intmax_user_freq;#ifdefCONFIG_RTC_INTF_D
5、EV_UIE_EMULstructwork_structuie_task;structTImer_listuie_TImer;/*Thosefieldsareprotectedbyrtc-irq_lock*/unsignedintoldsecs;unsignedintuie_irq_acTIve:1;unsignedintstop_uie_polling:1;unsignedintuie_task_acTIve:1;unsignedintuie_timer_active:1;#endif;这个结构是RTC驱动程序的基本数据结构,但是他不像其他核心的基本结构一样,驱动程序以他为参数调用注册函数注
6、册到核心。这个结构是由注册函数返回给驱动程序的。 2. struct rtc_class_ops 结构cppview plaincopystructrtc_class_opsint(*open)(structdevice*);void(*release)(structdevice*);int(*ioctl)(structdevice*,unsignedint,unsignedlong);int(*read_time)(structdevice*,structrtc_time*);int(*set_time)(structdevice*,structrtc_time*);int(*read_al
7、arm)(structdevice*,structrtc_wkalrm*);int(*set_alarm)(structdevice*,structrtc_wkalrm*);int(*proc)(structdevice*,structseq_file*);int(*set_mmss)(structdevice*,unsignedlongsecs);int(*irq_set_state)(structdevice*,intenabled);int(*irq_set_freq)(structdevice*,intfreq);int(*read_callback)(structdevice*,in
8、tdata);int(*alarm_irq_enable)(structdevice*,unsignedintenabled);int(*update_irq_enable)(structdevice*,unsignedintenabled);这个结构是RTC驱动程序要实现的基本操作函数,注意这里的操作不是文件操作。驱动程序通过初始化这样一个结构,将自己实现的函数与RTC核心联系起来。这里面的大部分函数都要驱动程序来实现。而且这些函数都是操作底层硬件的,属于最底层的函数。 3. struct rtc_time 结构cppview plaincopystructrtc_timeinttm_sec
9、;inttm_min;inttm_hour;inttm_mday;inttm_mon;inttm_year;inttm_wday;inttm_yday;inttm_isdst;代表了时间与日期,从RTC设备读回的时间和日期就保存在这个结构体中三. class.c 1. 模块初始化函数:rtc_initcppview plaincopystaticint_initrtc_init(void)rtc_class=class_create(THIS_MODULE,rtc);if(IS_ERR(rtc_class)printk(KERN_ERR%s:couldntcreateclassn,_FILE_
10、);returnPTR_ERR(rtc_class);rtc_class-suspend=rtc_suspend;rtc_class-resume=rtc_resume;rtc_dev_init();rtc_sysfs_init(rtc_class);return0;rtc_init首先调用class_create创建了一个类-rtc。我们知道类是一个设备的高层视图,他抽象出了底层的实现细节。类的作用就是向用户空间提供设备的信息,驱动程序不需要直接处理类。然后初始化类结构的相应成员,rtc_suspend,rtc_resume这两个函数也是在class.c中实现的。接下来调用rtc_dev_i
11、nit(),这个函数为RTC设备动态分配设备号,保存在rtc_devt中。最后调用rtc_sysfs_init,初始化rtc_class的属性。 2. 为底层驱动提供接口:rtc_device_register,rtc_device_unregistercppview plaincopystructrtc_device*rtc_device_register(constchar*name,structdevice*dev,conststructrtc_class_ops*ops,structmodule*owner)structrtc_device*rtc;intid,err;if(idr_p
12、re_get(err=-ENOMEM;gotoexit;mutex_lock(err=idr_get_new(mutex_unlock(/*-(1)-*/if(errid=id;rtc-ops=ops;rtc-owner=owner;rtc-max_user_freq=64;rtc-dev.parent=dev;rtc-dev.class=rtc_class;rtc-dev.release=rtc_device_release;mutex_init(spin_lock_init(spin_lock_init(init_waitqueue_head(strlcpy(rtc-name,name,R
13、TC_DEVICE_NAME_SIZE);dev_set_name(/*-(2)-*/rtc_dev_prepare(rtc);err=device_register(if(err)gotoexit_kfree;/*-(3)-*/rtc_dev_add_device(rtc);rtc_sysfs_add_device(rtc);rtc_proc_add_device(rtc);dev_info(dev,rtccore:registered%sas%sn,rtc-name,dev_name(/*-(4)-*/returnrtc;exit_kfree:kfree(rtc);exit_idr:mut
14、ex_lock(idr_remove(mutex_unlock(exit:dev_err(dev,rtccore:unabletoregister%s,err=%dn,name,err);returnERR_PTR(err);(1):处理一个idr的结构,idr在linux内核中指的就是整数ID管理机制,从本质上来说,idr是一种将整数ID号和特定指针关联在一起的机制。这个机制最早是在2003年2月加入内核的,当时是作为POSIX定时器的一个补丁。现在,在内核的很多地方都可以找到idr的身影。详细实现请参照相关内核代码。这里从内核中获取一个idr结构,并与id相关联。 (2):分配了一个rtc
15、_device的结构-rtc,并且初始化了相关的成员:id, rtc_class_ops等等。 (3):首先调用rtc_dev_prepare(在rtc-dev.c中定义)。因为RTC设备本质来讲还是字符设备,所以这里初始化了字符设备相关的结构:设备号以及文件操作。然后调用device_register将设备注册到linux设备模型核心。这样在模块加载的时候,udev daemon就会自动为我们创建设备文件rtc(n)。 (4):先后调用rtc_dev_add_device,rtc_sysfs_add_device,rtc_proc_add_device三个函数。rtc_dev_add_dev
16、ice注册字符设备,rtc_sysfs_add_device只是为设备添加了一个闹钟属性,rtc_proc_add_device创建proc文件系统接口。四. rtc-dev.c rtc-dev.c 初始化了一个file_operations结构-rtc_dev_fops,并定义了这些操作函数。 1. rtc_dev_fops rtc基本的文件操作cppview plaincopystaticconststructfile_operationsrtc_dev_fops=.owner=THIS_MODULE,.llseek=no_llseek,.read=rtc_dev_read,.poll=r
17、tc_dev_poll,.unlocked_ioctl=rtc_dev_ioctl,.open=rtc_dev_open,.release=rtc_dev_release,.fasync=rtc_dev_fasync,;2. 函数的实现(以rtc_dev_read为例) cppview plaincopyrtc_dev_read(structfile*file,char_user*buf,size_tcount,loff_t*ppos)structrtc_device*rtc=file-private_data;DECLARE_WAITQUEUE(wait,current);unsignedl
18、ongdata;ssize_tret;if(count!=sizeof(unsignedint)return-EINVAL;add_wait_queue(do_set_current_state(TASK_INTERRUPTIBLE);spin_lock_irq(data=rtc-irq_data;rtc-irq_data=0;spin_unlock_irq(if(data!=0)ret=0;break;if(file-f_flagsret=-EAGAIN;break;if(signal_pending(current)ret=-ERESTARTSYS;break;schedule();whi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 你了解linux RTC 驱动模型? 了解 linux 驱动 模型

链接地址:https://www.31ppt.com/p-4927274.html