{"id":2154,"date":"2026-03-14T09:00:03","date_gmt":"2026-03-14T08:00:03","guid":{"rendered":"https:\/\/g7itchme.wordpress.com\/?p=2154"},"modified":"2026-03-14T09:00:03","modified_gmt":"2026-03-14T08:00:03","slug":"reihe-embedded-world-die-unsichtbaren-gehirne-verstehen-teil-10","status":"publish","type":"post","link":"https:\/\/technodidact.de\/en\/reihe-embedded-world-die-unsichtbaren-gehirne-verstehen-teil-10\/","title":{"rendered":"Reihe: Embedded World \u2013 Die unsichtbaren Gehirne verstehen (Teil 10)"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Debuggen im Verborgenen \u2013 Die Kunst, Unsichtbares sichtbar zu machen<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Von DerSchneider<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Einleitung: Die Suche im Nebel<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Stellen Sie sich vor, Sie schreiben ein Programm f\u00fcr Ihren PC. Es st\u00fcrzt ab. Sie haben einen Bildschirm, eine Tastatur, eine Maus. Sie k\u00f6nnen Breakpoints setzen, Variablen inspizieren, den Call-Stack durchsuchen. Der Computer selbst erz\u00e4hlt Ihnen, was falsch l\u00e4uft.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Stellen Sie sich jetzt vor, Sie programmieren einen Mikrocontroller in einer laufenden Maschine. Es gibt keinen Bildschirm, keine Tastatur, keine Maus. Das Programm l\u00e4uft \u2013 oder eben nicht. Aber es sagt Ihnen nichts. Es ist ein stummer, unsichtbarer Geist im Silizium, und Sie m\u00fcssen herausfinden, warum er sich nicht so verh\u00e4lt, wie Sie es wollen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das ist die Realit\u00e4t des Embedded-Debuggings. Es ist die Kunst, Unsichtbares sichtbar zu machen, mit begrenzten Mitteln aus winzigen Hinweisen die Ursache eines Fehlers zu erschlie\u00dfen. Dieser Artikel f\u00fchrt in diese Kunst ein. Wir lernen die Werkzeuge und Techniken kennen, mit denen Embedded-Entwickler ihre unsichtbaren Kollegen zum Reden bringen.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hauptteil<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. Die einfachste Methode: Serial over Debug<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Beginnen wir mit der einfachsten und zugleich m\u00e4chtigsten Debugging-Methode: der seriellen Ausgabe. Fast jeder Mikrocontroller hat eine UART-Schnittstelle. Schlie\u00dft man sie an einen USB-Seriell-Wandler an, kann man Nachrichten an den PC senden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">c<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">printf(\"Sensorwert: %d\\n\", wert);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Das ist das Embedded-\u00c4quivalent zu&nbsp;<code>System.out.println()<\/code>&nbsp;oder&nbsp;<code>console.log()<\/code>. Einfach, aber oft genial effektiv. Man sieht, welche Werte das Programm verarbeitet, welche Pfade es nimmt, wo es h\u00e4ngen bleibt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Grenzen: Es braucht die UART-Hardware, es beeinflusst das Timing (ein&nbsp;<code>printf<\/code>&nbsp;kann Tausende von Taktzyklen dauern) und es funktioniert nicht, wenn der Fehler genau in der Kommunikation liegt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Trotzdem: In mindestens 80 Prozent aller F\u00e4lle reicht die serielle Ausgabe, um einen Fehler zu finden. Sie ist das Schweizer Taschenmesser des Embedded-Debuggings.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. Die n\u00e4chste Stufe: LED-Debugging<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Was, wenn keine UART vorhanden ist oder die Schnittstelle selbst Fehler macht? Dann hilft die \u00e4lteste Debugging-Methode der Welt: die LED.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Man nehme eine LED, schlie\u00dfe sie an einen freien Pin an und lasse sie in bestimmten Situationen blinken:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">c<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><em>\/\/ Fehlerfall signalisieren<\/em>\nif (fehler) {\n    while(1) {\n        led_ein();\n        delay(100);\n        led_aus();\n        delay(100);\n    }\n}\n\n<em>\/\/ Programmfortschritt anzeigen<\/em>\nvoid funktion1() {\n    led_gruen_ein();\n    <em>\/\/ ... Arbeit ...<\/em>\n    led_gruen_aus();\n}\n\nvoid funktion2() {\n    led_rot_ein();\n    <em>\/\/ ... Arbeit ...<\/em>\n    led_rot_aus();\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die LED ist der Urvater aller Debugging-Werkzeuge. Sie ist immer da, kostet nichts und verr\u00e4t oft genug: L\u00e4uft das Programm \u00fcberhaupt? Kommt es in diese Schleife? Bleibt es an dieser Stelle h\u00e4ngen?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Manche Entwickler haben ganze Kodierungen entwickelt \u2013 zwei LEDs, die bin\u00e4r den Zustand anzeigen, oder eine LED, deren Blinkmuster eine Fehlernummer codiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>3. Der Profi: In-Circuit-Debugger (JTAG\/SWD)<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr ernsthafte Debugging-Arbeiten kommt man um einen Debugger nicht herum. Die meisten Mikrocontroller haben eine spezielle Debug-Schnittstelle \u2013 JTAG (Joint Test Action Group) oder SWD (Serial Wire Debug).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit einem Debugger kann man:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Das Programm anhalten (Breakpoints setzen)<\/li>\n\n\n\n<li>Variablen lesen und ver\u00e4ndern<\/li>\n\n\n\n<li>Den Call-Stack ansehen<\/li>\n\n\n\n<li>Das Programm Schritt f\u00fcr Schritt ausf\u00fchren<\/li>\n\n\n\n<li>Speicherbereiche inspizieren<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Das ist so, als h\u00e4tte der Mikrocontroller pl\u00f6tzlich einen Bildschirm und eine Tastatur. Man kann live hineinschauen, w\u00e4hrend das Programm l\u00e4uft \u2013 oder es genau dort anhalten, wo der Fehler auftritt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Hardware kostet wenig (ein ST-Link oder J-Link ist schon f\u00fcr unter 20 Euro zu haben), und die Entwicklungsumgebungen (Eclipse, VS Code mit entsprechenden Plugins) unterst\u00fctzen das hervorragend.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>4. Die Zeitmaschine: Der Logikanalysator<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Manche Fehler sind zeitkritisch. Ein Interrupt kommt zu sp\u00e4t, ein Signal ist zu kurz, zwei Ereignisse \u00fcberlappen sich unerwartet. Solche Fehler sieht man mit einem Debugger nicht, weil der das Programm anh\u00e4lt und damit das Timing zerst\u00f6rt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hier kommt der Logikanalysator ins Spiel. Er zeichnet digitale Signale \u00fcber die Zeit auf und zeigt sie als Wellenform an. Man sieht genau, wann welcher Pin seinen Zustand \u00e4ndert, wie lang Impulse sind, ob die zeitlichen Abl\u00e4ufe stimmen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein einfacher Logikanalysator (oft f\u00fcr unter 10 Euro als USB-Stick erh\u00e4ltlich) kann Wunder wirken:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ist der Taster wirklich entprellt?<\/li>\n\n\n\n<li>Kommt das SPI-Signal mit der richtigen Frequenz?<\/li>\n\n\n\n<li>Stimmen die Timing-Vorgaben des Datenblatts?<\/li>\n\n\n\n<li>\u00dcberschneiden sich zwei Interrupts unerwartet?<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Die aufgezeichneten Signale l\u00fcgen nicht. Sie zeigen die physikalische Realit\u00e4t, nicht die Programm-Logik.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>5. Das Fenster in die Vergangenheit: Der Oszilloskop<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wo der Logikanalysator nur digitale Signale (HIGH\/LOW) kennt, zeigt das Oszilloskop die tats\u00e4chlichen Spannungsverl\u00e4ufe. Das ist wichtig, wenn es um analoge Probleme geht:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Rauschen auf der Stromversorgung<\/li>\n\n\n\n<li>\u00dcberschwinger auf Signalleitungen<\/li>\n\n\n\n<li>Langsame Anstiegszeiten<\/li>\n\n\n\n<li>Fehlerhafte Pegel<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Oszilloskop ist teurer und komplexer als ein Logikanalysator, aber f\u00fcr bestimmte Probleme unersetzlich.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>6. Die Kunst des Printf, wenn kein Printf geht<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Oft hat man keine UART frei oder die Ausgabe st\u00f6rt das Timing zu sehr. Dann muss man kreativ werden:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Ringspeicher im RAM:<\/strong>&nbsp;Man legt einen Puffer im RAM an und schreibt Debug-Informationen hinein. Wenn das Programm anh\u00e4lt (oder gezielt gestoppt wird), liest man den Puffer aus.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">c<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#define DEBUG_SIZE 100\ntypedef struct {\n    unsigned long time;\n    int event;\n    int value;\n} debug_entry_t;\n\ndebug_entry_t debug_buffer[DEBUG_SIZE];\nint debug_index = 0;\n\nvoid debug_log(int event, int value) {\n    debug_entry_t *e = &amp;debug_buffer[debug_index];\n    e-&gt;time = millis();\n    e-&gt;event = event;\n    e-&gt;value = value;\n    debug_index = (debug_index + 1) % DEBUG_SIZE;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nach einem Absturz kann man den Puffer \u00fcber den Debugger auslesen und sieht, was vor dem Absturz passiert ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>GPIO als Logikanalysator:<\/strong>&nbsp;Man nutzt einen freien Pin, setzt ihn vor wichtigen Aktionen und l\u00f6scht ihn danach. Mit einem Logikanalysator kann man dann die Dauer und Reihenfolge der Aktionen messen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>7. Der Klassiker: Heisenbugs<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die fiesesten Fehler in Embedded Systems sind die, die verschwinden, wenn man sie sucht \u2013 sogenannte Heisenbugs (nach Werner Heisenberg, der zeigte, dass Messung das Gemessene ver\u00e4ndert).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Klassische Beispiele:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ein Fehler tritt nur auf, wenn der Debugger\u00a0<em>nicht<\/em>\u00a0angeschlossen ist.<\/li>\n\n\n\n<li>Ein Fehler verschwindet, sobald man eine LED zur Anzeige einbaut.<\/li>\n\n\n\n<li>Ein Fehler tritt nur auf, wenn das Programm im Release-Modus l\u00e4uft, nicht im Debug-Modus.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Die Ursache ist fast immer ein Timing-Problem. Der Debugger verlangsamt das Programm, die LED-Ausgabe dauert ihre Zeit, der Release-Modus optimiert Code anders. Pl\u00f6tzlich sind die zeitlichen Bedingungen andere, und der Fehler zeigt sich nicht mehr.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die L\u00f6sung: So nah wie m\u00f6glich an der Realit\u00e4t debuggen. Logikanalysator statt Printf, Ringspeicher statt serielle Ausgabe, genaue Analyse der Timing-Anforderungen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>8. Fallstricke und typische Fehler<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Erfahrung zeigt: Bestimmte Fehler treten immer wieder auf. Eine kleine Ph\u00e4nomenologie:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Vergessene Initialisierung:<\/strong>&nbsp;Ein Timer l\u00e4uft nicht, weil das entsprechende Register nie gesetzt wurde. Das Programm wartet ewig auf ein Ereignis.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Falsche Register:<\/strong>&nbsp;Man schreibt ins falsche Register oder verwechselt die Bitpositionen. Der Pin tut nicht, was er soll.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Interrupt-Konflikte:<\/strong>&nbsp;Zwei Interrupts st\u00f6ren sich gegenseitig. Ein niederpriorer Interrupt wird nie bedient, weil ein hochpriorer dauernd kommt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Stack-Overflow:<\/strong>&nbsp;Der Stack w\u00e4chst in den Variablenbereich (oder umgekehrt). Das Programm zeigt merkw\u00fcrdiges, scheinbar zuf\u00e4lliges Verhalten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Race Conditions:<\/strong>&nbsp;Zwei Tasks greifen gleichzeitig auf dieselbe Variable zu. Mal geht&#8217;s gut, mal nicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Optimierungsfallen:<\/strong>&nbsp;Der Compiler optimiert Code weg, den er f\u00fcr \u00fcberfl\u00fcssig h\u00e4lt (z.B. Zugriffe auf Hardware-Register, die er nicht als solche erkennt). Das Schl\u00fcsselwort&nbsp;<code>volatile<\/code>&nbsp;ist oft die L\u00f6sung.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>9. Ein Praxisbeispiel: Der flackernde Taster<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Erinnern Sie sich an das Taster-Beispiel aus Artikel 3? Der Taster prellt, und wenn man nicht entprellt, flackert die LED.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das Debugging mit verschiedenen Methoden:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>LED-Debugging:<\/strong>\u00a0Man l\u00e4sst eine LED parallel zum Taster leuchten. Sie flackert \u2013 das zeigt das Prellen.<\/li>\n\n\n\n<li><strong>Logikanalysator:<\/strong>\u00a0Man schlie\u00dft den Analysator an den Taster-Pin. Das Bild zeigt mehrere Impulse in wenigen Millisekunden.<\/li>\n\n\n\n<li><strong>Software-Entprellung:<\/strong>\u00a0Man implementiert eine einfache Entprellung und pr\u00fcft mit dem Logikanalysator, ob das Prellen verschwunden ist.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Jede Methode hat ihren Beitrag geleistet, und zusammen ergeben sie ein vollst\u00e4ndiges Bild.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>10. Pr\u00e4vention ist besser als Debugging<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die beste Debugging-Strategie ist, Fehler gar nicht erst zu machen. Einige Grundregeln:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Defensive Programmierung:<\/strong>\u00a0Immer Pr\u00fcfungen einbauen, auf NULL-Zeiger testen, Bereichs\u00fcberschreitungen vermeiden.<\/li>\n\n\n\n<li><strong>Assertions:<\/strong>\u00a0An kritischen Stellen Bedingungen pr\u00fcfen und bei Verletzung Alarm schlagen.<\/li>\n\n\n\n<li><strong>Code-Reviews:<\/strong>\u00a0Ein zweites Paar Augen sieht oft, was man selbst \u00fcbersehen hat.<\/li>\n\n\n\n<li><strong>Modulare Tests:<\/strong>\u00a0Jedes Modul einzeln testen, bevor man es integriert.<\/li>\n\n\n\n<li><strong>Versionskontrolle:<\/strong>\u00a0Immer wissen, was sich ge\u00e4ndert hat.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Trotzdem: Fehler werden passieren. Die Kunst ist, sie systematisch zu finden \u2013 nicht durch wildes Herumprobieren, sondern durch methodisches Vorgehen mit den richtigen Werkzeugen.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fazit und Ausblick<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Debuggen in Embedded Systems ist eine Detektivarbeit. Die Spuren sind oft klein, die Zeugen schweigen, und der T\u00e4ter ist unsichtbar. Aber mit den richtigen Werkzeugen \u2013 von der einfachen LED \u00fcber den Debugger bis zum Logikanalysator \u2013 und einer methodischen Vorgehensweise lassen sich auch die hartn\u00e4ckigsten Fehler finden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wir haben die Werkzeuge kennengelernt. Aber Werkzeuge allein gen\u00fcgen nicht. Man muss auch wissen, wo die besonderen Gefahren lauern \u2013 gerade in sicherheitskritischen Systemen, wo ein Fehler nicht nur \u00e4rgerlich, sondern lebensbedrohlich sein kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit diesem Thema \u2013 der Sicherheit in Embedded Systems \u2013 besch\u00e4ftigen wir uns im n\u00e4chsten Artikel.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Debuggen im Verborgenen \u2013 Die Kunst, Unsichtbares sichtbar zu machen Von DerSchneider Einleitung: Die Suche im Nebel Stellen Sie sich vor, Sie schreiben ein Programm f\u00fcr Ihren PC. Es st\u00fcrzt ab. Sie haben einen Bildschirm, eine Tastatur, eine Maus. Sie k\u00f6nnen Breakpoints setzen, Variablen inspizieren, den Call-Stack durchsuchen. Der Computer selbst erz\u00e4hlt Ihnen, was falsch [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[46,26],"tags":[2069],"class_list":["post-2154","post","type-post","status-publish","format-standard","hentry","category-industrie-4-0","category-mit-den-handen","tag-embedded-world"],"_links":{"self":[{"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/posts\/2154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/comments?post=2154"}],"version-history":[{"count":0,"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/posts\/2154\/revisions"}],"wp:attachment":[{"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/media?parent=2154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/categories?post=2154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/technodidact.de\/en\/wp-json\/wp\/v2\/tags?post=2154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}