J'ai acquis il y a quelques temps une carte de développement STM32 "BluePill" intégrant un STM32F103C8T6. Elle coûte environ 2$ et embarque un microcontrôleur tournant à 72MHz. Vous trouverez plus de détail sur cette carte sur le wiki de STM32Duino.

Pour le développement embarqué, il est pratique d'avoir une sortie série sur sa carte pour debugger plus facilement. On peut utiliser pour cela un port série du microcontrôleur et dialoguer avec l'ordinateur au travers d'un convertisseur USB-Série. Mais il est également possible d'utiliser directement le debugger comme interface pour obtenir cette trace. J'utilise personnellement cette dernière solution quand elle est disponible car cela ne nécessite pas de matériel supplémentaire.

La trace que j'ai implémenté possède les caractéristiques suivantes :

  • trace ITM utilisant la pin SWO
  • support de commandes type printf()

Une trace ITM ne nécessite pas d'intervention du debugger, au contraire d'un trace Semihosting qui est très intrusive. Elle est cependant plus lente.

Software embarqué

La partie logiciel permettant de faire fonctionner la trace vient du projet µOS++. Je n'ai fait que récupérer les sources pour les utiliser. Vous trouverez les trois fichiers sources nécessaires en annexe de ce billet (trace_impl.c, Trace.h et Trace.c).

Les préambule de compilation suivants sont nécessaires pour faire fonctionner la trace et la configurer pour le bon mode :

#define TRACE
#define OS_USE_TRACE_ITM
#define \\__ARM_ARCH_7M\\__

Il vous suffit ensuite d'utiliser les fonctions qui sont définies dans le fichier Trace.h :

  • trace_printf(const char* format, ...) dont le fonctionnement est analogue à la fonction printf() standard
  • trace_puts(const char *s) pour afficher une chaîne de caractère seule
  • trace_putchar(int c) pour afficher un caractère seul


Debugger

Pour tous les debugger, il est nécessaire de connecter la pin SWO du microcontrôleur à celle du debugger. Pour le STM32F103C8T6, il s'agit de la pin PB3.

J-Link

Sous Eclipse ou sous System Workbench pour STM32, la trace est facilement utilisable. Il suffit d'installer et d'utiliser le plug-in J-Link de ARM MCU Eclipse, puis de cocher la case "Enable SWO" dans les options du debugger. N'oubliez pas de renseigner la fréquence de fonctionnement du CPU et de la trace (2MHz pour la BluePill). Dans le cas contraire, la trace fonctionnera seulement lors d'un debug avec flash du programme et non lors d'un "attach to runing target".

Vous vous retrouvez ainsi avec une trace intégrée à Eclipse avec une console dédiée.

Je n'ai pas essayer de faire fonctionner la trace avec le J-Link et avec OpenOCD. Mais je présume que les informations indiquées dans la section "Trace avec OpenOCD" sont valables.

ST-Link

La trace avec le ST-Link peut être visualisée à l'aide du logiciel ST-Link Utility. L'inconvénient est qu'il n'est pas possible de debugger la carte tout en utilisant ce logiciel.

Tous les environnements de développement que j'ai utilisé pour le STM32 repose sur l'utilisation de OpenOCD pour faire fonctionner le debugger ST-Link. Vous pouvez donc suivre les indications de la section "Trace avec OpenOCD" pour avoir une trace tout en debuggant.

ST-Link Clone

Les clones du ST-Link n'ont pas de pin SWO par defaut. Il convient donc de modifier le clone pour ajouter cette fonctionnalité. Les indications peuvent être trouvées sur le billet suivante : Ajouter une fonctionnalité de trace aux clones du ST-Link.

Pour l'utilisation de la trace, toutes les indications données dans la sous-section ST-Link s'appliquent aux clones du ST-Link.


Trace avec OpenOCD

OpenOCD permet d'utiliser la trace sur les STM32 au moyen de la commande tpiu config. Il suffit donc de l'ajouter avec les bons paramètres dans votre fichier de configuration OpenOCD. Dans mon cas, voici le résultat :

tpiu config internal /home/user/Documents/traceswo.log uart off 72000000 2000000

Et l'explication de cette commande :

  • internal /home/user/Documents/traceswo.log : la trace est enregistrée dans le fichier local traceswo.log.
  • uart : utilisation de l'encodage UART 8N1.
  • off : désactivation du formatteur. J'avoue ne pas savoir de quoi il retourne mais la documentation indique de l'activer seulement si la trace est utilisé à la fois en ITM et ETM. Ce qui n'est pas mon cas.
  • 72000000 : fréquence d'horloge du microcontrôleur embarqué sur ma carte.
  • 2000000 : fréquence de la trace.

Pour plus d'information sur l'utilisation de cette commande OpenOCD, vous pouvez vous référer à la documentation. J'ai également ajouter à ce billet de blog mon fichier de configuration OpenOCD sous le nom de sparkcore.cfg.

Si vous essayer de lire le contenu du fichier généré par la trace OpenOCD, vous allez vite vous rendre compte que le contenu est illisible à cause des codes ASCII de fin de transmission ajoutés après chaque caractère. Heureusement j'ai trouvé un petit logiciel qui a été écrit pour filtrer tout ça et avoir une trace lisible :ARM SWO trace data listener/parser (linux et OSX seulement). Une fois compilé, vous avez plus qu'à lancer le programme depuis une console avec comme paramètre le fichier dans lequel OpenOCD enregistre la trace. Et l'option -t permet de voir seulement les nouvelles données avec un mode suivit, parfait pour debugger en direct !