Dogłębne debugowanie systemów wbudowanych: SEGGER RTT i SystemView dla FreeRTOS
Efektywne debugowanie i analiza wydajności systemów wbudowanych to kamień węgielny w rozwoju mikrokontrolerów. Technologie SEGGER RTT (Real-Time Transfer) i SystemView oferują potężne narzędzia do tych zadań, umożliwiając deweloperom uzyskanie szczegółowych informacji debugowania i głębokie monitorowanie systemu operacyjnego czasu rzeczywistego (RTOS), takiego jak FreeRTOS, bez zatrzymywania pracy urządzenia docelowego. W tym artykule przyjrzymy się zasadom działania i praktycznym aspektom konfiguracji RTT Viewer do wyświetlania logów oraz SystemView do wizualizacji zdarzeń RTOS, co jest kluczowe dla diagnostyki złożonych wzorców zachowań oprogramowania wbudowanego.
Podstawy debugowania systemów wbudowanych i rola SEGGER RTT
Debugowanie systemów wbudowanych wymaga specjalistycznych podejść, które minimalizują wpływ na zachowanie urządzenia docelowego. Tradycyjne metody, takie jak debugowanie JTAG/SWD z punktami przerwania, mogą wprowadzać niepożądane opóźnienia. Tutaj z pomocą przychodzą mechanizmy takie jak DAP (Debug Access Port), ITM (Instrumentation Trace Macrocell) i RTT (Real-Time Transfer).
- DAP (Debug Access Port): Sprzętowy blok zapewniający dostęp do magistral i rdzenia mikrokontrolera w celu debugowania.
- ITM (Instrumentation Trace Macrocell): Wyspecjalizowany blok w rdzeniach Cortex-M (od M3), przeznaczony do szybkiego wyprowadzania komunikatów debugowania z minimalną stratą czasu.
- RTT (Real-Time Transfer): Opatentowana technologia firmy SEGGER, wykorzystująca bufor cykliczny w pamięci RAM mikrokontrolera do dwukierunkowej wymiany danych z komputerem hosta. Kluczową zaletą RTT jest nieinwazyjność: procesor mikrokontrolera nie jest zatrzymywany, a informacje debugowania są przesyłane z bardzo dużą prędkością, co czyni ją idealną do wyprowadzania logów (
printf) w czasie rzeczywistym.
Aby zintegrować RTT z projektem, należy dodać pliki źródłowe biblioteki SEGGER RTT. Proces ten nie jest związany z konkretnym środowiskiem programistycznym (IDE), czy to Keil uVision, czy innym. Po kompilacji i uruchomieniu, debugger J-Link automatycznie wyszukuje strukturę RTT Control Block (CB) w pamięci RAM mikrokontrolera. Blok ten zawiera identyfikator, liczbę kanałów oraz opis buforów cyklicznych do odczytu i zapisu, stanowiąc punkt wejścia do wymiany danych. W większości przypadków wyszukiwanie jest zautomatyzowane, ale możliwa jest również ręczna konfiguracja adresu.
Przykład podłączenia i użycia RTT:
Podłączenie plików nagłówkowych:
#include <stdio.h>
#include "SEGGER_RTT.h"
Funkcje pomocnicze dla typizowanych wiadomości (opcjonalnie, dla wygody):
#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);
}
Inicjalizacja Control Block i wyprowadzanie logów:
SEGGER_RTT_Init();
// ...
LOG_INFO("Central Heating: %s\r\n", Boiler.isCentralHeatingActive(response) ? "on" : "off");
LOG_ERR("Error: OpenTherm is not initialized");
Narzędzie RTT Viewer, będące częścią pakietu sterowników J-Link, umożliwia przeglądanie tych logów. Obsługuje ono wyświetlanie informacji na różnych zakładkach (terminalach) oraz wykorzystanie wielu kanałów RTT do bardziej zaawansowanego przesyłania danych użytkownika. Zalety RTT obejmują możliwość wyprowadzania printf przez SWD bez angażowania dodatkowych pinów mikrokontrolera (np. SWO), kompatybilność z Cortex-M0/M0+, prostotę konfiguracji i bardzo wysoką prędkość działania w porównaniu z innymi metodami.
SystemView: Szczegółowa analiza wydajności RTOS w czasie rzeczywistym
SystemView to potężne narzędzie SEGGER do analizy i wizualizacji pracy systemów wbudowanych w czasie rzeczywistym, które wykorzystuje RTT jako warstwę transportową. Pozwala ono deweloperom głębiej zrozumieć zachowanie FreeRTOS, śledząc przełączanie zadań, obsługę przerwań i inne zdarzenia systemowe. Konfiguracja SystemView jest bardziej złożona niż RTT i obejmuje kilka kluczowych kroków:
- Podłączenie plików źródłowych: Dodaj niezbędne pliki SystemView do projektu.
- Konfiguracja FreeRTOS: SystemView działa, przechwytując makra śledzenia FreeRTOS (trace-makra), które są umieszczone w kluczowych punktach jądra (np. podczas tworzenia zadania lub przełączania kontekstu). Aby aktywować ten mechanizm w pliku
FreeRTOSConfig.h, należy:
* Ustawić #define configUSE_TRACE_FACILITY 1.
* Dla FreeRTOS V10+ dodać #define INCLUDE_xTaskGetIdleTaskHandle 1.
* Na samym końcu pliku FreeRTOSConfig.h dołączyć SEGGER_SYSVIEW_FreeRTOS.h.
Przykład makr śledzenia:
```c
#define traceTASK_SWITCHED_IN() SEGGER_SYSVIEW_OnTaskStartExec((U32)pxCurrentTCB)
#define traceTASK_SWITCHED_OUT() SEGGER_SYSVIEW_OnTaskStopExec()
#define traceISR_ENTER() SEGGER_SYSVIEW_RecordEnterISR()
// itd.
```
- Użycie DWT_CYCCNT dla precyzyjnego pomiaru czasu: Rdzenie Cortex-M3/M4 zawierają wbudowany moduł DWT (Data Watchpoint and Trace) z 32-bitowym licznikiem cykli (CYCCNT). SystemView wykorzystuje go jako bardzo precyzyjne odniesienie czasowe. W funkcji
SEGGER_SYSVIEW_Conf()należy aktywować ten licznik:
```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);
}
```
Upewnij się również, że makro SYSVIEW_RAM_BASE odpowiada adresowi RAM twojego mikrokontrolera.
- Obsługa przerwań (ISR): W przeciwieństwie do przełączania zadań, które SystemView przechwytuje za pomocą makr FreeRTOS, przerwania wymagają jawnych wywołań. Do procedur obsługi przerwań należy dodać funkcje
SEGGER_SYSVIEW_RecordEnterISR()iSEGGER_SYSVIEW_RecordExitISR():
```c
void EINT15_10_IRQHandler()
{
SEGGER_SYSVIEW_RecordEnterISR();
if(EINT->IPEND & EINT_IPEND_11) {
// Twój kod
}
SEGGER_SYSVIEW_RecordExitISR();
}
```
- Nazywanie przerwań: Dla przejrzystości w SystemView należy poinformować narzędzie o nazwach przerwań, uzupełniając funkcję
_cbSendSystemDesc()(znajdującą się wSEGGER_SYSVIEW_Config_FreeRTOS.c):
```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");
//...
}
```
- Funkcje pobierania ID przerwania i znacznika czasu: Dodaj do
main(lub innego dogodnego miejsca) dwie funkcje, niezbędne do prawidłowego działania SystemView:
```c
// Funkcja do pobierania numeru aktualnie aktywnego przerwania (ISR)
U32 SEGGER_SYSVIEW_X_GetInterruptId(void) {
// W rdzeniu Cortex-M, numer przerwania jest przechowywany w dolnych 9 bitach rejestru IPSR.
return (((volatile U32)(0xE000ED04u)) & 0x1FFu);
}
// W Cortex-M3/M4 używamy rejestru licznika zegara rdzenia DWT_CYCCNT
U32 SEGGER_SYSVIEW_X_GetTimestamp(void) {
return ((volatile U32)(0xE0001004u));
}
```
- Końcowa inicjalizacja: Po inicjalizacji sprzętu i peryferiów w funkcji
mainwywołajSEGGER_SYSVIEW_Conf(), a następnie uruchom harmonogram zadańvTaskStartScheduler():
```c
InitPhy();
SEGGER_SYSVIEW_Conf(); // Segger SystemView Initialization
CreateDeviceTasks();
vTaskStartScheduler(); // Start the real time scheduler
```
Po pomyślnej konfiguracji narzędzie SystemView zapewni szczegółową wizualizację zachowania systemu. Jedną z najcenniejszych zalet SystemView jest jego zdolność do działania nawet wtedy, gdy docelowy mikrokontroler nie jest w trybie debugowania. Pozwala to na monitorowanie w rzeczywistych warunkach pracy, podłączając J-Link w razie potrzeby do diagnostyki, co znacznie upraszcza wykrywanie złożonych, zależnych od czasu błędów.
Integracja i wybór narzędzi: RTT Viewer kontra SystemView
SEGGER RTT Viewer i SystemView to narzędzia komplementarne, z których każde rozwiązuje swoje zadania w procesie rozwoju oprogramowania wbudowanego. RTT Viewer idealnie nadaje się do wyprowadzania logów tekstowych i informacji debugowania, zastępując tradycyjny printf i oferując przy tym znacznie wyższą wydajność oraz nieinwazyjność. SystemView z kolei podnosi analizę na nowy poziom, dostarczając graficzną reprezentację zdarzeń FreeRTOS, takich jak przełączanie kontekstu, wykonywanie zadań i obsługa przerwań, co jest krytyczne dla optymalizacji wydajności i wykrywania problemów z harmonogramowaniem.
Wybór między SEGGER_RTT_printf a SEGGER_SYSVIEW_Print (jeśli jest używany do wyprowadzania wiadomości tekstowych w SystemView) zależy od kontekstu: SEGGER_RTT_printf jest przeznaczony do ogólnych logów, natomiast funkcje SystemView – do zdarzeń, które mają być zintegrowane z osią czasu analizy. Ważne jest, aby zauważyć, że SystemView używa własnego wewnętrznego kanału RTT do przesyłania danych śledzenia, który zazwyczaj nie jest przeznaczony do bezpośredniej interakcji użytkownika. Chociaż SystemView może działać również bez RTOS, jego funkcjonalność będzie znacznie ograniczona, ponieważ wiele jego możliwości opiera się na hakach systemu operacyjnego.
Użycie DWT_CYCCNT zamiast SysTick dla znaczników czasu w SystemView wynika z kilku czynników. DWT_CYCCNT to dedykowany sprzętowy licznik cykli procesora, który zapewnia najwyższą możliwą precyzję i nie zależy od ustawień timera systemowego używanego przez RTOS. Gwarantuje to, że znaczniki czasu w SystemView będą maksymalnie wiarygodne i nie będą podatne na zniekształcenia spowodowane działaniem samego systemu operacyjnego.
Istnieją również inne narzędzia do śledzenia i analizy RTOS, takie jak Tracealyzer firmy Percepio, które również oferują bogatą funkcjonalność do wizualizacji i analizy zachowania systemów wbudowanych. Jednak SEGGER RTT i SystemView wyróżniają się głęboką integracją z ekosystemem J-Link i wysoką wydajnością, co czyni je jednymi z preferowanych rozwiązań dla deweloperów pracujących z mikrokontrolerami Cortex-M.
Co ważne:
- SEGGER RTT zapewnia szybkie, nieinwazyjne wyprowadzanie logów debugowania (
printf) poprzez bufor cykliczny w pamięci RAM. - SystemView to potężne narzędzie do wizualizacji i analizy FreeRTOS w czasie rzeczywistym, wykorzystujące RTT jako transport.
- Dla dokładnej osi czasu SystemView opiera się na sprzętowym liczniku DWT_CYCCNT (Cortex-M3/M4).
- Oba narzędzia znacznie upraszczają diagnostykę złożonych problemów, umożliwiając monitorowanie systemu bez zatrzymywania procesora.
- SystemView pozwala analizować zachowanie systemu nawet poza trybem debugowania, podłączając J-Link w razie potrzeby.
— Editorial Team
Brak komentarzy.