关于LPC24XX的程序移植
近来单片机升级了,一下子进入32位时代,有点措手不及!还好,网络互相的现代,工程师不必从头开始,充分利用网络资源,加快开发进程。由于以前一直使用KEIL开发51单片机,使用方便,便于调试仿真。值得庆幸的是现在ARM型单片机也可以在KEIL中调试。可是网上大部分ARM实例是基于ADS的。直接移植过来就会一警告和错误。
为了加快开发进程,还是选择移植借鉴部分实用例程。具体解决问题方法如下:
新推出的KEIL版开发工具RVMDK与老版ADS在工具架构组成上有以下不同:ARM编译器版本、调试器、软件仿真、以及调试单元。
出现如下提示:
USBdma.h(128): warning: #1-D: last line of file ends without a newline
compiling USBDriver.c...
USBHAL.h(40): warning: #1-D: last line of file ends without a newline
USBdma.h(128): warning: #1-D: last line of file ends without a newline
提示:"文件结束了但没有空行"这个警告, 这是由RVMDK编译器产生的警告,所有程序文件最后一行必须有空行,也可不去理它。在提示处按一下回车就行了。
Startup.s(214): warning: A1608W: MOV pc,<rn> instruction used, but BX <rn> is preferred
Startup.s(258): warning: A1608W: MOV pc,<rn> instruction used, but BX <rn> is preferred
由于编译器版本的变化,对应的编译选项也有所变化。将options for target中asm标签页里面的Eenable ARM/Thumb interworking复选框去掉,就不产生这样的告警信息啦,不过不知道这样做会影响什么!
也可以根据提示改为BX跳转。如果您的程序中存在ARM/Thumb指令相互调用的情况,那么使用BX指令能够返回到正确的处理器状态。而使用MOV指令则不能实现处理器状态的切换。所以keil编译器建议您使用BX指令。例如把MOV PC, LR 改为BX LR 。
fio_release.axf: Error: L6238E: startup.o(vectors) contains invalid call from '~PRES8' function to 'REQ8' function FIQ_Exception.
fio_release.axf: Error: L6238E: startup.o(vectors) contains invalid call from '~PRES8' function to 'REQ8' function TargetResetInit.
这是由于对目标文件进行链接时,ARM工具的连接器会严格检查各个文件(objects),判断它们是否复合ARM体系结构的ABI表准。由于RVCT与ADS编译链接工具所遵循的ARM ABI不同,所以将ADS的遗留工程直接移植到RVMDK并进行连接时,用户可能会遇到错误或者警告:新工具的ABI要求在函数调用时,系统必须保证堆栈指针8byte对齐,即每次进栈或者出栈的寄存器数目必须为偶数。这是为了能够更加高效的使用STM与LDR指令对“double”或者“long long”类型的数据进行访问。而老的ARM开发工具ADS并没有考虑到新的ARM内核架构,其ABI对于堆栈的操作仅仅要求4byte对齐。所以当用户将在ADS中编译连接成功的工程代码移植到RVMDK上,或者将老的、ADS遗留的目标文件、库文件在新工具RVMDK中进行连接时,RVMDK的连接器就会报出以上的错误。
解决方法如下:
在每个汇编文件的开头,添加“PRESERVE8”指令。
AREA vectors,CODE,READONLY之前加 PRESERVE8。
如下:
AREA vectors,CODE,READONLY
改为:
PRESERVE8
AREA vectors,CODE,READONLY
检查汇编源码中的指令,确保堆栈操作指令是8byte对其的。ADS的遗留代码一次性将5个寄存器压栈,由于ARM的指令寄存器宽度为32位,即4byte,显然5个寄存器入栈之后,堆栈指针不能够满足64位,8byte对齐。为了解决这种情况,我们可以将另外一个并不需要压栈的寄存器,R12,同时压栈,这样当6个32位寄存器进栈之后,堆栈就能满足64位对齐了。
如: STMFD SP!, {R0-R3, LR}改为:STMFD SP!, {R0-R3, R12,LR}
好了通过以简单的更改,程序通过了。由于接触时间太短,分享的只是解决方法,详细部分还不太清楚。希望共同讨论!