2021-09-19 1:24 PM
I am successfully using all the SWV debugging functionality in STM32CubeIDE except for the ITM functionality, as described in UM1609 and in the advanced debugging videos on youtube from ST.
I have both tried overriding the "_write " function in main.cpp or replacing "__IO_putchar" with "ITM_SendChar" in syscalls.c, but I don't see any output when using printf and ITM port 0 (described in video 4 and section 4.3.5 in UM1609).
I have further tested sending output to ITM port 31, as described in video 5, but still cannot see any output.
Some details and further questions
Solved! Go to Solution.
2021-09-20 7:33 AM
I finally figured out that it was the clock speed that was the problem. I am not sure what the limit is for running ITM is, but it is working for 84 MHz and not on 180 MHz. I assume that the other SWV traces will also be inaccurate at high clock as data will be lost in transfer and not be shown in graphs and logs.
2021-09-20 4:02 AM
I have tried ruling out a few things by copying the code from the youtube ST advanced debugging video series:
The advanced debugging capabilities in STM32CubeIDE is really impressive if i can make it work. Can someone test the ITM functionality on a different MCU or board? Preferably on a M4.
2021-09-20 5:10 AM
Tested now also the original code from ST (http://bit.ly/AdvDebugMaterials) with my Nucleo-F722ZE on 216 MHz default system clock, but I still get no output from ITM. All other SWV functionality is working. What am I missing?
2021-09-20 6:46 AM
> SWO is left unconnected
Fairly sure SWO is used to transfer ITM information.
2021-09-20 7:23 AM
Check with STM32 Cube Programmer or ST-LINK Utilities, both have a SWV Viewer
There must be a common understanding of the clock speeds.
Print those clocks out, perhaps also pull the SWO divider value out.
Double check solder bridges on DISCO and NUCLEO boards, ensuring PB3/SWO get to the debugger, and the pin isn't reconfigured elsewhere.
Check RCC/GPIO registers.
2021-09-20 7:33 AM
I finally figured out that it was the clock speed that was the problem. I am not sure what the limit is for running ITM is, but it is working for 84 MHz and not on 180 MHz. I assume that the other SWV traces will also be inaccurate at high clock as data will be lost in transfer and not be shown in graphs and logs.
2024-04-10 1:48 AM - edited 2024-04-10 1:54 AM
Updating to the ST-Link current latest version 3.14.5 fixed the issue for me. Try that first before attempting to downgrade your ST-Link. I have testet this with an STM32G491RE-Nucleo and STM32CubeIDE version 1.15.
Hope this helps :)
Edit: Clock speed should not be an issue, I have testet it at 170MHz. The clock is anyway prescaled down as shown in the upper left under "Clock Settings".
2025-08-21 7:51 AM - edited 2025-08-21 8:26 AM
I used STM32F411,
Managed to get it to work succefully on Keil IDE, bare metal not using any HAL.
Using this tutorial and then 2 others below:
https://blog.embeddedexpert.io/?p=800
This one found later is very complete and specific to STM32Cube, shows the soldering too:
https://www.phippselectronics.com/debug-an-stm32-with-printf-using-only-an-st-link/?srsltid=AfmBOorCxzUAUEuBmm9tu8dBFsDcoqrF5useMoWPx1Xr0boK0YVY9dgK
HARDWARE SETUP:
A STM32 board + ST LINK v2 clone
I used the Chinese Clone, followed this tutorial to solder the PA10 pin == SWO pin to a wire than THEN is to be connected to your STM32's PB3 pin which is the SWO to USB Virtual Com Port VCP connection, basically where the ITM_SendChar() usart function is sending its serial data to.
Note: Soldering it is not impossible but actually quite hard, took me about 90 minutes of soldering with my thinnest soldering tip, then find my thinest wire, and solder under the phone in macro mode, did not have a magnifier, to see what I was doing.
Pretty much the smallest solder I've ever done. But well it worked.
Tutorial here to jhelp with the soldering and locating the pin.
Location: 6th pin from the bottom of the picture, 7th pin from the top end of the picture.
It is a tiny tiny pin and soldering takes patience... I did it im no solder expert, got basic iron, did not use a binocular but if you have one use it, or else use the phone in macro mode and use a coffee mug or piece of wood to hang the phone then work underneath it. USE the MACRO mode on you phone, much better definition image close in macro than zooming in in normal mode.
https://lujji.github.io/blog/stlink-clone-trace/
However the tutorial is not instructing you that the T-SWO pin / PA10 / pin 32 on ST Link v2 needs to be connected then to your PB3 (by default) pin on STM32F411, as this is the default for SWO, this tutorial mentions it:
https://deepbluembedded.com/stm32-debugging-with-st-link-v2-swd-serial-wire-viewer/
1. Override printf to use ITM_SendChar() ,ideally do it in a file called Retarget.c Additional to main.c
// Retarget.c
#include "stm32f4xx.h"
#include <stdio.h>
int fputc(int ch, FILE *f)
{
ITM_SendChar(ch);
return(ch);
}
#ifdef __cplusplus
extern "C" {
#endif
int _write(int file, char *ptr, int len) {
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++) { // 96 84 80 50 48 32 24 25 16
ITM_SendChar(*ptr++);
}
return len;
}
#ifdef __cplusplus
}
2. Alternatively I believe this work for CubeIDE, and for keil redefine _write(), here i have done both, to be sure and it works.
3. Setup your IDE. in this case Keil IDE with the following Trace setup:
- Speed 16MHZ for my STM32f411CE it worked. I believe the speed however is not essential. check your system clock speed by checking the SystemCoreClock variable.
- What is essential is to ENABLE the Trace.
- Check to use the Core clockb
- ESSENTIAL : Select ALL of the ITM stimulus bits 0 to 31. In the past I used only 0 as recommended by many tutotials: DID NOT WORK ! Figured out it was the element that prevented the whole thing to work ! so set it to 0xFFFFFFFF
- Finally set the privilege mask to 0x00000008.
Note others report using only bit 0 stimulus 0x00000001 and then privilege 0x00000000.
Try both !
Screenshot of important values below: Essential value in Yellow.
4. Like mentioned earlier, print something in the while loop in order to be able to test your output.
#include <stdint.h>
#include "stm32f4xx.h"
#include <stdio.h>
#include "core_cm4.h" // or core_cm3.h depending on your core
#ifdef __cplusplus
extern "C" {
#endif
int _write(int file, char *ptr, int len) {
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++) { // 96 84 80 50 48 32 24 25 16
ITM_SendChar(*ptr++);
}
return len;
}
#ifdef __cplusplus
}
#endif
void USART_write(int ch);
void USART2_Init(void);
void delay(uint32_t ms) {
// Assuming HCLK is 16MHz for example. Adjust according to your clock configuration.
// SysTick->LOAD = (SystemCoreClock / 1000) * ms - 1; // For 1ms tick
SysTick->LOAD = (16000 - 1) * ms; // For a 1ms delay with 16MHz HCLK
SysTick->VAL = 0; // Clear current value
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; // Use HCLK, enable SysTick
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); // Wait for COUNTFLAG
SysTick->CTRL = 0; // Disable SysTick after delay
}
int main()
{
printf("Hello, STM32!\n");
printf("Hello, STM32!\n");
printf("Hello, STM32!\n");
printf("Hello, STM32!\n");
USART2_Init();
while(1){
printf("Hello, STM32!\n");
delay(1000);
}
}
Ok so now you have done the 1. soldering of SWO on your ST link v2 clone, you have connected it to your STM32 PB3 SWO pin, but then you have no clue as to is it gonna work or why is it not ?
And my word this is where all the tutorials I found thus far were coming short : not telling you anything about testing, and diagnostic of 1. the HW connections then the 2.software
Showing the system clock using SystemCoreClock here:
HOW DO YOU TEST that the SWO Connection is working ?
As below highlighted in REd the ST link v2 clone SWO / PA10/31 pin to SWO/ PB3 on STM32F411 connection, it is breakable : 2 parts wire.
Note: no need to connect it through the header of the St link clone, it is another risky, risk of damaging the clone for no reasons, when you can just add a new wire like i did 1. simpler 2.faster 3. does not force you to sacrifice one of the existing header pins and connection.
This test is missing from ALL the tutorial I found !
- Once you have configured your IDE (as below) and printf() redefinition (as below) , then EVEN if your settings e.g. TRACE Clock wrong or ITM Stimulus bits are wrong, You will still see data coming through to the Debug window SWV viewer window in Keil or Cube IDE.
It will not print meaningful ASCII Chars, only incoherent characters but you will see the data incoming, and can switch to HEX view mode to check that data is sent.
Wrong chars but data coming yay !
if the speed of your clock is too fast it might fail without showing anything due to being unable to sync with viewer. So my advice on testing clock speeds: Start with the lowest to the greatest e.g.
// 100 96 84 80 50 48 32 24 25 16 MHZ. =>> 16, then 25, then ... lowest first.
So TEST: in the while(1) loop in your main: add endless printf(xxx) statements until you see something.
This is the VERY FIRST KEY step, that is not explained anywhere pretty much, that I figured out of luck and a tiny bit of experience debugging sh**ty stuff.
ADDITIONAL TEST, very helpful BREAK THE SWO WIRE ON AND OFF see what happens !: I set up a breakable wire in 2 parts, that I played with to disconnect while running the Keil IDE SWV debug trace viewer and indeed when disconnecting it the data stopped coming immediately on the viewer and then resumed instantly once reconnected.
So yes these 2 Hardware test steps, testing that your SWO pin is spitting data out, is the very first thing.
TAKEAWAYS
1. I wish ST was documenting this process better at least with the official ST link
2. Take the time to locale your SWO pin, on your STM32, should be PB3 on STMF4xx, it is key,
3. the system clock should be given by SystemCoreClock but apparently it is now always up to date depending your your setup and if using HAL or not. etc. I am no expert but best bet so far.
General tip : Try figure out the clock speeds which are realistically possible e.g. for STM32F411, the max is 100MHZ, however common prescaler, PLL, M H configuration will give you the most likely speeds:
// 100 96 84 80 50 48 32 24 25 16 MHZ.
4. I REALLY wish there was an easy way to obtain the clock speed when not using CMSIS or HAL libs. but just read a couple of registers and obtain it in a simple way. it is a key element.
When using STM32CUbeMX and all that boilerplate generated code, you have the UI to configure the clock speed in an easy way. But in Keil or if adopting Bare metal approach then it takes very good knowledge of STM32 to be 110% sure about it. And as every detail matters, then if entering the wrong speed in the IDE Trace configuration, then it could fail just because of that.
So yup typical issues all tangled together making a simple task tricky due to domino effect of issues and wrong config details stacking up...
I am a newbie at STM32 only my 3rd day working with it, experimenting and this kind of thing e.g. hard to get a decent debug setup, when on Arduino or ESP32 it takes nothing to get serial to work, just ... S***CKS !
Enjoy ! hope this helps !
Romain, French C/C++ Engineer in New Zealand.