SWO printing with STM32
SWO printing is needed for CI/CD processes as it allows for printf() messages to be displayed on a terminal, which can be remotely accessed. this can be achieved using openOCD, gbd and semihosting.
(we still need stm32cubeide for the initial setup, im not sure how can i set up everything in the terminal, unfortunately)
TLDR
Set up semihosting printing with STM32CubeIDE and write the code for printing
Use OpenOCD to connect to the physical board, and open up gdb server and a port for gdb to connect.
Use gdb to connect to gdb server
so basically you would want 2 terminals one running openOCD and one running gdb.
Setting up the board for SWO
Physical board used: Nucleo F446RE
Setting up in STMcubeide (ew)
Setting up the debugger
Configure debugger settings to use openOCD in STM32CubeIDE. you can add new debug configurations that use openOCD.
you have to change Debug Probe to ST-Link(OpenOCD)
and set the initialization commands to monitor arm semihosting enable
exclude syscalls.c by checking exclude resource from build
Right click on the main project root, go to properties
and add rdimon
in MCU Linker libraries
Sample code
main thing to note is the inclusion of
#include <stdio.h>
#include <stdint.h>
external function
extern void initialise_monitor_handles(void);
finally in the main loop, initializing monitor handle and printing with print()
initialise_monitor_handles();
printf("hello world \n");
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <stdint.h>
/* USER CODE END Includes */
extern void initialise_monitor_handles(void);
int main(){
initialise_monitor_handles();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5);
printf("hello world \n");
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Using OpenOCD
STM32CubeIDE automatically generates openocd startup command for you, you can just copy and paste that by clicking on show command line
Just remember to add the extra command "-c" "init" "-c" "arm semihosting enable"
at the end
Here is a sample command on my laptop
PS C:\> C:\ST\STM32CubeIDE_1.10.1\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.openocd.win32_2.2.300.202301161003\tools\bin\openocd.exe "-f" "SWO Debug OpenOCD.cfg" "-s" "C:/Users/Ku/STM32CubeIDE/F446RE_Test/SWO" "-s" "C:/ST/STM32CubeIDE_1.10.1/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.debug.openocd_2.0.600.202303311036/resources/openocd/st_scripts" "-s" "C:/ST/STM32CubeIDE_1.10.1/STM32CubeIDE/plugins/com.st.stm32cube.ide.mpu.debug.openocd_2.0.500.202301161420/resources/openocd/st_scripts" "-c" "gdb_report_data_abort enable" "-c" "gdb_port 3333" "-c" "tcl_port 6666" "-c" "telnet_port 4444" "-c" "init" "-c" "arm semihosting enable"
Using gdb
OpenOCD only serves as a server, a middleman between the stm32 chip and you, you would need an additional debugger to step through the breakpoints and control the debugging process. this is where gdb comes in.
To use gbd, first download the gnu arm toolchain here Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer
cd
to the path of toolchain and start gdb by callingarm-none-eabi-gdb.exe
indicate which file you would want to debug with
file [pathname]
, in case of stm32 series, this would be the path to your.elf
fileconnect to openocds remote gdb server port with
target extended-remote [network path]
Sample command
C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin\arm-none-eabi-gdb.exe
file /Users/Ku/STM32CubeIDE/F446RE_Test/SWO/Debug/SWO.elf
target extended-remote 127.0.0.1:3333
// press c to step forward
Sample output on the openOCD terminal
[<https://github.com/STMicroelectronics/OpenOCD]>
Licensed under GNU GPL v2
For bug reports, read
<http://openocd.org/doc/doxygen/bugs.html>
swv
Info : STLINK V2J41M27 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.264000
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
Info : clock speed 4000 kHz
Info : stlink_dap_op_connect(connect)
Info : SWD DPIDR 0x2ba01477
Info : [STM32F446RETx.cpu] Cortex-M4 r0p1 processor detected
Info : [STM32F446RETx.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for STM32F446RETx.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : [STM32F446RETx.cpu] external reset detected
semihosting is enabled
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : accepting 'gdb' connection on tcp/3333
[STM32F446RETx.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0800092c msp: 0x20020000, semihosting
configuring PLL
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
Info : device id = 0x10006421
Info : flash size = 512 KiB
hello world
hello world
...
hello world
shutdown command invoked
shutdown command invoked