Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE
Hello,
I am attempting to add functionality to the Blink LED program running in FLASH to allow it to be updated via USB with the usb_flash_programmer.exe. I was following this thread:
The Blink LED program is found at: C:\ti\c2000\C2000Ware_5_00_00_00\device_support\f2837xd\examples\cpu1\blinky
I included the USB BOOT ROM code found at: C:\ti\c2000\C2000Ware_5_00_00_00\libraries\boot_rom\f2837xd\revB\rom_sources
In the beginning of main() in the Blink LED application I added the check to see if GPIO 46 is set or not. If it is set, that means the USB is attached to the PC and to then call USB_Boot(). If not, it will continue to initialize everything and start running the main loop of the program.
Uint32 main(void)
{
uint32_t gpio46_value = GPIO_readPin(46);
if(gpio46_value == 1) //Checking whether USB is connected or not.
{
DevCfgRegs.DC12.bit.USB_A = 1;
Uint32 EntryAddr = USB_Boot(USB_BOOT); //Calling USB_Boot function.
return EntryAddr;
}
//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
InitSysCtrl();
//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
InitGpio();
GPIO_SetupPinMux(BLINKY_LED_GPIO, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(BLINKY_LED_GPIO, GPIO_OUTPUT, GPIO_PUSHPULL);
//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
DINT;
//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
//
InitPieCtrl();
//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
IER = 0x0000;
IFR = 0x0000;
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
InitPieVectTable();
//
// Enable global Interrupts and higher priority real-time debug events:
//
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
//
// Step 6. IDLE loop. Just sit and loop forever (optional):
//
for(;;)
{
//
// Turn on LED
//
GPIO_WritePin(BLINKY_LED_GPIO, 0);
//
// Delay for a bit.
//
DELAY_US(1000*500);
//
// Turn off LED
//
GPIO_WritePin(BLINKY_LED_GPIO, 1);
//
// Delay for a bit.
//
DELAY_US(1000*500);
}
}.
Here is the USB_Boot code from C:\ti\c2000\C2000Ware_5_00_00_00\libraries\boot_rom\f2837xd\revB\rom_sources. I commented out the EntryAddr checks.
Uint32 USB_Boot(Uint16 bootMode)
{
uint32_t entryAddr = FLASH_ENTRY_POINT;
uint32_t EntryAddr = 0xFFFFFFFF;
uint32_t disconnectDelay;
//If the USB module is not enabled, bypass the bootloader
if (DevCfgRegs.DC12.bit.USB_A == 0)
return FLASH_ENTRY_POINT;
//Assign the USB data reader function to the global
//function pointer for loading data.
GetWordData = &USB_GetWordData;
//Set up the USB to receive data
USB_Boot_Init();
/*
EntryAddr = TI_OTP_C1BROM_ESCAPE_POINT_13;
if((EntryAddr != 0xFFFFFFFF) &&
(EntryAddr != 0x00000000))
{
// if OTP is programmed, then call OTP function
((void (*)(void))EntryAddr)();
}
*/
//The first data word should be a valid key. If it's not,
//bypass the bootloader.
if (USB_GetWordData() != 0x08AA)
return FLASH_ENTRY_POINT;
//Use the shared utility functions to load the data.
ReadReservedFn();
entryAddr = GetLongData();
CopyData();
/*
EntryAddr = TI_OTP_C1BROM_ESCAPE_POINT_13;
if((EntryAddr != 0xFFFFFFFF) &&
(EntryAddr != 0x00000000))
{
// if OTP is programmed, then call OTP function
((void (*)(void))EntryAddr)();
}
*/
//Disconnect from the bus, disable USB interrupts, and
//reset the USB module. But first, wait for any ongoing
//transfers to complete.
for (disconnectDelay = 0; disconnectDelay < 10000; disconnectDelay++) {;}
USBREG8(USB_O_POWER) &= ~USB_POWER_SOFTCONN;
EALLOW;
PieCtrlRegs.PIEIER9.bit.INTx15 = 0;
IER &= ~M_INT9;
DevCfgRegs.SOFTPRES11.bit.USB_A = 1;
DevCfgRegs.SOFTPRES11.bit.USB_A = 0;
EDIS;
//Bypass and disable the main and aux PLLs
EALLOW;
ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 0;
ClkCfgRegs.SYSPLLMULT.bit.IMULT = 0;
ClkCfgRegs.SYSPLLCTL1.bit.PLLEN = 0;
ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 0;
ClkCfgRegs.AUXPLLMULT.bit.IMULT = 0;
ClkCfgRegs.AUXPLLCTL1.bit.PLLEN = 0;
EDIS;
/*
EntryAddr = TI_OTP_C1BROM_ESCAPE_POINT_13;
if((EntryAddr != 0xFFFFFFFF) &&
(EntryAddr != 0x00000000))
{
// if OTP is programmed, then call OTP function
((void (*)(void))EntryAddr)();
}
*/
return entryAddr;
}
Here is the USB_Boot_Init() function from C:\ti\c2000\C2000Ware_5_00_00_00\libraries\boot_rom\f2837xd\revB\rom_sources. I also commented out the EntryAddr checks.
void USB_Boot_Init()
{
uint32_t EntryAddr = 0xFFFFFFFF;
//Soprano
//Lock the main PLL< aux PLL and enable the USB module clock
//
//USBCLK = 120 MHz / 2, sourced from the external oscillator for precision
//
//SYSCLK must be greater than USBCLK / 2, according to Design. The PLL minimum
//Fout is 110 MHz, so let's set the multiplier to give 120 MHz and keep the
//output divider at 1.
EALLOW;
ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL = 0x0; //Use INTOSC2 (~10 MHz) as the main PLL clock source
ClkCfgRegs.SYSPLLMULT.all = 12; //Set IMULT to 12, clear FMULT
ClkCfgRegs.SYSPLLCTL1.bit.PLLEN = 1; //Enable the main PLL
ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = 0; //Set PLLSYSCLKDIV to 1
while (ClkCfgRegs.SYSPLLSTS.bit.LOCKS != 1) {;} //Wait for the PLL to lock
ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 1; //Turn off the main PLL bypass
ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 0x1; //Use XTAL (20 MHz) as the aux PLL clock source
ClkCfgRegs.AUXPLLMULT.all = 6; //Set IMULT to 6, clear FMULT - 120MHz
ClkCfgRegs.AUXPLLCTL1.bit.PLLEN = 1; //Enable the aux PLL
ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV = 2/2; //Set AUXPLLDIV to 2
while (ClkCfgRegs.AUXPLLSTS.bit.LOCKS != 1) {;} //Wait for the PLL to lock
ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 1; //Turn off aux PLL bypass
CpuSysRegs.PCLKCR11.bit.USB_A = 1; //Enable the clock to the USB module
/*
EntryAddr = TI_OTP_C1BROM_ESCAPE_POINT_13;
if((EntryAddr != 0xFFFFFFFF) &&
(EntryAddr != 0x00000000))
{
// if OTP is programmed, then call OTP function
((void (*)(void))EntryAddr)();
}
*/
//Connect the PHY to the GPIO pins by setting the GPBAMSEL
//bits for GPIOs 42 and 43. VBUS and ID are now de-spec'd
//due to the lack of a 5V fail-safe ESD structure, so
//GPIOs 46 and 47 are not muxed out.
GpioCtrlRegs.GPBAMSEL.bit.GPIO42 = 1;
GpioCtrlRegs.GPBAMSEL.bit.GPIO43 = 1;
EDIS;
//Register the USB interrupt handler and enable CPU interrupts
c1brom_enable_pie_in_boot(0);
EALLOW;
PieVectTable.USBA_INT = &UsbIntHandler;
PieCtrlRegs.PIEIER9.bit.INTx15 = 1;
EDIS;
IER |= M_INT9;
EINT;
/*
EntryAddr = TI_OTP_C1BROM_ESCAPE_POINT_13;
if((EntryAddr != 0xFFFFFFFF) &&
(EntryAddr != 0x00000000))
{
// if OTP is programmed, then call OTP function
((void (*)(void))EntryAddr)();
}
*/
//Reset the USB driver's global variables
ResetUsbDriver();
//Force USB device mode by setting DEVMODOTG and DEVMOD
USBREG32(USB_O_GPCS) = 0x3;
//Clear active interrupts
USBREG16(USB_O_TXIS);
USBREG16(USB_O_RXIS);
USBREG8(USB_O_IS);
//Set up endpoint 1 for bulk transfers with a 64-byte FIFO
USBREG8(USB_O_EPIDX) = 1;
USBREG8(USB_O_RXFIFOSZ) = 0x03;
USBREG16(USB_O_RXFIFOADD) = 0x100;
USBREG8(USB_O_RXCSRH1) = 0x40;
//Enable USB interrupts for EP0 transmit/receive, EP1 receive, disconnection, and reset
USBREG16(USB_O_TXIE) = 0x0001;
USBREG16(USB_O_RXIE) = 0x0002;
USBREG8(USB_O_IE) = (USB_IE_DISCON | USB_IE_RESET);
//Attach the USB PHY to the bus
USBREG8(USB_O_POWER) |= USB_POWER_SOFTCONN;
}
When I run the program with the USB attached to a PC it is getting stuck on the while loop in the very first USB_GetWordData() call.
//Read 16 bits from an incoming USB message
Uint16 USB_GetWordData()
{
Uint16 retVal;
//Wait for the USB receive buffer to be refilled
while (g_UsbRxBuffer == 0) {;}
//Read the next data value, update the buffer pointer and length,
//and do end-of-packet handling.
retVal = *g_UsbRxBuffer++;
g_UsbRxPacketLength -= 2;
if (g_UsbRxPacketLength == 0)
{
g_UsbRxBuffer = 0;
AckEp1();
}
return retVal;
}
I never see the USB enumerate on the PC in the device manager.
Any thoughts on what I am doing incorrectly?
Anything I can check?
Thanks,
Brent