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.

RTOS/TM4C1294KCPDT: TM4C1294KCPDT

Part Number: TM4C1294KCPDT
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Hi,

I am trying to develop a custom boot loader for a TM4C1294 board. As we need some additional functionalities in the boot loader other than firmware update, our plan is to develop the boot loader with the TI-RTOS itself.

Is it possible to jump to the application image (that is also developed using TI-RTOS) from the TI-RTOS based boot loader?

Regards,

Sooraj

  • Hi,
    I don't really see a reason why not.
    Please take a look at this post which may also help.
    e2e.ti.com/.../679617
  • Hi Charles,

    Thank you for your reply.
    I visited the link you shared and went through the discussion in it.
    Also, I tried to jump from a TI-RTOS application to a firmware image copied to a different location of the flash memory. It works.

    Regards,
    Sooraj
  • Hi Charles,

    I developed a simple application using TIRTOS that can copy image binary to flash memory and jump to it.

    I created two binary images to toggle an LED, one with TIRTOS and other one is bare metal. It is built to run from the location 0x00200000.
    I copied the bare-metel image to flash by using this code and tried to jump to it. It failed when I jump to the starting location of the image, but it worked when I changed the jump location to that of the function _c_init00.

    When I tried with the image built using TI RTOS, it failed to run in both cases.
    I tried the method, suggested in the discussion you shared, to specify the RTOS vectors. Still it failed.

    var ti_sysbios_family_arm_m3_Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi');
    ti_sysbios_family_arm_m3_Hwi.vectorTableAddress = 0x4000;

    Could you answer following questions.

    How can I make it running when I jump to the start address of the image?

    What could be the problem with the RTOS based image?

    In RTOS based image, is it required to specify the image address anywhere other than
    the .CMD file and .cfg file?
  • Hi,
    Didn't you say you wanted the application to start at 0x200000? Why do you have ti_sysbios_family_arm_m3_Hwi.vectorTableAddress = 0x4000?
  • Hi Charles,

    Sorry for the mistake, I directly copied it from the discussion you shared.
    In my code, I replaced the address 0x4000 with 0x200000.

    Regards,
    Sooraj
  • Hi,
    Sorry for being late to reply. Is your issue resolved. If you still have question on calling TI-RTOS application from your bootloader I will forward you question to our TI-RTOS experts for suggestions.
  • Hi,
    I have not heard back from you. Hopefully you are able to resolve the issue. I will close the thread for now. If you have new questions you can open a new thread. If you resolved your issue you can also share with the community your methods and findings which will benefit people who are looking for the same solution.
  • Hi Charles,

    Sorry for the delayed response,

    I manged to branch execution to the image loaded to the flash memory from boot loader code.

    I followed the below steps to do that.
    1. Loaded the first 4 bytes of the new firmware image to stack pointer. For that we kept the address of the flash, where the image resides, in register r0.
    asm(" ldr sp, [r0]");

    2. Loaded next 4 bytes to a processor register(here r0 itself) and branched execution to that location(this is the address of _c_int00).
    This is like the code in boot.asm file.
    asm(" ldr r0, [r0, #4]");
    asm(" bx r0");

    But I am not succeeded in properly passing the address to the register r0 from C code.

    I noticed that, when I passed an integer argument to a function, that gets copied to the register r0.

    So what I did is, wrote a function with an integer argument to it.
    Inside the function moved the data in the location pointed by r0 to sp, then jumped to the location pointed by next 4 locations. So the function will look like this,

    eg: void funcName(unsigned int argName)
    {
    asm(" ldr sp, [r0]"); /* Here the content of argName in in r0, even without specifically moving to it */

    asm(" ldr r0, [r0, #4]");
    asm(" bx r0");
    }

    I would like to verify the steps,
    Could you confirm, whether this method is proper or not?
    And, Is it sure that the content in the argument to the function 'argName' will get copied to the register r0 always?
    If not, how can we do that?

    Regards,
    Sooraj
  • Yes, when calling a function in C, the first argument is always passed in R0.

  • Hi Bob Crosby,

    Thank you for confirming that.

    Regards,
    Sooraj

  • Hi,

    Now I am facing a new problem.
    The application loaded from my boot-loader runs for few seconds and stops running.
    When I checked the processor registers, I noticed exception number 25 in PSR.
    If I run the application using JTAG, it runs without any issues.

    My boot-loader is built to run from address 0x0000 0000 and application to 0x0001 0000.
    I created the sample application with TI-RTOS.
    I modified the linker command file of the application project as follows,

    MEMORY
    {
    FLASH_BOOT (RX) : origin = 0x00000000, length = 0x00010000
    FLASH_APP (RX) : origin = 0x00010000, length = 0x00060000
    SRAM (RWX): origin = 0x20000000, length = 0x00020000
    }

    SECTIONS
    {
    .text : > FLASH_APP
    .const : > FLASH_APP
    .cinit : > FLASH_APP
    .pinit : > FLASH_APP
    .init_array : > FLASH_APP

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

    __STACK_TOP = __stack + 512;

    And the configuration file (XXX.cfg) of the application project I added the below lines,

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

    The function calling the application from bootloader is implemented as shown below,
    void func(unsigned int arg)
    {
    asm(" ldr sp, [r0]");
    asm(" ldr r0, [r0, #4]");
    asm(" bx r0");
    }

    Address of the application firmware is passed to the function while calling it. eg: func(0x00010000);

    Could you find any issues in this implementation ?

    Regards,
    Sooraj
  • The code transferring control to the bootloader looks fine. Have you verified that you have get the proper stack address programmed into location 0x10000 and the proper start address in 0x10004? Also, the address at 0x10004 needs to be odd because the M4 only uses Thumb 2 code. If the application starts running, then fails, it might be a problem caused by an interrupt. Here is an application note that walks you through the process of finding the root cause for aborts:
    www.ti.com/.../spma043.pdf
  • Hi,

    Thank you for your reply,
    I went through the application note you shared.

    After analyzing the processor register when the program stopped running(as explained in the document), I could find that an interrupt triggered by the timer 1 is causing the problem.

    I tried by disabling the timer in the application image, I worked without any problem. Then I moved the code to disable the timer to the boot-loader, it worked without any problems this time too.

    I am not enabling the timer in my code, I wonder why the timer which is not enabled is triggering an interrupt.
    When I tried to disable timer 1, I had to enable the peripheral at first by calling the function 'SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1)'.

    As the boot loader code stays separate from the application code, there is a chance for enabling the timer in the application code in future for using it, will it make any problems then?

    Could you confirm one more point, is disabling the timer the proper solution for this problem?

    Best Regards,
    Sooraj
  • Since there could be other interrupt sources enabled by the main routine, I suggest that you disable them at the NVIC like is done in the example boot_demo1.c. It is really best done in the application code before it calls the bootloader:

        //
        // We must make sure we turn off SysTick and its interrupt before entering 
        // the boot loader!
        //
        ROM_SysTickIntDisable(); 
        ROM_SysTickDisable(); 
    
        //
        // Disable all processor interrupts.  Instead of disabling them
        // one at a time, a direct write to NVIC is done to disable all
        // peripheral interrupts.
        //
        HWREG(NVIC_DIS0) = 0xffffffff;
        HWREG(NVIC_DIS1) = 0xffffffff;
        HWREG(NVIC_DIS2) = 0xffffffff;
        HWREG(NVIC_DIS3) = 0xffffffff;