Depuración Avanzada de Sistemas Embebidos: SEGGER RTT y SystemView para FreeRTOS
La depuración efectiva y el análisis de rendimiento de los sistemas embebidos son pilares fundamentales en el desarrollo de microcontroladores. Las tecnologías SEGGER RTT (Real-Time Transfer) y SystemView ofrecen herramientas potentes para estas tareas, permitiendo a los desarrolladores obtener información de depuración detallada y realizar un monitoreo profundo de un sistema operativo en tiempo real (RTOS), como FreeRTOS, sin detener el funcionamiento del dispositivo objetivo. Este artículo explorará los principios de operación y los aspectos prácticos de la configuración de RTT Viewer para la salida de registros (logs) y SystemView para la visualización de eventos del RTOS, lo cual es de vital importancia para diagnosticar patrones de comportamiento complejos en el software embebido.
Fundamentos de la Depuración de Sistemas Embebidos y el Rol de SEGGER RTT
La depuración de sistemas embebidos exige enfoques especializados que minimicen el impacto en el comportamiento del dispositivo objetivo. Los métodos tradicionales, como la depuración JTAG/SWD con puntos de interrupción (breakpoints), pueden introducir retrasos indeseables. Aquí es donde mecanismos como DAP (Debug Access Port), ITM (Instrumentation Trace Macrocell) y RTT (Real-Time Transfer) acuden al rescate.
- DAP (Debug Access Port): Un bloque de hardware que proporciona acceso a los buses y al núcleo del microcontrolador para la depuración.
- ITM (Instrumentation Trace Macrocell): Un bloque especializado en los núcleos Cortex-M (a partir del M3), diseñado para la salida de mensajes de depuración a alta velocidad con una sobrecarga de tiempo mínima.
- RTT (Real-Time Transfer): Una tecnología propietaria de SEGGER que utiliza un búfer circular en la RAM del microcontrolador para el intercambio bidireccional de datos con el ordenador anfitrión. La ventaja clave de RTT es su no intrusividad: la CPU del microcontrolador no se detiene, y la información de depuración se transmite a velocidades muy altas, lo que lo hace ideal para la salida de registros en tiempo real (
printf).
Para integrar RTT en un proyecto, es necesario añadir los archivos fuente de la biblioteca SEGGER RTT. El proceso no está ligado a un Entorno de Desarrollo Integrado (IDE) específico, ya sea Keil uVision u otro. Después de la compilación y ejecución, el depurador J-Link busca automáticamente la estructura RTT Control Block (CB) en la RAM del microcontrolador. Este bloque contiene un identificador, el número de canales y una descripción de los búferes circulares para lectura y escritura, proporcionando un punto de entrada para el intercambio de datos. En la mayoría de los casos, la búsqueda es automatizada, pero la configuración manual de la dirección también es posible.
Ejemplo de conexión y uso de RTT:
Inclusión de archivos de cabecera:
#include <stdio.h>
#include "SEGGER_RTT.h"
Envolturas para mensajes tipados (opcional, por conveniencia):
#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);
}
Inicialización del Bloque de Control y salida de registros:
SEGGER_RTT_Init();
// ...
LOG_INFO("Central Heating: %s\r\n", Boiler.isCentralHeatingActive(response) ? "on" : "off");
LOG_ERR("Error: OpenTherm is not initialized");
La utilidad RTT Viewer, incluida en el paquete de controladores J-Link, permite visualizar estos registros. Soporta la salida de información a varias pestañas (terminales) y el uso de múltiples canales RTT para una transferencia de datos personalizada más avanzada. Las ventajas de RTT incluyen la capacidad de emitir printf a través de SWD sin usar pines adicionales del microcontrolador (por ejemplo, SWO), compatibilidad con Cortex-M0/M0+, facilidad de configuración y una velocidad de operación muy alta en comparación con otros métodos.
SystemView: Análisis Profundo del Rendimiento de RTOS en Tiempo Real
SystemView es una potente herramienta de SEGGER para analizar y visualizar el funcionamiento de sistemas embebidos en tiempo real, utilizando RTT como su capa de transporte. Permite a los desarrolladores obtener una comprensión más profunda del comportamiento de FreeRTOS al rastrear los cambios de tarea, el manejo de interrupciones y otros eventos del sistema. La configuración de SystemView es más compleja que la de RTT e implica varios pasos clave:
- Incluir archivos fuente: Añada los archivos de SystemView necesarios a su proyecto.
- Configuración de FreeRTOS: SystemView funciona interceptando las macros de traza de FreeRTOS, que se encuentran en puntos clave del kernel (por ejemplo, durante la creación de tareas o el cambio de contexto). Para activar este mecanismo en el archivo
FreeRTOSConfig.h, debe:
* Establecer #define configUSE_TRACE_FACILITY 1.
* Para FreeRTOS V10+, añada #define INCLUDE_xTaskGetIdleTaskHandle 1.
* Al final del archivo FreeRTOSConfig.h, incluya SEGGER_SYSVIEW_FreeRTOS.h.
Ejemplo de macros de traza:
```c
#define traceTASK_SWITCHED_IN() SEGGER_SYSVIEW_OnTaskStartExec((U32)pxCurrentTCB)
#define traceTASK_SWITCHED_OUT() SEGGER_SYSVIEW_OnTaskStopExec()
#define traceISR_ENTER() SEGGER_SYSVIEW_RecordEnterISR()
// etc.
```
- Uso de DWT_CYCCNT para una temporización precisa: Los núcleos Cortex-M3/M4 contienen un módulo DWT (Data Watchpoint and Trace) integrado con un contador de ciclos de 32 bits (CYCCNT). SystemView lo utiliza como referencia de tiempo de alta precisión. En la función
SEGGER_SYSVIEW_Conf(), debe activar este contador:
```c
void SEGGER_SYSVIEW_Conf(void) {
// ---- Configuración de DWT (para 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; // Habilitar acceso a TRCENA
DWT_CYCCNT = 0; // Limpiar contador
DWT_CTRL |= DWT_CTRL_CYCCNTENA; // Iniciar conteo DWT
SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
&SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
}
```
Además, asegúrese de que la macro SYSVIEW_RAM_BASE coincida con la dirección RAM de su microcontrolador.
- Manejo de Rutinas de Servicio de Interrupción (ISR): A diferencia del cambio de tareas, que SystemView intercepta a través de macros de FreeRTOS, las interrupciones requieren llamadas explícitas. Debe añadir las funciones
SEGGER_SYSVIEW_RecordEnterISR()ySEGGER_SYSVIEW_RecordExitISR()a sus manejadores de interrupción:
```c
void EINT15_10_IRQHandler()
{
SEGGER_SYSVIEW_RecordEnterISR();
if(EINT->IPEND & EINT_IPEND_11) {
// Su código
}
SEGGER_SYSVIEW_RecordExitISR();
}
```
- Nombrar interrupciones: Para mayor claridad en SystemView, debe informar a la herramienta los nombres de las interrupciones extendiendo la función
_cbSendSystemDesc()(que se encuentra enSEGGER_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");
//...
}
```
- Funciones para obtener ID de interrupción y marca de tiempo: Añada dos funciones necesarias para el correcto funcionamiento de SystemView a
main(o a otra ubicación conveniente):
```c
// Una función para obtener el número de la interrupción activa actual (ISR)
U32 SEGGER_SYSVIEW_X_GetInterruptId(void) {
// En el núcleo Cortex-M, el número de interrupción se almacena en los 9 bits inferiores del registro IPSR.
return (((volatile U32)(0xE000ED04u)) & 0x1FFu);
}
// En Cortex-M3/M4, usamos el registro contador de ciclos del núcleo DWT_CYCCNT
U32 SEGGER_SYSVIEW_X_GetTimestamp(void) {
return ((volatile U32)(0xE0001004u));
}
```
- Inicialización final: Después de inicializar el hardware y los periféricos en la función
main, llame aSEGGER_SYSVIEW_Conf(), y luego inicie el planificador de tareasvTaskStartScheduler():
```c
InitPhy();
SEGGER_SYSVIEW_Conf(); // Inicialización de Segger SystemView
CreateDeviceTasks();
vTaskStartScheduler(); // Iniciar el planificador en tiempo real
```
Tras una configuración exitosa, la utilidad SystemView proporcionará una visualización detallada del comportamiento del sistema. Una de las ventajas más valiosas de SystemView es su capacidad para operar incluso cuando el microcontrolador objetivo no está en modo de depuración. Esto permite el monitoreo en condiciones de operación reales, conectando J-Link según sea necesario para diagnósticos, lo que simplifica significativamente la identificación de errores complejos y dependientes del tiempo.
Integración y Selección de Herramientas: RTT Viewer vs. SystemView
SEGGER RTT Viewer y SystemView son herramientas complementarias, cada una abordando tareas específicas en el desarrollo de software embebido. RTT Viewer es ideal para la salida de registros de texto e información de depuración, reemplazando el tradicional printf mientras ofrece un rendimiento significativamente mayor y no intrusividad. SystemView, a su vez, eleva el análisis a un nuevo nivel al proporcionar una representación gráfica de eventos de FreeRTOS como cambios de contexto, ejecución de tareas y manejo de interrupciones, lo cual es de vital importancia para la optimización del rendimiento y la identificación de problemas de planificación.
La elección entre SEGGER_RTT_printf y SEGGER_SYSVIEW_Print (si se usa para mensajes de texto en SystemView) depende del contexto: SEGGER_RTT_printf es para registros generales, mientras que las funciones de SystemView son para eventos que necesitan ser integrados en la línea de tiempo del análisis. Es importante destacar que SystemView utiliza su propio canal RTT interno para la transmisión de datos de traza, que normalmente no está destinado a la interacción directa del usuario. Aunque SystemView puede operar sin un RTOS, su funcionalidad se verá severamente limitada, ya que muchas de sus capacidades dependen de los "hooks" del sistema operativo.
El uso de DWT_CYCCNT en lugar de SysTick para las marcas de tiempo en SystemView se debe a varios factores. DWT_CYCCNT es un contador de ciclos de procesador de hardware dedicado que proporciona la mayor precisión posible y es independiente de la configuración del temporizador del sistema utilizada por el RTOS. Esto asegura que las marcas de tiempo en SystemView sean lo más fiables posible y no estén sujetas a distorsiones debido al propio funcionamiento del sistema operativo.
Existen otras herramientas para el rastreo y análisis de RTOS, como Tracealyzer de Percepio, que también ofrecen una rica funcionalidad para visualizar y analizar el comportamiento de sistemas embebidos. Sin embargo, SEGGER RTT y SystemView destacan por su profunda integración con el ecosistema J-Link y su alto rendimiento, lo que las convierte en soluciones preferidas para desarrolladores que trabajan con microcontroladores Cortex-M.
Lo importante:
- SEGGER RTT proporciona una salida de registros de depuración (
printf) de alta velocidad y no intrusiva a través de un búfer circular en la RAM. - SystemView es una herramienta potente para la visualización y análisis en tiempo real de FreeRTOS, utilizando RTT como su transporte.
- Para una línea de tiempo precisa, SystemView se basa en el contador de hardware DWT_CYCCNT (Cortex-M3/M4).
- Ambas herramientas simplifican significativamente el diagnóstico de problemas complejos al permitir el monitoreo del sistema sin detener la CPU.
- SystemView permite el análisis del comportamiento del sistema incluso fuera del modo de depuración, conectando J-Link bajo demanda.
— Editorial Team
Aún no hay comentarios.