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 bootloader - jump to desired flash location and run app

Other Parts Discussed in Thread: TM4C123GH6PM

Hello


I have spent couple of long days playing around with the bootloader before I posted this question (memory model, arm instructions etc). The idea seems to be simple, I would like to have the small piece of code that will perform jump into the flash memory location when it can run the application.

I am not going to describe in details what is not working trying to save the time of the audience, I will describe the easiest test case I'm trying to make to work.

My test example is trying to get to work an existing example:

http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/317657.aspx?pi307171=3

1. I have written a simple app in ccs that blink LED1 using delay in the loop + fire timer interrupt that blink LED2 (to see is the interrupt vector table being looked after). After playing a lot with the linker script I keep it simple for now. Blinking app is starting at 0x00000000 in flash. It works perfectly, using LMFlash I can save bin on the HDD, erase and upload back again it is working fine every time. I have stored offseted version of the blinking led program 0x00 to 0xC00, and again I can erase, upload and run.

2. I cloned LED test program, removed everything in main and copy/paste code from the link example:

HWREG(NVIC_VTABLE) = 0x00002800;
        __asm(" ldr r1, [r0]\n"
        " mov sp, r1");

        __asm(" ldr r0, [r0, #4]\n"
        " bx r0\n");

3. I have uploaded offseted version of the blinking led program (0x00 to 0xC00) into flash location 0x00002800 (I have verified that by reading all flash memory into a file)

My problem is that nothing happens, led is not blinking, I would like to get confidence that I can upload the application into any location of the flash with the same result. Ideally I want to keep two different apps in the flash and decide which one I jump upon start.

I have attached source of the app + linker that two examples are based on:

App:

unsigned int isrcounter;
unsigned int test;


//---------------------------------------------------------------------------
// delay()
//
// Creates a 500ms delay via TivaWare fxn
//---------------------------------------------------------------------------
void delay(void)
{
     SysCtlDelay(6700000);        // creates ~500ms delay - TivaWare fxn

}


int main(void) {


    // if it is 0x31 0x31 0x31 0x31 then Block 1 switch to Vector 0x2800
    if(1)
    {
        HWREG(NVIC_VTABLE) = 0x00002800;
        __asm(" ldr r1, [r0]\n"
        " mov sp, r1");

        __asm(" ldr r0, [r0, #4]\n"
        " bx r0\n");
    }


    /*


    //HWREG(NVIC_VTABLE) = (unsigned long)0x00001800;
    //Set CPU Clock to 40MHz. 400MHz PLL/2 = 200 DIV 5 = 40MHz
    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

    // ADD Tiva-C GPIO setup - enables port, sets pins 1-3 (RGB) pins for output
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4);

    // Turn on the LED
    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 4);

    uint32_t ui32Period;
        //to get the timer interrupt working
                    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
                    TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
                    //ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
                    int tmp=SysCtlClockGet();
                    TimerPrescaleSet(TIMER1_BASE, TIMER_A, 50000);
                    ui32Period = SysCtlClockGet()/1000;//devide by 1000 to get one ms interval
                    TimerLoadSet(TIMER1_BASE, TIMER_A, 900000);
                    IntEnable(INT_TIMER1A);
                    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
                    IntMasterEnable();
                    TimerEnable(TIMER1_BASE, TIMER_A);

                    while(1)
                                    {
                                        test++;

                                            // LED values - 2=RED, 4=BLUE, 8=GREEN
                                            if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4))
                                            {
                                                GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
                                            }
                                            else
                                            {
                                                GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 16);
                                            }
                                            delay();

                                    }

*/}


void ledToggle(void)
{
    // LED values - 2=RED, 4=BLUE, 8=GREEN
    if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
    }
    else
    {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
    }
}


void TimerIntHandler(void)
{

    isrcounter++;

// Clear the timer interrupt
TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

ledToggle();                            // toggle LED


}

LINKER FILE

#define APP_BASE 0x00000000 //0x00002800
#define RAM_BASE 0x20000000

--retain=g_pfnVectors

MEMORY
{
    FLASH (RX) : origin = 0x00000000, length = 0x00030000
    SRAM (RWX) : origin = 0x20000000, length = 0x00008000
}

/* The following command line options are set as part of the CCS project.    */
/* If you are building using the command line, or for some reason want to    */
/* define them here, you can uncomment and modify these lines as needed.     */
/* If you are using CCS for building, it is probably better to make any such */
/* modifications in your CCS project and leave this file alone.              */
/*                                                                           */
/* --heap_size=0                                                             */
/* --stack_size=256                                                          */
/* --library=rtsv7M4_T_le_eabi.lib                                           */

/* Section allocation in memory */

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

    .vtable :   > 0x20000000
    .data   :   > SRAM
    .bss    :   > SRAM
    .sysmem :   > SRAM
    .stack  :   > SRAM
}

__STACK_TOP = __stack + 512;

Thanks

Patrick

  • Hi,

        I think it will help you if you study how Tivaware bootloader example programs work together like boot_serial and boot_demo1. 

        One important file to review is the startup file of boot_serial. Besides that there is the Boot loader User's Guide.

        Also, boot loader topic has been discussed here several times. You can do a search here in the forum regarding boot loaders and learn from those posts.

    - kel

  • Hello Pat,

    Kel's suggestion of using the TIVAWare bootloader example program is perfect.

    We did a simple flash boot loader example for TM4C129 which you may be able to retrofit for TM4C123

    http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/355240/1252972.aspx#1252972

    Regards

    Amit

  • Hi Kel

    The examples from TI copy bootloader to ram, I needed very simple entry app (bootloader) performing jump into desired memory address (Target application). I got it to work initially with interrupts causing problems but finally I have fixed everything.

    Please find the example how to get it to work bellow:

    Bootloader simplified (only looks after jump into 0x2800)

    int main(void) {


        IntMasterDisable(); // disable interrupts
            HWREG(NVIC_VTABLE) = 0x00002800;
            __asm(" ldr r1, [r0]\n"
            " mov sp, r1");

            __asm(" ldr r0, [r0, #4]\n"
            " bx r0\n");
    }

    ***************LINKER FILE bootloader

    /******************************************************************************
     *
     * Default Linker Command file for the Texas Instruments TM4C123GH6PM
     *
     * This is derived from revision 11167 of the TivaWare Library.
     *
     *****************************************************************************/

    #define APP_BASE 0x00000000 //0x00002800
    #define RAM_BASE 0x20000000

    --retain=g_pfnVectors

    MEMORY
    {
        FLASH (RX) : origin = 0x00000000, length = 0x00030000
        SRAM (RWX) : origin = 0x20000000, length = 0x00008000
    }

    /* The following command line options are set as part of the CCS project.    */
    /* If you are building using the command line, or for some reason want to    */
    /* define them here, you can uncomment and modify these lines as needed.     */
    /* If you are using CCS for building, it is probably better to make any such */
    /* modifications in your CCS project and leave this file alone.              */
    /*                                                                           */
    /* --heap_size=0                                                             */
    /* --stack_size=256                                                          */
    /* --library=rtsv7M4_T_le_eabi.lib                                           */

    /* Section allocation in memory */

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

        .vtable :   > 0x20000000
        .data   :   > SRAM
        .bss    :   > SRAM
        .sysmem :   > SRAM
        .stack  :   > SRAM
    }

    __STACK_TOP = __stack + 512;

    *************************************************

    ******************APP that resides at 0x2800

    unsigned int isrcounter;
    unsigned int test;


    //---------------------------------------------------------------------------
    // delay()
    //
    // Creates a 500ms delay via TivaWare fxn
    //---------------------------------------------------------------------------
    void delay(void)
    {
         SysCtlDelay(6700000);        // creates ~500ms delay - TivaWare fxn

    }


    int main(void) {






        //HWREG(NVIC_VTABLE) = (unsigned long)0x00001800;
        //Set CPU Clock to 40MHz. 400MHz PLL/2 = 200 DIV 5 = 40MHz
        SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

        // ADD Tiva-C GPIO setup - enables port, sets pins 1-3 (RGB) pins for output
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4);

        // Turn on the LED
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 4);

        uint32_t ui32Period;
            //to get the timer interrupt working
                        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
                        TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
                        //ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
                        int tmp=SysCtlClockGet();
                        TimerPrescaleSet(TIMER1_BASE, TIMER_A, 50000);
                        ui32Period = SysCtlClockGet()/1000;//devide by 1000 to get one ms interval
                        TimerLoadSet(TIMER1_BASE, TIMER_A, 900000);
                        IntEnable(INT_TIMER1A);
                        TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
                        IntMasterEnable();
                        TimerEnable(TIMER1_BASE, TIMER_A);

                        while(1)
                                        {
                                            test++;

                                                // LED values - 2=RED, 4=BLUE, 8=GREEN
                                                if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4))
                                                {
                                                    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
                                                }
                                                else
                                                {
                                                    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 16);
                                                }
                                                delay();

                                        }

    }


    void ledToggle(void)
    {
        // LED values - 2=RED, 4=BLUE, 8=GREEN
        if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
        {
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
        }
        else
        {
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
        }
    }


    void TimerIntHandler(void)
    {

        isrcounter++;

    // Clear the timer interrupt
    TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

    ledToggle();                            // toggle LED


    }

    *****************APP LINKER

    /******************************************************************************
     *
     * Default Linker Command file for the Texas Instruments TM4C123GH6PM
     *
     * This is derived from revision 11167 of the TivaWare Library.
     *
     *****************************************************************************/

    #define APP_BASE 0x00002800 //0x00000000 //0x00002800
    #define RAM_BASE 0x20000000

    --retain=g_pfnVectors

    MEMORY
    {
        FLASH (RX) : origin = APP_BASE, length = 0x00030000  //FLASH (RX) : origin = 0x00000000, length = 0x00030000
        SRAM (RWX) : origin = 0x20000000, length = 0x00008000
    }

    /* The following command line options are set as part of the CCS project.    */
    /* If you are building using the command line, or for some reason want to    */
    /* define them here, you can uncomment and modify these lines as needed.     */
    /* If you are using CCS for building, it is probably better to make any such */
    /* modifications in your CCS project and leave this file alone.              */
    /*                                                                           */
    /* --heap_size=0                                                             */
    /* --stack_size=256                                                          */
    /* --library=rtsv7M4_T_le_eabi.lib                                           */

    /* Section allocation in memory */

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

        .vtable :   > 0x20000000
        .data   :   > SRAM
        .bss    :   > SRAM
        .sysmem :   > SRAM
        .stack  :   > SRAM
    }

    __STACK_TOP = __stack + 512;

    ******************FINALLY SCREENSHOT FROM THE LM FLASHER

    HOW TO RUN IT:

    1. Bootloader, compile , debug and stop (code will stay in the MCU)

    2. Compile test program (do not debug or run on the development board)

    3. Open LM flash and upload bin according to the screenshot

    Best luck

    Patrick