SW4STM32 and SW4Linux fully supports the STM32MP1 asymmetric multicore Cortex/A7+M4 MPUs

   With System Workbench for Linux, Embedded Linux on the STM32MP1 family of MPUs from ST was never as simple to build and maintain, even for newcomers in the Linux world.
And, if you install System Workbench for Linux in System Workbench for STM32 you can seamlessly develop and debug asymmetric applications running partly on Linux, partly on the Cortex-M4.
You can get more information from the ac6-tools website and download two short videos (registration required) highlighting:

System Workbench for STM32

ST-link printf to console with GDB and semihosting or ITM and ST Link Utility

This post will attempt to compile information that is found in various posts into single place.

Semihosting is using printf to the GDB console ie it will show up in system workbench / eclipse console while debugging when configured properly. This will only work in debug mode. At this point openOCD doesn’t support displaying SWO trace data.

ITM uses printf and the CMSIS ITM _SendChar() function to output a message through the SWO line. The ST Link Utility is used to veiw these printf statements. ITM is considerably faster than semihosting.

This post assumes that you are familiar with how to use the ST cube and can import projects into system workbench / eclipse. The projects were completed using system workbench version 1.8, cube version 4.15, and the STM32F401C-DISCO board. The relevant part of the cube configuration is in the SYS peripheral.

Output to debug console using GDB
In the SYS peripheral debug should be set to Serial Wire. Trace Asynchronous SW works, but it reserves PB3 for SWO. If you chose the STM32F401C-DISCO board in the cube setup it will have the pin labeled SWO on PB3 regardless of the choice made in SYS peripheral. For GDB console output generate the cube project and import into eclipse.

  1. The linker needs to know to include librdimon: Project -> Properties -> C/C++ Build -> Settings -> MCU GCC Linker -> Linker flags set to -specs=nosys.specs -specs=nano.specs -specs=rdimon.specs -lc -lrdimon
  2. Project -> Properties -> Run/Debug Settings -> edit correct debug setting -> startup -> add monitor arm semihosting enable to initialization commands
  3. Add extern void initialise_monitor_handles(void); above main. I chose user code 0 section. You do not have to include stdio.h or stdlib.h when using a cube generated project and semihosting
  4. Add initialise_monitor_handles(); to the main loop before the while(1)
  5. Use printf as you would normally remembering that without the \n character it will not output to the console when debugging

Output to ST Link Utility using ITM
Make the project in the same way as for GDB console output. Serial wire or asynchronous SW can be chosen. If serial wire is selected than PB3 must be left unused. If PB3 is set to other GPIO functionality the ITM messages will not work.

ITM setup is very easy. Add the below code to your main.c. I chose user code 0 again.

int _write(int file, char *ptr, int len)
	int DataIdx;

	for (DataIdx = 0; DataIdx < len; DataIdx++)
	   ITM_SendChar( *ptr++ );

	return len;

From there printf using ITM can be used with ST Link Utility with no additional changes.

Of course the _write function can also used with a uart for printf functionality. I did not include that as it seems to be very well covered elsewhere. Hope this helps someone.


Thankyou Michael for this great entry

I want just to highlight that when using ITM the user has to make sure that SWO related solder bridges are soldered.
eg : STM32F429I-DISCO >> SB9 ; F3-DISCO >> SB10 ; ...


Great point about the solder joints. I think the new ones come with a low value resistor closing the correct solder bridges. I have both the STM32F072B-DISCO and the STM32F401C-DISCO dev boards and they both already have that low value resistor closing the bridges. Also, check your schematics. There is a possibilitiy you can use a jumper wire to the SWD connector’s SWO line and have it work that way.

Another thing to remind everyone is that if you are making your projects using something other than the ST Cube you might have to include the relevant files manually. That is to say the CMSIS files for the ITM or librdirmon for semihosting.

What are the solder bridges for Nucleo-F767ZI?

SB110 (on by default)
plz refer to STM32 Nucleo-144 board User manual

Hi, please can you explaine how to activate the SWO without passing by CubeMX, by adding the code responsible for this manually.
So i stalled with the semihosting and i get it to work in SWSTM32 on stm32f407biggrinbiggrinbiggrin:
-First you dont need to add the serial wire from cubemx if you need a cubemx project (for me a default project just activate the semihosting without more confugiration).
-If you dont need to use a cubemx project you just need to do the steps as described above(1-5) then delete all the function in syscalls.c which make errors then delete the “int _write(int file, char *ptr, int len)” and then the semihosting is working.

I do not know what the debug serial wire code check box does. I do not think it does anything. Have you tried either of the methods to output data through the SWO line?

So can the semihosting be used with the ST-Link V2 debugger and the ST Link Utility?

I found that Semihosting does not work when in release mode (burning)
therefore i used to comment and uncomment the call to initialise_monitor_handles() each time per release/debug

To avoid it i did the following
1. in main.c define weak stub
__weak void initialise_monitor_handles( void )

2. continue calling initialise_monitor_handles() in main() anyway

If debugging, the initialise_monitor_handles() will be taken from linked library rdimon
If working in release mode, initialise_monitor_handles() will be taken from the main.c implementation (because you are not liked to rdimon library anymore)

How do I import the definition of ITM_SendChar ?

I am new to ARM developing....also new to ST....but so far I love it. I’ve been developing on an ESP32 for a year and think I may just switch to ST. I have semihosting working using the instructions under Output to debug console using GDB and it works great.

I don’t understand the other option (Output to ST Link Utility using ITM) at all. Can someone give me a high level understanding of what it does and why I might want to use it instead of GDB?

When I have included the
above the while(1) loop in main the make recipe fails. Is there a library that I need to include for this to work? Adding the linker flags to the G++ linker does nothing.

Just wanted to let everyone know that I was able to get it working eventually.

With C++ projects:
\# include “stdlib.h”
\# include “stdio.h”

extern “C”{
extern void intialise_monitor_handles(void);

and then place initialise_monitor_handles first thing in main(), just after HAL_Init();

I followed the above post. But in my system workbench setup i am not able to find out tool_setting->Mcu Gcc compiler option. attaching the screenshot for this.

Can someone please confirm why this option is not present in my setup? Or how can i get this.

Nikhil Sahu



Looks like you’ve created a “Makefile project”, not an “Executable” or “Static Library” project where SW4STM32 will generate the Makefile from the tool settings; in your case you can’t edit compiler settings, just because the compiler invokation is done by the Makefile that you provide by yourself.

You should then convert the proposed settings to the appropriate C/C++ compiler settings in your Makefile for using ITM or semihosting for printf.


Bernard (Ac6)


I am added the flag in my makefile as
LDFLAGS = -g -Wl,gc-sections,-Map=$*.map,-cref -fno-short-enums -Wl,no-enum-size-warning -T $(LDSCRIPT) $(CPU) -specs=nosys.specs -specs=nano.specs -specs=rdimon.specs -lc -lrdimon

But after this when i am doing the compilation we are facing multiple definition error (but these funtions are not defined anywhere i double checked this) as

arm-none-eabi-gcc -g -Wl,gc-sections,-Map=output/bl-v2/release/main.map,-cref -fno-short-enums -Wl,no-enum-size-warning -T ./STM32L496ZGTx_FLASH.ld -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -specs=nosys.specs -specs=nano.specs -specs=rdimon.specs -lc -lrdimon -o output/bl-v2/release/main.out output/bl-v2/release/startup_stm32l496xx.o output/bl-v2/release/system_stm32l4xx.o output/bl-v2/release/ackbar_main.o output/bl-v2/release/assert.o output/bl-v2/release/board_id.o output/bl-v2/release/console.o output/bl-v2/release/gps.o output/bl-v2/release/ble.o output/bl-v2/release/backlight.o output/bl-v2/release/lte.o output/bl-v2/release/button.o output/bl-v2/release/hallsensor.o output/bl-v2/release/vibsensor.o output/bl-v2/release/accelgyro.o output/bl-v2/release/power.o output/bl-v2/release/lpm.o output/bl-v2/release/is66wve.o output/bl-v2/release/it8951.o output/bl-v2/release/printf.o output/bl-v2/release/extflash.o output/bl-v2/release/sys.o output/bl-v2/release/syscalls.o output/bl-v2/release/tasklet.o output/bl-v2/release/temp.o output/bl-v2/release/mfgdata.o output/bl-v2/release/ymodem.o output/bl-v2/release/bitmap.o output/bl-v2/release/stsafe.o output/bl-v2/release/flash_if.o output/bl-v2/release/adc.o output/bl-v2/release/clock.o output/bl-v2/release/common.o output/bl-v2/release/fifo.o output/bl-v2/release/gpio.o output/bl-v2/release/i2c.o output/bl-v2/release/rtc.o output/bl-v2/release/spi.o output/bl-v2/release/sram.o output/bl-v2/release/stm32l4xx_it.o output/bl-v2/release/timer.o output/bl-v2/release/uart.o output/bl-v2/release/watchdog.o output/bl-v2/release/key_det.o output/bl-v2/release/extflash_mgr.o output/bl-v2/release/security_mgr.o output/bl-v2/release/disp_mgr.o output/bl-v2/release/logging_mgr.o output/bl-v2/release/vehicle_mgr.o output/bl-v2/release/settings_mgr.o output/bl-v2/release/messaging_mgr.o output/bl-v2/release/gps_mgr.o output/bl-v2/release/rtc_mgr.o output/bl-v2/release/sys_events.o output/bl-v2/release/timer_mgr.o output/bl-v2/release/app_main.o output/bl-v2/release/messaging.o output/bl-v2/release/phonehome.o output/bl-v2/release/vehicle_motion.o output/bl-v2/release/plate_attachment.o output/bl-v2/release/fault.o output/bl-v2/release/demo.o output/bl-v2/release/ssl_client.o output/bl-v2/release/http_client.o output/bl-v2/release/campaignZone.pb-c.o output/bl-v2/release/config.pb-c.o output/bl-v2/release/eventEnvelope.pb-c.o output/bl-v2/release/log.o output/bl-v2/release/message.pb-c.o output/bl-v2/release/protobuf-c.o output/bl-v2/release/readWriteEvent.o ./Drivers//STM32L4xx_HAL_Driver/libstm32l4hal.a ./Middlewares//ST/STSAFE_A/libstsafe.a ./Middlewares//Third_Party/FreeRTOS/libfreertos.a ./Middlewares//Third_Party/mbedTLS/mbedtls-2.6.0/library/libmbedtls.a ./Middlewares//Third_Party/mbedTLS/mbedtls-2.6.0/library/libmbedx509.a ./Middlewares//Third_Party/mbedTLS/mbedtls-2.6.0/library/libmbedcrypto.a ./Middlewares//Third_Party/xz/xz.a -lm
output/bl-v2/release/syscalls.o: In function `initialise_monitor_handles’:
D:\work\/src/drivers/syscalls.c:100: multiple definition of `initialise_monitor_handles’
c:/ac6/systemworkbench/plugins/fr.ac6.mcu.externaltools.arm-none.win32_1.17.0.201812190825/tools/compiler/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/hard\librdimon_nano.a(rdimon-syscalls.o):syscalls.c:(.text.initialise_monitor_handles+0x0): first defined here
output/bl-v2/release/syscalls.o: In function `_kill’:
D:\work/src/drivers/syscalls.c:108: multiple definition of `_kill’

Hello All,

I enabled semihosting and add main function below.

int main(void)
/* Initialize STM32L4x HAL */

/* my code

  • /


But when i do debug we are getting below logs on debug console.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08076c3c in initialise_monitor_handles ()

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08076ace in _swiopen ()

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08076b4c in _get_semihosting_exts ()

Program received signal SIGTRAP, Trace/breakpoint trap.
0x080767fa in _swiread ()

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08076928 in _swiclose ()

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08076c76 in initialise_monitor_handles ()

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08076c90 in initialise_monitor_handles ()

Program received signal SIGTRAP, Trace/breakpoint trap.
0x080769fa in _swistat ()

Any one can suggest what is missing here.

One more red log is comming as “”“No source available for “initialise_monitor_handles() at 0x8076c3c” “””