Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
Toggle table of contents sidebar

# Device Firmware Upgrade (DFU) over USB

The DFU implementation in `lib_xua` is compliant with version 1.1 of Universal Serial Bus Device Class Specification for Device Firmware Upgrade.

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`.

For further details of DFU the API and the implementation, please see * lib_dfu (https://www.xmos.com/libraries/lib_dfu) documentation.

## Enumerating as a WinUSB device on Windows

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.