移植:
广义上讲移植包括软件移植和硬件移植。从狭义上讲,移植就是指软件移植,即将一个软件从一个平台迁移到另一个与其不同的平台上工作。
通常移植分为以下三种情况:
1:从一个硬件平台移植到另一个硬件平台
2:从一个操作系统移植到另一个操作系统
3:从一种软件库环境移植到另一个软件库环境
Bootloader的移植:
Bootloder是操作系统和硬件的纽带,它负责初始化硬件,引导操作系统内核,检测各种参数给操作系统内核使用。
一个功能强大的Bootloader就相当于一个小型的操作系统。
在嵌入式领域中,操作系统移植的关键在于Bootloader的移植以及操作系统内核与硬件相关部分的移植。
VIVI的移植:
1:VIVI顶层Makefile文件的修改。
VIVI作为Linux系统的启动代码,在编译配置时需要用到函数库,包括交叉编译库和头文件,交叉编译开关选项设置,
还包括Linux内核代码中的库和头文件,所以。通常需要修改VIVI工程管理文件Makefile
2:VIVI中与硬件相关的初始化:
与具体运行在哪一个处理器平台上相关的文件都存放在VIVI/arch/目录下,对于S3c2410X处理器,
对应的目录为s3c2410.其中的head.s文件是VIVI启动配置代码,加电复位运行的代码就是从这里开始的。
3:对不同Flash启动的修改:
VIVI能从Nor flash或者Nand flash启动,因此启动程序,linux内核及根文件系统,
甚至还包括图形用户界面都需要存放在nor flash或nand flash中。
4:内核启动参数设置:
经过修改后,开发板可以从nand flash或 nor flash中启动,所以相应地也要修改启动命令。
5:Flash驱动的实现:
移植VIVI的最后一步就是实现Flash驱动,程序员需要根据自己系统中具体Flash芯片型号及配置来修改驱动程序,
使Flash设备能够在嵌入式系统中正常工作。
Bootloader的交叉编译:
为了进行交叉编译,需要修改Bootloader目录下的Makefile文件,将其中的编译器由gcc改为交叉编译器arm-linux-gcc。
然后再使用make命令,系统自动完成整个编译。
Bootloader的下载:
Bootloader的下载时利用JTAG口进行的,操作平台可以是Windows或桌面Linux,只是两者使用的工具或软件不同而已。
嵌入式linux内核的移植:
内核是嵌入式Linux的核心部分,因为Linux与Windows不同,前者的内核和文件系统,图形用户系统可以分开,
它们的开发,移植,下载甚至运行都可以是分开的。内核的移植是一个比较复杂的任务,也是嵌入式系统开发中非常重要的一个过程。
内核移植一般包括内核配置,内核编译和内核下载3大步骤。
移植内核首先要准备好编译内核的编译器即交叉编译工具链,然后从相关的网站下载要移植的内核源代码
ARM9内核移植的准备和关键文件的修改:
1:设置目标平台和指定交叉编译器:在源代码的最上层根目录下的Makefile文件中,指定所移植的硬件平台,以及所使用的交叉编译器。
2:arch/arm目录下的Makefile修改:内核系统的启动代码是通过此文件产生的。
3:arch/arm目录下Config.in修改:Config.in文件是用来设置Menuconfig配置菜单的,他们是一一对应关系。
这里把嵌入式目标板的CPU平台加在相应的地方,这样在配置Linux内核时就能够选择是否支持该平台了。
4:arch/arm/boot目录下Makefile修改:编译出来的内核存放在改目录下。这里用来指定内核解压到实际硬件内存系统中的物理地址。
一般如果内核无法正常启动,很可能是这里的地址设置不正确。
5:arch/arm/boot/compressed目录下Makefile修改:该文件从vmlinux中创建一个压缩的vmlinuz镜像文件,
该文件中用到的SYSTEM,ZTEXTADDR,ZBSSADDR和ZRELADDR是从arch/arm/boot/Makefile文件中得到的。
6:arch/arm/boot/compressed目录下添加head-s3c2410.s
7:arch/arm/def-configs目录:这里定义了一些平台的config文件,比如lart和assert等。把配置好的s3c2410的配置文件复制到这里即可。
8:arch/arm/kernel目录下Makefile修改:该文件主要用来确定文件类型的依赖关系
9:arch/arm/kernel目录下的文件debug-armv.s修改:如添加关闭外围设备的时钟,保证系统的正常运行。
10:arch/arm/kernel目录下的文件entry-armv.s修改:如添加CPU初始化时处理中断的汇编代码。
11:arch/arm/mm目录下的相关文件:此目录下的文件是和ARM平台相关的内存管理内容,只有mm-armv.s文件需要移植。
12:arch/arm/mach-s3c2410目录下的相关文件:高版本的linux内核才这个目录。内核对处理器的基本信息提供支持,有关开发板的外设
内核的配置与剪裁:
配置内核与剪裁是移植内核过程中很重要的一步,也是非常复杂的一步。
配置内核的目的是剪裁掉不必要的文件和目录,获得一个最简单的又能满足用户开发的操作系统,
以解除嵌入式开发过程中所遇到的存储空间有限的困扰。
通常有四种主要的配置内核的方法:
1make config
2make oldconfig
3make menuconfig
4make xconfig
内核的编译:
编译内核通常也需要几个步骤,一是清除以前编译通过的残留文件;二是编译内核image文件和可加载模块;三是安装模块。
在编译内核之前,可先参考内核目录下的README文件和Documentation/Changes文件,
其中README文件告诉我们通过的安装内核的方法,Changes文件主要告诉编译和运行内核需要的最低工具软件列表。
基本步骤:
1:make dep命令用在内核2.4或之前,用于建立源文件之间的依赖关系,在执行内核配置命令之后使用。
2:make clean命令用于删除前面留下来的中间文件,该命令不会删除.config等配置文件。
3:make zImage命令用于编译生成压缩形式的内核映像,编译成功后,就会在arm\arm\boot目录下生成zImage文件。
4:如果在配置菜单的过程中,有些选项被选则为模块的,即选项前为[M],并且在回答Enable loadable module support时选了"YES"的,
则接下来就还要用命令make modules来编译这些可加载模块,并用make modules_install将make modules生成的模块文件复制到相应目录。
5:如果是直接升级PC桌面Linux系统的内核,那么接下来还要用make install来安装新内核。
内核的下载:
1:启动终端工具,练好串口线,在开机后快速的按空格键,就进入到Bootloader的控制台命令下。
2:在Bootloader命令行下,向flash芯片中烧写kernel,等待烧写完成。
嵌入式Linux文件系统的移植:
:文件系统是Linux/UNIX系统的一个重要组成部分,也是操作系统正常工作时的必要组成部分,在启动时内核需要根文件系统来挂载和组织文件。
在目前的Linux操作系统中,内核代码映像文件保存在根文件系统中,
系统引导启动程序会从这个根文件系统设备上把内核执行代码加载到内核中去运行。
:在Linux中,用户能看到的文件空间是用一个单树状结构来组织的,根文件系统的最顶层称为root,
其下的每一个目录都有其具体的目的和用途,一般是根据FHS(文件系统层次结构标准)定义建立一个正式的文件系统结构的。
FHS是在UNIX/Linux操作系统的文件系统中是用于确定在何处存储何种文件的标准。
:常见的根文件系统有JFFS2,NSF,ext2等。
Linux下设备驱动程序的开发:
Linux驱动开发是嵌入式软件设计中的主要内容,也是嵌入式Linux移植中工作量最大的部分。
驱动程序概述:
设备驱动程序是应用程序与硬件之间的一个中间软件层,可以看作是一个硬件抽象层(HAL),为应用程序屏蔽了硬件细节。
在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。
在操作系统看来,设备驱动程序是内核的一部分,它主要实现的功能有:
对设备进行初始化和释放,吧数据从内核传送到硬件和从硬件读取数据;
读取应用程序传送给设备文件的数据,回送应用程序请求的数据以及检测和处理设备出现的错误。
设备类型分类:
linux操作系统下又3类主要的设备文件类型:字符设备,块设备,网络设备。字符设备和块设备的主要驱动在于是否使用了缓冲技术。
1:字符设备
字符设备和普通文件之间有主要的区别。普通文件可以来回读/写,而大多数字符设备仅仅是数据通道,只能顺序读/写。
2:块设备
块设备是文件系统的物质基础,它也支持像文件一样被访问。
3:网络设备
网络设备是一个物理设备,如以太网卡,但软件也可以作为网络设备,典型的是回送设备(loopback).
设备驱动与文件系统的关系:
Linux通过设备文件系统对设备进行管理,各种设备都以文件的形式存放在/dev目录下,称为“设备文件”。
应用程序可以像普通文件一样打开,关闭和读/写这些设备文件。
为了管理这些设备,系统为设备编了号,每个设备号又分为主设备号和次设备号。
重要的数据结构和函数:
1.设备驱动中关键数据结构
设备驱动程序所提供的这组入口点由几个结构向系统进行说明,分别是file_operations数据结构,inode数据结构和file数据结构。
2设备驱动开发中的基本函数:
设备注册函数
内存操作函数
中断申请和释放函数
I/O端口操作
设备驱动程序所提供的入口点,在设备驱动程序初始化的时候向系统进行说明,以便系统在适当的时候调用。
同时,初始化部分一般还负责为设备驱动程序申请系统资源。
包括内存中断,中断,时钟,I/O端口等,当然这些资源也可以在open子程序或别的地方申请。
在这些资源不用的时候,应该释放他们,以利于资源的共享。
字符设备驱动程序的组成
1:驱动程序的注册和注销:
设备驱动程序通过命令isnmod以模块的方式动态加载后,此时的入口点是宏module_init
2:设备操作:
在设备成功注册之后,就可对他进行打开,读写,控制和释放等操作。
在Linux内核中,字符设备使用file_operations结构来定义设备的各种操作集合。
3 :驱动程序的中断处理:
在实际的系统中设备的许多工作通常与处理器不同步,而且总比处理器慢。
如果让处理器一直等待到设备准备好时才进行操作会造成处理器资源的浪费。一种好的方法就是在设备准备好后通知处理器来进行处理,
这种方法就是中断。由于系统的中断资源有限。驱动程序在使用中断前需要申请,使用完后需要释放。
Linux中,中断的申请和释放分别通过request_irq()函数和free_rq()函数来实现。
动态和静态加载方式:
linux设备驱动模块属于内核的一部分,可以用静态和动态两种方式来进行编译和加载。两者方式的开发过程稍有不同,也各有特点。
静态加载方式:
静态方式就是将驱动程序的源代码实现放到内核源代码中,和整个内核一起编译。它需要修改内核源代码和文件系统。
并重新烧录下载到嵌入式设备中,这样当内核启动时就会加载驱动程序。
内核的修改:设备驱动程序写完后,就可以将文件加到Linux的内核中了。
文件系统的修改:在内核中加上驱动程序后,还不能直接在应用程序中使用驱动程序中的函数。
如open,ciose等,因为还需要在文件系统中提供设备访问接口,也就是在/dev/目录下的设备名与设备号。
动态加载方式:动态加载方式就是将驱动程序编译成一个可加载,卸载的模块目标文件,然后添加到内核中去即可。
这种方法的好处就是通过将与内核中一些不常用的驱动采取动态加载方式从而可以减少内核的大小,并且模块被插入内核后,
它就和内核其他部分一样可方便的被使用。
驱动程序添加到内核中:对于动态驱动程序的源代码,
其初始化函数和静态方式的定义不同,这里要用到这样一些函数:
int __init device_init(void); __init指示该函数仅在加载初始化时作用,加载后该函数内存就别释放掉了。
void __exit device_exit(void); __exit指示该函数仅用于模块卸载。该函数只能在模块被卸载或者系统关闭时被调用。
module_init(device_init);宏module_init指示该模块的加载函数。
module_exit(device_exit);宏module_exit指示该模块的卸载函
文件系统下设备名的创建驱动添加安装好后,还需要修改文件系统
阅读(4377) | 评论(1) | 转发(1) |