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.

TM4C123GH6PM: Call TivaWare CAN Bootloader from Application

Part Number: TM4C123GH6PM

Hello,

I am trying to implement a CAN Bootloader using the TivaWare Bootloader Code. So far, I managed to successfully flash and execute an application to the TM4C over CAN, but I cannot return to the bootloader. More precisely, I can return to the bootloader (i.e. the UpdateHandler) using the SVCall, but somewhere in the "ProcessorInit" function it fails causing the programm to jump to the FaultISR.

// function copied from boot_demo1.c
void JumpToBootLoader(void)
{
    HWREG(NVIC_DIS0) = 0xffffffff;
    HWREG(NVIC_DIS1) = 0xffffffff;

    (*((void (*)(void))(*(uint32_t *)0x2c)))();
}
//defines from bl_config.h
#define APP_START_ADDRESS       0x1000
#define VTABLE_START_ADDRESS    0x1000

//linker script
#define APP_BASE 0x00001000
#define RAM_BASE 0x20000000

MEMORY
{
    FLASH (RX) : origin = APP_BASE, length = 0x3F000
    SRAM (RWX) : origin = RAM_BASE, length = 0x00008000
}

SECTIONS
{
    .intvecs:   > APP_BASE
    .text   :   > FLASH
    .const  :   > FLASH
    .cinit  :   > FLASH
    .pinit  :   > FLASH
    .init_array : > FLASH

    .vtable :   > RAM_BASE
    .data   :   > SRAM
    .bss    :   > SRAM
    .sysmem :   > SRAM
    .stack  :   > SRAM
}

Above, I provided the sections of code that I think have the highest potential of causing this problem. The application that I'm running does nothing more than to blink an LED a few times and than jump back to the bootloader. Is the configuration in general correct? Is it ok that I override the bootloaders vector table (in SRAM) with the one of my application? 

Any help would be highly appreciated. 

Regards,

Josua

  • Hello Josua,

    Are you using the ROM boot loader or a Flash boot loader?

    What do you mean by "I override the bootloaders vector table (in SRAM) with the one of my application"? When does it get overwritten?
  • Hello Ralph,

    as far as I can tell from the TivaWare Bootloader User's Guide and the Datasheet there is no ROM Bootloader for CAN (only for Serial interfaces).

    Hence, I'm using the flash bootlloader.

    The Bootloader starts its execution from 0x00 in flash memory, then calls the ProcessorInit() function, which copies the bootloader from flash into SRAM and continues execution from SRAM. Therefore, the bootloaders vector table now sits at the beginning of SRAM at 0x20000000. When the bootloader has successfully downloaded an application, the application's vector table is copied to this address overwriting the bootloaders vtable. At least, this is my understanding of the bootloaders operation. Please correct me if I am wrong.

    Basically, this should not be a problem as a call to UpdateHander() will copy the bootloader back to SRAM restoring its vtable. However, I am clueless as to what else could cause this problem (beside the configuration that I posted).

    Regards,

    Josua

  • Hello Josua,

    You're right about there not being a CAN boot loader, sorry about that, it slipped my mind that CAN was the one case where there isn't a ROM boot loader present but a Flash boot loader is!

    Your understanding of how the boot loader copies Flash into SRAM and executes from there is correct.

    You are using the TM4C123 and not a TM4C129 device correct? Just want to make sure because for TM4C129 I would have a very strong idea as to what is going on wrong if it were a TM4C129 device.

    Since you are landing in FaultISR, I think the quickest means to get this resolved would be to get more info about what caused the FaultISR. This can be found out by following the steps in this document: www.ti.com/.../spma043

    Please report back the results of what is being set that causes the FaultISR to occur and then I can help you further!
  • Josua Janus said:
    the application's vector table is copied


    This is true for TI-RTOS apps, but not in general. Are you using TI_RTOS or some other code that claims to copy the vector table to SRAM?

    Regardless, this is probably not the cause of your fault because the bootloader re-copies its vector table when called. Any app modifications are overwritten.

    Ralph's document will recommend you capture the PC value from the exception stack from.

    Another way is to single step over your code until you hit the offending function. To do this, you need to follow this guide: https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/691665

  • Thanks for the replies.

    Yes, I am using a TM4C123 and not a TM4C129 and also, I am not using any kind of RTOS or code that is in any way complex (at least for now).

    I did try to single step through the code, but I am not quite sure about the offending instruction yet.

    Let me describe my approach:

    First I started the bootloader in Debug mode in CCS and flashed my demo application over CAN. After a successful download, I set up a breakpoint at the SVCall instruction in the demo application.

    000015d8:   202C                movs       r0, #0x2c

    Then I started going through the disassembly step by step. As there were no debug symbols defined in flash, I compared the address to the address with the same offset in SRAM to find out what function is being called (e.g. 0x0000076c ->0x2000076c). 
    The SVC called the UpdateHander() function, which in turn called the ProcessorInit() function of the bootloader.

    0000076c:   F7FFFFC4            bl         #0x200006f8 		// UpdateHandler()
    000006f8:   2000                movs       r0, #0			// ProcessorInit()

    The ProcessorInit() function went through a couple of instructions and than cycled once trough the copy loop. At this point, I got a little bit suspicious. Although I do not really have a clue when it comes to assembler, I thought that the loop which copies all the code from flash to SRAM should repeat more than once.

       ;; Copy the code image from flash to SRAM.
        ;;
        movs    r0, #0x0000
        movs    r1, #0x0000
        movt    r1, #0x2000
        ldr     r2, bss_start
    copy_loop:
            ldr     r3, [r0], #4
            str     r3, [r1], #4
            cmp     r1, r2
            blt     copy_loop

    After that, the zero loop was called and I tried to step through it, but I could not get out of it manually in a reasonable amount of time. Also I was not really sure about what it is doing, because none of the core registers changed (except the PC of course).

        ;;
        ;; Zero fill the .bss section.
        ;;
        movs    r0, #0x0000
        ldr     r2, bss_end
    zero_loop:
            str     r0, [r1], #4
            cmp     r1, r2
            blt     zero_loop
    
        ;;
        ;; Set the vector table pointer to the beginning of SRAM.
        ;;
        movw    r0, #(NVIC_VTABLE & 0xffff) //breakpoint here stops in loop
        movt    r0, #(NVIC_VTABLE >> 16)    //breakpoint was set at this instruction

    Anyways, I tried to set a breakpoint at the first instruction after the loop, which resulted in the program still stopping in the loop. So I set the breakpoint at the second instruction after the loop, but the program never reaches this point.

    When I pause the program I am in the FaulISR() of my demo application(!) and the FaultStatus register has a value of one indicating an instruction access violation. The address in the NVIC_FAULT_ADDR register is not listed in the datasheet (0xE000EDF8), but it belongs to the cortex-m4f peripherals (NVIC etc).

    Next, I am going to try to inspect the exception stack as described in the guide and post the results. In the mean time, I thought that I share the insights that I made so far. Also, I would be grateful, if somebody could provide me with a little bit of clarity on the functionality of the two loops.

    Best Regards,

    Josua

  • Hi Josua,

    You may find more information from the Fault status register at address 0xE000ED28. This register has the exception cause. The NVIC has "normal" peripheral interrupts. These should be documented in section 3 of the datasheet. Try search the pdf for the offset (d28) instead of the entire address. The value of this register is valuable to know and is discussed in the guide.

    Edit: did you mean to type 0xE000ED28 instead of 0xE000EDF8? We might be looking at the same register here.

    The loop happening twice is actually a bad assumption on my part. Ralph and I aren't sure why the debugger goes through this loop a second time when the debug session starts the execution (PC) in SRAM. The actual operation should be the loop occurs in flash memory, then the assembly code branches into SRAM just past the copy loop (bx lr). This explains why you are able to hit flash based hardware breakpoints.

    This explanation from Miles gives some background: https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/295119/1033395#1033395

    My bad assumption was based on a contradiction of "So single-stepping from _c_int00() is not going to work". It works for me!