Every C programmers must use printf function to print Hello World on PC command line console. This function is defined in <stdio.h> which is standard input output. The printf function is commonly used when the program runs on PC. However, it is not usually picked as a debugging method when we develop the code for the microcontrollers.
The main reason is inefficient. The standard library code size is big for microcontroller's limited flash and RAM. To cope with this issue, vendors start to provide light version of printf instead of using the standard library. IDE's toolchain also provide the alternation. I will introduce four different methods to utilize printf function in developing embedded systems: print characters using UART, SWO and RTT.
Demo Environment
Hardware
NXP RT 1064 Evaluation Kit
Micro usb to PC for CMSIS-DAP debugger and UART1
J-Trace Cortex M Pro
Software
IAR WorkBench for ARM 9.50.1
NXP SDK v2.15 for RT 1064
Segger J-link software package
Print characters over Putty/HyperTerminal via UART
Open hello_world.eww with IAR WorkBench for ARM. SDK_2_15_000_EVK-MIMXRT1064\boards\evkmimxrt1064\demo_apps\hello_world\iar
Check Debugger.
Run Putty(Find out COM port from Device Manager and set baudrate to 115200).
Power on and run application.
-
Check result in Putty.
Print characters over J-Link SWO Viewer
Open hello_world_swo.eww with IAR WorkBench for ARM. SDK_2_15_000_EVK-MIMXRT1064\boards\evkmimxrt1064\demo_apps\hello_world_swo
Remove jumper of J47, J48, J49, J50.
Plug J-Trace to J21.
Check trace clock freq with MCUXpresso tool.
Check Debugger.
Power on and run application.
Run J-Link SWO Viewer(Configure CPUClock = 132000[kHz] = 132MHz)
Check result in J-Link SWO Viewer(Whenever press SW8, hello_world is printed, otherwise, timer_trigger is printed).
Print characters over IDE's Terminal I/O
Continue from previous setup. The current project is hello_world_swo.
Add SDK_DEBUGCONSOLE=0 symbol in C/C++ Compiler/Preprocessor.
Check result in Terminal I/O
You probably feel characters are printed really slow. This is because project setting is using semi-hosting for stdout instead of SWO. Let's configure to SWO and re-run the application. Now, you should see a single line is printed instead of character by character.
Print characters over Segger RTT viewer
Go to Program Files\SEGGER\JLink_V794g\Samples\RTT and unzip the file.
Create RTT folder in hello_world_swo\RTT.
Copy Config\SEGGER_RTT_Conf.h to RTT folder.
Copy RTT\SEGGER_RTT.c/h, SEGGER_RTT_printf.c to RTT folder.
Copy Syscalls\SEGGER_RTT_Syscalls_IAR.c to RTT folder.
-
Add RTT in project path.
Add Group(RTT) and add all files in project.
Build project and open hello_world_swo.map and search _SEGGER_RTT.
Run J-Link RTT Viewer.
Check the result in RTT Viewer.
Summary
UART is the most primitive way of using PRINTF. When we did not have a good debugger, this option can be still used. Since it is using UART, maximum speed is varied by baudrate. Depending on the circuit layout, this can be suffered by noise and experience packet drop. To handle UART communication, the mircrocontroller needs to reserve resources to support and it can cause under performance.
SWO's output can be re-directed to either IDE toolchain's Terminal I/O or J-Link SWO Viewer. J-Trace Pro clock frequency can go up to 150MHz(Current project set up was 132MHz-close enough to max). As long as this is using SWO not semi-hosting, characters are able to be printed fast enough. To send a character, ITM_SendChar() can be used instead of PRINTF.
RTT's output is only available over J-Link RTT Viewer. However, this is the fastest way to deliver outputs without overhead on CPU. Also, RTT can relay certain output to specific virtual terminal and font color/background color can be configured by an user. RTT API can be found here: https://wiki.segger.com/RTT#API_functions.
The performance comparison between RTT and SWO is shown below:
https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/