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.

F28M35H52C: F28M35 M3 Bootloader: how to jump to application code ?

Part Number: F28M35H52C
Other Parts Discussed in Thread: SYSBIOS, CONTROLSUITE

Hello Dear community.

In our project, we need to have a bootloader to update the M3 firmware stored on a SD card(spi). We'll also need to update the C28, but let's focus only on M3 for now.

I first wanted to try to jump from the bootloader to the application as a first test, after 'manually' flashing both firmwares via CCS and the JTAG debug probe..

I first tried a "naive" approach :

I have 2 CCS projects, one for the bootloader and one for the application.

The booloader linker file looks like :

...
FLASH_BOOT (RWX) : origin = 0x00200030, length = 0x00000004 // Not exactly sure what is put in this section, but I guess this one is key.. ?
FLASH (RWX)      : origin = 0x00200034, length = 0x0001FFCC // Bootloader code (I know, it's a big section for bootloader..)
RSVD_FIRMWARE    : origin = 0x00220000, length = 0x0005FF00 // Reserved for application and main function address
...
.text       : > FLASH
.binit      : > FLASH
.cinit      : > FLASH
.pinit      : > FLASH
.const      : > FLASH
...


And the application linker file:

...
RSVD_BOOTLOADER  : origin = 0x00200030, length = 0x0001FFD0 FLASH_BOOT (RWX) : origin = 0x00220000, length = 0x00000004 // Not exactly sure what is put in this section FLASH (RWX)      : origin = 0x00220004, length = 0x0005FEF8 // Application code MAIN_ADDR (RWX) : origin = 0x0027FEFC, length = 0x00000004 // Stores the main function address of application ... .text : > FLASH .binit : > FLASH .cinit : > FLASH .pinit : > FLASH .const : > FLASH ...


So in the application code, I store the main function pointer address at a specific flash address(0x0027FEFC in this case).
In the bootloader code, I simply retreive the application main function address and try to call the function from there. I know that the main function address is retrieved correctly, but when I call the application main function, nothing happens. It just hangs and I don't catch any exception message in the debugger.

I understand this is quite a naive solution, but it looks like it worked for some guy on another plateform as described in the OP here e2e.ti.com/.../113899

Could anyone point me in the right direction to solve my problem ? Any advice or example would be greatly appriciated.

I've searched a lot but didn't find any example for the Concerto chips. I know that CodeSkins propose commercial solutions for my plateform, but we would really like to do it on our own for now.


Thanks everyone!
Ril

UPDATE:

After reading this post:https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/321081

I also tried:

// Set the vector table to the beginning of the app in flash.
  HWREG(NVIC_VTABLE) = 0x22000000; // also tried with 0x220001, 0x220004 and 0x220005
  
  // Load the stack pointer from the application's vector table.
  //
  __asm("    ldr     r1, [r0]\n"
        "    mov     sp, r1");

 
  // Load the initial PC from the application's vector table and branch to
  // the application's entry point.
  //
  __asm("    ldr     r0, [r0, #4]\n"
        "    bx      r0\n");

but it didn't work.

  • Ril

    I apologize for the delay. Have you had any success branching to the entry point?

    When branching to address, the BLX instruction will result in usagefault if bit[0] is 0.
    To branch to an address, I've used the following:

    entry_addr = 0x1234; //This is the address of the function I want to branch to
    entry_addr |= 0x1; //This satisfies the condition I just mentioned
    ((void (*)(void))entry_addr)(); //This calls the function at that address

    Best regards
    Chris
  • Hi Chris, thanks for your answer.

    I still didn't have any success with this.

    When you talk about entry_addr, you mean the main function address of the application right ? Can it be this simple ? When are the global and static variables initialized?

    When I do that without anythig else, I get the following error in the debugger:

    """

    ti.sysbios.family.arm.m3.Hwi: line 1087: E_hardFault: FORCED
    ti.sysbios.family.arm.m3.Hwi: line 1199: E_usageFault: INVSTATE: Invalid EPSR and instruction combination
    Exception occurred in background thread at PC = 0x00000000.
    Core 0: Exception occurred in ThreadType_Task.
    Task name: {unknown-instance-name}, handle: 0x20000238.
    Task stack base: 0x20000288.
    Task stack size: 0x800.
    R0 = 0x00000000  R8  = 0xffffffff
    R1 = 0x00000000  R9  = 0xffffffff
    R2 = 0x00000075  R10 = 0xffffffff
    R3 = 0x00000001  R11 = 0xffffffff
    R4 = 0x00000001  R12 = 0x00000000
    R5 = 0x00000075  SP(R13) = 0x200009b0
    R6 = 0x00000000  LR(R14) = 0x00224cc3
    R7 = 0xffffffff  PC(R15) = 0x00000000
    PSR = 0x00000000
    ICSR = 0x0440f803
    MMFSR = 0x00
    BFSR = 0x00
    UFSR = 0x0002
    HFSR = 0x40000000
    DFSR = 0x00000001
    MMAR = 0xe000ed34
    BFAR = 0xe000ed38
    AFSR = 0x00000000
    Terminating execution...

    """

    When I add before that:

    HWREG(NVIC_VTABLE) = APP_FLASH_START; // Tried values 0x00220000, 0x00220004, 0x00220005...

    I get no apparent error, but the debugger shows me line 117 of /.../ti/ccsv6/tools/compiler/arm_15.12.3.LTS/lib/src/trgmsg.c :

        for (i = 0; i < length; i++) PACKCHAR(*data++, p, i+8);

    and nothing else happens.

    Could you provide a more complete example of what you did? Apparently, it worked for you.

    I would appriciate if you could also tell me how you programmed your firmware(s) to flash.

    Thanks again for your support.

    Ril

  • Ril

    You should branch to _c_int00 (see controlSUITE examples' statup_ccs.c), this procedure part of the RTS library, does all that pre-variable setup and then at the end branches to the "main" symbol.

    I've used this method of branching as part of the boot code, not for firmware update. Refer to controlSUITE examples for programming flash. I will see if I can find any firmware update code, not sure if we have some.

    Best regards
    Chris
  • Christopher,

    Did you have any chance to find this example somewhere ?

    We tried the following without success :

    // equivalent to FLASH_BOOT in b.cmd (see below)
    // we also tried with 0x220004, equivalent to FLASH in b.cmd
    #define APP_START 0x220000  
    
    void JumpToFlashB()
    {
       uint32_t entry_addr = 0x23A9ED; // This is the address of the function _c_int00 in the other application
       entry_addr |= 0x1;
       HWREG(NVIC_VTABLE) = APP_START; // With or without this line
       ((void (*)(void))entry_addr)();
    }

    I was wondering if the way I link the stages was leading to something wrong.

    Here is what I have in my cmd file (simplified):

    A.cmd

    MEMORY
    {
       FLASH_BOOT (RWX)    : origin = 0x00200030, length = 0x00000004
       FLASH (RWX)         : origin = 0x00200034, length = 0x0001FFCC
       RSVD_B (RWX) : origin = 0x00220000, length = 0x0005FF00 // Jump to this sector with JumpToFlashB()
    }

    B.cmd

    MEMORY
    {
       RSVD_A (R) : origin = 0x00200030, length = 0x0001FFD0
       FLASH_BOOT (RWX)    : origin = 0x00220000, length = 0x00000004
       FLASH (RWX)         : origin = 0x00220004, length = 0x0005FEF8 // Starts at sector xxx
    }

    Any idea or functional example on your side ?

    Cheers,

  • Ril

    Sorry, I haven't had any luck finding an example. It is looking like we don't have one currently.
    The address you're calling has (or have tried) a function that calls c_int00.
    Ex from "startup_ccs.c" in controlSUITE:
    void myfunc()
    {
    // Jump to the CCS C Initialization Routine.
    __asm(" .global _c_int00\n"
    " b.w _c_int00");
    }

    You're getting the same error as you mentioned previously?

    Best regards
    Chris
  • Hello Chris,

    Christopher Chiarella said:

    You're getting the same error as you mentioned previously?

    Yes, I have the same behavior when doing the call like that.

    After looking at this post: https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/660862   , I can reproduce the same behavior : I set a break point at the call, then do 'Step into' and the application code starts (with a few driver issues). Any idea how this is happening ?

    I feel like there is something more to do, like settings interrupt vectors ? 

    On a side note, I can reboot 'on myself' without issue by calling _c_int00, but it fails when calling the same function from the second stage.

    Thanks for your help Chris.

    Ril

  • Ril,

    I posted few debug steps on the forum post  https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/660862, you pointed to.

    I don;t think there is anything wrong with the branch itself, it could be failing after and before reaching main(). Please see if you can perfrom the same debug steps that I suggested in the linked post.

    Hope this helps.

    Best Regards
    Santosh Athuru

  • Hi Santosh,

    Sorry for the delayed response. I didn't have time to work on this lately but I followed the discussion on the post you mentioned and it solved my problem !

    In particular, since I was also running TI-RTOS, I needed to do

    Hwi_disableInterrupt(FAULT_SYSTICK);

    before jumping to the main application.

    Thanks for your support.

    Ril