
※ 스타트업 코드
위 그림을 보면, startup_stm32f411retx.s라는 것이 있다. ST이든, TI이든, NXP이든, 어떠한 Microcontroller이든, Microcontroller을 위한 스타트업 코드를 반드시 프로젝트에 포함시켜야 한다.
현재 임베디드 보드에는 어떠한 표준 출력 장치가 연결되어 있지 않기 때문에 출력을 확인할 수 없다. 그래도 하나의 해결책이 있는데, 이는 ARM Cortex 프로세서 자체에서 제공된다.
ARM Cortex M3/M4/M7 기반 MCU에서 printf 출력을 사용하는 방법에 대해 말해보겠다. 참고로 본 방법은 ARM Cortex M0 또는 M0 프로세서에는 해당되지 않는다. 왜냐하면 trace 기능을 사용할 수 없기 때문이다. ARM Cortex 프로세서에서는 SWD Interface의 SWO(Serial Wire Output) 핀을 사용하여 printf을 작동시킬 수 있다.
예를 들어, 마이크로컨트롤러 STM32F407VG가 있다고 하겠다. 여기에는 ARM Cortex M4 프로세서가 포함되어 있다.

또한, ST link V2 또는 V1 DEBUG Circuit이 있다. 이는 보드에 탑재된 ST-link 온보드 디버그 회로이다. 이 디버그 회로를 통해, 마이크로컨트롤러 내부 Flash에 PG을 작성하고, 다양한 Memory 위치를 읽고, 프로세서를 실행하거나 정지시킬 수 있으며, 기타 디버그 관련 작업을 할 수 있다.
이 회로에 USB을 연결하면, PC는 보드와 통신이 가능하다. 그리고 ARM Cortex M 프로세서에서 나오는 SWO 핀이라는 핀이 있으며, 이것이 디버그 회로와 연결된다. printf는 바로 이 SWO 핀을 통해 작동한다.

ARM Cortex M4 프로세서 내부에는 ITM(Instrumentation Trace Macrocell) Unit이라는 유닛 또는 주변장치가 있다. ITM은 OS나 애플리케이션 이벤트 추적을 위한 printf 스타일 디버깅을 지원하는, 선택적인(optional) application-driven trace source이다. 또한, 진단 시스템 정보를 생성하는 데에도 사용될 수 있다.
이 유닛은 ARM Cortex M3 이상의 프로세서에만 존재한다. 그리고 프로세서를 디버깅하려면, 다시 말해, Memory 위치를 읽거나, 프로세서 레지스터를 읽거나, 프로세서를 정지시키거나 실행시키려면 디버그 인터페이스를 사용해야 한다. 여기서 사용되는 디버스 인터페이스는 SWD(Serial Wire Debug)이다.
SWD은 ARM 디버그 인터페이스에 접근하기 위한 2-wire protocol이다. SWD은 SWD connector를 통해 작동되며, 이 connector에는 세 개의 pins이 존재한다. 하나는 trace에 사용되고, 나머지는 debug에 사용된다. 참고로, trace란 프로세서로부터 trace 관련 정보를 얻기 위한 것이다.
앞서 언급한 것처럼, SWD는 ARM 디버그 인터페이스에 접근하기 위한 2-wire protocol이다. 이는 ARM Debug Interface Specification v5의 일부이며, JTAG의 대안으로 제공된다.
SWD의 physical layer은 두 개의 라인으로 구성된다. 하나는 SWDIO라는 양방향 데이터 라인이고, 다른 하나는 host가 구동하는 클럭인 SWCLK이다. 여기서 사용되는 보드에서는, ST-Link 회로가 바로 host이다.
SWDIO은 디버그 관련 명령을 전송한다. 예를 들어, IDE에서 breakpoint을 삽입할 때, 그 정보는 SWDIO 데이터 라인을 통해 프로세서로 전송된다. IDE에서 프로세서를 정지시키고자 할 때도, 그 정보는 SWDIO 라인을 통해, SWCLK의 도움을 받아 프로세서로 전송된다. 프로세서와 통신하려면 이 SWD 인터페이스의 두 핀, SWDIO와 SWCLK를 사용하면 된다. 두 핀 모두 보드에 탑재된 ST-Link 회로가 제어한다.
SWD 인터페이스를 사용하여 MCU의 내부 flash에 PG을 쓰고, Memory 영역에 접근하고, breakpoint를 추가하거나 CPU를 정지 및 실행시킬 수 있다. 또한, printf 디버깅을 위한 Serial Wire Viewer를 사용할 수 있다.
앞서 말했듯이, SWD는 디버그에 사용되는 두 개의 핀만 있지만, 선택적인 핀으로 SWO라는 핀이 있으며 이는 printf 기능에 사용된다.
또다른 디버그 인터페이스로 JTAG이 있다. JTAG과 SWD의 차이는, JTAG은 SWD보다 더 많은 핀이 필요하다. JTAG은 ARM7이나 ARM9 계열을 위한 전통적인 디버그 연결 메커니즘이었지만, Cortex-M 계열에서는 ARM이 Serial Wire Debug 인터페이스를 도입했다. SWD는 JTAG에서 사용되던 4개의 핀을 2개로 줄이도록 설계되었다.
또한, SWD 인터페이스는 SWO을 추가로 제공하여 tracing을 낮은 비용으로 하는 Single Wire Viewing을 가능하게 한다.

ITM Unit을 자세하게 보면, FIFO, buffer, 또는 register라고 할 수 있는 것이 보인다. 이 FIFO는 프로세서에서 나오는 SWO 핀에 연결되어 있으며, 그 핀은 보드의 디버그 회로로 연결된다. 따라서 printf가 이 FIFO에 데이터를 쓰는 순간, 그 메시지는 SWO 핀을 통해 나오게 되며, 우리는 그것을 capture할 수 있다.
참고로 32CubeIDE와 TrueSTUDIO 같은 IDEs은 capture을 지원한다. SWO 핀은 보드의 ST-Link 회로에 연결되어 있으며, 디버그 SW를 통해 capture될 수 있다.
<참고 자료>
Kiran Nayak, Microcontroller Embedded C Programming: Absolute Beginners, Udemy, 2025.05.