基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发(兰州理工

更新时间:2024-06-21 16:40:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发

兰州理工硕士论文 I目录

摘要............................................................... IAbstract........................................................... II插图索引.......................................................... III第1章绪论.........................................................1

1.1嵌入式系统意义.........................................................1 1.2嵌入式系统.............................................................2 1.2.1嵌入式系统简介...................................................2 1.2.2嵌入式系统国内外现状.............................................3 1.3 ARM9平台..............................................................4 1.4设备驱动..............................................................5 1.5本文主要工作...........................................................5 第2章实验平台硬件分析.............................................7 2.1平台总体结构分析.......................................................7 2.2处理器性能分析.........................................................8 2.3存储器电路分析........................................................10 2.4电源和复位电路分析....................................................11 2.5接口电路..............................................................11 2.5.1 USB接口........................................................11 2.5.2 LCD接口........................................................12 2.5.3网络接口电路....................................................12 2.6本章小结..............................................................13 第3章嵌入式Linux系统构建........................................14 3.1搭建交叉开发环境......................................................14 3.1.1交叉编译环境的搭建..............................................14 3.1.2交叉调试环境....................................................16 3.2 Uboot的移植..........................................................18

3.2.1 Nand Flash启动U-BOOT的基本原理................................20 3.2.2加入支持Nand Flash启动代码.....................................20 3.2.3 U-BOOT对Nand Flash命令的支持..................................21 3.3嵌入式Linux2.6.29内核移植............................................21 3.3.1 Linux内核文件结构..............................................21 3.3.2内核移植过程....................................................24 3.根文件系统的制作......................................................26 3..1建立根文件系统..................................................27 3..2制作YAFFS2文件系统.............................................28 3.本章小结..............................................................29 第4章设备驱动....................................................30 4.1设备驱动简介..........................................................30 4.2 LCD设备驱动设计......................................................31

4.2.1帧缓冲设备结构..................................................31 4..2帧缓冲驱动的编写................................................33 4.3 USB设备驱动设计......................................................34 4.3.1 USB的具体构成..................................................34 4.3.2 USB驱动程序结构分析............................................36 4.4网络驱动设计..........................................................44 4.4.1 DM9000结构分析.................................................44 4.4.2 Dm9000驱动移植过程.............................................44 4.4.3 Dm9000驱动简要分析.............................................46 4.5本章小结.............................................................48 总结与展望.........................................................491 工作总结................................................................492 展望...................................................................49 参考文献...........................................................50 致谢...............................................................53

附录A攻读硕士学位期间发表论文.....................................54

I摘要

随着各种处理器性能的不断提高以及价格的不断下降,带有操作系统的嵌入式系统因其体积小,可靠性高、功能强、灵活方便等诸多优点,已渗透到工业、农业、教育、国防、科研及日常生活等各个领域。而Linux系统因为开源、功能多样、性能稳定等特点成为了嵌入式系统的首选。而嵌入式设备种类繁多,性能各异的特点又增加了产品中关于驱动设计的复杂性。因此在嵌入式系统的开发过程中驱动设计的地位举足轻重。本文介绍了Linux的发展情况和体系结构,并在此基础上阐述了Linux作为嵌入式系统开发的优势和不足。在具体实践的过程中结合S3C2440处理器和Mini2440实验平台,进行了嵌入式Linux的移植和驱动设备的开发。在嵌入式Linux的移植过程中:首先结合Linux系统和实验平台的硬件要求搭建了交叉开发环境,在此过程中解决了选用软件之间版本不兼容的问题。其次通过对开源的Uboot作出一定的修改,生成了合适的系统引导程序,用于完成了Linux系统移植的前序步骤,这里主要解决了NandFlash在启动过程中的数据搬移问题。再次进行了Linux内核的裁剪和移植,并在移植成功的前提下进行了USB设备、LCD设备、网络设备的驱动设计。针对常见的嵌入式设备,主要遇到了以下的问题。诸如:(1)在USB设备中嵌入式Linux系统的发展现状、体系结构特点(2)实验平台的硬件特性简介,包括USB电路、LCD电路结构等等(3)嵌入式Linux的开发。这包括交叉编译环境搭建的过程、Uboot的结构和移植过程、Linux内核的分析以及相关的裁剪移植、yaffs根文件系统的制作(4)介绍了常用设备的驱动的结构和实现过程。包括USB设备、LCD设备以及网络设备经过以上的工作,本文为嵌入式Linux系统和设备驱动的开发给出了较为完整的流程,对其他开发者来说有一定的参考。

关键词:嵌入式Linux系统;交叉编译;Uboot;Linux内核移植;

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发IIAbstractWith continuous improving performance and declining prices of processors,because of small size,high reliability,strong function,flexibility,and many otheradvantages,the embedded systems has been widely used into industry,agriculture,education,national defense,scientific research,daily life and

other fields.The Linuxsystem has so many adventages such as the open source,versatile,stable performance,so it becomes the first choice of the embedded systems.The wide types and differentperformances of embedded devices add to the complexity of the design on the drive.Therefore,the development of device driver holds an important position in theembedded system design.This article describes the development and architecture of Linux,and representsadvantages and disadvantages of Linux as an embedded system.In practice,combiningS3C2440 processor and Mini2440 experimental platform,the embedded Linux is portedand device drivers are developed.In the process of embedded Linux porting,firstlybuild cross development environment based on embedded Linux system andexperimental platform,and solve the problem of compatible versions among softwares.Secondly,generate the appropriate system boot procedures by revising open-sourceUboot to complete the pre-order steps of Linux system porting,which mainly solve dataporting problems in the process of NandFlash starting.Finally,after Linux kernelcutting and transplantation,design USB devices,LCD devices and network devicesbefore successful porting.This paper is structured into four parts:(1)The developing status and structures of embedded Linux system in USB devices.(2)Introduce hardware features of the USB circuit,LCD circuit,etc.(3)Develop embedded Linux.This includes the process of cross-compile compilingenvironment,Uboot structure and porting process,Linux kernel analysis and relatedcutting port,the production of yaffs root file system.(4)Describe driver architecture and implementation process of the common device,including USB devices,LCD devices and network devices.After the above work,this article not only offers a complete process for embeddedLinux system design and device driver development,but also provides a reference forother developers.Keywords:Embedded systems;Cross compiler;Uboot;Linux kernel porting;

兰州理工硕士论文 III插图索引图

2.1开发板电路结构...............................................................................................................7图 2.2结构框图..........................................................................................................................8图 2.3内存结构图.......................................................................................................................9图 2.4 SDRAM结构图..............................................................................................................10图 2.5 NandFlash电路图...........................................................................................................10图 2.6电源电路........................................................................................................................11图 2.7复位电路........................................................................................................................11图 2.8 USB电路图.....................................................................................................................12图 2.9 LCD电路图.....................................................................................................................12图2.10网络芯片图...................................................................................................................13图 3.1交叉编译图.....................................................................................................................15图 3.2调试原理图.....................................................................................................................16图 3.3 minicom配置图..............................................................................................................17图 3.4硬件调试图.....................................................................................................................18图 3.5 Uboot结构图...................................................................................................................19图 3.6启动原理图......................................................................................................................20图 3.7 Uboot的烧写...................................................................................................................21图 3.8内核结构图.....................................................................................................................23图 3.9内核裁剪图.....................................................................................................................26图

3.10文件系统配置图...........................................................................................................29图 4.1驱动原理图....................................................................................................................31图 4.2 USB结构图...................................................................................................................35图 4.3驱动流程图....................................................................................................................37图 4.4 USB挂载图....................................................................................................................43图 4.5 DM9000结构框图........................................................................................................44图 4.6目标板IP配置图...........................................................................................................46图 4.7网络连接测试图.............................................................................................................46

1第1章绪论

1.1嵌入式系统意义

在信息技术和网络技术日新月异的今天,嵌入式系统因结构小巧、稳定性高、灵活方便等诸多优点,在工农业、国防科研及日常生活得到了广泛的应用,并对各个行业的技术升级、产品性能提升、生产效率提高起到了重要的推动作用[1]。嵌入式产品有着广泛的应用,包括了我们周围诸如机顶盒、个人数字助理、移动及多媒体设备、医疗仪器等多种设备。同时,Linux操作系统因其开放源代码、易于开发、功能强大、稳定、成本低等优势迅速跻身于主流嵌入式开发平台。在计算机发展过程中,UNIX操作系统的出现是一个重要的里程碑,曾免费供美国及一些西方国家的大学和科研机构使用,并提供源码。后来Linux Torbald在Unix的基础上进行了该进,创造了一个以其名字命名的操作系统-Linux,与商业操作系统不同是,Linux是一个开源免费的操作系统。对于Linux在嵌入式系统中的应用,都是根据各种系统的多样性,对内核进行一定的裁剪和修改,而不是生搬硬套。具体包括以下方面:(1)在Linux的移植过程中,特别是移植到具体的处理器中时,因为不同的处理器有着不用的指令系统和结构系统,所以需要做出相应的修改和补充。(2)在满足系统性能的前提下,为了压缩内核的大小以及提高系统的启动速度,需要对Linux内核进行删减和裁剪。(3)嵌入式系统因根据用户的需求定制,导致了外部设备不能像一般设备那样通用,而这就需要有针对性的开发一些特别的设备驱动程序,以满足不同外设的需要。(4)不同的应用领域导致了对于实时性要求的高低不同,而这就需要采取不同的对策,解决诸如优先级调度、时钟精度、优先级反转等各种复杂的问题以实现相应的实时性要求[2-4]。模块化是Linux内核的特色,内核的许多功能和结构都可以按照需求加以取舍和裁剪,有些结构根据系统启动加载的需求,比如部分模块在启动时需要较长,并且又不是频繁需要使用。这个时候就可以将其独立编译生成动态安装的模块,在系统需要的时候再安装运行。嵌入式Linux经修改和扩充可以保留这个特点,当嵌入式系统的需求改变的时候,还可以根据这个修补过的版本,再次进行裁剪和编译以生成许多不同的可执行镜像,满足嵌入式系统不同的功能需求,更好更快的完成项目要求。

21.2嵌入式系统

1.2.1嵌入式系统简介

嵌入式系统一般定义为:以应用为中心,以计算机技术为基础、软硬件可裁剪、适应于应用系统,对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统[5]。以嵌入式Linux系统为例,一般具有一下的应用特征。内核体积较小:在Linux系统中性能齐全的内核大概占用1MB的内存空间,而包含虚拟内存和内核核心功能的微内核,在奔腾处理中只占用大概100KB的空间。而一个包含网络以及可以在386处理器执行简单实用程序的Linux系统,仅仅只需要大概500KB的内存。同时具有上述功能的微内核的结构也并不复杂,内核的高

层是以模块化的组织形式存在的,这些包括网络以及文件系统等等,而驱动程序和其他部件作为微内核的底层在运行时可作为动态模块临时编译或者添加到内核中去。这可以根据嵌入式系统定制需求的多样性,提供高度模块化的构造方法。可靠性和稳定性:嵌入式系统要求很高的可靠性和稳定性,而Linux在通用操作系统领域中的优异表现已证明其性能是绝对可靠的,因此选用Linux作为嵌入式操作系统,对于提升系统整体可靠性和稳定性来说是很有保障性的。多任务和实时性:多任务性和实时性是嵌入式系统的特色,而这方面Linux也具有一定的优势,其在多任务方面性能优良。Linux进程有三种调度策略,即非实时、实时FIFO和实时基于优先权轮询法。虽然实时性不出众,但一般的要求基本都能达到。可裁剪性和定制性:这是嵌入式操作系统一般要求,虽然Linux是单内核结构,但它具有特色鲜明的模块机制。模块不仅具有可裁剪性,还可以在系统中动态的加载和卸载,这使得模块化成为了Linux的特征之一。除了模块化机制以外,Linux内核可以根据需求在源码级别上进行配置和选择。因此Linux可以根据实际的情况,经过一定的裁剪和配置以满足嵌入式系统的实际应用需求。完善的网络功能:嵌入式系统要求具有完善的网络功能,而Linux自身就是一个优秀的网络操作系统,几乎所有的网络协议和网络接口都已经定制在Linux中,而且具有很高的执行效率和吞吐量。硬件平台的普适性:Linux具有广泛的硬件支持特性,不仅涵盖了RISC和CISC,还包括了32位和64位等多种处理器。Linux常用于的微处理器是Intel x86芯片家族,但它同样能在Motorola公司的68KB系列CPU和IBM、Apple、PowerPC,以及Strong ARM等处理器系统中运行,这意味着嵌入式Linux将具有更广泛的应用背景。Linux支持大量周边硬件设备,其上有丰富的驱动程序,支持各种非主流硬件设备和最新的硬件技术,而且当前许多厂商也直接提供Linux上的驱动,并且全球的Linux爱好者也编写了大量的驱动程序,使Linux更适合于各种不同的硬件平台[6-8]。

目前,嵌入式Linux系统开发如雨后春笋,已经开辟了很大的市场空间,除了一些耳熟能详Linux公司,像RedHat、VALinux等已经从事了多年的嵌入式Linux开发之外,不少新公司(像Lineo、Time Sys等)和大公司(如IBM、SGI、Intel等),以及一些以前针对专用嵌入式系统的公司也在从事嵌入式Linux的应用和开发。嵌入式Linux主要可以分为两类(1)在不删减Linux完整功能的前提下,针对实际应用中对嵌入式系统体积的严格要求,使其尽量的减小。如μClinux。(2)在一些对于实时性要求较高的控制场合,特别是硬实时系统中有针对性的将Linux开发成实时系统。如RT Linux,Hard Hat Linux等[9]。1.2.2嵌入式系统国内外现状Lineo公司的代表作μClinux已经成为开源嵌入式Linux的一个经典。在Linux内核还是2.0的时候,μClinux就产生了。其主要在不具有内存管理单元(MMU)的处理器上使用。根据嵌入式系统对内核体积的要求,μClinux裁剪了大量Linux代码,尽管如此其仍然具有Linux操作系统的出色功能,具有代表性的是稳定、可靠的网络功能和完善的文件系统。RT Linux(Real Time Linux)由Victor Yodaiken和Michael Baranov开发出的全球范围内较早的实时Linux系统。现在RT Linux应用特别广泛,这其中既包括宇航工业中的数据采集、遥感测控等高精端应用,也包括电影特效处理等等RT Linux保留了Linux内核的绝大部分内容,同时利用内核的模块化机制,采用模块导入和独立内核管理实时任务的方案。其工作流程是这样的:在启动了Linux内核之后,内核本身转化为一个优先级最低的空闲任务,当有实时任务要求处理时,这个实时任务的优先级是高于内核的,所以能被系统快速的响应,即在实时任务存在的基础上响应实时任务。RT Linux将内核机制分为非实时机制以及实时机制两个部分,这有利于每个机制独立优化,并且这样的内核结构简单而且体积小巧。Monta Vista Linux公司是全球知名的嵌入式Linux系统解决方案提供商之一,其提供的方案是针对体积小、可靠性高、响应快以及非台式Linux能解决的问题。Monta Vista Linux公司的Hard Hat Linux(2.1版本已更名为MontaVista Linux)是专门针对嵌入的系统的。MontaVista Linux可以为系统启动和运行环境制定的合适的硬件配置,这样可以获得高效的性能和可接

受的体积。与国外相比,国内从事嵌入式技术起步比较晚,没有自己生产嵌入式芯片的能

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发力,在嵌入式操作系统方面有自主知识产权的产品也很少,在这方面,源代码开放的Linux已经逐渐成为国内公司与国外厂商争一日之长的有力武器。国内许多公司也在做嵌入式Linux的开发,有以下几种产品:PocketIX OS:PocketIX OS是由广州博利思公司推出的嵌入式Linux产品。这个系统在2.2.13内核的基础上进行了改善,保留了x窗口、浏览器以及文件管理和文字处理功能,并且具有体积小巧、运行速度快的特点。该系统在网络终端、Pocket PC、个人数字助理、电视机机顶盒、车载导航、智能家电等方面有不错的表现。CC-Linux:CC-Linux是由中科院软件所、国防科技大学、西北工业大学等和几家具有雄厚研发能力的公司共同完成。包括嵌入式Linux内核、嵌入式图形环境CSGUI、嵌入式配置工具和开发环境SDK/ETK、系统应用软件等子系统。CC-Linux为高效可用的面向Internet应用设备的嵌入式Linux操作系统,目标产品为机顶盒和PDA[14-18]。CC-Linux对通用的Linux进行了合理的裁剪,实现了支持多种文件系统、软实时、电源管理、多平台和多线程支持等特点,这使得该系统实际上已经成为中国嵌入式操作系统的经典之作。此外,在市场上还有红旗嵌入式Linux、蓝点点嵌入式Linux系统、网虎科技推出的COVENTIVE等。“863计划”重点支持项目中也有使用Linux作为嵌入式操作系统开发的方向。它们所具备的共同特点如下:(1)精简的内核,应用的处理器广泛。这其中包括:x86、StrongARM、ARM、MIPS、Power PC等。(2)提供完善的图形用户接口和图形化界面(3)提供嵌入式浏览器、多媒体播放器、邮件管理、文本编辑软件等应用程序。(4)提供完整的开发工具和SDK,用户可以根据自身的需求,对其提供的开发版本进行一定的修改,以满足不同的需求。嵌入式Linux已经在消费电子设备中得到广泛应用,基于嵌入式Linux的手持设备和智能手机已经具有了很大的市场。1.3 ARM9平台正是因为Linux具有良好的硬件平台普适性,使得其可以方便的移植到ARM处理器上。ARM处理器核已经有6个系列产品:ARM7、ARM9、ARM9E、ARM10E、SecureCore及较新的ARM11系列。进一步的产品来自于合作伙伴,例如:IntelXscale微体系结构和StrongARM产品。ARM7、ARM9、ARM9E和ARM10E是个通用处理器系列。每个系列提供一套特定的性能来满足设计者对功耗、性能和体积的需求。ARM9系列微处理器包含ARM920T、ARM922T和ARM940T这3种类型内核,主要应用于无线设备、仪器仪表、车载设备、机顶盒、智能手机和数字摄影机等。目前市场上得到广泛应用的ARM处理器一般都是使用了ARM7和ARM9内核,后者性能比较突出,主要用于高端设备,而前者价格低廉在工业控制中得到较大的推广。ARM9核对ARM7核的功能进行了显著提高和增强。ARM9和ARM7一样不仅支持Thumb指令,并支持片上调试。而ARM9最主要的是将指令流水线由3级增加到5级。其实ARM9使用5级流水线也是受到StrongARM流水线的启发而设计的,并针对StrongARM的某些不足加以该进,从而获得更好的性能[19-20]。据LinuxDevices最新的嵌入式Linux市场分析预测报告,ARM处理器是使用最多的嵌入式开发架构。有30%的项目在使用ARM,而26%左右的项目在使用x86架构。可以预计,ARM处理器在未来几年的使用率将继续保持第一位。

1.4设备驱动设备驱动程序是进入Linux内核世界的大门,对整个系统的运行起着至关重要的作用。对嵌入式Linux设备驱动的研究,有助于深入理解嵌入式Linux内核代码。设备驱动程序在Linux内核中扮演着重要的角色,它们如同一个个独立的“黑盒子”,隐藏了设备具体的工作方式,而用户只需要根据已经定义好的内部编程接口即可以完成对特定的硬件的操作。Linux所支持的每一款硬件,一定要有配套的驱动程序,否则它就无法在Linux系统下发挥功能。也就是说没有设备驱动程序,就不会有功能完整的运行系统。嵌入式系统设备的

多样性导致了不同的系统需要开发者自己制定设备驱动程序,来配套操作相应的硬件设备,这就决定了驱动开发占据了嵌入式系统开发的主要地位。而免费开源的Linux在嵌入式领域的发展为我国发展自己的嵌入式操作系统,扭转软件市场的被动局面,提供了难得的机遇,也为振兴国内软件行业中找到了最佳突破口,使我国有机会迎头赶上国际的先进水平。因此嵌入式Linux设备驱动程序的开发和研究具有重要的社会和商业价值。1.5本文主要工作本课题根据嵌入式系统发展的情况以及实验室条件限制,选用了基于ARM920T核的S3C2440处理器,对嵌入式Linux的内核移植、驱动设计进行了研

第一章主要介绍了嵌入式系统的课题意义以及国内外Linux发展的研究现状。第二章主要介绍了实验平台的各种接口配置和硬件电路结构第三章介绍了嵌入式Linux的构建过程。首先介绍了交叉开发环境的搭建,本文未使用常用的交叉编译工具链,而是针对实验平台的特点选用设当的软、硬件搭建了相应的开发环境;其次介绍了Uboot引导程序的开发,针对目前Uboot的优缺点,改善了Uboot启动时对储存器的配置要求;再次就是在上面的基础上移植了Linux内核和制作了相应的文件系统。第四章介绍了设备驱动的开发,这主要包括LCD驱动、USB驱动以及网络设备驱动的设计。

兰州理工硕士论文7第2章实验平台硬件分析本平台使用的硬件系统是友善之臂的mini2440开发板,这是一款实用ARM9开发板,它采用Samsung S3C2440为微处理器,并采用稳定的CPU内核电源芯片和复位芯片来保证系统运行时的稳定性。其实物图如图所示:图2.1开发板电路结构2.1平台总体结构分析Mini2440提供了丰富的外部资源,足以支持一般的开发任务,图2-3是平台功能框图:

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发8S3C2440处理器时钟复位电路NandFlashLCD串口系统扩展接口按键及LED电源电路USB口网口JTAG口图2.2结构框图各部分功能分析如下:(1)Samsung S3C2440A处理器:其主频为400MHz,最高533Mhz(2)SDRAM内存:64M SDRAM包括32bit数据总线以及高达100MH频率z时钟,其主要用于系统调试和程序的运行(3)FLASH存储:128M Nand Flash以及2M Nor Flash,前者掉电非易失,后者可以直接运行简易的测试代码。该部分主要用于存储系统引导程序、操作系统、文件系统以及在系统掉电后需要保存的用户数据。(4)时钟和复位电路S3C2440通过外部12MHz的时钟输入,经过内部锁相环可以倍频到400MHz,而复位电路可以完成系统上电复位以及运行时的用户手动复位。(5)LCD显示板上集成4线电阻式触摸屏接口,可以直接连接四线电阻触摸屏,支持多种屏幕。(6)以太网接口采用DM9000网卡芯片,它可以自适应10/100M网络,RJ45连接头内部已经包含了耦合线圈,因此不必另接网络变压器。(7)USB接口开发板具有两种USB接口,一个是USB Host,它和普通PC的USB接口是一样的,另外一种是USB Slave,一般用于下载程序到目标板。(8)JTAG接口用于系统调试,借助于边界扫描技术的方式对芯片进行内部访问,可对系统进行调试和编程。2.2处理器性能分析S3C2440是三星公司推出的16/32位RISC微处理器,针对手持设备和一般应用市场中对低功耗、高性价比的需求,提出的解决方案。其采用了ARM920T的内核,0.13um的CMOS标准宏单元和存储器单元,并集成了以下片上功能:

兰州理工硕士论文9(1)1.2V内核供电,1.8V/2.5V/3.3V存储器供电,3.3V外部I/O供电,具备16KB的I-Cashe和16KBDCashe/MMU微处理器(2)LCD控制器(最大支持4K色STN和256K色TFT)提供1通道LCD专用DMA(3)4通道DMA并有外部请求引脚、3

通道UART、2通道SPI、1通道IIC-BUS接口(4)USB主机/设备、4通道PWM定时器和1通道内部定时器/看门狗定时器、8通道10比特ADC和触摸屏接口[21-23]除了这些以外,在系统管理器上也提供了灵活多变的特性,这些特性包括:(1)支持大/小端方式、高速总线模式和异步总线模式(2)共有8个内存块,每块空间最大为128M,使用时BANK0-6采用固定BANK起始寻址,BANK7具有可编程的BANK起始地址和大小。其内部配置的地址空间分配见图2-3图2.3内存结构图(3)支持MMU,MMU是指内存管理单元,它使用分页式管理机制。虚拟地址空间划分成称为页的单位,而相应的物理地址空间也被进行划分,单位是页桢。页和页桢的大小必须相同,页的大小定义为4KB或者8KB,当应用程序调用内存时,首先通过MMU,找到虚拟地址对应的物理地址,如果物理地址是在外部设备比如磁盘,则首先把物理地址对应的数据或者程序代码读入到内存中,并且更新PMM以反映这个变化。只有通过MMU,才能保护内存,并且使得系统不会因为进程的异常,而导致系统处于不稳定的状态。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发102.3存储器电路分析存储器分为两个部分:SDRAM存储系统和Flash存储系统。其中SDRAM是易失性存储器,用于程序运行时提供数据空间,当系统上电或者手动复位的时候,MCU从0X0处执行系统初始化代码,比如建立系统和用户堆栈,存放代码运行时的数据等等。它使用了两片外接的32M bytes总共64M bytes的SDRAM芯片(型号为:HY57V561620FTP),它们并接在一起形成32-bit的总线数据宽度,这样可以增加访问的速度;因为是并接,故它们都使用了nGCS6作为片选,其物理起始地址为0x30000000,如图2-4所示:A023A124A225A326A429A530A631A732A833A934A1022A1135BA121nWE16nSRAS18nSCS19nSCAS17LDQM15UDQM39SCKE37SCLK38VDD227VDD114DQ02DQ14DQ25DQ37DQ48DQ510DQ611DQ713DQ842DQ944DQ1045DQ1147DQ1248DQ1350DQ1451DQ1553VDDQ03VSS254VSS141VSS028VSSQ352VSSQ246VSSQ112VSSQ06BA020VDD01VDDQ349VDDQ243VDDQ19A1236U6HY57V561620(32MB)/或其他兼容型号VDD33VLnWBE0LnWBE1LSCKELSCLK0LnSCS0LnSRASLnSCASLnWELADDR2LADDR3LADDR4LADDR5LADDR6LADDR7LADDR8LADDR9LADDR10LADDR11LADDR12LADDR13LADDR14LADDR24LADDR25LDATA0LDATA1LDATA2LDATA3LDATA4LDATA5LDATA6LDATA7LDATA8LDATA9LDATA10LDATA11LDATA12LDATA13LDATA14LDATA15图2.4 SDRAM结构图本实验平台还使用非易失的Flash存储器,即Nand Flash,型号为K9F1G08,大小为128M,其具有掉电非易失的存储特点,适用于存储编译好的系统内核。由于Nand Flash不具有地址线,它有专门的控制接口与CPU相连,数据总线为8-bit,其硬件电路结构如图2-5所示:VDD33VCLE16ALE17WE18WP19I/O029I/O130I/O231I/O332VSS13VCC12I/O441I/O542I/O643I/O744VCC37R/B7RE8CE9VSS36SE6U2

K9F1208LDATA0LDATA1LDATA2LDATA3LDATA4LDATA5LDATA6LDATA7nFWEnFREALEnFCECLERnBC100.1uFR610KVDD33V图2.5 NandFlash电路图

兰州理工硕士论文112.4电源和复位电路分析本平台的电源系统比较简单,直接使用外接的5V电源,通过降压芯片产生整个系统所需要的三种电压:3.3V、1.8V、1.25V(实测可能有偏差)。电路结构如图2-6所示:图2.6电源电路本开发板采用的复位芯片是MAX811,通过它来实现CPU所需要的低电平复位,其电路图如下所示:nRESETRSTSW-PB11223344U9MAX811R2470VDD33VC34104图2.7复位电路2.5接口电路2.5.1 USB接口USB总线是一种较新的串行总线标准,其在PC机和外部设备互联的速度较

快。USB总线具有性价比高、使用简单、支持热插拔、易扩展等特点,已广泛的应用于嵌入式系统中。在物理结构上,USB系统是一个星形结构,但在逻辑结构上每个USB逻辑设备都是直接与USB HOST相连进行数据传输的[24-25]。本平台有两种USB接口,包括是USB Host和USB Slave,前者可以像普通PC机上的USB接口一样接诸如USB摄像头、USB键盘和鼠标、优盘等常见的串行总线外设,后者一般用于下载程序到实验板中去。电路图如下所示:

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发121 2USB_ENR29 1.5KPDN0PDP0VBUS1D-2D+3GND4USB-HOSTUSB Port A typeVBUS1D-2D+3GND4USB-DEVICEUSB Port A type21R23 221 2R28 15K21R24 221 2R27 15KVDD5VUSB(HOST)SOCKETDN0DP0USB_5VUSB_D-USB_D+1 2R26 221 2R25 221 2R30 470KUSB使能引脚,使用GPC5图2.8 USB电路图2.5.2 LCD接口本平台的LCD接口有41个间距0.5mm的引脚,这包含了行场扫描、时钟和使能等控制信号,和RGB数据信号(RGB输出为8:8:8,色深为24位即可显示1600万色);除此之外还有PWM输出(GPB1可通过寄存器配置为PWM),和复位信号(nRESET),其中LCD_PWR是背光控制信号。而引脚37、38、39、40为触摸屏接口,它们可以直接连接触摸屏使用。图中的J2可以对LCD驱动板进行供电。LCD_PWRGPB1nRESET1234567891011121314151617181920212223242526272829303132333435363738394041LCDLCD41PVDDLCDVD0VD1VD2VD3VD4VD5VD6VD7VD8VD9VD10GNDVD11VD12VD13VD14VD15GNDVD16VD17VD18VD19VD20VD21VD22VD23GNDVFRAMEVLINEVCLKTSXMTSXPTSYMTSYPVMGNDVDDLCD123J2CON3VDD5VVDD33V图2.9 LCD电路图2.5.3网络接口电路本平台采用了DM9000网卡芯片,这是一个集成度较高的低功耗、高性能的以太网控制芯片,其采用LQFP48管教封装,与MCU连接有8bit/16bit模式,支持3.3V和5V的I/O控制,内置AUTOMDI-X功能10/100M PHY支持多种连接模式,并且配

兰州理工硕士论文13备了标准的10/100M自适应、16K大容量的FIFO、4路多功能GPIO、掉电和全双工等功能[26-28]。其图如下所示:图2.10网络芯片图2.6本章小结本章介绍了实验平台的各种硬件设备的接口情况,包括各种常用的设备。比如USB设备、网络设备、LCD设备等等。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发14第3章嵌入式Linux系统构建如第2章的介绍可知本平台虽然硬件资源丰富,各种接口比较灵活,但要把完整的Linux直接移植到该平台上,还是不太可能的。因为Linux内核文件非常巨大,兼容了很多的硬件,能满足不同的开发要求,但这样的内核体积也是很大的,代码有几百万行,文件有几百MB之大,而我们的实验平台的存储器大小只有100多MB,要想把内核原封不动的移植过来是不太可能的,而且内核所有功能我们并不都需要。这就需要我们除了对硬件平台有较深理解之外,还要了解移植的一般过程。嵌入式系统和PC系统启动的方式类似,都需要有一定的引导程序,在PC机启动的时候,首先是加电自检,也就是运行BIOS系统。这个系统可以把系统从硬件启动过渡到软件管理中,为下一步的从硬盘中将操作系统调用至内存运行做好准备,而嵌入式系统的这种类似于BIOS的系统,我们称之为Bootloader[29-31]。这个程序可以作为系统的启动代码,通过运行这个程序,我们可以将开发板调整到适合载入嵌入式系统的状态,而Bootloader又和平台的硬件息息相关,我们就需要自己动手编写或者移植通用的Bootloader来实现这个过程。在本平台中通过裁剪Uboot来实现上述的过程。Uboot就是

一个在嵌入式系统开发中比较通用的Bootloader,但仍需要根据平台的特点进行一定的修改。所有上述的开发过程都需要在一个功能强大的平台中进行修改,因为嵌入式系统是一个资源有限的系统,想要在这个平台中进行软件的编程,开发和调试,基本上是不可能,但在PC机中确可以进行复杂的软件开发。所以现在唯一可行的办法就是通过将PC机和嵌入式系统进行一个的整合,生成一个交叉编译环境。这个交叉编译环境简言之就是按照平台的要求在PC机中生成可以在另一个平台中运行的程度代码。这样我们就可以在PC机(宿主机)中进行软件的交叉编译和调试,最终生成一个可在嵌入式系统中执行的程序。3.1搭建交叉开发环境嵌入式系统的软件开发与通常的软件开发的区别主要在于软件实现部分,其中又可以分为编译和调试两个部分,在搭建开发环境同样也分为两个部分。3.1.1交叉编译环境的搭建所谓交叉编译就是在一个平台上生成可以在另一个平台上执行的代码,因为不同的CPU需要不同的编译器,而交叉编译功能就是把相同的程序代码翻译成不

兰州理工硕士论文15同的CPU可以执行的语言。通常在Linux环境下的ARM交叉编译器命名为arm-linux-gcc,交叉链接器为arm-linux-ld[32-33],交叉编译过程如图3.1所示:可供调试或者烧写的程序源程序交叉编译器目标模块库文件编辑器交叉链接器图3.1交叉编译图要生成和本平台对应的交叉编译器,主要分为三个部分:一是标准C编译器gcc;二是二进制工具binutils;三是库文件glibc。其中binutils主要用于生成一些辅助工具,如as、ld等;gcc用于生成arm-linux-gcc交叉编译工具(可以编译内核);glibc主要是提供用户程序使用的基本函数库。此外我们还可以使用GNU交叉工具链,但这种软件通用性不太好,编译容易出错。下面简述下软件的安装过程,首先我们从GNU的网站上(ftp://gcc.gnu.org/pub/)下载这些软件:gcc-4.3.0、glibc-4.3.2、binutils-2.15。我们将这些软件包放在同一个目录中,在使用Linux上,我们使用root权限,防止编译因为权限问题不通过。我们在/home/user目录下创建两个目录crosstools、tmp。我们将下载的3个软件压缩包先解压到tmp目录下:tar xvzf binutils-2.15.tar.bz2–C/home/user/tmp,以相同的方式解压其他两个压缩包。然后在crosstools中创建binutils文件夹,之后执行make install,将二进制工具包binutils安装起来。安装arm-linux-gcc比较复杂,一般需要安装两次。由于没有glibc的支持,第一次安装好的arm-linux-gcc工具是不能编译使用了C库的内核文件和其他程序的。所以需要我们对gcc的配置文件作出一定的修改,具体是给变量ATRGET-LIBGCC2_CFLAGS增加一个选项-Dinhibit-libc_D__gthr_posix_h,安装glibc软件包类似于以上的方法。等上述软件安装好之后,再次安装arm-linux-gcc。完成这些工作之后我们编写hello world!测试程序来验证编译工具是否已经成功安装。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发163.1.2交叉调试环境我们知道调试对于程序的开发时非常重要的,它可以使开发出来的程序更加稳定。嵌入式系统的调试于一般的PC机程序调试有两个不同的地方:一是软件调试方式、二是硬件方式,但它们都具有如下的典型特点。(1)调试器和被调试器进程并不在同一台机器中运行,一般情况下调试器进程在PC机(宿主机)上执行,而被调试的进程则在各种定制的调试板(目标机)上运行。(2)调试器通过某种通信方式(串口、网络、并口、JTAG等)控制被调试进程(3)有时候我们可以在目标机上安装某种代理调试工具,用来和调试器相配合来完成目标机上的运行程序的调试。这种调试代理一般分为两类:一是有调试功能的硬件设备;二就是一些专门的软件调试工具。(4)通过在宿主机中运行根据目标机特性模拟出的系统仿真器,可以简化调试的复杂度,上述的情况虽然在物理结构上实现了一台机器运行不同的程序,但是在逻辑上还是有目标机和宿主机的区别[34]。下面分别对软件调试和硬件片上调试作详细的介绍和配置(1)软件方式软件方式调试主要是通过在目标机系统和调试器中分别添加相应的通

信模块,在调试的过程中,让这些模块完成调试信息的传送,这就是所谓的嵌入调试桩的方式。该方式的比较常见的就是Gdb调试器。Gdb的交叉调试器分为GdbServer和GdbClient,其中前者安装在目标板上,后者是本地的Gdb调试器。它们的调试原理如图3.2所示内核应用程序目标机GdbserverGdbLinux环境宿主机串口、网络图3.2调试原理图Gdb调试的工作流程:

兰州理工硕士论文17(1)首先建立调试器和目标机的通信连接,在本平台中,我们通过使用串口软件minicom来实现(2)在目标机开启GdbServer进程,并监听对应端口(3)在宿主机上运行调试器Gdb,此时Gdb会自动寻找远端通信进程(4)在宿主机的Gdb通过Gdbserver请求对目标机上的程序发出控制命令(5)GdbServer把目标系统所有异常处理转向通信模块,并告知宿主机上Gdb当前异常(6)宿主机上Gdb向用户现实被调试程序产生了哪一类异常[35-37]以上方法实际上是通过软件来控制目标机的所有异常处理,这主要是通过通信模块来实现交互的,但这些必须要在系统初始化、通信端口初始化完成之后才能使用,因此一般用于调试嵌入式系统的应用程序,并且这还不能调试嵌入式系统的内核和启动代码。这里我们将安装Gdb6.0,具体步骤如下所示:(1)从网上下载压缩软件包,并解压:tar xvzf gdb-6.0.tar.gz(2)配置调试器../configure–target=arm-linux–prefix=/usr/local/arm(3)编译安装:make install(4)编译适用于arm处理器的GdbServer要完成目标机和宿主机的通信,就必须采用合适的通信方式,在本平台中我们采用minicom作为通信介质,对于minicom的配置,主要集中在通信的波特率、硬件数据流等,下图是minicom的配置图3.3 minicom配置图(2)硬件方式相对于软件调试而言,硬件调试器有更强大的能力和性能,其通过仿真硬件执行过程,可以监控系统的执行情况,这里我们使用JTAG端口技术,该技术采用边界扫描方式进行在线的调试,基本思想就是在靠近芯片的输入输出管脚上增加一个移位寄存器单元。其原理图如下所示:

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发18宿主机目标机调试器程序JTAG图3.4硬件调试图本平台主要采用ADS调试工具,这个工具是arm公司针对arm处理器而推出的集成开发环境,主要包括两大模块:针对代码编辑编译的CoderWarrior forARMDeveloper Suite、针对硬件调试的AXD Debugger。3.2 Uboot的移植Uboot是指universal bootloader即通用的系统启动程序,它遵循GPL开发源码条款。第3章开头对bootloader的功能进行了简单的叙述,这里我们以Uboot为例对系统的加载流程作进一步的了解。Uboot的启动分为两个阶段。在第一个阶段主要完成以下的工作:(1)基本的硬件初始化,包括屏蔽所有终端、设置CPU的速度和时钟频率、RAM初始化、关闭CPU内部指令(2)为第二阶段准备RAM空间,通常为了获得更快的执行速度,通常把第二阶段加载到RAM空间执行。(3)将第二阶段所需要的数据转移至RAM中,这就需要确定存储在Flash等固态存储设备中的第二阶段的起始地址和终止地址(4)设置堆栈指针和存取方式,准备好第二阶段需要的C语言环境第二阶段的主要工作是指:(1)从汇编语言跳转到main入口函数,第二阶段是用C语言实现的,其不但可以更好的完成复杂的功能,也可以获得较好的可读性和移植性。(2)初始化本阶段要使用的硬件设备,包括初始化串行接口、初始化系统设备的计时器。(3)检测系统内存映射,这主要就是计算系统的全部空间中,用于寻址RAM单元的地址范围(4)加载内核映像和rootfs,主要是根据设计的要求拷贝Flash中的各种数据到RAM中[38]为了实现Uboot的移植,首先必须对uboot中的文件结构有一定的了解,结合本平台的需要,我们主要对ARM环境下对主要部分作一定分析,如下图所示:

兰州理工硕士论文19UbootBoardCpu Lib_arm Include Common图3.5 Uboot结构图(1)Board

目录:依赖于具体的平台,主要是存放电路板相关的目录文件,比如Makefile文件等。这都与硬件和地址分配相关(2)Cpu目录:其中的子目录都是Uboot所支持的CPU,比如有arm920t、mips、powerpc、i386等。这些特定的子目录中最重要有以下三个文件:用于初始化cpu、设置cache的文件cpu.c;用于中断和异常处理设置的文件interrupt.c;用于设置堆栈和工作方式的文件start.s。(3)Lib_arm目录:这是一个针对ARM结构体系的通用文件,主要实现ARM平台通用的函数(4)Include目录:头文件和开发板配置文件,所有平台的配置文件都在configs目录下(5)Common目录:这是个和处理器结构体系无关的文件,主要是用于实现各种命令的C文件。由于makefile文件决定了上面这些目录的编译链接,所以我们在执行make之前,首先要对Makefile文件添加如下所示:S3c2440_config:unconfig@.mkconfig$(@:_config=)arm arm920t s3c2440配置完成后,在board中建立s3c2440目录,并复制smdk2410目录中的内容,之后执行make smdk2440_config。这条命令主要完成三个功能:(1)在include文件夹下建立相应的文件软链接(2)生成Makefile包含文件include/config.mk,这定义了四个变量ARCH=arm、CPU=arm920t、BOARD=smdk2440、SOC=s3c2440。(3)生成include/config.h头文件,只有一行#include“config/smdk2440.h”其次在include/configs/中建立配置头文件然后指定交叉编译工具的路径以及测试编译。具体的步骤在此省略了,上面的工作是Uboot的移植前序步骤,不过这里存在一个问题:代码搬运。本平台是基于NandFlash启动,但Uboot并不支持这一启

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发20动方式,这就需要我们对这部分进行一定的修改和完善。3.2.1 Nand Flash启动U-BOOT的基本原理(1)前4K的问题一旦S3C2440配置成从Nand Flash启动(配置由硬件工程师在电路板设置),S3C2440的Nand Flash控制器有一个特殊的功能,即在S3C2440上电后Nand Flash控制器会把闪存上的前4K数据自动复制到4K的内存RAM中,并将0x00000000作为内部RAM的起始地址,CPU从0x00000000的内存位置开始运行汇编程序,这个过程自动完成无需人工干涉。而程序员要实现的,就是如何在4K大小的空间中添加最核心的系统启动程序。(2)启动程序的安排由于Nand Flash控制器从Nand Flash中复制到内部RAM的代码大小是有限的,所以在启动程序的前4K空间,必须完成两个任务:一是完成S3C2440的核心配置,二是如何把启动程序(UBOOT)的其余部分拷贝到RAM中。3.2.2加入支持Nand Flash启动代码首先在include/configs/smdk2440.h中加入CONFIG_S3C2440_NAND_BOOT,如下:#define CONFIG_S3C2440_NAND_BOOT 1支持从Nand Flash中启动.下图是程序流程图:开始关中断,初始化堆栈,跳转到C函数发送成功?读出NandFlash的数据到RAM中设置NandFlash控制器,并发送复位信息读取完整?结束设置标志位,并输出信息设置标志位,并输出信息YYNN图3.6启动原理图

兰州理工硕士论文213.2.3 U-BOOT对Nand Flash命令的支持UBOOT通过指令实现对NandFlash的操作。对NandFlash的指令为:nand info、nand device、nand read、nand write、nand erease、nand bad。主要数据结构有以下两种:struct nand_flash_dev、struct nand_chip。前者包括设备的信息,诸如芯片型号、存储容量、设备ID、I/O总线宽度等信息;后者是NandFlash工作时所支持的信息[40]。U-BOOT支持Nand Flash命令移植主要是有如下的步骤:设置配置选项、加入自己的Nand Flash芯片型号、编写自己的Nand Flash初始化函数。以上就完成了Uboot对NandFlash的支持,使用交叉工具链编译完善之后的Uboot,生成uboot.bin的二进制文件。使用jtag将编译好的uboot烧写到开发板中去。U-Boot 1.1.6(Jan 6 2011-16:16:50)DRAM:64 MBFlash:2 MBNAND:256 MiB***Warning-bad CRC,using default environmentIn:serialOut:serialErr:serialMini2440@nand info图3.7 Uboot的烧写3.3嵌入式

Linux2.6.29内核移植3.3.1 Linux内核文件结构在移植Linux操作系统以前,需先认识一下Linux的内核结构。Linux内核主要由5个子系统组成:进程调度、内存管理、虚拟文件系统、网络接口、进程间通信。(1)进程调度(SCHED):决定进程如何使用CPU的资源。比如有多个进程要执行的时候,调度程序安装事先设置的优先级顺序,决定哪个进程最有资格占用CPU的控制权,而其他进程则在优先级最高的进程取得CPU控制权之后,进入等待队列中等候调度程序的安排。(2)内存管理(MM):多个进程在系统安全的基础上可以共同使用一片内存区域。Linux系统和Windows系统一样具有虚拟内存管理方法,主要原理就是在程序运行时,根据内存的大小以及程序需要的资源量,将程序分为三个部分:代码段、数据段、堆栈段。每个部分的总和是大于内存的实际大小的,但是在程序运行中并不需要把所有的程序全部调入到内存中去,而是根据程序运行的需要将当前用的到的代码、数据或者堆栈内容放入到内存中去,而将暂时用不到的东西存放在诸

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发22如硬盘这样的外设中。一旦程序需要时,Linux系统又负责硬盘和内存的数据传输功能,将这些必要的东西送入到内存中去。内存管理从逻辑上分为两个部分:一是具有进程映射和逻辑内存交换功能的硬件无关部分;二是为内存管理硬件提供虚拟接口的硬件有关部分。(3)虚拟文件系统(VFS):这个为所有设备提供统一的借口,使得上层的开发者不需要知道硬件运行的具体过程。VFS支持多种文件系统结构,包括yaffs2,fat等。文件系统又分为上下两层结构:上层指逻辑文件结构,其向用户层提供结构函数,以供用户方便掉用;下层指设备驱动程序,为逻辑文件结构提供钩子调用函数,方便用户通过两级调用的方式,实现对具体设备的操作。设备驱动程序必须针对具体的设备控制器来编写驱动模块。(4)网络接口(NET):包含了对所有网络标准存取和网络硬件的支持。网络接口分为网络协议和网络驱动两部分。前者支持所有可能的网络传送协议,而后者负责与硬件设备通讯,其包含了大部分可能的硬件设备的驱动方案。(5)进程间通讯(IPC):支持进程之间所有的通信机制。不论是进程调用中心还是其他子系统,都需要通过它来实现系统的正常运转。因为每个子系统都会经历挂起或恢复进程。比如一个进程因为等待外部设备操作时,其被挂起;而当外部设备读写任务完成时,该进程即被恢复继续执行。这就需要进程间的相互通信来实现上述的功能。当进程等待的时候,它通过这个机制告知调度程序,需要挂起。等外部设备完成任务时,又通过这个机制来告知调度程序进行恢复挂起的进程,以完成改进程的功能[41-42]。各个子系统之间的依赖关系如下:进程调度与内存管理之间的关系:这两个子系统互相依赖。在多任务环境下,程序运行时必须要创建进程,而内存管理第一时间为相应的进程分配内存,并在该程序之行的时候,将其装入到内存中去。进程间通信与内存管理的关系:在共享内存的过程中,只有发挥进程间通信子系统的功能,才能使得共享的内存中的数据或者代码安全,否则就容易产生死锁或者死等的问题。虚拟文件系统与网络接口之间的关系:虚拟文件系统利用网络接口支持网络文件系统(NFS),也利用内存管理支持RAMDISK设备。内存管理与虚拟文件系统之间的关系:内存管理利用虚拟文件系统支持交换,交换进程(swapd)定期由调度程序调度,这也是内存管理依赖于进程调度的唯一原因。当一个进程存取的内存映射被换出时,内存管理向文件系统发出请求,同时,挂起当前正在运行的进程。除了这些依赖关系外,有些资源是内核中的所有子系统都必须要使用的共同的资源。例如:分配和释放内存空间的过程,打印警告或错误信息的过程,还有系统的调试例程等等。一般在Linux系统中的/usr/src/Linux-*.*.*.*(*.*.*.*代表内

兰州理工硕士论文23核版本,如2.6.29)目录下就是内核源代码(若没有类似目录则是因为还没安装内核代码)。Linux内核非常庞大,一个功能齐全,包罗万象的内核有数百兆之

多。整个代码分布如图所示。charvideo??ext2vfat??i386arm??ipv4802??drivers fs arch netinit kernel mm ipcinclude图3.8内核结构图/arch子目录包含了针对所有硬件结构的内核代码,如I386,MIPS和ARM。/drivers子目录包括了所有的设备驱动程序,如usb和sound。/fs子目录包含了所有的文件系统的结构代码,如ntfs和jffs2等。/include子目录包含了内核代码所需的大部分库文件,该模块可以在其他模块的基础上重建内核。该目录也包括了不同平台需要的库文件。比如,asm-arm是arm平台需要的库文件。/init子目录包含了内核的引导程序,内核从此处开始运行。/ipc子目录包含了进程间通信代码。/kernel子目录包含了主内核代码。/mm子目录包含了内存管理的全部代码。/net子目录包含了和网络相关的代码,如arm和ipv6。/crypto子目录包含了加密算法。/security子目录包含了和安全相关的代码[43]。depend文件和Makefile文件存在于每个目录下,这时Linux系统的特色。这两个文件都是辅助系统成功编译的重要文件。后者指出了编译时需要用到的编译器和编译的顺序,这也是移植内核过程中不可缺少的文件。(1)arch目录Linux内核之所以能实现跨多种平台移植,这与其独具特色的内核结构密不可分。这个结构把内核源码分解成两个部分。一部分与体系结构息息相关,而另一

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发24个部分则完全可以脱离这个体系结构。而在arch目录中就包含了与体系结构相关的内核代码。其中的每一个目录都针对一种特定的平台,比如本平台采用的ARM处理器和PC中使用的i386。不论是什么平台,都肯定有以下几个目录:boot:包括内核启动时针对特定处理器结构的部分或全部代码。kernel:保存支持体系结构特有的(如信号处理和SMP)特征的实现。lib:存放体系结构中关于(如strlen和memcpy)通用函数的如何实现的程序。mm:包含了体系结构中对于内存管理程序如何实现的代码。math-emu:模拟FPU的代码。对于ARM处理器来说,此目录用mach-xxx代替。显然,移植工作的重点就是移植arch目录下的文件。(2)drivers目录:该目录体积十分巨大,几乎占了内核一半的大小。其几乎提供了所有设备的驱动程序。这些驱动程序有些是本平台能用到的,而大部分本平台并不需要,这就需要对其适当的筛选。(3)fs目录:该目录下列出了Linux所支持的文件系统。Linux支包括ntfs在内的很多文件系统。实际情况中文件系统与硬件平台无关。(4)include目录:这里很多头文件都和内核的编译有很大关系。例如与平台无关的头文件在include/linux子目录下。不同的处理器平台需要的头文件基本都不相同,因此该目录和arch目录相似,按平台结构划分了多个子目录。(5)init目录:该目录包含最主要的初始化代码(不同于系统的引导代码),其中main.c和version.c文件。是引导系统工作的主要代码文件。(6)ipc目录:主要是指进程间的通信代码。3.3.2内核移植过程1下载linux内核从http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.29.5.tar.bz2下载linux2.6.29.5内核至home/arm/dev_home/kernel.进入内核解压后的目录。2修改Makefile修改内核目录树根下的的Makefile,找到ARCH和CROSS_COMPILE,修改ARCH?=arm CROSS_COMPILE?=arm-linux-gcc,然后设置你的PATH环境变量,使其可以找到你的交叉编译工具链:[arm@localhostlinux2.6.29]#echo$PATH/usr/local/arm/3.4.4/bin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/ly/bin如果/usr/local/arm/3.4.4/bin搜索路径,加入下面语句在~/.bashrc中[arm@localhost linux2.6.29]#vi~/.bashrcexport PATH=/usr/local/arm/3.4.4/bin:$PATH再重新登陆.

兰州理工硕士论文253指明分区信息(1)建立Nand Flash分区表这其中给bootloader分配1MB的空间;给内核镜像文件分配3MB的空间;给根文件系统分配80MB的空间;给用户

分配40MB的空间。目标板计划分4个区,分别存放bootloader,kernel,rootfs以及以便以后扩展使用的用户文件系统空间。(2)加入Nand Flash分区struct s3c2440_nand_set nandset={nr_partitions:4,/*分区数量*/partitions:partition_info,/*分区表*/};(3)建立Nand Flash芯片支持(4)加入Nand Flash芯片支持到Nand Flash驱动另外,还要修改此文件中的s3c_device_nand结构体变量,添加对dev成员的赋值。4指定启动时初始化当kernel启动时,我们需要依据之前对分区的设置来进行初始化配置,首先修改arch/arm/machs3c2410/machsmdk2410.c文件[arm@localhost linux2.6.29]$vi arch/arm/machs3c2410/machsmdk2410.c修改smdk2440_devices指明初始化时需要设置的flash分区信息static struct platform_device*smdk2410_devices[]__initdata={&s3c_device_usb,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c,&s3c_device_iis,/*添加如下语句即可*/&s3c_device_nand,};保存,退出。5禁止Flash ECC校验我们的内核都是通过UBOOT烧写到NandFlash中的,而由于UBOOT所使用的是由软件ECC算法产生ECC校验码,这与内核校验的ECC码不一样,所以我们在这里选择禁止内核ECC校验。在drivers/mtd/nand/s3c2410.c这个文件中,我们找到下面这个函数s3c2410_nand_init_chip()函数,在该函数体最后一行加上一条语句:chip>eccmode=NAND_ECC_NONE。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发266配置并编译内核为了我们的内核支持devfs以及在启动时并在/sbin/init运行之前能自动挂载/dev为devfs文件系统,修改fs/Kconfig文件。找到menu\filesystems\,添加如下语句:config DEVFS_FS bool\mount at boot\。说明:mtdblock2是本平台所使用的第3个闪存分区,它的组成方式是这样的:rootfs#console=ttySAC0,115200使kernel启动时的信息通过输出串口0输出到显示屏中去。2.6.29的内核对于串口已经改为ttySAC0,但这对用户空间的串口编程并无大碍,用户空间的串口编程针对的仍是/dev/ttyS0的。以下是内核编译的结果图。图3.9内核裁剪图3.4根文件系统的制作随着32位CPU价格不断下跌,片上存储设备的容量相比越来越大,越来越多的嵌入式系统开始应用各种嵌入式操作系统。一般在嵌入式领域,只要应用到操作系统的必然会需要一个,甚至是多个文件系统。所谓文件系统,其实就是存储在设备中文件的结构和组织方式。这种设备的类型很多,可能是RAM、NandFlash等等。如今,对于类型不一,种类繁多的设备,文件系统也有很多可以使用。比如EXT2、TEMPFS、RAMDISK、CRAMFS、JFFS1/2、YAFFS1/2、XFS等。除此之外,还有不少公司为用户定制专门的商用文件系统[44]。文件系统是针对具体的设备提出的解决方法。通常情况下会首先要考虑的就是稳定性,健壮性。如果应用场合中只需要烧写一次成型而不需要更新程序的话,选择CARAMFS这样的只读文件系统是非常方便和快捷的,这也有利于批量的生产成品,并且它有一个最大的好处就是其具有很高的压缩比,从而可以减小存储空间,这样可以降低生产中的成本。但是一旦处于一个随时需要读写数据的应用场景的时候,诸如像数据采集这种需要频繁保存数据的场合中时,只读的文件系统根本满足不了系统的需求,我们可以选择其他方式的文件组织方式,比如JFFS

兰州理工硕士论文27或者YAFFS这一类的可读写的系统。不过在实际应用中,需要考虑的因素还远远不止这些,实际情况只能针对具体的问题进行分析,下面以我们的应用为基础来分析下如何在自己的系统中选择合适的文件系统。在本文涉及的领域中,并不是一个类似于数据采集的场合,所以我们不需要频繁的更改数据,但是这却避免不了的要牵涉数据的存取。因为我们的平台采用的是NANDFLASH,所以可以在根文件系统的选择上采用压缩率较好

的CRAMFS,而在根文件系统下我们还可以挂载一个可读写的YAFFS2文件系统。这样既可以提高存储设备的利用率,又可以保证数据的正常读取。YAFFS2(Yet Another nandFlash FileSytem2)是专门针对NandFlash设备的一种文件系统。虽然YAFFS2类似于JFFS/JFFS2文件系统,但由于采用了增强的碎片整理机制和均衡磨损技术,不但它的读写速度较JFFS/JFFS2有很大的提高,其使用寿命和稳定性可靠性也有很大的提升。这使得该文件系统可以在大容量芯片中得到推广使用。所以说YAFFS文件系统具有很大的优势和发展潜力。3.4.1建立根文件系统Linux内核启动以后,会参数linux_cmd_line的引导而跳转到根文件系统的入口地址,来完成文件系统的初始化和挂载任务。根文件的制作方法分为两种:一是自己手动建立;而是使用一些开发套件来实现根文件系统的快速建立。手动建立在调试过程中会比较麻烦,本平台使用一个开发套件来帮助完成基本文件系统的建立。Busybox就是这样的一种开发套件,其本身是由Bruce Perens发起的一项计划,本来是用来协助Debian在发行套件中用来建立安装磁盘。但由于Busybox不仅小巧而且有很强大的功能,导致了其在嵌入式系统中应用广泛。具体的方法是:首先下载Busybox常用的可靠版本(www.busybox.net),解压后类似于内核的配置过程,直接到相应的目录中执行make menuconfig命令,从而可以进入Busybox配置界面(这个界面类似于内核配置图)。在Applets下面选择适合平台的命令,然后退出保存。其次是执行make,make install。这时就会在Busybox的目录下生成_install目录,这个目录就已经包含了配置好的命令工具包。本平台中只要把这个目录拷贝到工作目录,并且更名为rootfs。这样我们就在该目录的基础上建立了根文件系统。在rootfs/下,首先在/rootfs/dev下建立必须的设备文件。关于设备的建立,可以参考Filesystem Hierarchy Standard来确定需要的哪些设备文件,下一步就是完成/rootfs/etc这个目录下的3个比较重要的文件inittab,fstab,init.d/rcS(或者是rc.d/rc.sysinit,这个由inittab决定)。最后,加入需要的链接库文件就可以了。但是这部分的实现是比较繁琐的,因为走到这一步时,我们对于应用中到底需要哪些具体的库文件并不是很清楚,这

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发28就导致了我们制作的文件系统的大小并不是太好控制的。而通常情况下这里有两种经验性的处理方法:一是采用readelf这个工具包来找出链接库;二是参考linux相关网站上所提供的文件系统,来进一步确定我们平台中所需要的链接库文件。3.4.2制作YAFFS2文件系统根文件系统做好后,可以通过NFS(http://nfs.sourceforge.net/nfs-howto/)来测试文件系统是否可行,最后我们要把这个文件系统烧进目标板。可以有两种方式来应用YAFFS2文件系统,一是CRAMFS+YAFFS2的组合,一种是纯YAFFS2文件系统格式。在本平台中内核和根文件系统的应用十分稳定,所以从节省空间、降低成本、保护系统的角度来看,选用CRAMFS这种高压缩率、只读文件系统,具有很大的现实意义[45]。对于CRAMFS只读文件系统,我们采用mkcramfs/rootfs~/root.img这几个命令来生成cramfs镜像,而/rootfs本身就是之前建立好的目录,~/root.img作为生成镜像的指定保存目录来用。由于YAFFS2文件系统就是根据NandFlash设备来设计的,而在本文的应用中文件系统恰好设置成从NandFlash中启动的,这就需要我们在内核中加入支持NandFlash启动的设备驱动代码,并在arch\\arm\\mach-s3c2410\\devs.c文件中添加有关NandFlash分区的代码。在本平台中将NandFlash分为bootloader、kernel、root三个彼此相连的分区。下面是具体的执行过程:在相应的网站中下载YAFFS2(GPL)源码,首先解压后在YAFFS2目录下执行:patch-ker.sh~/Linux2.6.29.5命令,这样就可以在相应的目录中产生YAFFS2目录。而下一步就是在该目录下执行make menuconfig命令来在内核的配置相应的驱动程序,等到这些都顺利完成之后保存退出设置。其次执行make命令,Make结束后就生成了一个有挂载yaffs2文件系统能力的内核镜像。而在Uboot源文件中,将NandFlash分成几个分区,此时这里的

分区必须和前面所提到的devs.c文件里的分区保持一致,因为内核和文件系统的地址均在前面都到确认,所以最后启动时也会到相应的地址去寻找指令。在本平台中,我们将Flash分成Uboot、kernel、root、user四个分区。其中CRAMFS文件系统挂载于根目录下,而YAFFS2文件系统挂载于用户目录下。在YAFFS2源文件的utils目录下,执行make命令就可以生成mkyaffs2image镜像工具,而执行./mkyaffs2image则可以生成yaffs2文件系统。当然也可以将YAFFS2作为动态模块来编译到内核中,因为根文件系统是CRAMFS格式,如此这样可以使得文件系统更加灵活。文件系统最后的目的就是在内核启动完成后进行加载,而文件系统不止一种挂载方式,具体的说有两种方式:手动和自动挂载。文件的挂载显然是要在无人的情况下自动的进行,这就需要对/etc/init.d/rcS的脚本进行编辑。在这个里面可以

兰州理工硕士论文29对时间进行设置、配置交换分区大小、采集主机名等等。等到脚本都设置完成之后,就可以将文件系统烧写到相应分区中去,到此处我们就成功的添加了对于文件系统的支持。图3.10文件系统配置图3.5本章小结本章重点介绍了Uboot和Linux内核的移植过程,并针对本平台的储存方式,加入了相应的支持代码。并且制作了相应的文件系统,为下一步的驱动的开发设计提供了可靠,稳定的软件平台。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发30第4章设备驱动设备驱动程序是Linux内核的重要组成部分,控制了操作系统和硬件设备之间的交互。它通过向用户提供针对系统硬件的标准化接口,使得用户在程序设计的过程中不需要特别关注设备的工作细节。在Linux系统的运行状态中,分为三层结构,顶层的是用户层的应用程序,中层是内核的运行,而底层则是设备驱动层,内核和驱动紧密相连,任何用户层的应用程序,想要控制对应的硬件设备,都必须通过驱动层才能实现。4.1设备驱动简介Linux系统中设备一般可以分为三种类型:字符设备、块设备和网络设备。文中所涉及的LCD驱动属于字符型设备驱动程序。在对字符设备发出读、写请求时,实际的硬件I/O一般就紧接着发生了。Linux系统访问设备就像访问文件一样,例如打开关闭设备系统调用open()和close()函数。设备驱动的工作流程是这样的:在加载时首先需要调用入口函数init_module(),这主要是将设备的寄存器和控制器进行初始化设置。而这个入口函数中最典型的子函数就是register_chrdev()和register_blkdev(),前者完成向内核注册字符设备的任务,后者实现了块设备在内核中的注册过程。当这些设备在内核中注册成功后,系统会向这个成功注册的设备分配主设备号和自定义的次设备号,同时还要和文件系统建立起一定的联系。字符设备驱动在向Linux内核注册的过程中,首先其对应的向量表chrdevs会添加device_struct这个数据结构,同时在注册成功时,系统分配的设备标识符会作为这个向量表的指针。对于device_struct这个针对设备的数据结构,其一般由两个部分组成:一个是指向该设备名称的字符型指针,另一个是对于这个设备进行文件操作的一组返回值为布尔型的指针。而对于这些设备的文件操作其实就存在于设备驱动程序中,当需要打开、读写这些设备的时候,都通过上面的文件操作来实现的。而注册登记的过程,实际上就是将模块所能识别的文件操作调用函数和设备驱动中的设备结构体相关联起来,形成类似于管道的功能。一旦这种关系建立起来,内核可以通过模块与设备之间的管道关系,实现对设备的操作。但是这个时候内核和应用程序并没有直接的接口函数,应用程序只能通过在文件系统中创建节点的方式,来和设备文件结构体形成关联。在Linux中系统中通过mknod()创建针对这个设备的文件节点,这样应用程序就可以通过文件系统来直接操作外部设备了。这也实现了Linux对设备的读写就如同对文件的读写。当设备驱动卸载的时候,这个过程和加载的时候刚好相反,

兰州理工硕士论文31首先应用程序通过文件系统首先删除掉对应的节点,之后内核会根据

设备号来释放其占用的硬件资源,来实现对具体设备的卸载过程。下图是设备驱动的结构图。应用程序设备文件驱动模块硬件内核Open,read,writeOpen,read,write以设备号建立节点返回主设备号Insmod()注册图4.1驱动原理图4.2 LCD设备驱动设计4.2.1帧缓冲设备结构帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象成一种设备,针对图形化界面下的应用程序显示问题,提供了一种可以直接读写显示缓存区的方案。这种设置对于用户层是透明的,即用户无法知晓具体的显存大小、存储机制等等。用户只要通过对该接口的调用,可以直接完成诸如画图和图形框的显示。该方案也是Linux中显示汉字的唯一解决方案,除此之外这是PC机中解决窗口显示的主要方式。帧缓冲设备对应的设备驱动文件为/dev/fb,当系统有不止有一个显卡时,Linux也支持多达32个帧缓冲设备的显示,其文件编号分别从/dev/fb0到/dev/fb31,而一般情况下指向/dev/fb0的帧缓冲设备通常是/dev/fb,即为当前默认的帧缓冲设备。在本平台的系统中,只有一个帧缓冲设备,所以对于缓存的显示设置是足够的。帧缓冲设备为典型的字符设备:其主设备号为29,从设备号从0到31总共有32个,这分别对应/dev/fb0-/dev/fb31。通过默认的帧缓冲设备,应用程序的操作方式有:

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发32(1)对/dev/fb的读写:相当于对缓冲区的读写操作。比如使用命令cp/dev/fb0 tmp,其可以将此时的屏幕的内容复制到一个具体的文件中,而cp tmp>/dev/fb0这个命令则将缓冲区的图形或者数据投影到屏幕上。(2)映射操作:在现代计算机技术中,出于对数据和代码的保护,通常情况并不支持应用程序对内存的具体内容的进行直接的读写操作,这种模式称为保护模式。每个应用程序都有相对独立的虚拟地址空间。Linux作为先进的操作系统也不例外。所以为了将文件的内容映射到用户空间,Linux针对文件操作中提供了一个称为mmap的函数。对于帧缓冲设备,同样可以通过映射操作,将显示缓冲区的物理地址映射到用户空间的一段虚拟地址中。映射完成后用户就可以通过这段虚拟地址,对屏幕缓冲区进行数据的读写操作或者在屏幕上绘制图形。事实上应用程序的图形显示功能都是通过映射操作来实现的。而映射操作运行于系统的内核态,所以我们要做的工作一般不多。(3)I/O控制:帧缓冲设备中对于输入输出部分的控制,如屏幕的像素大小、分辨率、色彩深度等等主要是通过底层的驱动来完成的。在应用程序中,操作/dev/fb的一般步骤如下:(1)打开/dev/fb设备文件。(2)通过调用函数ioctrl来获取当前屏幕的参数,如屏幕大小,每个像素点RGB位数。由此可以计算出相应的显示缓冲区的大小。(3)将显示缓冲区的内容映射到用户空间中去。(4)映射后完成后就可以通过读写显示缓冲区,来实现图形显示和图形的绘制。典型程序段如下:#includeint main(){int fbfd=0;struct fb_var_screeninfo vinfo;struct fb_fix_screeninfo finfo;long int screensize=0;/*打开设备文件*/fbfd=open(\取得LCD的相关参数*/ioctl(fbfd,FBIOGET_FSCREENINFO,&finfo);ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo);/*计算显示缓冲区容量*/screensize=vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;

兰州理工硕士论文33/*将显示缓冲区映射到用户地址空间*/fbp=(char*)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED,fbfd,0);4.2.2帧缓冲驱动的编写帧缓冲设备是字符设备的一种,采用“文件层-驱动层”的关联方式。文件层中,Linux对它的定义为:static struct file_operations fb_fops={owner:THIS_MODULE,read:fb_read,write:fb_write,ioctl:fb_ioctl,mmap:fb_mmap,open:fb_open,release:fb_release,};这些函数在Linux的目录(linux/driver/video/fbmem.c)中有对应的定义。显示设备不仅接收来自于用户层的数据和图形,而且还要对内核态的控制命令作出相应,这就使得显示设备的驱动设计很特别,其不仅要通过底层的函数来实现屏幕的显示和图形的绘制,还要和内核态交换诸如设备记录信息的通信。这个信息交换函数,主要是指

struct fb_info结构体。在本平台的系统中,对于显示的要求不是很复杂,只用到了该数据结构中的少数几个成员,以下是对嵌入式系统中常用的成员做个简介,这有利于我们采取有针对性的开发。fb_info这个结构体纪录了包括帧缓冲设备的参数、状态和相关操作的全部信息。不同的帧缓冲设备对应不同的fb_info结构,这是嵌入式系统中关于显示部分需要开发的地方。Fb_info的主要变量有Modename、fontname、fbops这三个,前者代表设备名称,中间是显示字体,后者是一个指向具体的底层操作的指针。除了上述的结构体需要驱动开发人员根据相应的硬件特点有针对性的进行编写之外,还包括以下两个结构体:fb_var_screeninfo和fb_fix_screeninfo。其中fb_var_screeninfo记录用户可更改的显示控制器参数,包括像素数量和每个像素点的大小;fb_var_screeninfo中的xres用于表示一行中的像素点数量,而yres定义屏幕一列的像素点个数,bits_per_pixel则表示一个像素点所占用的字节数[46]。而fb_fix_screeninfo与前面的结构体fb_var_screeninfo相反,只记录用户不可更改的参数,如显示缓冲区的物理地址。一旦用户程序要进行映射操作时,就可以从fb_fix_screeninfo中读取到对应的物理地址。在掌握了上述的原理之后,编写帧缓冲驱动的工作是比较简单的,具体要做

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发34的就是:1.编写初始化函数:首先初始化LCD控制器,这其中主要是针对显示模式和颜色进行设置,然后在SDRAM中为LCD分配缓冲区。这主要通过kmalloc函数来实现对一片连续的空间的分配。本文采用的LCD像素大小为240x320,有24位色彩,需要分配的缓冲区大小为240x320x3=230KB,缓冲区的起始地址保存在LCD控制寄存器中。最后对fb_info结构进行设置,包括填写成员变量,调用注册函数register_framebuffer(&fb_info)将fb_info注册进入内核。2.编写fb_info中指向缓冲区操作的指针fb_ops:对于本平台的要求,只需要写好以下几个函数就行:struct fb_ops{……..int(*fb_get_fix)(struct fb_fix_screeninfo*fix,int con,struct fb_info*info);int(*fb_get_var)(struct fb_var_screeninfo*var,int con,struct fb_info*info);int(*fb_set_var)(struct fb_var_screeninfo*var,int con,struct fb_info*info);…….};struct fb_ops用来设置/获取fb_info结构中的成员变量的。当应用程序对设备文件进行I/O操作时候会调用它们。例如对于fb_get_fix(),应用程序传入的是fb_fix_screeninfo结构,在函数中对其成员变量赋值,主要是smem_start(缓冲区起始地址)和smem_len(缓冲区长度),最终返回给应用程序。而fb_set_var()函数的传入参数是fb_var_screeninfo,函数中需要对xres,yres,和bits_per_pixel赋值。4.3 USB设备驱动设计4.3.1 USB的具体构成USB驱动程序存在于不同的内核子系统和USB硬件控制器之间,USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口,而不必考虑系统当前存在的各种不同类型的USB硬件控制器。USB是一个非常复杂的设备,内核为我们提供了一个称为USB的核心的子系统来处理大部分的复杂性。USB设备有以下三个部分组成:配置、接口和端点。如下图所示:

兰州理工硕士论文35USB HostUSB Device DriverUSB CoreUSBHCD(EHCI/OHCI/UHCI)HOST ControllerUSB Device DriverUSB CoreUSBHCD(EHCI/OHCI/UHCI)Device ControllerHardwareUSB Device图4.2 USB结构图利用端点通信是USB通信的特点,端点又分为四种方式:中断、批量、等时、控制。而USB端点的数据传输采用半双工的方式,即在一个确定的时间点上,数据要么是从主机到设备,要么就是设备到主机,这种工作方式类似于单向管道。根据上面所说的可以得出这样的结论:USB设备的设置非常灵活,且有不止一种配置方式,而USB的接口也具有以上类似的多样性功能。而驱动程序的工作方式是首先将USB对象注册到USB子系统中,之后利用制造商

和设备标识来判断硬件是否已经成功安装,之后就是利用USB的串行通道和控制器来实现数据的传输。上面我们简要说明了驱动程序的基本理论,在写一个设备驱动程序之前,我们还要了解以下两个概念:模块和设备文件[47]。模块:我们知道一个程序从代码写作到最后的运行,首先是在代码写作完成后用编译器进行编译以生成目标对象,之后通过链接器将目标对象链接起来,最后是生成可执行的程序。而模块其实就是目标对象文件,因为没有链接所以不能独立运行,但是模块可以被装载进内核而运行,从而可以增强内核的功能。Linux下对于硬件的驱动有两种方式:一是直接加载到内核代码中,随内核的启动而运行相应的设备;二是以模块方式,编译生成一个目标对象文件,在应用程序需要的时候再加载到内核空间运行,所以通常对于驱动就是指驱动模块。设备文件:在文件系统中设备是文件系统创建的一个节点,这个节点在逻辑上以文件的形式存在。但这又不同于常见的文件,设备文件的特点是其与硬件息息相关,内核为硬件指定了主从设备号和其他硬件信息,这些信息都是以节点的形式存在于文件系统中。其中主设备号用于区别不同的硬件设备,且对应着确定的驱动程序,而从设备号主要用于区分同一类设备的不同属性或者使用方式。主设备号一般存在于/proc/devices文件中,而设备节点存在于相应的文件系统中。一

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发36旦我们要使用某个具体的外部设备,首先是调用驱动的对象目标模块,这个模块可以是已经运行于内核态,也可以是调用的时候动态加载进入内核的。等驱动模块加载成功后,其会由内核分配到一个主设备号和从设备号。主设备号如上文所说决定了驱动的类型,可以使字符设备、也可以是块设备、还可以是网络设备。之后通过设备号将设备和驱动关联起来,此时系统就知道了这个设备所对应的驱动程序。等这些完成后文件系统会根据设备号,创建一个设备文件节点。这样就可以通过对文件的操作来实现对设备的诸如:打开、读写、关闭等操作。4.3.2 USB驱动程序结构分析写一个USB的驱动程序最基本的要做四件事:驱动程序要支持的设备、注册USB驱动程序、探测和断开、提交和控制urb。驱动程序支持的设备:一般使用struct usb_device_id这个结构体来控制单一的USB驱动程序。在本平台中,我们根据USB的特征,对程序中的定义进行一定的修改。注册USB驱动程序:structusb_driver是USB驱动设计中的重要数据结构,包含了很多函数和变量。struct usb_driver结构体要初始设置的有5个字段,其框架如下所示:static struct usb_driver skel_driver={.owner=THIS_MODULE,.name=\sconnect,.id_table=skel_table,};这部分的流程图如下所示:

兰州理工硕士论文37开始初始化设备,如产品ID向系统注册USB设备注册成功?向系统提供设备驱动结构体信息成功提供?结束YNY N图4.3驱动流程图struct module*owner:这是一个指向该驱动模块的指针。USB通过对它来对驱动计数,保证它能正常的运行或者卸载。const char*name:这是一个指向常量字符的指针,其指向驱动的名称。这个指针所指向的常量字符在整个驱动中是独一无二的。一般将它与驱动模块设为同一名称。int(*probe)(struct usb_interface*intf,const structusb_device_id*id):这是指向驱动探测函数的指针。只要当USB接口有空闲,并且驱动接口有请求的时候,这个函数就要被调用。void(disconnect)(struct usb_interface*intf):指向驱动断开函数的指针。如果系统要卸载某个USB接口或者驱动时,就调用这个函数。const struct usb_device_id*id_table:指向设备ID表的指针。这个表中存放了可以被驱动识别和支持的USB设备。只有设置好这个变量,USB的所有函数才能被识别和相应。usb_register_driver函数是能把structusb_driver注册到USB核心的注册函数。当USB驱动模块初始化之后,上述的工作就已经完成了。static int__init usb_skel_init(void){int result;/*驱动注册到USB子系统中*/result=usb_register(&skel_driver);

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发38if(result)err(\failed.Error number%d\是USB注销函数,只有系统要注销USB驱动时才会使用这个函数。调用的时候,可以将与USB接口互联的设备全部断开,从而可以使内核能够注销掉这些无用的驱动。它的结构是这样的:static void__exit usb_skel_exit(void){/*从子系统注销驱动程序*/usb_deregister(&skel_driver);}探测和断开:如果有一个设备已经成功安装,此时USB核心恰好接受这个设备的请求时,驱动就会使用探测函数将这个设备的信息发送给USB核心,由核心来判断这个新安装的设备是否适用。而当驱动因为某种原因放弃设备的控制权之后,USB核心就会使用断开函数,用它来完成后续的清理工作。探测函数在工作中时,USB驱动为了能准备的调用USB设备时,其会将与调用相关的结构体全部进行初始化操作。探测函数会使用循环探测的方法来访问接口中的所有端点,并在每个端点访问的过程中加以局部指针,这样为后续的访问节省了很多时间,也提高了访问的速度。在第一轮探测完所有端点后,通过检查检查USB_DIR_IN来确定端点的末地址。如果所有这些探测都通过了,并且驱动程序已经发现了正确的端点类型,则使用一个结构体来保存该端点的所有信息,以便于以后和该端点通信:/*找到批量IN类型的端点

*/buffer_size=endpoint->wMaxPacketSize;dev->bulk_in_size=buffer_size;dev->bulk_in_endpointAddr=endpoint->bEndpointAddress;dev->bulk_in_buffer=kmalloc(buffer_size,GFP_KERNEL);if(!dev->bulk_in_buffer){err(\所有的USB设备响应时间都是有限的。而在这个有限时间内,驱动使用函数usb_set_intfdata来联系接口的信息。当这一切都完成后,USB驱动程序必须在探测函数中调用usb_register_dev函数来把该设备注册到USB核心里:

兰州理工硕士论文39/*注册设备到USB核心*/retval=usb_register_dev(interface,&skel_class);if(retval){/*有些情况下是不允许注册驱动程序的*/err(\当一个USB设备被断开时,和该设备相关联的所有资源都应该被尽可能的清理掉,在此时,如果已在在探测函数中调用了注册函数来为该USB设备分配了一个次设备号话,必须调用usb_deregister_dev函数来把次设备号交还给USB核心。在断开函数中,从接口获取之前调用usb_set_intfdata设置的任何数据也是很重要的。然后设置structusb_interface结构体中的数据指针为NULL,以防任何不适当的对该数据的错误访问。在探测函数中会对每一个接口进行一次探测,所以我们在写USB驱动程序的时候,只要做好第一个端点,其它的端点就会自动完成探测。在探测函数中我们要注意的是在内核中用结构体struct usb_host_endpoint来描述USB端点,这个结构体在另一个名为structusb_endpoint_descriptor的结构体中包含了真正的端点信息,structusb_endpoint_descriptor结构体包含了所有的USB特定的数据,该结构体中我们要关心的几个字段是:bEndpointAddress:这个是特定的USB地址,可以结合USB_DIR_IN和USB_DIR_OUT来使用,以确定该端点的数据是传向设备还是主机。bmAttributes:这个是端点的类型,这个值可以结合位掩码USB_ENDPOINT_XFERTYPE_MASK来使用,以确定此端点的类型是USB_ENDPOINT_XFER_ISOC(等时)、USB_ENDPOINT_XFER_BULK(批量)、USB_ENDPOINT_XFER_INT的哪一种。wMaxPacketSize:这个是端点一次可以处理的最大字节数,驱动程序可以发送数量大于此值的数据到端点,在实际传输中,数据量如果大于此值会被分割。bInterval:这个值只有在端点类型是中断类型时才起作用,它是端点中断请求的间隔时间,以毫秒为单位。提交和控制urb:当驱动要把数据传送到USB设备中,通过分

配urb的方式来实现数据的传输:urb=usb_alloc_urb(0,GFP_KERNEL);if(!urb){retval=-ENOMEM;

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发40goto error;}虽然驱动已经为urb分配了空间,但要想将数据成功的传送到缓冲区,还要通过创建并使用DMA缓冲区才能真正实现数据的收发。下面是部分传送代码:buf=usb_buffer_alloc(dev->udev,count,GFP_KERNEL,&urb->transfer_dma);if(!buf){retval=-ENOMEM;goto error;}if(copy_from_user(buf,user_buffer,count)){retval=-EFAULT;goto error;}当数据从用户空间正确复制到局部缓冲区后,urb必须在可以被提交给USB核心之前被正确初始化:/*初始化urb*/usb_fill_bulk_urb(urb,dev->udev,usb_sndbulkpipe(dev->udev,dev->bulk_out_endpointAddr),buf,count,skel_write_bulk_callback,dev);urb->transfer_flags|=URB_NO_TRANSFER_DMA_MAP;然后urb就可以被提交给USB核心以传输到设备了:/*把数据从批量OUT端口发出*/retval=usb_submit_urb(urb,GFP_KERNEL);if(retval){err(\submitting write urb,error%d\error;}当urb被成功传输到USB设备之后,urb回调函数将被USB核心调用,之后初始化urb,使其指向skel_write_bulk_callback函数,以下就是该函数:static void skel_write_bulk_callback(struct urb*urb,struct pt_regs*regs){ 兰州理工硕士论文41struct usb_skel*dev;dev=(struct usb_skel*)urb->context;if(urb->status&&!(urb->status==-ENOENT|urb->status==-ECONNRESET|urb->status==-ESHUTDOWN)){dbg(\write bulk status received:%d\释放已分配的缓冲区*/usb_buffer_free(urb->dev,urb->transfer_buffer_length,urb->transfer_buffer,urb->transfer_dma);}有时候USB驱动程序只是要发送或者接收一些简单的数据,驱动程序也可以不用urb来进行数据的传输,这是里涉及到两个简单的接口函数:usb_bulk_msg和usb_control_msg,在这个USB框架程序里读操作就是这样的一个应用:/*进行阻塞的批量读以从设备获取数据*/retval=usb_bulk_msg(dev->udev,usb_rcvbulkpipe(dev->udev,dev->bulk_in_endpointAddr),dev->bulk_in_buffer,min(dev->bulk_in_size,count),&count,HZ*10);/*如果读成功,复制到用户空间*/if(!retval){if(copy_to_user(buffer,dev->bulk_in_buffer,count))retval=-EFAULT;elseretval=count;}usb_bulk_msg接口函数的定义如下:int usb_bulk_msg(struct usb_device*usb_dev,unsigned int pipe,void*data,int len,int*actual_length,int timeout);其参数为:struct usb_device*usb_dev:指向批量消息所发送的目标USB设备指针。unsigned int pipe:批量消息所发送目标USB设备的特定端点,此值是调用

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发42usb_sndbulkpipe或者usb_rcvbulkpipe来创建的。void*data:如果是一个OUT端点,它是指向即将发送到设备的数据的指针。如果是IN端点,它是指向从设备读取的数据应该存放的位置的指针。int len:data参数所指缓冲区的大小。int*actual_length:指向保存实际传输字节数的位置的指针,至于是传输到设备还是从设备接收取决于端点的方向。int timeout:以Jiffies为单位的等待的超时时间,如果该值为0,该函数一直等待消息的结束。如果该接口函数调用成功,返回值为0,否则返回一个负的错误值。usb_control_msg接口函数定义如下:int usb_control_msg(struct usb_device*dev,unsigned intpipe,__u8request,__u8requesttype,__u16 value,__u16 index,void*data,__u16 size,int timeout)除了允许驱动程序发送和接收USB控制消息之外,usb_control_msg函数的运作和usb_bulk_msg函数类似,其参数和usb_bulk_msg的

参数有几个重要区别:struct usb_device*dev:指向控制消息所发送的目标USB设备的指针。unsigned int pipe:控制消息所发送的目标USB设备的特定端点,该值是调用usb_sndctrlpipe或usb_rcvctrlpipe来创建的。__u8 request:控制消息的USB请求值。__u8 requesttype:控制消息的USB请求类型值。__u16 value:控制消息的USB消息值。__u16 index:控制消息的USB消息索引值。void*data:如果是一个OUT端点,它是指身即将发送到设备的数据的指针。如果是一个IN端点,它是指向从设备读取的数据应该存放的位置的指针。__u16 size:data参数所指缓冲区的大小。int timeout:以Jiffies为单位的应该等待的超时时间,如果为0,该函数将一直等待消息结束。如果该接口函数调用成功,返回传输到设备或者从设备读取的字节数;如果不成功它返回一个负的错误值。这两个接口函数都不能在一个中断上下文中或者持有自旋锁的情况下调用,同样,该函数也不能被任何其它函数取消,使用时要谨慎。要给未知的USB设备写驱动程序,只需要把这个框架程序稍做修改就可以用了,把0xfff0这两个值改为未知USB的ID号。之后就是在探测函数中把需要探测的接口端点类型写好,在这个框架程序中只探测了批量(USB_ENDPOINT_XFER_BULK)IN和OUT端点,可以在此处使用掩码(USB_ENDPOINT_XFERTYPE_MASK)让其探测其它的端点类型,驱动程序会对USB设备的每一个接口进行一次探测,当探测成功后,驱动程序就被绑

兰州理工硕士论文43定到这个接口上。再有就是urb的初始化问题,如果你只写简单的USB驱动,这块不用多加考虑,框架程序里的东西已经够用了。还有一个初始化等时urb的,在被提交到USB核心前,必须在驱动程序中手工地进行初始化,可以参考内核源代码树下的/usr/src/~/drivers/usb/media下的konicawc.c文件。现在驱动程序已经大体写好了,然后在linux下把它编译成模块就可以把驱动模块插入到内核中运行了,编译的Makefile文件可以这样来写:ifneq($(KERNELRELEASE),)obj-m:=xxx.oelseKERNELDIR?=/lib/modules/$(shell uname-r)/buildPWD:=$(shell

pwd)default:$(MAKE)-C$(KERNELDIR)M=$(PWD)modulesendifclean:rm-rf*.mod.**.o*.ko.*.ko.*.tmp*.*.mod.o.*.*.o.*其中xxx是源文件的文件名,在linux下直接执行make就可以生成驱动模块(xxx.ko)了。生成驱动模块后使用insmodxxx.ko就可以插入到内核中运行了,lsmod命令可以查看已经嵌入到内核中的模块的具体名称,也可以用命令rmmod把模块卸载掉;如果把编译出来的驱动模块拷贝/lib/modules/~/kernel/drivers/usb/下,然后depmod一下,那么你在插入USB设备的时候,系统就会自动加载驱动模块的,可以看到驱动程序已经绑定到接口上。图4.4 USB挂载图

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发444.4网络驱动设计4.4.1 DM9000结构分析本平台采用了DM9000网卡芯片,这是一个集成度较高的低功耗、高性能的以太网控制芯片,其采用LQFP48管教封装,与MCU连接有8bit/16bit模式,支持3.3V和5V的I/O控制,内置AUTOMDI-X功能10/100M PHY支持多种连接模式,并且配备了标准的10/100M自适应、16K大容量的FIFO、4路多功能GPIO、掉电和全双工等功能。其结构图如下所示MemoryManagementInternalSRAMPorcessornIetfraceAUTONegotiationMII Mangementcontrol&RegisterEEPROMTX-MachineControl&Status RegisterRX-MachineMII100 Base-TXTranseciver100Base-TXPCSAUTO-MDIX100Base-TXTx/Rx图4.5 DM9000结构框图4.4.2 Dm9000驱动移植过程1.在内核编译配置选项中,driver-->net-->10/100M net-->DM9000 support选项选中。2.在arch/arm/mach-s3c2410/devs.c中添加dm9000的platform_device。3.在arch/arm/mach-s3c2410/devs.h中声明平台设备eievk_dm9000_device:4.在arm/arm/mach-s3c2410/mach-smdk2410.c中将eievk_dm9000_device添加到平台设备列表中:static struct

platform_device*smdk2440_devices[]__initdata={&s3c_device_usb,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c,&s3c_device_iis,&eievk_dm9000_device,//add dm9000 by beelike

兰州理工硕士论文45&s3c_device_nand,};5.此时Dm9000设备已经成功注册进入驱动核心。下面进入driver/net/dm9000.C中,还需要做两方面的工作:设置芯片MAC地址,使能DM9000的中断。根据开发板的特点,设置以下的内容:1)GPFCON(56000050)GPF7[15:14]置10,功能设置为EINT7。这可以用函数实现:s3c2410_gpio_cfgpin(S3C2410_GPF7,S3C2410_GPF3_EINT7);2)EXTINT0(56000088)[30:28]置0低电平触发中断3)外部中断屏蔽寄存器。EINTMASK(560000a4)[7]置0以enable interrupt EINT74)全局中断屏蔽寄存器INTMASK(4A000008)[4]置0使能EINT4_7。代码修改:在dm9000.C的开始添加如下定义:/********************beelike add********************/#includestatic char net_mac_addr[]={0x00,0xe0,0x3d,0xf4,0xdd,0xf7};//MACstatic

void*extint0,*intmsk,*eintmsk;#define EINTMASK(0x560000a4)//外部中断屏蔽#define EXTINT0(0x56000088)//外部中断方式#define INTMSK(0x4A000008)//中断屏蔽/*******************end add***********************/在dm9000.C中dm9000_probe(struct platform_device*pdev)中适当位置(设置MAC之后,register_netdevice()之前)添加如下代码:/***********beelike add********/for(i=0;i<6;i++){ndev->dev_addr[i]=net_mac_addr[i];}extint0=ioremap_nocache(EXTINT0,4);//intmsk=ioremap_nocache(INTMSK,4);eintmsk=ioremap_nocache(EINTMASK,4);s3c2410_gpio_cfgpin(S3C2410_GPF7,S3C2410_GPF7_EINT7);writel(readl(extint0)&0x8fffffff,extint0);//eint7 low levelwritel(readl(intmsk)&(~(1<<4)),intmsk);//writel(readl(extint0)&(~(1<<7)),extint0);iounmap(intmsk);iounmap(extint0);

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发46iounmap(eintmsk);/******************end*********/编译下载之后,启动内核后:图4.6目标板IP配置图图4.7网络连接测试图4.4.3 Dm9000驱动简要分析1.定义DM9000的platform_device,并为platform_data分配资源。2.在实验平台的列表中增加platform_device这个数据结构。3.在DM9000.C中,重新指定该芯片的驱动程序static struct platform_driver dm9000_driver={.driver={.name=\emove=dm9000_drv_remove,.suspend=dm9000_drv_suspend,

兰州理工硕士论文47.resume=dm9000_drv_resume,};4.在内核中加载module_init(dm9000_init)这个初始化程序,用来注册DM9000的驱动。5.定义了board_info这个数据结构,其主要功能是存储和芯片相关的信息,包括占用资源的大小、如何实现读写操作等等。6.模块初始化函数最终将调用probe函数。这个函数完成的基本过程:(1)分配网络设备号ndev=alloc_etherdev(sizeof(struct board_info));(2)从内核中分配设备所需要的资源空间:db->addr_res=platform_get_resource(pdev,IORESOURCE_MEM,0);db->data_res=platform_get_resource(pdev,IORESOURCE_MEM,1);db->irq_res=platform_get_resource(pdev,IORESOURCE_IRQ,0);(3)在内核的映射中申请资源,并保存映射地址:db->addr_req=request_mem_region(db->addr_res->start,i,pdev->name);db->data_req=request_mem_region(db->data_res->start,iosize,pdev->name);db->io_addr=ioremap(db->addr_res->start,i);db->io_data=ioremap(db->data_res->start,iosize);(4)根据DM9000的数据宽度来设置读写数

据帧的指针。(5)现在复位芯片:dm9000_reset(db);db中已经包含了详细的芯片信息。(6)读取芯片ID号并判断是否为0x90000A46。(7)初始化以太网ndev:ether_setup(ndev);(8)设置ndev的基本操作:ndev->open=&dm9000_open;ndev->hard_start_xmit=&dm9000_start_xmit;ndev->tx_timeout=&dm9000_timeout;ndev->watchdog_timeo=msecs_to_jiffies(watchdog);ndev->stop=&dm9000_stop;ndev->get_stats=&dm9000_get_stats;ndev->set_multicast_list=&dm9000_hash_table;(9)添加中断响应程序,并配置好网络设备的MAC地址(10)将ndev记录于平台设备platform_dev中去。注册ndev。7.一旦probe正常的执行完,内核中注册好了eth0这个网络接口。在系统启动之后,配置eth0,这将引起ndev->open()调用。8.配置好eth0接口后,将网络设备连接好。具体的收发过程是这样的:协议层将

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发48用已经封装好上层协议数据skb_buffer调用dm9000_start_xmit(struct sk_buff*skb,struct net_device*dev)函数。发送函数流程:netif_stop_queue(dev)用于暂停上层收发数据。正在发送中的数据计数加1。重新使能接口:发送结束后DM9000产生中断,在中断函数中读取芯片相关寄存器判断的中断原因。如果是发送结束,则递减正发送包计数。9.接收过程:网络数据包到达,DM9000自动接收并存放在DM内部RAM中,产生中断。在中断处理中识别中断原因并调用接收处理函数dm9000_rx:读取芯片相关寄存器确认DM9000正确的收到一帧数据。申请skb_buffer,将数据从DM9000中拷贝到skb_buffer中。设置skb->dev=nev,skb->protocol=eth_type_trans(skb,dev)。然后把skb_buffer交给上层协议:netif_rx(skb);最后更新接口统计信息:db->stats.rx_packets++;收到包总数+1。4.5本章小结本章详细介绍了嵌入式系统中外部设备的驱动设计,这包括基于帧缓冲技术的LCD驱动、USB驱动以及DM9000网卡的驱动移植过程。在开发的过程中发现了驱动的多样性和复杂性,了解到驱动的移植比动手设计驱动本身来的更为快捷。

兰州理工硕士论文49总结与展望1工作总结本文对嵌入式系统和Linux操作系统的现状及发展情况进行了适当的介绍,之后讲解了嵌入式系统和Linux的基础知识,研究和分析了Bootloader和Linux内核移植的具体流程。详细介绍了实验平台的电路结构及部分外设的特点,并阐述了如何在该平台下进行内核和引导程序的移植,以及驱动程序的开发。本文的工作总结分为以下五点:(1)构建嵌入式系统开发平台,并在此基础上成功搭建了交叉开发环境,这位进一步的研究打下了扎实的基础。(2)分析了系统引导程序的具体工作原理及启动流程,详细研究了Uboot的结构和组织形式。最后将Uboot成功移植到本实验平台中。(3)重点论述了Linux操作系统的内部结构及工作原理,在此理论基础上,介绍了linux2.29.5内核在实验平台中的具体移植方法,并成功建立了YAFFS文件系统(4)详细介绍了Linux驱动程序的工作原理、核心结构和通信机制,以及不同类型设备中驱动程序的差异。(5)对USB驱动、LCD驱动、网络设备驱动进行了详细的分析和研究,并讲述了其驱动程序开发过程。根据USB的热插拔特性,实现USB设备的自动加载,并对USB驱动不稳定这一缺点进行了改进,最终实现了在实验平台上进行了USB驱动的开发。2展望在今后的工作中,本课题仍有很多需要改进的地方。例如:现在图形3D技术发展迅猛,在嵌入式系统开发中,特别是在消费电子方面,在LCD的显示驱动中如何实现3D技术是以后的开发研究的重点。在USB和网络设备驱动中,可以根据其中的共同点,建立起一个统一的模块。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发50参考文献[1]田泽.嵌入式系统开发与应用[M].北京:北京航空航天大学出版社出版发行,2005:p40-p48.[2]华清远见嵌入式

培训中心编著.嵌入式Linux系统开发[M].北京:人民邮电出版社,2009.3:p10-p60.[3]Jonatban Corbet著,Linux Device Drivers,Third Edition[M].北京:中国电力出版社,2005.11:p40-p48.[4]李俊编著.嵌入式Linux设备驱动开发详解[M].北京:人民邮电出版社,2008.3:p292-p301.[5]Karim Yaghmour著.O'Reilly Taiwan公司译.构建嵌入式Linux系统[M].北京:中国电力出版社,2004:p5-p30.[6]Christopher Hallinan.Embedded Linux Primer.(影印版).北京:人民邮电社,2008:p3-p35.[7]颜华.基于ARM的嵌入式Linux操作系统研究与移植[D].北京:北京工业大学,2007:p18-20.[8]Karim Yaghmour,Jon Master.Building Embedded Linux Systems.2rd[M].O'Reilly,2008:p68-p80.[9]Michael Barr,Anthony Massa.Programming Embedded Systems.(影印版)[M].南京:东南大学出版社,2007:p117-120.[10]ADI.ADSP-BF561 Blackfin Processor Hardware Reference[Z].2003[11]DAVICOM Semiconductor Inc.DM9000 A Ethernet Controller with GeneralProcessor Interface Data Sheet[M].2005.[12]三恒心科技编著.ARM9原理与应用设计[M].北京:电子工业出版社,2008.3:p161-p171.[13]徐千洋著.Linux C函数库参考手册[M].北京:中国青年出版社,2002:p70-p80.[14]范永开,杨爱林.Linux应用开发详解[M].北京:人民邮电出版社,2006:p2-p45.[15]韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社,2008:p3-p30.[16]MindShare,Inc著.USB系统体系[M].北京:中国电力出版社,2003.9.p165-170.[17]C.Pearson1,T.Giuma2,&A.Harris2。TRANSPARENT CONNECTIVITY FOREMBEDDED SYSTEM DESIGN[J].The Third International Multi-Conference onComputing in the Global Information Technology,2008.10.[18]熊明.基于嵌入式Linux的USB2.0 OTG IP驱动程序研究和设计[D].成都:电子科技大学,2009.5:p5-p7.

兰州理工硕士论文51[19]周辉.基于嵌入式Linux的人脸识别系统的研究[D].西安:长安大学,2009.5:p18-p23.[20]王丽伟.基于53C2440A和Linux的嵌入式存储设备驱动程序的研究与开发[D].青岛:青岛大学,2009.5:p5-p8.[21]马洪伟.Linux平台下PCI图像卡的驱动程序设计与研究[D].武汉:华中科技大学,2005.4:p22-p24.[22]Sonia Thakur,James M.Conrad.An Embedded Linux Based Navigation Systemfor an Autonomous Underwater Vehicle[J].IEEE,2007:p56-p58.[23]孙钟秀等编著.操作系统教程[M].北京:高等教育出版社,2000:p10-p15.[24]G.Anastasi and et al.”Understanding the real behavior of Mote and 802.11 ad hocnetworks:an experimental approach.”In Pervasive and Mobile Computin-g,Volume1,pp.212-240,2005.[25]A.R.Agnihotri,S.Ono,and P.H.Madden.”Recursive bisection placement:fengshui5.0 implementation details.”In International Symposium on PhysicalDsign,pp.210-220,2005.[26]吕京建,肖海桥.嵌入式处理器分类与现状,http://www.bol-system.com/:p1-p3.[27]张焕强.基于Linux的实时系统,2003 http://www-900.ibm.com.cn:p1-p3.[28]广州友善之臂计算机科技有限公司.mini2440[5].2007:5.[29]samsung.KgF1208芯片手册[s].2003:p8-p10.[30]赵威.SD存储卡的设计和实现[J].上海:上海交通大学,2007.2:17-20.[31]张纪坤,张小全等.嵌入式Linux系统开发技术详解-基于ARM〔M].北京:人民邮电出版社,2006:p104-p110.[32]杨延军.用busybox制作嵌入式Linux的文件系统[J].单片机与嵌入式系统应用,2005.4:p8-p10.[33]熊伟,董金明.嵌入式Linux中根文件系统的实现[J].电子测量技术,2007.7:p78-p80.[34]程科.嵌入式Linux设备驱动程序的设计与研究[D].成都:电子科技大学,2004.6:p19-p25,p26-p30.[35]张恒.基于ARMg处理器开发平台上USB总线的应用研发[D].西安:西安电子科技大学2007.1:p40-p50,p60-p70.[36]董志国,李式巨.嵌入式Linux设备驱动程序开发[J].计算机工程与设计,2006,p20(27).[37]Cypress Semiconductor Corporation.SL811HS Embeded USB Host/SlaveController Specification.2002[38]孟伟君,周利华.嵌入式Linux下基于CGI的文件上传下载的实现[J].计算机技术

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发52与发展.2006年第5期:p226-p228.[39]李亚锋.ARM嵌入式Linux设备驱动实例开发[M].北京:中国电力出版社.2008.7:p24-p34.[40]徐英慧,马忠梅等.ARM9嵌入式系统设计―基于S3C2410与Linux[M].北京:北京航空航天大学出版社.2007:p221-p224.[41]胡明庆等.操作系统教程与实验[M].北京.清华大学出版社.2007.1:p447-p456.[42]李亚峰.ARM嵌入式Linux系统开发从入门到精通[M].北京.清华大学出版社.2007.8:p110-p138.[43]赖于树.ARM微处理器与应用开发.北京.电子工业出版社.2007.8.p130-135[44]王文义,武华北.Linux中进程间信号通信机制的分析及其应用[J].北京:计算机工程与应用.2005:p4(3).[45]Kato,K;Yamamoto,T.;Hirota,T,and Mizuyama,M,”Embeded Linux Technologies toDevelop Mobile Phones for the Mainstream Market,”Consumer Communicationsand Networking Conference,2006.CCNC2006.2006 3rdIEEE Vol.2.pp.1045-1055,[46]冯国进.嵌入式Linux驱动程序设计从入门到精通[M].北京:清华大学出版社.2007:p146-p148.[47]邵长彬,李洪亮.用Busybox制作嵌入式Limix根文件系统[J].微计算机信息(嵌入式与SOC),2007,10-2(23):p48-p50.[48]何景波.基于Linux的嵌入式应用系统技术研究[D].太原:中北大学,2009.4:p22-p26.

兰州理工硕士论文53致谢时光如白驹过隙,一转眼三年的时间即将过去,回想起我的三年研究生生活,我感慨万千。这三年来,缑老师为我们提供了很好的学习条件和学习环境,使得我们能静下心来一门心思做学问。缑老师思维敏捷,眼光长远,善于发现问题的本质,在学习上给予了我们极大的启发和帮助。在缑老师的谆谆教诲下,我不仅学会了相应的专业知识,培养了独立思考的能力,更锻炼了我们的创新意识和学术探讨能力。在生活上他也一直给予我们无私的关怀,使得我们能全身心地投入到学习中。另外缑老师严谨的治学态度、雷厉风行的工作作风、宽于待人、正直无私的品格让我敬佩,而这些都是我今后工作和学习的榜样。在这里,我真诚的感谢缑老师,感谢您对我的严格要求,使我找到自己的奋斗目标。在此我还要感谢在三年的学习期间给我以很大帮助各位老师,正是由于你们的教导,我才能一步步走下去。同时我还要感谢我的舍友们和实验室的同学们,在课题的进行中多次都到你们的指导,为我提供了许多宝贵的意见,使得课题得以顺利进行。另外,我还要感谢我的家人,感谢他们对我的理解和支持,给我以前进的动力克服遇到的各种难题。

基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发54附录A攻读硕士学位期间发表论文[1]缑新科,滕永.基于ARM9的嵌入式Linux系统分析和移植.[J]甘肃科学学报(已录用待发表).

本文来源:https://www.bwwdw.com/article/5oi3.html

Top