嵌入式软件开发简介-宋海平-马晓平_第1页
嵌入式软件开发简介-宋海平-马晓平_第2页
嵌入式软件开发简介-宋海平-马晓平_第3页
嵌入式软件开发简介-宋海平-马晓平_第4页
嵌入式软件开发简介-宋海平-马晓平_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

嵌入式软件开发简介-宋海平-马晓平第一页,共34页。嵌入式软件开发简介嵌入式系统的特点嵌入式系统设计的生命周期执行环境独特的软件技术ADS编译器相关知识编程注意事项第二页,共34页。嵌入式系统特点嵌入式系统一般用于特定的任务嵌入式系统通常及其关注成本嵌入式系统有实时约束嵌入式系统一般用实时操作系统(RTOS)嵌入式系统大多有功耗约束嵌入式系统的系统资源有限嵌入式系统通常在ROM中存放所有目标代码第三页,共34页。嵌入式系统设计生命周期产品定义(需求分析)开发计划的制定软件设计(概要设计和详细设计)编码及单元测试硬件和软件集成系统测试产品发布维护和升级第四页,共34页。执行环境内存结构系统启动中断响应周期栈帧第五页,共34页。执行环境内存结构一般微处理器的内存映像如下图:系统空间代码空间ROM数据空间I/O空间RAM数据空间堆栈图1处理器的内存映像第六页,共34页。内存结构系统空间为存放异常向量表的内存空间。处理器用异常向量标识出在系统遇到中断或其他异常(比如被零除、溢出错误、内存操作出错或指令错误)时将运行哪段代码,进行相应的处理。在系统空间之上的代码空间存放着指令。一般要把系统和代码空间存放在同一ROM物理设备中。在代码空间之上,ROM数据空间存放常量数值,比如错误信息和其他字符串。栈用来保存当前运行状态和所有暂停运行的进程的上下文。因此,栈包含所有局部变量以及函数和中断的返回地址。只有提供了栈空间,程序才能进行中断服务或调用函数。栈一般位于内存的高端,即栈从上向下增长。第七页,共34页。内存结构所有静态分配的读/写变量都放在自由内存(RAM数据空间)中。全局变量是静态分配变量最常见的形式,C语言中的“static”型变量也放在这里。任何拥有全局生存期的可修改变量都存放在自由内存中。所有动态分配(使用new或malloc())的对象和变量都放在堆中。许多嵌入式系统并没有使用堆。最后的内存组成部分是映射到内存的外部设备寄存器(如键盘、显示屏、耳机、光感应器、充电器)。这些设备的状态放在I/O空间区域。第八页,共34页。系统启动系统启动有两个阶段:硬件阶段和软件阶段。硬件阶段:一旦复位线有效(装电池或按“电源”键),处理器就进入到硬件阶段。此阶段的主要职责是使CPU开始运行程序或运行一些要把CPU控制权转交给程序的代码,程序的最初几行代码定义了如何启动软件。软件阶段:此阶段的职责是初始化核心元件和内存的关键结构(用来建立完整的运行时环境)。系统启动的具体过程与处理器的类型有关。第九页,共34页。系统启动过程举例(Arm微处理器)从程序的初始入口点处开始运行,这里用ENTRY伪操作标识程序入口点;调用复位异常处理中断(如boot_reset_handler)函数;对存储器和外围控制硬件进行初始化;执行ROM和RAM有效性校验和测试,如验证ROM中是否包含一个有效的应用映像;将已初始化的数据(ROM

中)拷贝到可写的数据区(RAM

中),并将剩下的RAM空间初始化为0;初始化数据栈指针调用main()函数开始运行主程序第十页,共34页。中断响应周期定义:当CPU接收到中断信号,他就把正在做的事情放在一边,执行处理此中断的指令,然后回到先前的任务。当某个设备发出中断信号给CPU,CPU将:把下一条指令(返回地址)的地址压入栈中从异常向量表加载ISR(中断服务程序)地址到程序计数器中禁止中断恢复运行正常的取指周期,此时取出的是ISR指令第十一页,共34页。栈帧(StackFrame)定义:分配给一个函数的所有栈空间(参数、返回地址和局部变量)称为栈帧栈被用来存放所有的函数局部变量和参数,函数调用的处理流程如下:把所有参数压栈调用函数为所有局部变量在栈中分配存储空间执行函数释放分配给局部变量的栈空间从函数返回释放参数所使用的栈空间第十二页,共34页。独特的软件技术控制外设内嵌式汇编汇编程序访问C变量C++程序使用C程序头文件内存映射访问使用存储类限定符volatile速度和代码密度中断和中断服务例程(ISRs)第十三页,共34页。控制外设嵌入式系统程序员经常需要编写一些直接控制外设的代码(如键盘、lcd、uim卡、充电器、麦克、speaker等)。对于不同的计算机体系结构,设备可能是端口映射的,也可能是内存映射的。如果系统结构支持独立的I/O地址空间,且外设是端口映射的,则必须用汇编语言完成实际操作,这是由于C语言没有真正的“端口”概念。对基于内存映射的外设,可通过C语言指针来访问内存映射硬件。通过简单的强制类型转换操作使指针定位到指定的任意内存地址。如用如下代码读寄存器的值:

unsignedshortx; volatileunsignedshort*io_regs; io_regs=(unsignedshort*)0x40000000; x=*io_regs[10];在ARM中,使用基于内存映射的方式控制外部设备第十四页,共34页。内嵌式汇编如果仅仅需要从特定端口进行读写操作,使用内嵌式汇编是最简单的解决方案。内嵌式汇编依赖于编译器。使用方式有如下两种:使用类似_asm/_endasm的特殊标志符;把汇编语句包装起来,类似函数调用,如asm(“

”);ARMADS1.2编译器使用第一种方式。其语法如下:__asm{instruction[;instruction]...[instruction]}若两个指令在同一行,则必须用分号隔开。若一条指令分两行显示则必须在行尾加符号‘\’.第十五页,共34页。汇编程序访问C变量在C程序中声明的全局变量可以被汇编程序通过地址间接访问。具体访问方法如下:使用IMPORT伪操作声明该全局变量使用LDR指令读取该全局变量的内存地址根据该数据的类型,使用相应的LDR指令读取该全局变量的值使用相应的指令修改该全局变量的值AREAglobals,CODE,READONLYEXPORTasmsubIMPORTglobal;用IMPORT伪操作声明该变量AsmsubLDRr1,=global;将器内存地址读入到寄存器R1中LDRr0,[r1];再将其值读入到寄存器R0中ADDr0,r0,#2STRr0,[r1];修改后再将寄存器r0的值赋予变量globalMOVpc,lrEND第十六页,共34页。C++程序使用C程序头文件

在C++程序使用C程序头文件时,必须将用户定义的头文件包含在伪操作extern“C”{}中,有如下两种方法来完成这种操作:在C++程序中包含该头文件时,将其放在伪操作extern“C”{}中。

//c++codeextern“C”{#include“my-cheader1.h”//在C++程序中使用伪操作extern“C”{}#include“my-cheader1.h”}intmain(){//…..return0;}第十七页,共34页。C++程序使用C程序头文件在该头文件中使用伪操作extern“C”{},使得其被C++程序包含时,自动加上extern“C”{}。

/*Cheaderfile*/#ifdef__cplusplus//如果头文件被C++程序引用

extern“C”{//在头文件中使用伪操作extern“C”{}#endif/*头文件实际内容*/

#ifdef__cplusplus}#endif第十八页,共34页。存储类限定符volatile大多数编译器为了减小代码尺寸,一般要对代码进行优化;或者为了获得更高的执行效率,有时可能把内存数据放到数据高速缓存(CACHE)中。这种方法是基于一个关键性假设:除非明确地把某值写到内存,否则内存中的值不会改变。由于硬件外设的寄存器值随时都在变化,为了避免出现问题,可用关键字volatile来告诉编译器不要使用各种方法对其进行优化,也不必把它放到数据高速缓存中。第十九页,共34页。速度和代码密度在很多情况下,如果是通过指针而不是正常的变量引用执行操作,编译器就能产生占用空间更少且执行速度更快的代码。如果某个函数操作某个变量多次,或者逐个访问某个数组的成员变量,通过指针来进行访问可能会产生更有效率的代码。如对如下代码:voidstrcpy2(chardst[],charconstsrc[]){intI;for(I=0;src[I];I++){dst[I]=src[I];}}第二十页,共34页。速度和代码密度(cont.)转换为汇编指令后,函数长度为34个字节,循环体有4条指令。这个循环可以用指针的方式,即:voidstrcpy2(char*dst,charconst*src){while((*dst++=*src++)){;}}转换为汇编指令后,函数长度为20个字节,循环体有2条指令。可以看出,用指针方式既节省了代码空间,又提高了执行效率。第二十一页,共34页。ADS编译器相关ADS工具包(toolkits)编译选项示例结构和域的对齐

第二十二页,共34页。ADS工具包(toolkits)ADS编译器提供如下工具:工具名称功能描述armcc

ARMC编译器armcpp

ARMC++编译器armasm

ARM汇编器armlink

ARM连接器FromELF

将连接生成的ARMELF文件转化为其他格式的文件(如BIN、HEX)armar

建立ARM库文件的工具第二十三页,共34页。编译选项示例选项名称描述备注-I"$(ARMINC)"指定搜索包含文件的路径C:\apps\include-cpuARM7TDMI指定CPU为ARM7-apcs/interwork指定过程调用标准(PCS)为interwork以及进行软件栈检查Interwork指允许混合使用ARM和Thumb代码。ARM指令是32位指令(执行速度快);Thumb指令是16位指令-littleend字节排序的方式为“小端排序”,即一个数据字的最小有效位(LSB)的字节存在最低的地址上如对数值0x2f1d,第一个字节存放0x1d;第二个字节存放0x2f第二十四页,共34页。编译选项(cont.)选项名称描述备注-fa对数据流是否出现异常进行检查如检查是否一个变量没有被赋值而被使用-Wb指定产生警告信息的级别-Ospace-O2进行基于缩小代码尺寸(以可能增加执行时间为代价)的优化。使用完全优化(fullyoptimized)的级别-ofile

指定生成的目标文件的名称第二十五页,共34页。结构和域的对齐结构的每个域用如下方式进行对齐:

将下一个地址分配给char类型的域,即1-对齐将下面偶数地址分配给short类型的域,即2-对齐将下面4的倍数地址分配给其它类型的域,即4-对齐为了对齐,需要给结构添加一些字节。添加的方式为:对static或extern类型的结构,添加0对其他类型的结构,用原有位置上的值来添加第二十六页,共34页。结构的对齐方式非压缩的(non-packed)结构的对齐方式为各个域的对齐值的最大值。如对结构struct{charC;intx;shorts}ex1;用下图的方式来分配地址空间。从此例可以看出实际分配的字节个数(12)比定义的字节个数要多(7)。第二十七页,共34页。结构对齐方式(cont.)考虑到对齐方式,为了节省空间,在定义非压缩结构时应注意每个域的先后顺序。如下结构要占用12个字节struct{ chara; charb; charc; intx;

chard}ex2;第二十八页,共34页。结构对齐方式(cont.)若定义为如下结构则只占用8个字节struct{ chara; charb; charc;

chard; intx; }ex2;

用限定符__packed定义的压缩结构的对齐值为1,实际开辟的空间和定义的一样。若某个域为浮点数,则不能将此结构定义为压缩结构。对不是全部为byte类型的压缩结构,一般不能用赋值语句,而只能用memcpy语句(由于字节对不齐,可能需要调用异常向量boot_abort_handler来自动纠错,从而影响性能或者程序会死掉)。

第二十九页,共34页。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论