cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot set ITMENA

avidroneg
Associate III

I'm attempting to follow https://community.st.com/t5/stm32-mcus/using-the-itm-console-for-printf-redirects-and-lwip-debug/tac-p/850072/highlight/true#M1661 but this always fails. This is on an STM32F303K8T. My reference manual says

avidroneg_0-1769105638276.png

and offers an example:

    "To output a simple value to the TPIU:
• Configure the TPIU and assign TRACE I/Os by configuring the DBGMCU_CR (refer to
Section 33.17.2: TRACE pin assignment and Section 33.16.3: Debug MCU
configuration register)
• Write 0xC5ACCE55 to the ITM Lock Access Register to unlock the write access to the
ITM registers
• Write 0x00010005 to the ITM Trace Control Register to enable the ITM with Sync
enabled and an ATB ID different from 0x00
• Write 0x1 to the ITM Trace Enable Register to enable the Stimulus Port 0
• Write 0x1 to the ITM Trace Privilege Register to unmask stimulus ports 7:0
• Write the value to output in the Stimulus Port Register 0: this can be done by software
(using a printf function)"

Based on this, and based on the IDE-provided definition of ITM_SendChar:

/**
  \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);
}

I have written:

// Number of ITM ports (defined by the ARM standard)
static const size_t N_PORTS = 32u;


bool logi_enable_itm(void) {
    // Follow along with 33.14.2 'Example of configuration'

    // 1. Configure the TPIU and assign TRACE I/Os by configuring the DBGMCU_CR
    // Done by the debugger host (i.e. Cube).

    // 2. Write 0xC5ACCE55 to the ITM Lock Access Register to unlock the write access to the
    // ITM registers
    ITM->LAR = 0xC5ACCE55u;

    // 3. Write to the ITM Trace Control Register to enable the ITM
    ITM->TCR = ITM_TCR_ITMENA_Msk;

    // 4. Write to the ITM Trace Enable Register to enable the Stimulus Ports
    ITM->TER = 0b111111u;

    // 5. Write 0x1 to the ITM Trace Privilege Register to unmask stimulus ports 7:0
    ITM->TPR = 1u;

    // (not documented)
    // ITM->LAR = 0u;

    return true;
}

static bool ITM_SendCharTo(uint8_t ch, uint8_t port) {
    if (port >= N_PORTS)
    	return false;
    const uint32_t
        tcr = ITM->TCR & ITM_TCR_ITMENA_Msk,  // ITM enabled
        ter = ITM->TER & (1u << port);        // port enabled
    if (!(tcr && ter))
        return false;

    while (ITM->PORT[port].u32 == 0u)
        __NOP();

    ITM->PORT[port].u8 = ch;
    return true;
}

 

but this always hangs on the NOP loop. I've also tried changing the ITM_TCR_TraceBusID and enabling SYNC, to no avail.

What could be happening here?

1 REPLY 1
avidroneg
Associate III

Right after posting this, I found that STCube's SWV ITM Data Console needed to have Start Trace enabled for the loop to unblock, which I guess is what is implied by the SYNC feature. That's fine for debugging I guess, but this seems like a non-starter for production when the debugger is not connected.