This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM48L940: Jump from Bootloader to Application

Part Number: RM48L940

I'm trying to do a bootloader that jumps to an application. The following is what I've done so far:

  1. Created a bootloader project that configures the some peripherals and blink some LEDs. This works fine.
  2. Created a user application project that I want my bootloader to jump to (I'm not interested in loading from external source like SPI or UART yet; I just force app binary into flash and expect to jump to there).

The user application doesn't execute correctly. When I step through my bootloader I can see it jumping to the address I specify for the user application 0x00020000. 

When I step past my application start address of 0x00020000  I run into undefEntry (at address x4). This may be because my bootloader project doesn't have symbols for my application, but I'm not sure. Regardless, my application doesn't continue to execute even when I simply power up and expect it to run. Note that my application doesn't configure any devices - it just tries to write to a GPIO, the same one the bootloader configured and successfully used. Correct me if I need to reinitialize any peripherals after bootloader does it and jumps to app.

The following are my linker scripts. As you can tell I'm trying to locate my user application at 0x00020000. I've tried converting both boot and app output to raw binary and loading them at address 0x0 and 0x00020000 respectively and it doesn't make a difference. The bootloader always runs OK, but not the app. I'll appreciate any help in debugging this or addressing anything I missed.

BOOT_LINKER.cmd

/*----------------------------------------------------------------------------*/

define memory mem with size = 4G;

define region VECTORS = mem:[from 0x00000000 size 0x00000020];
define region FLASH = mem:[from 0x00000020 size 0x0017FFE0]
| mem:[from 0x00180000 size 0x00180000];
define region STACK = mem:[from 0x08000000 size 0x00001500];
define region RAM = mem:[from 0x08001500 size 0x0003eb00];
define block HEAP with size = 0x800, alignment = 8{ };

initialize by copy {readwrite};
do not initialize {section .noinit};

place in VECTORS {readonly section .intvecs};
place in FLASH {readonly};
place in RAM {readwrite};
place in RAM {block HEAP};
/*----------------------------------------------------------------------------*/

APP_LINKER.cmd

/*----------------------------------------------------------------------------*/

define memory mem with size = 4G;

define region VECTORS = mem:[from 0x00020000 size 0x00000020];
define region FLASH = mem:[from 0x00020020 size 0x0017FFE0]
| mem:[from 0x00180000 size 0x00180000];
define region STACK = mem:[from 0x08000000 size 0x00001500];
define region RAM = mem:[from 0x08001500 size 0x0003eb00];
define block HEAP with size = 0x800, alignment = 8{ };

initialize by copy {readwrite};
do not initialize {section .noinit};

place in VECTORS {readonly section .intvecs};
place in FLASH {readonly};
place in RAM {readwrite};
place in RAM {block HEAP};
/*----------------------------------------------------------------------------*/

  • Hello,

    There is no problem with the liner cmd files for bootloader and application. Can you post the exception vector table (sys_intvecs.asm) and sys_start.c for the application?
  • Hello,

    I wrote two piece of code to test "bootloader" and application. The first piece of code acts as bootloader which is located at 0x00000000, and the 2nd piece of code acts as application which is programmed to 0x20000 of the flash. Both are programmed to flash using CCS8.

    Bootloader" the code is branched to 0x20000 in main()
    void main(void)
    {
    /* USER CODE BEGIN (3) */
    '''
    }
    ((void (*)(void))0x00020000)();


    Application toggles the GIO to turn on/off one LED on RM48 HDK.
  • Thanks for the reply. I got past the initial issue last week and was able to go from boot to application. However, this is still done by the boot code branching to undefEntry and because undefEntry in the bootloader vector table has a branch to the application image at 0x00200000, it finds the app and works OK. What causes boot to jump to undefEntry and why can't it start from application resetEntry directly as intended in the bootlaoder main below?

    Secondly, I wanted to use the boot to configure/setup various hardware resources and not have to do the same in the app. However, I'm see that in the app I still have to reconfigure the ports I use for GIO to drive an LED even boot already configured and use the same port successfully. What is doable?

    My bootloader main is:

    void main(void)
    {
        
      //Jump to system app; SYS_START_ADDRESS = 0x00200000
        g_ulTransferAddress = (uint32_t)SYS_START_ADDRESS;
        ((void (*)(void))g_ulTransferAddress)();
    }

    Vector table for bootloader is below; I tried 0x001FFFF8 (i.e. 0x00200000 - 8) and it didn't work. Also using # for immediate gives a syntax error. Not sure if that's just IAR assembler:

    ;-------------------------------------------------------------------------------
    ; interrupt vectors resetEntry b _c_int00 ;0x00 Bootloader reset undefEntry b 0x00200000 ;0x04 undefined_instruction, branch to application svcEntry b svcEntry ;0x08 software_interrupt, branch to application prefetchEntry b prefetchEntry ;0x0C prefetch_abort, b _dabort ;0x10 data_abort b phantomInterrupt ; reserved ldr pc,[pc,#-0x1b0] ;0x18 ldr pc,[pc,#-0x1b0] ;0x1C end ;-------------------------------------------------------------------------------

    Vector table for app is:

    ;-------------------------------------------------------------------------------
    ; interrupt vectors
    
    resetEntry
            b   _c_int00
    undefEntry
            b   undefEntry
    svcEntry
            b   svcEntry
    prefetchEntry
            b   prefetchEntry
            b   _dabort
            b   phantomInterrupt
            ldr pc,[pc,#-0x1b0]
            ldr pc,[pc,#-0x1b0]
    
        end
    ;-------------------------------------------------------------------------------

  • I resolved the undefEntry issue (was due to address mismatch between code and vector table).

    So my two issues that remain are:

    1. I wanted to use the boot to configure/setup various hardware resources and not have to do the same in the app. However, I see that in the app I still need to reconfigure the ports I use for GIO to drive an LED even though the boot code already configured and used the same ports successfully in the bootloader. What is doable?

    2. Not really an issue, but a questions. In many examples I've seen it is suggested to set the application address in the vector table to address-8. In my case this will be 0x0001FFF8. However, the only address that works for me in the vector table is 0x00020000 (the actual application start address).
  • Hello,

    1. Yes, you don't have to reconfigure the peripherals in your application which has the same configure as in bootloader. But I recommend to redo the configuration in application. When different settings is required, you don't have to update both application and bootloader. After the code jump to the application, you are not able to call the functions in the bootloader.

    2. Program Counter (PC) always pointers two instructions beyond the current executed instruction. So if you want to branch to 0x200000, the value in bootloader should be 0x200000-0x08
    b #0x1FFFF8

    Which IDE do you use, CCS, IAR, other?
  • Thanks for the reply.

    Regarding #2, I'm using IAR version 8.22.1. Let me know what to look for to address this.

  • what is the disassembly value for this statement?
  • Hello,

    Did you check your disassembly or the content at 0x00000004 (Flash address)? If you use bl #0x20000, the value at 0x04 should be EA008000

    0xE means Alway (no condition). A mean Branch without link.

    Offset is 0x8000 (0x20000 shifted right 2 bits)

    The branch offset must take account of the prefetch operation, which causes the PC to be 2 words (8 bytes) ahead of the current instruction. When execute the instruction at 0x04 (b #20000), the PC = 0x04+0x08. After 0x04 (b #20000) is executed, PC=0x04+0x08+0x20000 = 0x2000B

    This means the "prefetch exception handler" in application code will be called rather than "undef exception handler" (at 0x20000+0x04) is called.