/
SWO printing with STM32

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

  1. Set up semihosting printing with STM32CubeIDE and write the code for printing

  2. Use OpenOCD to connect to the physical board, and open up gdb server and a port for gdb to connect.

  3. 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

image.png
image-1.png
image-5.png

exclude syscalls.c by checking exclude resource from build

image-6.png

Right click on the main project root, go to properties and add rdimon in MCU Linker libraries

image-2.png
image-4.png

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

image-7.png

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

  1. cd to the path of toolchain and start gdb by calling arm-none-eabi-gdb.exe

  2. indicate which file you would want to debug with file [pathname], in case of stm32 series, this would be the path to your .elf file

  3. connect 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

Related content