• No results found

Although USB Device Firmware Upgrade functionality is provided primarily by the USB boot loader (boot_usb), applications which want to support DFU funcionality should publicize this in their configuration descriptor and be able to receive a request from the host indicating that they should switch into DFU mode to receive an upgrade.

The DFU device class supports this runtime DFU capability, providing a simple method for an application to indicate to the host that it is DFU-capable and to be signalled that a USB-based firmware upgrade is being requested. The device class is unusual in that it must be used as part of a composite device. Runtime DFU capability makes no sense on its own since it is basically only an indication that the DFU USB boot loader is present and usable.

The USB boot loader must also be used by any device supporting the DFU runtime device class since it implements all DFU mode operation and performs the actual upgrade operation. The run- time device class adds two sections to the configuration descriptor for the main application - a DFU Interface Descriptor and a DFU Functional Descriptor. Standard DFU DETACH requests sent to the DFU interface from the host result in a callback being made to the client application indicating that it must transfer control back to the USB boot loader (via theUSBDDFUUpdateBegin()function. This function removes the application’s existing device from the USB bus then reenters the boot loader which, in turn, publishes DFU mode descriptors and reconnects to the bus as a pure DFU device capable of downloading or uploading application images from the host.

2.11.1

Using the DFU Device Class

Theboot_demo_usbapplication provides an example of an application using the Device Firmware Upgrade class. To support DFU in your application, do the following:

1. Ensure that your application is built to run alongside the USB boot loader (boot_usb). This requires that it is linked to run from the address defined in label APP_START_ADDRESS

defined in thebl_config.hused to build the boot loader. Typically, for the USB boot loader, this is 0x1800.

2. Add a function to your application following the prototype:

uint32_t DFUDetachCallback(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgData, void *pvMsgData)

This function need only check ui32Event and, if it is USBD_DFU_EVENT_DETACH, signal the application main loop that it should exit and pass control back to the USB boot loader in preparation for a firmware upgrade.

3. Add a mechanism in your application main loop to detect the signal set in your DFUDetach- Callback function and call theUSBDDFUUpdateBegin()function. This function tidies up and passes control to the boot loader.

4. Define a structure of type tDFUInstance, ensuring that the linker places it in SRAM. This is used as workspace by the DFU class driver.

5. Define a structure of typetUSBDFUDeviceand initialize it to contain a pointer to your callback function and instance data workspace.

//***************************************************************************** //

// The DFU runtime interface initialization and customization structures //

//***************************************************************************** const tUSBDDFUDevice g_sDFUDevice =

{

DFUDetachCallback, (void *)&g_sDFUDevice };

6. Create an array of structures of typetCompositeEntrywhich define the individual device class instances that are to be used in the composite device. A structure defining a composite device containing a HID interface and the DFU runtime interface would look like the following:

//**************************************************************************** //

// The number of device class instances that this composite device uses. //

//**************************************************************************** #define NUM_DEVICES 2

//**************************************************************************** //

// The array of devices supported by this composite device. //

//**************************************************************************** tCompositeEntry g_psCompDevices[NUM_DEVICES];

7. Define the additional structures and storage required by the composite device class. For the HID/DFU device described above, this would look like:

//**************************************************************************** //

// Allocate the Device Data for the top level composite device class. // //**************************************************************************** tUSBDCompositeDevice g_sCompDevice = { // // TI USBLib VID. // USB_VID_TI_1CBE, //

// USB_PID_COMP_HID_DFU, // // This is in milliamps. // 500, //

// Bus powered device. //

USB_CONF_ATTR_BUS_PWR,

//

// Device event handler function pointer (receives connect, disconnect // and other device-level notifications).

//

DeviceHandler,

//

// The string table. This is the string table for the main device (no DFU // strings are required).

//

g_pStringDescriptors, NUM_STRING_DESCRIPTORS,

//

// The Composite device array. // NUM_DEVICES, g_psCompDevices }; //**************************************************************************** //

// A buffer into which the composite device can write the combined config // descriptor.

//

//**************************************************************************** uint8_t g_pui8cDescriptorBuffer[COMPOSITE_DDFU_SIZE + COMPOSITE_DHID_SIZE];

8. Rework the USB library initialization function calls to use the composite device. Again, follow- ing the HID/DFU example:

//

// Initialize each of the device instances that forms our composite // USB device.

//

pvMouseDevice =

USBDHIDMouseCompositeInit(0, &g_sMouseDevice, &g_psCompDevices[0]); pvDFUDevice =

USBDDFUCompositeInit(0, &g_sDFUDevice, &g_psCompDevices[1]);

//

// Pass the USB library our device information, initialize the USB // controller and connect the device to the bus.

//

USBDCompositeInit(0, &g_sCompDevice, DESCRIPTOR_BUFFER_SIZE, g_pcDescriptorBuffer);

2.11.2

Windows Drivers for DFU Devices

Since DFU presents itself as another interface on the USB device, a device driver is required even though the interface is essentially static and does nothing other than listen for a single request while in runtime mode. No version of Microsoft Windows includes a generic Device Firmware Upgrade driver so any application supporting DFU must provide a suitable driver. For USBLib applications, a DFU driver is provided in theSW-USB-windrivers-xxxxpackage which may be downloaded via a link fromhttp://www.ti.com/tivaware.

The DFU driver is common between the USB boot loader (boot_usb) and the runtime DFU in- terface provided by the DFU device class. It consists of two USBLib-specific DLLs along with the Microsoft-supplied co-installers for the WinUSB subsystem. Support is provided for WindowsXP, Windows Vista and Windows7 in both 32 bit and 64 bit flavors. The two DLLs are:

lmusbdll.dll A low level interface above WinUSB which provides simple packet transmission and reception and the ability to perform a control transaction on endpoint 0. Applications may be built using this interface without the need to download and install the Windows Device Driver Kit. The DLL itself requires the Windows DDK to build since WinUSB headers are not provided in the Windows SDK.

lmdfu.dll A high level API above the DFU function. This DLL allows DFU-capable devices to be found on the bus and application images to be downloaded to or uploaded from those devices. To create a driver for your DFU-enabled device, either create a new .INF file from the

boot_usb.infexample, substituting your device’s VID, PID and DFU interface number for those in the original file or merge the content of this .inf (with the same changes) into a combined .inf for your composite device.

Note that the device publishs PID 0x00FF when in DFU mode so you must ensure that your driver .INF file contains an entry to install the driver for devices publishing this PID in addition to your composite device’s standard PID.

2.11.3

Programming DFU Devices

The firmware on a DFU-capable USB device may be updated using either the LM Flash Program- mer application or the command line dfuprogtool. Source code fordfuprogis included in the releases for all USB-enabled kits and can be found in C:\ti\TivaWare-for-C-Series\tools\dfuprog assuming you installed TivaWare in the default location. The executable for the application is in- stalled as part of the “Windows-side examples for USB kits” package (SW-USB-win-xxxx) which can be downloaded via a link onhttp://www.ti.com/tivaware. By default, dfuprog.exe

can be found in C:\Program Files\Texas Instruments\TivaWare\usb_examples.

LM Flash Programmer only lists connected DFU devices which are in DFU mode but thedfuprog

tool also allows runtime DFU devices to be enumerated and switched into DFU mode ready for programming using either LM Flash Programmer or another call todfuprog. The command

dfuprog -e

enumerates all DFU-capable devices attached to the host system and provide information on each. To switch a device from runtime mode to DFU mode, issue the command

where<index>is the index of the device (as displayed duringdfuprog -e) whose mode is to be switched.

When a device is switched from runtime mode to DFU mode, you will hear Windows’ usual indi- cation that a USB device has been disconnected followed immediately by a reconnection as the boot loader starts and publishes is DFU mode descriptors to the host. These descriptors use PID 0x00FF rather than the PID published by the composite device as suggested in the USB DFU speci- fication. Once this mode switch has taken place, the device will be visible in LM Flash Programmer’s device list shown when “Manual Configuration” is chosen along with the “USB DFU” interface. If LMFlash was running when the mode switch took place, press the “Refresh” button to search for and display the DFU device.

To program a device in DFU mode, either use LM Flash Programmer’s GUI or dfuprog -f

<filename>.

2.12

Device Firmware Upgrade Device Class Driver Defini-