Skip to main content
VMiki.1
Associate II
April 26, 2022
Question

STM32F769 DWT CYCCNT

  • April 26, 2022
  • 16 replies
  • 6413 views

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

This topic has been closed for replies.

16 replies

TDK
April 26, 2022

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

"If you feel a post has answered your question, please click ""Accept as Solution""."
VMiki.1
VMiki.1Author
Associate II
April 26, 2022

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).

TDK
April 27, 2022

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.

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
April 27, 2022

One explanation may be, that your system clock frequency is lower without the debugger connected. Output SYSCLK onto MCO.

JW

VMiki.1
VMiki.1Author
Associate II
April 27, 2022

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.

waclawek.jan
Super User
April 27, 2022

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

VMiki.1
VMiki.1Author
Associate II
April 27, 2022

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:

0693W00000LzF28QAF.png 

With debugger:

0693W00000LzF1tQAF.png 

0693W00000LzF3VQAV.png 

TDK
April 27, 2022
WFI puts the core to sleep. It waits for an instruction before it wakes up.
"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
April 27, 2022

I'd expect that to diminish the power saving from WFI to zero. Can you please comment/measure?

JW

waclawek.jan
Super User
May 1, 2022

> The same WFI instruction is used on my F4 projects to calculate cpu load by keeping track of CYCCNT in WFI

I've just tried on an 'F429:

  • WFE (I am lazy to write even a minimal ISR) with SCB_SCR.SLEEPDEEP=0 results in DWT_CYCCNT running continuously from system clock
  • WFE with SCB_SCR.SLEEPDEEP=1 (I did not bother with setting the bits in PWR which would switch off the regulators) results in DWT_CYCCNT stopping during the sleep period, while it keeps running at cca 16MHz (presumably HSI) if the DBG bits in DBGMCU_CR (I was lazy to found out which one particularly, I presume DBG_STOP)

So, the behaviour mainly depends on state of SLEEPDEEP bit in processor. I don't think this is much different in Cortex-M7.

@VMiki.1​ , how do you set SLEEPDEEP?

JW

VMiki.1
VMiki.1Author
Associate II
May 2, 2022

SCB_SCR.SLEEPDEEP is 0, was the first thing I checked. This DWT_CYCCNT behavior is "new to me" for the F7.

Piranha
Principal III
May 1, 2022

> with the debugger unplugged

When on F7 I disconnect a J-Link with a GUI from the IDE (not the hardware), it stops the DWT->CYCCNT. Most likely disables some bits in CoreDebug->DEMCR and DWT->CTRL. Of course, after resetting the MCU manually, the code configures the necessary bits and the CPU load measuring works again.