Der Applikation auf die Finger geschaut Software-Debugging auf ARM-Cortex-M3/M4-basierten Bausteinen

Sie wissen hoffentlich genau, was die Software in Ihrem Mikrocontroller erledigen soll. Wenn Sie sich aber fragen, warum sie nicht wie gewünscht arbeitet und was sie eigentlich innerhalb der MCU macht, dann sind Sie nicht alleine. Die Techniken, die ARM unter dem Namen "CoreSight" zusammenfasst, eröffnen vielseitige Einsicht- und Einflussmöglichkeiten auf das Innenleben der Controller.

Vielleicht haben Sie eine asynchrone Applikation geschrieben, die ein Multitasking-Betriebssystem und ereignisgesteuerte Interrupts nutzt. Dies macht Debugging-Praktiken wie printf-Instrumentierung oder das Setzen von Breakpoints und das Durchlaufen der Applikation in Einzelschritten nicht nur ermüdend und ineffizient, es ist auch wahrscheinlich, dass komplexe Timing-Probleme übersehen werden, da der Core ständig angehalten wird.

Falls der Baustein für Ihr nächstes Projekt auf einem Cortex-M3- oder -M4-Core von ARM basiert, wird es einfach: Leistungsfähige Debug-Logik ist hier bereits integriert. Ein guter Debugger nutzt dann diese Logik und untersucht das Applikationsverhalten aus verschiedenen Blickwinkeln.

ARM-Cortex-M3-/M4-Debug-Architektur

Die Debug-Architektur besteht aus fünf wesentlichen Elementen (Bild 1). Einige davon, wie die Embedded Trace Macrocell (ETM), sind optional und nur in einigen Bausteinen mit implementiert. Wir konzentrieren uns hier auf die Instrumentation Trace Macrocell (ITM), Data Watchpoint und Trace (DWT) sowie ETM, und wie ein Debugger diese nutzt. Zuerst aber muss noch ein wichtiges Konzept für das gesamte ARM-Cortex-M-Debugging erwähnt werden: Serial Wire Debug (SWD), eine der zur Verfügung stehenden Debug-Schnittstellen.

Während die JTAG-Schnittstelle ursprünglich für Testzwecke entwickelt wurde, ist SWD von Grund auf als kostengünstige Debug-Schnittstelle erstellt worden, um JTAG zu ersetzen und dem Anwender eine bessere Kontrolle und mehr Leistungsmerkmale zu geben. SWD verwendet nur zwei Anschlüsse, die den JTAG-Pins überlagert sind. Damit sind auf dem Chip keine zusätzlichen Pins erforderlich, um SWD-Zugriff zu ermöglichen. Bei Bausteinen mit wenigen Anschlüssen ist dies ein Vorteil. Eine SWD-Debug-Probe ist erforderlich, um diesen Debug-Modus zu nutzen. Die meisten JTAG-Probes für ARM-Cores sind aber zum SWD-Port kompatibel.

Serial Wire Output (SWO) ist ein Highspeed-Kanal, der Datenpakete von der ITM zum Debugger überträgt, ohne dabei die Ausführung im Core anzuhalten. SWO verwendet einen seriellen UART oder Manchester-Codierung und bietet zusammen mit ITM und DWT äußerst nützliche Funktionen. SWO erfordert SWD als Debug-Modus und kann nicht im JTAG-Modus verwendet werden.

Instrumentation Trace Macrocell

Die ITM ist ein zentraler Teil der Debug-Logik in den ARM-Cortex-M3/M4-Cores. Es ist ein einfacher Trace, der ausgewählte Trace-Daten über einen Lowspeed-Zugriffsport bereitstellt. Eine separate Trace-Probe ist dabei nicht erforderlich; die meisten SWD-Probes können die Trace-Funktion innerhalb der ITM verwenden.

Infokasten: ETM - Der "On-Chip-Emulator"
Die Embedded Trace Makrocell, die in vielen Cortex-M3- und -M4-Mikrocontrollern implementiert ist, ersetzt den Funktionsumfang, den früher ein kompletter In-Circuit-Emulator inklusive Bond-out-Chip bot. Die aufwendigen Adapter, die ein In-Circuit-Emulator benötigt, werden durch standardisierte Cortex-Debug-Anschlüsse ersetzt, die mit preisgünstigen Miniatursteckverbindern im 0,05-Zoll-Raster verbunden werden.

Die DWT-Einheit (Data Watchpoint and Trace), die auch das Wort "Trace" im Namen führt, zeichnet nur die Zugriffe auf Variablen auf. Erst mit der ETM gelingt die lückenlose Aufzeichnung aller Befehle, die der Controller-Kern ausgeführt hat. Allerdings ist das Datenaufkommen sehr hoch. Ein Debug-Adapter wie der ULINKpro von Keil nimmt diese Datenflut über die Serial-Wire-Schnittstelle auf, die im "Manchester"-Modus mit 100 Mbit/s betrieben wird. Zum Entwicklungs-PC hin werden diese Daten komprimiert auf 25 Mbit/s über USB weitergereicht und im Debugger in Echtzeit dargestellt.

Mit diesem "Streaming Trace" werden sämtliche Befehle, die der Controller ausführt, aufgezeichnet, und es lässt sich genau verfolgen, welche Verzweigungen des Programms durchlaufen wurden und ob es ggf. "abgestorbene Äste" mit nicht durchlaufenen Code-Segmenten gibt. Auch die Zeitanalyse, die sich aus der Aufzeichnung ergibt, leistet eine wichtige Hilfestellung bei der Performance-Optimierung des Codes.
Der "On-Chip-Emulator"

Was ist nun ein einfacher Trace? Die ITM selbst bietet 32 Kanäle für Software-Trace, die von der Software verwendet werden können, um Datenpakete für die ITM zur Verteilung an den Debugger (über SWO) zu generieren. Dies dient zur Instrumentierung des Codes mit sehr geringem Overhead, da der Core nicht angehalten werden muss, um die Nachricht oder Daten auszugeben. Dazu ist nur ein einziger Schreibbefehl an eines der 32 ITM-Stimulus-Register erforderlich.

Die ITM verwaltet auch Trace-Events, die durch eine andere Einheit aufgerufen werden, die DWT. Die Rolle der ITM besteht in diesem Fall in der Formatierung dieser Events und deren Paketierung. Optional kann jedes Paket auch mit einem Zeitstempel versehen und versendet werden.

DWT (Data Watchpoint und Trace) bietet mehrere Funktionen, die Informationen von den Systembussen sammeln. Die DWT-Einheit generiert Events für die ITM zur Paketierung, die Zeitstempel und Events zur weiteren Verteilung auf dem SWO-Kanal.

DWT bietet vier unabhängige Komparatoren oder Watchpoints, die bei einer Adress- oder Datenübereinstimmung ein Event auslösen. Sie lassen sich für verschiedene Zwecke nutzen, einschließlich dem Triggern der ETM, eines ITM-Pakets oder zur Unterbrechung des Codes bei bestimmten Bedingungen.