基于Linux操作系统下RTC驱动开发文档格式.docx
《基于Linux操作系统下RTC驱动开发文档格式.docx》由会员分享,可在线阅读,更多相关《基于Linux操作系统下RTC驱动开发文档格式.docx(44页珍藏版)》请在冰豆网上搜索。
7.1设计思路16
7.2RTC程序实现16
7.2.1RTC基本数据结构16
7.2.2注册字符设备16
7.2.3定义操作函数17
7.2.4函数声明18
7.3编译生成.ko文件18
7.4实际运行及结果18
第8章结论20
谢辞21
参考文献22
附录ARTC驱动程序23
附录BMakefile文件41
附录C应用层测试程序41
摘要:
论文主要研究了Linux系统下的RTC芯片驱动架构,并设计了一个基于Tiny210开发板的RTC字符设备驱动。
首先对Linux体系进行了简单介绍,分析了Linux系统的应用和特性,并对现有平台Tiny210开发板进行了简单分析。
在对实际项目RTC驱动开发的分析设计的基础上,采用了以动态模块加载方式的字符设备驱动模型。
在对RTC芯片各个模块的简单介绍中快速构建和开发了一个该芯片的驱动模型,实现了对硬件时间的读写、闹钟的设置功能。
减少了开发的复杂性,缩短了开发时间,且具有很强的可扩展、可移植性。
关键词:
Linux操作系统;
Tiny210开发板;
字符设备驱动;
RTC芯片
DriverDevelopmentofRealTimerClock(RTC)BasedonLinux
Abstract:
Inthisthesis,theRTCchipdriverunderLinuxsystemarchitectureanddesignofadevelopmentboardbasedTiny210RTCcharacterdevicedrivers.First,abriefintroductionLinuxsystemtoanalyzetheapplicationandfeaturesofLinuxsystems,andexistingplatformsTiny210developmentboardforasimpleanalysis.OnthebasisoftheactualprojectRTC-drivendevelopmentofanalysisanddesign,usingadynamicmoduleloadingcharacterdevicedrivermodel.QuicklybuildinRTCchipforeachmoduleinabriefanddevelopamodelofthechipdriver,therealizationofhardwaretimetoreadandwrite,alarmsettingfunction.Reducingthecomplexityofdevelopmentandshortenthedevelopmenttime,andhasastrongscalability,portability.
Keywords:
Linuxoperatingsystem;
Tiny210developmentboard;
Characterdevicedriver;
RTCchip
第1章Linux概述
1.1Linux操作系统的诞生和发行版
1.1.1Linux系统的诞生
1981年IBM推出了微型计算机IBMPC。
在它推出的前10年内,MS-DOS操作系统主宰了整个计算机操作系统界。
而在当时,计算机硬件的价格在不断下跌,但软件仍处于高位。
苹果的操作系统MacOS的是无疑是最好的性能,但价格高,没有人可以轻易接近。
到1991年,随着GNU计划开发出来了一些工具,以及GNUC编译器的发布。
甚至MINIX也因为版权开始需要购买才能获得源代码。
在GNUHURD操作系统的开发工作却不是能在几年内完成的。
对于莱纳斯来说,已经等不及了。
起初,他只是为了学习386架构的编程技术,但随后的Linux开发过程已经彻底改变了他的主意。
在1991年初,莱纳斯在学习MINIX的操作系统的时候产生了开发一个新的属于自己的理想中的操作系统的想法。
最早与Linux(当然此时还不叫Linux这个名称)相关的新闻是莱纳斯在1991年7月3号的comp.os.minix上发布的消息。
而在莱纳斯8月25日发布的消息中,他第一次向外界透露出有开发免费的操作系统的意向,可是它并不会象GNU那种现在已经在行业中成型的系统那样专业,而代码量不会很大[1]。
直到1991年的10月5日,莱纳斯在comp.os.minix新闻组上发布消息,正式向外宣布Linux内核系统的诞生(Freeminix-likekernelsourcesfor386-AT)。
这段消息就是直到今日都广为流传的被称为Linux的诞生宣言。
因此对Linux社区,及其所用用户来说,10月5日都是一个特殊的日子。
直到今天,包括现在的RedHat公司在内的很多公司都会在发布许多Linux的新版本时选择了这个日子。
Linux是一种源于UNIX的操作系统,虽然从严格意义上讲,Linux这个词实际上是指Linux内核,但实际上人们已经习惯了把整个基于Linux内核以及在此基础上的各种工具的操作系统统称为Linux。
1.1.2Linux发行版
通常来讲,一个Linux的发行版不仅仅是指Linux内核,还包括了使用Linux的软件的安装工具,以及各种工具软件,而在一些特定的版本中中也有一些特定软件,只不过现在都习惯于把它们统称为Linux发行版。
每一种发行版的开发都是针对着不同的目标,像是支持不同计算机结构,更强调实时应用,和专门面向嵌入式系统等。
主流的Linux发型版有Ubuntu,RedHat等等。
1.2Linux应用和特性
1.2.1Linux的应用
Linux的基本思想就是——万物皆文件,因此它拥有极高的灵活性和可移植性,再加上它的UNIX背景,使它Linux在服务器的操作系统方面具有广泛运用。
直到现在,Linux还是提供网站服务供应商最常使用的平台。
虽然因为新的编程语言的兴起,它的市场份额在不断减少,但在嵌入式行业,Linux基于其低廉成本与小体积依然是不可动摇的霸主,像在机顶盒、手机及移动装置等硬件平台上,Linux已经是不可或缺的[3]。
1.2.2Linux的特性
⑴完全兼容
因为Linux兼容了POSIX1.0标准,所以一些常见的Windows的程序完全可以在Linux上无障碍运行,这也为用户从Windows转到Linux提供了方便。
因为现在Windows的巨大影响力,许多用户在使用Linux前,都会因为以前Windows的使用习惯而担心能否适应新的环境,而这一点就使他们不在顾虑。
⑵完全免费,发展迅速
Linux是一款完全免费的操作系统。
因为Linux社区的存在,所有的Linux用户都可以轻易的得到当前任意版本的Linux的源代码,并按照自己的意愿来修改它。
正是由于这一点,每时每刻,每一次的技术进步,每一种新平台面世,都有来自世界各地的精英都参与了Linux的更新和实现,无数的灵感跟不断进步的技术与编程思想,让Linux有了无穷的可能性,并在无数程序员的努力下不断壮大。
⑶多用户、多任务
正如当今世界发展的主流那样,Linux也支持多用户。
这保证了各用户的相对独立,之间互不影响,都对于自己的文件设备有自己的权利。
而多任务则是现在各种智能设备的主要特点,为了节省运行时间和解放更多的系统资源,实现了多进程的并行执行,Linux操作系统就是其中的典范。
⑷良好的界面
因为现在Windows系统的强烈影响,Linux同时具有可以通过键盘输入相应的指令来进行操作的字符界面和类似Windows图形界面的X-Window系统提供的图形界面。
后者使用户可以类似于Windows操作系统使用鼠标对其进行操作,而不会因为转换了操作系统感到不适应。
⑸丰富的网络功能
Unix最大的优势就是其强大的网络功能,而从Unix衍生出来的Linux系统也继承了它在网络功能上的优势。
Linux的网络功能和其内核紧密相连,在这方面它要比其他操作系统更有优势。
⑹可靠的安全、稳定性能
Linux采取了许多安全技术措施为内部信息安全提供了保障。
而且Linux的极高的稳定性使它在对要应用到网络服务器这类有较高稳定性要求的服务上有非常高的适应性。
⑺支持多种平台
Linux作为一种嵌入式操作系统,在各种移动装置上应用广泛。
Linux因为其开源的特性使它基本可以在市场上绝大部分的硬件平台上运行,这也使它精简体积小的内核可以方便地移植多种嵌入式处理器上。
第2章Tiny210开发板
2.1Tiny210简介
Tiny210是一款高性能的CortexA8核心板,它由广州友善之臂设计、生产和发行销售。
它采用三星S5PV210作为主处理器,运行主频可高达1GHz。
S5PV210内部集成了PowerVRSGX540高性能图形引擎,支持3D图形流畅运行,并可流畅播放1080P大尺寸视频[4]。
Tiny210主要采用了2.0mm间距的双排针,引出CPU大部分常用功能引脚,并力求和Tiny6410核心板三排引脚兼容(P1,P2,CON2)[5]。
2.2Tiny210硬件配置
如图2-1:
2.3软件支持
⑴Superboot-210
⑵Android2.3+Linux-3.0.8
⑶Android4.0
⑷WindowsCE6
第3章移植前准备
3.1软件平台的搭建
3.1.1虚拟机的安装
在有了硬件平台的支持下(Tiny210开发板)开始进行软件平台的搭建。
在pc机上安装一个虚拟机,本文选用的虚拟机是VMwareWorkstation。
虚拟机其实就是在主机中占用一块内存在主机的硬件平台上搭建一个类似主机的运行环境,在VMware中,你可以在一个以主机的分割的内存为基础的窗口中加载一台虚拟机,运行自己的操作系统和应用程序,而不影响主机任何操作。
3.1.2RedHatLinux的安装
在安装了VmwareWorkstation的条件下,创建一个虚拟机给它分配20G的磁盘大小。
512M的内存空间。
然后从网上下载RedHatLinux操作系统安装包iso文件,我下载的是RedHatLinux-5的iso文件,该版本的Linux内核时3.0的,相对来说是版本比较高的内核。
在获得RedHat的iso文件后,在创建的虚拟机中安装该Linux操作系统。
3.1.3软件包和源码包的准备和下载
需要的软件有交叉编译器arm-Linux-gcc,我选用的交叉编译器为Tiny210的开发自带的交叉编译器,该编译器是4.0版本以上的,正是由于我即将下载内核源码版本比较高,因此我们选用的交叉编译器的版本也是相对来说比较高的。
从www.kernel.org网站下载Linux的内核源代码linux-3.0.8.tar.gzRTC。
BootLoader是在硬件平台运行之前完成对硬件的初始化病唤醒操作系统的程序。
就是通过BootLoader来实现初始化硬件设备,从而给操作系统提供了一个合适的软硬件环境,并为调用它做好准备。
我选择的BootLoader是U_boot[6]。
第4章Linux内核
现在自己的当前目录,即~目录下,解压自己的内核源代码:
tarxvzflinux-3.0.8.tgz
解压Linux内核源码包,在当前目录下生成一相应的文件夹linux-3.0.8,这就是该内核的所有实现代码。
Linux的内核的目录包含很多个文件夹,分别用于实现不同的功能(如图4-1)[7]。
(假设相对于Linux-3.0.8):
图4-1Linux根目录
其中有几个比较重要的需要着重了解:
⑴/drivers驱动目录,该目录是所有被加载到内核的设备驱动的程序。
其中又把设备驱动进一步划分成几类,如字符设备驱动,块设备驱动等。
⑵/include该目录包括编译核心所需要的大部分头文件,也是Linux下程序编译的查找默认路径。
⑶/net该目录里不用说就是核心的网络层代码。
⑷/init该目录中包含内核的所有硬件初始化代码,这是内核所有工作的起点,像是main.c和Version.c这两个C语言程序的编译入口文件就在其中,同时也是是所有进程的最初父进程。
⑸/kernel该内核管理的核心代码放在这里,也就是通常所说的内核的具体实现,一般除了内核裁剪都不需要对它进行操作。
⑹/documentation该目录下是对每个目录作用的具体说明的文档以及一些功能的实例,就相当于产品说明书。
⑺/ipc该目录包含了核心进程间的通信代码,是Linux多任务特性具体实现。
⑻/lib该目录是编译默认路径,包含了内核绝大部分的库文件与代码。
⑼/modules该目录存放了已建好的、可动态加载的模块,裁剪内核的主要工作目标。
第5章RTC芯片
5.1RTC芯片简述
RTC(realtimeclock)实时时钟,顾名思义,拥有真实时间的时钟,其实它的主要作用就是在操作系统没有工作的时候自主维护时间表,并在需要的时候给操作系统提供系统时间。
开发板的时间系统可以分成两种,分别是系统时间和硬件时间。
硬件时间指的就是RTC芯片自主维护的时间,因为RTC芯片是电池供电的,所以在硬件平台掉电后时间表不会丢失。
Linux内核就把RTC芯片当作“离线”的时间与日期维护器。
当Linux内核启动时,都要通过RTC来进行初始化,从RTC中读取时间保存到系统中,得到系统时间。
而在运行期间,内核以软件的形式维护系统的当前时间与日期,并在关机或必要的时候将时间回写RTC芯片,由它自主维护。
另外如果RTC拥有了IRQ中断并且可以定时,那么RTC还可以作为一个闹钟用来在内核睡眠时唤醒内核。
Linux有两种RTC驱动的接口,一个是老的接口,专门用在PC机上的。
另外一钟新接口是基于Linux设备驱动程序的。
而后者创建了一个RTC驱动模型,并注册到RTC核心中,把所有工作交由RTC芯片完成。
5.2I2C总线简介
I2C总线是一种由Philips公司开发的两线式串行总线标准,用于链接微控制器及其外围设备。
I2C有100K和400K两种工作速率,它支持多机通讯和多主控模块设计,并且每个电路模块都有唯一的地址,还允许每个在I2C总线上的期间都可以使用独立的电源。
本文就是介绍基于I2C总线的Linux字符设备驱动。
I2C由数据线(SDA)和时钟线(SCL)构成的同步串行总线,可发送和接受数据,在处理器与控制芯片之间、芯片与芯片之间进行双向传送[8]。
I2C总线在传送数据过程中共有三种类型信号,它们分别是开始信号、结束信号和应答信号[9]。
第6章字符设备驱动相关知识
6.1模块机制
Linux提供了一种被称为模块(Module)的机制提供了对许多模块支持,设备驱动每个模块由不同代码组成,实现不同功能[10](所有的模块在一起才是一个可执行程序)。
insmod将模块动态加载到正在运行内核;
rmmod程序移除模块;
Linux内核模块的程序结构:
⑴module_init()——加载模块函数(必须)
使用insmod命令加载模块时,内核就会执行该模块的加载函数,也就是说这就是整个模块函数的入口,就是通过它来完成模块的初始化相关工作。
⑵module_exit()——卸载模块函数(必须)
当使用rmmod命令卸载某模块时,内核就会执行该这段函数,完成对模块的删除和空间的释放。
⑶MODULE_LICENSE()——模块许可证声明(必须)
这一段函数就是描述内核将要加载的模块的工作权限,如果在加载模块时不声明LICENSE,内核就会报警:
kerneltainted,意思就是内核被污染。
⑷module_param()——模块参数(可选)
这个函数括号内放置着模块内部声明的全局变量,对应着在加载模块时rommod命令后面跟着的参数,这些参数就会被传入模块内。
⑸EXPORT_SYMBOL()——模块导出符号(可选)
这个函数括号内也放置着数量不等参数,也就是符号(可以是函数或变量),而在这个模块结束之后,其他模块就可以通过这个符号使用本模块中这些到处的参数,变量或函数。
⑹其他一些声明MODULE_XXXXX()——模块声明(可选)
不同的声明对应着不同的功能选项,视实际情况而定。
模块加载函数:
staticint__initinitialization_rtc(void)
{
/*初始化代码*/
}
module_init(initialization_rtc);
模块卸载函数
staticvoid__exitcleanup_rtc(void)
{
/*释放资源*/
module_exit(cleanup_rtc);
6.2字符设备开发基本步骤
⑴向内核确定主该设备的主次设备号
⑵实现字符驱动程序:
填充file_operations结构体
实现模块加载函数用以注册字符设备
实现模块卸载函数完成模块的释放和删除
⑶创建设备文件节点
6.3主、次设备号[11]
⑴主设备号是内核识别一个设备的标识。
整数(占12bits),范围从0到4095,通常使用1到255。
⑵次设备号由内核使用,用于正确确定设备文件所指的设备。
整数(占20bits),范围从0到1048575,一般使用0到255。
⑶设备编号的内部表达
dev_t类型(32位,其中主设备号12位,次设备号20位):
是属于Linux内核编程的专有类型,用来保存设备编号。
从dev_t类型变量中获得主设备号和次设备号:
这是两个封装好的函数
MAJOR(dev_trtc);
//获得主设备号
MINOR(dev_trtc);
//获得次设备号
将主设备号和次设备号转换成dev_t类型:
这也是一个封装好的函数
dev_t=MKDEV(int,int);
⑷分配主设备号
手工分配主设备号的函数:
#include<
linux/fs.h>
//这是Linux内核中有关设备号的头文件
intregister_chrdev_region(dev_tnum,unsignedint,char*rtc);
这是自己手动把num分配给rtc作为主设备号。
⑸动态分配主设备号:
intalloc_chrdev_resion(dev_t*,unsignedint,unsignedint,char*rtc);
这是内核自动分配一个设备好给rtc。
⑹释放设备号
voidunregister_chrdev(dev_t,unsignedint);
在该设备号不再使用之后,释放并删除它,以节约内核资源。
6.4实现字符驱动程序
实现字符设备驱动,最重要的就是字符设备结构体cdev,以及驱动接口结构体--file_operations。
⑴cdev结构体
structcdev
{
structkobjectxxx;
/*内核内嵌的对象*/
structmodule*xxx;
/*所属模块*/
structfile_operations*xxx;
/*文件操作结构体*/
structlist_headxxx;
/*不常用*/
dev_txxx;
/*设备号*/
unsignedintxxx;
};
⑵file_operations结构体
字符驱动和内核的接口:
在内核代码中,./include/linux/fs.h下的代码实现,定义了字符驱动程序只要填充一个file_operations结构体并把它注册到内核中,内核就有了通过它操作这个字符设备的能力。
⑶file_operations的主要成员:
structmodule*xxx:
指向模块本身
open:
提供打开设备的函数接口;
release:
提供关闭设备的函数接口;
read:
实现从设备上读取数据的函数接口;
write:
实现向设备上写入数据的函数接口;
ioctl:
I/O控制函数;
llseek:
定位读写指针位置并把他们输出出来;
⑷ioctl函数
为设备驱动程序执行用户空间的“命令”提供了一个特有的接口用来设置或者读取设备的具体信息。
⑸cmd参数的定义
Linux内核对file_operations的ioctl()函数的cmd参数有特殊的定义:
如图6-1。
图6-1cmd参数
构造命令编号的宏:
_IO()给没有参数的命令;
_IOR()给从驱动中读数据的命令;
_IOW()给写入数据的命令;
_IOWR()用于双向传输。
⑹Ioctl函数模板
staticlongrtc_dev_ioctl(structfile*file,unsignedintcmd,unsignedlongarg)
...
switch(cmd){
caseRTC_EPOCH_SET:
Break;
caseRTC_SET_TIME:
...
break;
caseRTC_IRQP_SET:
caseRTC_PIE_ON:
}
图6-2字符设备驱动
第7章RTC驱动实现
7.1设计思路
Linux设备驱动属于内核的一部分,Linux内核的驱动模块可以用两种不同的方式加载和编译:
⑴通过内核裁剪,随同Linux的启动直接加载编译进Linux内核;
⑵把驱动程序编译成一个可加载和删除的动态模块,可以在需要时随时使用insmod命令加载,r