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.
We have implemented USB DFU bootloader support on an 80MHz TMS320F28069 using the boot_loader code from controlSUITE (f2806x\v141\MWare\boot_loader\) and communicate to it with unmodified dfuprog (f2006x\v141\MWare\tools\dfuprog\).
Most of the time this works perfectly. However, about 20% of the time, dfuprog reports that it cannot find the target device.
For some host PCs, the behavior is even worse - suggesting that this is possibly related to a subtle timing issue.
I have traced the failure and found it consistently occurs when the bootloader returns a NAK in response to the DATA IN phase of a DFU_GETSTATUS command.
The two attached USB packet captures show the successful and failure cases:
In DFU_Good.pdf, transfer 1232 is a successful DFU_GET_STATUS, transfer 1233 is a successful DFU_REQUEST_TI command, and transfer 1234 is a successful DFU_DOWNLOAD.
In DFU_Fail.pdf, transfer 2017 is a NAK'd DFU_GET_STATUS, and 2018 is a NAK'd DFU_REQUEST_TI command. The operation aborts at this point.
These transfers are performed by the TIDFUDeviceOpen() function in tidfu.cpp. I've attached the relevant code snippet.
The code does not check the return status of DFUMakeDeviceIdle() or CheckForTIProtocol(), and I see no code to perform a retry on NAK.
I have confirmed that this implementation is the same in the latest version (V151) in controlSUITE 3.3.9
Is this a known issue? Any recommended fix? Any thoughts as to why the boot_loader code responds with NAK some of the time?
By the way, all F28069 code is built with CCS 6.1.1. dfuprog is built with VS2013.
Update 20160404:
Based on additional USB traces, it appears the problem may occur when DFU_GETSTATUS is the first command sent to the bootloader following the USB SOF packet).
Bill
Bill,
Try this... In bl_usb.c in the boot_loader project, please USB0DeviceIntHandler with this implementation.
__interrupt void
USB0DeviceIntHandler(void)
{
unsigned long ulTxStatus = 0UL, ulGenStatus = 0UL;
uint16_t usbis = 0U, txis = 0U;
//
// Get the current full USB interrupt status.
//
//
// Do-While to make sure that all status registers are cleared before continuing.
// This eliminates the race condition which can cause the USB interrupt to stay high
// and never get triggered again.
//
do
{
// Get the transmit interrupt status.
txis = HWREGH(USB0_BASE + USB_O_TXIS);
// Get the general interrupt status.
usbis = (uint16_t)HWREGB(USB0_BASE + USB_O_IS);
ulTxStatus |= txis;
ulGenStatus |= usbis;
}
while((txis != 0x0000U) || (usbis != 0x0000U));
//
// Received a reset from the host.
//
if(ulGenStatus & USB_IS_RESET)
{
USBDeviceEnumResetHandler();
}
//
// USB device was disconnected.
//
if(ulGenStatus & USB_IS_DISCON)
{
HandleDisconnect();
}
//
// Handle end point 0 interrupts.
//
if(ulTxStatus & USB_TXIE_EP0)
{
USBDeviceEnumHandler();
}
PieCtrlRegs.PIEACK.all |= 0x10;
}
sal
Sal,
This did not help - behavior is the same as the unmodified code. However, It allowed me to discover a clue that suggests our application code is, in some way inducing or at least exacerbating the problem.
While testing this change , I found the following repeatable scenario:
1. Use Uniflash to download the updated bootloader binary to the board, erasing entire flash
2. Cycle power on the board - it comes up in the bootloader since no application is present
3. Use dfuprog to connect to the bootloader and successfully enumerate the board, erase application flash, and download the application!
4. Cycle power on the board - The bootloader jumps to the newly downloaded application and runs fine
5. Instruct the application to enter the bootloader by jumping to AppUpaterUSB() in bl_usb.c
6. The UpdaterUSB() function runs, and enters its while loop waiting for a USB command
7. Use dfu prog -e to connect to the bootloader - and encounter the intermittent problem with DFUDeviceStatusGet() when trying to enumerate.
I repeated steps 1-7 multiple times. step 3 never fails. Step 7 fails with the frequency I've described previously. When step 7 succeeds, I am also able to erase flash and reprogram the application successfully.
In the application firmware, prior to branching to AppUpdaterUSB(), I call USBCDCTerm() on the USB port, and stop my periodic systick timer, which is the only active interrupt source at the time. Windows correctly detects the transition, uninstalls the CDC driver and installs the DFU driver.
Can you think of any additional initialization that I should be performing prior to branching to AppUpdaterUSB()?
Bill
PS, I should also note that we are building dfuprog with it's own local copies of tidfu.dll and tiusb.dll, all built from the same controlSuite release. We are not relying on the copies installed with the device driver. In fact, my goal is to add the microsoft winusb descriptors to the bootloader configuration so no driver inf is required at all.