资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,嵌入式系统开发与应用,基于ARM的嵌入式程序设计ok,5.1,ARM,汇编语言的伪操作、宏指令与伪指令,5.1.1,两种常见的,ARM,编译开发环境,5.1.2 ADS,编译环境下的伪操作和宏指令,5.1.3 GNU,编译环境下的伪操作和宏指令,5.1.4 ARM汇编语言的伪指令,5.1.1,两种常见的,ARM,编译开发环境,ADS/SDT IDE,开发环境:它由,ARM,公司开发,使用了,CodeWarrior,公司的编译器;,集成了,GNU,开发工具的,IDE,开发环境:它由,GNU,的汇编器,as,、,交叉编译器,gcc,、,和,链接器,ld,等组成。,5.1.2ADS,编译环境下的伪操作和宏指令,ADS,编译环境下的伪操作可分为以下几类:,符号定义(,Symbol Definition,),伪操作,数据定义(,Data Definition,),伪操作,汇编控制(,Assembly Control,),伪操作,信息报告(,Reporting,),伪操作,其他(,Miscellaneous,),伪操作,符号定义伪操作,伪操作,语法格式,作 用,GBLA,GBLA Variable,声明一个全局的算术变量,并将其初始化成0。,GBLL,GBLL Variable,声明一个全局的逻辑变量,并将其初始化成FALSE。,GBLS,GBLS Variable,声明一个全局的字符串变量,并将其初始化成空串“”。,LCLA,LCLA Variable,声明一个局部的算术变量,并将其初始化成0。,LCLL,LCLL Variable,声明一个局部的逻辑变量,并将其初始化成FALSE。,LCLS,LCLS Variable,声明一个局部的串变量,并将其初始化成空串“”。,SETA,SETA Variable expr,给一个全局或局部算术变量赋值。,SETL,SETL Variable expr,给一个全局或局部逻辑变量赋值。,SETS,SETS Variable expr,给一个全局或局部字符串变量赋值。,RLIST,name LISTlist of registers,为一个通用寄存器列表定义名称。,CN,name CN expr,为一个协处理器的寄存器定义名称。,CP,name CP expr,为一个协处理器定义名称。,DN/SN,name DN/SN expr,DN/SN为一个双精度/单精度的VFP寄存器定义名称。,FN,name FN expr,为一个FPA浮点寄存器定义名称。,数据定义伪操作,伪操作,语法格式,作 用,LTORG,LTORG,声明一个数据缓冲池(也称为文字池)的开始。,MAP,MAP expr,base-register,定义一个结构化的内存表(Storage Map)的首地址。,FIELD,label FIELD expr,定义一个结构化内存表中的数据域。,SPACE,label SPACE expr,分配一块连续内存单元,并用0初始化。,DCB,label DCB expr,expr,分配一段字节内存单元,并用expr初始化。,DCD/DCDU,label DCD expr,expr,分配一段字内存单元。,DCDO,label DCDO expr,expr,分配一段字对齐的字内存单元。,DCFD/DCFDU,label DCFD Ufpliteral,fpliteral,为双精度的浮点数分配字对齐的内存单元。,DCFS/DCFSU,label DCFS U fpliteral,fpliteral,为单精度的浮点数分配字对齐的内存单元。,DCI,label DCI expr,expr,在ARM代码中分配一段字对齐的内存单元;在Thumb代码中,分配一段半字对齐的半字内存单元。,DCQ/DCQU,label DCQUliteral,literal,分配一段以双字(8个字节)为单位的内存,DCW/DCWU,label DCWUexpr,expr,DCW用于分配一段半字对齐的半字内存单元。,汇编控制伪操作,伪操作,语法格式,作 用,IF,ELSE及ENDIF,IF logical expression,ELSE,ENDIF,能够根据条件把一段源代码包括在汇编语言程序内或者将其排除在程序之外。,WHILE及WEND,WHILE logical expression,WEND,能够根据条件重复汇编相同的一段源代码。,MACRO、MEND及MEXIT,MACRO,$label macroname$parameter,$parameter,;宏代码,MEND,MACRO标识宏定义的开始,MEND标识宏定义的结束。MERIT用于从宏中跳转出去。用MACRO和MEND定义的一段代码,称为宏定义体。通过宏名称来调用宏。,信息报告伪操作,伪操作,语法格式,作 用,ASSERT,ASSERT logical expression,对汇编程序的第二遍扫描中,如果其中ASSERT中条件不成立,ASSERT伪操作将报告该错误信息。,INFO,INFO numeric-expression,string-expression,在汇编处理过程的第一遍扫描或者第二遍扫描时INFO伪操作报告诊断信息。,OPT,OPT n,通过OPT伪操作可以在源程序中设置列表选项。,TTL,TTL title,在列表文件的每一页的开头插入一个标题。,SUBT,SUBT subtitle,在列表文件的每一页的开头插入一个子标题。,其他伪操作,伪操作,语法格式,作 用,CODE16,CODE16,告诉汇编编译器后面的指令序列为16位的Thumb指令,CODE32,CODE32,告诉汇编编译器后面的指令序列为32位的ARM指令。,EQU,name EQU expr,type,为数字常量、基于寄存器的值和程序中的标号(基于PC的值)定义一个字符名称。,AREA,AREA sectionname,attr,attr,定义一个代码段或者数据段。,ENTRY,ENTRY,指定程序的入口点。,END,END,告诉编译器已经到了源程序结尾。,ALIGN,ALIGN expr,offset,通过添加补丁字节使当前位置满足一定的对齐方式。,EXPORT/GLOBAL,EXPORT symbol WEAK,声明一个符号可以被其他文件引用,相当于声明了一个全局变量。,IMPORT,IMPORT symbol WEAK,告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号。,EXTERN,EXTERN symbol WEAK,告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号。,GET/INCLUDE,GET filename,将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。,INCBIN,INCBIN filename,将一个文件包含到当前源文件中,被包含的文件不进行汇编处理。,KEEP,KEEPsymbol,告诉编译器将局部符号包含在目标文件的符号表中。,NOFP,NOFP,禁止源程序中包含浮点运算指令。,REQUIRE,REQUIRE lable,指定段之间的相互依赖关系。,RN,name RN expr,为一个特定的寄存器定义名称。,ROUT,name ROUT,定义局部变量的有效范围。,5.1.3 GNU,编译环境下的伪操作和宏指令,GNU,编译环境下的伪操作可分为以下几类:,常量编译控制伪操作,汇编程序代码控制伪操作,宏及条件编译控制伪操作,其他伪操作,常量编译控制伪操作,伪操作,语法格式,作 用,.byte,.byte expr,expr,分配一段字节内存单元,并用expr初始化。,.hword/.short,.hword expr,expr,分配一段半字内存单元,并用expr初始化。,.ascii,.ascii expr,expr,定义字符串expr(非零结束符)。,.asciz/.string,.asciz expr,expr,定义字符串expr(以/0为结束符)。,.float/.single,.float expr,expr,定义一个32bit IEEE 浮点数expr。,.double,.double expr,expr,定义64bit IEEE浮点数expr。,word/.long/.int,.word expr,expr,分配一段字内存单元,并用expr初始化。,.fill,.fill repeat,,size,value,分配一段字节内存单元,用size长度value填充repeat次。,.zero,.zero size,分配一段字节内存单元,并用0填充内存。,.space/.skip,.space size,value,分配一段内存单元,用value将内存单元初始化。,字符编译控制,.equ,.equiv,操作符,.set,.global,.globl,说,明,将,symbol,定义为,expr,作用同.equ,定义,symbol,为,expr,,若symbol已定义则出错,将,symbol,定义为全局标号,使用同.global,语,法,.equ symbol,expr,.set symbol,expr,.equiv symbol,expr,.global symbol,.globl symbol,例,子,.equ Version,0.1,.set Co,EMBEST,.equiv Version,0.2,.global MyAsmFunc,.globl MyAsmFunc,汇编程序代码控制伪操作,伪操作,语法格式,作 用,.section,.section expr,定义域中包含的段。,.text,.text subsection,将操作符开始的代码编译到代码段或代码段子段。,.data,.data subsection,将操作符开始的数据编译到数据段或数据段子段。,.bss,.bss subsection,将变量存放到.bss段或.bss段的子段。,.code 16/.thumb,.code 16,.thumb,表明当前汇编指令的指令集选择Thumb指令集。,.code 32/.arm,.code 32,.arm,表明当前汇编指令的指令集选择ARM指令集。,.end,.end,标记汇编文件的结束行,即标号后的代码不作处理。,.include,.include,“filename”,将一个源文件包含到当前源文件中。,.align/.balign,.align alignment ,fill ,max,通过添加填充字节使当前位置满足一定的对齐方式。,宏及条件编译控制伪操作,伪操作,语法格式,作 用,.macro、.exitm及.endm,.macro acroname,parameter,parameter,.endm,.macro伪操作标识宏定义的开始,.endm标识宏定义的结束。用.macro及.endm定义一段代码,称为宏定义体。.exitm伪操作用于提前退出宏。,.ifdef,,.else及.endif,.ifdef condition,.else,.endif,当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。其中else可以缺省。,其他伪操作,伪操作,语法格式,作 用,.eject,.eject,在汇编符号列表文件中插入一分页符。,.list,.list,产生汇编列表(从.list 到.nolist)。,.nolist,.nolist,表示汇编列表结束处。,.title,.title “heading”,使用“heading”作为标题。,.sbttl,.sbttl “heading”,使用“heading”作为子标题。,.ltorg,.ltorg,在当前段的当前地址(字对齐)产生一个文字池。,.req,.req name,expr,为一个特定的寄存器定义名称。,.err,.err,使编译时产生错误报告。,.print,.print string,打印信息到标准输出。,.fail,.fail expr,编译汇编文件时产生警告。,5.1.4ARM汇编语言的伪指令,伪指令,语法格式,作 用,ADR,ADR,cond register,expr,将基于PC或基于寄存器的地址值读取到寄存器中。小范围的地址读取。,ADRL,ADRL cond register,expr,将基于PC或基于寄存器的地址值读取到寄存器中。中等范围的地址读取。,LDR,LDR cond register,=expr|label-expr,将一个32位的立即数或者一个地址值读取到寄存器中。大范围的地址读取。,NOP,NOP,在汇编时将被替换成ARM中的空操作。,5.2 ARM,汇编语言程序设计,5.2.1,ARM汇编中的文件格式,5.2.2 ARM汇编语言语句格式,5.2.3 ARM汇编语言编程的重点,5.2.4,ARM汇编程序实例,5.2.1ARM,汇编中的文件格式,ARM,源程序文件(可简称为源文件)可以由任意一种文本编辑器来编写程序代码,它一般为文本格式。在,ARM,程序设计中,常用的源文件可简单分为以下几种:,源程序文件,文件名,说,明,汇编程序文件,*.S,用,ARM,汇编语言编写的,ARM,程序或,Thumb,程序。,C,程序文件,*.C,用,C,语言编写的程序代码。,头文件,*.H,为了简化源程序,把程序中常用到的常量命名、宏定义、数据结构定义等等单独放在一个文件中,一般称为头文件。,5.2.2ARM,汇编语言语句格式,ARM,汇编语言语句格式如下所示:,symbol,instruction|directive|pseudo-instruction,;,comment,其中:,instruction,为指令。,directive,为伪操作。,pseudo-instruction,为伪指令。,symbol,为符号。,comment,为语句的注释。,ARM汇编语言程序格式,ARM,汇编语言是以段(,section,)为单位来组织源文件的。段是相对独立的、具有特定名称的、不可分割的指令或者数据序列。段又可以分为代码段和数据段,代码段存放执行代码,数据段存放代码运行时需要用到的数据。一个,ARM,源程序至少需要一个代码段,大的程序可以包含多个代码段和数据段。,举例说明ARM,汇编语言源程序的基本结构,.equx,45/*x=45*/,.equy,64/*y=64*/,.equstack_top,0 x1000/*define the top address for stacks*/,.global _start,.text,_start:/*code start*/,movsp,#stack_top,movr0,#x /*put x value into R0*/,strr0,sp/*save the value of R0 into stacks */,movr0,#y/*put y value into R0 */,ldrr1,sp/*read the data from stack,and put it into R1*/,ADDr0,r0,r1,STRr0,sp,stop:,bstop/*end the code,cycling*/,.end,5.2.3,ARM汇编语言编程的重点,ARM,数据处理操作,设置条件码,汇编语言子程序调用及返回,跳转表思想,ARM,与,Thumb,之间的状态转换及函数的相调用,ARM数据处理操作,ARM中数据的处理有以下三种形式:,简单的寄存器操作,立即数操作,寄存器移位操作,其中32位立即数在32位指令中的编码以及ARM特有的寄存器移位操作是数据处理方面的难点。,设置条件码,ARM,的任何数据处理指令都能通过增加“,S,”操作码来设置条件码(,N,,,Z,,,C,和,V,)。,条件执行,ARM,指令集不同寻常的特征是每条指令(除了某些,v5T,指令)都可以是条件执行的。,条件转移,在程序中,可以通过条件码的使用让,微处理器决定是否进行转移,还可用来控制循环的退出。,汇编语言子程序调用及返回,子程序的调用,在,ARM,汇编语言中,子程序调用是通过,BL,指令来完成的。,BL,指令的语法格式如下:,BL,subname,其中,,subname,是被调用的子程序的名称。,子程序的返回,在返回调用子程序时,转移链接指令保存到,LR,寄存器(,r14,),中的值需要拷贝回程序寄存器,PC,(,r15,)。,跳转表思想,在程序设计中,有时为使程序完成一定的功能,需要调用一系列子程序中的一个,而决定究竟调用哪一个由程序的计算值确定。跳转表是解决该问题的有效方案。跳转表是利用程序计数器PC在通用寄存器文件中的可见性来实现的,如下例所示:,ARM与Thumb间的状态转换及函数的相调用,状态切换的实现,ARM/Thumb,之间的状态切换是通过一条专用的转移交换指令,BX,来实现的。,BX,利用,Rn,寄存器中目的地址值的最后一位来判断跳转后的状态。当最后一位为,0,时,表示转移到,ARM,状态;当最后一位为,1,时,表示转移到,Thumb,状态,如下图所示。,ARM与Thumb间的状态转换及函数的相调用,ARM/Thumb,之间的函数调用,在同一状态下的子程序调用,通常只需要一条指令实现调用:,BL function,实现返回也只需要从,LR,恢复,PC,即可:,MOV PC,,,LR,在不同状态下的子程序调用中,就需要进行状态之间的切换,需要考虑到以下几点:,需要由,BX,来切换状态,因为,BL,不能完成状态切换。,需要在,BX,之前先保存好,LR,,,BX,不能自动保存返回地址到,LR,。,需要,用“,BX LR,”,来返回,不能使用“,MOV PC,,,LR,”,,,返回时要仔细考虑保存在,LR,中最低位的内容是否正确。,5.2.4ARM,汇编程序实例,简单的,ARM,指令程序,数据块复制,利用跳转表实现程序跳转,ADS,编译环境下的汇编代码与,GNU,编译环境下有较多不同点,主要是符号及伪操作的不同。,5.3 嵌入式,C,语言程序设计基础,5.3.1,C语言“预处理伪指令”在嵌入式程序 设计中的应用,5.3.2 嵌入式程序设计中的函数及函数库,5.3.3 嵌入式程序设计中常用的C语言语句,5.3.4 嵌入式程序设计中C语言的变量、数 组、结构、联合,5.3.1C语言,“预处理伪指令”在嵌入式程序设计中的应用,“预处理命令”可以改进程序设计的环境,提高编程效率,一般以#号打头,可分为以下三种:,文件包含,宏定义,条件编译,文件包含,文件包含伪指令可将头文件包含到程序中,头文件中定义的内容包括符号常量、复合变量原型、用户定义的变量类型原型和函数的原型说明等。编译器编译预处理时用文件包含的正文内容替换到实际程序中。,文件包含伪指令的格式,#include ;,标准头文件,#include“头文件名.h”,;自定义头文件,#include 宏标识符,文件包含举例,#define MYINCLUDE “d:EmbestIDEdef.h”,#include “44blib.h”,#include “44b.h”,#include MYINCLUDE,#include “./LCD_Test/bmp.h”,宏定义,宏定义伪指令分为:简单宏、参数宏、条件宏、预定义宏及宏释放。,简单宏,:,#define,宏标识符 宏体,参数宏:,#define,宏标识符(,形式参数表),宏体,条件宏定义:,#,ifdef,宏标识符,#,ifndef,宏标识符,#,undef,宏标识符,#define,宏标识符,宏体,#define,宏标识符,宏体,#else,#else#,undef,宏标识符,#define,宏标识符,宏体,#define,宏标识符,宏体,#,endif,#,endif,宏定义举例,简单宏,#define rSYSCFG(*(volatile unsigned*)0 x1c00000),参数宏,#define SQR(x,y)sqrt(x)*(y)+(y)*(y),#define min(x1,x2)(x1x2)?x1:x2),条件宏定义,#ifndef BLOCK-SIZE,#define BLOCK-SIZE 128,#else,#undef BLOCK-SIZE,#define BLOCK-SIZE 128,#endif,条件编译,条件编译伪指令是写给编译器的,指示编译器在满足某一条件时仅编译源文件中与之相应的部分。其格式如右框中所示:,#if(条件表达式1),#elif(条件表达式2),#elif(条件表达式n),#else,#endif,5.3.2,嵌入式程序设计中的函数及函数库,函数是,C,语言程序设计的核心。一个较大的,C,语言程序一般是由一个主函数和若干个子函数组成,每个函数完成一个特定的功能。函数之间也可以相互调用。,函数的格式:,定义性说明格式:,存储类说明符 类型说明符 修饰符 标识符(参数表)函数体,原型说明格式:,extern 类型说明符修饰符 标识符(参数表)函数体,存储类说明符:,static、extern,类型说明符:,char、unsigned char,int、unsigned,long、unsigned long,float、double、long double,struct、union、void,修饰符:,interrupt、near、far、huge,标识符:,函数名、*函数名等,嵌入式程序设计中的函数及函数库,函数库是为了减少编程工作量,将一些常用的功能的函数放在函数库中供公共使用.,它包括C的标准库函数,也包括一些用户自己编写非标准库。,例如,,44,blib.h 是根据基于S3C44B0X处理器的开发板及其功能模块编写的一个C语言函数库。它不属于C语言的标准库。,44blib.c结构如下:,用户定义头文件:,44blib.h:库函数原型定义,44b.h:44B0X片上各模块寄存器宏定义,def.h:数据类型重新宏定义,常用常量宏定义,Option.h:44B0X片上可选项宏定义,标准头文件,:,Stdarg.h:定义读函数参数表宏,String.h:串操作和内存操作函数,Stdio.h:标准I/O预定义函数,Ctype.h:字符分类及转换信息,void delay(int time);/延时函数,void port_init(void);/I/O端口初始化函数,void cache_flush(void);/清空cache,void uart_init(int nMainClk,int nBaud);,void uart_select(int nChannel);,void uart_txempty(int nChannel);,char uart_getch(void);,char uart_getkey(void);,void uart_sendbyte(int nData);,void uart_sendstring(char*pString);,void uart_printf(char*fmt,.);,void timer_start(int nDivider);/Watchdog Timer is used.,int timer_stop(void);/Watchdog Timer is used.,void sys_init();/Interrupt,Port and UART,int get_uartID();,5.3.3,嵌入式程序设计中常用的,C,语言语句,C,语言语句格式为:,标号:,语句,;,C,语言语句很多,,常用到的有以下几种:,条件语句,swith,语句,循环语句,5.3.4,嵌入式程序设计中,C,语言的变量、数组、结构、联合,变量,存储类型,类型说明符,修饰符,标识符,初值,,标识符,初值,;,存储类说明符,:,auto,、,register,、,extern,、,static,类型说明符,:,char,、,unsigned char,int,、,unsigned,long,、,unsigned long,float,、,double,、,long double,struct,、,union,、,void,修饰符,:,const,、,volatile,const,int,a;volatile unsigned char*a;,标识符,:,变量名、*变量名等,数组,一维数组:,类型说明符,标识符,常量表达式,初值,初值,,;,char,标识符,=“,字符串”;,二维数组:,类型说明符 标识符,mn,初值表,初值表,;,指针数组和数组指针,类型说明符,*,标志符,常量表达式,=,地址,地址,,;,类型说明符 (*标志符),=,数组标识符,;,嵌入式程序设计中,C,语言的变量、数组、结构、联合,结构说明,存储类说明符,struct,结构原型名,类型说明标识符,,标识符,;,类型说明标识符,,标识符,;,标识符,=,初值表,,标识符,=,初值表,;,嵌入式程序设计中,C,语言的变量、数组、结构、联合,联合说明,存储类说明符,union,联合原型名,类型说明符,标识符,,标识符,;,类型说明符,标识符,,标识符,;,标识符,=,初值表,,标识符,初值表,;,5.4 嵌入式,C,语言程序设计实例,5.4.1,S3VCE40开发板,测试程序实例,5.4.2,嵌入式C语言程序编写的简单构架,5.4.3,Flash测试代码介绍,5.4.1,S3VCE40,开发板的,测试程序实例,我们以,S3VCE40,开发板上的各个功能模块的整个测试程序为例,介绍如何运用,C,语言进行基于,ARM,的嵌入式程序设计。该程序完成的功能如下所示:,实验板加电时数码管八段全亮;,LED1,、,LED2,轮流闪烁(频率近,1Hz,);,使用,PC,键盘操作;串口终端输出信息如图:,然后使用开发板上的,PC,键盘选择各部分功能测试操作,如下图:,程序源代码介绍,整个测试程序主文件main.c的代码构成图如下图所示,由BootLoader启动程序进入C语言主函数main()入口。,5.4.2嵌入式C语言程序编写的简单构架,#include,预,编译指令,个,C,语言代码,一般要用,#include,编译指令将所需要的头文件加到该程序中,这是很有必要的,尤其是对编写较大的程序代码时。随后是定义一些外部变量,并对程序中的函数进行声明。,主函数,main,(),的编写;,在每一个,C,语言代码中,一定要有一个,main,(),函数,在该函数中完成该程序文件所要完成的各个功能,一般是通过调用各个子函数来完成。当然,它也可以调用其他文件中的函数。,完成相应功能的各个功能函数的编写。,各个函数之间可以相互调用。,5.4.3Flash测试代码介绍,下面给出,功能测试程序中,Flash,测试程序的代码结构图:,5.5 嵌入式C语言程序设计技巧,5.5.1 变量定义,5.5.2 参数传递,5.5.3 循环条件,5.5.1,变量定义,在变量声明的时候,最好把所有相同类型的变量放在一起定义,这样可以优化存储器布局。,由下例可以看出:,对于局部变量类型的定义,使用,short,或,char,来定义变量并不是总能节省存储空间。有时使用,32,位,int,或,unsinged,int,局部变量更有效率一些,如下图所示:,变量定义中,为了精简程序,程序员总是竭力避免使用冗余变量。但有时使用冗余变量可以减少存储器访问的次数这可以提高系统性能。,errs为全局变量,void test1(void),errs+=f();,errs+=g();,Void test2(void),int local=errs;,local+=f();,local+=g();,errs=local;,5.5.2,参数传递,为了使单独编译的C语言程序和汇编程序能够互相调用,定义了统一的函数过程调用标准ATPCS。ATPCS定义了寄存器组中的R0R3作为参数传递和结果返回寄存器,如果参数数目超过四个,则使用堆栈进行传递。,内部寄存器的访问速度是远远大于存储器的,所以要尽量使参数传递在寄存器里面进行,即应尽量把函数的参数控制在四个以下。,5.5.3,循环条件,计数循环是程序中十分常用的流程控制结构,一般有以下两种形式:,for,(loop=1;loop New Workspace,,,系统弹出工程创建对话框。,在,Project name,编辑框中输入新建工程名,led_,int,,,Location,编辑框中输入保存该工程的目录路径,C:EmbestIDEEV4510led_int,。,选择,OK,按钮,创建新工程,led_,int,,,集成环境将创建与工程同名的,workplace,和,project,。,在工作区窗中选择右键菜单创建源文件夹并添加相关源文件。,工程的建立和配置,工程,配置,工程创建完成后,需要对工程进行配置,,Embest,IDE,才能正确的编译、链接和调试等。,选择,Project Settings,菜单项,弹出工程配置对话框,如下图所示,。,工程配置包括处理器的选择、仿真器配置、调试配置、目录配置、编译配置、汇编配置、链接配置,工程配置是整个软件开发过程中非常关键的一步。,5.7.5,在RAM中调试软件,软件的调试既可以在ROM区也可以在RAM区完成,由于RAM区可以很方便地读写,访问速度高,因此软件开发过程中的调试只要硬件条件许可,都应该在RAM区完成。,软件调试前需要完成以下几步:,编译链接工程,连接仿真器、评估板,程序下载,5.7.6,软件的固化,在RAM中调试通过的程序与最终固化到电路板的Flash中的程序有所区别,需要做以下改动:,在汇编器的预定义选项中设置,ROM=1,,,或者直接在,init.s,文件中增加“,.,equ,ROM”,。,在链接器的链接文件中选择,ldscript,.flash,。,重新编译程序。然后使用,Elf to Bin,工具将,led_int.elf,文件转换成二进制指令格式文件,led_int.bin,。,最后使用,Embest,Flash Programmer,将,led_int.bin,下载到电路板的,Flash,中,如图所示。,5.7.7,程序在Flash中调试,程序在Flash中与在RAM中调试工程配置不同:,调试选项中不需要执行脚本文件,该工作在启动文件中完成,需要将连接后行为(,Action after connected,),选项改为无(,None,);,调试过程也有所不同:,连接仿真器后,无需再执行下载(,Download,),程序操作;,如果要从启动程序的入口开始调试程序,先必须执行复位(,reset,),命令,此时程序将停在零地址处;,程序在,Flash,中调试时最多可以设置两个硬件断点。,
展开阅读全文