홈으로 돌아가기

J-Link SWD를 통한 Cortex-M용 RTT CLI

이 기사는 ARM Cortex-M에서 J-Link RTT를 통한 CLI 셸 통합을 설명합니다. 초기화 코드, 명령 처리 및 응답 전송이 제공됩니다. Viewer 설정, TCP 액세스, UART와의 비교가 논의됩니다.

RTT를 통한 CLI: UART 없는 ARM용 SWD 셸
Advertisement 728x90

ARM Cortex-M용 J-Link RTT를 통한 CLI 셸 설정하기

UART 없이 SWD를 통해 CLI를 구현하려면 SEGGER_RTT 라이브러리를 사용하세요. 소스 파일을 다운로드하세요: SEGGER_RTT.h (API, 253줄), SEGGER_RTT.c (구현, 1751줄), SEGGER_RTT_printf.c (printf, 516줄), SEGGER_RTT_Conf.h (설정, 333줄).

제로 RTT 채널 초기화부터 시작하세요:

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;
}

펌웨어 시작 시 SeggerInit()을 호출하여 논블로킹 송수신 버퍼를 구성하세요.

Google AdInline article slot

들어오는 명령 처리하기

메인 루프나 타이머에서 SEGGER_RTT_Read를 통해 채널을 주기적으로 폴링하세요:

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;
}

함수는 수신된 바이트 수를 반환합니다. 데이터를 CLI 핸들러에 전달하세요: cli_process_data().

펌웨어에서 응답 전송하기

문자열을 전송하려면 SEGGER_RTT_Write를 사용하세요. putc/puts 및 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;
    }
}

Tx FIFO에서 데이터를 추출하여 RTT 채널에 기록하세요. 이렇게 하면 데이터 손실 없이 비동기 전송이 보장됩니다.

  • FIFO 장점: 버퍼링으로 피크 부하 시 오버플로를 방지합니다.
  • 모니터링: tx_cnt를 로깅하여 누락된 전송을 디버깅하세요.
  • 확장성: 다중 채널 지원 (num > 0).

PC에서 J-Link RTT 뷰어 구성하기

SEGGER J-Link 패키지를 설치하세요. C:\Program Files\SEGGER\JLink_V834에서 JLinkRTTViewer.exe를 실행하세요.

연결을 구성하세요:

Google AdInline article slot
  • SWD 또는 JTAG를 선택하세요.
  • 대상 장치를 지정하세요 (ARM Cortex-M).
  • 속도를 설정하세요 (메가헤르츠까지).
  • 연결을 확인하세요.

터미널 0에 명령을 입력하세요 — 색상 강조를 지원합니다. FIFO 오버플로가 발생하면 SEGGER_RTT_Conf.h를 편집하여 버퍼 크기를 늘리세요.

TCP를 통한 대체 접근

RTT 뷰어는 127.0.0.1:19021에 소켓을 엽니다 (netstat -ano | grep 19021로 확인).

PuTTY나 Tera Term을 사용하여 연결하세요:

  • 호스트: 19021
  • 유형: TCP

이것은 UART 터미널을 에뮬레이트합니다. WiFi 네트워크를 통해 원격으로 작동합니다.

RTT CLI의 장점과 한계

장점:

  • 단계별 디버깅과 병렬 작동.
  • ELF 파일 불필요: 플래시 후 J-Link에 전달.
  • SWD 속도로 즉시 전송.
  • 강조 표시된 로그 복사-붙여넣기.
  • 다중 터미널.

단점:

  • J-Link 의존성 (AVR/ESP32/RISC-V 미지원).
  • MCU 리셋 시 연결 끊김 — 수동 재연결 필요.
  • 별도의 입력 창 (TCP로 해결).
  • 뷰어에서 \r 미지원 (Tera Term에서 사용 가능).

| 측면 | SWD를 통한 RTT | UART |

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

| 속도 | MHz SWD | 115200+ |

| 핀 | 3-4 | 2+ |

| 디버깅 | 병렬 | 아니오 |

| 리셋 | 연결 끊김 | 안정적 |

핵심 포인트

  • 초기 로깅을 위해 main() 전에 RTT를 초기화하세요.
  • 멈춤을 피하려면 NO_BLOCK_SKIP을 사용하세요.
  • tx/rx_cnt 로그로 FIFO 오버플로를 모니터링하세요.
  • TCP 19021로 UI 뷰어 문제를 해결하세요.
  • J-Link 지원 Cortex-M에 적합합니다.

— Editorial Team

Advertisement 728x90

다음 읽기