3
votes

I am coding a small cortex M0+ bootloader. I have a inline assembly below that start the main application from the bootloader by loading the stack pointer and reset handler from application position in Flash.

#define FLASH_APP_START 0x1000

[...]

    __asm(
            // Update stack pointer from user code vector table
            "LDR     r0, =%0 \n"
            "LDR     r1, [r0] \n"
            "MOV     sp, r1 \n"

            // Load user code reset handler and jump to the user code
            "LDR     r0, [r0, #4] \n"
            "BX      r0 \n"
            :
            : "X"(FLASH_APP_START)
            :
        );

When compiling this code I get the following error:

Error: bad expression -- `ldr r0,=#4096'

GCC add the # before the constant that should not be there. If I replace the first line by the following it works perfectly.

LDR r0, =0x1000

So the question is how could I use the defined constant ?

Thanks in advance for any help

1
A few thoughts: You are changing r0 and r1 in this template without clobbering them. That seems bad. As for the #, you could try %c0.David Wohlferd
A capital 'R' as a constraint for the literal pool is improperly documented in the gcc manual. David's suggestion is correct; use the '%creg' modifier as per godbolt example. The manual has this under the title 'Modifier Description '.artless noise
A related question on inline assembler and the constant pool.artless noise

1 Answers

1
votes

First there's as no reason to use inline assembly here, the simple solution would be to just write this code as a normal assembly language file. You can define the FLASH_APP_START macro in a header file that you can include in both the assembly and C source files if necessary.

If you still want to use inline assembly then next simplest solution would be to let the compiler do most of the work for you and reduce the assembly statement to just what it can't do:

    void ** const flash_vector_table = (void **) FLASH_APP_START;
    asm volatile ("mov sp, %[stack]\n\t"
                  "bx %[reset]\n"
                  :
                  :
                  [stack] "r" (flash_vector_table[0]),
                  [reset] "r" (flash_vector_table[1]));