This section describes the DFU implementation in lib_xua, which is supported by lib_dfu.
For information about using a DFU loader to send DFU commands to the USB Audio device, refer to appnote
AN02019: Using Device Firmware Upgrade (DFU) in USB Audio.
The USB device descriptors expose a DFU interface that handles updates to the boot image of the device over USB.
The host sends DFU requests as Host to Device Class requests to the DFU interface.
On receiving DFU commands from the host, the dfu_usb_class_int_requests function is called from the Endpoint 0 thread.
This function calls the DFU handler functions over the dfuInterface XC interface.
The DFU handler thread, DFUHandler that implements the server side of the dfuInterface has to be
scheduled on the same tile as the flash so it can access the flash memory.
The dfuInterface interface essentially links USB to the
XMOS flash user library.
The DFU interface is enabled by default (See XUA_DFU_EN define in xua_conf_default.h).
When DFU is enabled, there are two sets of descriptors that the device can export, depending on the mode in which it operates.
There is a descriptor set for the runtime mode, which is the mode the device normally operates in and a set of descriptors for the DFU mode.
In the runtime mode, the DFU interface is one of potentially multiple interfaces that the device exposes.
Fig. 9 shows the DFU interface
descriptors when enumerating in runtime mode as seen in a Beagle USB analyser trace.
Fig. 9 DFU interface when part of runtime mode descriptor set¶
Note the bInterfaceProtocol field set to Runtime.
In DFU mode, the device exports the DFU descriptor set. The DFU mode descriptors specify only one interface, the DFU interface.
Fig. 10 shows the DFU interface
descriptors when enumerating in DFU mode as seen in a Beagle USB analyser trace.
Fig. 10 DFU interface when part of DFU mode descriptor set¶
Note the bInterfaceProtocol field set to DFU mode.
Before starting the DFU upload or download process, the host sends a DFU_DETACH command to detach the device from runtime to DFU mode.
In response to the DFU_DETACH command, the device reboots itself into DFU mode and enumerates using the DFU mode descriptors.
Once the device is in DFU mode, the DFU interface can accept commands defined by the
DFU 1.1 class specification.
After detaching the device, the host proceeds with the DFU download/upload commands to write/read the firmware upgrade image to/from the device.
Once the DFU download or upload process is complete, the host sends a DETACH command, and the device reboots itself back in runtime mode.
Note
It is recommended that the runtime mode and DFU mode descriptors have different product IDs. This is to ensure that the host operating
system loads the correct driver as the device switches between runtime and DFU modes. The runtime and DFU PID are defined as overridable
defines PID_AUDIO_2 and DFU_PID respectively in xua_conf_default.h. Users can define custom PIDs in their application by overriding these defines.
During the DFU download process, on receiving the first DFU_DNLOAD command (wBlockNum = 0), the device erases
FLASH_MAX_UPGRADE_SIZE bytes of the upgrade section of the flash. This is done by repeatedly calling the function to erase a flash sector until the entire upgrade section is erased.
and can take several seconds. To avoid the DFU_DNLOAD request timing out, the flash erase is instead done in the DFU_GETSTATUS handling
code for block 0. So for block 0, the device ends up returning the status as dfuDNBUSY several times while the flash
erase is in progress. Fig. 11 describes the DFU download process.
Fig. 11 Message sequence chart for the DFU download operation¶
Note
Once a valid upgrade image is loaded in flash, on subsequent reboots, the device will boot from the upgrade image.
If the upgrade image is invalid e.g. invalid CRC, the factory image will be loaded. To revert back to the factory image,
there is a custom request available XMOS_DFU_REVERTFACTORY.
The Endpoint 0 code supports extra descriptors called the Microsoft Operating System (MSOS) descriptors
that allow the device to enumerate as a WinUSB device on Windows.
The MSOS descriptors report the compatible ID as WINUSB which enables Windows to load Winusb.sys as the device’s
function driver without a custom INF file. This means that when the device is connected, the DFU interface
shows up as WinUSB compatible automatically, without requiring the user to manually load a driver for it using a utility like Zadig.
The MSOS descriptors are present in the file xua_ep0_msos_descriptors.c and also in lib_xud in the file simple_ep0_msos_descriptors.c.
In order to enumerate as a device capable of supplying MSOS descriptors, the device’s bcdUSB version in the device descriptor has to be 0x0201.
On seeing the bcdUSB version as 0x0201 when the device enumerates, the host requests for a descriptor called the Binary Device Object Store (BOS) descriptor.
This descriptor contains information about the capability of the device. It specifies the device to be MSOS 2.0 capable and contains information about
the vendor request code (bRequest) and the request length (wLength) that the host needs to use to when making a vendor request to query for the MSOS
descriptor.
The host then makes a vendor request with the bRequest and wLength as specified in the BOS platform descriptor querying for the MSOS descriptor.
Warning
If writing a host application that also sends vendor requests to the device, users should ensure that they do not use the bRequest that is reserved
for the MSOS descriptor. The MSOS descriptor vendor request’s bRequest is defined as the
XUA_REQUEST_GET_MSOS_DESCRIPTOR define in xua_conf_default.h.
#define XUA_REQUEST_GET_MSOS_DESCRIPTOR 0x20
The MSOS descriptor reports the compatible ID as WINUSB for the DFU interface. It also specifies the device interface GUID in its registry property.
The GUID is required to access the DFU interface from a user application running on the host (for example the Thesycon DFU driver or the dfu-util DFU application)
Note
The default device interface GUID for the DFU interfaces is specified in the XUA_WINUSB_DEVICE_INTERFACE_GUID_DFU define in xua_conf_default.h.
Users can override this by redefining XUA_WINUSB_DEVICE_INTERFACE_GUID_DFU in the application. A utility such as guidgenerator can be used for generating a GUID.
Tip
The MSOS descriptors for reporting WinUSB compatibility are only relevant for Windows.