cancel
Showing results for 
Search instead for 
Did you mean: 

How to use semihosting with STM32CubeIDE and STM32

LauraCx
ST Employee

How can semihosting be used when debugging STM32 devices with STM32CubeIDE?
An example using semihosting with Nucleo-STM32F401
 board and OpenOCD.

  1. 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.
  1. Update STM32CubeIDE project

    1. Remove default syscalls.c

Remove default <syscalls.c> file from build if this file is included in STM32CubeIDE project.
    1. 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 */
  }
    1. Update GCC Linker configuration

In Libraries add “rdimon” library.
1565.png
In Miscellaneous add Other flags “-specs=rdimon.specs”
1567.png
 
    1. Build

The project is now updated to use semihosting. Build the project.
  1. Debug with semihosting

    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
 
    1. 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.
  1. 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
 
Comments
RusikOk
Associate III

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

juergen.mader
Associate

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?

juergen.mader
Associate

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
Associate III

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

Strooom
Associate III

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" */

Version history
Last update:
‎2021-01-13 08:20 AM
Updated by: