2020-04-01 09:25 PM
Hi, I am trying to get printf functionality work on Discovery kit IoT node board, however it doesn't seem to work.
I went through the user manual and performed the steps mentioned, screenshot from ITM section in user manual is given below,
and below is in the code snippet
//Debug Exception and Monitor Control Register base address
#define DEMCR *((volatile uint32_t*) 0xE000EDFC)
#define DBGMCU_CR *((volatile uint32_t*) 0xE0042004)
/* ITM register addresses */
#define ITM_STIMULUS_PORT0 *((volatile uint32_t*) 0xE0000000 )
#define ITM_TRACE_CNTL *((volatile uint32_t*) 0xE0000E80 )
#define ITM_TRACE_EN *((volatile uint32_t*) 0xE0000E00 )
#define ITM_TRACE_PRIVELAGE *((volatile uint32_t*) 0xE0000E40 )
#define ITM_LOCK_ACCESS *((volatile uint32_t*) 0xE0000FB0 )
void ITM_SendChar(uint8_t ch)
{
//Enable TRCENA
DEMCR |= ( 1 << 24);
DBGMCU_CR |= (1 << 0 | 1 << 1 | 1 << 2 | 1 << 5);
DBGMCU_CR &= ~(1 << 6 | 1 << 7);
ITM_LOCK_ACCESS = 0xC5ACCE55;
ITM_TRACE_CNTL = 0x00010005;
//enable stimulus port 0
ITM_TRACE_EN |= ( 1 << 0);
ITM_TRACE_PRIVELAGE |= ( 1 << 0);
// read FIFO status in bit [0]:
while(!(ITM_STIMULUS_PORT0 & 1));
//Write to ITM stimulus port0
ITM_STIMULUS_PORT0 = ch;
}
one thing I noticed in debugger is ITM_LOCK_ACCESS register always shows 0 even if I write some value. please let me know if I am doing anything wrong or missing something.
Thanks
2020-04-02 12:28 PM
Hi, it works for me on the same board using STM32CubeIDE 1.3.0 (and used to work before).
In main.c add
int __io_putchar(int ch){
ITM_SendChar(ch);
return(ch);
}
No need to implement ITM_SendChar, that's already done in /Drivers/CMSIS/Include/core_cm4.h.
In the Debug configuration, you have to enable SWV and set the correct clock freq.: 80 MHz (cf. .ioc clock settings).
When debugging halts at the first breakpoint (main()), open the SWV ITM Data Console.
Click on the tools icon (upper right), enable stimulus port 0.
Click on the red record button (must be repeated for each new debug session), et voilà: printf( "Hello world!\n" ); prints on the SWV ITM Data Console.
Don't forget the trailing '\n' because stdout is line buffered unless you change that.
If that really doesn't work, check if a breakpoint in ITM_SendChar is hit when you printf.
hth
KnarfB
2020-04-02 12:38 PM
Doing a lot of unnecessary and duplicative initialization, good chance you're stepping on yourself. Try to separate the SWV initialization from the character output.
The LAR isn't typically used on CM3/CM4 parts, first needed it with CM7
/**
\brief ITM Send Character
\details Transmits a character via the ITM channel 0, and
\li Just returns when no debugger is connected that has booked the output.
\li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
\param [in] ch Character to transmit.
\returns Character to transmit.
*/
__STATIC_INLINE uint32_t 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 (ch);
}
As KnarfB points out the clock speed is critical, but also depends on the debugger and SW clocking. It is possible to compute the baud/bit rate setting if you tool generally uses the same clock, ie 2 MHz for ST-LINK/V2
On the DISCO/NUCLEO boards double check the SWO routing and solder-bridges, make sure PB3/SWO gets all the way to the ST-LINK on-board.