Débugger Marlin avec ST-Link V2

Si vous avez déjà utilisé un Marlin Firmware sur votre imprimante 3D, il est très probable que vous ou quelqu'un d'autre ait créé le firmware pour votre imprimante. Cependant, Marlin est un joyeux mélange hétéroclyte de fonctionnalités et il est très peu probable que vous obteniez exactement la perle rare que vous attendiez.

Par exemple, si vous avez modifié votre imprimante, vous devrez alors construire une version spécialisée de Marlin avec la nouvelle option activée.

Créer un microprogramme avec Marlin

Considérons ici deux scénarios possibles :

Vous aviez déjà construit votre firmware

Dans ce cas, vous savez déjà comment personnaliser le fichier Configuration.h et Configuration_adv.h. Dans ce cas, vous pouvez sauter la section suivante.

Vous utilisiez un firmware pré-compilé

Dans ce cas, vous ne savez probablement pas comment construire Marlin, ou quels sont les fichiers Configuration.h et Configuration_adv.h. Je ne vais pas reformuler l'excellent tutoriel de Marlin ici, même si c'est un gros complexe pour les nouveaux venus. Pour simplifier au maximum, je vous conseille d'installer d'abord Visual Studio Codium et PlatformIO. Ensuite, téléchargez (ou mieux, clonez avec git si vous savez comment faire) le code source de Marlin depuis leur dépôt en cliquant sur le bouton vert "Code".

Dans l'archive/dossier téléchargé, vous trouverez un répertoire appelé "Marlin" contenant 2 fichiers d'intérêt : Configuration.h et Configuration_adv.h. Le meilleur conseil que je puisse vous donner ici est de rechercher, dans la boîte de recherche Github, un fork de Marlin pour votre imprimante (par exemple, en entrant le nom de votre imprimante dans la boîte de recherche et Marlin). Ensuite, extrayez les en-têtes de configuration de ce fork. Veuillez vous assurer que le fork n'est pas trop vieux, ou vous devrez retravailler les changements dans les fichiers de configuration lorsque Marlin améliorera version après version.

Une fois cela fait, lancez platformio run dans le dossier principal et corrigez tout problème jusqu'à ce qu'il se construise correctement. Si vous avez Visual Studio Codium et PlatformIO, il faut spécifier la plate-forme pour laquelle vous construisez dans PIO Home et ensuite cliquer sur cette icône :

Icône pour lancer la construction

S'il ne se construit pas, veuillez vous référer à la documentation de Marlin ci-dessus ou demander via les commentaires de cette page.

Exécution du microprogramme sur votre imprimante

Ok, maintenant vous avez un binaire à installer sur votre imprimante. Vous devrez suivre la procédure de mise à jour du micrologiciel de votre imprimante pour l'installer (chaque fabricant d'imprimantes fournit ici sa propre procédure, mais elle se résume généralement à mettre un ou plusieurs fichiers sur une carte SD et à démarrer l'imprimante).

Si vous avez de la chance et que quelqu'un d'autre a déjà suivi le même chemin que vous et a corrigé tous les bugs, alors vous avez terminé, félicitations !

Cependant, je suis presque sûr que vous lisez cette page parce qu'elle ne fonctionne pas aussi bien que vous l'espériez. Dans ce cas, vous devrez déboguer le micrologiciel et, contrairement à votre ordinateur, la carte mère de votre imprimante est très limitée, ce qui rend le débogage assez difficile (mais pas impossible).

Débogage d'un microprogramme

Sur votre imprimante, vous pouvez avoir n'importe quel type de processeur. Si le CPU est trop limité (comme, par exemple, un AVR), le débogage sera lui aussi trop limité et vous finirez par insérer printf ou serial.write dans le code et ce sera une plaie.

Dans cet article, je n'expliquerai le cas que lorsque l'appareil fonctionne sur un ARM 32 bits, et en particulier sur le processeur d'un STM32. Ces cas sont très courants et leur débogage est très peu coûteux.

Matériel

Vous devrez utiliser un dongle USB ST-Link V2 comme celui que vous trouverez dans le lien affilié ci-dessous. Vous aurez également besoin du schéma de la carte mère de votre imprimante, et de localiser les broches appelées 3.3V, GND, SWDIO, SWCLK. Vous devrez connecter le fil JST du programmateur à la carte mère de votre imprimante.

Cette partie n'est pas trop difficile, mais vérifiez les connexions et connectez le fil lorsque l'imprimante est éteinte et sans que votre ordinateur soit connecté au dongle USB (vous aurez peut-être besoin d'un câble d'extension USB, il vaut mieux prolonger le câble USB que les 4 fils).

Logiciels

Une fois que vous avez tout branché, vous devez télécharger un logiciel appelé OpenOCD. Il existe pour Linux et Windows, et je vous conseille vivement d'utiliser la version Linux si vous le pouvez car il est plus facile de configurer AMHA. Si vous avez utilisé PlatformIO et VSCodium, alors il est probablement déjà téléchargé pour vous (dans ce cas, vous trouverez le binaire et le script dans votre répertoire personnel, dans le dossier ~/.platformio/packages/tool-openocd/). Si vous travaillez sous Windows, le chemin sera différent, cherchez sur votre disque dur un dossier tool-openocd. Si vous ne l'avez pas installé, vous pouvez ajouter cette ligne à la définition de votre carte mère dans le fichier platformio.ini :

#
# MKS Robin Nano (STM32F103VET6)
#
[env:mks_robin_nano35]
platform = ${common_stm32f1.platform}
extends = common_stm32f1
board = genericSTM32F103VE
platform_packages = tool-stm32duino
extra_scripts = ${common.extra_scripts} buildroot/share/PlatformIO/scripts/mks_robin_nano35.py
build_flags = ${common_stm32f1.build_flags} -DMCU_STM32F103VE -DSS_TIMER=4
# \/ Ajoutez ceci ici \/
debug_tool = stlink
# /\ Ajoutez ceci ici /\

OpenOCD est un démon/serveur qui communique avec le dongle ST-Link V2 et instruit/surveille le processeur STM32 de votre carte mère. Ainsi, il est nécessaire que le serveur et le dongle soient reconnus et autorisés à fonctionner avec la permission de votre utilisateur. Sous linux, cela signifie que vous devez vous assurer que vous êtes autorisé à accéder au périphérique USB (si ce n'est pas le cas, vous devrez exécuter OpenOCD en tant que root avec "sudo" comme préfixe dans les commandes suivantes). Sur la plupart des systèmes, vous devrez entrer dans un groupe "usb hardware", en ajoutant votre utilisateur au même groupe que celui du périphérique USB détecté.

Pour l'instant, ce n'est pas très important, à condition que vous utilisiez le serveur en tant que root, mais si vous avez l'intention de déboguer en permanence, vous gagnerez du temps en configurant un accès correct au périphérique.

Sur la version récente d'OpenOCD, il n'y a plus de distinction entre la configuration de ST-Link et de ST-Link V2, donc je vais passer les anciens tutoriels qui indiquaient de spécifier le fichier de configuration à utiliser.

Démarrage du serveur et débogage de l'imprimante

Sur de nombreuses imprimantes, le processeur intégré n'exécute pas directement votre firmware. Il exécute d'abord un petit logiciel qui se charge de charger votre firmware, mais aussi de vérifier si une nouvelle version est présente sur la carte SD et de la faire clignoter dans ce cas. Ce petit logiciel s'appelle un "bootloader" et vous ne devez pas l'écraser, sinon vous ne pourrez plus mettre à jour votre firmware via la carte SD (vous serez limité à l'utilisation du dongle ST-Link).

Dans la plupart des cas, le bootloader est petit, il vous suffit donc de trouver où placer votre firmware. Encore une fois, dans la plupart des cas pour STM32, il sera à l'adresse 0x8007000 mais attention que certaines cartes utilisent 0x8008000 pour le décalage. En cas de doute, ouvrez le fichier appelé platformio.ini dans le dossier source de Marlin et recherchez votre carte dans une section [env:something]. Si votre forum contient une clé board_build.offset, vous devrez l'utiliser comme base pour calculer l'offset. Ainsi, par exemple, le forum Lerdge lit :

#
# Lerdge base
#
[lerdge_common]
platform           = ${common_stm32.platform}
extends            = common_stm32
board              = LERDGE
board_build.offset = 0x10000

Cela signifie que le code sera exécuté à l'adresse 0x08010000.

Encore une fois, la plupart du temps, le bootloader ne peut pas être débogué via OpenOCD car il sera protégé (et vous n'êtes probablement pas intéressé par son code de toute façon). C'est douloureux, car cela signifie que vous ne pouvez pas réinitialiser la carte dans le débogueur et vous attendre à ce que le débogueur se comporte correctement (puisqu'il n'a pas de symbole pour le chargeur d'amorçage).

Donc, pour continuer le débogage, vous devez exécuter le débogueur comme un débogage post mortem (ou pseudo post mortem, voir ci-dessous). Dans ce mode, nous demanderons à OpenOCD de ne pas réinitialiser la carte lors de sa connexion et nous la connecterons une fois que le firmware sera chargé et en cours d'exécution.

La ligne de commande pour lancer OpenOCD ressemblera plus ou moins à ceci :

$  ~/.platformio/packages/tool-openocd/bin/openocd -d2 -s ~/.platformio/packages/tool-openocd/scripts -f interface/stlink.cfg -f target/stm32f1x.cfg -c "reset_config none separate"

Vous devrez ajuster le type de CPU de votre carte mère (pour moi, c'est stm32f103vet6, donc j'ai choisi target/stm32f1x.cfg). Si vous avez besoin de lancer OpenOCD en tant que root, vous devrez lancer la commande préfixée par sudo et remplacer le chemin ~/ par le chemin absolu /home/you/ aux deux endroits.

Une fois lancée, elle devrait produire quelque chose comme ceci :

xPack OpenOCD, x86_64 Open On-Chip Debugger 0.10.0+dev-00378-ge5be992df (2020-06-26-09:27)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 2

none separate

Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 1000 kHz
Info : STLINK V2J29S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.079592
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections

Ensuite, vous devrez aller dans votre dossier source Marlin et exécuter le débogueur sur le fichier ELF de votre firmware comme ceci :

$ ~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-gdb /path/to/Marlin/.pio/build/board/firmware.elf

Remplacez "board" par votre carte ou plate-forme comme indiqué dans "platformio.ini".

Une fois que GDB a démarré, vous devrez vous connecter à OpenOCD à distance via :

> tar ext:3333
> si

La première commande est un raccourci vers target extended remote localhost:3333 avec le port 3333 étant le port listé dans la sortie OpenOCD ci-dessus. La seconde commande est un raccourci pour step into afin que GDB récupère/synchronise avec l'état actuel du CPU. Une fois que vous y êtes, les commandes GDB habituelles sont disponibles, comme list pour lister le code source autour de l'instruction CPU courante, info local pour lister la variable locale dans la fonction courante, bt pour obtenir une trace de la pile et b file.cpp:123 pour placer un point d'arrêt sur la ligne 123 du fichier file.cpp. Attention à ne pas lancer run car cela signifierait redémarrer l'application (dans ce cas, le CPU) et cela échouerait avec un bootloader.

Commandes GDB interdites

Afin d'éviter de casser votre système, vous devrez éviter toute commande adressée à la cible distante (comme "monitor reset halt"), ou celles induisant le reset du firmware (comme "load") car GDB ne sait pas comment faire cela correctement, et OpenOCD ne sait pas non plus et peut casser les choses en essayant.

Sur certaines plates-formes, il n'y a pas de configuration correcte du hardfault handler, donc quand le CPU se bloque, vous ne pouvez pas obtenir de trace de la pile (ceux qui utilisent encore du code libmaple sont connus pour casser dans ce cas). libmaple est obsolète et sera supprimé quelque part dans le futur, mais en attendant, si cela se produit, vous devrez probablement mettre un peu de volatile bool loop = true ; while(loop); dans le code avant qu'il ne se verrouille afin que le CPU bouge où vous le souhaitez et ainsi vous pourrez progresser en changeant la variable loop dans le débogueur via set loop = false dans GDB une fois qu'il est arrêté sur la boucle. J'ai proposé un PR pour cette fonctionnalité et elle est en cours d'analyse. Avec un peu de chance, ce problème sera résolu dans le futur.

Si vous avez une carte mère MKS Robin Nano v1.2 (celle dans l'imprimante Sapphire Plus), vous pouvez corriger ces problèmes en suivant mon tutoriel ici

!!!Triple buse!!!

Le débogage peut provoquer un incendie si vous ne comprenez pas ce que vous faites. Débranchez les heater (à la fois le hotbed et la hotend) si vous n'êtes pas sûr.

Attention cependant, le débogage via GDB arrête de nombreux garde-fous dans le code et donc cela ne devrait jamais se produire pendant l'impression (sinon vous n'aurez probablement pas de surveillance thermique de votre hotend et il peut brûler et prendre feu!!!). Donc si le bogue que vous essayez de déboguer se produit pendant l'impression, n'utilisez pas la méthode ci-dessus pour le déboguer, utilisez plutôt le bon vieux "printf".

Liens sponsorisés :

Afin de payer les coûts d'infrastructure de ce blog, je vous propose quelques liens affiliés concernant le matériel mentionné ci-dessus :

Article précédent Article suivant