Lyon 3 Posted March 31, 2014 Share Posted March 31, 2014 Hi, Found on web several postings related to some available, but unused hardware on Cortex-Mx processors (unused on some platforms, available on others. Adapted for TM4C as below: #include "inc/hw_nvic.h" /* for definition of NVIC_DBG_INT */ #include "inc/hw_memmap.h" /* for definition of DWT_BASE */ #include "inc/hw_types.h" /* for definition of HWREG */ #define DWT_O_CYCCNT 0x00000004 static uint32_t c_start, c_stop; // declaration of an initialization function void EnableTiming(void); // definition of that function /******************************************************************************/ void EnableTiming(void){ HWREG(NVIC_DBG_INT) |= 0x01000000; /*enable TRCENA bit in NVIC_DBG_INT*/ HWREG(DWT_BASE + DWT_O_CYCCNT) = 0; /* reset the counter */ HWREG(DWT_BASE) |= 0x01; /* enable the counter */ enabled = 1; } /******************************************************************************/ // and then, in the code to be examined write these: EnableTiming(); c_start = HWREG(DWT_BASE + DWT_O_CYCCNT); // at the beginning of the tested code // your code follows here c_stop = HWREG(DWT_BASE + DWT_O_CYCCNT); // at the end of the tested code // then c_stop - c_start is the execution number of cycles for the code; // just multiply with clock period to find out the execution time of the code. // At 80MHz, the 32 bit counter gives you a total time 2^32 x 12.5ns = ~53 seconds! // Another interesting function is this one /**********************************************************/ void TimingDelay(unsigned int tick) { unsigned int start, current; start = HWREG(DWT_BASE + DWT_O_CYCCNT); do { current = HWREG(DWT_BASE + DWT_O_CYCCNT); } while((current-start)<tick); } /*********************************************************/ Enjoy! L spirilis, bluehash, igor and 3 others 6 Quote Link to post Share on other sites
pabigot 355 Posted April 8, 2014 Share Posted April 8, 2014 Excellent; thank you. For reference, here's a portable version using CMSIS, checked on Tiva and EFM32 processors. (You will need to include the CMSIS device header, e.g. TIVA.h for TM4C and em_device.h for EFM32. That's hidden in bspacm/core.h below.) For reference, the necessary information is in the ARMv7-M Architecture Reference Manual; you have to register with ARM to download the PDF. See sections C1.6.5 for DEMCR and C1.8 for DWT. /* BSPACM - demonstrate cycle counter interface * * Written in 2014 by Peter A. Bigot <http://pabigot.github.io/bspacm/> * * To the extent possible under law, the author(s) have dedicated all * copyright and related and neighboring rights to this software to * the public domain worldwide. This software is distributed without * any warranty. * * You should have received a copy of the CC0 Public Domain Dedication * along with this software. If not, see * <http://creativecommons.org/publicdomain/zero/1.0/>. */ #include <bspacm/core.h> #include <stdio.h> #define BSPACM_CORE_ENABLE_CYCCNT() do { \ if (! (DWT_CTRL_NOCYCCNT_Msk & DWT->CTRL)) { \ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; \ DWT->CYCCNT = 0; \ DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; \ } \ } while (0) #define BSPACM_CORE_DISABLE_CYCCNT() do { \ if (! (DWT_CTRL_NOCYCCNT_Msk & DWT->CTRL)) { \ DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; \ CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; \ } \ } while (0) #define BSPACM_CORE_CYCCNT() DWT->CYCCNT #define BSPACM_CORE_DELAY_CYCLES(cycles_) do { \ uint32_t const delta = (cycles_); \ uint32_t const cc0 = DWT->CYCCNT; \ while ((DWT->CYCCNT - cc0) < delta) { \ /* spin */ \ } \ } while (0) void main () { uint32_t cc0 = 0; BSPACM_CORE_ENABLE_INTERRUPT(); printf("\n" __DATE__ " " __TIME__ "\n"); printf("System clock %lu Hz\n", SystemCoreClock); if (DWT_CTRL_NOCYCCNT_Msk & DWT->CTRL) { printf("DWT does not support cycle counting\n"); return; } BSPACM_CORE_ENABLE_CYCCNT(); do { uint32_t cc1 = DWT->CYCCNT; uint32_t delta = cc1 - cc0; printf("Cycle counter %lu, delta %lu\n", cc1, delta); cc0 = cc1; BSPACM_CORE_DELAY_CYCLES(8000000U); } while (1); } Lyon and bluehash 2 Quote Link to post Share on other sites
bluehash 1,581 Posted April 13, 2014 Share Posted April 13, 2014 Sweetness! Thanks guys. Quote Link to post Share on other sites
Mr.Cruz 0 Posted April 30, 2014 Share Posted April 30, 2014 Nice code dump! Just thought I'd add a few notes: In the first implementation, if you make the functions inline, the compiler can optimize out the function jump, and you can get a slightly more accurate time measurement (pushing/popping registers to go to and from functions generally takes around 12 cycles if I recall) CMSIS is interesting, and I have yet to get a chance to play with it. I think the CMSIS example will be more accurate due to the #define macros (no pushing/popping registers from the stack), but some cycles will be lost due to de-referencing. Nice code dumps! Quote Link to post Share on other sites
pabigot 355 Posted April 30, 2014 Share Posted April 30, 2014 CMSIS is interesting, and I have yet to get a chance to play with it. I think the CMSIS example will be more accurate due to the #define macros (no pushing/popping registers from the stack), but some cycles will be lost due to de-referencing. FWIW, DWT is a compile-time constant pointer, not a variable, so there's no double-dereference (the CYCCNT value is read directly from its register). This is true of all CMSIS pointers to mapped memory. Mr.Cruz 1 Quote Link to post Share on other sites
Mr.Cruz 0 Posted April 30, 2014 Share Posted April 30, 2014 Ah! Wonderful!I may look at CMSIS yet! Quote Link to post Share on other sites
krishnat 0 Posted February 6, 2017 Share Posted February 6, 2017 Hi ,which systemclock should I configure with ADC & timer module ( I am using both module in same code)..??SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); freq = SysCtlClockGet(); // 80MHzSysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); freq = SysCtlClockGet(); // 50MHzSysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); freq = SysCtlClockGet(); // 40MHzIf I dont write any of above, I get :: freq = SysCtlClockGet(); // 16MHzMy requirement is lowest execution time.Should I configure to 80MHz..?? If I do so will both ADC and Timers will work fine..??Is any extra configuration needed...?Regards,Krishnat Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.