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
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 ;