Volver al inicio

RTT CLI para Cortex-M vía J-Link SWD

El artículo describe la integración de shell CLI vía J-Link RTT en ARM Cortex-M. Se proporciona código de inicialización, procesamiento de comandos y envío de respuestas. Se discute configuración de Viewer, acceso TCP y comparación con UART.

CLI vía RTT: shell SWD para ARM sin UART
Advertisement 728x90

Configuración de una Shell CLI mediante J-Link RTT para ARM Cortex-M

Para implementar una CLI sobre SWD sin UART, utiliza la biblioteca SEGGER_RTT. Descarga los archivos fuente: SEGGER_RTT.h (API, 253 líneas), SEGGER_RTT.c (implementación, 1751 líneas), SEGGER_RTT_printf.c (printf, 516 líneas), SEGGER_RTT_Conf.h (configuración, 333 líneas).

Comienza inicializando el canal RTT cero:

void SeggerInit() {
    SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
    SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);    
    SEGGER_RTT_SetTerminal(0); 
}

bool segger_rtt_init_custom(void) {
    bool res = true;
    SeggerInit();
    return res;
}

Llama a SeggerInit() al inicio del firmware para configurar los búferes de transmisión y recepción no bloqueantes.

Google AdInline article slot

Procesamiento de Comandos Entrantes

Consulta periódicamente el canal mediante SEGGER_RTT_Read en el bucle principal o un temporizador:

bool segger_rtt_proc_one(uint8_t num) {
    bool res = false;
    LOG_PARN(SEGGER_RTT, "RTT%u,Proc", num);
    SeggerRttHandle_t* Node = SeggerRttGetNode(num);
    if(Node) {
        if(Node->RxBuffer) {
            if(Node->buffer_size) {
                unsigned rx_byte = SEGGER_RTT_Read(Node->BufferIndex, 
                                                   Node->RxBuffer, 
                                                   Node->buffer_size);
                if(rx_byte) {
                    res = segger_rtt_writer(num);
                    LOG_DEBUG(SEGGER_RTT,"RxData:[%s]=[%s],rxByteCnt:%u Bytes", 
                              ArrayToStr(Node->RxBuffer,rx_byte), 
                              ArrayToAsciiStr(Node->RxBuffer,rx_byte), 
                              rx_byte);
                    res = cli_process_data(Node->cli_num, 
                                           Node->RxBuffer, 
                                           rx_byte);
                    memset(Node->RxBuffer, 0, rx_byte);
                }
            }
        }
    }
    return res;
}

La función devuelve el número de bytes recibidos. Pasa los datos al manejador CLI: cli_process_data().

Envío de Respuestas desde el Firmware

Para transmitir cadenas, usa SEGGER_RTT_Write. Implementa funciones para putc/puts y un búfer FIFO:

Google AdInline article slot
void segger_rtt1_puts(void* stream_ptr, const char* str, int32_t len) {
    SeggerRttHandle_t* Node = SeggerRttGetNode(1);
    if(Node) {
        if(str) {
            if(len) {
                unsigned tx_cnt = SEGGER_RTT_Write(Node->BufferIndex,
                                                   (void* )  str,
                                                   (unsigned) len);
                (void)tx_cnt;
            }
        }
    }
}

void segger_rtt1_putc(void* stream_ptr, char ch) {
    SeggerRttHandle_t* Node = SeggerRttGetNode(1);
    if(Node) {
        unsigned tx_cnt = SEGGER_RTT_Write(Node->BufferIndex,
                                           (void* )  &ch,
                                           (unsigned)  1);
        (void)tx_cnt;
    }
}

Extrae datos del FIFO Tx y escríbelos en el canal RTT. Esto asegura transmisión asíncrona sin pérdida de datos.

  • Ventajas del FIFO: El almacenamiento en búfer evita desbordamientos durante picos de carga.
  • Monitoreo: Registra tx_cnt para depurar transmisiones perdidas.
  • Escalabilidad: Soporte para múltiples canales (num > 0).

Configuración de J-Link RTT Viewer en PC

Instala el paquete SEGGER J-Link. Ejecuta JLinkRTTViewer.exe desde C:\Program Files\SEGGER\JLink_V834.

Configura la conexión:

Google AdInline article slot
  • Selecciona SWD o JTAG.
  • Especifica el dispositivo objetivo (ARM Cortex-M).
  • Establece la velocidad (hasta megahercios).
  • Confirma la conexión.

Introduce comandos en Terminal 0 — soporta resaltado de colores. Si el FIFO se desborda, edita SEGGER_RTT_Conf.h para aumentar los tamaños de búfer.

Acceso Alternativo mediante TCP

RTT Viewer abre un socket en 127.0.0.1:19021 (verifica con netstat -ano | grep 19021).

Conéctate usando PuTTY o Tera Term:

  • Host: 19021
  • Tipo: TCP

Esto emula una terminal UART. Funciona de forma remota a través de una red WiFi.

Ventajas y Limitaciones de la CLI RTT

Ventajas:

  • Operación paralela con depuración paso a paso.
  • No requiere archivo ELF: flashea y pasa a J-Link.
  • Transmisión instantánea a velocidades SWD.
  • Copia y pega registros con resaltado.
  • Múltiples terminales.

Desventajas:

  • Dependencia de J-Link (no para AVR/ESP32/RISC-V).
  • Desconexión al reiniciar el MCU — requiere reconexión manual.
  • Ventana de entrada separada (resuelto mediante TCP).
  • Sin soporte para \r en Viewer (disponible en Tera Term).

| Aspecto | RTT vía SWD | UART |

|--------|-------------|------|

| Velocidad | MHz SWD | 115200+ |

| Pines | 3-4 | 2+ |

| Depuración | Paralela | No |

| Reinicio | Desconexión | Estable |

Puntos Clave

  • Inicializa RTT antes de main() para registro temprano.
  • Usa NO_BLOCK_SKIP para evitar bloqueos.
  • Monitorea desbordamiento FIFO mediante registros tx/rx_cnt.
  • TCP 19021 resuelve problemas del Viewer de interfaz.
  • Adecuado para Cortex-M con soporte J-Link.

— Editorial Team

Advertisement 728x90

Leer después