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:
Mon Aug 29 01:30:30 2016 +0000
Revision:
5:88b6ced3df89
Parent:
4:00ccc80cbeb8
Child:
6:2f7ee2af27f9
Add initial USB DFU blinky example

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 5:88b6ced3df89 16 */
hudakz 0:0279e8c1f111 17
hudakz 0:0279e8c1f111 18 DigitalOut myled(LED1);
hudakz 0:0279e8c1f111 19
devanlai 5:88b6ced3df89 20 bool detached = false;
devanlai 5:88b6ced3df89 21 void onDetachRequested() {
devanlai 5:88b6ced3df89 22 detached = true;
devanlai 5:88b6ced3df89 23 }
devanlai 5:88b6ced3df89 24
devanlai 5:88b6ced3df89 25 void resetIntoBootloader() {
devanlai 5:88b6ced3df89 26 // Turn on write access to the backup registers
devanlai 5:88b6ced3df89 27 __PWR_CLK_ENABLE();
devanlai 5:88b6ced3df89 28 HAL_PWR_EnableBkUpAccess();
devanlai 5:88b6ced3df89 29
devanlai 5:88b6ced3df89 30 // Write the magic value to force the bootloader to run
devanlai 5:88b6ced3df89 31 BKP->DR2 = 0x544F;
devanlai 5:88b6ced3df89 32 BKP->DR1 = 0x4F42;
devanlai 5:88b6ced3df89 33
devanlai 5:88b6ced3df89 34 HAL_PWR_DisableBkUpAccess();
devanlai 5:88b6ced3df89 35
devanlai 5:88b6ced3df89 36 // Reset and let the bootloader run
devanlai 5:88b6ced3df89 37 NVIC_SystemReset();
devanlai 5:88b6ced3df89 38 }
devanlai 5:88b6ced3df89 39
hudakz 0:0279e8c1f111 40 int main() {
hudakz 3:dd01afd4f893 41 confSysClock(); //Configure system clock (72MHz HSE clock, 48MHz USB clock)
hudakz 4:00ccc80cbeb8 42
devanlai 5:88b6ced3df89 43 USBDFU usbDFU(0x1234, 0x0006, 0x0001, false);
devanlai 5:88b6ced3df89 44 usbDFU.attach(onDetachRequested);
hudakz 0:0279e8c1f111 45
hudakz 0:0279e8c1f111 46 while(1) {
devanlai 5:88b6ced3df89 47 // Check the DFU status
devanlai 5:88b6ced3df89 48 if (!usbDFU.configured()) {
devanlai 5:88b6ced3df89 49 usbDFU.connect(false);
devanlai 5:88b6ced3df89 50 }
devanlai 5:88b6ced3df89 51 if (detached) {
devanlai 5:88b6ced3df89 52 for (int i=0; i < 5; i++) {
devanlai 5:88b6ced3df89 53 myled = 1;
devanlai 5:88b6ced3df89 54 wait_ms(100);
devanlai 5:88b6ced3df89 55 myled = 0;
devanlai 5:88b6ced3df89 56 wait_ms(100);
devanlai 5:88b6ced3df89 57 }
devanlai 5:88b6ced3df89 58 resetIntoBootloader();
devanlai 5:88b6ced3df89 59 }
devanlai 5:88b6ced3df89 60
devanlai 5:88b6ced3df89 61 // Do normal stuff
hudakz 0:0279e8c1f111 62 myled = !myled;
hudakz 0:0279e8c1f111 63 wait_ms(1000);
hudakz 0:0279e8c1f111 64 }
hudakz 0:0279e8c1f111 65 }
hudakz 0:0279e8c1f111 66