Published on

Solutions de débogage pour ARM sous Linux

Authors
  • Name
    Anthony Rabine

Le débogage sur une cible embarquée est nécessaire pour mener à bien vos projet de façon professionnelle. La méthode Arduino à base de print est un bon début, mais on ressent vite le besoin de placer des points d'arrêt. Sous Linux, des solutions accessibles existent, je vais vous présenter deux de mes préférées.

Le port SWD / JTAG

Le JTAG est un standard (une norme) permettant l'interopérabilité entre tous les cœurs permettant de contrôler l'électronique à partir d'une autre machine. Historiquement, cette solution a été conçue pour le test de carte électronique elle a été un peu détournée pour permettre le débogage d'un processeur. Ainsi, cette technique a remplacé petit à petit les émulateurs, grosses machineries qui prenaient la place d'un microcontrôleur et "émulait" toutes ses fonctions, y compris les périphériques (UART/SPI...).

Les émulateurs étaient très chers mais performants là ou le JTAG possède de nombreuses contraintes et limitations. Cependant, cela suffit largement pour le développement.

Chez ARM, ils ont créé leur truc à eux appelé SWD qui ne nécessite que quatre fils pour fonctionner (La clock, la data, un reset et la masse). Cette interface est utilisée sur tous les microcontrôleurs basés sur ce cœur.

Donc, pour pourvoir dialoguer avec le microcontrôleur et placer des points d'arrêt, il faut un lien entre ce port SWD et l'ordinateur. Il faut ce que l'on appelle une sonde JTAG.

La solution Segger

Segger est un fabricant de sondes mais pas seulement : il propose des librairies type middleware (stack IP, librairies graphiques, RTOS ...) et depuis peu un environnement de développement complet.

Il n'y a rien à redire sur leurs outils, ils sont fantastiques et accessibles. Par exemple, vous pouvez commencer avec la sonde JLINK EDU mini qui coûte dans les 20 Euros pour ensuite passer à quelque chose de plus sérieux quand vous aurez les moyens (ils ont des sondes très performantes tournant dans les 400/700 euros).

image

L'avantage de cette solution est qu'elle est reconnue partout, n'importe quel IDE supporte cette sonde (oui, même MPLAB de Microchip, c'est dire !). Ils fournissent des pilotes pour Linux contenant différents outils, bref, c'est très très pratique.

D'ailleurs, un de leurs outils est une passerelle GDB qui tourne en tâche de fond et convertit le protocole de débogage de GDB vers leur protocole propriétaire. Pratique si votre débogueur est GDB !

La solution libre BlackMagic Probe

Cette solution est particulièrement intéressante car cette sonde embarque un serveur GDB, donc directement pilotable par votre client GDB !

image

La sonde est un poil chère, environ 60 Euros, mais je trouve que c'est un bon investissement pour quelqu'un travaillant souvent sur des cibles ARM sous Linux. J'ai fait ce choix, et j'en suis assez content.

Voici mon setup.

Tout d'abord, il va vous falloir relier le BlackMagic sur le port SWD de votre microcontrôleur. Dans mon exemple, j'utilise une carte Arduino MKR Zero à base d'un microcontrôleur SAMD21G18A. Chez Arduino, ils ont eu la bonne idée de rendre accessible les broches du SWD au dos de la carte, moyennant la soudure d'un connecteur. Voici ce que donne mon câblage :

image

C'est terminé côté matériel. Maintenant, téléchargez la dernière version de la chaîne de développement GCC disponible pour tous les systèmes d'exploitation directement sur le site de ARM : https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain

Chez moi, je l'ai installé dans le répertoire /opt. Ouvrez une ligne de commande et lancez GDB :

opt/gcc-arm-none-eabi-2020/bin$ ./arm-none-eabi-gdb

Le prompt (gdb) s'affiche.

La première chose à faire est d'autoriser GDB à accéder à toute la mémoire (pas seulement cette de l'exécutable) :

(gdb) set mem inaccessible-by-default off

Ensuite, on dit à GDB qu'il va déboguer via une liaison série, dans notre cas c'est le port /dev/ttyACM0. Si vous êtes sous Windows, utilisez un truc du genre "\.\COM23".

(gdb) target extended-remote /dev/ttyACM0
Remote debugging using /dev/ttyACM0

On scan le bus SWD pour rechercher un coeur :

(gdb) monitor swdp_scan
Target voltage: 3.3V
Available Targets:
No. Att Driver
 1      Atmel SAMD21G18A (rev D) M0+

Super, il nous indique la tension de la carte cible et le bon microcontrôleur.

On s'y attache :

(gdb) attach 1
Attaching to Remote target
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
0x00015330 in ?? ()

Ok c'est normal, nous n'avons programmé aucun firmware et GDB ne sait donc pas quoi faire. Allons-y, je vous épargne les dizaines de lignes de Loading :

(gdb) load /home/anthony/git/personnel/OpenStoryBox/osb-firmware/ports/atmel-samd/osb.X/dist/Default/debug/osb.X.debug.elf
Loading section .data.impure_data%1, size 0x418 lma 0x20000118
...
Loading section .text._mon_putc%196, size 0x4 lma 0x15370
Start address 0x14774, load size 89452
Transfer rate: 20 KB/sec, 406 bytes/write.

Youpi, cela fonctionne du tonnerre, et sans aucun fichier de configuration c'est le bonheur !

À vous de déboguer en ligne de commande, sisi c'est possible, ou choisir le bon IDE comme cela est décrit ci-dessous.

La solution OpenOCD

Cette solution est la solution du pauvre, mais qui marchotte. OpenOCD est un logiciel qui tourne en tâche de fond et se place entre GDB et votre matériel, par exemple une sonde que l'on trouve sur toutes les cartes STM32, la STlink.

Autrefois, c'était le seul moyen de déboguer dans l'embarqué sur Linux ou Windows gratuitement. Aujourd'hui, je suis moins convaincu car cela rajoute une complexité avec son fichier de configuration à gérer pour un résultat pas super performant ni stable. Bref, je vous le déconseille.

Quels outils graphiques pour les sondes SWD ?

Il y a plein de choix car beaucoup d'environnements graphiques de débogage supportent GDB. Attention, il faudra cependant bien paramétrer votre outil car il faudra utiliser le GDB fournit dans votre chaîne de compilation croisée.

Mon choix est d'utiliser Eclipse car l'ayant pratiqué de longues années en environnement professionnel je me sens relativement à l'aise, même si on ne peut jamais être totalement à l'aise avec Eclipse 😄. Les autres choix dans le domaine gratuit sont (liste non exhaustive) :

  • VisualStudio Code avec ses multitudes de plug-ins (notamment PlatformIO)
  • QtCreator avec son plugin Bare Metal
  • Netbeans
  • Code::Blocks

L'autre solution, commerciale mais performante, est d'utiliser les outils de Segger :

  • Une sonde JLink
  • Le débogueur Ozone, qui peut être téléchargé gratuitement sur le site de l'éditeur

Débogage avec Ozone/JLink

Là c'est simple, démarrez Ozone, une fenêtre popup s'ouvre.

Spécifiez la référence de votre microcontrôleur : image

Spécifiez le port de débogage. Attention à la vitesse de votre SWD, si vous avez des grands fils volants il est peu probable que vous puissiez monter trop haut en fréquence. C'est aussi dépendant de la fréquence de votre processeur.

image

Enfin choisissez votre fichier exécutable, le format ELF est complet (il contient des informations de débogage, notamment l'emplacement des fichiers sources).

image

Et voilà !

image

Débogage avec Eclipse

Voici les extensions conseillées avec Eclipse :

  • Eclipse Embedded CDT (Gestion fine des outils de développement embarqués)
  • EmbSysRegView (pour voir les registres des micros de manière plus sympa)

Lorsque vous avez votre projet d'ouvert sous Eclipse, faîtes un clique-droit et sélectionnez 'Debug As...' puis 'Debug Configurations'.

Créez une nouvelle configuration de débogage de type "GDB Hardware Debugging". Dans le premier onglet, choisissez un exécutable, normalement Eclipse devrait le trouver au sain du projet.

image

Dans le deuxième onglet, décochez "Remote Target" et choisissez l'exécutable client GDB se trouvant sur votre disque. La procédure de connexion se fera à l'aide de script dans l'onglet suivant.

image

Dans ce troisième onglet "Startup", entrez la liste des commandes dans la première case "Initialization Commands"

set mem inaccessible-by-default off
target extended-remote /dev/ttyACM0
monitor swdp_scan
attach 1

Laissez coché "Load image" et "Load symbols". C'est parti, vous pouvez lancer la session !

image

Super, après le chargement, on se retrouve dans la perspective de débogage, notre programme est stoppé dans le main.

image

Un résultat simple, réalisé par des étapes simples et limitées. L'avantage est que cette solution est générique pour tous les ARM.

Conclusion

Quelle que soit votre solution, n'hésitez pas à passer du temps dans le choix et le test d'un bon environnement de débogage. Vous gagnerez du temps et le plaisir de développement sera accru !