您好,  [请登录] [QQ登录]  [支付宝登录[免费注册]

商品分类

分享到: 百度搜藏 搜狐微博 新浪微博 腾讯微博 QQ收藏 人人网 Facebook Twitter

ARM嵌入式体系停止向量表的动态配置

发布日期:2011-04-21

    摘 要:通常32位ARM嵌入式体系的停止向量表是在步伐编译前设置好的,每次编写停止步伐都要改C步伐的汇编启动代码,相称繁琐。本文给出一种配置ARM停止向量表新要领。该要领比通常要领仅增长一条指令实行时间,简便高效,成果完备,向量表在运行时动态天生,C步伐可以利用牢固向量表的启动代码,并可隐蔽起来。

    关键词:动态配置 嵌入式体系 ARM 停止向量表

一样平常32位ARM嵌入式体系的停止向量表是步伐编译前设置好的。在编写32位ARM嵌入式体系的停止办事步伐、设置和修改ARM体系布局的停止向量表时,常感触相称贫苦,不得不修改汇编代码,对不喜好利用汇编代码编程的步伐员尤其云云。当必要在步伐运行进程中动态修改停止向量的步伐时会感触更为不便,不得不增长很多分支处理惩罚指令才华实现。为此本文提出一种简便高效的配置要领,实现了ROM固化步伐在运行时动态配置ARM嵌入式体系停止向量表的成果。

1 ARM停止向量两种设置要领

在32位ARM体系中,一样平常都是在停止向量表中安排一条分支指令或PC寄存器加载指令,实现步伐跳转到停止办事例程的成果。比方:

IRQEntry B HandleIRQ ;跳转范畴较小

B HandleFIQ

或IRQEntry LDR PC,=HandleIRQ ;跳转的范畴是恣意32位地点空间

LDR PC,=HandleFIQ

LDR伪指令等效天生1条存储读取指令和1条32位常数定义指令。32位常数存储在LDR指令相近的存储单位中,相对偏移小于4KB。该32位数据便是要跳转到的停止办事步伐入口地点。

之以是利用LDR伪指令,是由于ARM的RISC指令为单字指令,不克不及装载32位的立即数(常数),无法直接把一个32位常数数据或地点数据装载到寄存器中。下面一样平常步伐与上述伪指令成果等效,但停止向量表形貌得更为清楚。此中VectorTable为相对LDR指令的偏移量:

IRQEntry LDR PC,VectorTable+0

;与LDR PC,=HandleIRQ等效

LDR PC,VectorTable+4

;与LDR PC,=HandleFIQ等效

……

VectorTable DCD HandleTRQ

DCD HandleFIQ

……

HandleIRQ

……

HandleFIQ

一样平常ARM嵌入式体系的步伐都是固化在从00000000H开始的低端ROM空间中,停止向量表VectorTable也是固化在ROM中,以是上述两种要领都无法在步伐运行时动态随机修改停止向量表。不论对付初学ARM处理惩罚器的步伐员还是有经历的步伐员,设置停止向量都相称繁琐,必须修改ARM的C步伐的启动代码。一段晦涩的汇编代码很不方便,比较容易堕落。

2 X86与ARM处理惩罚器停止向量表比较

实模式X86步伐员都熟习,在X86体系布局的PC体系中,不论是用汇编还是用C语言,都可以动态随机地设置、修改停止向量表—只必要大略地把停止步伐例程的入口地点写入到停止向量表数据区,即可完成向量表的设置。

X86向量表设置方便的缘故起因有两个。其一是停止向量表与步伐代码完全疏散,停止向量表设置在RAM数据空间,向量表存放的数据是纯粹地点数据;而在ARM向量表中存放的是与停止办事例程入口有关的一条分支指令。另一个缘故起因是,除BIOS外,大多数PC步伐都是在运行时加载到RAM中的,步伐数据是不加区别的,以是可以很容易在步伐运行的进程中从数据天生步伐,并可以很容易把CPU控制权转到新天生的步伐中。

外貌上看,在ARM第二种停止向量设置要领的向量表VectorTable中也是纯地点数据,不含指令代码,好像可以把VectorTable设置在RAM数据段中。然而一样平常ARM体系的ROM代码段和RAM数据段间的偏移宏大于2 12,故高出了LDR利用PC为基址的相对寻址范畴。

代码中的VectorTable是一个与当前PC间的一个偏移,LDR指令的相对地点是在编译时谋略的,请求VectorTable<2 12,以是VectorTable不克不及随意摆设在RAM空间中。VectorTable一样平常只能摆设在停止跳转指令相近的代码区内里。

3 ARM布局中停止向量表的动态配置要领

要在ARM布局中实现与X86中一样方便的在停止向量的随机存取成果,向量表的地点数据必须可以摆设在恣意32位地点的RAM空间中。为此,停止处理惩罚必须增长一条指令,先跳转到向量表,然后实行向量表中动态天生的跳转指令,跳转到停止办事步伐,拜见下列初始化代码:

;******向量表******

ENTRY

B ResetHandle ;原向量偏移 ,停止号

B ReseHandle ;0x00 ,00

LDR PC,=NewVectorTable+0x08 ;0x04,未定义 ,01

LDR PC,=NeWVector Table+0x10 ;0x08,SWI,02

LDR PC,=NewVectorTable+0x18 ;0x0c,未定义 ,03

LDR PC,=NewVectorTable+0x20 ;0x10,未定义 ,04

LDR PC,=NewVectorTable+0x28;0x14,未定义 0,05

LDR PC,=NewVectorTable+0x30 ;0x18,IRQ ;06

LDR PC,=NewVectorTable+0x38 ;0x1c,FIQ ,07

……

;******代码段******

ResetHandle

……

;***数据段,为NewVectorTable分派数据空间***

NewVectorTable # 128;大小根据必要定义,每向量2个字(8字节);

步伐运行时,停止办事的初始化 步伐必须设置好新的停止向量表,即在NewVectorTable表中动态天生下列指令:

NewVectorTable;表摆设在RAM顶端0x0c1fff00处(由硬件设置)

LDR PC,[PC,#4];指令代码为0xe51ff004,成果为PC〈-[PC+4]

nVt00 DCD ISR_RESET_HANDLE

LDR PC,[PC,#4];与LDR PC,nVt01指令等效

nVt01 DCD ISR_UNDEF_HANDLE

LDR PC,[PC,#4]

nVt02 DCD ISR_SWI_HANDLE

LDR pC,[PC,#4]

nVt03 DCD ISR_UNDEF_HANDLE

LDR PC,[PC,#4]

nVt04 DCD ISR_UNDEF_HANDLE

LDR PC,[PC,#4]

nVt05 DCD ISR_UNDEF_HANDLE

LDR PC,[PC,#4]

NVt06 DCD ISR_IRQ_HANDLE

LDR PC,[PC,#4]

nVt07 DCD ISR_FIQ_HANDLE

……

可用C函数在NweVectorTable中天生含上述指令的向量表,详细实现如下:

#define VECTOR_TABLE 0x0c1fff00

//向量表首地点,根据实际硬件来配置

#define INSTRUCTION_LDR_PC 0xe51ff004

//加载PC寄存器的指令码

//设置向量C函数,ISR_Handle停止办事步伐地点

void SetVector(unsigned char no,unsigned long int ISR_Handle){

unsigned long int * pVectorTable;

//定义32位无标记数指令,指向向量表

pVectorTable=((unsigned long int *)(VECTOR_TABLE+(no<<3)));

*pVectorTable++=INSTRUCTION_LDR_PC;

//在向量表中安排LDR PC,[PC,#4]指令

*pVectorTable=ISR_Handle;//设置停止办事例程入口地点

}

//读取向量C函数,no代表停止号

unsigned long int GetVector(unsigned char no){

unsigned long int *pVectorTable;

pVectorTable=((unsigned long int *)(VECTOR_TABLE+(no<<3)));

return *(++pVectorTable);//返回停止处理惩罚步伐入口地点

}

利用上述初始化代码和向量设置函数,除复位向量外,别的全部停止向量都可以指向了在RAM数据区中的新向量表,并给定一个同一的停止编号。停止办事步伐可以放在任意模块文件中编译连接,不必要修改原向量表代码,但在打开停止利用停止办事例程前必须利用C函数SetVector()设置停止向量。

4 结论

本文提出的停止向量表配置战略和实现要领,简便高效,仅比标准处理惩罚要领增长一条指令的实行时间。当把ARM的C初始化汇编代码中全部停止源(包括扩展的表里部停止源)的向量都指向了新向量表,并同一编号,以后编写任意停止办事步伐险些不必要修改汇编代码,C初始化代码完全可以对C步伐员隐蔽起来,并可以像在X86体系下一样动态地设置和修改停止向量。