Source: https://blog.csdn.net/booksyhay/article/details/109028712
Compiled by: Technology Makes Dreams Greater | Li Xiaoyao
DWT Tracking Component
Cortex-M3 Authority Guide:
16.2 TRACE COMPONENTS: DWT
The rest of the DWT counters are typically used for profiling the application codes. They can be programmed to emit events (in the form of trace packets) when the counter overflows. One typical application is to use the CYCCNT register to count the number of clock cycles required for a specific task, for benchmarking purposes.
16.2 Trace Components: Data Watchpoint and Trace (DWT)

There are remaining counters in DWT that are typically used for profiling application code. By programming them, they can emit events (in the form of trace packets) when the counter overflows. The most typical application is to use the CYCCNT register to measure the number of cycles taken to execute a specific task, which can also be used for timing benchmarks (such as CPU usage statistics in an operating system).
DWT in Cortex-M
In Cortex-M, there is a peripheral called DWT (Data Watchpoint and Trace), which is used for system debugging and tracing.

It has a 32-bit register called CYCCNT, which is an up counter that records the number of kernel clock cycles. Each time the kernel clock ticks, this counter increments by 1. The precision is very high; if the kernel clock is 72M, the precision is 1/72M = 14ns, which is sufficient since the execution time of programs is typically in microseconds, so 14ns precision is more than enough.
The maximum recordable time is: 59.65s. The calculation method is 2^32/72000000.
When CYCCNT overflows, it resets to 0 and starts counting again.
Usage Method
To implement the delay function, three registers are involved: DEMCR, DWT_CTRL, and DWT_CYCCNT, which are used to enable DWT functionality, enable CYCCNT, and obtain the system clock count value, respectively.
DEMCR
To enable the DWT peripheral, it needs to be controlled by bit 24 of another core debug register, DEMCR, where writing 1 enables it (important to note for exams!!). The address of DEMCR is 0xE000 EDFC
About DWT_CYCCNT
Before enabling the DWT_CYCCNT register, clear it to 0. Let’s look at the base address of DWT_CYCCNT; from the ARM-Cortex-M manual, we can see that its base address is 0xE000 1004, and the reset default value is 0. It is readable and writable; writing 0 to 0xE000 1004 clears the DWT_CYCCNT.

About CYCCNTENA
CYCCNTENA enables the CYCCNT counter. If not enabled, the counter does not count and no event is generated for PS sampling or CYCCNTENA. In normal use, the debugger must initialize the CYCCNT counter to 0. It is the first bit of the DWT control register; writing 1 enables it, otherwise the CYCCNT counter will not work.
[https://developer.arm.com/documentation/ddi0337/e/system-debug/dwt/summary-and-description-of-the-dwt-registers?lang=en]

In Summary
Steps to use DWT’s CYCCNT:
-
First, enable the DWT peripheral, controlled by bit 24 of the core debug register DEMCR, write 1 to enable it.
-
Clear the DWT_CYCCNT register to 0 before enabling it.
-
Enable the CYCCNT register, controlled by DWT’s CYCCNTENA, which is bit 0 of the DWT control register, write 1 to enable it.
Register Definitions:
//0xE000EDFC DEMCR RW Debug Exception and Monitor Control Register.
//Enable DWT module functionality
#define DEMCR ( *(unsigned int *)0xE000EDFC )
#define TRCENA ( 0x01 << 24) // DWT enable bit of DEMCR
//0xE0001000 DWT_CTRL RW The Debug Watchpoint and Trace (DWT) unit
//Enable CYCCNT counter to start counting
#define DWT_CTRL ( *(unsigned int *)0xE0001000 )
#define CYCCNTENA ( 0x01 << 0 ) // DWT's SYCCNT enable bit
//0xE0001004 DWT_CYCCNT RW Cycle Count register,
//Internal value of CYCCNT counter (32-bit unsigned)
#define DWT_CYCCNT ( *(unsigned int *)0xE0001004) //Display or set processor cycle count value
Usage Example:
vvolatile unsigned int *DWT_CYCCNT ;
volatile unsigned int *DWT_CONTROL ;
volatile unsigned int *SCB_DEMCR ;
void reset_timer(){
DWT_CYCCNT = (int *)0xE0001004; //address of the register
DWT_CONTROL = (int *)0xE0001000; //address of the register
SCB_DEMCR = (int *)0xE000EDFC; //address of the register
*SCB_DEMCR = *SCB_DEMCR | 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CONTROL = 0;
}
void start_timer(){
*DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter
}
void stop_timer(){
*DWT_CONTROL = *DWT_CONTROL | 0 ; // disable the counter
}
unsigned int getCycles(){
return *DWT_CYCCNT;
}
main(){
....
reset_timer(); //reset timer
start_timer(); //start timer
//Code to profile
...
myFunction();
...
stop_timer(); //stop timer
numCycles = getCycles(); //read number of cycles
...
}
Example 2:
#define start_timer() *((volatile uint32_t*)0xE0001000) = 0x40000001 // Enable CYCCNT register
#define stop_timer() *((volatile uint32_t*)0xE0001000) = 0x40000000 // Disable CYCCNT register
#define get_timer() *((volatile uint32_t*)0xE0001004) // Get value from CYCCNT register
/***********
* How to use:
* uint32_t it1, it2; // start and stop flag
start_timer(); // start the timer.
it1 = get_timer(); // store current cycle-count in a local
// do something
it2 = get_timer() - it1; // Derive the cycle-count difference
stop_timer(); // If timer is not needed any more, stop
print_int(it2); // Display the difference
****/
Example 3:
#define DWT_CR *(uint32_t *)0xE0001000
#define DWT_CYCCNT *(uint32_t *)0xE0001004
#define DEM_CR *(uint32_t *)0xE000EDFC
#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)
/* Initialize timestamp */
void CPU_TS_TmrInit(void)
{
/* Enable DWT peripheral */
DEM_CR |= (uint32_t)DEM_CR_TRCENA;
/* Clear DWT CYCCNT register count to 0 */
DWT_CYCCNT = (uint32_t)0u;
/* Enable Cortex-M3 DWT CYCCNT register */
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}
uint32_t OS_TS_GET(void)
{
return ((uint32_t)DWT_CYCCNT);
}
Copyright Notice:This article is sourced from the internet, freely conveying knowledge, copyright belongs to the original author. If there are copyright issues, please contact me for deletion.
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
Follow my WeChat public account, reply "Join Group" to join the technical exchange group according to the rules.
Click "Read the original text" for more sharing, welcome to share, collect, like, and view.