Blinky example with USB Device Firmware Upgrade (DFU) detach support for use with a no-offset bootloader

Dependencies:   USBDevice_STM32F103 mbed-STM32F103C8T6 mbed

Fork of STM32F103C8T6_USBSerial by Zoltan Hudak

Overview

This is an example application that runs on an STM32F103C8 "bluepill" board using a USB DFU bootloader. Once the bootloader and this application have been uploaded, it blinks just like any other blinky example. However, it also enumerates as a USB DFU runtime device, making it possible to re-enable the bootloader and upload new code over USB.

Installing the bootloader

A pre-built copy of the bootloader can be downloaded from GitHub.

Note that this bootloader primarily lives in the upper 8KiB of flash, so no application offset is needed (and the online compiler doesn't let you set an application offset, anyways).

See Zoltan Hudak's page for an example of using an Nucleo board to program a standalone board.

Uploading programs

Once the bootloader has been flashed, it will enumerate as a USB DFU device. dfu-util can be used to upload new programs to the board over USB. Note that on Windows, you may need to use a program such as Zadig to associate the WinUSB driver with the DFU interface.

You can check if the bootloader was uploaded successfully by seeing if dfu-util can find it using dfu-util -l

dfu-util 0.8

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Cannot open DFU device 0a5c:21e6
Found DFU: [1209:db42] ver=0100, devnum=25, cfg=1, intf=0, alt=0, name="DAPBoot DFU", serial="463112677267505055FF7206"

If you get something like "dfu-util: Cannot open DFU device 1209:db42", you may need to fix your permissions.

You can then upload your code over USB using:

dfu-util -d 1209:db42 -D STM32F103C8T6_USBDFU_NUCLEO_F103RB.bin

If all goes well, you should see something along the lines of

dfu-util 0.8

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 1209:db42
Run-time device DFU version 0110
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 0110
Device returned transfer size 1024
Copying data from PC to DFU device
Download	[=========================] 100%        29716 bytes
Download done.
state(7) = dfuMANIFEST, status(0) = No error condition is present
dfu-util: unable to read DFU status after completion

The board should now blink once per second. If you run "dfu-util -l" again, it should now show the DFU runtime:

Found Runtime: [1234:0006] ver=0001, devnum=26, cfg=1, intf=0, alt=0, name="DFU", serial="0123456789"

Since it has a different USB VID/PID pair than the bootloader, if you ran into any permissions/drivers issues with the bootloader, you will need to solve them again for the application.

You can switch from the application to the back to bootloader by running

dfu-util -d 1234:0006 -e

dfu-util can also handle switching from the application to the bootloader and uploading code in one step:

dfu-util -d 1234:0006,1209:db42 -D your_firmware.bin
Committer:
devanlai
Date:
Fri Nov 25 19:15:08 2016 +0000
Revision:
8:082264cba2e2
Parent:
6:2f7ee2af27f9
Update to new library version with callback fix

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:0279e8c1f111 1 #include "stm32f103c8t6.h"
hudakz 0:0279e8c1f111 2 #include "mbed.h"
devanlai 5:88b6ced3df89 3 #include "USBDFU.h"
devanlai 5:88b6ced3df89 4
devanlai 5:88b6ced3df89 5 /*
devanlai 5:88b6ced3df89 6 * This is an example program demonstrating a USB DFU runtime combined with
devanlai 5:88b6ced3df89 7 * a USB DFU bootloader that does not require an offset.
devanlai 5:88b6ced3df89 8 *
devanlai 5:88b6ced3df89 9 * It normally blinks an LED at 1Hz, but when it receives a DFU detach
devanlai 5:88b6ced3df89 10 * request over USB (eg, by running "dfu-util -d 1234:0006 -e"), it
devanlai 5:88b6ced3df89 11 * blinks 3 times rapidly and resets into the bootloader.
devanlai 5:88b6ced3df89 12 *
devanlai 5:88b6ced3df89 13 * New programs can be uploaded by running
devanlai 5:88b6ced3df89 14 * dfu-util -d 1234:0006,1209:db42 -D your_firmware.bin
devanlai 5:88b6ced3df89 15 *
devanlai 6:2f7ee2af27f9 16 * The companion bootloader source can be found on GitHub:
devanlai 6:2f7ee2af27f9 17 * https://github.com/devanlai/dapboot/tree/highboot
devanlai 6:2f7ee2af27f9 18 *
devanlai 5:88b6ced3df89 19 */
hudakz 0:0279e8c1f111 20
hudakz 0:0279e8c1f111 21 DigitalOut myled(LED1);
hudakz 0:0279e8c1f111 22
devanlai 5:88b6ced3df89 23 bool detached = false;
devanlai 5:88b6ced3df89 24 void onDetachRequested() {
devanlai 5:88b6ced3df89 25 detached = true;
devanlai 5:88b6ced3df89 26 }
devanlai 5:88b6ced3df89 27
devanlai 5:88b6ced3df89 28 void resetIntoBootloader() {
devanlai 5:88b6ced3df89 29 // Turn on write access to the backup registers
devanlai 5:88b6ced3df89 30 __PWR_CLK_ENABLE();
devanlai 5:88b6ced3df89 31 HAL_PWR_EnableBkUpAccess();
devanlai 5:88b6ced3df89 32
devanlai 5:88b6ced3df89 33 // Write the magic value to force the bootloader to run
devanlai 5:88b6ced3df89 34 BKP->DR2 = 0x544F;
devanlai 5:88b6ced3df89 35 BKP->DR1 = 0x4F42;
devanlai 5:88b6ced3df89 36
devanlai 5:88b6ced3df89 37 HAL_PWR_DisableBkUpAccess();
devanlai 5:88b6ced3df89 38
devanlai 5:88b6ced3df89 39 // Reset and let the bootloader run
devanlai 5:88b6ced3df89 40 NVIC_SystemReset();
devanlai 5:88b6ced3df89 41 }
devanlai 5:88b6ced3df89 42
hudakz 0:0279e8c1f111 43 int main() {
hudakz 3:dd01afd4f893 44 confSysClock(); //Configure system clock (72MHz HSE clock, 48MHz USB clock)
hudakz 4:00ccc80cbeb8 45
devanlai 5:88b6ced3df89 46 USBDFU usbDFU(0x1234, 0x0006, 0x0001, false);
devanlai 5:88b6ced3df89 47 usbDFU.attach(onDetachRequested);
hudakz 0:0279e8c1f111 48
hudakz 0:0279e8c1f111 49 while(1) {
devanlai 5:88b6ced3df89 50 // Check the DFU status
devanlai 5:88b6ced3df89 51 if (!usbDFU.configured()) {
devanlai 5:88b6ced3df89 52 usbDFU.connect(false);
devanlai 5:88b6ced3df89 53 }
devanlai 5:88b6ced3df89 54 if (detached) {
devanlai 5:88b6ced3df89 55 for (int i=0; i < 5; i++) {
devanlai 5:88b6ced3df89 56 myled = 1;
devanlai 5:88b6ced3df89 57 wait_ms(100);
devanlai 5:88b6ced3df89 58 myled = 0;
devanlai 5:88b6ced3df89 59 wait_ms(100);
devanlai 5:88b6ced3df89 60 }
devanlai 5:88b6ced3df89 61 resetIntoBootloader();
devanlai 5:88b6ced3df89 62 }
devanlai 5:88b6ced3df89 63
devanlai 5:88b6ced3df89 64 // Do normal stuff
hudakz 0:0279e8c1f111 65 myled = !myled;
hudakz 0:0279e8c1f111 66 wait_ms(1000);
hudakz 0:0279e8c1f111 67 }
hudakz 0:0279e8c1f111 68 }
hudakz 0:0279e8c1f111 69