STM32 printf() usage in STM32CubeIDE

STM32CubeIDE์—์„œ printf()์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • UART: ์ƒ๋Œ€์ ์œผ๋กœ ๋ถˆํŽธํ•จ, ์†๋„ ๋น ๋ฆ„
  • SWV: ์ค‘๊ฐ„
  • Dynamic 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;
}

๊ธฐ๋ณธ์ ์œผ๋กœ 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
tip

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.

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: SYSCLK
    • SWO Colck
caution

Wait for sync packet์„ ํ•ด์ œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. SWO๋ฅผ ํ†ตํ•ด ์ถœ๋ ฅํ•˜๋Š” ์†๋„๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ์˜ ์‹คํ–‰ ์†๋„์— ๋น„ํ•ด ๋Š๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— sync๋ฅผ ํ•˜๋ฉด ์ปจํŠธ๋กค๋Ÿฌ์˜ ์†๋„๊ฐ€ ๋Š๋ ค์ง‘๋‹ˆ๋‹ค.

syscalls.c๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ปดํŒŒ์ผ๋  ์†Œ์Šค ์ค‘์— ์•„๋ฌด ์œ„์น˜์—๋‚˜ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. RTOS๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ syscalls.c๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด์„œ heap ์„ค์ •์„ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

int _write(int32_t file, uint8_t *ptr, int32_t len) {
/* Implement your write code here, this is used by puts and printf for
* example */
for(int32_t i = 0; i < len; ++i) {
ITM_SendChar(*ptr++);
}
return len;
}

Debug -> Window -> Show View -> SWV -> SWV ITM Data Console

๊ธฐ๋ณธ์ ์ธ ITM ํฌํŠธ๋Š” 0 ๋ฒˆ์ž…๋‹ˆ๋‹ค. port 0 ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์„ค์ •์—์„œ ITM Stimulus Ports์— 0 ๋ฒˆ์„ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค.

SWV ITM Data Console ์ฐฝ์—์„œ Start Trace๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ณ  ๋””๋ฒ„๊น…์„ ํ•˜๋ฉด console์— printf()์„ ํ†ตํ•ด ์ถœ๋ ฅํ•œ ๋‚ด์šฉ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Dynamic printf()

Dynamic printf์€ debuggingํ•  ๋•Œ, ๋งค์šฐ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ํŠน๋ณ„ํžˆ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜ ์„ค์ •์„ ๋ฐ”๊ฟ€ ํ•„์š” ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ํŒŒ์ผ ์ž์ฒด์— ์ฝ”๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

๋‹จ, ์ฝ”๋“œ์˜ ์‹คํ–‰ ์†๋„๊ฐ€ ๋Š๋ ค์ง‘๋‹ˆ๋‹ค.

์ถœ๋ ฅ์„ ์›ํ•˜๋Š” ์œ„์น˜์˜ ์ค„ ๋ฒˆํ˜ธ๋ฅผ ์˜ค๋ฅธ์ชฝ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ Add Dynamic-Printf์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  printf() ํ•ญ๋ชฉ์— ์›ํ•˜๋Š” ๋‚ด์šฉ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋””๋ฒ„๊น…์„ ์‹œ์ž‘ํ•˜๋ฉด Debugger Console์— ํ•ด๋‹น ๋‚ด์šฉ์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

Last updated on