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.

F28M36 - Bare-metal bootloader jump to TI-RTOS on M3 core - RTOS stuck in idle task

Other Parts Discussed in Thread: SYSBIOS

I am working on a bootloader and an application on the F28M36 M3 core. These are two entirely separate programs, each with their own CCS projects.

The bootloader is programmed into flash sector N and M (0x200000) and does not use an RTOS. Eventually, it will check program validity and allow updates from some external sources to application flash (after copying itself to RAM). It is not intended to ever be changed (though, in theory, it could, just at the risk of corrupting itself).

The application is programmed into the remaining sectors (starts at 0x210000, but main program space is 0x218000). The application uses TI-RTOS, and is currently basically a blinky example with modified linker layouts to avoid the bootloader and provide a known address to jump to.

When the bootloader concludes that the application should start (i.e. no update or completed update), it jumps to the application start, and begins execution.

The project setups look like this:

main_bootloader.c

static void jumpStackPointer(uint32_t address)
{
    __asm(" mov sp, r0\n"   // sp is now *address
          " bx r0\n" );     // jump to *address
}
    
void jumpToApplication(void)
{
    /*
     * Disable interrupts
     * Doesn't work with or without this line.
     * With this line means PRIMASK will be 1 after start app
     * Without means PRIMASK will be 0
     */
    IntMasterDisable();
    
    /* Adding this gives a hard fault */
    //HWREG(NVIC_VTABLE) = 0x210000; // redirect the vector table
    
    jumpStackPointer(0x210000 + 1);
}

bootloader.cmd

MEMORY
{
    /* Flash Block 0, Sector N */
    RESETISR (RX)   : origin = 0x00200030, length = 0x0008
    INTVECS (RX)    : origin = 0x00201000, length = 0x0258
    /* Flash copied to RAM (e.g. Flash API functions) 
     * for now, all BL functions go here, but that's not required
     */
    FLASHLOAD (RX)  : origin = 0x00201258, length = 0xEDA8
    
    /* Flash Block 0, Sector L to Flash Block 0, Sector A, minus Z2 CSM */
    /* Application flash, not used by bootloader */
    APP_FLASH (RX)  : origin = 0x00210000, length = 0xEFE00
    
    ...
}

application.cfg

var m3Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi');
m3Hwi.resetVectorAddress = 0x218000;

application.cmd

MEMORY
{
    BOOTROM (RX)    	: origin = 0x0,        length = 0x10000

    /* Bootloader Reset ISR */
    BL_RESETISR (RX) : origin = 0x00200030, length = 0x0008

    /* Application starts at Flash Block 0, Sector L */
    /* Reset ISR is mapped to bootloader-known address */
    FLASH_BOOT (RX) : origin = 0x00210000, length = 0x0008
    /* not currently used */
    INTVECS (RX)    : origin = 0x00211000, length = 0x0258

    /* For storing code in Flash to copy to RAM at runtime
     * Remainder of Flash Block 0, Sector L */
    FLASHLOAD (RX)  : origin = 0x00211258, length = 0x6DA8

    /* Flash Block 0, Sector K to Flash Block 0, Sector A - minus Z2 CSM*/
    FLASH (RX)      : origin = 0x00218000, length = 0xE7E00
    
    /* RAM areas */
    C03SRAM (RWX)   : origin = 0x20000000, length = 0x8000
    S07SHRAM (RWX)  : origin = 0x20008000, length = 0x10000
    C415SRAM (RWX)  : origin = 0x20018000, length = 0x18000
    CTOMMSGRAM (R)  : origin = 0x2007F000, length = 0x800
    MTOCMSGRAM (RW) : origin = 0x2007F800, length = 0x800
}

SECTIONS
{
    /* Allocate program areas: */
    .text       : > FLASH
    .cinit      : > FLASH
    .pinit      : > FLASH
    .binit      : > FLASH
    .init_array : > FLASH

    /* Initialized sections go in Flash */
    .const      : > FLASH

    /* Allocate uninitalized data sections: */
    .data       : > C03SRAM  | C415SRAM
    .bss        : > C03SRAM  | C415SRAM
    .dma        : > S07SHRAM | C415SRAM
    .sysmem     : > C03SRAM  | C415SRAM
    .stack      : > C03SRAM  | C415SRAM
    .cio        : > C03SRAM  | C415SRAM
    .neardata   : > C03SRAM  | C415SRAM
    .rodata     : > C03SRAM  | C415SRAM
    .args       : > C03SRAM  | C415SRAM
}

__STACK_TOP = __stack + 256;

Both programs compile and run in isolation. Some bits of the map files indicate things look normal - the application doesn't have anything in BL flash and the BL has nothing in application flash, and each has a _c_int00 entry point:

bootloader.map

ENTRY POINT SYMBOL: "_c_int00"  address: 0020975d

MEMORY CONFIGURATION

         name            origin    length      used     unused   attr    fill
----------------------  --------  ---------  --------  --------  ----  --------
  RESETISR              00200030   00000008  00000006  00000002  R  X
  INTVECS               00201000   00000258  00000200  00000058  R  X
  FLASHLOAD             00201258   0000eda8  00008b54  00006254  R  X
  APP_FLASH             00210000   000efe00  00000000  000efe00  R
  ...

application.map

ENTRY POINT SYMBOL: "_c_int00"  address: 0021ff55

MEMORY CONFIGURATION

         name            origin    length      used     unused   attr    fill
----------------------  --------  ---------  --------  --------  ----  --------
  BOOTROM               00000000   00010000  00000000  00010000  R  X
  BL_RESETISR           00200030   00000008  00000000  00000008  R  X
  FLASH_BOOT            00210000   00000008  00000004  00000004  R  X
  INTVECS               00211000   00000258  00000000  00000258  R  X
  FLASHLOAD             00211258   00006da8  00000000  00006da8  R  X
  FLASH                 00218000   000e7e00  0000c3ac  000dba54  R  X
  C03SRAM               20000000   00008000  000020fb  00005f05  RW 
  S07SHRAM              20008000   00010000  00000000  00010000  RW X
  C415SRAM              20018000   00018000  00000000  00018000  RW X
  CTOMMSGRAM            2007f000   00000800  00000000  00000800  R   
  MTOCMSGRAM            2007f800   00000800  00000000  00000800  RW 
  
GLOBAL SYMBOLS: SORTED BY Symbol Address 

address   name                                                              
-------   ----                                                              
00000000  __ASM__                                                           
...                                                         
00000300  __STACK_SIZE                                                      
00210001  _ti_catalog_arm_cortexm3_concertoInit_Boot_entry                  
00218000  ti_sysbios_family_arm_m3_Hwi_resetVectors                         
0021803d  SysCtlSRAMSizeGet   
...

When I call the bootloader jump into the application, it does work - the program goes off into the higher flash memory, first to 0x210000, when it vectors to _c_int00:

00210000:   F00FBFA8            b.w        #0x21ff54

The reset vectors "ti_sysbios_family_arm_m3_Hwi_resetVectors" at 0x218000 (start of main application flash area) also look plausible:

00218000:   1DFC                adds       r4, r7, #7
00218002:   2000                movs       r0, #0
00218004:   FF550021            vhadd.u16  d16, d5, d17
00218008:   12C5                asrs       r5, r0, #0xb
0021800a:   0022                movs       r2, r4
0021800c:   12C5                asrs       r5, r0, #0xb
0021800e:   0022                movs       r2, r4
00218010:   12C5                asrs       r5, r0, #0xb
00218012:   0022                movs       r2, r4

After that, the the LEDs light up (they initialise to on) and the program starts, but gets stuck in the idle task: ti_sysbios_knl_Idle_loop__E and ti_sysbios_knl_Idle_run__E. I lose all debugging symbols after the jump, but the application map file tells me what the addresses are.

I have tried not turning the interrupts off before jumping (which seems dangerous). This had the effect of not setting PRIMASK to 1 when the application runs, but otherwise did nothing.

I have also tried setting the XDC bootFromFlash config to false, but that didn't change anything either:

var Boot = xdc.useModule('ti.catalog.arm.cortexm3.concertoInit.Boot');
Boot.bootFromFlash = false;

Is there a further step I should take when jumping into a TI-RTOS application from a bootloader on an F28M36 M3 processor?

  • John,

    It wasn't clear to me what was wrong with the application?  Being in the Idle loop simply means there is no Task or other threads that are running.

    What other threads do you have in your application?

    I would suggest having a Task in the system that blinks an LED forever with a delay via a Task_sleep() if you want to know that your system is still alive.

    Judah

  • Hi Judah,

    That is exactly how the application works: there is a heartbeat/blink task that does Task_sleep() and toggles the GPIOs. The problem is that no tasks actually seem to be executing.

    The main function is fairly straight forward - the essence of it is:

    main_application.c

        
    #define B_TASKSTACKSIZE   256
    
    Void _blinkFxn(UArg arg0, UArg arg1)
    {
        while (1)
        {
            Task_sleep((unsigned int) arg0);
            
            /* Doesn't toggle when branching from Bootloader */
            GPIO_toggle(Board_LED0);
        }
    }
    
    static Task_Params tskPrms_blink;
    static Task_Struct taskBStruct;
    static Char taskBStack[B_TASKSTACKSIZE];
        
    int main(void)
    {
        /* Call board init functions from Board.h */
        Board_initGeneral();
        Board_initGPIO();
    
        /* Construct blink RTOS Task thread */
        Task_Params_init(&tskPrms_blink);
        tskPrms_blink.arg0 = 100;
        tskPrms_blink.stackSize = B_TASKSTACKSIZE;
        tskPrms_blink.stack = &taskBStack;
        Task_construct(&taskBStruct, (Task_FuncPtr) _blinkFxn,
                &tskPrms_blink, NULL);
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

    The Board.h functions are pretty much just the ones from TMDXDOCK28M36.c (in tirtos_c2000_2_16_01_14/products/tidrivers_c2000_2_16_01_13/packages/ti/boards/TMDXDOCK28M36) - there isn't any extra setup done in my TMDXDOCK28M36_initGeneral(), for example.

    When I run the application in the debugger, it works - the LEDs blink at the expected rate. When I branch in from the bootloader, the LEDs come on (they initialise to on once the GPIO pins become outputs), but they never start to blink. So I am getting past Board_initGPIO(), and I am not landing in a fault handler, I'm just stuck somewhere in BIOS_start(), with no tasks ever getting going.

    It's quite tricky to see exactly what's going on, because after the branch, there is no stack or symbolic mapping in the debugger, but functions I see are things like ti_sysbios_knl_Idle_run__E, ti_sysbios_knl_Idle_loop__E, ti_sysbios_hal_Hwi_checkStack, ti_sysbios_family_arm_m3_Hwi_getStackInfo__E, and so on. The SP and PC registers looks plausible (at least PC is in the application flash!):

    PC	0x0021F22C	Program Counter [Core]	
    SP	0x20000840	General Purpose Register 13 - Stack Pointer [Core]	
    LR	0x0021F6EB	General Purpose Register 14 - Link Register [Core]
    
    CONTROL	00000010	Control	
    FAULTMASK	00000000	Faultmask	
    BASEPRI	00000000	Basepri	
    PRIMASK	00000001	Primask
    

    If you break and manually change PRIMASK to 0 in the debugger and resume, then the blinking starts, but not calling IntMasterDisable() before the branch on the bootloader seems like a recipe for diaster, and doesn't seem to work anyway. How should this be handled?

  • Do you know if you actually get to the _blinkFxn()?

    If the Timer is not ticking or blocked from getting an ISR then the Task_sleep() won't return.  So first try to determine if you actually get to the _blinkFxn(),

    It definitely sounds like something to do with Interrupts.  I will try to get someone with a better knowledge of this device to see if they know what could be going on.

    Judah

  • I conversed with a couple of SYSBIOS guys.  They said that SYSBIOS does not set the PRIMASK (nor does it clear it) and expects it to be 0 when you get into BIOS_start().

    Could you try writing a 0 to PRIMASK in main() and see if you app works?

    Judah

  • Hi Judah,

    Yes, it does seem that simply calling IntMasterEnable() at the start of application main will allow the tasks to start. So that is now working and booting though to the application now. Thank you!

    Is that all I need to worry about for interrupts when jumping from bootloader to application: just toggle PRIMASK on each side of the jump?

    From the HWI module docs, Hwi_enable() shouldn't be called from main(), but is internally called during BIOS startup. If TI-RTOS doesn't use PRIMASK at all, it is presumably not a problem to call the MWare IntMasterEnable() in the main() of a TI-RTOS app, prior to RTOS start?

  • John,

    "Is that all I need to worry about for interrupts when jumping from bootloader to application: just toggle PRIMASK on each side of the jump?"

    The looks to be the case.

    "If TI-RTOS doesn't use PRIMASK at all, it is presumably not a problem to call the MWare IntMasterEnable() in the main() of a TI-RTOS app, prior to RTOS start?"

    Yes, that is correct.

    Judah