STM32CubeIDE에서 다양한 printf() 사용법
STM32CubeIDE에서 printf()을 사용하는 방법이 여러가지가 있습니다.
- SWV
- UART
- Dynamic Printf
기본적으로 tiny_printf.c를 사용하기 때문에 char(%c)
, char*(%s)
, int(%d, %i)
, uint(%u)
, uint2hex(%x, %X)
를 사용할 수 있습니다.
float(%f)
를 사용하고싶은 경우 두 가지 방법이 있습니다.
- Project -> Properties -> C/C++ Build -> Settings
- Tool Settings -> MCU Settings -> Runtime library: Standard C
- Project -> Properties -> C/C++ Build -> Settings
- Tool Settings -> MCU Settings -> Runtime library: Reduced C
- Check Use float with printf from newlib-nano
Reduced C에서 float을 활성화 하는 두번째 방법을 추천합니다.
SWV printf()
SWV(Serial Wire Viewer), Atollic사는 아래와 같이 설명하고 있습니다.
Serial Wire Viewer is a real-time trace technology that uses the Serial Wire Debugger(SWD) port and the Serial Wire Output (SWO) pin. Serial Wire Viewer provides advanced system analysis and real-time tracing without the need to halt the processor to extract the debug information.
MCU 설정 시 Pinout & Configuration -> System Core -> SYS -> Debug 가 JTAG 또는 Trace Asynchronous Sw로 설정되어 있어야하고 SWO 핀이 디버거와 연결되어 있어야 합니다.
SWV를 사용하기 위해 ITM(Instrumentation Trace Macrocell)을 사용해서 출력하고 싶은 내용을 SWO를 통해 출력합니다.
- Run -> Debug Configurations -> STM32 Cortex-M C/C++ Application -> <proejct> Debug
- Debugger
- GDB Server Command Line Options: SWD
- Serial Wire Viewer (SWV): Enable
- Core Clock: SystemCoreClock
- SWO Colck
컴파일될 소스 중에 아무 위치에나 아래 코드를 추가하면 됩니다. RTOS를 사용하는 경우 heap 설정을 하시기 바랍니다.
#ifdef __cplusplus
extern "C" int _write(int32_t file, uint8_t *ptr, int32_t len) {
#else
int _write(int32_t file, uint8_t *ptr, int32_t len) {
#endif
for(int32_t i = 0; i < len; ++i) { ITM_SendChar(*ptr++); }
return len;
}
디버그 시작 후, Perspective가 Debug로 변경되면 Debug -> Window -> Show View -> SWV -> SWV ITM Data Console를 눌러 뷰를 추가해 줍니다.
기본적인 ITM 포트는 0 번입니다. SWV ITM Data Console 창에서 port 0 을 추가하고 설정에서 ITM Stimulus Ports에 0 번을 체크합니다.
SWV ITM Data Console 창에서 Start Trace버튼을 누르고 디버깅을 하면 console에 printf()을 통해 출력한 내용이 표시됩니다.
UART printf()
컴파일될 소스 중에 아무 위치에나 아래 코드를 추가하면 됩니다.
#ifdef __cplusplus
extern "C" int _write(int32_t file, uint8_t *ptr, int32_t len) {
#else
int _write(int32_t file, uint8_t *ptr, int32_t len) {
#endif
if( HAL_UART_Transmit(&huart1, ptr, len, len) == HAL_OK ) return len;
else return 0;
}