2025-09-30 6:24 AM
I have overall found this feature to be very unreliable, for reasons unknown. The data comes out OK from PB3 and goes all the way to the STLINK V3, at the expected speed, 1MHz, but Cube IDE displays nothing. I have this across a number of development units. Sometimes it works and then stops...
Anyway, digging into this, it looks like the entire trace macrocell is configured via the debugger when (or before) reset is released from the target. That is why none of the STM example code sets up any of this stuff. I also managed, years ago, to get SWV working not with Cube IDE but with the STM32 STLINK Utility, which presumably does the same via-debugger config tricks.
Also just because you see 1MHz stuff on the scope doesn't mean that it is in the right format for Cube IDE to decode it.
So I went looking for how to get this stuff configured in software in the target. Obviously any such config will override the Cube/debugger config so you will have to make sure Cube IDE's config matches exactly if you still want that to work. And after a lot of work I found the following, and wonder whether it is complete:
1) Set up PB3 to be an output, probably fast mode, and enable portb clock.
2) Set up the macrocell. I found this on this ST forum
/*
Initialize the SWO trace port for debug message printing
portMask : Stimulus bit mask to be configured
cpuCoreFreqHz : CPU core clock frequency in Hz
baudrate : SWO frequency in Hz
*/
void swoInit (uint32_t portMask, uint32_t cpuCoreFreqHz, uint32_t baudrate)
{
uint32_t SWOPrescaler = (cpuCoreFreqHz / baudrate) - 1u ; // baudrate in Hz, note that cpuCoreFreqHz is expected to match the CPU core clock
CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk; // Debug Exception and Monitor Control Register (DEMCR): enable trace in core debug
DBGMCU->CR = 0x00000027u ; // DBGMCU_CR : TRACE_IOEN DBG_STANDBY DBG_STOP DBG_SLEEP
TPI->SPPR = 0x00000002u ; // Selected PIN Protocol Register: Select which protocol to use for trace output (2: SWO)
TPI->ACPR = SWOPrescaler ; // Async Clock Prescaler Register: Scale the baud rate of the asynchronous output
ITM->LAR = 0xC5ACCE55u ; // ITM Lock Access Register: C5ACCE55 enables more write access to Control Register 0xE00 :: 0xFFC
ITM->TCR = 0x0001000Du ; // ITM Trace Control Register
ITM->TPR = ITM_TPR_PRIVMASK_Msk ; // ITM Trace Privilege Register: All stimulus ports
ITM->TER = portMask ; // ITM Trace Enable Register: Enabled tracing on stimulus ports. One bit per stimulus port.
DWT->CTRL = 0x400003FEu ; // Data Watchpoint and Trace Register
TPI->FFCR = 0x00000100u ; // Formatter and Flush Control Register
// ITM/SWO works only if enabled from debugger.
// If ITM stimulus 0 is not free, don't try to send data to SWO
if (ITM->PORT [0].u8 == 1)
{
bItmAvailable = 1 ;
}
}
What I don't get however is the comment "ITM/SWO works only if enabled from debugger.". What is this about? There may not be a debugger!
The actual output function is the usual ST one:
// Copy of the one in core_cm4.h
static inline void ITM_SendChar (uint32_t ch)
{
if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
{
while (ITM->PORT[0U].u32 == 0UL)
{
__NOP();
}
ITM->PORT[0U].u8 = (uint8_t)ch;
}
return;
}
2025-09-30 6:58 AM - edited 2025-09-30 7:02 AM
@PHolt.1 wrote:I found this on this ST forum
Please give a link to where you found it.
@PHolt.1 wrote:What I don't get however is the comment "ITM/SWO works only if enabled from debugger.". What is this about?
Some debug features are only accessible via a debugger - the CPU has no access.
See also DHCSR in Cortex-M0.
PS:
ARM document accessible registers here.
ARM's SWO documentation here.
2025-09-30 7:06 AM
It is in this thread
Re with-debugger-only operation, I recall reading that the SWO output can be used without a debugger. It seems to be just a UART. The above link and the code there suggests that is the case, otherwise who would bother?
You can also look here
https://gist.github.com/mofosyne/178ad947fdff0f357eb0e03a42bcef5c
which contains similar stuff.
2025-09-30 7:10 AM
@PHolt.1 wrote:It seems to be just a UART.
AIUI, one of the supported SWO protocols is UART:
2025-09-30 7:28 AM - edited 2025-09-30 8:39 AM
Yes; it supports various encodings including Manchester, but AFAICT the 32F4 to STLINK V3 to Cube IDE interface is just a standard NRZ UART.
Presumably one doesn't have (up to) 12MHz NRZ going back to the PC via USB :) so the reception must be implemented by the STM CPU in the debugger (32F723 in the little one I am looking at) which packages the data and buffers it for the PC host to retrieve it over USB.
Looking at it on a scope, it looks like a standard microcontroller UART i.e. normally high, with a start bit going low. But I can't be sure.
It would be interesting if it could be used as a standalone output. I cannot find details of these registers anywhere e.g.
TPI->FFCR = 0x00000100u ;
EDIT:
This
shows that what I want is basically impossible.
So back to why SWV ITM is not working :)
2025-09-30 9:52 AM - edited 2025-09-30 10:19 AM
>So back to why SWV ITM is not working :)
It IS working...if you do it right, not sooo difficult (but not always working instantly...dont ask me why.).
1. its not working without debug/st-link , because the debug unit has to know, it should do it now.
2. you could write these instructions yourself, without "debug" active, as shown in your link (gist/git...).
3. to send on printf(...) you only need: (at end of main, see user code marks)
/* USER CODE BEGIN 4 */
int __io_putchar(int ch)
{
ITM_SendChar(ch);
return (ch);
}
/* USER CODE END 4 */
...then send is simple as:
printf("**** start *******\r\n"); // always \n needed !
+
enable in debug SWV: (cpu core clock has to be the real clock value ! ! here 200MHz )
+
set itm0 , when debug started, wait at main, in SWV settings:
+ "start" with the red button
-> then run program and get the messages you send:
btw
sometimes its not working on the first run, end debug, start it again, red button again...
funny: if its working, its always working, also after mod code, compile, debug...no need to start it again... :)
+
Without debug etc its more easy and straight : use one of the many uarts, set it on (i do) 3 Mbit, transmit only;
on a plug you can connect to a running machine and see the messages, without stopping or changing the "normal" running status; no debug session needed.
2025-09-30 2:11 PM
You have to disable PC Sampling.
I posted it here
PC Sampling is only for the SWV Statistical Profiling feature. I don't think you can have SWV ITM debugs and Statistical Profiling running concurrently.
In fact I now find Statistical Profiling is very hard to get working, but I used it successfully a few years ago (earlier version of Cube than my 1.14.1).
BTW I froze Cube at 1.14.1 because later versions don't fix anything, and mostly broke the debugger.
2025-09-30 7:06 PM - edited 2025-10-02 4:47 AM
> What I don't get however is the comment "ITM/SWO works only if enabled from debugger.". What is this about? There may not be a debugger!
The meaning of "debugger" here is the any external software or firmware that drives the SWD interface from outside.
2025-09-30 11:17 PM
Not driving, it just has to be programmed to do the SWV output, as the debug unit is sleeping or waiting to do something at startup, but you want it to do something.
So you use the debug st-link to set it to the desired mode.
2025-09-30 11:30 PM - edited 2025-09-30 11:32 PM
It seems clear from the EEVBLOG thread (link above) that the SWO cannot be used as a simple UART. The data is encoded in some complicated way. In fact, on a scope I see continuous data, with what looks like a 2 byte packet coming out every 90us. And continuous data going into the target from the debugger.
That code above for enabling SWO is a redherring. It is for the narrow application scenario of some 3rd party OpenOCD debugger, and then the target needs to run some code to set it up. With Cube IDE + STLINK, the debugger uses the SWD interface to set up the target CPU trace macrocell entirely.
The general reliability issues remain, however, and AFAICT disabling PC Sampling is now a requirement for the SWV ITM debug console to work. I can reproduce this across several targets and operating systems.