Skip to main content
ST Employee
January 13, 2021

How to use semihosting with STM32CubeIDE and STM32

Summary

Semihosting can be used to enable code running on STM32 to communicate with the host computer during a debug session. This makes it possible to use host computer I/O (for example keyboard, display, or file system) instead of having such input/output resources on the embedded system during development.


1. Using semihosting with STM32CubeIDE

To use semihosting with STM32CubeIDE some updates are needed to be done in the project. A debugger supporting semihosting is also required. This article guides on how to enable semihosting when using OpenOCD, ST-LINK and STM32 devices.
Note1: ST-LINK GDB server does not support semihosting!
Note2: Please consult SEGGER documentation if semihosting with SEGGER J-LINK is preferred.

2. Update STM32CubeIDE project

2.1. Remove default syscalls.c

Remove default <syscalls.c> file from build if this file is included in STM32CubeIDE project.

2.2. Update main.c

Add the following two lines in beginning of main.c to include <stdio.h> and to use initialise_monitor_handles() prototype.

#include <stdio.h>
extern void initialise_monitor_handles(void);


Add a call to initialise_monitor_handles() function in the beginning of main() function and some variables to be used for semihosting.

int main(void)
{
 /* USER CODE BEGIN 1 */
 initialise_monitor_handles();

 char s[50];
 char *p;
 FILE *fp;
 p=s;


Add some semihosting commands into main() function. Example: Using scanf, printf, fopen, fclose, and fprintf.

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 printf("Hello, World!\n");
 fp=fopen("c:\\dev\\mytest.txt", "w");

 while (1)
 {
	 printf("Enter string:\n");
	 scanf("%s", p);
	 printf("\nReceived string: ");
	 printf(p);
	 printf("\n");
	 fprintf(fp,p);
	 fprintf(fp,"\n");
	 fclose(fp);

	 HAL_Delay(500);
	 fp=fopen("c:\\dev\\mytest.txt", "a");

 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
 }

 

2.3. Update GCC Linker configuration

In Libraries add “rdimon” library.
1565.png

In Miscellaneous add Other flags “-specs=rdimon.specs”

1567.png
 

2.4. Build

The project is now updated to use semihosting. Build the project.

3. Debug with semihosting

3.1. Create/Update OpenOCD debug configuration

Create a new debug configuration for the project or update an existing one. Make sure that OpenOCD is used.
Note: ST-LINK GDB server does not support semihosting.

Add “monitor arm semihosting enable” initialization command in Debug Configurations - Startup tab.
1570.png
 

3.2. Debug

The Debug Console view is used for semihosting input/output and when debugging it will ask to enter strings…
Example: Entering “TEST” and “123456”

Open On-Chip Debugger 0.10.0+dev-01288-g7491fb4 (2020-10-27-17:36)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : STLINK V2J37M26 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.244649
..
..
semihosting is enabled

target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000860 msp: 0x20018000, 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 : Padding image section 0 at 0x08000194 with 12 bytes
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000a04 msp: 0x20018000, semihosting
Hello, World!
Enter string:
TEST

Received string: TEST
Enter string:
123456

Received string: 123456
Enter string:

Stop the debug session to analyze the log file.

4. Analyze debug session

The program opens and writes to the file c:\dev\mytest.txt. Open the <mytest.txt> file and information from the debug session can be seen.
1571.png
 

This topic has been closed for replies.

6 replies

RusikOk
Associate III
August 29, 2022

why so easy? All it took was half a day...

Visitor II
August 30, 2023

Hi,

I use STM32CubeIDE Version: 1.12.1. I can't build my project:

>>>

09:36:11 **** Incremental Build of configuration Debug for project CPU_Rotomat_MP0N ****
make -j12 all
arm-none-eabi-g++ "../Src/main.cpp" -mcpu=cortex-m7 -std=gnu++14 -g3 -DUSE_HAL_DRIVER -DMP0N -DSTM32F767xx -DUSE_FULL_LL_DRIVER -DDEBUG -c -I../Inc -I../Drivers/CMSIS/Include -I../Drivers/CMSIS/Device/ST/STM32F7xx/Include -I../Drivers/STM32F7xx_HAL_Driver/Inc -I../Drivers/STM32F7xx_HAL_Driver/Inc/Legacy -I../Middlewares/Third_Party/LwIP/src/include -I../Middlewares/Third_Party/LwIP/system -I../Drivers/BSP/Components/lan8742 -I../Middlewares/Third_Party/LwIP/src/include/netif/ppp -I../Middlewares/Third_Party/LwIP/src/include/lwip -I../Middlewares/Third_Party/LwIP/src/include/lwip/apps -I../Middlewares/Third_Party/LwIP/src/include/lwip/priv -I../Middlewares/Third_Party/LwIP/src/include/lwip/prot -I../Middlewares/Third_Party/LwIP/src/include/netif -I../Middlewares/Third_Party/LwIP/src/include/compat/posix -I../Middlewares/Third_Party/LwIP/src/include/compat/posix/arpa -I../Middlewares/Third_Party/LwIP/src/include/compat/posix/net -I../Middlewares/Third_Party/LwIP/src/include/compat/posix/sys -I../Middlewares/Third_Party/LwIP/src/include/compat/stdc -I../Middlewares/Third_Party/LwIP/system/arch -Og -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -fno-use-cxa-atexit -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Src/main.d" -MT"Src/main.o" --specs=nano.specs -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -o "Src/main.o"
arm-none-eabi-g++ -o "CPU_Rotomat_MP0N.elf" @"objects.list" -lrdimon -mcpu=cortex-m7 -T"D:\workspace_STM32CubeIDE_1.10_Test\CPU_Rotomat_MP0N\STM32F767BITx_FLASH.ld" --specs=nosys.specs -Wl,-Map="CPU_Rotomat_MP0N.map" -Wl,--gc-sections -static -specs=rdimon.specs --specs=nano.specs -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group
c:\st\stm32cubeide_1.10.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.200.202301161003\tools\arm-none-eabi\bin\ld.exe: ./Src/main.o: in function `main':
D:/workspace_STM32CubeIDE_1.10_Test/CPU_Rotomat_MP0N/Debug/../Src/main.cpp:290: undefined reference to `initialise_monitor_handles()'
collect2.exe: error: ld returned 1 exit status
make: *** [makefile:87: CPU_Rotomat_MP0N.elf] Error 1
"make -j12 all" terminated with exit code 2. Build might be incomplete.

09:36:13 Build Failed. 3 errors, 0 warnings. (took 2s.580ms)

<<<

What's going wrong?

Visitor II
August 31, 2023

Hi,

I've checked with a c-project, everything is working fine. But with my c++-project it isn't linking.

I think the problem is calling a c-function from a cpp-file, but where can I place 

#ifdef __cplusplus
extern "C" {
#endif ?

Has anybody an idea?

Strooom
Senior
February 25, 2024

I have the same question / problem as @juergen.mader 

Strooom
Senior
February 27, 2024

Ok, it’s simple : just put it around the forward declaration 

 

#ifdef __cplusplus
extern "C"
{
#endif
void initialise_monitor_handles(void);
#ifdef __cplusplus
}
#endif /* extern "C" */

chriskuku
Senior II
September 9, 2025

Thanks for this guide. It worked (partially). Got the printf("Hello World"); working, writing to the STM32CubeIDE into the gdb traces console.

But I cannot enter a string using scanf(). The string isn't terminated, when I type in 

e.g. hello (followed by a <cr>)