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.

TM4C123GE6PM: Access ROM Bootloader via FTDI-USB

Part Number: TM4C123GE6PM
Other Parts Discussed in Thread: TM4C123GH6PM

Tool/software:

We have moved from the LaunchPad and created our own board. Programming via FTDI-USB over serial UART0 is working using LM Flash Programmer for our board.

I used the code from the samples to blink a light and if SW1 switch is clicked it launches bootloader. If I were to accidently not upload the correct code with something to enable the bootloader is it possible to start the bootloader? 

Is there a default configuration for a blank chip to enable the bootloader? For instance by default is BOOTCFG set so that I can raise a pin high to get bootloader to run? I just want to be sure that I do not brick the first prototype that we have created.

Thanks in advance!

  • I used the code from the samples to blink a light and if SW1 switch is clicked it launches bootloader. If I were to accidently not upload the correct code with something to enable the bootloader is it possible to start the bootloader? 

    Is there a default configuration for a blank chip to enable the bootloader? For instance by default is BOOTCFG set so that I can raise a pin high to get bootloader to run? I just want to be sure that I do not brick the first prototype that we have created.

    Your understanding is correct. You can force the device into bootloader mode by configuring the BOOTCFG register and specify a GPIO pin as an input to force the device into the bootloader mode. 

    This register is not written directly, but instead uses the FMD register as explained in “Non-Volatile
    Register Programming-- Flash Memory Resident Registers” on page 613. When this register is
    committed, the new value cannot be read back until after the power cycle. This register provides
    configuration of a GPIO pin to enable the ROM Boot Loader as well as a write-once mechanism to
    disable external debugger access to the device. At reset, the user has the opportunity to direct the
    core to execute the ROM Boot Loader or the application in Flash memory by using any GPIO signal
    from Ports A through H as configured by the bits in this register. At reset, the following sequence is
    performed:
    1. The BOOTCFG register is read. If the EN bit is clear, the ROM Boot Loader is executed.
    2. In the ROM Boot Loader, the status of the specified GPIO pin is compared with the specified
    polarity. If the status matches the specified polarity, the ROM is mapped to address 0x0000.0000
    and execution continues out of the ROM Boot Loader.
    3. If the EN bit is set or the status doesn't match the specified polarity, the data at address
    0x0000.0004 is read, and if the data at this address is 0xFFFF.FFFF, the ROM is mapped to
    address 0x0000.0000 and execution continues out of the ROM Boot Loader.
    4. If there is data at address 0x0000.0004 that is not 0xFFFF.FFFF, the stack pointer (SP) is loaded
    from Flash memory at address 0x0000.0000 and the program counter (PC) is loaded from
    address 0x0000.0004. The user application begins executing.

  • Ok. What is the default for the BOOTCFG register? If I did not program the chip, what would be the default GPIO pin and polarity?

  • Hi,

      The default value of BOOTCFG register on a virgin device will be 0xFFFFFFFE. If you look at the bit 8 (EN), it is a 1. This means that GPIO is disabled from forcing the device into ROM bootloader at reset. You can program the PORT, PIN and POL fields to specify which Port pin and polarity to enter ROM bootloader execution. If you only clear the EN bit, then by default a HIGH level on Port H7 will be recognized to enter ROM bootloader.  

  • If I programmed a virgin chip to say blink an LED and it did not include any code to modify the BOOTCFG register, could I bring GPIO pin H7 to GND (low) and enter the boot loader on a reset?

    "In the ROM Boot Loader, the status of the specified GPIO pin is compared with the specified polarity."

  • If I programmed a virgin chip to say blink an LED and it did not include any code to modify the BOOTCFG register, could I bring GPIO pin H7 to GND (low) and enter the boot loader on a reset?

    "In the ROM Boot Loader, the status of the specified GPIO pin is compared with the specified polarity."

    No, you cannot because the EN bit is not clear on a virgin device. 

  • Thanks Charles!
    Can you give me an example of a blinking light program with a modified BOOTCFG that would be the recommended practice for loading a first program or any program such that one can always invoke the ROM bootloader by bringing a GPIO pin high?

  • 1. Start with a virgin device or you can first erase the entire flash. 

    2. You need to use the FMA, FMD and FMC to program the BOOTCFG register. Note this is a one time program. Once programmed, the only method to change its value again is to do a "Unlock" operation and restore the device to its factory setting. Use the below code as an example to use Pin E6 on HIGH to execute ROM bootloader.

    // FMA should have this value to program BOOTCFG
    HWREG(0x400FD000) = 0x75100000;
    // Data to be flashed in BOOTCFG, must be stored in FMD
    HWREG(0x400FD004) = 0xFFFF9AFE; //FMD to enable Port E6 on HIGH for ROM bootloader execution
    // FMC should have writekey and commit bit
    HWREG(0x400FD008) = 0xA4420000 | 0x9; // FMC
    // Wait until commit is complete
    while (HWREG(0x400FD008) & 0x9);

    3. With the Pin E6 LOW, load your blinky code using LM Flash Programmer in UART mode. Note the flash at this moment is still empty. It does not matter if GPIO pin is asserted or not because the stack pointer and reset vector are all F's. 

    4. You should see the blinky program loaded

    5. With the Pin E6 still LOW, load another program like the hello.c using LM Flash Programmer in UART mode. It will not load because a valid program image is already in the flash and the Pin E6 is LOW. 

    7. Change the input E6 to HIGH. 

    8. Load the hello program and the bootloader is forced to load the hello program and overwrite the blinky on the flash memory.

  • I see you used Pin E6 in the example but I do not see that on the datasheet (tm4c123gh6pm.pdf) for the TM4C123G.

    Is it possible to use PD1 or PF4?

  • You can use any pin that is available on the specific device you want to use. It is just that I use E6 based off of a different TM4C123 package. 

  • Ok noted, I see that is available on the 100 pin version. This has been very helpful. I have a couple more questions:

    Question 1:

    You said: "Once programmed, the only method to change its value again is to do a "Unlock" operation and restore the device to its factory setting."

    Is it possible to perform an "Unlock" operation using UART?

    Question 2:

    If starting with virgin device and I send a .bin file with a code snippet to update BOOTCFG will that not effect the stack pointer and reset vector, will they still remain all F's?

    // FMA should have this value to program BOOTCFG
    HWREG(0x400FD000) = 0x75100000;
    // Data to be flashed in BOOTCFG, must be stored in FMD
    HWREG(0x400FD004) = 0xFFFF9AFE; //FMD to enable Port E6 on HIGH for ROM bootloader execution
    // FMC should have writekey and commit bit
    HWREG(0x400FD008) = 0xA4420000 | 0x9; // FMC
    // Wait until commit is complete
    while (HWREG(0x400FD008) & 0x9);

  • Question 1:

    You said: "Once programmed, the only method to change its value again is to do a "Unlock" operation and restore the device to its factory setting."

    Is it possible to perform an "Unlock" operation using UART?

    No, you cannot. You can use the LM flash program to "Unlock" the device. 

    Question 2:

    If starting with virgin device and I send a .bin file with a code snippet to update BOOTCFG will that not effect the stack pointer and reset vector, will they still remain all F's?

    Yes, the flash will be programmed with your code snippet to program the BOOTCFG through the JTAG interface or even UART interface. However, since the BOOTCFG register is already programmed, you can assert your pin PD1 or PF4 to force for bootloader execution to download your new firmware from UART. You can also erase the flash after you programmed the BOOTCFG through JTAG so that the SP and reset become F's with the rest of the flash. 

  • In order to use LM flash program to unlock you must have a JTAG interface? Via Serial interface these options are gone.

  • You cannot use UART to unlock. It must be done through JTAG. This is documented in the d/s. 

  • Understood, thanks for clarifying and the quick responses.

    Is it safe to say that if I run the appropriate code snippet to set the BOOTCFG register then I should always be able to assert the pin PD1 or PF4 to force bootloader execution to download new firmware from UART?

  • Charles,

    So what I would like to run on a virgin device will be the following and my expectation is that I will use GPIO pin PD1 and ground it to enable the bootloader. How does this look?

    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    
    #define FLASH_FMA  0x400FD000
    #define FLASH_FMD  0x400FD004
    #define FLASH_FMC  0x400FD008
    
    int main(void)
    {
        // 1. FMA should have this value to program BOOTCFG
        HWREG(FLASH_FMA) = 0x75100000;
    
        // Data to be flashed in BOOTCFG, must be stored in FMD
        // 2. BOOTCFG value: PD1 active LOW = 0xFFFF65FF
        HWREG(FLASH_FMD) = 0xFFFF65FF; //FMD to enable Port D1 on LOW for ROM bootloader execution
    
        // FMC should have writekey and commit bit
        HWREG(FLASH_FMC) = 0xA4420000 | 0x9;
    
        // Wait until commit is complete
        while (HWREG(FLASH_FMC) & 0x9);
    
    }

  • You didn't clear bit 8 which is to enable GPIO for ROM bootloader. Should be 0xFFFF64FE. 

  • Thanks for catching that. Here is the what I am going to go with. How does that look?

    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    
    #define FLASH_FMA  0x400FD000
    #define FLASH_FMD  0x400FD004
    #define FLASH_FMC  0x400FD008
    
    int main(void)
    {
        // 1. FMA should have this value to program BOOTCFG
        HWREG(FLASH_FMA) = 0x75100000;
    
        // Data to be flashed in BOOTCFG, must be stored in FMD
        // 2. BOOTCFG value: PD1 active LOW = 0xFFFF65FF
        HWREG(FLASH_FMD) = 0xFFFF64FE; //FMD to enable Port D1 on LOW for ROM bootloader execution
    
        // FMC should have writekey and commit bit
        HWREG(FLASH_FMC) = 0xA4420000 | 0x9;
    
        // Wait until commit is complete
        while (HWREG(FLASH_FMC) & 0x9);
    
    }

  • Yes, that should do it. 

  • Got it working! Thanks for the support!