Dans Hackable 40 [1], nous avons fait connaissance avec la Black Magic Probe, un outil de mise au point faisant fonctionner un serveur GDB et permettant de se passer totalement d'OpenOCD pour contrôler l'exécution d'un code sur un microcontrôleur ARM. Le buzz récent autour du Flipper Zero, un « multi-tool pour geeks », ainsi que quelques connaissances qui se reconnaîtront m'ont fait me pencher sur le « Wi-Fi Debugger Module » de ce périphérique...
Le Flipper Zero [2] semble être un outil vraiment très intéressant, puisqu'il regroupe un grand nombre de fonctionnalités sous la forme d'un petit boîtier équipé d'un écran LCD présentant une interface « rigolote », avec une mascotte de dauphin (d'où le nom). Le Flipper Zero sait faire de la communication sub-GHz (433 MHz principalement), de la RFID 125 kHz, du NFC (+ Mifare Classic inclus), du Bluetooth, de l'infrarouge, du 1-Wire, de l'USB, de l'authentification U2F, etc. Le tout avec un firmware open source [3] s'exécutant sur un microcontrôleur STM32WB55RG (ARM Cortex-M4 + Cortex-M0+) et une communauté qui semble extrêmement active. Et, sans surprise, le produit est absolument indisponible après la campagne de financement participatif sur KickStarter et les livraisons de l'été dernier.
Mais le point qui nous intéresse ici n'est pas tant cet adorable gadget que le module permettant de le programmer et de mettre au point son firmware. Le Flipper Zero ne dispose pas de connectivité Wi-Fi par lui-même, mais les développeurs ont eu l'excellente idée de rendre l'outil de développement, ou plus exactement la sonde SWD/JTAG, compatible avec un réseau sans fil. Ainsi, le Wi-Fi Debugger Module [4] est un circuit qui se connecte sur la tranche du Flipper Zero et offre une solution de flashage et de mise au point. Mais plus intéressant encore, ce circuit repose sur un ESP32 avec un firmware basé sur FreeRTOS où le code de la Black Magic Probe est une application.
À cette date, je n'ai pas de Flipper Zero, faute de m'être réveillé assez tôt sur le sujet. Le module ne m'est donc pas d'une grande utilité en lui-même, mais présente une solution intéressante en guise de système de programmation et de mise au point. Dans l'article précédent sur la Black Magic Probe ou BMP [1], nous avons pu voir comme il était agréable de fusionner un ensemble connecteur SWD + sonde + OpenOCD + GDB en un montage unique faisant fonctionner directement un serveur GDB. Avec une telle configuration, il suffisait de demander au GDB local de se connecter en USB/série au serveur de la BMP pour programmer la flash de la cible, exécuter les codes pas-à-pas ou encore placer des points d'arrêt pour vérifier le contenu de la SRAM, des variables ou des registres.
Le module imaginé par les créateurs du Flipper Zero va plus loin. Il permet non seulement de faire de même via une liaison USB, mais aussi, et surtout à travers le réseau (via Wi-Fi). Plus besoin d'un câble et d'un ordinateur à proximité de la cible, il suffit de brancher le module et de tout faire à distance. Car, oui, cette solution n'est absolument pas spécifique au Flipper Zero et fonctionnera parfaitement pour toutes cibles disposant d'un connecteur SWD (ou Serial Wire Debug en version longue).
Mieux encore, non seulement le schéma du module Flipper Zero est disponible [5], mais il est parfaitement reproductible avec une carte de développement ESP32-S2 comme le Lolin/Wemos S2 Mini [6] qu'on trouvera sans problème sur les sites habituels pour moins de 4 € [7].
1. Le montage
L'ESP32-S2 n'est pas un microcontrôleur choisi par hasard, puisque c'est, semble-t-il, le seul de la gamme Espressif (ESP8266, ESP32, ESP32-S2, ESP32-S3, ESP32-C3 et ESP32-C6) à proposer de l'USB OTG en plus de la classique connectivité Wi-Fi. Il ne dispose pas du Bluetooth ou de BLE, mais inclus 320 Ko de SRAM, 4 Mo de flash intégrés et 2 Mo de PSRAM intégrés, le tout construit autour d'un processeur Tensilica Xtensa LX7 à 270 MHz (+ un core RISC-V pour l'ULP (Ultra Low Power)). Le point clé est ici l'USB OTG afin de permettre le fonctionnement en USB CDC, rendant le montage accessible sous la forme d'un port série.
Pour reproduire le module Flipper Zero, un Lolin/Wemos S2 Mini dispose de toute la connectivité nécessaire :
- IO1 et IO2 respectivement connectés aux lignes SWCLK et SWDIO ;
- IO3, IO4 et IO5 connectés à des LED, via des résistances adaptées de (100 à 330 ohms selon la couleur) dont les anodes communes sont reliées au 3,3 volts ;
- IO17 et IO18 formant respectivement RX et TX d'une liaison série « logicielle » (les lignes IO44 et IO43 de l'UART « physique » n'étant pas accessibles sur le S2) ;
- IO0 correspond à la broche devant être mise à la masse pour activer le bootloader et reprogrammer la flash ;
- EN étant la ligne de reset.
Ces deux dernières broches sont reliées à deux boutons-poussoirs sur la carte. On peut donc très simplement passer le S2 en mode programmation en maintenant enfoncé le bouton « 0 » et en appuyant brièvement sur celui marqué « RST ». Ce reset étant contrôlé manuellement, ceci nous vaut un message d'avertissement lors de la programmation, mais sans conséquence pour la bonne marche des opérations.
Le port série, via IO17 et IO18, s'avère être d'une grande importance, du moins avec la version testée du firmware (commit 74ef924 du 2 juin 2022), comme nous le verrons plus loin. Il est donc capital de relier ces deux lignes à un convertisseur USB/série (3,3 volts !), faute de quoi vous aurez bien du mal à régler les paramètres de connexion Wi-Fi.
Dans l'article sur la BMP dans le numéro 40, j'avais utilisé une carte STM Nucleo-F401RE pour transformer la partie ST-LINK par flashage du firmware BMP dans le STM32F103 s'y trouvant. L'autre partie de la carte étant le domaine du STM32F411 et les deux étant reliés directement sur le circuit imprimé (et deux cavaliers), nous n'avions pas eu besoin de parler de la connexion SWD.
Ici, nous comptons utiliser une sonde autre que la partie ST-LINK déjà interfacée. Il nous faut donc connecter le STM32F411 à la carte Wemos S2 Mini et retirer les cavaliers. Ceci se fera assez simplement via la nomenclature suivante :
- Masse : broche 19 ;
- SWCLK : broche 15 ;
- SWDIO : broche 13 ;
- SWO et RESET ne sont pas connectés.
Les désignations concernent le connecteur CN7 (Morpho dans le jargon STM), c'est celui qu'on voit à gauche lorsqu'on regarde la carte d'en haut avec le connecteur USB en haut et avec la sérigraphie lisible dans le bon sens.
Remarquez qu'avec une Raspberry Pi Pico, les choses sont plus simples, puisque le connecteur « DEBUG » est distinct et la question du branchement ne se pose donc pas.
2. Construction et flashage
L'assemblage du montage est relativement simple, puisque nous venons de l'évoquer à l'instant. Il vous suffira de connecter le convertisseur USB/série aux broches IO17 et IO18 du S2 et de faire de même avec IO1 et IO2 pour les signaux SWCLK et SWDIO sur la cible (plus la masse, bien entendu). Les LED peuvent être ajoutées, mais n'ont pas de réel usage pratique à mon sens. Notez qu'il s'agit normalement d'une unique LED RGB pouvant donc prendre plusieurs couleurs en fonction de l'état des trois broches, exactement comme la LED LD1 sur la partie ST-LINK/BMP de la carte Nucleo.
C'est donc l'aspect logiciel qui sera le point le plus important ici. Pour construire le firmware, vous aurez besoin de l'environnement ESP-IDF, que nous avons déjà traité dans les pages du magazine (numéro 34 [8]) en version 4.0. Nous en sommes à présent à la version 4.3.4, mais peu de choses ont énormément changé concernant l'installation ou l'utilisation pratique.
Si vous êtes sous Windows, il existe un installer qui fera tout le travail à votre place (dépendances incluses). Celui-ci est disponible sur le site de téléchargement d'Espressif [9].
Sous GNU/Linux et macOS, la procédure sera un peu moins automatisée et nécessitera l'installation d'un certain nombre de prérequis. Là encore, une page dédiée du site d'Espressif décrira la procédure en détail [10].
Passée l'étape des prérequis, l'installation en elle-même se résume à invoquer le script adéquat en spécifiant les différentes plateformes pour lesquelles on souhaite développer. Ici, ceci se résumerait potentiellement à :
Bien entendu, mieux vaudra ne pas se limiter au seul ESP32-S2 et opter pour l'installation de l'ensemble des plateformes en spécifiant simplement all. Notez que, depuis peu, le script d'installation est également décliné en une version pour le shell Fish, si vous aimez la simplicité et les choses multicolores qui piquent les yeux.
Le travail de l'installeur consiste, en grande part, à télécharger, désarchiver et copier les chaînes de compilation pour les différentes architectures (dans ~/.espressif sur un système GNU/Linux). Rien n'est effectivement installé dans le système ou ne nécessite de permissions du super-utilisateur. Cette souplesse vous obligera cependant à initialiser l'environnement dans le terminal avant utilisation, en invoquant source export.sh dans le répertoire esd-idf (là encore, une déclinaison Fish existe, ainsi que pour les interpréteurs de commandes Windows) :
Comme le message de fin le précise, vous pouvez ensuite vous rendre dans le répertoire de votre projet et utiliser la commande idf.py pour procéder à différentes opérations, dont la construction.
Le firmware du module de développement du Flipper Zero est disponible sur GitHub [11] et pourra être cloné, puis directement construit avec :
Notez que le firmware est composé d'un ensemble de modules (BMP [12], M*Lib [13], et TinyUSB [14]) et que, de ce fait, l'option --recursive est indispensable (ou cloner le dépôt normalement et faire git submodule update --init --recursive ensuite).
ATTENTION : Le dépôt Git contient un fichier sdkconfig correspondant à la configuration du SDK pour ce projet ESP-IDF. Celle-ci est déjà parfaitement adaptée à la construction du firmware et ne nécessite pas de modification (via idf.py menuconfig). Pire encore, l'utilisation de idf.py set-target esp32s2, pour définir la cible, aura pour effet de réinitialiser cette configuration et le contenu de sdkconfig. Ceci n'est pas nécessaire, le projet est déjà configuré pour ESP32-S2. Si vous comptez jouer avec les paramètres, voire porter le projet sur un autre modèle d'ESP32, faites une copie du sdkconfig pour pouvoir revenir facilement en arrière en cas de problème (ou simplement utiliser git checkout sdkconfig).
Si l'opération de construction se déroule avec succès, ce qui devrait être le cas, vous retrouverez dans build/ le firmware binaire :
Vous pourrez alors connecter votre S2 Mini en USB et le basculer en mode programmation via les boutons « RST » et « 0 ». Celui-ci devrait alors apparaître dans le système comme un périphérique USB CDC (dmesg) :
Si toutes les permissions sont correctement configurées (ce qui sort totalement du cadre de cet article), il vous suffira d'invoquer une nouvelle fois idf.py en spécifiant le périphérique en question :
Le flashage semble se conclure sur une erreur, mais ce n'est absolument pas le cas (c'est le problème dont je parlais en tout début d'article). En réalité, l'ESP-S2 ne peut simplement pas être redémarré via USB CDC comme ce serait le cas avec un ESP32 et le contrôle de flux de la puce USB/série (DTR et/ou RTS). Ninja signale l'erreur, mais le message n'est en réalité qu'un avertissement vous demandant de redémarrer vous-même le microcontrôleur. Chose qu'on fera dans la foulée sans discuter.
3. Paramétrage du Wi-Fi
La procédure standard pour configurer le module consiste normalement à se connecter au point d'accès Wi-Fi qu'il propose par défaut sous le nom « blackmagic » (canal 1, mot de passe « iamwitcher », spécifié dans main/network.c), puis d'accéder à l'interface web pour basculer en mode station/client Wi-Fi et en spécifiant les paramètres du point d'accès à utiliser. Pour une raison mystérieuse, ceci ne fonctionne pas et la page web en question affiche un message d'erreur :
Fort heureusement, nous avons eu la présence d'esprit de connecter l'interface série logicielle du S2 Mini et pouvons donc accéder (115200 bps 8N1) à cette dernière, où nous découvrons une ligne de commandes (REPL) permettant de configurer différents éléments :
En dehors du logo qui est du plus bel effet, nous avons là une interface dont l'aide peut être affichée avec ? et qui va nous permettre de configurer le Wi-Fi. De base avec le firmware fraîchement flashé, nous sommes en mode point d'accès :
Nous pouvons, à l'aide de quelques commandes, paramétrer tout cela :
Notez également que la commande wifi_scan vous permettra d'obtenir une liste des points d'accès visibles à proximité. Si reboot ne fonctionne pas, utilisez simplement le bouton « RST » du S2 Mini. Une fois le redémarrage effectué, l'ESP32 devra normalement s'être connecté au point d'accès et avoir obtenu une adresse IP. Choses que vous pouvez vérifier facilement via la console série avec :
Un service mDNS sera également mis en service, vous permettant d'accéder au montage via son nom d'hôte, blackmagic.local, vous évitant d'utiliser l'adresse IP pouvant potentiellement changer selon votre configuration DHCP. En cas de problème, il faudra vérifier l'exactitude des paramètres et éventuellement tester une autre version du firmware (c'est celui de développement qui est utilisé ici). Vous pouvez également obtenir des informations sur le périphérique avec :
Vous pouvez aussi jeter un œil à l'interface web, toujours active, présentant diverses informations, dont la liste des processus FreeRTOS actifs :
4. Utilisation avec un STM32F401 et un RP2040
Nous avons à présent un module accessible via le LAN et nous pouvons donc tester le fonctionnement du serveur GDB Black Magic Probe. Celui-ci est accessible via la liaison USB/série, exactement comme c'est le cas avec la BMP classique que nous connaissons déjà. Nous allons d'ailleurs utiliser le même code simpliste, pour STM32F401, que la dernière fois :
Très classiquement, nous lançons GDB pour traiter le fichier blinkF401.elf (compilé avec les symboles de debug), spécifions la cible distante en précisant le premier port série fourni par le S2 Mini et nous nous attachons à la cible après avoir scanné les périphériques SWD présents. S'en suit la mise en place d'un point d'arrêt et une nouvelle exécution du programme qui s'arrête automatique sur main().
Ceci n'a rien de bien exceptionnel, si ce n'est par le fait que nous nous passons de la nécessité d'exécuter OpenOCD en parallèle pour servir d'interface avec GDB. Ce qui est très intéressant, en revanche, est de pouvoir faire exactement la même chose via le réseau :
Nous obtenons le même comportement que précédemment, mais en Wi-Fi ! Notez que nous avons spécifié le nom d'hôte de l'ESP32, chose bien plus pratique que d'utiliser son adresse IP. Un nom d'hôte que vous ne pouvez changer qu'en modifiant les sources (network.c), puisqu'il n'existe pas d'option de configuration pour cet élément. Il pourrait être intéressant de faire et de soumettre cette modification, voire de compléter automatiquement le nom avec le numéro de série de l'ESP32S2 (ou son adresse MAC). Ceci est également valable pour le numéro de port TCP utilisé par défaut, défini dans network-gdb.c.
Nous pouvons donc tranquillement manipuler et analyser notre code, mais aussi reflasher le firmware sur la cible :
Et donc avoir un cycle de développement et de mise au point beaucoup plus efficace qu'en utilisant tout autre matériel encombrant.
Ces manipulations ont également été réalisées avec une cible Raspberry Pi Pico et son microcontrôleur RP2040, avec exactement les mêmes opérations et les mêmes résultats. Je vous ferai grâce cependant ici des sorties console, qui n'apporteraient pas grand-chose de plus à l'article. D'autres microcontrôleurs peuvent être certainement utilisés de la même manière, comme ceux de Nordic par exemple, mais je n'ai testé ici que le STM32 et le RP2040.
Conclusion
Comme nous pouvons le voir, lorsqu'un nouveau projet est mis en route, ce n'est pas nécessairement le point sur lequel se concentre toute l'attention du public qui est le seul intéressant. Très souvent, ce genre d'initiative implique le développement d'outils et de projets satellites qui peuvent parfaitement être utilisés dans un autre contexte et un autre environnement. Ici, à défaut d'avoir pu mettre la main sur un Flipper Zero, nous avons découvert un outil de développement furieusement intéressant et polyvalent. Certes, l'aspect général n'est pas aussi « fini » que le module original, mais tout ceci reste cependant parfaitement fonctionnel (sachant que le port série logiciel n'est plus nécessaire une fois la configuration faite et que rien ne vous empêche de mettre cela dans un joli petit boîtier).
Je terminerai en précisant que les sources du firmware du module ont moins d'un an, avec une unique release (0.0.2) pour l'instant. Il reste donc beaucoup de choses à améliorer (comme les options de configuration du port GDB ou du nom d'hôte, par exemple) et peut-être souhaiterez-vous apporter votre pierre à l'édifice, sur ces points spécifiques (si je ne l'ai pas déjà fait), ou d'autres...
Références
[1] https://connect.ed-diamond.com/hackable/hk-040/black-magic-probe-deboguez-vos-codes-avec-facilite
[3] https://github.com/flipperdevices/flipperzero-firmware
[4] https://docs.flipperzero.one/development/hardware/wifi-debugger-module
[5] https://cdn.flipperzero.one/Flipper_Zero_WI-FI_Module_V1_Schematic.PDF
[6] https://www.wemos.cc/en/latest/s2/s2_mini.html
[7] https://fr.aliexpress.com/item/1005003145192016.html
[8] https://connect.ed-diamond.com/Hackable/hk-034/developpement-esp32-avec-le-nouveau-esp-idf-4.0
[9] https://dl.espressif.com/dl/esp-idf/?idf=4.4
[10] https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html#
[11] https://github.com/flipperdevices/blackmagic-esp32-s2
[12] https://github.com/flipperdevices/blackmagic