Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STM32 - How to enable DWT Cycle counter

I am using the STM32F7-Discovery board and have been stuck at trying to enable the DWT cycle counter. From what I've seen online this should suffice for enabling it:

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL  |= 1;

However, whenever I run that code the values are not changed or the operations are skipped (I am not too sure what is happening).

I've tried making pointers to the addresses in memory and altering them directly with no avail either. Ex:

volatile uint32_t *DWT_CONTROL = (uint32_t *) 0xE0001000;
volatile uint32_t *DWT_CYCCNT = (uint32_t *) 0xE0001004;
volatile uint32_t *DEMCR = (uint32_t *) 0xE000EDFC;
*DEMCR = *DEMCR | 0x01000000;
*DWT_CYCCNT  = 0;
*DWT_CONTROL = *DWT_CONTROL | 1;

Currently, the only way I've gotten the is when stepping through with the debugger in Visual Studios (with VisualGDB), if I change the value of DWT->CTRL to the ON value the cycle counter begins. Aside from that though, I cannot seem to get the value to change in code.

Edit: What could be causing the behavior where these lines of code are not performing their tasks but also not crashing and continuing.

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL  |= 1;

After running these lines of codes, all of the values at those memory locations stay the same and are not altered with the operations that were supposed to be performed.

E.G. :

//DWT_CTRL_CYCCNTENA_Msk = 1
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk 

Should result in the value of DWT->CTRL being 0x40000001 but it remains at its default value 0x40000000

The pictures below are an example of what is occurring during runtime.

Before: Before

After: After

like image 411
KenQueso Avatar asked Apr 02 '16 20:04

KenQueso


3 Answers

Maybe missing to unlock the dbg regs (DWT->LAR = 0xC5ACCE55): Sequence below solved pb for me :

      CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
      DWT->LAR = 0xC5ACCE55; 
      DWT->CYCCNT = 0;
      DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
like image 153
Howard Plouch Avatar answered Nov 16 '22 17:11

Howard Plouch


Not sure if that is identical on the STM32F7, but this is how to do it correctly using the CMSIS headers on a STM32F4 (should actually work on any Cortex-M3/4(/7?) which provides this module):

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

You have to enable the trace module, too. Caution the code is not interrupt-safe! In general, you should leave the counter just free running and take differences of snapshots for timing.

Just make sure your toolchain does not use interfere with your code. OpenOCD/gdb do not, not sure how about tools which provide a manual profiling funtionality.

As I already emphasised in the comments: Don't use some homebrew definitions for registers. ST (and ARM) provide CMSIS headers for the standard peripheral modules (DWT and CoreDebug are actually ARM IPs) which you should use. This includes not using magic numbers, but the defined constants/macros.

More information can be found in the "Architecture Reference Manual". Caution: there is also an "Architecture Application Level Reference Manual", which is not what you want.

like image 35
too honest for this site Avatar answered Nov 16 '22 17:11

too honest for this site


You are doing everything right, except you are missing to unlock access to DWT register (as Howard pointed out). In your code it would be something like:

volatile uint32_t *DWT_CONTROL = (uint32_t *) 0xE0001000;
volatile uint32_t *DWT_CYCCNT = (uint32_t *) 0xE0001004;
volatile uint32_t *DEMCR = (uint32_t *) 0xE000EDFC;
volatile uint32_t *LAR  = (uint32_t *) 0xE0001FB0;   // <-- added lock access register

*DEMCR = *DEMCR | 0x01000000;     // enable trace
*LAR = 0xC5ACCE55;                // <-- added unlock access to DWT (ITM, etc.)registers 
*DWT_CYCCNT = 0;                  // clear DWT cycle counter
*DWT_CONTROL = *DWT_CONTROL | 1;  // enable DWT cycle counter

Note that, as stated in ARMv7-M Architecture Reference Manual, lock mechanism only applies to software access. DAP access is always allowed (that's why you could enable cycle counter using the debugger).

Please note that both STM32F7 documentation and ARM documentation have a typo and give 0xE0000FB0 as address of Lock Access register (see here). Using provided CMSIS core registres definitions (core_cm7.h) would have avoided you this problem since they are correct, and of course would have been more efficient as Olaf stated ;)

like image 4
paolok17 Avatar answered Nov 16 '22 19:11

paolok17