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.

Best ever, "Serial Boot Loader Application Note w/Code Base" now is on-line!

Other Parts Discussed in Thread: EK-TM4C1294XL

Greetings,

As an occasional forum participant the need for greater, "Serial Boot Loader" detail & clarity became obvious.   And that mission has (yesterday) been very well accomplished!

Amit Ashara's forum work is respected & appreciated - yet his creation of this detailed, yet very readable (and understandable) "Serial Boot Loader Application Note" breaks new ground!   Forty-five pages of well explained background & implementation await each reader.   Amit's use of diagrams - many w/ key/critical details in color - greatly aids understanding.

You can find TI's, "Serial Boot Loader Application Note w/Code Base" at:

http://www.ti.com/lit/an/spma074/spma074.pdf

Amit's work is sure to save we forum users countless time & effort.   

Comments, questions, additions & user results - all are welcomed by Amit - w/in this thread.   (this may serve as a new, "Boot Loader Central" depository - which proves superior to multiple, individual, "harder to find" threads.)

  • Hello cb1,

    Thank you for the kind words. I think the Application Note and others to follow are more based on

    e2e.ti.com/.../423619

    And other forum posts where issues in understanding the device and its function need "examples"...

    Comments Welcome.

    Regards
    Amit
  • (copied from other thread, leaving out cb1 comments.....)

    Thanks to Amit I have replicated the example spma074 but have a question about the state of the target.

    When I download an app from Host GUI thru programmer to target, target immediately executes app upon completion of the dl.

    But after a power cycle I must press the target reset button before the target app code executes. So it would appear that the target stays in the bootloader upon power up rather than going to the app. I also tried disconnecting the GPIO pin used to force the target into Bootloader, but thats not it.

    I suspect it is in the tmc_device_recovery_code, in the setting of the HWREGs(probably FLASH_BOOTCFG). Is there a good description of how hw_flash.h can be used? I have looked in data sheet for TM4C1294, BootLoader Users Guide(spmu301a), and ROM Users Guide (spmu363a) but no luck so far in setting up FLASH_BOOTCFG beyond this single example.

    I'd like to be able to jump from app into ROM bootloader (example already jumps from ROM bootloader to app upon completion -> basically I'd like to sw trigger the jump to bootloader as opposed to using GPIO pin) and to have app run from power up rather than stay in bootloader waiting for reset button.

    Thanks,

    -Phil B
    -----------------------------------------------------------------------------------------------------------

    Hello Phil

    If you have just used the binary codes without any modification, then did you try to connect the GPIO pin to 3.3V via a pull up resistance before powering up?

    Also what is the exact nature of information that you require on FLASH_BOOTCFG?

    Regards
    Amit

    ------------------------------------------------------------------------------------------------------------=-

    Amit,
    I will try the GPIO pin pulled up. But I thought that the SBL GUI on default would not have engaged the GPIO pin so it should be the correct state. (But I havent looked at the state with a probe so will try the pull up)

    ok, so to rephrase my additional question:

    What would the code be to jump into the ROM bootloader from the app (bypassing the use of the GPIO pin).
    I found this in the boot_demo1.c but it states this is for flash based bootloader rather than ROM based bootloader.

    void
    JumpToBootLoader(void)
    {
    //
    // 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;

    //
    // Return control to the boot loader. This is a call to the SVC
    // handler in the boot loader.
    //
    (*((void (*)(void))(*(uint32_t *)0x2c)))();
    }

    Maybe this jump can be used for either bootloader or maybe its just a different address than 0x2c?
    Thanks,
    -Phil

    ------------------------------------------------------------------------------------------------------
    ok, pulling up the GPIO pin allows the app to run from power up. Thanks!
    -Phil


    ---------------------------------------------------------------------------------------------------------

    Hello Phil

    The code to jump to boot loader could be a lot of other things. As an example, some of the TivaWare examples on boot loader with display, use the touch on the display to jump to boot loader. A magic packet on Ethernet could be another example.

    Regards
    Amit
  • Amit,
    I tried the JumpToBootloader code above but I dont think I'm in the correct bootloader as the SBL GUI responds with 'TIMEOUT from Target'.

    My setup is 'same as your demo' but with Target GPIO B4 pulled up(No GPIO jump to bootloader), Target power back on ICDI and running modified Target tm4c_all_led_blink code that when USR_SW2 is pressed runs the JumpToBootloader() code above. Once code has branched as indicated above I try the GUI file DL.

    Do I need to change HWREG (FLASH_CFG) ? What is actually code to jump into ROM bootloader?

    Thanks,
    -Phil
  • Hello Phil

    OK. Rewind. The example codes that come along with SBL do not have a JumpToBootloader call. Did you make any changes to the code?

    If the tm4c_device_recovery_code binary file has been flashed already and the device power cycled then you do not need to change BOOTCFG register.

    Regards
    Amit
  • Amit,

    Yes, I modified the examples to attempt a JumpToBootloader call. I added that code from boot_demo1.c into a modified tm4c_all_led_blink but may not be appropriate in this case.

    So I have tm4c_device_recovery_code as unchanged in Target. ie, I have the default BOOT_CFG settings.

    But I did change tm4c_all_led_blink to based on USR_SW2 attempt to jump into the ROM bootloader thereby negatiing the need for GPIO  output from Programmer to Target to place into Bootloader.

    Also I have tried this in 2 ways:

    1. Target Powered by ICDI, Target GPIO pin pulled up, using ICDI to load image below direct to Target and after DL and button pushes attempt to load file from SBL GUI.

    2. Target powered by Programmer and GPIO connected between Programmer and Target (your default mode). DL image below using SDL GUI, then after pushing Target buttons, then disable ticbox for Boot Pin Control and attempt to load new file from SBL GUI.

    In each case I get the same error: TIMEOUT from Target. I'm thinking the branch is invalid in the JumpToBootLoader().

    My code is as follows: (usr_sw2_mode is just there to see feedback from USR_SW2 and verify isr):

    static uint32_t usr_sw2_mode = 0;
    static uint32_t ui32SysClock;

    //*****************************************************************************
    //
    // Passes control to the bootloader and initiates a remote software update.
    //
    // This function passes control to the bootloader and initiates an update of
    // the main application firmware image via UART0 or USB depending
    // upon the specific boot loader binary in use.
    //
    // \return Never returns.
    //
    //*****************************************************************************
    void
    JumpToBootLoader(void)
    {
        //
        // 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;

        //
        // Return control to the boot loader.  This is a call to the SVC
        // handler in the boot loader.
        //
        (*((void (*)(void))(*(uint32_t *)0x2c)))();
    }


    //*****************************************************************************
    //
    // GPIOJIntHandler.
    //
    //*****************************************************************************
    void
    GpioJIntHandler(void)
    {

        //
        // Clear the GPIO interrupt.
        //
        //
        // Delay here on button push for simple debouncing.
        //
        SysCtlDelay(ui32SysClock / 10);

        //
        // Clear the timer interrupt.
        //
        ROM_GPIOIntClear(GPIO_PORTJ_AHB_BASE, GPIO_INT_PIN_1);


        if (usr_sw2_mode < 2)
            usr_sw2_mode ++;
        else
            JumpToBootLoader();
    }


    //*****************************************************************************
    //
    // The program main function.  It performs initialization, then runs a loop to
    // blink LED's
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Variable for Clock Frequency
        //

    #if (defined (TARGET_IS_TM4C129_RA0) || \
         defined (TARGET_IS_TM4C129_RA1) || \
         defined (TARGET_IS_TM4C129_RA2))

        //
        // Set the System Clock to 120MHz if the device is a TM4C129
        //
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_XTAL_25MHZ |
                                SYSCTL_CFG_VCO_480), 120000000);

        //
        // Configure GPIO Port F Pins 1-3 as GPIO Output (LED)
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
        GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, (GPIO_PIN_1 | GPIO_PIN_0));

        //
        // Initialize the buttons driver.
        //
        ButtonsInit();

        //
        // Enable the interrupt for the button.
        //
        ROM_GPIOIntEnable(GPIO_PORTJ_AHB_BASE, GPIO_INT_PIN_1);

        //
        // Set pad config.
        //
        MAP_GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_PIN_1,
                              GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

        //
        // Set direction.
        //
        ROM_GPIODirModeSet(GPIO_PORTJ_BASE, GPIO_PIN_1, GPIO_DIR_MODE_IN);

        //
        // Enable the interrupt for the button.
        //
        ROM_GPIOIntEnable(GPIO_PORTJ_BASE, GPIO_INT_PIN_1);

        //
        // Enable interrupt to NVIC.
        //
        ROM_IntEnable(INT_GPIOJ);

        ROM_IntMasterEnable();


        //
        //
        while(1)
        {
            if (usr_sw2_mode == 0)
            {
                // Blink the LED's together
                GPIOPinWrite(GPIO_PORTN_BASE, (GPIO_PIN_1 | GPIO_PIN_0),
                    (GPIO_PIN_1 | GPIO_PIN_0));
                SysCtlDelay(ui32SysClock/12);
                GPIOPinWrite(GPIO_PORTN_BASE, (GPIO_PIN_1 | GPIO_PIN_0),
                    0x0);
                SysCtlDelay(ui32SysClock/12);
            }
            else
            {
                // Alternate LED's
                GPIOPinWrite(GPIO_PORTN_BASE, (GPIO_PIN_1 | GPIO_PIN_0), (GPIO_PIN_0));
                SysCtlDelay(ui32SysClock/12);
                GPIOPinWrite(GPIO_PORTN_BASE, (GPIO_PIN_1 | GPIO_PIN_0), (GPIO_PIN_1));
                SysCtlDelay(ui32SysClock/12);

            }
        }
    #endif

    #if (defined (TARGET_IS_TM4C123_RB1) || \
         defined (TARGET_IS_TM4C123_RB2))

        //
        // Set the System Clock to 80MHz if the device is a TM4C123
        //
        SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                           SYSCTL_XTAL_16MHZ);

        //
        // Get the System Clock Frequency
        //
        ui32SysClock = SysCtlClockGet();

        //
        // Configure GPIO Port F Pins 1-3 as GPIO Output
        //
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1));
        GPIOPinWrite(GPIO_PORTF_BASE, (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1), 0x0);

        //
        // Blink the LED's together
        //
        while(1)
        {
            GPIOPinWrite(GPIO_PORTF_BASE, (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1),
                    0x0);
            SysCtlDelay(ui32SysClock/12);
            GPIOPinWrite(GPIO_PORTF_BASE, (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1),
                    (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1));
            SysCtlDelay(ui32SysClock/12);
        }


    #endif
    }

  • Hello Phil,

    The JumpToBootloader is required when there is a flash based boot loader. In the example provided there is no flash based boot loader which would explain why you are getting a Timeout.

    The solution is to implement a Flash based boot loader that can be invoked by the call, move the application out of the 0x0 to the next sector in flash, so that when flash based boot loader is invoked, it may update the application image.

    Regards
    Amit
  • Amit,
    So the only way to get to the ROM based boot loader is via a GPIO line?

    I will look into using a flashed based bootloader for the sw control.

    Thanks for all the help,
    -Phil
  • Hello Phil,

    Or you can call the ROM_UpdateXXX function instead of making the 0x2c call.

    Regards
    Amit
  • Amit,
    I replaced the 0x2c call with
    ROM_UpdateUART() but with no change in behavior. Still the SBL GUI times out when trying to DL file to the target when the Boot Pin Control box is unticked. This should be using UART0 same as when using GPIO to go to bootloader.
    -Phil
  • Hello Phil,

    I would suggest checking the example

    D:\ti\TivaWare_C_Series-2.1.2.111\examples\boards\dk-tm4c129x\boot_demo_uart where before calling ROM_UpdateUART the UART0 is first initialized.

    At the same time based on this thread, I do see a lot of room for improving the Application Note.

    Regards
    Amit
  • Thanks, Amit!
  • , could you please add this app note to the resource explorer? I was searching app notes under tm4c123 and tm4c129x and I didn't find it.

    Could you please also check if are any missing? I find it much more easy to consult this "repository"
  • Hello Luis,

    We are working on the automated system of pulling it and newer application notes planned into Resource Explorer.

    Regards
    Amit
  • Truth in Advertising Dept: This thread "disappeared for 3 or so hours!"  (today, Dec 21, '15)   Now has been restored.  

    We were advised that thread had "30 day sticky rating" - and was just renewed!   

  • Hello Amit,

    I have added code to initialize UART0. But when I run the ROM_UpdateUART() , the Target LEDs are blinking which means the Target is running an app and is not sitting in the bootloader awaiting an image to be DL (and hence the timeout from the Programmer if I attempt a DL). How do I communicate to the bootloader to wait for an image from UART0? I thought that was what ROM_UpdateUART() is supposed to do.

    I have a pull up on GPIO input PB4 that the device_recovery_code is looking for for the normal demo jump to ROM bootloader.

    Again, all I am looking for is a way to remove the need for GPIO input PB4 to cause the Target to jump to ROM bootloader, but instead use target sw to make this change from app to bootloader.

    My UART0 init code is copied from boot_demo_uart.c

        //
        // Enable interrupt to NVIC.
        //
        ROM_IntEnable(INT_GPIOJ);

        ROM_IntMasterEnable();

        //
        // Enable the UART that will be used for the firmware update.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

        //
        // Configure the UART for 115200, 8-N-1.
        //
        ROM_UARTConfigSetExpClk(UART0_BASE, ui32SysClock, 115200,
                                (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_WLEN_8));

        //
        // Enable the UART operation.
        //
        ROM_UARTEnable(UART0_BASE);

    Thanks,

    -Phil

  • Hello Phil,

    The configuration of the UART is all correct except

    1. The interrupts must be disabled before calling the ROM_UpdateUART() and the GPIO corresponding to UART-0 configured for UART operation

    HWREG(NVIC_DIS0) = 0xffffffff;
    HWREG(NVIC_DIS1) = 0xffffffff;
    HWREG(NVIC_DIS2) = 0xffffffff;
    HWREG(NVIC_DIS3) = 0xffffffff;
    HWREG(NVIC_DIS4) = 0xffffffff;

    2. To use a Switch, you need to first of all ensure that there is a Pull Up on the IO so that when the switch is pressed to connect the pin to GND, it should be able to detect the new level.

    Regards
    Amit
  • Hello Amit,

    I already have the interrupts as you indicated and I am using USR_SW2 on the Target(Launchpad T129) which I believe is already properly grounded? I have no change in my result.

    So I worked on 'starting over' and making a 'smaller' change relative to your demo. Instead of your demo using 2 GPIO pins to reset and trigger the boot loader, I connected the reset line from the Programmer into a 'new' GPIO pin, PK6 and use that (rather than Target USR_SW2) as a GPIO Isr into the Target to cause the jump to bootloader. This way the Programmer is active while the Target jumps into the boot loader. I pulled up the Target RST and Target PB4 from your demo.

    I set an LED just before jumping into the boot loader to verify that action. In each case above, using the Launchpad USR_SW2 or using PK6 as a GPIO isr to jump into the boot loader, I am not able to get the boot loader to accept a file DL.

    My code for the jump (including LED writes)

    void
    JumpToBootLoader(void)
    {
        // Set the LED's to know state
        // PF4 = LED3
        GPIOPinWrite(GPIO_PORTF_BASE, (GPIO_PIN_4),
            (GPIO_PIN_4));

        //
        // 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;
        HWREG(NVIC_DIS4) = 0xffffffff;

        //
        // Return control to the boot loader.  This is a call to the SVC
        // handler in the boot loader.
        //
        ROM_UpdateUART();

        // Test if returns from boot loader.
        // PF0 = LED4
        GPIOPinWrite(GPIO_PORTF_BASE, (GPIO_PIN_0),
            (GPIO_PIN_0));


    }

    I even tried keeping the PB4 connected but I dont know if ROM_UpdateUART() looks at PB4 the same way that a reset does.(Nor if the Programmer timing is appropriate for that)

    How does the boot loader know that a DL is required w/o the PB4 input? (or maybe I am asking how can that be configured?)

    Thanks again,

    -Phil

  • Hello Phil,

    The serial boot loader example is now available for EK-TM4C1294XL in TivaWare 2.1.2.111 release. May be you can use that and work it backwards to your project files.

    D:\ti\TivaWare_C_Series-2.1.2.111\examples\boards\ek-tm4c1294xl\boot_demo1
    D:\ti\TivaWare_C_Series-2.1.2.111\examples\boards\ek-tm4c1294xl\boot_demo2
    D:\ti\TivaWare_C_Series-2.1.2.111\examples\boards\ek-tm4c1294xl\boot_serial

    Regards,
    Amit
  • Amit,

    Thanks I will look into those examples.

    -Phil