Blue Pill - SWO
Table des matières
TL;DR
Utiliser la PIN PB3 pour le debug (Serial Wire Output).
Le matériel
Au choix:
- un "vrai" adaptateur st-link v2
- la version 3
- le st-link intégré d'une carte NUCLEO (mon cas)
- un clone st-link V2 modifié (rechercher "st-link clone swo", inaccessible vu mon niveau de soudure)
Le branchement
Dans mon cas, le connecteur CN4 de la NUCLEO ne fournit pas d'alimentation, je branche la Blue Pill en 5V à l'aide du connecteur CN8:
Connecteur | Pin | Blue Pill |
CN4 | 2 | PA14 |
CN4 | 4 | PA13 |
CN4 | 6 | PB3 |
CN8 | GND | GND |
CN8 | 5V | 5V |
La contrainte
Il faut passer les commandes suivantes à "openocd":
tpiu config internal /tmp/swo.out uart off 8000000
itm ports on
où
- /tmp/swo.out est le nom du fichier de log
- 8000000 correspond à SystemCoreClock
Les commandes suivantes arrêtent le debug:
tpiu config disable
itm ports off
Le tout est intégré au Makefile:
make swo_on SWO_SPEED=72000000
make swo_off
Edit 2024-05-24
La syntaxe a évolué et il faut désormais utiliser:
swo_off:
@echo 'stm32f1x.tpiu disable' | nc -N 127.0.0.1 4444
@echo 'itm ports off' | nc -N 127.0.0.1 4444
swo_on:
@echo 'stm32f1x.tpiu configure -protocol uart -traceclk $(SWO_SPEED) -output /tmp/swo.out' | nc -N 127.0.0.1 4444
@echo 'stm32f1x.tpiu enable' | nc -N 127.0.0.1 4444
@echo 'itm ports on' | nc -N 127.0.0.1 4444
Les avantages
Le gros du boulot se trouve dans le fichier STM32-base-STM32Cube-master/CMSIS/ARM/inc/core_cm3.h qui fournit une fonction ITM_SendChar(uint32_t ch). Il ne reste plus qu'à faire un copier/coller/remplacer de goret pour obtenir depuis usart.{h,c} une déclinaison swo.{h,c} fournissant les fonctions:
- void swo_init(void)
- void swo_puts(const char * const buf)
- void swo_printf(const char * const fmt, ...)
La configuration est réduite au minimum:
- activer le GPIO B et l'Alternate Function
- passer la PIN 3 en sortie à 2 MHz (O02_AF_PP)
C'est tout ! Une fois le code chargé et les commandes passées à "openocd", le fichier /tmp/swo.out" est créé:
$ tail -f /tmp/swo.out
Hello world !
Hello world !
Hello world !
Hello world !
...
Le fichier n'est pas exactement du texte ("cat -vte" ou "xxd" pour voir que chaque caractère est précédé de 0x01) mais c'est bien suffisant pour du debug. Plus besoin d'adaptateur usb/série !
Le code complet: https://gitlab.com/dsx/blue-pill/-/tree/master/stm32f103c8t6/03_swo
Ce qui peut ne pas plaire
On voit bien que la seule différence entre USART et SWO est la fonction d'envoi de caractère: usart_putc d'un côté et ITM_SendChar de l'autre. Je pourrais faire
#ifdef USE_DBG_SWO
#define DBG_SEND_CHAR ITM_SendChar
#endif
#ifdef USE_DBG_USART
#define DBG_SEND_CHAR usart_putc
#endif
et tout regrouper dans 2 fonctions dbg_puts et dbg_printf mais il ne faut pas oublier que l'USART nécessite beaucoup plus de configuration (DMA, interruption ...).
A retenir
A condition d'avoir le matériel adéquat (un st-link avec une broche SWO fonctionnelle) on peut ajouter très facilement du debug "à la papa" et faire l'économie d'un adaptateur usb/série.
A lire
Bien qu'il y soit question de Rust, il faut absolument lire http://blog.japaric.io/itm/ (anglais).