Déboguer un ESP32-WROOM sous PlatformIO via son interface JTAG

5
(3)

Déboguer permet d’analyser les bugs d’un programme. La majorité des développeurs débutants utilisent la fonction Serial.print() pour déboguer leur programme. Mais l’utilisation de traces n’est pas très pratique pour déboguer un programme. Ne sachant pas en général d’où vient le problème, il faut positionner de nombreuses traces. Et il faut les modifier maintes fois avant d’identifier la cause du problème. L’utilisation d’un débogueur est bien plus efficace et permet d’analyser des bugs bien plus rapidement qu’avec des traces.

Quand on debug le programme, c’est le débogueur qui a la main sur le microcontrôleur. Le débogueur permet d’exécuter le programme pas à pas afin d’analyser son comportement. Il permet d’inspecter les variables, les registres et la mémoire du microcontrôleur. Le débogueur permet généralement de modifier l’état du programme (variable, registre, mémoire…) lorsque son exécution est stoppée.

Une interface JTAG permet d’accéder directement aux ressources internes des circuits intégrés, ce qui en fait un mécanisme essentiel pour le débogage des systèmes à base de microcontrôleur.

Dans ce tutoriel, j’explique comment déboguer un programme sur un ESP32 au travers de son interface JTAG, en utilisant Visual Studio Code et PlatformIO. Je détaille l’installation et l’utilisation sous Linux, mais c’est très similaire sous Windows.

Le débogueur que j’utilise est GDB (GNU Debugger), plus précisément xtensa-esp32-elf-gdb qui est la version de GDB adaptée à l’architecture ESP32 Wroom que j’utilise. OpenOCD (Open On-Chip Debugger) agit comme une interface pour communiquer avec le microcontrôleur ESP32 au travers de l’adaptateur JTAG ESP-PROG.

Les broches du JTAG

Une interface JTAG est composée de 4 broches principales :

  • TDI (Test Data In)
  • TDO (Test Data Out)
  • TCK (Test Clock)
  • TMS (Test Mode Select)

Les signaux de l’interface JTAG sont connectées aux broches suivantes de l’ESP32 :

Les broches JTAG de l’ESP32
Broches JTAG d’un uPesy ESP32-WROOM

Les broches JTAG sur l’ESP-PROG :

Les broches JTAG de l’ESP-PROG
Schéma de câblage entre l’ESP32-WROOM et l’ESP-PROG

Connexion de l’ESP-PROG et de l’ESP32

L’ESP-PROG est relié au PC via un câble USB qui sera utilisé pour la communication entre les deux équipements et pour l’alimentation électrique de l’ESP-PROG.

Il n’est pas nécessaire de relier la carte ESP32 au PC. En effet débogage de l’ESP32 sera effectué via le protocole JTAG au travers de l’ESP-PROG, et le programme sera également téléversé sur l’ESP32 au travers de l’ESP-PROG. Il suffit donc de relier la prise USB de la carte ESP32 sur une alimentation USB.

Configuration de la communication entre le PC et l’ESP-Prog

Il faut suivre la procédure d’installation détaillée dans la documentation de PlatformIO. Sur Linux il suffit d’installer les règles udev en entrant les commandes suivantes dans un terminal :

curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules
sudo service udev restart

Installation de Visual Studio Code et PlatformIO

La procédure d’installation de Visual Studio Code et de PlatformIO est décrite dans mon tuto Programmez un Raspberry Pi Pico avec Visual Studio Code et PlatformIO.

Pour l’instant le composant GDB de la toolchain fourni par Espressif nécessite l’installation de libpython2.7.so.1.0, pour résoudre ce problème il suffit d’installer le package python2.7-dev.

 sudo apt install python2.7-dev

Fichier de configuration de PlatformIO

Il faut modifier le fichier de configuration platformio.ini qui est généré par défaut.

La vitesse du moniteur série qui est utilisé pour afficher les traces (Serial.print) :

monitor_speed = 115200

Le nom de l’outil de debug utilisé pour déboguer notre carte, nous utilisons esp-prog:

debug_tool = esp-prog

Nous allons également téléverser le programme sur l’ESP32 via l’adaptateur ESP-PROG en utilisant le protocole esp-prog:

upload_protocol = esp-prog

Le point d’arrêt initial de débogueur, que nous positionnons dans la fonction setup :

debug_init_break = tbreak setup

Voici le contenu du fichier platformio.ini modifié :

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:upesy_wroom]
platform = espressif32
board = upesy_wroom
framework = arduino
monitor_speed = 115200
upload_protocol = esp-prog
debug_tool = esp-prog
debug_init_break = tbreak setup

Le programme à déboguer

Nous allons déboguer le programme suivant, qui contient un bug que nous souhaitons identifier et corriger. Copier-coller ce code dans le fichier main.cpp :

// Deboguer un ESP32 avec PlatformIO
// via son interface JTAG
// https://tutoduino.fr/
// Copyleft 2023
#include <Arduino.h>
int test(int a)
{
  int result;
  result = 1000 / a;
  return result;
}
void setup()
{
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  delay(1000);
}
void loop()
{
  int randNumber, result;
  randNumber = random(20); // Generate a pseudo-random between 0 and 20
  result = test(randNumber);
  // These kind of traces are not required anymore with a debugger
  Serial.print("Calling test function with value ");
  Serial.print(randNumber);
  Serial.print(" returned ");
  Serial.println(result);
  digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
  delay(500);                      // wait for 500ms
  digitalWrite(LED_BUILTIN, LOW);  // turn the LED off
  delay(500);                      // wait for a 500ms
}

Il faut ensuite lancer le débogage du programme en cliquant sur Exécuter/Démarrer le débogage :

Lancement de l’exécution du programme sur l’ESP32 en mode débogage via le JTAG

Le programme s’exécute jusqu’à l’appel de la fonction setup(), nous avons en effet configuré ce point d’arrêt initial du débogueur dans le fichier de configuration platformio.init avec debug_init_break = tbreak setup.

Le débogueur s’arrête sur le point d’arrêt initial dans la fonction setup()

Il est maintenant possible d’avancer pas à pas dans le programme grâce au menu de contrôle du débogueur situé en haut au milieu de l’écran :

Menu de contrôle du débogueur

Vous pouvez ensuite exécuter le programme pas à pas, positionner d’autres points d’arrêt, continuer l’exécution jusqu’au prochain point d’arrêt, inspecter la mémoire et les variables…

Execution pas à pas d’un programme arrêté dans la fonction test() et visualisation de la valeur des variables

Notre programme contient un bug que vous devez avoir identifié. Il y a en effet une division par zéro dans la fonction test() si le paramètre passé en argument est égal à zéro. Comme la fonction test() est appelée avec un argument qui est un nombre aléatoire compris entre 0 et 20, ce bug va se produire aléatoirement et générer une exception.

Nous cliquons donc sur la commande “Continuer” du débogueur pour continuer l’exécution du programme, et attendre qu’il plante. A ce moment le débogueur fournit toutes les informations nécessaire à l’identification et la correction du bug : on voit que le programme est arrêté dans la fonction test() et que la variable a est égale à zéro. PlatformIO mentionne même en bas à droite l’information “Division by zero (from data-evaluate-expression result)“, on ne peut être plus clair !

Le débogueur permet d’identifier facilement le bug, il s’agissait d’une division par zéro !

Erreur lors du lancement du débogage

Avec la version que j’utilise (Visual Studio Code 1.81.0, PlatformIO Core 6.1.9 Home 3.4.4, OpenOCD v0.11.0-esp32-20220706), je rencontre plusieurs erreurs lors du démarrage du débogage du programme.

Échec lors de l’accès mémoire en écriture pour le point d’arrêt
Échec de vérification du flashage…

Généralement je rencontre les deux erreurs ci-dessus l’une après l’autre, et ce n’est qu’après le troisième démarrage que cela fonctionne. Je continue d’essayer de trouver une solution à ce problème, mais sans succès pour l’instant. Il ne faut donc pas hésiter à relancer le débogage et répondre “Oui” si Visual Studio Code vous demande de démarrer une autre instance de ‘PIO Debug’. Si tout se déroule sans erreur, le débogueur va s’arrêter sur le point d’arrêt configuré dans la fonction setup().

Avez-vous besoin de l’ESP-PROG ?

L’ESP-PROG est un adaptateur JTAG externe basé sur le composant FT2232H, qui est un circuit intégré d’interface USB vers UART.

Certaines cartes de développement ESP32 intègrent ce composant FT2232H et ne nécessitent donc pas l’utilisation d’un adaptateur JTAG externe. Vous pouvez directement déboguer la carte en la reliant avec un câble USB à votre PC.

Le microcontrôleur ESP32-C3 intègre un adaptateur JTAG au travers de son contrôleur USB Serial/JTAG. Si vous êtes intéressez, voir mon tutoriel déboguer un ESP32-C3 via son interface JTAG.

Différentes architectures possibles en fonction des cartes ESP32

Ce tuto est terminé, n’hésitez pas à donner votre avis et à laisser un commentaire, cela m’aidera à l’améliorer.

Merci à Gotronic et uPesy pour la fourniture de la carte ESP32 Wroom qui a été utilisée pour réaliser ce tutoriel !

Votre avis compte !

Note moyenne : 5 / 5. Nombre de votes : 3

Pas encore de vote pour ce tutoriel

Désolé si cet article ne vous a pas intéressé

Merci de commenter afin que je puisse l’améliorer.

Dites-moi comment améliorer cette page.