Tiefgehende Fehlersuche in Embedded Systems: SEGGER RTT und SystemView für FreeRTOS
Effektives Debugging und die Leistungsanalyse eingebetteter Systeme sind Eckpfeiler der Mikrocontroller-Entwicklung. Die Technologien SEGGER RTT (Real-Time Transfer) und SystemView bieten leistungsstarke Werkzeuge für diese Aufgaben. Sie ermöglichen Entwicklern, detaillierte Debug-Informationen zu erhalten und ein Echtzeitbetriebssystem (RTOS) wie FreeRTOS tiefgehend zu überwachen, ohne den Betrieb des Zielgeräts zu unterbrechen. Dieser Artikel beleuchtet die Funktionsprinzipien und praktischen Aspekte der Konfiguration von RTT Viewer für die Protokollausgabe und SystemView für die Visualisierung von RTOS-Ereignissen, was für die Diagnose komplexer Verhaltensmuster in eingebetteter Software von entscheidender Bedeutung ist.
Grundlagen des Debuggings eingebetteter Systeme und die Rolle von SEGGER RTT
Das Debugging eingebetteter Systeme erfordert spezialisierte Ansätze, die den Einfluss auf das Verhalten des Zielgeräts minimieren. Herkömmliche Methoden, wie das JTAG/SWD-Debugging mit Breakpoints, können unerwünschte Verzögerungen verursachen. Hier kommen Mechanismen wie DAP (Debug Access Port), ITM (Instrumentation Trace Macrocell) und RTT (Real-Time Transfer) ins Spiel.
- DAP (Debug Access Port): Ein Hardware-Block, der den Zugriff auf die Busse und den Kern des Mikrocontrollers für Debugging-Zwecke ermöglicht.
- ITM (Instrumentation Trace Macrocell): Ein spezialisierter Block in Cortex-M-Kernen (ab M3), konzipiert für die Hochgeschwindigkeitsausgabe von Debug-Nachrichten mit minimalem Zeitaufwand.
- RTT (Real-Time Transfer): Eine proprietäre Technologie von SEGGER, die einen Ringpuffer im RAM des Mikrocontrollers für den bidirektionalen Datenaustausch mit dem Host-Computer nutzt. Der Hauptvorteil von RTT ist seine Nicht-Intrusivität: Die CPU des Mikrocontrollers wird nicht angehalten, und Debug-Informationen werden mit sehr hoher Geschwindigkeit übertragen, was es ideal für die Echtzeit-Protokollausgabe (
printf) macht.
Um RTT in ein Projekt zu integrieren, müssen die Quellcodedateien der SEGGER RTT-Bibliothek hinzugefügt werden. Der Prozess ist nicht an eine bestimmte integrierte Entwicklungsumgebung (IDE) gebunden, sei es Keil uVision oder eine andere. Nach der Kompilierung und Ausführung sucht der J-Link-Debugger automatisch nach der RTT Control Block (CB)-Struktur im RAM des Mikrocontrollers. Dieser Block enthält einen Identifikator, die Anzahl der Kanäle und eine Beschreibung der Ringpuffer zum Lesen und Schreiben, was einen Einstiegspunkt für den Datenaustausch bietet. In den meisten Fällen erfolgt die Suche automatisiert, eine manuelle Adresskonfiguration ist jedoch ebenfalls möglich.
Beispiel für RTT-Verbindung und -Nutzung:
Einbinden von Header-Dateien:
#include <stdio.h>
#include "SEGGER_RTT.h"
Wrapper für typisierte Nachrichten (optional, zur Vereinfachung):
#define LOG_INFO(msg, ...) { SEGGER_RTT_TerminalOut(0, "INFO: "); SEGGER_RTT_printf(0, msg, ##__VA_ARGS__); }
#define LOG_ERR(msg, ...) { SEGGER_RTT_TerminalOut(0, "ERROR: "); SEGGER_RTT_printf(0, msg, ##__VA_ARGS__); }
void LOG_FLOAT(const char* prefix, float value, const char* suffix) {
char buf[64];
snprintf(buf, sizeof(buf), "%s%.2f%s", prefix, value, suffix);
SEGGER_RTT_TerminalOut(0, buf);
}
Initialisierung des Control Blocks und Ausgabe von Protokollen:
SEGGER_RTT_Init();
// ...
LOG_INFO("Central Heating: %s\r\n", Boiler.isCentralHeatingActive(response) ? "on" : "off");
LOG_ERR("Error: OpenTherm is not initialized");
Das Dienstprogramm RTT Viewer, das im J-Link-Treiberpaket enthalten ist, ermöglicht die Anzeige dieser Protokolle. Es unterstützt die Ausgabe von Informationen auf verschiedene Registerkarten (Terminals) und die Verwendung mehrerer RTT-Kanäle für eine fortgeschrittenere benutzerdefinierte Datenübertragung. Zu den Vorteilen von RTT gehören die Möglichkeit, printf über SWD auszugeben, ohne zusätzliche Mikrocontroller-Pins (z. B. SWO) zu verwenden, die Kompatibilität mit Cortex-M0/M0+, die einfache Einrichtung und eine sehr hohe Betriebsgeschwindigkeit im Vergleich zu anderen Methoden.
SystemView: Tiefgehende Echtzeit-RTOS-Leistungsanalyse
SystemView ist ein leistungsstarkes SEGGER-Tool zur Echtzeit-Analyse und Visualisierung des Betriebs eingebetteter Systeme, das RTT als Transportschicht nutzt. Es ermöglicht Entwicklern, ein tieferes Verständnis des FreeRTOS-Verhaltens zu erlangen, indem es Task-Wechsel, Interrupt-Behandlung und andere Systemereignisse verfolgt. Die Konfiguration von SystemView ist komplexer als die von RTT und umfasst mehrere wichtige Schritte:
- Quellcodedateien einbinden: Fügen Sie die erforderlichen SystemView-Dateien zu Ihrem Projekt hinzu.
- FreeRTOS-Konfiguration: SystemView funktioniert, indem es FreeRTOS-Trace-Makros abfängt, die sich an Schlüsselstellen im Kernel befinden (z. B. während der Task-Erstellung oder des Kontextwechsels). Um diesen Mechanismus in der Datei
FreeRTOSConfig.hzu aktivieren, müssen Sie:
* #define configUSE_TRACE_FACILITY 1 setzen.
* Für FreeRTOS V10+ #define INCLUDE_xTaskGetIdleTaskHandle 1 hinzufügen.
* Ganz am Ende der Datei FreeRTOSConfig.h SEGGER_SYSVIEW_FreeRTOS.h einbinden.
Beispiel-Trace-Makros:
```c
#define traceTASK_SWITCHED_IN() SEGGER_SYSVIEW_OnTaskStartExec((U32)pxCurrentTCB)
#define traceTASK_SWITCHED_OUT() SEGGER_SYSVIEW_OnTaskStopExec()
#define traceISR_ENTER() SEGGER_SYSVIEW_RecordEnterISR()
// etc.
```
- Verwendung von DWT_CYCCNT für präzises Timing: Cortex-M3/M4-Kerne enthalten ein integriertes DWT (Data Watchpoint and Trace)-Modul mit einem 32-Bit-Zähler (CYCCNT). SystemView verwendet diesen als hochpräzise Zeitreferenz. In der Funktion
SEGGER_SYSVIEW_Conf()müssen Sie diesen Zähler aktivieren:
```c
void SEGGER_SYSVIEW_Conf(void) {
// ---- Setup DWT (for Cortex-M3/M4) ----
#define DEMCR ((volatile U32)0xE000EDFCu)
#define DWT_CTRL ((volatile U32)0xE0001000u)
#define DWT_CYCCNT ((volatile U32)0xE0001004u)
#define DEMCR_TRCENA (1u << 24)
#define DWT_CTRL_CYCCNTENA (1u << 0)
DEMCR |= DEMCR_TRCENA; // Enable access to TRCENA
DWT_CYCCNT = 0; // Clear counter
DWT_CTRL |= DWT_CTRL_CYCCNTENA; // Start DWT count
SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
&SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
}
```
Stellen Sie außerdem sicher, dass das Makro SYSVIEW_RAM_BASE mit der RAM-Adresse Ihres Mikrocontrollers übereinstimmt.
- Interrupt Service Routine (ISR)-Behandlung: Im Gegensatz zum Task-Wechsel, den SystemView über FreeRTOS-Makros abfängt, erfordern Interrupts explizite Aufrufe. Sie müssen die Funktionen
SEGGER_SYSVIEW_RecordEnterISR()undSEGGER_SYSVIEW_RecordExitISR()zu Ihren Interrupt-Handlern hinzufügen:
```c
void EINT15_10_IRQHandler()
{
SEGGER_SYSVIEW_RecordEnterISR();
if(EINT->IPEND & EINT_IPEND_11) {
// Your code
}
SEGGER_SYSVIEW_RecordExitISR();
}
```
- Interrupts benennen: Für mehr Klarheit in SystemView müssen Sie dem Tool die Interrupt-Namen mitteilen, indem Sie die Funktion
_cbSendSystemDesc()(zu finden inSEGGER_SYSVIEW_Config_FreeRTOS.c) erweitern:
```c
static void _cbSendSystemDesc(void) {
SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",O=FreeRTOS");
SEGGER_SYSVIEW_SendSysDesc("I#15=SysTickIRQ");
SEGGER_SYSVIEW_SendSysDesc("I#46=ModbusIRQ");
//...
}
```
- Funktionen zum Abrufen von Interrupt-ID und Zeitstempel: Fügen Sie zwei Funktionen, die für den korrekten SystemView-Betrieb erforderlich sind, in
main(oder an einer anderen geeigneten Stelle) hinzu:
```c
// A function to get the number of the current active interrupt (ISR)
U32 SEGGER_SYSVIEW_X_GetInterruptId(void) {
// In the Cortex-M core, the interrupt number is stored in the lower 9 bits of the IPSR register.
return (((volatile U32)(0xE000ED04u)) & 0x1FFu);
}
// In Cortex-M3/M4, we use the DWT_CYCCNT core clock counter register
U32 SEGGER_SYSVIEW_X_GetTimestamp(void) {
return ((volatile U32)(0xE0001004u));
}
```
- Abschließende Initialisierung: Nach der Initialisierung der Hardware und Peripheriegeräte in der
main-Funktion rufen SieSEGGER_SYSVIEW_Conf()auf und starten dann den Task-SchedulervTaskStartScheduler():
```c
InitPhy();
SEGGER_SYSVIEW_Conf(); // Segger SystemView Initialization
CreateDeviceTasks();
vTaskStartScheduler(); // Start the real time scheduler
```
Nach erfolgreicher Konfiguration liefert das SystemView-Dienstprogramm eine detaillierte Visualisierung des Systemverhaltens. Einer der wertvollsten Vorteile von SystemView ist seine Fähigkeit, auch dann zu arbeiten, wenn der Ziel-Mikrocontroller nicht im Debug-Modus ist. Dies ermöglicht die Überwachung unter realen Betriebsbedingungen, wobei der J-Link bei Bedarf für die Diagnose angeschlossen wird, was die Identifizierung komplexer, zeitabhängiger Fehler erheblich vereinfacht.
Integration und Tool-Auswahl: RTT Viewer vs. SystemView
SEGGER RTT Viewer und SystemView sind komplementäre Tools, die jeweils spezifische Aufgaben in der Entwicklung eingebetteter Software adressieren. RTT Viewer ist ideal für die Ausgabe von Textprotokollen und Debug-Informationen, ersetzt das traditionelle printf und bietet dabei eine deutlich höhere Leistung und Nicht-Intrusivität. SystemView wiederum hebt die Analyse auf ein neues Niveau, indem es eine grafische Darstellung von FreeRTOS-Ereignissen wie Kontextwechseln, Task-Ausführung und Interrupt-Behandlung liefert, was für die Leistungsoptimierung und die Identifizierung von Scheduling-Problemen von entscheidender Bedeutung ist.
Die Wahl zwischen SEGGER_RTT_printf und SEGGER_SYSVIEW_Print (falls für Textnachrichten in SystemView verwendet) hängt vom Kontext ab: SEGGER_RTT_printf dient allgemeinen Protokollen, während SystemView-Funktionen für Ereignisse gedacht sind, die in die Analyse-Zeitleiste integriert werden müssen. Es ist wichtig zu beachten, dass SystemView einen eigenen internen RTT-Kanal für die Übertragung von Trace-Daten verwendet, der normalerweise nicht für die direkte Benutzerinteraktion vorgesehen ist. Obwohl SystemView auch ohne RTOS betrieben werden kann, ist seine Funktionalität stark eingeschränkt, da viele seiner Fähigkeiten auf Betriebssystem-Hooks angewiesen sind.
Die Verwendung von DWT_CYCCNT anstelle von SysTick für Zeitstempel in SystemView ist auf mehrere Faktoren zurückzuführen. DWT_CYCCNT ist ein dedizierter Hardware-Prozessorzykluszähler, der die höchstmögliche Genauigkeit bietet und unabhängig von den vom RTOS verwendeten System-Timer-Einstellungen ist. Dies stellt sicher, dass die Zeitstempel in SystemView so zuverlässig wie möglich sind und keinerlei Verzerrungen durch den Betrieb des Betriebssystems unterliegen.
Es existieren auch andere Tools für RTOS-Tracing und -Analyse, wie beispielsweise Tracealyzer von Percepio, die ebenfalls umfangreiche Funktionen zur Visualisierung und Analyse des Verhaltens eingebetteter Systeme bieten. SEGGER RTT und SystemView zeichnen sich jedoch durch ihre tiefe Integration in das J-Link-Ökosystem und ihre hohe Leistung aus, was sie zu bevorzugten Lösungen für Entwickler macht, die mit Cortex-M-Mikrocontrollern arbeiten.
Was wichtig ist:
- SEGGER RTT ermöglicht eine schnelle, nicht-intrusive Ausgabe von Debug-Protokollen (
printf) über einen Ringpuffer im RAM. - SystemView ist ein leistungsstarkes Tool zur Echtzeit-Visualisierung und -Analyse von FreeRTOS, das RTT als Transportschicht nutzt.
- Für eine genaue Zeitleiste stützt sich SystemView auf den Hardware-DWT_CYCCNT-Zähler (Cortex-M3/M4).
- Beide Tools vereinfachen die Diagnose komplexer Probleme erheblich, indem sie die Systemüberwachung ohne Anhalten der CPU ermöglichen.
- SystemView ermöglicht die Analyse des Systemverhaltens auch außerhalb des Debug-Modus, indem der J-Link bei Bedarf angeschlossen wird.
— Editorial Team
Noch keine Kommentare.