SWO_uart output corruption

Using nRF52832 (Cortex M4) and have configured the SWO to output debug printing.

This works fine immediately after programming, but there is intermittent corruption  if the debug/programmer is disconnected and the product is power-cycled.

Setup code is...
void SWO_Init(void)
uint32_t SWOSpeed = 57600; // default baud rate
uint32_t SWOPrescaler = (CPU_CORE_FREQUENCY_HZ / SWOSpeed) + 1; // SWOSpeed in Hz,

CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk; // enable trace in core debug */
*((volatile unsigned *)(ITM_BASE + 0x400F0)) = 0x00000002; // "Selected PIN Protocol Register": Select which protocol to use for trace output (2: SWO NRZ, 1: SWO Manchester encoding)
*((volatile unsigned *)(ITM_BASE + 0x40010)) = SWOPrescaler; // "Async Clock Prescaler Register". Scale the baud rate of the asynchronous output
*((volatile unsigned *)(ITM_BASE + 0x00FB0)) = 0xC5ACCE55; // ITM Lock Access Register, C5ACCE55 enables more write access to Control Register 0xE00 :: 0xFFC
ITM->TCR = ITM_TCR_TraceBusID_Msk | ITM_TCR_SWOENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_ITMENA_Msk; // ITM Trace Control Register
ITM->TPR = ITM_TPR_PRIVMASK_Msk; // ITM Trace Privilege Register
ITM->TER = 1; // ITM Trace Enable Register. Enabled tracing on stimulus port 0
*((volatile unsigned *)(ITM_BASE + 0x01000)) = 0x400003FE; // DWT_CTRL
*((volatile unsigned *)(ITM_BASE + 0x40304)) = 0x00000100; // Formatter and Flush Control Register

We have used the CMSIS SWO_Putchar (core_cm4.h), and tried modifying it to allow for Fifo-full blocking, and re-written it to use exclusive (STREXNE) register accesses.  These did not affect the symptoms.

I think this problem has been seen in other places - https://community.arm.com/developer/ip-products/processors/f/cortex-m-forum/8934/problem-with-swo-when-debugger-not-connected

But no solution has been posted as far as I can tell.

We have also dumped the registers, and the only difference we can find in the coredebug registers is that C_DEBUGEN is set when the SWO is reliable, and is clear when it is not...

The ref manual states that this bit is only accessible through the DAP, so I cannot think of an easy way to test its influence on the problem.

Does anybody have any ideas about this?


  • After much headscratching - another support site gave me this answer

    "When (Cortex M-series) target enters true low power mode (in the absence of debug connection) due to a sleep event and there is data in the ITM/TPIU that has not been flushed, then the data stream gets mangled with garbage due to what appears to be clock gating/changes when core transitions to sleep."

    When the debugger is active, the core does not go into deep sleep, so this does not occur.

    Another user has found the exact same problem using WFE.

    It would be good to wait for TX_done, but the only flags I can find are ITM busy, and FIFO available.  Neither of those are suitable to hold off the WFE instruction.