05-基于ARM的嵌入式程序设计.ppt

上传人:本田雅阁 文档编号:3456149 上传时间:2019-08-27 格式:PPT 页数:50 大小:1.16MB
返回 下载 相关 举报
05-基于ARM的嵌入式程序设计.ppt_第1页
第1页 / 共50页
05-基于ARM的嵌入式程序设计.ppt_第2页
第2页 / 共50页
05-基于ARM的嵌入式程序设计.ppt_第3页
第3页 / 共50页
05-基于ARM的嵌入式程序设计.ppt_第4页
第4页 / 共50页
05-基于ARM的嵌入式程序设计.ppt_第5页
第5页 / 共50页
点击查看更多>>
资源描述

《05-基于ARM的嵌入式程序设计.ppt》由会员分享,可在线阅读,更多相关《05-基于ARM的嵌入式程序设计.ppt(50页珍藏版)》请在三一文库上搜索。

1、第 5 章,基于 ARM 的嵌入式程序设计,主要内容:,ARM 汇编语言程序设计,C 与汇编语言混合编程,ARM 汇编语言编程示例,一、ARM 汇编语言程序设计,1、两种常用IDE简介 2、ADS/SDT下的伪操作 3、ARM汇编语言伪指令 4、ARM汇编语言的文件和语句 5、ARM汇编语言编程的几个问题 6、ARM汇编语言编程示例,1、两种常用 IDE 简介,ADS/SDT IDE开发环境:它由ARM公司开发,使用了CodeWarrior公司的编译器; 集成了GNU开发工具的IDE开发环境:它由GNU的汇编器as、交叉编译器gcc、和链接器ld等组成。,2、ADS/SDT 下的伪操作,ADS

2、编译环境下的伪操作可分为以下几类: 符号定义(Symbol Definition)伪操作 数据定义(Data Definition)伪操作 汇编控制(Assembly Control)伪操作 信息报告(Reporting)伪操作 其他(Miscellaneous)伪操作,符号定义(Symbol Definition)伪操作,数据定义(Data Definition)伪操作,汇编控制(Assembly Control)伪操作,信息报告(Reporting)伪操作,其他(Miscellaneous)伪操作,3、ARM 汇编语言伪指令,4、ARM 汇编语言的文件和语句,ARM汇编语言语句格式如下所示

3、: symbol instruction|directive|pseudo-instruction ;comment 其中: instruction为指令 directive为伪操作 pseudo-instruction为伪指令 symbol为符号 comment为语句的注释,ARM汇编语言是以段(section)为单位来组织源文件的。段是相对独立的、具有特定名称的、不可分割的指令或者数据序列。一个ARM源程序至少需要一个代码段,大的程序可以包含多个代码段和数据段。,ARM汇编语言源程序的基本结构举例:,AREA Example,CODE,READONLY ENTRY start MOV R0

4、,#40 MOV R1,#23 ADD R0,R0,R1 END 程序体部分实现了一个简单的加法运算。,5、ARM 汇编语言编程的几个问题,ARM数据处理操作 设置条件码 汇编语言子程序调用及返回 跳转表思想 ARM与Thumb之间的状态转换及函数的互相调用,32位立即数在32位指令中的编码以及ARM特有的寄存器移位操作是数据处理方面的难点,ARM数据处理操作,ARM的任何数据处理指令都能通过增加“S”操作码来设置条件码N、Z、C、V。 每条指令都可以条件执行。 在程序中可以通过条件码的使用让微处理器决定是否进行转移,还可用来控制循环的退出。,设置条件码,汇编语言子程序调用及返回,在ARM汇编

5、语言中,子程序调用是通过BL指令来完成的。BL subname 其中,subname是被调用的子程序的名称。 在返回调用子程序时,转移链接指令保存到LR寄存器(R14)中的值需要拷贝回程序寄存器PC(R15)。,跳转表思想,在程序设计中,有时为使程序完成一定的功能,需要调用一系列子程序中的一个,而决定究竟调用哪一个由程序的计算值确定。跳转表是解决该问题的有效方案。跳转表是利用程序计数器PC在通用寄存器文件中的可见性来实现的,如下例所示:,ARM与Thumb之间的状态转换及函数的互相调用,ARM/Thumb之间的函数调用时: 在同一状态下的子程序调用、返回,通常都只需要一条指令实现:BL fun

6、ction 和 MOV PC,LR 在不同状态下的子程序调用中,就需要进行状态之间的切换,需要考虑到以下几点: 需要由BX来切换状态,因为BL不能完成状态切换。 需要在BX之前先保存好LR,BX不能自动保存返回地址到LR。 需要 用“BX LR”来返回,不能使用“MOV PC,LR”,返回时要仔细考虑保存在LR中最低位是否正确。,6、ARM 汇编语言编程示例,AREA ARMex,CODE,READONLY ENTRY start MOV R1,#10 MOV R2,#3 ADD R1,R1,R1 stop MOV R0,#0x18 LDR R1,=0x20026 SWI 0x123456 ;

7、将CPU控制权交给调试器 END,示例 1:简单的ARM指令程序,AREA Block,CODE,READONLY NUM EQU 20 ENTRY LDR R0 , = src LDR R1 , = dst MOV R2 , # NUM MOV SP , # 0x400 Bcopy MOVS R3 , R2 , LSR # 3 BEQ Cword STMFD SP ! , R4 - R11 Ocopy LDMIA R0 ! , R4 - R11 STMIA R1 ! , R4 - R11 SUBS R3 , R3 , # 1 BNE Ocopy,示例 2:数据块批量复制程序(一次8字,不足则

8、单字复制),LDMFD SP ! , R4 - R11 Cword ANDS R2 , R2 , # 7 BEQ Stop Wcopy LDR R3 , R0 , # 4 STR R3 , R1 , # 4 SUBS R2 , R2 , # 1 BNE Wcopy Stop MOV R0 , # 0x18 LDR R1 , = 0x20026 SWI 0x123456 ;将CPU控制权交给调试器 AREA Bdata,DATA,READWRITE src DCD 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4 dst DCD 0,0,0,0,0,0,0,0,

9、 0,0,0,0,0,0,0,0, 0,0,0,0 END,二、C 与汇编语言混合编程,1、嵌入式C语言程序设计的几个问题 2、C与汇编语言混合编程及示例,1、嵌入式 C 语言程序设计的几个问题, 变量定义 参数传递 循环条件,在变量声明的时候,最好把所有相同类型的变量放在一起定义,这样可以优化存储器布局。由下例可以看出: 对于局部变量类型的定义,使用short或char来定义变量并不是总能节省存储空间。有时使用32位int或unsinged int局部变量更有效率一些,如下图所示: 变量定义中,为了精简程序,程序员总是竭力避免使用冗余变量。但有时使用冗余变量可以减少存储器访问的次数这可以提高

10、系统性能。, 变量定义,为了使各自单独编译的C语言程序和汇编程序能够互相调用,定义了统一的函数过程调用标准ATPCS。ATPCS规定寄存器组中的R0R3作为参数传递和结果返回寄存器,如果参数数目超过四个,则使用堆栈进行传递。 内部寄存器的访问速度是远远大于存储器的,所以要尽量使参数传递在寄存器里面进行,即应尽量把函数的参数控制在四个以下。, 参数传递, 循环条件,计数循环是程序中常用的流程控制结构,一般有以下两种形式: for (loop=1;loop=limit;loop+) for (loop=limit;loop!=0;loop-) 这两种循环形式在逻辑上并没有差别,但是映射到具体的体系

11、结构中时,就产生了不同,如下图所示:,2、C 与汇编语言混合编程及示例, ATPCS 规则 内嵌汇编 C和ARM汇编程序间相互调用, ATPCS 规则,ATPCS(ARM-Thumb Produce Call Standard)是ARM程序和Thumb程序中子程序调用的基本规则,目的是为了使单独编译的C语言程序和汇编程序之间能够相互调用。 这些基本规则包括子程序调用过程中寄存器的使用规则、数据栈的使用规则和参数的传递规则。,寄 存 器 的 使 用 规 则,根据堆栈指针指向位置的不同 和增长方向的不同可以分为以下4种数据栈 : FD (Full Descending) 满递减 ED (Empty

12、 Descending)空递减 FA (Full Ascending) 满递增 EA (Empty Ascending) 空递增 ATPCS规定数据栈为FD(满递减)类型,并且对数据栈的操作是8字节对齐的。,数据栈的使用规则,参数个数固定的子程序参数传递规则: 第一个整数参数,通过寄存器R0R3来传递。其他参数通过数据栈传递。 参数个数可变的子程序参数传递规则: 当参数不超过4个时,可以使用寄存器R0R3来传递参数;当参数超过4个时,还可以使用数据栈来传递参数 子程序结果返回规则 结果为一个32位整数时,可以通过寄存器R0返回;结果为一个64位整数时,可以通过寄存器R0和R1返回,依次类推。,

13、参数的传递规则,在C程序中嵌入汇编程序可以实现一些高级语言没有的功能,并可以提高执行效率。 armcc和armcpp内嵌汇编器支持完整的ARM指令集;tcc和tcpp用于Thumb指令集。所以,同一个C程序中不能同时包含ARM指令和Thumb指令。 内嵌的汇编指令包括大部分的ARM指令和Thumb指令,但是不能直接引用C的变量定义,数据交换必须通过ATPCS进行。 嵌入式汇编在形式上表现为独立定义的函数体。, 内嵌汇编,内嵌汇编示例:,# include void astrcpy(char *p1,char *p2) char tempch; _asm loop:LDRB tempch,p1,

14、#1 STRB tempch,p2,#1 CMP tempch,#0 BNE loop ,void main() 定义并初始化str1、str2, 定义字符串tempstr _asm MOV R0,str1 MOV R1,str2 MOV R2,tempstr BL astrcpy,(R0,R2) BL astrcpy,(R1,R0) BL astrcpy,(R2,R1) , C和ARM汇编程序间相互调用,遵守ATPCS的前提下,注意export和extern的配合使用,示例:C程序调用汇编程序,#include extern void strcpy(char *,char *) void m

15、ain() char *src=“source”; char *dst=“destination”; strcpy(dst,src); printf(“%sn%sn”,src,dst); ,area Scopy,code,readonly export strcpy strcpy LDRB R2,R1,#1 STRB R2,R0,#1 CMP R2,#0 BNE strcpy MOV PC,LR end,示例:汇编程序调用C程序,int g(int a,int b,int c,int d,int e) return a+b+c+d+e; C程序用于计算五个数之和 汇编程序则把四个放入R0R3,

16、 最后一个放在数据栈内; 编译器判断出需要几个参数, 自动取得。,area f,code,readonly extern g STR LR,SP,#-4! ADD R1,R0,R0 ADD R2,R1,R0 ADD R3,R1,R2 STR R3,SP,#-4! ADD R3,R1,R1 BL g ADD SP,SP,#4 LDR PC,SP,#4 end,1、求两个向量的点积 2、SWI 软件中断 3、IRQ 中断 4、异常中断向量表的搬运,三、ARM 汇编语言编程示例,例程 1:求两个向量的点积,#include #define low32(a) (unsigned *) ,_int64

17、dotprod(int *a, int *b, unsigned n) _int64 sum=0; do sum += mlal(sum, *a+, *b+); while(-n!=0) return sum; _int64 mlal(_int64 sum, int a, int b) _asm SMLAL low32(sum), high32(sum), a, b return sum; ,例程 2:SWI 软件中断,执行SWI指令时系统自动完成以下工作: R14_SVC = SWI指令的下面一条指令的地址 SPSR_SVC = CPSR CPSR4:0= 0b10011 CPSR5= 0

18、CPSR7= 1 ; 禁止响应 IRQ 中断 PC = 0x00000008,SWI中断处理程序(与系统相关的ARM指令代码) SWISTART: STMFD SP!, R0-R3, R12, LR MRS R0, SPSR TST R0, #0x20,LDRNEH R0, LR, #-2 ; 读SWI立即数 BICNE R0, R0, #0xFF00 LDREQ R0, LR, #-4 BICEQ R0, R0, #0xFF000000 CMP R0, #MaxSWI ; 判断是否越界 LDRLS PC, PC, R0, LSL #2 B SWI_OutofRange ; 占4 个字节 SW

19、ITable: DCD DOSWI_0 DCD DOSWI_1 DOSWI_0: LDMFD SP!, R0-R3, R12, PC DOSWI_1: LDMFD SP!, R0-R3, R12, PC,例程 3:IRQ 中断,响应IRQ中断请求时系统自动完成以下工作: R14_IRQ = 当前PC+8 SPSR_IRQ = CPSR CPSR4:0= 0b10010 CPSR5= 0 CPSR7= 1 ; 禁止响应其他 IRQ 中断 PC = 0x00000018,IRQ中断处理程序(与系统相关的ARM指令代码) SUB R14, R14, #4 ; 前面加 8,此处减 4 STMFD R1

20、3!, R12, R14 MRS R12, SPSR ; 允许IRQ中断嵌套 STMFD R13!, R12 MOV R12, #IntBase ; 中断源提供功能号 LDR R12, R12, #IntLevel,MRS R14, CPSR ; 允许响应IRQ中断 BIC R14, R14, #0x80 MSR CPSR_C, R14 LDR PC, PC, R12, LSL #2 NOP ; 用于占4 字节而已 DCD INT0 DCD INT1 INT0: STMFD R13!, R0-R11 MRS R12, CPSR ORR R12, R12, #0x80 MSR CPSR_C, R

21、12 ; 禁止响应IRQ中断 LDMFD R13!, R0-R12 MSR SPSR_CXSF, R12 LDMFD R13!, R12, PC ; 逆序恢复现场 INT1: STMFD R13!, R0-R11 ,例程 4:异常中断向量表的搬运,当操作系统配置为地址 0x0 处为RAM,而不是ROM时,在引导操作系统前应从ROM中搬运(复制)异常中断向量表到RAM,以保证各异常的正常响应。 假定,保存在ROM中的异常中断向量表和异常中断向量处理程序入口地址为:,Export Int_Vectors ;异常中断向量表 Int_Vectors: LDR PC , Int_Table LDR PC

22、 , (Int_Table + 4) LDR PC , (Int_Table + 8) LDR PC , (Int_Table + 12) LDR PC , (Int_Table + 16) LDR PC , (Int_Table + 20) LDR PC , (Int_Table + 24) LDR PC , (Int_Table + 28),Export Int_Table ;异常中断处理程序的入口点函数 Int_Table: Int_Initialize_Addr DCD Int_Initialize Undef_Instr_Addr DCD Undef_Instr_ISR SWI_Ad

23、dr DCD SWI_ISR Prefetch_Abort_Addr DCD Prefetch_Abort_ISR Data_Abort_Addr DCD Data_Abort_ISR Undef_Addr DCD 0 ;暂时无定义 IRQ_Handler_Addr DCD Int_IRQ_Parse FIQ_Handler_Addr DCD Int_FIQ_Parse,通常,这二者需要放在最低地址(对小端存储模式 而言)也即物理地址 0x0 处。,定义部分空间,在设置新的异常中断向量时,用于保存原来的异常中断向量: OLD_Undef_Vect DCD 0x00000000 OLD_Unde

24、f_Addr DCD 0x00000000 OLD_SWI_Vect DCD 0x00000000 OLD_SWI_Addr DCD 0x00000000 OLD_IRQ_Vect DCD 0x00000000 OLD_IRQ_Addr DCD 0x00000000 OLD_FIQ_Vect DCD 0x00000000 OLD_FIQ_Addr DCD 0x00000000,;Undef ;SWI ;IRQ ;FIQ,下面的子程序用于设置异常中断向量表:分三个部分,Export Int_Install_Vector_Table Int_Install_Vector_Table : STMDB

25、 SP! , A1-A4 , LR ;保存工作寄存器以及返回地址 ;首先保存原异常中断向量表,以备后用 MOV A3 , # 0x04 ;Undef 异常中断向量 LDR A1 , A3 , # 0 LDR A2 , = OLD_Undef_Vect STR A1 , A2 , # 0 MOV A3 , # 0x24 LDR A1 , A3 , # 0 LDR A2 , = OLD_Undef_Addr STR A1 , A2 , # 0 ,MOV A3 , # 0x08 ;SWI 异常中断向量 LDR A1 , A3 , # 0 LDR A2 , = OLD_SWI_Vect STR A1

26、, A2 , # 0 MOV A3 , # 0x28 LDR A1 , A3 , # 0 LDR A2 , = OLD_SWI_Addr STR A1 , A2 , # 0 MOV A3 , # 0x18 ;IRQ 异常中断向量 LDR A1 , A3 , # 0 LDR A2 , = OLD_IRQ_Vect STR A1 , A2 , # 0 MOV A3 , # 0x38 LDR A1 , A3 , # 0 LDR A2 , = OLD_IRQ_Addr STR A1 , A2 , # 0 ,MOV A3 , # 0x1C ;FIQ 异常中断向量 LDR A1 , A3 , # 0 LD

27、R A2 , = OLD_FIQ_Vect STR A1 , A2 , # 0 MOV A3 , # 0x3C LDR A1 , A3 , # 0 LDR A2 , = OLD_FIQ_Addr STR A1 , A2 , # 0 ;然后将异常中断向量表以及处理程序入口地址从ROM复制到RAM中地址 0x0 开始的区域 MOV V5 , # 0 ;设定初始地址 ADR V6 , Int_Vectors LDMIA V6! , A1-V4 ;异常中断向量表 STMIA V5! , A1-V4 LDMIA V6! , A1-V4 ;处理程序入口地址 STMIA V5! , A1-V4 ,;最后,若需要回复某些异常中断向量如SWI原来的值,则可以: IF NU_Printf_Support MOV R0 , # 0x08 LDR R1 , OLD_SWI_Vect STR R1 , R0 , # 0 MOV R0 , # 0x28 LDR R1 , OLD_SWI_Addr STR R1 , R0 , # 0 ENDIF LDMIA SP! , A1-A4 , LR MOV PC , LR ;恢复工作寄存器并返回,至此,子程序 Int_Install_Vector_Table 结束,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1