|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
<strong>引言</strong>
在前面的文章中提到过,很多情况下应用程序需要在ARM跟Thumb状态之间相互切换,这部分就讨论交互工作的实现方法和一些注意问题。
<strong>1需要交互的原因</strong>
前面提到过,Thumb指令在某些特殊情况下具有比ARM指令更为出色的表现,主要是在代码长度和窄带宽存储器系统性能两方面。正是因为Thumb指令在特定环境下的优势,它在很多方面得到了广泛应用。但是因为下面一些原因,Thumb又不可能独立地组成一个应用系统。
◇ Thumb指令集在功能上只是ARM指令集的一个子 集,某些功能只能在ARM状态下执行,如CPSR和 协处理器的访问。
◇ 进行异常响应时,处理器会自动进入ARM状态。
◇ 从系统优化考虑,在宽带存储器上不应该放置 Thumb代码,很多窄带系统具有宽带的内部存储器。
◇ 即使是一个单纯的Thumb应用系统,也必须加一 个汇编的交互头程序,因为系统总是自动从ARM 开始启动。
所以,不可避免地会产生ARM与Thumb之间交互的问题。
<strong>2状态切换的实现</strong>
处理器在 ARM/Thumb之间的状态切换是通过一条专用的跳转交换指令BX来实现的。BX指令以通用寄存器(R0~R15)为操作数,通过拷贝Rn到PC来实现 4GB空间范围内的一个绝对跳转。BX利用Rn寄存器中存储的目标地址值的最后一位来判断跳转后的状态。如图1所示,是用BX指令实现状态切换。
<ignore_js_op>
2010-4-5 10:15:57 上传
<strong>下载附件</strong> (19.8 KB)
</ignore_js_op>
无论ARM还是Thumb,其指令存储在存储器中都是边界对齐的(4字节或2字节对齐)。因此,在执行跳转过程中,PC寄存器中的最低位肯定被舍弃,不起作用。在BX指令的执行过程中,最低位正好被用作状态判断的标识,不会造成存储器访问不对齐的错误。
图 2 中是一段直接进行状态切换的例程:
<ignore_js_op>
2010-4-5 10:15:57 上传
<strong>下载附件</strong> (36.46 KB)
</ignore_js_op>
下面是一段直接进行状态切换的例程。
;从ARM状态开始
CODE32 ;汇编关键字
ADR R0, Into_Thumb+1 ;得到目标地址,末位置1, ;转向Thumb
BX R0 ;执行 ? ;其它代码
CODE16 ;汇编关键字
Into_Thumb ;Thumb代码段起始地址
… ;Thumb代码
ADR R5, Back_to_ARM ;得到目标地址,末位缺 ;省为0,转向ARM
BX R5 ;执行
… ;其它代码
CODE32 ;汇编关键字
Back_to_ARM ;ARM代码段起始地址
我们知道,在ARM的状态寄存器CPSR 中,bit-5是状态控制位T-bit,决定当前处理器的运行状态。如果直接修改CPSR的状态位,也能够达到改变处理器运行状态的目的。但是这样会带来一个问题,因为ARM采用多级流水线的结构,所以在程序执行过程中,指令流水线上会存在几条预取指令(具体数目视流水线级数而不同)。当修改CPSR的 T-bit后,状态的转变会造成流水线上预取指令的执行错误。而如果用BX指令,则执行后会进行流水线的刷新动作,清除流水线上的残余指令,在新的状态下重新开始指令预取,从而保证状态转变时指令流的正确衔接。
<strong>3ARM/Thumb之间的函数调用</strong>
在无交互的子程序调用中,其过程比较简单。实现调用通常只需要一条指令:
BL function
实现返回也只需要从LR恢复PC即可:
MOV PC, LR
函数的调用过程如图3所示。
<ignore_js_op>
2010-4-5 10:15:57 上传
<strong>下载附件</strong> (14.57 KB)
</ignore_js_op>
如果子函数和父函数不在同一种状态下执行,因为状态切换,需要对函数调用作更多的考虑。
①BL不能完成状态切换,需要由BX来切换状态。
②BX不能自动保存返回地址到LR,需要在BX之前先保存好LR。
③用“BX LR”来返回,不能使用“MOV PC, LR”,因为这条指令同样不能实现状态切换。返回时要仔细考虑保存在LR中最低位的内容是否正确。
假如用户直接使用汇编语言进行状态交互跳转,上述的几个问题都需要用手工编码加以处理。如果用户使用高级语言进行开发,不需要为ARM/Thumb之间的相互调用增加额外编码,但是最好要对其调用过程加以了解。下面以ARM ADS中的编译工具为例进行说明,如图4所示。
<ignore_js_op>
2010-4-5 10:15:57 上传
<strong>下载附件</strong> (21.9 KB)
</ignore_js_op>
①两个函数func1()和func2()被编译成不同的指令集(ARM或Thumb)。
注意:func1()和 func2()在这里位于二个不同的源文件中。
②编译时必须告诉编译器和链接器足够的信息,一方面让编译器能够使用正确的指令码进行编译,另一方面,当在不同的状态之间发生函数调用时,链接器将插入一段链接代码(veneers)来实现状态转换。
上述过程中的一个特点是:func1()还是使用通常的BL指令来进行子程序调用,而 func2()返回时则直接使用“BX LR”,没有对LR进行判断和最低位的设置。这是因为当执行BL指令对LR进行保存时,其最低位会被自动设置,以满足返回时状态切换的需要,可直接使用 “BX LR”。
在上面的例子中,为了让编译器在编译函数func2()时使用BX而不是BL进行返回,必须告诉编译器要按照满足交互工作要求的方式进行编译。在ARM的编译器选项设置中,应选择“-apcs /interwork”。这样,函数的返回指令会被正确设置,并且当链接器进行目标代码的链接时,能够在需要的地方插入正确的链接代码实现状态切换。
当然,插入了链接代码会相应地增加代码长度,通常一段veneer包含3条指令,即12B字节长度。可以用“-info veneers”选项使链接器输出所有veneers的位置和长度信息。
<strong>4交互程序之间的兼容性</strong>
因为在指定交互选项后,编译及链接后的输出代码跟在无交互情况下不同,所以当多个源文件如果使用了不同的设置进行编译,相互之间的调用可能产生兼容性问题。图5说明了这些关系。
<ignore_js_op>
2010-4-5 10:15:58 上传
<strong>下载附件</strong> (27.81 KB)
</ignore_js_op>
在一个使用交互工作的项目工程管理中,对此要加以仔细考虑。
<strong>5V5架构的扩展</strong>
ARM在V5版本的架构中,对ARM/Thumb的交互增加了新的支持。针对前面第3节中提到的函数调用和返回问题,V5版本中专门对指令做了扩展。
①增加了新指令BLX,解决了原来BX和BL指令各自的欠缺。使交互的函数调用可以由一条指令实现,省去了跳转代码的开销。
②扩展了以PC为目标地址的数据传输指令功能。PC加载值的最低位将被自动送到状态寄存器CPSR的T状态位。也就是说,通过给PC赋值的方法也能实现状态的切换,这样就使习惯的函数返回方法——从堆栈中恢复寄存器,也能实现交互调用函数的正确返回了。
所以,V5架构以后的代码,不再需要额外的链接代码,缩小了代码长度,提高了状态切换时的执行效率。当然,在V5及以后的架构中,继续保持了对以前代码的良好兼容性。
<strong>6Thumb-2</strong>
ARM和Thumb因为其各自的优势,都得到了极为广泛的应用。在一个应用程序中,用户要根据系统的具体情况灵活分配,使用不同的编译器,把不同的代码编译成ARM或Thumb,以希望得到最优的代码长度和性能平衡。这样做能够达到系统优化的目的,但是也给设计人员带来了额外的交互处理工作。最近,ARM公司公布了一项新的发明——Thumb-2指令集,该指令集同时包含32位和16位指令,在代码长度和性能之间作了最佳的平衡。这样,以后用户就可以用一个统一的Thumb-2编译器来解决现在面临的很多问题了。
如图6所示,是Thumb-2指令集跟ARM和Thumb之间的比较。
<ignore_js_op>
2010-4-5 10:15:57 上传
<strong>下载附件</strong> (22.76 KB)
</ignore_js_op>
<strong>引证文献</strong>
1. 杨志强 嵌入式系统设计与发展 [期刊论文] -青海师范大学学报(自然科学版)2005(03)
2. 刘志勇 基于ARM的无线视频传输硬件系统的初步研究与开发 [学位论文] 硕士2005
3. 李晶 基于 LINUX的无线局域网芯片驱动程序的设计与开发 [学位论文] 硕士2005
作 者:ARM中国 费浙平
来 源:单片机与嵌入式系统应用 2003(12) |
|