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.

  • Resolved

Bootloading an RTOS application

Prodigy 60 points

Replies: 3

Views: 2243

I'm using Keil with the LM3S9B90 Rev B1.  I'm responsible for creating a custom bootloader that loads the main application firmware.  The main application firmware build is confirmed to be working as stand-alone.  It uses the Keil RTX rtos. 

The bootloader appears to be working as well.  A new application image is loaded from external SPI flash to internal flash successfully.  I've verified the newly written image using the LM Flash Programmer utilty.

My problem occurs after the bootloader loads the application firmware.  The application then crashes to the fault isr.  I tried to look at the SP to see where the PC was before the fault, and it seems the PC somehow got off in the weeds, executing from RAM.  At no point should the application firmware be executing from RAM.  Stepping through the application dissassembly, it seems to start off correctly, but crashes later.

The application firmware project settings were changed to start at 0x5000 in the scatter file, using
LR_IROM 0x00005000 0x0003B000
ER_IROM 0x00005000 0x0003B000

From my bootloader startup file, where control is given to the application:

    ; Set the vector table address to the beginning of the application.
    movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
    movw    r1, #(NVIC_VTABLE & 0xffff)
    movt    r1, #(NVIC_VTABLE >> 16)
    str     r0, [r1]

    ; Load the stack pointer from the application's vector table.
    ldr     sp, [r0]

    ; Load the initial PC from the application's vector table and branch to
    ; the application's entry point.
    ldr     r0, [r0, #4]
    bx      r0

I experimented a bit by replacing the application firmware with my bootloader at 0x5000 to see if it would also crash, but it seemed to work, branching  to itself at 0x5000 after performing the bootloader update checks from RAM.

Is there anything I'm missing that stands out?

  • Have you confirmed that when you changed the scatter file for the main application, that the vector table remained at the beginning of the image and didn't somehow get relocated to somewhere other than 0x5000?

    Also, is it possible that the RTOS is somehow reprogramming the NVIC_VTABLE after it starts to a value other than 0x5000?

    Can't think of anything else at this time, but will continue to ask around.


  • In reply to Bobby Bradford:

    Thanks for your reply Bobby,


    I did confirm the NVIC_VTABLE is at the start of the the application firmware binary for the 0x5000 build. 

    Also, once in the fault isr, I confirmed the VTABLE at address 0xe000ed08 to not be overwritten and still be 0x00005000.

  • In reply to DanielP:

    My problem is resolved.  I changed the MCU to rev C1, and now the application loads properly from the bootloader handoff.  I don't see any errata on B1 that should have an effect, but I won't dig too much into it.


    The problem now is stepping through my bootloader code with Rev C1 silicon with the flash patch in the way.

    The current stellarisware bootloader model does not allow debugging of a modified bootloader on Rev C1 because it is built for 0x000 but placed at 0x1000, confusing the linker.  I've found a fairly simple way around this in case anyone is also having trouble. (This has worked for me so far using KEIL, but not tested to be bulletproof).  The changes allow the debugger to correctly resolve routines once they are executing from RAM.  Remember to manually step through the beginning of the bootloader until it is copied to ram, then breakpoints will work after that.

    -Set up tools to build bootloader for address 0x1000 as you would for an offset for your application described in the BL user manual.

    -Use FLASH_PATCH_COMPATIBLE definition as before

    -Modify the following snippets (changes highlighted):



      export  __Vectors
        dcd     g_pulStack + (_STACK_SIZE * 4)  ; Offset 00: Initial stack pointer
      ; these are now taken care by the build offset
      ;  if      :def:_FLASH_PATCH_COMPATIBLE
      ;  dcd     Reset_Handler + 0x1000          ; Offset 04: Reset handler
      ;  dcd     NmiSR + 0x1000                  ; Offset 08: NMI handler
      ;  dcd     FaultISR + 0x1000               ; Offset 0C: Hard fault handler
      ;  else
        dcd     Reset_Handler                   ; Offset 04: Reset handler
        dcd     NmiSR                           ; Offset 08: NMI handler
        dcd     FaultISR                        ; Offset 0C: Hard fault handler
      ;  endif
        dcd     IntDefaultHandler               ; Offset 10: MPU fault handler
        dcd     IntDefaultHandler               ; Offset 14: Bus fault handler
        dcd     IntDefaultHandler               ; Offset 18: Usage fault handler
        dcd     0                               ; Offset 1C: Reserved
        dcd     0                               ; Offset 20: Reserved
        dcd     0                               ; Offset 24: Reserved
        dcd     0                               ; Offset 28: Reserved
      ;  if      :def:_FLASH_PATCH_COMPATIBLE
      ;  dcd     UpdateHandler + 0x1000          ; Offset 2C: SVCall handler
      ;  else
        dcd     UpdateHandler                   ; Offset 2C: SVCall handler
      ;  endif


    ; Initialize the processor by copying the boot loader from flash to SRAM, zero
    ; filling the .bss section, and moving the vector table to the beginning of
    ; SRAM.  The return address is modified to point to the SRAM copy of the boot
    ; loader instead of the flash copy, resulting in a branch to the copy now in
    ; SRAM.
        export  ProcessorInit
        ; Copy the code image from flash to SRAM.
        if      :def:_FLASH_PATCH_COMPATIBLE
        movs    r0, #0x1000

        movs    r0, #0x0000
        if      :def:_FLASH_PATCH_COMPATIBLE
        movs    r1, #0x1000

        movs    r1, #0x0000
        movt    r1, #0x2000
        import  ||Image$$SRAM$$ZI$$Base||
        ldr     r2, =||Image$$SRAM$$ZI$$Base||
        if      :def:_FLASH_PATCH_COMPATIBLE
        add     r2,#4096

            ldr     r3, [r0], #4
            str     r3, [r1], #4
            cmp     r1, r2
            blt     copy_loop

        ; Zero fill the .bss section.
        movs    r0, #0x0000
        import  ||Image$$SRAM$$ZI$$Limit||
        ldr     r2, =||Image$$SRAM$$ZI$$Limit||
        if      :def:_FLASH_PATCH_COMPATIBLE
        add     r2,#4096


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.