Atmel SAM4E Bootloader/VTOR executing new application

I've written a boot loader for the Atmel SAM4E device which is working to a point, it can receive new application code via SPI, erase flash and write to flash, but I don't understand how to execute the new application. I've learned the VTOR can be relocated, but I'm not sure how. (my application sits at address 0x00420000).
I'm very new to writing code for ARM, so I'd appreciate any help.

Many thanks

Paul

  • Hi, Paul!!!

    You can shared you application?
    I try to do somthing like that in my bootloader.

    Best regards

  • Hello everyone!

    I am also trying to write my own bootloader, so I am facing similar problems dealt in this post.

    One good question would be, when am I able to modify the VTOR? I say this because I init the bootloader as a normal application with its Interrupt Vector Table, and being the reset vector in 0x0000_0000, I pretend to do all the bootloader stuff and after finishing, modify VTOR register and jump to 0x0000_2000 (the bootloader has been configured with BOOTPROT 2, so 8K memory has been "protected" for this purpose). Is this possible? It is not working right now. I tried to modify VTOR before and after initializing the board (ATMEL R21 with a ARM CORTEX M0+).

    In order to modify the VTOR I do it like this:

    SCB->VTOR = ((uint32_t)0x00002000);

    But being the VTOR just from 32:7 won't it be better to do it like this?

    SCB->VTOR = ((uint32_t)0x00002000 << (SCB_VTOR_TBLOFF_Pos - 1)); // shift 7 to the left ARM Information Center

    After doing this (that is nor working), I pretend to jump to the application so... which considerations should I bear in mind? Would be enough just with a jump to the 0x0000_2000 address?

    void start_application( uint32_t app_link_location )

    {

       asm(" blx r0");

    }

    Because I have seen in other posts code like this inside the function:

    asm(" ldr r1, [r0,#0]"); // get the stack pointer value from the program's reset vector

    asm(" mov sp, r1");      // copy the value to the stack pointer asm(" ldr r0, [r0,#4]"); // get the program counter value from the program's reset vector

    asm(" mov r0, #0");

    asm(" blx r0");          // jump to the start address

    or even something like this avoiding the assembly:

    void jump_to_application( void )

    {

      typedef int(*fn_prt_t)(void);

      fn_prt_t main_prog;

      main_prog= (fn_prt_t)0x00002000;

      main_prog();

    }

    I would really appreciate any advice.

    Best regards,

    Iván

  • binary_exec((void*) 0x00420000);

    int binary_exec(void * vStart){
    int i;

    // -- Check parameters
    // Should be at least 32 words aligned
    if ((uint32_t)vStart & 0x7F) return 1;

    wdt_disable(WDT);

    Disable_global_interrupt();

    // Disable IRQs
    for (i = 0; i < 8; i ++) NVIC->ICER[i] = 0xFFFFFFFF;
    // Clear pending IRQs
    for (i = 0; i < 8; i ++) NVIC->ICPR[i] = 0xFFFFFFFF;

    // -- Modify vector table location
    // Barriars
    __DSB();
    __ISB();

    __set_MSP(vStart);

    // Change the vector table
    SCB->VTOR = ((uint32_t)vStart & SCB_VTOR_TBLOFF_Msk);

    // Barriars
    __DSB();
    __ISB();


    Enable_global_interrupt();


    // -- Load Stack & PC
    _binExec(vStart);
    return 0;
    }


    void _binExec (void * l_code_addr){
    __asm__ ("mov r1, r0 \n"
    "ldr r0, [r1, #4] \n" //I also tryed #5 but that doesn't work, too
    "ldr sp, [r1] \n"
    "blx r0"
    );
    }