usbdfu : Device Firmware Upgrade par USB

Introduction

usbdfu est un programme pour microprocesseur STM32F103. Il permet la mise à jour, en mémoire flash, d'un programme d'application fonctionnant sur le même processeur par l'intermédiaire de l'interface USB. Le code est extrait du logiciel black magic probe et des exemples de libopencm3 qui sont d'ailleurs du même auteur, donc merci à Gareth.

Quelques modifications minimes ont été nécessaires pour l'adapter aux modules appelés blueplill et maple-mini-clone avec l'objectif de rendre ce programme indépendant d'une autre application.

Ce programme est utile aux développeurs qui ont à charger un certain nombre de fois leur apllication en mémoire flash pour le tester. Un utilisateur final devra toutefois charger son application par la liaison série, du moins pour ce modèle de processeur.

Bootloader DFU (Device firmware update)

Usbdfu est chargé dans les premiers 8 kB de la mémoire flash par la liaison série. Son rôle est de communiquer avec le programme dfu-util, sur le host et de lancer l'application installée.

Dfu-util [2] est un outil qui s'exécute sur la machine de développement et qui communique, par USB, avec une cible qui connait le protocole DFU et, dans notre cas, le bootloader usbdfu, le but étant de télécharger le code d'une application en mémoire flash.

Au démarrage du processeur, c'est usbdfu qui est exécuté. Il regarde si une application est présente et lit la valeur du port BOOT1. Si BOOT1 est à 1, il lance l'application, si BOOT1 est à 0 ou si il ne trouve pas d'application, il se met en mode bootloader.

Fonctionnement vu du coté machine de développement

Du coté machine de développement, on souhaite exécuter l'application en cours de développement et de s'y connecter par la liaison série ou USB. Puis lorsque une modification est nécessaire, le source est modifié, puis compilé, en général, une commande make suffit. Puis le nouveau programme doit être transféré sur le processeur, pour cela une commande make flash gère le transfert. Mais cela ne se fait tout seul, une certaine préparation est nécessaire.

  1. dfu-util demande à l'application de faire un reset un peu spécial, ce qui implique que l'application ait un bout de code pour répondre à dfu-util.
  2. le reset consiste à activer une résistance de pull down dans le micro qui met BOOT1 à 0 et d'activer un scb_reset_core().
  3. usbdfu prend le relai, voit BOOT1 à 0 et reste en mode bootloader.
  4. dfu-util charge le programme.
  5. usbdfu fait un scb_reset_system().
  6. usbdfu voit BOOT1 à 1 et lance l'application.

Sur certaines cartes, il peut être nécessaire de rajouter une résistance de pull up afin que usbdfu lise 1 sur BOOT1. Cette resistance existe sur bluepill si on met le strap boot1 à 1, mais n'existe pas sur maple-mini-clone, une valeur de 100 k fait l'affaire.

Utilisation de dfu-util

Pour atteindre le mode Bootloader Usb, il faut, après avoir brancher le cable mini-usb ou micro-usb:

La commande lsub laisse apparaitre la ligne suivante, ce qui montre que usbdfu est reconnu:

...
Bus 004 Device 004: ID 1d50:6017 OpenMoko, Inc. Black Magic Debug Probe (DFU)
...

On peut alors lister les interfaces disponibles

sudo dfu-util -l

et voici la liste:


sudo dfu-util -l
$ dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 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/

Found DFU: [1d50:6017] ver=0100, devnum=38, cfg=1, intf=0, path="8-1", alt=0, name="@Internal Flash   /0x08000000/8*001Ka,120*001Kg", serial="C1DBCB0D"

Sachant que le système peut être dans 2 modes : le mode bootloader et le mode application, les 2 commandes suivantes permettent le choix du mode. Une de ces commandes peut être installée dans le Makefile sous la cible flash et exécutée par la commande make flash

# mode bootloader
$ sudo dfu-util -d 1d50::6017 -s 0x08002000:leave -D mymaple.bin

#mode application
$ sudo dfu-util -d 1d50:6018,:6017 -s 0x08002000:leave -D mymaple.bin

Voici un exemple de chargement du code d'une application à partir du mode application:

$ sudo dfu-util -d 1d50:6018,:6017 -s 0x08002000:leave -D mymaple.bin
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 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 1d50:6017
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 1024
DfuSe interface name: "Internal Flash   "
Downloading to address = 0x08002000, size = 9572
Download	[=========================] 100%         9572 bytes
Download done.
File downloaded successfully
Transitioning to dfuMANIFEST state

Si vous avez déjà une application toute prête, le bootloader usbdfu n'est plus très utile car on peut charger l'application avec stm32flash.

Dépendant de l'application s'exécutant sur le processeur, il est possible de le redémarrer en donnant la main au bootloader (mode detach), sans changer la valeur de BOOT1, en exécutant la commande suivante:

sudo dfu-util -e       # detach

Et avec une petite bidouille (non officielle), on peut redémarrer l'application en restant en mode application à partir du host, utile par exemple si on a connecté /dev/ACM0 à l'usart, en exécutant la commande suivante:

sudo dfu-util -e -E 0

La modification consiste à envoyer une valeur de timeout de wValue = 0xdead dans la requête DFU_DETACH. Pour cela, il faut modifier le fichier src/main.c avant le premier dfu_detach dans la distribution dfu-util et recompiler.

              int value = 1000;
              if ( mode == MODE_DETACH && detach_delay == 0 ){
                    value = 0xdead;
              }
              if (dfu_detach(dfu_root->dev_handle,
                              dfu_root->interface, value) < 0) {

Le démarrage de l'application se fait en connectant Boot1 à un 1 et an appuyant sur reset.

Compiler usbdfu

Usbdfu dépend de la librairie opencm3 [3], qui doit donc être installée au préalable. Après avoir téléchargé les sources de usbdfu, extraire les sources et compiler avec le compilateur précédemment installé:

tar Jxvf usbdfu-20yy.mm.dd.xz
cd usbdfu-20yy.mm.dd
make            # maple-mini-clone

BLUEPILL=1 make # bluepill

La variable BLUEPILL=1 effectue la commutation des différences entre la carte maple-mini-clone et la carte bluepill. Il est aussi possible de modifier le makefile pour éviter cette variable. Il est toujours possible de rajouter d'autres modèles.

On peut noter que usbdfu utilise la mémoire ram du processeur, mais comme usbdfu ne fonctionne pas en même temps que l'application, cette mémoire ram reste entièrement disponible pour l'application.

Références

  1. Open source flash program for STM32 using the ST serial bootloader.
  2. dfu-util - Device Firmware Upgrade Utilities.
  3. libopencm3 - Open Source ARM cortex m microcontroller library.

License

The usbdfu software are licensed under the terms of the GNU General Public License as published by the Free Software Foundation. See the file "COPYING" in the downloaded package.

Download