690 likes | 815 Views
开发环境的建立. 内容提要. 1 、宿主机 - 目标机开发模式 2 、 XsBase255 目标机环境 3 、宿主机环境 4 、试验 烧写 XsBase255 的 BootLoader 使用 Minicom 实现串口通信 建立开发环境 熟悉交叉编译环境和开发工具. 网络. HUB. 硬件调试器. Ethernet. Ethernet. JTAG. Serial. 主机工作站 PC. 目标扳. 1 、宿主机 - 目标机开发模式. 嵌入式系统开发与通常 PC 机上的软件开发的区别 交叉开发。 交叉编译。 特点.
E N D
内容提要 • 1、宿主机-目标机开发模式 • 2、XsBase255目标机环境 • 3、宿主机环境 • 4、试验 • 烧写XsBase255的BootLoader • 使用Minicom实现串口通信 • 建立开发环境 • 熟悉交叉编译环境和开发工具
网络 HUB 硬件调试器 Ethernet Ethernet JTAG Serial 主机工作站PC 目标扳 1、宿主机-目标机开发模式
嵌入式系统开发与通常PC机上的软件开发的区别嵌入式系统开发与通常PC机上的软件开发的区别 • 交叉开发。 • 交叉编译。 • 特点
一个嵌入式系统的开发环境一般包括: • 嵌入式目标板 • 开发用的宿主机(PC) • 硬件调试器
应用程序的开发通常是Linux操作系统在嵌入式目标机上运行进来之后进行。此时,更多的是在宿主机上使用GDB通过网络(或串口)与目标板通信,进行程序的调试。应用程序的开发通常是Linux操作系统在嵌入式目标机上运行进来之后进行。此时,更多的是在宿主机上使用GDB通过网络(或串口)与目标板通信,进行程序的调试。
XsBase255目标机环境 JTAG接口简介 • 在XSBase255目标机上,使用常用的硬件测试方法JTAG进行测试。 • 作为硬件测试手段,JTAG的功能与CPU状态无关,可以驱动设备的所有外部引脚并读入数据,而且在设备内部夺取外部的连接点(与通往外部的各个pin脚一一连接)。各个cell为了形成串行移位寄存器(边界扫描寄存器)而相连。整体的接口由5个pin脚来控制(TDI,TMS,TCK,nTRST,TDO)。其功能包括:测试线路连线和端子的连接状态;测试设备间的连接状态;进行Flash memory(闪存) 烧写等。
BootLoader Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。 • PC由BIOS和位于MBR(主引导记录)中的bootloader引导: • LILO(Linux Loader,Linux加载程序) • GRUB(GRand Unified Bootloader,完备的统一引导载入软件) • U-BOOT(Universal Boot Loader,支持嵌入式Linux 系统的引导)
Boot Loader是系统加电后运行的第一段代码。 • 通常情况下,Boot Loader通过串口与宿主机进行文件传输,但串口传输的速度是有限的,因此通过以太网连接并借助TFTP协议来下载文件是个更好的选择。 • 在XSBase255上使用的Boot Loader加载操作系统内核之前IP没有被设置。这个时候无法通过以太网进行数据传送,我们必须在Boot Loader上通过BootP设置IP,然后通过TFTP传送数据。
系统加电或复位后,所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令。基于XScale内核的CPU在复位时通常都从地址0x00000000处取它的第一条指令。而基于这种CPU构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROM、EEPROM或FLASH等)被映射到这个预先安排的地址上。因此在系统加电后,CPU将首先执行Boot Loader程序( 0x00000000)。 一个同时装有Boot Loader、内核的启动参数、内核映像和根文件系统映像的固态存储设备的典型空间分配结构图
大多数Boot Loader都包含两种不同的操作模式:"启动加载"模式和"下载"模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看,Boot Loader的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。 • 启动加载模式 • 下载模式
Boot Loader的阶段1通常包括以下步骤: a. 硬件设备初始化。 b. 为加载 Boot Loader 的 阶段2 准备 RAM 空间。 c. 拷贝 Boot Loader 的 阶段2 到 RAM 空间中。 d. 设置好堆栈。 e. 跳转到 阶段2 的 C 入口点。
Boot Loader的阶段2通常包括以下步骤: a. 初始化本阶段要使用到的硬件设备。 b. 检测系统内存映射(memory map)。 c. 将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中。 d. 为内核设置启动参数。
3、宿主机环境 3.1 BOOTP协议 3.2 TFTP协议 3.3 交叉编译 3.4 Make工具
3.1 BOOTP协议 • BOOTP服务的全称是BootStrap Protocol(引导协议) • 使用TCP/IP网络协议中的UDP 67/68两个通讯端口 • 常用到的DHCP服务就是从BOOTP服务扩展而来的 过程: • 第一步,在目标板由BootLoader启动BOOTP,此时目标板还没有IP地址,它就用广播形式以IP地址0.0.0.0向网络中发出IP地址查询的请求,这个请求帧中包含了客户机的网卡MAC地址等信息。
第二步,主机平台运行BootP服务的服务器接收到的这个请求帧,根据这帧中的MAC地址在Bootptab启动数据库中查找这个MAC的记录,如果没有此MAC的记录则不响应这个请求;如果有就将FOUND帧发送回目标板。FOUND帧中包含的主要信息有目标板的IP地址、服务器的IP地址、硬件类型、网关IP地址、目标板MAC地址和启动映象文件名。 • 第三步,目标板就根据FOUND帧中的信息通过TFTP服务器下载启动映象文件。
3.2 TFTP协议 • TFTP服务的全称是Trivial File Transfer Protocol(简单文件传输协议) • TFTP可以看成一个简化了的FTP,TFTP不需要认证客户端的权限,这样远程启动的目标板在启动一个完整的操作系统之前就可以通过TFTP下载启动映象文件,而不需要证明自己是合法的用户 • TFTP在安装时一定要设立一个单独的目录作为TFTP服务的根目录,设置TFTP服务为:只能下载不能上传等以减少安全隐患
3.3 交叉编译 • 交叉编译就是在一个架构下编译另一个架构的目标文件。目标文件在不同架构间由于采用的CPU指令集不同等原因不能通用。比如X86架构的程序不能运行于ARM架构的XSBase255目标机。 • 采用何种交叉编译器产生何种格式的目标文件还要取决于目标机的操作系统。 • 本门课程交叉编译就是在X86架构的宿主机上生成适用于ARM架构的,ELF格式的可执行代码。
3.4 Make工具 • GNU Make是一种常用的编译工具,通过它,程序员可以很方便地管理软件编译的内容、方式和时机,从而使程序员能够把主要精力集中在代码的编写上。Make自动判断源码中哪些部分有更新,重新编译这些文件并重新链接。对于那些由许多源文件组成的大型软件项目来说,采用这种项目管理方法则可以极大地提高工作效率,让原本复杂繁琐的开发工作变得简单。 • make 工具通过一个称为makefile的文件来完成并自动维护编译工作。makefile需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。当修改了其中某个源文件时,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。
基本规则 :目标、依赖关系、指令 target : dependency …… command …… 目标(target):需要由make工具创建的项目,是指令(command)执行的结果文件(目标文件或执行文件),也可以是一个标签(Lable),如make clean、make all等。 依赖(dependency):要创建的项目依赖于哪些文件或目标。依赖条件顶格书写。指令(command):创建每个项目时make需要运行的命令(任意的Shell命令) 。指令必须使用一个TAB符(制表位)开始进行书写。 在指令部分定义的指令会在依赖文件的内容有所变更或找不到目标文件时被执行。
如果一个工程有三个源文件write.c,read.c,main.c生成可执行程序test 。 用于生成test的Makefile文件如下: -c:对源程序进行预处理、编译,产生目标文件,但不进行连接。 -o <文件名>:定义输出的执行文件名为<文件名>。
clean不是一个文件,它只不过是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令,就要在make命令后明显得指出这个lable的名字。 • 例如,使用名为clean标签来进行清除,可以没有依赖关系部分,即执行命令 以此来清除所有的目标文件,以便重新编译。 相当于执行了: [root@XSBase test]# make clean [root@XSBase test]# rm test main.o read.o write.o
使用vi编译器创建Makefile后,进行make,则生成执行文件test。Make将按照 Makefile中指定的依赖关系来依次执行。 [root@XSBase test]# make Makefile依赖关系
宏和标签 • 为了makefile的易维护,在makefile中我们可以使用变量。makefile的变量也就是一个字符串,理解成C语言中的宏可能会更好。 比如,我们声明一个能够表示obj文件的宏,宏名可为objects,OBJECTS,objs,OBJS,obj或 OBJ等。 • 可使用宏(Macro)功能和标签(Label)功能使Makefile的创建更为灵活。宏起到以替换指定的内容使程序简单化的作用。宏必须要在$(..)里面使用。
例:利用宏来创建Makefile。在这里宏是OBJECTS,将main.o、read.o、write.o替换为OBJECTS来使用。
预定义的宏(Pre-defined Macro) 执行make -p可看到Make中事先指定好的各个值(宏,环境参数等)。
扩展名规则 • 扩展名规则(Suffix Rule)是根据文件的扩展名来进行适当的运算操作。例如,.c一般指C源文件,.o文件是目标文件。.c文件编译后应成为.o文件。 • 在这里出现名为.SUFFIXES的宏,这个宏自动处理Makefile中需要慎重处理的文件的扩展名。 .SUFFIXES = .c .o 上面的例子对带有.c和.o扩展名的文件按照扩展名规则来处理,自动操作使.c文件编译后生成.o文件。
内部宏定义(Internal Macro) 用于简化Makefile的写法
内部宏的用法 例子一: main.o : main.c io.h gcc -c $*.c 说明:$*是没有扩展名的当前目标文件,所以$*.c扩展为main.c。 例子二: test : gcc -o $@ -c main.c 说明:$@是当前目标文件,相当于test。 例子三: .c.o : gcc -c $< test: main.o gcc -o $@ main.o 说明:如果源文件.c比目标文件.o更新,则.c文件会自动编译。即在main.o生成之后更新了main.c的话,那么main.c就会被$<自动重新编译。
myprog:main.o display.o input.o gcc main.o display.o input.o -o myprog main.o:main.c commom.h gcc -c main.c display.o:display.c display.h common.h gcc -c display.c input.o:input.c input.h common.h gcc -c input.c clean: rm -f myprog main.o display.o input.o CC=gcc OBJS=main.o display.o input.o myprog:$(OBJS) $(CC) $(OBJS) -o $@ main.o:main.c commom.h $(CC) -c $< display.o:display.c display.h common.h $(CC) -c $< input.o:input.c input.h common.h $(CC) -c $< clean: rm -f myprog $(OBJS)
实验三 Makefile • 使用命令编译程序 • 使用预定义变量编译程序 • 使用预定义变量对多个.c文件编译 • 具体练习题目详见实验指导书
RPM • (1) rpm的主要功能及命令rpm的基本使用 • Red Hat软件包管理器(RedHat Package Manager, 简称RPM)。 • 在Red Hat Linux的光盘上,有许多以rpm为类型名的文件,它们是分类将各软件产品的所有必要的文件打包到相应文件中,这些文件就是软件包。安装程序用rpm命令打开这些软件包并将文件复制到硬盘中适当的位置上。
一系列的rpm命令构成了软件包管理器,rpm包管理的用途如下: • 可以安装、删除、升级和管理以rpm包形式发布的软件; • 可以查询某个rpm包中包含哪些文件,以及某个指定文件属于哪个rpm包; • 可以在查询系统中的某个rpm包是否已安装以及其版本; • 作为开发者可以把自己开发的软件打成rpm包发布; • 依赖性的检查,查询安装某个rpm包时,需要哪些其它的rpm包。
注意:rpm软件的安装、删除、更新只有root权限才能使用;对于查询功能任何用户都可以操作。注意:rpm软件的安装、删除、更新只有root权限才能使用;对于查询功能任何用户都可以操作。 • 软件包文件名是由软件包名、版本号和版本的发行号三部分组成,例如从软件包文件名“XFree86-3.3.2.3-25.rpm”,我们可以获得如下信息:软件包名:XFree86;版本号:3.3.2.3;版本的发行号:25。
命令rpm的基本使用方法 格式: rpm [options] [RPM filename…] • 功能:能够建立、编译、查询、校验、升级和卸载独立软件包的包管理器。 参数: • -qa 查看系统内所有已安装的软件包列表。 • -ql 软件包名称 查看此软件包中所有的文件及所在的目录。 • -qd 软件包名称 查看此软件包中所有的文档。 • -qc 软件包名称 查看此软件包中所有的组态配置文件。 • -qi 软件包名称 显示软件包的详细信息,包括版本号、大小、安装日期和简短说明。 • -qs 列出软件包中所有文件所处的状态。 • -p查询指定的。 • -R显示软件包的关联性信息。 • -e 删除软件包。 • -i 安装软件包。 • -V 验证软件包。
得到一个新软件,在安装之前,一般都要先查看一下这个软件包里有什么内容,假设这个文件是:Linux-1.4-6.i368.rpm,查看的组合命令有很多,在此介绍一些常用命令: 查看系统内所有已安装的软件包列表 • # rpm -qa 查看一个软件包的用途、版本等信息 • # rpm -qpi Linux-1.4-6.i368.rpm 系统将会列出这个软件包的详细资料,包括含有多少个文件、各文件名称、文件大小、创建时间、编译日期等信息。
查看一件软件包所包含的文件 • # rpm -qpl Linux-1.4-6.i368.rpm 可以用-qpl选项查看软件包将会在系统里安装哪些部分,以方便我们的选择。 查看软件包的文档所在的位置 • # rpm -qpd Linux-1.4-6.i368.rpm 查看一个软件包的配置文件 • # rpm -qpc Linux-1.4-6.i368.rpm 查看一个软件包的依赖关系 • # rpm -qpR Linux-1.4-6.i368.rpm
选择安装方式后,开始安装一个rpm 包。在安装过程中,若系统提示此软件已安装过或因其他原因无法继续安装,但如果确实想执行安装命令,可以在 -ivh后加一参数“-replacepkgs”。 # rpm -ivh Linux-1.4-6.i368.rpm 或 # rpm -ivh -replacepkgs Linux-1.4-6.i368.rpm
对低版本软件进行升级是提高其功能的好办法,这样可以省去卸载后再安装新软件的麻烦,要升级某个软件,只须执行如下命令:rpm -uvh <文件名>,注意:此时的文件名必须是要升级软件的升级补丁。 # rpm -Uvh Linux-1.4-6.i368.rpm • 不过,在安装和升级时,如果软件包有依赖关系的,需解决依赖关系;如果找不到依赖关系的包,可以用下面的命令强制安装。其中选项(--nodeps)表示不验证软件包的相互关联性;选项(--force)表示强行置换软件包或文件。 # rpm -ivh --nodeps --force Linux-1.4-6.i368.rpm # rpm -Uvh --nodeps --force Linux-1.4-6.i368.rpm • 如果对软件包仅仅是作测试,并不真正安装,则执行下面命令。 # rpm -ivh --test Linux-1.4-6.i368.rpm
如果需要为软件包指定安装目录:要加参数(--relocate) ,在默认情况下,通常可执行程序都放在安装目录下的bin或者sbin目录中。 # rpm -ivh --relocate /=/usr/local/newlinux Linux-1.4-6.i368.rpm • 在卸载某个安装过的软件时,需首先查出删除的rpm包,然后执行rpm -e <软件包名>命令来卸载。 # rpm -e newlinux • #卸载newlinux,如果有其它的rpm依赖于该rpm包,系统会出现警告。如果一定要卸载,可以用选项 --nodeps 忽略依赖关系。但最好不要这么做。
rpm管理包管理器还支持网络的安装和查询。 • 格式:rpm [选项] rpm包的http或者ftp的地址 • 例如,想通过 Fedora Core 4.0 的一个镜像查询、安装软件包。 # rpm -qpi http://mirrors.kernel.org/.../RPMS/rsh-0.17-29.rpm #查询 # rpm -ivh http://mirrors.kernel.org/.../RPMS/rsh-0.17-29.rpm #安装
实验二 开发环境的建立 4.1烧写XsBase255的BootLoader • 光盘拷贝:打开终端,将光盘中所有文件( 包括目录pxa255 )拷贝到Filestystem(即根目录“/”)中。 [root$localhost /]# mount /dev/cdrom /mnt/cdrom [root$localhost /]# cp –a /mnt/cdrom/* / • 创建Bootp:安装bootp rpm包,bootp rpm在提供的光盘的PRM目录里。 [root$localhost root]# cd /pxa255/RPM [root$localhost RPM]# rpm –i bootp-2.4.3-7.i386.rpm
新建bootp 文件 在/etc/xinetd.d目录下新建bootp文件并按如下配置。 也可通过拷贝方式获取bootp、bootptab、tftp三个配置文件 #cd /pxa255/Net_Config #cp bootp /etc/xinetd.d #cp tftp /etc/xinetd.d #cp bootptab /etc
inetd的设置 inetd 的设置文件是/etc/inetd.conf。在启动时,inetd 从这一文件读入设置信息。每1 行描述1 个服务的设置,各字段用分割符和空格分开。带#(注释)的行不予执行。以下表示行的格式。 <service_name> <socket_type> <protocol> <flag> <user> <server_path> <args> service_name:描述telnet 等服务名称。服务名称和端口号一览表登录在/etc/services 中。 socket_type:描述stream(流型)和dgram(数据型)等接口(socket)类型(种类)。 protocol:描述tcp 和udp 等,从登录在/etc/protocols 中找出的相对应的程序。 flag:描述wait 或nowait。仅在当socket_type 为dgram(数据型)时才有意义,到一个处理结束之前,等待下一个要求(wait),或者在有要求时不予等待(nowait),指示接受。 user:描述root 和nobody 等以什么样的用户权限启动服务。 server_path:以全路径描述启动的服务器程序。 args:描述在server_path 中记述的服务器程序的启动名和参数(选项)
新建bootptab 文件 在/etc下新建bootptab文件并按如下配置。 注意: 板子的ip地址和主机平台的ip地址必须在同一个网段内。 (例如主机IP: 192.168.10.100, 板子IP : 192.168.10.xxx)
重启xinetd 在主机平台重启xinetd。 创建tftp 安装tftp rpm
新建tftp 文件 在/etc/xinetd.d下新建tftp文件并按如下配置。 如完成上述步骤后tftp还不工作,请检查防火墙是否存在。 关闭防火墙使用lokkit命令。
下载Bootloader, Kernel, Filesystem 映象文件 建立tftpboot目录并复制映象文件 编译生成XSBase255专用的JTAG程序
正确连线 已经存在名为x-boot255的Boot Loader Image,用于XSBase255目标机。 用JTAG线正确连接宿主机和目标机,开启目标机。 • 利用JTAG烧写BootLoader • 正常运行结果如下图所示。 #cd /tftboot [root$localhost tftpboot ]#ls Jflash-XSBase255 rootfs.img x-boot255 zImage [root$localhost tftpboot ]#./Jflash-XSBase255 x-boot255