سؤال

I'm currently working on a bootloader for an ARM Cortex M3.

I have two functions, one in C and one in assembly but when I attempt to call the assembly function my program hangs and generates some sort of fault.

The functions are as follows,

C:

extern void asmJump(void* Address) __attribute__((noreturn));

void load(void* Address)
{
    asmJump(Address);
}

Assembly:

.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

And my problem is this:

The code prints "Hello" over serial and then calls load. The code that is loaded prints "Good Bye" and then resets the chip.

If I slowly step through the part where load calls asmJump everything works perfectly. However, when I let the code run my code experiences a 'memory fault'. I know that it is a memory fault because it causes a Hard Fault in some way (the Hard Fault handler's infinite while loop is executing when I pause after 4 or 5 seconds).

Has anyone experienced this issue before? If so, can you please let me know how to resolve it?

As you can see, I've tried to use the function attributes to fix the issue but have not managed to arrive at a solution yet. I'm hoping that someone can help me understand what the problem is in the first place.

Edit:

Thanks @JoeHass for your answer, and @MartinRosenau for your comment, I've since went on to find this SO answer that had a very thorough explanation of why I needed this label. It is a very long read but worth it.

هل كانت مفيدة؟

المحلول

I think you need to tell the assembler to use the unified syntax and explicitly declare your function to be a thumb function. The GNU assembler has directives for that:

  .syntax unified
  .section .text
  .thumb_func
  .global asmJump
asmJump:

The .syntax unified directive tells the assembler that you are using the modern syntax for assembly code. I think this is an unfortunate relic of some legacy syntax.

The .thumb_func directive tells the assembler that this function will be executed in thumb mode, so the value that is used for the symbol asmJump has its LSB set to one. When a Cortex-M executes a branch it checks the LSB of the target address to see if it is a one. If it is, then the target code is executed in thumb mode. Since that is the only mode supported by the Cortex-M, it will fault if the LSB of the target address is a zero.

نصائح أخرى

Since you mention you have the debugger working, use it!

Look at the fault status registers to determine the fault source. Maybe it's not asmJump crashing but the code you're invoking.

If that is your all your code.. I suppose your change of SP called the segment error or something like that. You should save your SP before changing it and restore it after the use of it.

ldr r6, =registerbackup
str sp, [r6]
#your code
...
ldr r6, =registerbackup
ldr sp, [r6]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top