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

2019-03-27 20:21

信模块,在调试的过程中,让这些模块完成调试信息的传送,这就是所谓的嵌入调试桩的方式。该方式的比较常见的就是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,所以可以在根文件系统的选择上采用压缩率较好


基于ARM9的嵌入式Linux系统研究及设备驱动程序的开发(兰州理工(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:初中英语起始阶段教学的思考与策略

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: