Skip to main content
Graduate II
May 12, 2025
Question

M0 in-line assembler moving from bootloader to main app

  • May 12, 2025
  • 11 replies
  • 1542 views

Folks,

I have a bootloader for an M0 which works without using interrupts. It works in that it loads the new app, the CRC in the new app matches and I then try and jump to 0x8004000.

In the past I have used a couple of different methods with M3/4 to boot to the app from bootloader dependent on what compiler/IDE I was using, but the M0 is slightly different due to how the vector table is not relocatable. So we've come up with a method to get round that and "all" I need to do is jump to 0x8004000.

I *think I need something like this:

void jump_to_normal_application(void)
{

 u32 jump_address;

 jump_address = *(volatile u32*) (MAIN_PROG_START_ADDRESS + 4);
 jump_to_application = (pFunction) jump_address;

 asm("ldr sp, =0x20002000");

 jump_to_application();

}


I'm getting the error:

Error: lo register required -- `ldr sp,=0x20002000'

I've searched this and although I can find many hits  I can't see anything vaguely relevant to my situation.

Also, I would like to make 0x20002000 on line 9 top be a #define or loading from a C variable


Can anyone help me with this please? __Set_MSP is not available to me due to the, errr, "individual" setup I am forced to use.

What is the way to do this and are any of my assumptions above even vaguely correct? Am using gcc.

    This topic has been closed for replies.

    11 replies

    Graduate
    May 20, 2025

    @DiBosco When I sometimes want to look to value I use my small function which convert data from R1 register to ASCII HEX string to buffer pointed in R0 register.
    Declaration in C looks:

    extern void my_htoa32(char * buf, uint32_t data);

     

    But if you want invoke this from assembler you should to do:

     ldr r0, = 0x20000369 // for example a free area for use as buffer 11 bytes
     ldr r1, = 0x42408200 // value for tested
     BL my_htoa32
     lll:
     b lll // neverending loop

     

    Function my_htoa32:

     .syntax unified
     .cpu cortex-m0
     .fpu softvfp
     .thumb
    
     .thumb_func
     .global my_htoa32
     .type my_htoa32, %function
    
    
     .text
    //----------------
    
    //======================================================
    // HEX 32BIT value convert to string
    //====================================
     // INPUT:
     // R0, = ; POINTER TO OUTPUT char DATA BUFFER
     // R1, = ; VALUE TO HEXADECIMAL CONVERT
    
     // output: no output, data in buffer are output
    //=======================================================
    //=========================
    my_htoa32:
    
     MOV R3, 0x7830 // "0x"
     STRH R3, [R0] // STORE "0x" TO BUFFER
     MOVS R3, 2 // output data 2 bytes after start buffer
    //--
    LP01:
     LSRS R2, R1, #28 // R2 = OUR DATA TO STRING CONVERT 1 BYTE = NYBBLE 0..F
     LSLS R1, R1, #4 // R1 * 16 = R1 << 4
     ADDS R2, R2, #0x30 // CONVERT TO NUMBER
     CMP R2, #0x3A
     BCC LP01A // if data < than 0x3a don't add #7
     ADDS R2,R2, 0x07 // CONVER TO LETTER
    LP01A:
     STRH R2, [R0, R3] // STRH store byte and zero terminated
     ADDS R3, R3, #1
     CMP R3, #10
     BNE LP01
    //---
     BX LR
    //=============================================================

     

    The result you can observe in STM32 Link Utility or in Cube Programmer:

     

    utility.jpg