2022-04-26 11:47 AM
I'm using the STM32F769-DISC0 development board and am utilizing the DWT->CYCCNT to calculate cpu load as well as using it as a high speed timer that runs at the clock frequency. When the debugger is plugged in, it functions fine. However, with the debugger unplugged, it iterates at a much lower rate and does not match the clock frequency.
I'm using the following code to enable DWT_CNT, and the LSR and CTR registers indicate it is on, but the problem continues with the debugger unplugged. I *must* be missing something, however I cannot find anything in the user manual that indicates what register (if any) I'm missing?
CoreDebug->DEMCR &= ~0x01000000;
CoreDebug->DEMCR |= 0x01000000; // TRCENA
DWT->LAR = 0xC5ACCE55; // unlock
DWT->CYCCNT = 0; // reset the counter
DWT->CTRL &= ~0x00000001;
DWT->CTRL |= 0x00000001; // enable the counter
2022-04-26 01:10 PM
> However, with the debugger unplugged, it iterates at a much lower rate and does not match the clock frequency.
How are you determining this exactly?
2022-04-26 01:17 PM
I'm using TIM10 in IC mode and record the DWT_CYCCNT at each edge and calculate frequency from it. With the debugger unplugged the frequency calculation is way higher than reality (Keysight scope on frequency signal for verification). When I noticed this discrepancy I leveraged the USB peripheral to transmit logging data at 1khz sample rate to a desktop client and included the DWT_CYCCNT value at each 1ms sample point. With the debugger plugged in, the cycle count is as expected... otherwise it's not, not even close.
The cpu load calculation is also significantly broken -- 4% with the debugger plugged in, and 92% with the debugger unplugged (as it leverages the CYCCNT).
2022-04-26 11:08 PM
One explanation may be, that your system clock frequency is lower without the debugger connected. Output SYSCLK onto MCO.
JW
2022-04-27 06:51 AM
I've verified that SYSCLK is 200MHz via MCO1 (SRC PLLCLK) whether the debugger plugged in or not -- so the clocks are correct. Using Keysight scope w/ Tektronix 1103 TEKPROBE.
2022-04-27 06:55 AM
Perhaps you are resetting DWT->CYCCNT at some point(s) in your code? Perhaps the core goes to sleep?
DWT->CYCCNT is part of the ARM core. It's unlikely to have a huge unrecognized, unreported hardware fault like this. Using DWT->CYCCNT for high-precision timing measurements is very common.
2022-04-27 08:14 AM
Prepare a minimal but complete compilable program, which outputs CYCCNT upon some stimulus (pin change) e.g. through USART. Try to avoid any "framework" or "library" such as Cube, RTOS, etc.
If this program still exhibits the problem, post this program.
JW
2022-04-27 10:12 AM
It appears the wfi instruction is the culprit, although I do not understand why and cannot find any explanation in either ST's user guide or in the ARM M7 Reference manual that would explain the "pause" of the CYCCNT. I put together a very basic application that only turns on USART1 and CYCCNT.
The program is clocked to 200MHz and just outputs CYCCNT and SYSTICK count to Serial after a WFI instruction. The more WFI instructions I add, the more of a pause I get in CYCCNT. For instance, with two WFI instructions, CYCCNT/SysTick gets me ~106MHz, while one WFI instruction gets me ~161MHz. This is with the debugger not running. Once the debugger is running I always get the correct CYCCNT.
Clearly I'm missing something, but I cannot find any reference material that explains this behavior (if it is expected). The same WFI instruction is used on my F4 projects to calculate cpu load by keeping track of CYCCNT in WFI (boiler plate as I understood it).
Without debugger:
With debugger:
2022-04-27 10:15 AM
I've found that it is the wfi instruction causing this when the debugger isn't running. Clearly I'm missing something that the debugger is changing and I need to address myself, but not seeing what it is?
2022-04-27 10:17 AM