... Fehlerliste auf. Dort listet es auch Fehler auf, die erst beim Bau des Programms auffallen, etwa fehlende Bibliotheken.
Fehler in der Logik treten allerdings erst beim Ablauf des Programms zutage. Die einfachste Möglichkeit, sie zu identifizieren, bieten Print-Ausgaben an entscheidenden Stellen im Code. Sie sehen dann, ob das Programm dort überhaupt vorbeikommt, und können die Werte von Variablen ausgeben. Dieses Vorgehen hat aber zwei gravierende Nachteile: Zum einen macht es erhebliche Mühe, zum anderen müssen Sie den Code anschließend noch bereinigen. Hier bietet sich der Einsatz des integrierten Debuggers des Pico an, der das Ausführen von Programmen auf Einzelschrittebene erlaubt.
Voraussetzungen
Damit das funktioniert, müssen Sie das Programm im Debug-Modus übersetzen und einen Steuerrechner (bei uns ein Ras- Pi) mit dem Pico verbinden. Außerdem kommt noch ein Hilfsprogramm ins Spiel, das zwischen Rechner und Pico vermittelt. Die Übersetzung im Debug-Modus schalten Sie wie im letzten Teil beschrieben in der Fußzeile von VSC an 1 1 .
Das Debugging übernimmt bei VSC ein Plugin, das bei der Installation mit auf dem Rechner gelandet ist. Da es sich bei C/C++-Entwicklung um das Brotund-Butter-Geschäft von Millionen von Entwicklern handelt, werden sowohl der Editor als auch die Plugins ständig weiterentwickelt. Aus diesem Grund lohnt sich ein regelmäßiges Update. Da das Installationsskript für VSC ein eigenes Repository hinzufügt, läuft dieses Update nicht anders als das jedes anderen Programms auch. Das Programmpaket für den Editor heißt dabei schlicht code. Das Update der Plugins erfolgt am Betriebssystem vorbei; je nach Einstellung übernimmt die IDE das selbst oder fragt nach.
Einstieg
Für das Debugging gibt es ganz links in der Leiste ein eigenes Icon 2 2 mit einem Dreieck plus Käfer (englisch: bug). Es symbolisiert das Abspielen eines Programms im Debug-Modus. Klicken Sie es an, wechselt die IDE in eine neue Ansicht 3 3 . Rechts verbleiben die Reiter mit dem Quellcode, in der Spalte links daneben finden Sie Daten zur aktuellen Debug-Session. Dazu gehören unter anderem die Variablen, die Register sowie die Haltepunkte.
Da VSC nicht wissen kann, ob Sie ein Programm auf dem RasPi oder dem Pico entwanzen wollen, stellen Sie das in der linken Spalte oben in der Ausklappliste neben dem grünen Dreieck ein. Praktischerweise legt der Projekt-Wizard die dafür notwendige Launch-Konfiguration automatisch an. Da es sich beim Prozessor auf dem Pico um eine Cortex-M0-CPU handelt, heißt sie Cortex Debug.
Ein Klick auf das grüne Dreieck startet anschließend das Debugging. Die IDE stößt zur Sicherheit einen Neubau des Programms an. Danach lädt es den Code auf den Pico und startet im Einzelschrittmodus. Durch die Low-Level-Initialisierung des Geräts müssen Sie sich nicht durchklicken, der Debugger bleibt aber automatisch am Anfang des Hauptprogramms (main()-Funktion) stehen 4 4 .
Langsam, aber sicher
Von jetzt an navigieren Sie mit den oberhalb des Quellcodes eingeblendeten Pfeiltasten 5 5 durch das Programm. Ganz links gibt es einen Reset-Knopf für den Pico, danach folgen in Blau die Ablauftasten. Über die Icons ganz rechts können Sie dagegen neu starten oder das Debugging komplett abbrechen.
Welche Aktionen die blauen Icons starten, lässt sich an ihrer Form erahnen. Das erste (Abspielen) startet einfach den Programmablauf ab der aktuellen Stelle. Das zweite (Einzelschritt) führt die aktuelle Zeile aus. Handelt es sich dabei um einen Funktionsaufruf, führt VSC ihn komplett aus, ohne in die Funktion hineinzuspringen. Das nächste Icon führt ebenfalls die aktuelle Zeile aus, verzweigt aber gegebenenfalls in eine Funktion, die Sie dann im Einzelschrittmodus im Detail untersuchen können. Mit dem vierten blauen Icon springen Sie aus einer Funktion heraus. Das beschleunigt den Debug-Prozess, wenn Sie etwa aus Versehen in eine Funktion hineingesprungen sind oder den interessanten Teil bereits durchlaufen haben.
Über das quadratische rote Icon verlassen Sie bei Bedarf den Einzelschrittmodus, das Programm läuft dann ungebremst weiter, allerdings nach wie vor im Debug-Modus. Zeitkritische Aktivitäten sind so nicht möglich.
Stoppschilder
Ein einfaches Weiterlaufen würde die Debug-Session praktisch beenden, denn der Prozessor arbeitet dann stur alle Befehle der Reihe nach in einer Endlosschleife ab. Das kann durchaus sinnvoll sein, aber in aller Regel möchten Sie noch irgendwo eingreifen. Deshalb stellen Sie vorher an geeigneter Stelle ein Stoppschild auf, im Englischen Breakpoint genannt.
VSC bezeichnet die Breakpoints in der deutschen Oberfläche als Haltepunkte.
Implizit existiert so ein Haltepunkt auch am Programmstart.
Neue Haltepunkte erstellen Sie durch einen Doppelklick auf die Zeilennummer der gewünschten Zeile, die VSC dann wie in Abbildung 6 6 mit einer roten Markierung verziert. Analog entfernen Sie den Breakpoint wieder. Alternativ nutzen Sie die Liste aller Haltepunkte in der linken Spalte, die Sie dazu eventuell erst aufklappen müssen. Dort können Sie die Breakpoints durch Entfernen des Hakens auch temporär deaktivieren.
TIPP
Die ersten beiden Teile der Pico-Serie finden Sie als PDF im Download-Bereich zu diesem Artikel.
Dateien zum Artikel herunterladen unter
www.raspi-geek.de/dl/46508
Läuft Ihr Programm nicht wie gewünscht, haben Sie in aller Regel einen Verdacht, woran das liegt. Um den Debug-Prozess abzukürzen, setzen Sie dann am Anfang der kritischen Funktion einen Haltepunkt, starten den Debugger und lassen ihn bis zum Haltepunkt weiterlaufen. So sparen Sie sich viele Klicks.
Variablen
Die IDE führt während der Ausführung eines Programms im Debug-Modus Buch. Dazu zählt vor allem die Aufrufliste, die den Pfad zum aktuellen Programmteil samt Parameter enthält. Die Liste der Variablen gibt ergänzend dazu den aktuellen Wert der lokalen und globalen Variablen wieder 7 7 . Das Schöne daran: Sie dürfen die Variablen jederzeit ändern.
Möchten Sie zum Beispiel Temperaturwerte unter null in Blau ausgeben, müssen Sie nicht auf einen Wintertag warten und beobachten, ob Ihr Programm richtig tickt. Einfacher klappt das mit einem Breakpoint nach dem Auslesen des Sensors. Anschließend überschreiben Sie den Messwert und lassen dann das Programm weiterlaufen.
Was nicht geht
Mit den hier beschriebenen Abläufen lassen sich viele Probleme lösen, allerdings nicht alle. Der Debugger von VSC hat noch einige Asse im Ärmel, die eventuell weiterhelfen. Über die linke Spalte können Sie sich zum Beispiel die Register oder bestimmte Speicherbereiche anzeigen lassen. Im Alltag benötigen Sie diese Funktionen aber eher selten.
Trotz der Mächtigkeit versagt der Debugger aber bei einer ganzen Klasse von Problemen. Alles, was mit der zeitlichen Abfolge von Ereignissen zu tun hat, kann er nicht lösen, denn der Messvorgang beeinflusst das Programm durch die extrem verlangsamte Ausführung massiv.
Initialisiert der Pico einen Sensor falsch, liegt das vielleicht daran, dass die MCU einfach zu schnell taktet und damit die Initialisierungsbefehle den Sensor in zu schneller Abfolge erreichen. Im Debug-Modus existiert dieses Problem jedoch faktisch nicht, der Fehler scheint einfach nicht vorhanden zu sein.
Da der Pico zwei CPU-Kerne hat, treten ähnliche Probleme auch bei Anwendungen auf, die beide Kerne nutzen. Die Koordination von zwei parallelen Programmteilen ist alles andere als trivial, und minimale Änderungen des zeitlichen Ablaufs führen oft zu einem ganz anderen Verhalten des Programms.
Fazit
Dieser Artikel konnte lediglich die Grundfunktionen des Debuggers von Visual Studio Code vorstellen. Möchten Sie tiefer in die Materie einsteigen, sollten Sie die gute Dokumentation lesen. Aber selbst mit den Basisfunktionen kommen Sie als Entwickler schon sehr weit.
Beim Autor hat sich inzwischen folgendes Vorgehen beim Programmieren für den Pico eingebürgert: Zuerst entsteht ein Prototyp auf dem Mikrocontroller mit Python – das geht schnell und dank der vielen Bibliotheken mit sehr wenig Code. Danach folgt falls notwendig die Umsetzung in C, ebenfalls auf dem Pico, weil dort die Entwicklung und das Debuggen so leichtfällt. Kapseln Sie dabei alle Pico-spezifischen Funktionen, ist die anschließende Portierung auf einen anderen Prozessor kein Hexenwerk mehr; im Idealfall genügen dann schon ein paar C-Makro-Definitionen. Dieser dritte Schritt kommt immer dann ins Spiel, wenn der Pico (auch von seinen physischen Maßen her) für den geplanten Einsatzzweck überdimensioniert ist.
Der vorliegende Artikel schließt unseren kleinen Workshop zur Pico-Programmierung ab. Aber der Pico hat natürlich noch mehr zu bieten, wie etwa sein PIO-Framework oder seine zwei Prozessoren. Diese Funktionen werden sicher bei dem ein oder anderen Projekt in der Zukunft eine Rolle spielen und dann im Zusammenhang mit dem Anwendungsfall hier ein Thema sein.
Haben Sie Gefallen an Visual Studio Code gefunden hat, sollten Sie einen Blick auf PlatformIO werfen. Dieses Plugin unterstützt viele verschiedene Mikrocontroller. Damit können Sie auch für diese die vielfältigen Funktionen einer modernen Entwicklungsumgebung nutzen. PlatformIO unterstützt seit Kurzem auch den Pico und nutzt dabei das Arduino-Framework. Das Portieren von Arduino-Code auf den Pico sollte damit noch leichter fallen als mit dem nativen Ansatz der Raspberry Pi Foundation.
(jlu)
Weitere Infos und interessante Links
www.raspi-geek.de/qr/46508