The TI E2E™ design support forums will undergo maintenance from July 11 to July 13. If you need design support during this time, open a new support request with our customer support center.

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.

TM4C1297NCZAD: TM4C1297nczadi3 as a USB Host - firmware update via read a binary file from a USB memory

Part Number: TM4C1297NCZAD
Other Parts Discussed in Thread: EK-TM4C1294XL, EK-TM4C129EXL,

Tool/software:

I am trying to start with the firmware update via USB memory using the example in TivaWare_C_Series-2.2.0.295\examples\boards\dk-tm4c129x\usb_stick_update, but I have not been successful. 

I'm not getting device detected/enumerated, and it always shows STATE_NO_DEVICE.

Thanks

        case MSC_EVENT_CLOSE:
        {
            //
            // Go back to the "no device" state and wait for a new connection.
            //
            g_eState = STATE_NO_DEVICE;
            break;
        }

  • Hi,

    I am trying to start with the firmware update via USB memory using the example in TivaWare_C_Series-2.2.0.295\examples\boards\dk-tm4c129x\usb_stick_update,

    The example you refer to is for a DK-TM4C129 EVM board that is no longer available for sales. If you have a LaunchPad (EK-TM4C1294XL) please try out the same example in C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\usb_stick_update. If you can get it working on a LaunchPad then you can compare the difference between the LaunchPad and your custom board. 

    Please go through the example description. As you can see in the description there are three conditions under which the usb_stick_update will load a new firmware from the USB stick. This example assumes the APP_START_ADDRESS at 0x8000. Your firmware on the USB stick must be linked and allocated to 0x8000. The firmware filename must be FIRMWARE.BIN and the USB stick needs to be a FA16 or FAT32 file system. You can reference the example firmware at C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\usb_stick_demo and rename from usb_stick_demo.bin to FIRMWARE.BIN. 

    USB Memory Stick Updater

    This example application behaves the same way as a boot loader. It resides
    at the beginning of flash, and will read a binary file from a USB memory
    stick and program it into another location in flash. Once the user
    application has been programmed into flash, this program will always start
    the user application until requested to load a new application.

    When this application starts, if there is a user application already in
    flash (at \b APP_START_ADDRESS), then it will just run the user application.
    It will attempt to load a new application from a USB memory stick under
    the following conditions:

    - no user application is present at \b APP_START_ADDRESS
    - the user application has requested an update by transferring control
    to the updater
    - the user holds down the USR_SW1 button when the board is reset

    When this application is attempting to perform an update, it will wait
    forever for a USB memory stick to be plugged in. Once a USB memory stick
    is found, it will search the root directory for a specific file name, which
    is \e FIRMWARE.BIN by default. This file must be a binary image of the
    program you want to load (the .bin file), linked to run from the correct
    address, at \b APP_START_ADDRESS.

    The USB memory stick must be formatted as a FAT16 or FAT32 file system
    (the normal case), and the binary file must be located in the root
    directory. Other files can exist on the memory stick but they will be
    ignored.

  • The customer board has the TM4C1297NCZADI3 microcontroller. This customer board has a USB Type-A female connector.

    1. Can I implement the example from C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\usb_stick_update For this specific microcontroller, TM4C1297NCZADI3, are there other types of boards, like dk-tm4c129x, ek-tm4c129exl, and ek-tm4c1294xl? Which of these examples is more compatible with this microcontroller on this customer board?

      #define PROG_LEN (FLASH_SIZE - 0x20000) 
      #define DATA_LEN  0x2000
      #define USB_STICK_UPDATE_ADDRESS      0x00000000  //USB stick update
      #define APP_START_ADDRESS             0x8000      //My Application
      
      MEMORY
      {
          /* Application stored in and executes from internal flash */
          PROG_FLASH (RX) : origin = APP_START_ADDRESS, length = PROG_LEN
      
          DATA_FLASH (RWX) : origin = USB_STICK_UPDATE_ADDRESS, length = DATA_LEN
          /* Application uses internal RAM for data */
          SRAM (RWX) : origin = 0x20000000, length = 0x00060000 /*0x00040000*/
      }
      
      /* Section allocation in memory */
      
      SECTIONS
      {
          .intvecs:   > APP_BASE
          .text   :   > PROG_FLASH
          .const  :   > PROG_FLASH
          .cinit  :   > PROG_FLASH
          .pinit  :   > PROG_FLASH
          .binit	:	> PROG_FLASH
          .init_array : > PROG_FLASH
      
          .vtable :   > RAM_BASE
          .data   :   > SRAM
          .bss    :   > SRAM
          .sysmem :   > SRAM
          .stack  :   > SRAM
          .TI.ramfunc : {} load=PROG_FLASH, run=SRAM, table(BINIT)
      }

    2. Is it necessary to modify the APP_START_ADDRESS At 0x8000, as shown in the code?

    3. The customer board has the pins for USB: USB0DP, USB0DM, USB0VBUS, but USB0ID (disconnected). I doubt I can use USB0ID if it is disconnected. Can I control it internally? My purpose for using USB is to update the firmware via a USB Type-A memory stick, so I understand it should be configured as a host. Can you provide me with an example of how I can do it? 

    Additionally, I see that the datasheet for the USB part is incomplete. There is no information on how to configure the registers. Where can I find this USB information for the TivaTm TM4C1297NCZAD microcontroller?

  • Hi,

    Can I implement the example from C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\usb_stick_update For this specific microcontroller, TM4C1297NCZADI3, are there other types of boards, like dk-tm4c129x, ek-tm4c129exl, and ek-tm4c1294xl? Which of these examples is more compatible with this microcontroller on this customer board?

    If you use a custom board with TM4C1297NCZAD on it then you can reference the TivaWare_C_Series-2.2.0.295\examples\boards\dk-tm4c129x\usb_stick_update. Please note that usb_stick_update is more like a bootloader which will reside at 0x0. You do NOT need to modify the .cmd file for usb_stick_update. The APP_BASE will be 0x00000000 in the .cmd file. What you need to specify is where the application firmware will reside in the bootloader source code. Look at usb_stick_update.c file on line 120 where it assumes the #define APP_START_ADDRESS equal to 0x8000. You can modify this address to other addresses that is a multiple of 1024 bytes. The bootloader (usb_stick_date) itself must reside at 0x0.  

    Please do NOT be confused between the APP_BASE that is already already in the usb_stick_update.cmd file and the APP_START_ADDRESS that is in the usb_stick_updarte.c file. 

    • Is it necessary to modify the APP_START_ADDRESS At 0x8000, as shown in the code?

     

    What you also need is an application firmware to work with. As I mentioned there is the example application at C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\dk-tm4c129x\usb_stick_demo. Look at the command file at C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\dk-tm4c129x\usb_stick_demo\usb_stick_demo_ccs.cmd. It is this file that has the APP_BASE set to 0x8000. See below snippet.

    /* The starting address of the application. Normally the interrupt vectors */
    /* must be located at the beginning of the application. */
    #define APP_BASE 0x00008000
    #define RAM_BASE 0x20000000

    /* System memory map */

    MEMORY
    {
    /* Application stored in and executes from internal flash */
    FLASH (RX) : origin = APP_BASE, length = 0x000f8000
    /* Application uses internal RAM for data */
    SRAM (RWX) : origin = 0x20000000, length = 0x00040000
    }

    1. The customer board has the pins for USB: USB0DP, USB0DM, USB0VBUS, but USB0ID (disconnected). I doubt I can use USB0ID if it is disconnected. Can I control it internally? My purpose for using USB is to update the firmware via a USB Type-A memory stick, so I understand it should be configured as a host. Can you provide me with an example of how I can do it? 

    I don't think you need VBUSID to run usb_stick_update.

  • Just to let you know that I run usb_stick_update on my DK-TM4C129x board and it successfully loads theusb_stick_demo program. If you have a DK board I will suggest you run it as is to get a feel for it. If you don't have a DK board, this is why I first suggested you you run on the EK-TM4C1294XL LaunchPad board by running the C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\usb_stick_update.

  • Hi Charles,

    Curious does USB updater have a flash erase function or does the user have to manually erase flash banks each time an update is required? 

  • Hi BP101,

      Yes, the updater has the flash erase/program function. See below function in usb_stick_update.c file. 

    //*****************************************************************************
    //
    // Read the application image from the file system and program it into flash.
    //
    // This function will attempt to open and read the firmware image file from
    // the mass storage device.  If the file is found it will be programmed into
    // flash.  The name of the file to be read is configured by the macro
    // \b USB_UPDATE_FILENAME.  It will be programmed into flash starting at the
    // address specified by APP_START_ADDRESS.
    //
    // \return Zero if successful or non-zero if the file cannot be read or
    // programmed.
    //
    //*****************************************************************************
    uint32_t
    ReadAppAndProgram(void)
    {
        uint_fast32_t ui32FlashEnd;
        uint_fast32_t ui32FileSize;
        uint_fast32_t ui32DataSize;
        uint_fast32_t ui32Remaining;
        uint_fast32_t ui32ProgAddr;
        uint_fast32_t ui32SavedRegs[2];
        volatile uint_fast32_t ui32Idx;
        uint_fast32_t ui32DriveTimeout;
    
        //
        // Initialize the drive timeout.
        //
        ui32DriveTimeout = USBMSC_DRIVE_RETRY;
    
        //
        // Check to see if the mass storage device is ready.  Some large drives
        // take a while to be ready, so retry until they are ready.
        //
        while(USBHMSCDriveReady(g_psMSCInstance))
        {
            //
            // Wait about 500ms before attempting to check if the
            // device is ready again.
            //
            SysCtlDelay(g_ui32SysClock/(3*2));
    
            //
            // Decrement the retry count.
            //
            ui32DriveTimeout--;
    
            //
            // If the timeout is hit then return with a failure.
            //
            if(ui32DriveTimeout == 0)
            {
                return(1);
            }
        }
    
        //
        // Initialize the file system and return if error.
        //
        if(SimpleFsInit(g_ui8SectorBuf))
        {
            return(1);
        }
    
        //
        // Attempt to open the firmware file, retrieving the file/image size.
        // A file size of error means the file was not there, or there was an
        // error.
        //
        ui32FileSize = SimpleFsOpen(USB_UPDATE_FILENAME);
        if(ui32FileSize == 0)
        {
            return(1);
        }
    
        //
        // Get the size of flash.  This is the ending address of the flash.
        // If reserved space is configured, then the ending address is reduced
        // by the amount of the reserved block.
        //
        ui32FlashEnd = FLASH_SIZE;
    #ifdef FLASH_RSVD_SPACE
        ui32FlashEnd -= FLASH_RSVD_SPACE;
    #endif
    
        //
        // If flash code protection is not used, then change the ending address
        // to be the ending of the application image.  This will be the highest
        // flash page that will be erased and so only the necessary pages will
        // be erased.  If flash code protection is enabled, then all of the
        // application area pages will be erased.
        //
    #ifndef FLASH_CODE_PROTECTION
        ui32FlashEnd = ui32FileSize + APP_START_ADDRESS;
    #endif
    
        //
        // Check to make sure the file size is not too large to fit in the flash.
        // If it is too large, then return an error.
        //
        if((ui32FileSize + APP_START_ADDRESS) > ui32FlashEnd)
        {
            return(1);
        }
    
        //
        // Enter a loop to erase all the requested flash pages beginning at the
        // application start address (above the USB stick updater).
        //
        for(ui32Idx = APP_START_ADDRESS; ui32Idx < ui32FlashEnd; ui32Idx += 1024)
        {
            ROM_FlashErase(ui32Idx);
        }
    
        //
        // Enter a loop to read sectors from the application image file and
        // program into flash.  Start at the user app start address (above the USB
        // stick updater).
        //
        ui32ProgAddr = APP_START_ADDRESS;
        ui32Remaining = ui32FileSize;
        while(SimpleFsReadFileSector())
        {
            //
            // Compute how much data was read from this sector and adjust the
            // remaining amount.
            //
            ui32DataSize = ui32Remaining >= 512 ? 512 : ui32Remaining;
            ui32Remaining -= ui32DataSize;
    
            //
            // Special handling for the first block of the application.
            // This block contains as the first two location the application's
            // initial stack pointer and instruction pointer.  The USB updater
            // relied on the values in these locations to determine if a valid
            // application is present.  When there is a valid application the
            // updater runs the user application.  Otherwise the updater attempts
            // to load a new application.
            // In order to prevent a partially programmed imaged (due to some
            // error occurring while programming), the first two locations are
            // not programmed until all of the rest of the image has been
            // successfully loaded into the flash.  This way if there is some error,
            // the updater will detect that a user application is not present and
            // will not attempt to run it.
            //
            // For the first block, do not program the first two word locations
            // (8 bytes).  These two words will be programmed later, after
            // everything else.
            //
            if(ui32ProgAddr == APP_START_ADDRESS)
            {
                uint32_t *pui32Temp;
    
                pui32Temp = (uint32_t *)g_ui8SectorBuf;
                ui32SavedRegs[0] = pui32Temp[0];
                ui32SavedRegs[1] = pui32Temp[1];
    
                //
                // Call the function to program a block of flash.  Skip the first
                // two words (8 bytes) since these contain the initial SP and PC.
                //
                ROM_FlashProgram((uint32_t *)&g_ui8SectorBuf[8],
                                 ui32ProgAddr + 8,
                                 ((ui32DataSize - 8) + 3) & ~3);
            }
    
            //
            // All other blocks except the first block
            //
            else
            {
                //
                // Call the function to program a block of flash.  The length of the
                // block passed to the flash function must be divisible by 4.
                //
                ROM_FlashProgram((uint32_t *)g_ui8SectorBuf, ui32ProgAddr,
                                 (ui32DataSize + 3) & ~3);
            }
    
            //
            // If there is more image to program, then update the programming
            // address.  Progress will continue to the next iteration of
            // the while loop.
            //
            if(ui32Remaining)
            {
                ui32ProgAddr += ui32DataSize;
            }
    
            //
            // Otherwise we are done programming so perform final steps.
            // Program the first two words of the image that were saved earlier,
            // and return a success indication.
            //
            else
            {
                ROM_FlashProgram((uint32_t *)ui32SavedRegs, APP_START_ADDRESS,
                                  8);
    
                return(0);
            }
        }
    
        //
        // If we make it here, that means that an attempt to read a sector of
        // data from the device was not successful.  That means that the complete
        // user app has not been programmed into flash, so just return an error
        // indication.
        //
        return(1);
    }