Egal in welchem Bereich der Programmierung du arbeitest, um das Debuggen kommst du einfach nicht herum. Beim Debuggen hast du die Möglichkeit, deinen Programmcode live, Zeile für Zeile, im laufenden Betrieb zu beobachten oder Variablen zu prüfen. Das hilft dir nicht nur dabei, Fehler – sogenannte Bugs – zu beheben, sondern auch Anpassungen vorzunehmen oder einfach nur den Code besser zu verstehen.
Mit dem Espressif ESP-Prog und PlatformIO gibt es eine einfache Möglichkeit, ESP32-MicroController zu programmieren und den Programmiercode im laufenden Betrieb zu debuggen. Wie genau das funktioniert und was du dafür brauchst, zeigt dir dieser Blogbeitrag.
Vorbereitung
Damit du diesen Beitrag Schritt für Schritt nachmachen kannst, benötigst du einige Bauteile. Schau dir dazu Tabelle 1 an. Je nachdem, wie du den ESP32 einsetzen möchtest, brauchst du entweder Jumper Male-Male oder Male-Female.
Hier ist die Tabelle, die die benötigte Hardware für den Aufbau auflistet:
Pos | Menge | Komponente |
---|---|---|
1 | 1 | ESP32 NodeMCU Development Board |
2 | 1 | BlackCotton Micro USB 2.0 Kabel, schwarz, 1,0m |
3 | 1 | Espressif ESP-Prog, Programmiergerät für SoC-Systeme |
4 | 1 | 40pin Jumper |
Tabelle 1: Benötigte Hardware für den Aufbau
Um dir das lange Suchen im Shop zu ersparen, habe ich einen entsprechenden Warenkorb für dich angelegt: Warenkorb auf Berrybase
Zusätzlich benötigst du eine lauffähige Programmierumgebung wie Visual Studio Code mit installierter PlatformIO-Erweiterung. Auch die Treiber für den ESP-Prog sind erforderlich, dazu erfährst du später mehr bei der Einrichtung von ESP-Prog und PlatformIO.
Anmerkung zum Debuggen und Warnung
Anders als bei gewöhnlicher Computersoftware programmierst du hier einen MicroController. Dafür wird ein externer Programmer – der Espressif ESP-Prog – verwendet, der eine physikalische Verbindung zum MicroController braucht. Beim ESP32 sind dies die vier GPIOs:
- GPIO 12
- GPIO 13
- GPIO 14
- GPIO 15
Zusätzlich muss auch die Stromversorgung mit 3,3V/5V und GND hergestellt werden. Achte darauf, dass der Jumper auf der richtigen Position steht, wie in Abbildung 1 gezeigt.
Abbildung 1: Den Jumper auf die richtige Spannung stellen
Die Beschriftung an der Seite hilft dir ein wenig weiter, wie der Jumper gesetzt werden muss.
Eine ausführliche Liste zu den Anschlüssen findest du direkt in der Dokumentation von PlatformIO, siehe Tabelle 2.
Natürlich, hier ist die Tabelle in einem textbasierten Format für Ihre Übersicht:
JTAG-Anschlussdetails für verschiedene ESP32-Varianten
ESP-Prog JTAG 10-Pin Connector | JTAG Signal | ESP32 Pin | ESP32-S2 und ESP32-S3 Pin | ESP32-C2, ESP32-C3, ESP32-C6, und ESP32-P4 Pin | ESP32-H2 Pin | Beschreibung |
---|---|---|---|---|---|---|
1 | VDD | VDD | VDD | VDD | VDD | Positive Supply Voltage — Power supply for JTAG interface drivers |
3 | GND | GND | GND | GND | GND | Digital ground |
2 | TMS | GPIO14 | GPIO42 | GPIO4 | GPIO2 | Test Mode State |
4 | TCK | GPIO13 | GPIO39 | GPIO6 | GPIO4 | JTAG Return Test Clock |
6 | TDO | GPIO15 | GPIO40 | GPIO7 | GPIO3 | Test Data Out |
8 | TDI | GPIO12 | GPIO41 | GPIO5 | GPIO5 | Test Data In |
Beachte dabei, dass diese GPIOs später für den Programmcode nicht mehr zur Verfügung stehen. Andernfalls riskierst du, dass entweder der ESP32 oder der ESP-Prog beschädigt werden. Im schlimmsten Fall könnte es sogar zu einem Kurzschluss kommen, der über die USB-Buchse an deinen PC weitergeleitet wird.
Ein weiterer wichtiger Hinweis: Verwende niemals beide USB-Anschlüsse (vom ESP32 und ESP-Prog) gleichzeitig! Dies könnte zu einem Defekt des ESP32 und/oder ESP-Prog führen. Halte immer nur eine Verbindung aufrecht und prüfe sorgfältig, dass alles korrekt angeschlossen ist. Der Upload beim Debuggen erfolgt ausschließlich über den ESP-Prog und nicht über den COM-Port des ESP32.
Den ESP-Prog vorbereiten
Bevor du den ESP-Prog mit PlatformIO nutzen kannst, musst du ihn noch umprogrammieren und Treiber für Windows nachinstallieren. Ich gehe hier nur auf Windows ein, weil die meisten wahrscheinlich Windows als Standardbetriebssystem verwenden.
Zunächst brauchst du den sogenannten VCP-Treiber, den du hier herunterladen kannst: VCP-Treiber. Wichtig ist, dass du den „Windows (Desktop)“-Treiber auswählst, siehe Abbildung 2.
Diesen Treiber musst du dann unter Windows installieren. Dafür brauchst du Administratorrechte, aber es dauert nur ein paar Minuten.
Anschließend muss der ESP-Prog „umprogrammiert“ werden. Dafür brauchst du das Tool Zadig, das du unter Zadig Download findest. Zum Zeitpunkt dieses Beitrags ist die Version 2.9 aktuell.
Nachdem du Zadig heruntergeladen hast, starte es und wähle den Treiber „Dual RS232-HS (Interface 0)“ aus. Damit das funktioniert, musst du unter „Options“ die Option „List all devices“ aktivieren. Danach wählst du „WinUSB (vXXXXX)“ und klickst auf „Replace Driver“, um den ESP-Prog umzuprogrammieren. Die Schritte sind noch einmal in Abbildung 3 erklärt.
Wenn der Treiber bereits ersetzt wurde, heißt der Button „Reinstall Driver“ anstatt „Replace Driver“.
Nach der Installation muss der ESP-Prog einmal vom PC getrennt und anschließend wieder verbunden werden, damit die korrekten Treiber geladen werden. Zadig sollte jetzt den WinUSB-Treiber anzeigen, nicht mehr FTDIBUS.
Damit sind die Vorbereitungen für den ESP-Prog abgeschlossen. Sollte es später Fehlermeldungen in PlatformIO geben, die zum Beispiel anzeigen, dass libusb_open()
fehlschlägt oder esp32.flash
kein free_driver_priv()
unterstützt, führe diese Vorbereitung erneut durch. Die Fehlermeldungen werden in der PlatformIO-Konsole angezeigt.
Die Verkabelung
Damit der Espressif ESP-Prog mit dem ESP32 funktioniert und später mit PlatformIO kommunizieren kann, muss er korrekt verkabelt werden. Sieh dir dazu Abbildung 4 an.
Wichtig ist hier der korrekte Anschluss, der bereits in der „Anmerkung zum Debuggen und Warnung“ beschrieben wurde. Zum besseren Verständnis zeigt Abbildung 5 das Pinout des JTAG des ESP-Prog.
Wenn du den Jumper auf dem ESP-Prog auf 3,3V oder 5V eingestellt hast, musst du sicherstellen, dass du auch den entsprechenden VIN-Pin am ESP32 verwendest. Andernfalls kann es zu Schäden am ESP32 kommen.
Einfacher Code und Debugging
In diesem Abschnitt erkläre ich dir anhand eines einfachen Codes, wie das Debuggen funktioniert. Das Projekt findest du im Repository von Berrybase. Der Quellcode belegt zwei Variablen mit zufälligen Zahlen, und eine Funktion summiert diese auf und gibt das Ergebnis zurück.
Hier ist der komplette Quellcode:
#include <Arduino.h>
// Function declarations:
int myFunction(int, int);
void setup() {
Serial.begin(DEBUG_BAUDRATE);
}
void loop() {
static int x, y = 0;
x = random(20);
y = random(50);
int result = myFunction(x, y);
Serial.println("Result: " + String(result));
delay(500);
}
// put function definitions here:
int myFunction(int x, int y) {
return x + y;
}
Code 1: Quellcode fürs Debuggen
Um das Debugging zu konfigurieren, müssen in der platformio.ini
Datei einige Einträge gemacht werden:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
upload_port = COM6
build_flags =
-DDEBUG_BAUDRATE=115200
debug_build_flags =
-O0
-g
-ggdb
debug_tool = esp-prog
debug_init_break = tbreak setup
Tabelle 3 erklärt im groben, was die Debugging Optionen machen, wobei in erster Linie die Debugging Option debug_tool wichtig ist. Dadurch wird der richtige Debugger und die Verbindung festgelegt, in diesem Fall der ESP-Prog. Allein mit dieser Option kann nun mit PlatformIO der Quellcode vom MicroController live debuggt werden.
Option | Beschreibung |
---|---|
debug_tool | Legt fest, welcher Debugger und welches Tool für das Debugging verwendet wird. |
debug_init_break | Ermöglicht das Setzen von Breakpoints in der Setup-Funktion, was besonders nützlich ist, um in der Initialisierungsphase zu debuggen. |
debug_build_flags | Enthält Einstellungen für den Build-Prozess während des Debuggens, wie z.B. O0 und ggdb , um die Sichtbarkeit aller Variablen zu gewährleisten. |
Als nächstes, damit man auch etwas während dem Debuggen sieht, müssen sogenannte Breakpoints im Quellcode gesetzt werden, siehe Abbildung 6. Das sind die kleinen roten Punkte, die neben der Zeilennummer im Quellcode angezeigt werden.
Vereinfacht gesagt, stoppt beim Debuggen der Quellcode an der Stelle und zeigt, sofern alles richtige konfiguriert wurde, alle Variablen und deren Inhalt. Ferner ist es möglich ab dem Breakpoint entweder in Einzelschritten, also Schritt für Schritt den Quellcode zu debuggen, also so wie der MicroController den Code abarbeiten würde oder direkt zum nächsten Breakpoint zu springen.
Das Ganze geht aber auf Kosten der Zeit, weil die interne Uhr vom MicroController nicht angehalten wird.
Nun soll der Quellcode auf den MicroController geladen und der Debugger gestartet werden. Ersteres würde man jetzt vermuten wird über den üblichen Upload-Button in der Fußzeile vermuten, siehe Abbildung 7.
Da jedoch der Debugger mitlaufen soll, bzw. der Quellcode an den Breakpoints halten soll, muss über das Menü Ausführen -> Debuggen starten bzw. F5, siehe Abbildung 8, der Code kompiliert und auf den MicroController geladen werden.
Direkt nach dem Start des Debuggings passieren gleich mehrere Sachen, siehe Abbildung 9. Zunächst sieht im Terminal alles danach aus, dass der Code normal kompiliert wird, wobei ein weiterer Reiter Debugging-Konsole aufgetaucht ist.
In diesem Fall wird der Code im sogenannten Debug-Modus kompiliert und dann über den ESP-Prog auf den MicroController übertragen. Direkt im Anschluss versucht sich der Debugger mit dem MicroController so zu verbinden, dass er auf den MicroController so Zugriff erlangt, um mitzuverfolgen, was gerade passiert. Die Meldungen in der Debugging-Konsole können an der Stelle erst einmal ignoriert werden, siehe Abbildung 10, da dieser erst einmal dazu dienen zu sehen, was aktuell gerade passiert.
Teilweise, kann es auch vorkommen, dass ein weiterer Dialog im Bereich der Debugging-Konsole erscheint, siehe Abbildung 11, was insofern nur bedeutet, dass PlatformIO gerade am Arbeiten ist, um Quellcode auf den MicroController zu laden und den ESP-Prog fürs Debugging zu starten.
Das ist alles nicht weiter schlimm und am Ende sollte der erste Breakpoint gelb hinterlegt sein, siehe Abbildung 12, da dieser erreicht wurde.
An der Stelle ist es nun möglich sich alle gespeicherten Werte in Variablen anzusehen, sofern diese schon angelegt oder global verfügbar sind, aber auch über Debuggingreiter, siehe Abbildung 13, auszuwählen, wie es weitergehen soll, wobei ich nicht auf alle Optionen eingehen werde. Wer schon mal Visual Studio oder ähnliche Programmierumgebungen verwendet hat, wird dies schon kennen.
Über den grünen Pfeil (F5) wird zum nächsten Breakpoint gesprungen, sobald diese Stelle aufgerufen wird. Über den blauen Pfeil der im Uhrzeigersinn zeigt (F10) wird ein sogenannter Prozedurschritt ausgeführt. Dabei wird nicht betrachtet was eine Anweisung im einzelnen macht, sondern im Fall vom ersten Breakpoint, wird zur nächsten Anweisung für die Variable „y“ übergegangen.
Mit dem blauen Pfeil der nach unten auf den Punkt zeigt (F11) wird ein sogenannter Einzelsprung durchgeführt. Hierbei wird jeder weitere einzelne Schritt gezeigt. Sollte dabei eine Funktion in unserem Fall der Variable „x“ einen Wert übergeben, wird in die Funktion gesprungen, um dort zu zeigen, was passiert.
Zuletzt möchte ich das rote Rechteck erwähnen (Umschalten + F5), welches das Debugging beendet.
Abschließende Worte
Für kleinere Programme ist das Debuggen oft nicht notwendig. Je komplexer ein Programm wird, desto eher treten jedoch Fehler auf, die gefunden werden müssen. Erster Anlaufpunkt ist natürlich die Auswertung von Kommentaren, die über den seriellen Monitor ausgegeben werden. Oft führt das allerdings nur bedingt zur Lösung.
Mit dem ESP-Prog und PlatformIO hast du eine hervorragende Möglichkeit, direkt in den Quellcode zu schauen und den Programmablauf Schritt für Schritt zu überwachen. So wirst du gezielt Fehler finden und beheben können.
Ob der ESP-Prog für dein Projekt wichtig ist, musst du selbst entscheiden – aber es bietet definitiv Vorteile bei der Fehlersuche. Bei größeren Projekten mit hunderten oder tausenden Zeilen Code nutze ich den ESP-Prog gerne, um zu überprüfen, ob alles so funktioniert, wie es soll.
Solltest du noch Fragen haben, hinterlasse mir einfach einen Kommentar!