Measuring the number of clock pulses on the cortex m7

I measured the number of clock cycles on cortex m4 and now I would like to do this on cortex m7. The board I use is STM32F746ZG.

For m4, everything worked with:

volatile unsigned int *DWT_CYCCNT; volatile unsigned int *DWT_CONTROL; volatile unsigned int *SCB_DEMCR; void reset_cnt(){ DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register *SCB_DEMCR = *SCB_DEMCR | 0x01000000; *DWT_CYCCNT = 0; // reset the counter *DWT_CONTROL = 0; } void start_cnt(){ *DWT_CONTROL = *DWT_CONTROL | 0x00000001 ; // enable the counter } void stop_cnt(){ *DWT_CONTROL = *DWT_CONTROL & 0xFFFFFFFE ; // disable the counter } unsigned int getCycles(){ return *DWT_CYCCNT; } 

The problem is that the DWT_CTRL register does not change when starting on m7 and remains 0x40000000 instead of changing to 0x40000001, so the number of cycles is always zero. From what I read in other posts, it looks like you need to set the FP_LAR register to 0xC5ACCE55 in order to be able to modify DWT_CTRL.

I added these definitions (tried both FP_LAR_PTR addresses below):

 #define FP_LAR_PTR ((volatile unsigned int *) 0xe0000fb0) //according to reference //#define FP_LAR_PTR ((volatile unsigned int *) 0xe0002fb0) //according to guy on the internet // Lock Status Register lock status bit #define DWT_LSR_SLK_Pos 1 #define DWT_LSR_SLK_Msk (1UL << DWT_LSR_SLK_Pos) // Lock Status Register lock availability bit #define DWT_LSR_SLI_Pos 0 #define DWT_LSR_SLI_Msk (1UL << DWT_LSR_SLI_Pos) // Lock Access key, common for all #define DWT_LAR_KEY 0xC5ACCE55 

and this function:

 void dwt_access_enable(unsigned int ena){ volatile unsigned int *LSR; LSR = (volatile unsigned int *) 0xe0000fb4; uint32_t lsr = *LSR;; //printf("LSR: %.8X - SLI MASK: %.8X\n", lsr, DWT_LSR_SLI_Msk); if ((lsr & DWT_LSR_SLI_Msk) != 0) { if (ena) { //printf("LSR: %.8X - SLKMASK: %.8X\n", lsr, DWT_LSR_SLK_Msk); if ((lsr & DWT_LSR_SLK_Msk) != 0) { //locked: access need unlock *FP_LAR_PTR = DWT_LAR_KEY; printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR); } } else { if ((lsr & DWT_LSR_SLK_Msk) == 0) { //unlocked *FP_LAR_PTR = 0; //printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR); } } } } 

When I call uncommented print, I get 0xC5ACCE55, but when I print it after the function returns, I get 0x00000000, and I have no idea why. Am I on the right track or is it completely wrong?

Edit: I think it would be nice to mention that I tried without all the extra code in the function and only tried to change the LAR register.

BR gustav

+8
c arm embedded stm32f7
source share
2 answers

Looking at the documents again, I am now incredibly suspicious of a typo or copy error in ARM TRM. 0xe0000fb0 is indicated as the address ITM_LAR, DWT_LAR and FP_LSR (and equivalent for * _LSR). Since all other ITM registers are on page 0xe0000000, it looks very horrible, as the one who was responsible for this part of the Cortex-M7 documentation accepted the Cortex-M4 register definitions, added new LARs and LSRs to the ITM page, and then copied them to DWT and FPB pages that update names but do not update addresses.

I would promise that you involuntarily unlock ITM_LAR (or real FP_LAR), and DWT_LAR is actually at 0xe000 1 fb0.

EDIT dwelch

Someone should have lunch for someone.

 hexstring(GET32(0xE0001FB4)); hexstring(GET32(0xE0001000)); hexstring(GET32(0xE0001004)); hexstring(GET32(0xE0001004)); PUT32(0xE000EDFC,0x01000000); hexstring(GET32(0xE0001FB4)); hexstring(GET32(0xE0001000)); hexstring(GET32(0xE0001004)); hexstring(GET32(0xE0001004)); PUT32(0xE0001000,0x40000001); hexstring(GET32(0xE0001FB4)); hexstring(GET32(0xE0001000)); hexstring(GET32(0xE0001004)); hexstring(GET32(0xE0001004)); PUT32(0xE0001FB0,0xC5ACCE55); PUT32(0xE0001000,0x40000001); hexstring(GET32(0xE0001FB4)); hexstring(GET32(0xE0001000)); hexstring(GET32(0xE0001004)); hexstring(GET32(0xE0001004)); 

Exit

 00000000 00000000 00000000 00000000 00000003 40000000 00000000 00000000 00000003 40000000 00000000 00000000 00000001 40000001 0000774F 0000B311 

The table in TRM looks funny, and as other documentation shows, you add 0xFB0 and 0xFB4 to the database, the rest of the DWT for Cortex-M7 is 0xE0001xxx, and it really seems that LAR and LSR are 0xE0001FB0 and 0xE0001FB4.

+2
source share

I would advise against creating your own register definitions when they are defined as part of CMSIS. This requires that the documentation and your interpretation are correct. In this case, it appears that the documentation is indeed incorrect, but the CMSIS headers are correct. It is much easier to check the CMSIS headers automatically than to check the documentation is correct, so I would always trust CMSIS.

I'm not sure which register FP_LAR can refer to, but your address assignment refers to ITM_LAR , but most likely you assumed DWT_LAR , which Cortex-M4 lacks.

Despite my advice to trust him, CMSIS 4.00 does not allow you to define masks for DWT_LSR / SWT_LAR , but I believe that they are identical to the corresponding ITM masks.

Note also that the LAR is a write-only register - any attempt to read it is pointless.

Your code using CMSIS will look like this:

 #include "core_cm7.h" // Applies to all Cortex-M7 void reset_cnt() { CoreDebug->DEMCR |= 0x01000000; DWT->CYCCNT = 0; // reset the counter DWT->CTRL = 0; } void start_cnt() { DWT->CTRL |= 0x00000001 ; // enable the counter } void stop_cnt() { DWT->CTRL &= 0xFFFFFFFE ; // disable the counter } unsigned int getCycles() { return DWT->CYCCNT ; } // Not defined in CMSIS 4.00 headers - check if defined // to allow for possible correction in later versions #if !defined DWT_LSR_Present_Msk #define DWT_LSR_Present_Msk ITM_LSR_Present_Msk ; #endif #if !defined DWT_LSR_Access_Msk #define DWT_LSR_Access_Msk ITM_LSR_Access_Msk ; #endif #define DWT_LAR_KEY 0xC5ACCE55 void dwt_access_enable( unsigned ena ) { uint32_t lsr = DWT->LSR;; if( (lsr & DWT_LSR_Present_Msk) != 0 ) { if( ena ) { if ((lsr & DWT_LSR_Access_Msk) != 0) //locked: access need unlock { DWT->LAR = DWT_LAR_KEY; } } else { if ((lsr & DWT_LSR_Access_Msk) == 0) //unlocked { DWT->LAR = 0; } } } } 
+1
source share

All Articles