全国高校ARM嵌入式教学及科研师资高级培训班讲稿.ppt
2004全国高校ARM嵌入式教学及科研师资高级培训班讲稿 基于ARM和uClinux的开发,2023/6/16,主讲:刘尚军,华中科技大学 武汉创维特,2,提纲,1,3,2,4,5,uClinux简介,uClinux驱动程序设计,uClinux内核移植,uClinux开发过程,6,7,第八章 基于ARM和uClinux的开发,uClinux上的图形系统,uClinux开发环境建立,uClinux应用程序设计,3,uClinux,uClinux简介,Linux与UNIX系统兼容,开放源代码。,Linux原本被设计为桌面系统,现在广泛应用于服务器领域。而更大的影响在于它正逐渐应用于嵌入式设备。uCLinux可以说是最早的嵌入式Linux发行版本。它是为没有MMU的处理器而设计的,进而发展了一个完整的开发平台,包括编译、调试等工具。,在uCLinux这个英文单词中u表示Micro,小的意思,C表示Control,控制的意思,所以uCLinux就是Micro-Control-Linux,字面上的理解就是“针对微控制领域而设计的Linux系统”。,在uCLinux的主页www.uclinux.org上有相关发行版本的源代码、编译工具等下载。JX44B0教学系统采用最新的uCLinux发行版本20040408,4,uClinux,uClinux简介,uClinux继承了linux的大多数特性:开源免费高度可裁剪:通常内核小于 512KBytes,文件系统可从几十KBytes到几Mbytes不等,视应用程序大小而定。,许多linux的应用程序和驱动程序可以直接或者经过很小改动就可以在uClinux上运行,5,uClinux与linux的区别 内存管理,uClinux简介,uClinux运行于没有MMU的处理器上,使用平坦式(flat)内存管理模式,虚拟内存到物理内存是一对一的映射关系,6,uClinux与linux的区别 fork与vfork,uClinux简介,uClinux的多进程管理只能通过vfork来实现,vfork使父进程锁定直到子进程exec()或者exit(),7,uClinux与uC/OS-II的区别 功能性,uClinux简介,uClinux来源于linux,包含一整套的编译、调试等开发工具、内核源代码、各种文件系统、图形接口、各种协议、驱动程序以及丰富的应用程序。,而uC/OS-II确切的来说只是一个微内核,仅仅包含多任务调度、简单内存管理等基本的多任务操作系统元素,且多任务调度算法和内存管理等都比较简单。对于想实现GUI、FS、协议等都必须另外购买或者移植,对于设备驱动程序没有提供专门统一的接口。,8,uClinux与uC/OS-II的区别 开发工具,uClinux简介,uClinux发布中包含了编译器和调试器等工具,它们都采用GCC编译器,汇编语法一致。,uC/OS-II没有指定编译器,在不同的平台下使用该平台下的编译器,而各个编译器,其汇编语法不同,因此,在不同类型平台下,汇编程序不一致。,9,uClinux与uC/OS-II的区别 开发资源,uClinux简介,在开发上,uClinux与linux采用相同的API调用,接口文档齐全,书籍、网上资源也比较多。,uC/OS-II虽没有标准的API接口,但是其内核非常简单、简洁,且书籍、网上资源也非常丰富。,10,uClinux与uC/OS-II的区别 移植性,uClinux简介,uClinux发布中包含了多种平台下的移植,可以通过配置内核选择体系结构和裁剪内核。,uC/OS-II的不同平台下的移植通过不同的移植代码独立发布,没有一个统一的界面,通过宏定义进行内核裁剪。,11,uClinux与uC/OS-II的区别 实时性,uClinux简介,uClinux内核不关心实时性问题,可以通过和RTLinux配合来实现实时。RTLinux处理实时任务,非实时任务由linux完成RTLinux是为linux提供实时性的方法,同样也适用于uClinux。通过RTLinux的patch,可以满足uClinux对实时性的需求,uC/OS-II采用占先式内核,实时性好,12,uClinux映像(image)文件结构,uClinux开发过程,uClinux映像由内核(kernel)和文件系统(fs)组成。,可以将kernel和fs统一编译到一个映像(image)文件中,也可以将kernel和fs独立地放置于不同的映像文件中(烧写到FLASH的不同区域),这需要通过修改Makefile文件和内核中的文件系统加载代码实现。,JX44B0中kernel和fs编译在一起。,uClinux支持压缩核心(zImage),它是对原核心映像文件(linux.bin)进行压缩,并在压缩后的文件头部添加一段解压缩代码。在该程序运行时,先运行这段解压缩代码将程序解压缩到uClinux核心运行地址,完成后,跳转到核心运行。,13,uClinux内核组成,uClinux开发过程,初始化程序段(init段)约32KBytes。,数据段(data)50100KBytes左右。,代码段(text)300KBytes左右,如果kernel和fs编译在一起,内核映像还包含文件系统(romfs)80KBytes,未初始化数据段(bss)100150KBytes左右。,14,uClinux开发步骤,uClinux开发过程,BOOTLOADER开发,uClinux开发环境建立,uClinux内核移植,应用程序开发,15,支持uClinux开发的BOOTLOADER,uClinux开发过程,引导uClinux,烧写uClinux内核映像和文件系统,初始化硬件,16,GNU交叉编译,uClinux开发环境建立,uClinux采用GNU交叉编译器,GNU的交叉编译器,包括以下组件:1.Gcc交叉编译器,即在宿主机上开发编译目标上可运行的二进制文件;2.Binutils辅助工具,包括objdump、objcopy等;3.Gdb调试器。,对于ARM可以采用如下两个版本的编译器:arm-elf-arm-linux-,17,arm-elf-交叉编译器(推荐使用),uClinux开发环境建立,arm-elf-gcc,arm-elf-ld,arm-elf-as,arm-elf-objdump,arm-elf-objcopy,arm-elf-gdb,18,arm-linux-交叉编译器,uClinux开发环境建立,arm-linux-gcc,arm-linux-ld,arm-linux-as,arm-linux-objdump,arm-linux-objcopy,arm-linux-gdb,19,选择uClinux开发环境,uClinux开发环境建立,Windows环境+Cygwin,Windows环境+VMWare虚拟机(安装RedHat 9.0),Linux环境,推荐RedHat 9.0,单机模式(一台计算机),双机模式(两台计算机),Windows+Linux,20,在linux环境下进行uClinux开发,uClinux开发环境建立,必须采用支持GDB的调试器(如ADT1000A)才能进行调试,否则只能通过BOOTLOADER进行简单的程序烧写运行等,调试信息的打印可以通过串口完成,使用linux下的minicom超级终端程序(类似于Windows上的超级终端工具)接收并显示目标板传送的打印信息,uClinux的程序编辑、编译、调试都在Linux环境进行,uClinux串口驱动完成后,可以通过内核打印函数printk向串口打印信息,这是uClinux内核调试过程中最有效的手段,21,在Windows+Cygwin环境下进行uClinux开发,uClinux开发环境建立,uClinux内核配置和编译等在Cygwin环境下运行,程序编辑和调试都在Windows环境下进行,必须采用支持Windows下进行linux调试的调试器(如ADT1000A)才能进行调试,否则只能通过BOOTLOADER进行简单的程序烧写运行等,调试信息的打印可以通过串口完成,使用Windows上的超级终端工具接收并显示目标板传送的打印信息,Cygwin是运行于Windows中的一个应用程序,它可以使得Linux环境下的应用程序可以在Cygwin环境下进行编译,即可以在Windows进行编译。,22,在Windows+VMWare虚拟机环境下进行uClinux开发,uClinux开发环境建立,如果需要使用只支持Windows环境下调试的调试器,可以通过在VMWare中安装linux虚拟机,在该虚拟机中进行编辑、编译uClinux,然后通过网络(ftp、nfs、ssh)等手段传送到Windows中,进行调试,这样编译和调试可以分别在linux和windows环境下但是是在一台电脑中完成,它的缺点是系统要求较高,运行速度慢。,也可以在两台电脑中分别安装linux和windows,分别实现编译和调试。,VMWare是运行于Windows中的一个应用程序,是一个虚拟机,可以在其上安装多个操作系统,相当于在Windows上安装一个虚拟的操作系统。,23,在linux环境下建立uClinux开发环境,uClinux开发环境建立,下载并安装uClinux源代码,安装编译器,24,安装编译器,uClinux开发环境建立,在Linux控制台下执行以下命令:sh arm-elf-tools-20030314.sh,JX44B0采用arm-elf-tools交叉编译环境arm-elf-tools-20030314.sh,该工具可以从www.uclinux.org/pub/uClinux/arm-elf-tools/上下载。,安装完成后,键入arm-elf-gcc,如果能看到下面的输出信息:Reading specs from/usr/local/lib/gccspecsgcc version 2.95.3 20010315(release)(ColdFire patches-20010318 from http:/XIP and shared lib patches from http:/,25,下载并安装uClinux源代码,uClinux开发环境建立,JX44B0的uCLinux发行文件为uClinux-dist-jx44b0.tar.gz,在linux下将该文件拷贝到/home/cvtech/jx44b0目录下,然后在该目录下执行:tar zxvf uClinux-dist-jx44b0.tar.gz,当tar程序运行完毕后,在/home/cvtech/jx44b0目录下会有一个uClinux-dist的新目录,这个目录就是uClinux的源码根目录,里面有进行uClinux开发的所有的源代码。,在uCLinux的主页www.uclinux.org上有相关发行版本的源代码、编译工具等下载。JX44B0采用最新的uCLinux发行版本20040408。,也可以从网上下载uClinux-dist发行版本,然后解压。,26,uClinux内核移植,uClinux内核移植,uCLinux内核的移植可以分为板级移植和片级移植。,对于uCLinux发行版本中已经支持的CPU通常只需要针对板级硬件进行适当的修改即可,这种移植叫做板级移植。,而对于uCLinux发行版本中没有支持的CPU则需要添加相应CPU的内核移植,这种移植叫做片级移植。,片级移植相对板级移植来说要复杂许多,JX44B0采用的uCLinux 20040408发行版本中已经包含S3C44B0X ARM7TDMI处理器的移植包,因此,只需要在其上进行uCLinux板级移植的基本过程和方法。,27,uClinux发行版本的目录结构,uClinux内核移植,28,uClinux内核的目录结构,uClinux内核移植,29,uClinux内核的arch目录,uClinux内核移植,与架构和平台相关的源代码都放在arch目录下,对于ARM的uClinux,包含于arch目录下的armnommu子目录中。,30,uClinux内核的arch目录,uClinux内核移植,当使用压缩核心时,boot目录下包含压缩和解压核心的源代码和Makefile文件。,kernel目录的entry-armv.S中为未压缩内核的起始执行文件,内核从其第一条指令处执行。,vmlinux.lds文件为核心的连接脚本文件,压缩核心解压后必须解压缩到该文件指定的地址。,31,uClinux内核移植,uClinux内核移植,配置内核,编译内核,下载、运行、调试内核,32,配置uClinux内核,uClinux内核移植,make config,make menuconfig,make xconfig,33,make config,uClinux内核移植,34,make menuconfig,uClinux内核移植,35,make xconfig,uClinux内核移植,36,uClinux常用配置选项,uClinux内核移植,系统及其存储器配置,网络支持,显示器支持,触摸屏支持,37,系统及其存储器配置,uClinux内核移植,在System Type菜单中中进行配置,包括大小端设置,但是ARM中许多uClinux发布并没有进行大端版本移植,因此,选择大端时要特别注意,存储器配置,包括SDRAM、FLASH地基地址和大小,内核执行方式,从RAM执行还是从FLASH执行,板级包的选择,38,网络支持,uClinux内核移植,在Networking options以及Network device support中进行配置,39,网络支持,uClinux内核移植,在Network device support配置中,添加选项Network device support,并在Ethernet(10 or 100Mbit)中选择Cirrus Logic CS8900A support,如下图两个图所示,40,显示器支持,uClinux内核移植,在Character devices以及Console drivers中进行配置。在Character devices配置中,添加选项Virtual terminal配置,如下图所示。,41,显示器支持,uClinux内核移植,在Console drivers中添加Support Frame buffer devices配置,42,触摸屏支持,uClinux内核移植,在Character devices的Mice子菜单中进行配置,43,编译uClinux内核,uClinux内核移植,建立依赖关系make dep,编译内核,make 编译内核make zImage 编译压缩核心(zImage)编译生成地uClinux映像文件通常保存在uClinux-dist/images目录下,44,下载、运行和调试内核,uClinux内核移植,通过调试器下载内核并运行,通过BOOTLOADER下载内核到SDRAM中运行,通过BOOTLOADER将内核烧写到FLASH中,然后运行uClinux,45,uClinux调试手段,uClinux内核移植,在uClinux开发中,由于可能没有标准键盘和显示器支持,因此,通常通过串口将显示信息发送到主机,由主机端超级终端工具接收,以完成显示功能。同时在超级终端中可以输入数据,然后由uClinux接收,以完成标准键盘功能。,调试过程中也可以通过串口将调试信息打印到超级终端,这是uClinux最有效和最简单的方法。,46,uClinux内核移植主要过程1,uClinux内核移植,对于板级移植,内核移植主要包括如下几个部分:,内核配置,包括板级包配置,如S3C44B0X-MBA44,体系结构相关代码修改,根据板级包的配置,修改相应的体系结构相关代码,包括:压缩核心启动代码:linuxarmnommu/boot/内核启动代码:linuxarmnommu/kernel/板级相关代码:linuxarmnommu/mach-S3C44B0X/,连接脚本核心连接脚本:linuxarmnommu/vmlinux.lds压缩核心连接脚本:linuxarmnommu/boot/compressed/linux.lds,47,uClinux内核移植主要过程2,uClinux内核移植,加载文件系统romfs,编写驱动程序驱动程序目录:linux网卡驱动程序:linuxLCD驱动程序:linux触摸屏驱动程序:linux,中断处理在JX44B0中,uClinux内核在SDRAM中运行,其中断向量表0 x0c000020处,因此在BOOTLOADER中必须将中断向量表正确导入到该处地址。,48,uClinux启动过程1,uClinux内核移植,核心打印信息,LCD显示初始化,触摸屏初始化,49,uClinux启动过程2,uClinux内核移植,加载文件系统,执行文件系统中的脚本/etc/rc,网卡驱动加载,50,uClinux启动过程3,uClinux内核移植,uClinux控制台,51,uClinux文件系统,uClinux内核移植,文件系统指文件存在的物理空间。在Linux系统中,每个分区都是一个文件系统,都有自己的目录层次结构。,Linux的最重要特征之一就是支持多种文件系统,这样它更加灵活,并可以和许多其它种操作系统共存。,Virtual File System(虚拟文件系统)使得Linux可以支持多个不同的文件系统。由于系统已将Linux文件系统的所有细节进行了转换,所以Linux核心的其它部分及系统中运行的程序将看到统一的文件系统。,Linux的虚拟文件系统允许用户同时能透明地安装许多不同的文件系统。虚拟文件系统是为Linux用户提供快速且高效的文件访问服务而设计的。,52,常用uClinux文件系统,uClinux内核移植,Linux系统核心可以支持十多种文件系统类型:JFS、ext、ext2、ext3、ISO9660、XFS、Minx、MSDOS、UMSDOS、VFAT、NTFS、HPFS、NFS、SMB、SysV、PROC、romfs等。,53,romfs文件系统,uClinux内核移植,romfs文件系统是一个精简的、只读文件系统。相对于一般的ext2文件系统要求更少的空间。,其空间的节约来自于两个方面:首先内核支持romfs文件系统比支持ext2文件系统需要更少的代码。其次romfs文件系统相对简单,在建立文件系统超级块(superblock)时需要更少的存储空间。,romfs文件系统不支持动态擦写保存,对于系统需要动态保存的数据采用虚拟ram盘的方法进行处理(ram盘将采用ext2文件系统)。目前所有的内核(2.4和2.5)都支持romfs,但是在一些linux发布中可能缺省没有将其编译进来。虽然如此,在嵌入式的特殊需求中,仍然被广泛应用。jx44b0 uCLinux系统采用romfs文件系统 ext2 ram盘。,54,编译uClinux文件系统,uClinux内核移植,配置文件系统,编译文件系统源代码,生成uClinux文件系统,生成romfs文件系统映像,编译romfs文件系统映像到内核中或者写到固定位置并由内核从该位置加载,55,uClinux文件系统相关文件和目录,uClinux内核移植,应用程序源代码:uClinux-dist/user,编译生成的uClinux文件系统:uClinux-dist/romfs,相关的脚本文件:uClinux-dist/vendors/Samsung/44b0 xinittabmotdpasswdrcMakefile,56,标准C库,uClinux内核移植,uC-libc,uClibc,可以配置,57,uClinux文件系统配置1,uClinux内核移植,在uClinux-dist目录下运行菜单配置:make menuconfig,选择Kernel/Library/Defaults Selection,58,uClinux文件系统配置2,uClinux内核移植,在Kernel/Library/Defaults Selection中选择Customize Vendors/User Settings(NEW),选择配置文件系统,然后保存、退出,59,uClinux文件系统配置3,uClinux内核移植,文件系统配置菜单,可以通过菜单进行文件系统的裁减,60,uClinux文件系统编译,uClinux内核移植,直接在uClinux-dist目录下make将编译内核和文件系统。,make user_only编译文件系统。,编译生成的文件系统位于uClinux-dist/romfs,也就是说uClinux文件系统成功加载后,其根目录和uClinux-dist/romfs一致。,编译生成的文件系统需要通过genromfs命令生成romfs文件系统映像。,romfs映像可以和内核一起编译或者由内核从指定位置加载。,61,uClinux内核移植的若干问题1,uClinux内核移植,源程序阅读问题1,uClinux内核源代码非常多,且结构复杂,uClinux内核有接近10000个文件,4000000行代码。,因此,阅读uClinux时必须借助一些工具Source insightUltraedit等,uClinux内核使用GNU C,它在ANSI C基础上进行了一些扩充,因此在许多编程习惯上与ANSI C不同。,大量使用宏定义,且许多宏定义非常复杂,这也在一定程度上增加了难度。,62,uClinux内核移植的若干问题1,uClinux内核移植,源程序阅读问题2,uClinux中并不是所有代码都编译进去,对于一个体系结构,只有很少部分的代码参与编译,因此,必须掌握uClinux发布中各目录的意义才能进一步清楚是否参与编译。,还可以通过查看.o文件的方式查看当前参与编译的是哪个文件,通常xxx.c文件生成的目标文件为xxx.o,只有生成了.o的文件才参与编译,注意:这适合于大部分情况,但是不是绝对的。,uClinux中大量使用条件编译,阅读代码时需要弄清楚,到底哪部分代码参与编译。#ifdef xxx#elif#endif,63,uClinux内核移植的若干问题2,uClinux内核移植,GNU C,从C+中吸收了inline和const等关键字。,ANSI C代码与GNU C中的保留关键字冲突通过双下划线(_)解决:如inline等价于_inline_、asm等价于_asm_,结构体的初始化,64,uClinux内核移植的若干问题2,uClinux内核移植,GNU C结构体初始化,结构体声明,ANSI C结构体初始化,必须按顺序,GNU C结构体初始化,无需按顺序,65,uClinux应用程序,uClinux应用程序设计,编写程序,编写Makefile文件,编译,运行,66,编写Makefile文件,uClinux应用程序设计,67,uClinux应用程序运行1,uClinux应用程序设计,应用程序运行可以采用如下两种方式:在uClinux内核启动起来,并且有办法从主机获取文件时,可以在uClinux控制台直接从主机获取编译后的应用程序。可以通过ftp、nfs、ssh等方式达到。也可以在编译应用程序后将该应用程序拷贝到uClinux-dist/romfs中,然后重新调用genromfs生成romfs映像文件并重新编译内核,然后下载运行新的内核,此时文件系统已经更新。,68,uClinux应用程序运行2,uClinux应用程序设计,uClinux应用程序必须编译成平坦格式的(flat),通过连接参数-Wl,-elf2flt完成。,69,uClinux应用程序运行3,uClinux应用程序设计,重新编译内核时,通常将应用程序添加到uClinux文件系统的bin目录,该目录有全局路径。且该文件应该具有执行属性,可以通过如下命令修改:chmod 777 leddemo在新内核启动后,直接在命令行输入文件名即可运行。,当直接在uClinux控制台中从主机上获取应用程序时,必须保存到可写的位置,比如JX44B0中的ram盘中:/var目录下,而不能保存到只有只读属性的/bin里面,也必须修改其具有执行属性,且通过如下命令执行该程序:./leddemo,70,配置uClinux应用程序启动后自动运行,uClinux应用程序设计,如果需要在系统启动以后自动运行leddemo程序,需要编辑romfs中的启动脚本文件,该文件为uClinux-dist/romfs/etc/rc使用vi编辑器编辑,在该文件最后添加如下脚本:/bin/leddemo该脚本将启动后运行leddemo,直到程序退出。或/bin/leddemo&它将在后台运行leddemo,不影响其他的程序运行。,71,linux驱动程序,uClinux驱动程序设计,Linux下对外设的访问只能通过驱动程序进行,Linux具有统一的驱动程序接口,以文件操作的方式管理驱动程序,如:open、read、write、ioctl,驱动程序是内核的一部分,可以使用中断、DMA等操作,驱动程序需要在用户态和内核态之间传递数据,72,uClinux驱动程序,uClinux驱动程序设计,uClinux没有屏蔽应用层对外设的直接访问,可以在用户态直接进行如下操作:*(unsigned char*)0 x02000006)=0 x3e;,uClinux下用户态无法处理中断,uClinux下对外设的访问推荐采用驱动程序进行,在内核态编写驱动程序(包括直接对外设操作、处理中断等),用户态通过标准驱动程序调用方法进行操作。,73,uClinux驱动程序编译方式,uClinux驱动程序设计,Linux中驱动程序的使用可以按照两种方式编译:一种是静态编译进内核另一种是编译成模块以供动态加载,由于uClinux不支持模块动态加载,而且嵌入式Linux不能够象桌面Linux那样灵活的使用insmod/rmmod加载卸载设备驱动程序,因而通常在uClinux中将设备驱动程序静态编译进内核。,74,uClinux下设备驱动程序分类,uClinux驱动程序设计,字符设备:是指存取时没有缓存的设备。典型的字符设备包括鼠标,键盘,串行口等。,块设备:块设备的读写都有缓存来支持,并且块设备必须能够随机存取(randomaccess)。典型的块设备主要包括硬盘软盘设备,CD-ROM等。,网络设备:Linux的网络系统主要是基于BSDunix的socket机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据的传递。系统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。,75,uClinux下设备驱动程序组成,uClinux驱动程序设计,自动配置和初始化子程序:负责检测所要驱动的硬件设备是否存在和是否能正常工作。如果该设备正常,则对这个设备及其相关的、设备驱动程序需要的软件状态进行初始化。这部分驱动程序仅在初始化的时候被调用一次。,服务于I/O请求的子程序:调用这部分是由于系统调用的结果。这部分程序在执行的时候,系统仍认为是和进行调用的进程属于同一个进程,只是由用户态变成了核心态,具有进行此系统调用的用户程序的运行环境,因此可以在其中调用sleep()等与进程运行环境有关的函数。,中断服务子程序:,76,uClinux下设备驱动程序I/O设备入口点1,uClinux驱动程序设计,在系统内部,I/O设备的存取通过一组固定的入口点来进行,这组入口点是由每个设备的设备驱动程序提供的。一般来说,字符型设备驱动程序能够提供如下几个入口点:,open:打开设备准备I/O操作。对字符特别设备文件进行打开操作,都会调用设备的open入口点。open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态。,close:关闭一个设备。当最后一次使用设备终结后,调用close子程序。独占设备必须标记设备可再次使用。,Read:从设备上读数据。对于有缓冲区的I/O操作,一般是从缓冲区里读数据。对字符特别设备文件进行读操作将调用read子程序。,77,uClinux下设备驱动程序I/O设备入口点2,uClinux驱动程序设计,write:往设备上写数据。对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。对字符特别设备文件进行写操作将调用write子程序。,ioctl:执行读、写之外的操作。,select:检查设备,看数据是否可读或设备是否可用于写数据。select系统调用在检查与设备特别文件相关的文件描述符时使用select入口点。如果设备驱动程序没有提供上述入口点中的某一个,系统会用缺省的子程序来代替。对于不同的系统,也还有一些其它的入口点。,78,uClinux下设备注册1,uClinux驱动程序设计,设备驱动程序所提供的入口点,在设备驱动程序初始化的时候向系统进行登记,以便系统在适当的时候调用。Linux系统里,通过调用register_chrdev向系统注册字符型设备驱动程序。register_chrdev定义为:#include#include int register_chrdev(unsigned int major,const char*name,struct file_operations*fops);,其中,major是为设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态地分配一个主设备号。name是设备名。fops是该驱动各个的入口点的文件操作结构指针。,79,uClinux下设备注册2,uClinux驱动程序设计,此函数返回0表示成功。返回-EINVAL表示申请的主设备号非法,一般来说是主设备号大于系统所允许的最大设备号。返回-EBUSY表示所申请的主设备号正在被其它设备驱动程序使用。如果是动态分配主设备号成功,此函数将返回所分配的主设备号。如果register_chrdev操作成功,设备名就会出现在/proc/devices文件里。,初始化部分一般还负责给设备驱动程序申请系统资源,包括内存、中断、时钟、I/O端口等,这些资源也可以在open子程序或别的地方申请。在这些资源不用的时候,应该释放它们,以利于资源的共享。,80,uClinux下中断处理,uClinux驱动程序设计,在Linux系统里,对中断的处理是属于系统核心的部分,因此如果设备与系统之间以中断方式进行数据交换的话,就必须把该设备的驱动程序作为系统核心的一部分。设备驱动程序通过调用request_irq函数来申请中断,通过free_irq来释放中断。,81,uClinux下内存分配、释放,uClinux驱动程序设计,作为系统核心的一部分,设备驱动程序在申请和释放内存时不是调用malloc和free,而代之以调用kmalloc和kfree,它们被定义为:#include void*kmalloc(unsigned int len,int priority);void kfree(void*obj);参数len为希望申请的字节数,obj为要释放的内存指针。priority为分配内存操作的优先级,即在没有足够空闲内存时如何操作,一般用GFP_KERNEL。,82,uClinux下内存分配、释放,uClinux驱动程序设计,使用一个没有申请的I/O端口不会使CPU产生异常,也就不会导致诸如“segmentation fault”一类的错误发生。任何进程都可以访问任何一个I/O端口。此时系统无法保证对I/O端口的操作不会发生冲突,甚至会因此而使系统崩溃。,因此,在使用I/O端口前,应该检查此I/O端口是否已有别的程序在使用,若没有,再把此端口标记为正在使用,在使用完以后释放它。int check_region(unsigned int from,unsigned int extent);void request_region(unsigned int from,unsigned int extent,const char*name);void release_region(unsigned int from,unsigned int extent);,83,uClinux下开关中断函数,uClinux驱动程序设计,在设备驱动程序里,通过如下函数实现打开和关闭中断功能:#include#define cli()_asm_ _volatile_(cli:)#define sti()_asm_ _volatile_(sti:),84,uClinux下用户态和核心态数据访问,uClinux驱动程序设计,在设备驱动程序里,还可能会用到如下的一些系统函数:#include void memcpy_fromfs(void*to,const void*from,unsigned long n);void memcpy_tofs(void*to,const void*from,unsigned long n);,在用户程序调用read、write时,因为进程的运行状态由用户态变为核心态,地址空间也变为核心地址空间。而read、write中参数buf是指向用户程序的私有地址空间的,所以不能直接访问,必须通过上述两个系统函数来访问用户程序的私有地址空间。memcpy_fromfs由用户程序地址空间往核心地址空间复制,memcpy_tofs则反之。参数to为复制的目的指针,from为源指针,n为要复制的字节数。,85,uClinux下设备驱动程序举例,uClinux驱动程序设计,模块加载,设备初始化,设备入口点实现,86,静态编译驱动程序进内核,uClinux驱动程序设计,87,设备初始化,uClinux驱动程序设计,88,设备入口点实现,uClinux驱动程序设计,89,嵌入式GUI需求,uClinux上的图形系统,随着手持式设备的硬件条件的提高,嵌入式系统对轻量级GUI的需求越来越迫切。,近来的市场需求显示,越来越多的嵌入式系统,包括PDA、机顶盒、DVD/VCD播放机、WAP 手机等等系统均要求提供全功能的Web浏览器。这包括HTML 4.0的支持、JavaScript的支持,甚至包括Java虚拟机的支持。而这一切均要求有一个高性能、高可靠的GUI的支持。,另外,在工业实时控制系统中对GUI的要求也越来越高。目前许多这类系统采用比较简单的手法实现GUI。但是,在出现Linux系统之后,许多工业控制系统开始采用Linux作为操作系统,并在其上加入GUI实现。,90,嵌入式GUI的基本要求,uClinux上的图形系统,小型、占用资源少,高性能,高可靠性,可配置,91,Linux下的GUI,uClinux上的图形系统,紧缩的X Window系统,MiniGUI,MicroWindows,OpenGUI,QT/Embedded,92,Linux下的GUI X Window,uClinux上的图形系统,X Window是Linux以及其他类UNIX系统的标准GUI。,X Window系统采用标准的客户/服务器体系结构,具有可扩展性好、可移植性好等优点。但该系统的庞大、累赘和低效率也是大家所共知的。,为了获得应用程序的可移植性,许多厂家都试图通过对X Window系统的紧缩开发,使之能够在嵌入式系统上运行。国外已经开发出了大小约为800K的X服务器。这对西方国家来说基本能够满足嵌入式系统的需求了。但该系统的源代码尚不开放,从而很难进行本地化开发。,93,Linux下的GUI MicroWindows,uClinux上的图形系统,MicroWindows是一个开放源码的项目,目前由美国一家公司在主持开发。该项目的开发非常活跃,国内也有人参与了其中的开发,并编写了GB2312等字符集的支持。,该项目的主要特色在于提供了比较完善的图形功能,包括一些高级的功能,比如Alpha混合,三维支持,TrueType字体支持等。但作为一个窗口