|
EDA365欢迎您!
您需要 登录 才可以下载或查看,没有帐号?注册
x
由于嵌入式系统是一个受资源限制的系统,因此直接在嵌入式系统硬件上进行编程显然是不合理的。在嵌入式系统的开发过程中,一般采用的方法是现在通用PC机上编程;然后通过交叉编译和链接,将程序做成目标平台上课运行的二进制代码格式;最后将程序下载到目标平台上的特定位置,由目标板上启动代码运行这段二进制代码,从而运行起嵌入式系统。图所示为嵌入式软件开发的基本流程。2 e1 @( e0 {, z" L3 L, O7 ]. h
整个过程中的部分工作在主机上完成的,另一部分工作在目标板上完成。首先,是在主机上的编程工作。纯粹使用汇编代码编写源代码,除了编写困难外,调试和维护困难也是汇编代码的难题;而c语言可直接对硬件进行操作,而且又有高级语言程序结构化、容易移植等优点,因而嵌入式系统源代码主要是由汇编语言和c语言混合编写。源代码编写完成后容易保存为源文件,再用主机上建立的交叉编译环境生成.obj文件,并且将.obj文件按照目标板的要求链接成合适的.image文件。最后通过重定位机制和下载过程,将.image文件下载到目标板上运行。由于无法保证目标板一次就可以运行编译、链接成功的程序,因此后期的调试排错工作就特别重要。调试只能在运行态完成,因此在主机和目标板之间通过连接,由主机控制目标板上程序的运行,可达到调试内核或者嵌入式应用程序的目的。( H: q1 W3 u h8 ^, m/ l1 Q# ^8 w
基于交叉开发环境的嵌入式应用软件开发主要分如下5个基本阶段:开发环境的建立、源代码编辑阶段、交叉编译和链接、重定位和下载、联机调试。下面分别对这5个阶段进行介绍:
5 A% R& P: G; o8 A& n6 ^5 ?1.
9 t* w1 _1 t; K" N) p4 g开发环境的建立# Y# `- o5 ~; W! \) O) R x0 ^
在开发之前,必须了解在嵌入式编程中使用的交叉开发环境。交叉开发环境的原理比较简单,只是在主机和目标机体系结构不同的情况下,在主机开发将在目标机器上运行的程序。
- I( w3 h6 _' a按照发布的形式,交叉开发环境主要分为开放和商用2种类型。开发式交叉开发环境实例主要有gcc,它可以支持多种交叉平台的编译器,由http:www.gnu.org负责维护。使用gcc作为交叉开发平台,要遵守GPL的规定。5 ]2 m N9 [: @) D" w
按照使用方式,交叉开发工具主要分为使用Makefile和IDE开发环境2种类型。使用Makefile的开发环境需要编译Makefile来管理和控制项目的开发,可以自己手写,优势也可以使用一些自动化的工具。这种开发工具是gcc、SDS CrossCompiler等。新类型的开发环境一般由一个用户友好的IDE界面,方便管理和控制项目的开发,如Code Warrior等。有些开发环境既可用Makefile管理项目,又可使用IDE,给使用者留下很大的余地。' v7 a$ ?; D" ~4 g* ?( ?8 Y
对交叉开发环境有了一定的了解后,就要根据开发需求选择一种开发环境进行代码编写。编写程序的第一件事情就是要会写程序,即要先会程序的规划,将问题需求跟踪程序功能明确地写下来,依据规划好的函数逐个写好。/ x" Q5 K& f1 F" x3 I$ ^3 k+ T
当嵌入式系统编程升级时,要考虑到跨平台的问题。跨平台就是把原始程序拿到不同的CPU的平台和编译环境中,仍然能够不用修改太多的代码就可达到程序原始目的。因为嵌入式系统所用的硬件平台不尽相同,若是为了不同的硬件平台而让程序做大幅度修改,就会变得非常不经济,特别是在当时嵌入式系统硬件百家争鸣的状况下,如何让写出的程序快速移植到各种不同的硬件上,已成为嵌入式应用程序开发飞主要考虑因素之一。
9 C, g& c$ G% U) r$ ^2.
8 g& M( h3 |8 T源文件编辑阶段
# }8 p2 |& y/ W% g* H& I: q( A源程序的启动代码、硬件初始化代码要用汇编语言编写,这样可以发挥汇编语言短小精悍的优势,以提高代码的执行效率。汇编语言编写完成后,代码转向c语言的程序入口点,执行c语言代码。C语言在开发大型软件的开发中最常用的语言。但是在与硬件关联较紧密的编程中,c语言要结合汇编语言进行混合编程,也即内嵌汇编。
: A# O$ C1 {6 }$ g2 F3 A3.$ I! T6 \6 x' F3 {4 K! z9 V
编译! `5 A- ^, S' F, \' ~
通常所说的翻译程序能够把某一种语言的程序转换成另一种语言程序,而后者与前者在逻辑上是等价的,如果汇编语言是诸如FORTRAN、Pascal、C、Ada或Java这样的“高级语言”,而目标语言是诸如汇编语言或机器语言之类的“低级语言”,这样的一个翻译程序成为编译程序。编译就是将“高级语言”转化为“低级语言”的过程。
9 L1 o0 r' {8 V2 @' V8 g编译器主要负责的工作就是将源代码编译成特定的目标代码,顺便检查语法的错误,所产生的代码是不能执行的,不过可从目标代码找出许多有用的信息。现在目标代码有2类:COFF与ELF。在目标文件中规定信息的组织方式,也即目标文件格式。目标文件格式的规定是为了不同的供应商提供的开发工具可以遵循很好的标准,以实现相互操作的。
; c" `2 R! S8 o1 D5 q" N4.: u% [) Q/ [; j; r! l: ^
链接+ v( \5 W3 d- \ L% {
一个程序员想在内存中运行,除了编译之外,还要经过链接的步骤。编译器只能在一个模块内部完成符号名到地址的转换工作,不同模式间的符号解析需要由连接器完成。为了解决不同模式间的链接问题,链接器主要有2项工作要做。
. {4 _# P! \( Y3 v( O" V1)符号解析
) Q( z; r& N* K& ^ Z2 x当一个模块使用了在该模块中没有定义过的函数或全局变量时,编译器生成的符号表会标记出所有这样的函数或全局变量;而链接器的责任就是要到其他模块中去查找他们的定义,如果没有合适的定义或者找到的合适的定义不唯一,符号解析都无法正常完成。
. R3 i7 y1 T) `. L2)重定位* N$ D' D( [$ K6 B- f- L
编译器在编译生成文件时,通常使用从零开始的相对地址。然而,在链接过程中,链接器将从一个指定的地址开始,根据输入的目标文件的顺序以段为单位将它们一个接一个地拼装起来。除了目标文件的拼装之外,在重定位的过程中还完成了2个任务:一是生成最终的符号表;二是对代码中的某些位置进行修改,所有需要修改的位置都由编译器生成的重定位表指出。1 E% ~/ j& W$ M
链接器将所有目标代码及lib里的数据区段,包括“.text”“.data”及“.bss”区段的数据合并,而且会将所有尚未编译的函数及变量调用彼此对应起来。0 V+ X8 C/ G. Q% g
在链接过程中,对于嵌入式系统的开发而言,都希望使用小型的函数库,以使最后产的可执行代码尽量小。因此在编译中使用的一般是经过特殊定制的函数库,比如使用c语言进行嵌入式开发者一般使用的嵌入式函数库有:μClibc/μClibm、μC-libc/μC-libm和newlib等。" u' i) _+ {- T3 ~( w5 `: P a
5.
7 _* X. c+ f' A8 U下载
5 e1 V( K; E/ D: G: M+ w下载就是把可执行映像文件烧写到ROM里,如本系列教程中使用的EmbestARM开发环境具有Flash编译器功能,烧写前使用Elf to Bin工具将映像文件(ELF格式转换为二进制格式),也可通过其他方式下载调试好的代码。" ?; ^3 j' r, A: b6 i3 A, j
当可执行的程序映像文件下载完成后,就可打开电源来运行系统。下载过的代码优势还需要在实际应用软件中进行进一步调试,调试确定无误后一个完整的嵌入式程序就可运行了。5 q; s. y8 [. O3 k1 n
6.! v8 g7 }2 e' N) o" @
调试
2 r- r% ? i5 V' Q+ U) Q; @嵌入式系统的调试分为软件调试和硬件调试2种:软件调试时通过软件调试器嵌入式系统软件;硬件调试时通过仿真调试器完成调试过程。由于嵌入式系统特殊的开发环境,不可避免的是,调试时必然需要目标平台和调试器两方面的支持。
5 x8 }6 [" s! [0 D2 y5 L通常作为调试软件部分的调试器是被集成在安装在目标机上嵌入式软件开发集成环境中的,例如Embest IDE中的Debhgger。软件调试工具一般具有ISS功能,即完成代码在无硬件调试环境下的模拟调试。而由于真正的硬件运行环境与软禁模拟环境有较大的差异,ISS只能用于开发编程练习或者软件的初步调试。
" W& L/ {/ A2 S. U使用硬件调试器,可获得比软件功能强大得多的调试性能。硬件调试器的原理一般是通过仿真硬件和真正执行过程,让开发者在调试过程中可时刻获得执行情况。硬件调试器主要有ICE和ICD两种。前者主要完成仿真模拟的功能,后者使用硬件上的在线调试任务。 |
|