我目前正在研究ARM Cortex M3的引导程序。
我有两个函数,一个在 C 中,另一个在程序集中,但当我尝试调用汇编函数时,我的程序挂起并生成某种错误。
功能如下,
C:
extern void asmJump(void* Address) __attribute__((noreturn));
void load(void* Address)
{
asmJump(Address);
}
装配
.section .text
.global asmJump
asmJump: @ Accepts the address of the Vector Table
@ as its first parameter (passed in r0)
ldr r2, [r0] @ Move the stack pointer addr. to a temp register.
ldr r3, [r0, #4] @ Move the reset vector addr. to a temp register.
mov sp, r2 @ Set the stack pointer
bx r3 @ Jump to the reset vector
我的问题是:
代码通过串行输出“Hello”,然后调用load
。加载的代码打印“Good Bye”,然后重置芯片。
如果我慢慢单步执行load
调用asmJump
的部分,一切都会完美无缺。但是,当我让代码运行时,我的代码会遇到'内存错误'。我知道这是一个内存错误,因为它以某种方式导致Hard Fault
(当我在4或5秒后暂停时,Hard Fault处理程序无限循环执行。)
之前有没有人遇到过这个问题?如果是的话,请你告诉我如何解决它?
正如您所看到的,我尝试使用函数属性来解决问题但尚未设法解决问题。我希望有人可以帮我理解问题所在。
修改
感谢@JoeHass的回答,以及@MartinRosenau的评论,我已经找到了this SO answer,它对我为什么需要这个标签进行了非常彻底的解释。这是一个很长的阅读,但值得。
答案 0 :(得分:8)
我认为你需要告诉汇编器使用统一语法并明确声明你的函数是一个拇指函数。 GNU汇编程序具有以下指令:
.syntax unified
.section .text
.thumb_func
.global asmJump
asmJump:
.syntax unified
指令告诉汇编程序您正在使用汇编代码的现代语法。我认为这是一些遗留语法的遗憾。
.thumb_func
指令告诉汇编器该函数将以拇指模式执行,因此用于符号asmJump
的值的LSB设置为1。当Cortex-M执行分支时,它会检查目标地址的LSB以查看它是否为1。如果是,则目标代码以拇指模式执行。由于这是Cortex-M支持的唯一模式,如果目标地址的LSB为零,则会出错。
答案 1 :(得分:1)
由于您提到调试器正在运行,请使用它!
查看故障状态寄存器determine the fault source。也许它不会asmJump
崩溃,而是你正在调用的代码。
答案 2 :(得分:0)
如果这是你的所有代码..我想你的SP更改称为段错误或类似的东西。 您应该在更改SP之前保存它,并在使用它之后将其恢复。
ldr r6, =registerbackup
str sp, [r6]
#your code
...
ldr r6, =registerbackup
ldr sp, [r6]