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.

TM4C1294NCPDT: Implementation of a simple DFU Boot Loader

Part Number: TM4C1294NCPDT


Using: TM4C1294NCPDT

Peripheral Library: TivaWare 2.1.4.178

I am trying to provide a way for our FSE folks a simple way to update our products firmware in the field using the LMI Flasher utility on their laptop computers.

In the code for simplicity, after setting the CPU clock (I do this if a push button is pushed) I want to dive into the ROM_UpdateUSB(0) function to begin the update.

When I run the code and look at Device Manager (sorry, win10) I see "Unknown USB Device (Device Descriptor Request Failed)". I try to update the driver with the SW-TM4C-2.1.4.178.PATCH-1.0 but windows tells me the best drivers for your device are already installed. I even tried to uninstall the existing driver as a previous post has suggested, but that has not help.

I have posted my code below in case I am not doing something correctly in the code. I hope to rule out my code as being the problem, then I can turn my attention to my PC.

Any suggestions would be greatly appreciated? Thanks!

#include "inc/hw_memmap.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/rom_map.h"
#include "driverlib/usb.h"
#include "usblib/usblib.h"
#include "usblib/device/usbdevice.h"


int main(void)
{
    uint32_t SysClock;
    uint32_t ui32PLLRate;
    //
    // Run from the PLL at 120 MHz.
    //
    SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    
    //
    // Tell the USB library the CPU clock and the PLL frequency.  This is a
    // new requirement for TM4C129 devices.
    //
    SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &ui32PLLRate);
    USBDCDFeatureSet(0, USBLIB_FEATURE_CPUCLK, &SysClock);
    USBDCDFeatureSet(0, USBLIB_FEATURE_USBPLL, &ui32PLLRate);

    //
    // Enable other GPIO peripherals used for update.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
    //
    MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7);
    //
    // Enable and reset the USB peripheral.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);
    MAP_USBClockEnable(USB0_BASE, 8, USB_CLOCK_INTERNAL);
	
    //
    // Wait for about a second.
    //
    MAP_SysCtlDelay(SysClock / 3);
    //
    // Re-enable interrupts at the NVIC level.
    //
    MAP_IntMasterEnable(); 			// Enable interrupts at NVIC level

    //
    // Call the USB boot loader within ROM.
    //
    ROM_UpdateUSB(0);
	
    while(1)
    {
    }
}

  • I don't have experience with the USB bootloader, but I did successfully run the DK-TM4C129X development board demo "boot_demo_usb" .(C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\dk-tm4c129x\boot_demo_usb)

    In the file "boot_demo_usb.c" they switched to the DFU bootloader with this code:

        //
        // Terminate the USB device and detach from the bus.
        //
        USBDCDTerm(0);
    
        //
        // Disable all interrupts.
        //
        ROM_IntMasterDisable();
    
        //
        // Disable SysTick and its interrupt.
        //
        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;
        HWREG(NVIC_DIS4) = 0xffffffff;
    
        //
        // Enable and reset the USB peripheral.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);
        ROM_USBClockEnable(USB0_BASE, 4, USB_CLOCK_INTERNAL);
    
        //
        // Wait for about a second.
        //
        ROM_SysCtlDelay(ui32SysClock / 3);
    
        //
        // Re-enable interrupts at the NVIC level.
        //
        ROM_IntMasterEnable();
    
        //
        // Call the USB boot loader.
        //
        ROM_UpdateUSB(0);
    
        //
        // Should never get here, but just in case.
        //
        while(1)
        {
        }
    

  • Hi Bob,

    I did a compare with the code you posted and detected a difference in one of the function call parameters.

    In your code listing you have ROM_USBClockEnable(USB0_BASE, 4, USB_CLOCK_INTERNAL) whereas in my code I have ROM_USBClockEnable(USB0_BASE, 8, USB_CLOCK_INTERNAL). The middle parameter represents the division value from the CPU clock down to the USB required clock speed of 60MHz.

    When looking at the user guide for the TivaWare Peripheral Driver Library (using version 2.1.4.178 on page 613) they show this example:

    When the USB_CLOCK_INTERNAL is specified, the ui32Div value must be set so that
    the PLL_VCO/ui32Div results in a 60-MHz clock.
    
    Example: Enable the USB clock with a 480-MHz PLL setting.
    //
    // Enable the USB clock using a 480-MHz PLL.
    // (480-MHz/8 = 60-MHz)
    //
    USBClockEnable(USB0_BASE, 8, USB_CLOCK_INTERNAL);

    In my code, I am using the 480MHz PLL setting and therefore used the divide by 8 value.

    Just to see what would happen, I changed my code to the divide by 4 as in your example, and now it is working.

    Do you know why the change of the divider from 8 to 4? Does this have something to do with SysCtlClockFreqSet clock setting code modification?

    Thanks,
    Alan

  • Yes, it makes sense to me know. There is an issue that was discovered which is listed in the errata documents as SYS#22. The issue is that the PLL clock divider sometimes (rarely) is stuck at divide by 2 and ignores being set to divide by 4. The solution implemented in TivaWare 2.1.4.178 was to modify the SysCtlClockFreqSet() function to use a 240MHz VCO and divide by 2 for 120MHz instead of 480MHz VCO and divide by 4 even though the option SYSCTL_CFG_VCO_480 was chosen. Clearly we missed updating the example on page 613.
  • Hi Bob,

    Thanks for your response. Now starting to make sense for me also.

    Can I now use:

    //
    // Tell the USB library the CPU clock and the PLL frequency.  This is a
    // new requirement for TM4C129 devices.
    //
    SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &ui32PLLRate);
    USBDCDFeatureSet(0, USBLIB_FEATURE_CPUCLK, &SysClock);
    USBDCDFeatureSet(0, USBLIB_FEATURE_USBPLL, &ui32PLLRate);

    rather than even use

    MAP_USBClockEnable(USB0_BASE, 4, USB_CLOCK_INTERNAL);

    since they both seem to be doing the same thing?

    Or would it be okay to just use USBClockEnable call with the divisor now set to 4 whenever setting USB clock and no need for the new requirement for TM4C129 devices as listed above?

    Thanks,
    Alan

  • Yes, now that we know what is going on, I think the first solution is preferred.