/*
Cortex-M3,M4,M7内核有一个外设叫DWT(Data Watchpoint and Trace),用于系统调试及跟踪。
它有一个32位的寄存器叫CYCCNT,它是一个向上的计数器,记录的是内核时钟运行的个数,内核时钟跳动一次,该计数器就加1,精度非常高。
当CYCCNT溢出之后,会清0重新开始向上计数。
1、使能DWT外设,由内核调试寄存器DEMCR的位24控制,写1使能。DEMCR的地址是0xE000 EDFC
2、使能DWT的CYCCNT计数器,由DWT->CTRL的bit0控制
3、获取计数值DWT_CYCCNT
*/
#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
/* Debug Exception and Monitor Control Register Definitions */
#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
#define DEMCR *(__IO uint32_t *)(CoreDebug_BASE + 0x0C)
#define DWT_CTRL *(__IO uint32_t *)(DWT_BASE)
#define DWT_CYCCNT *(__IO uint32_t *)(DWT_BASE + 0x04)
/* CPU core clock frequency. */
#define CPU_CORE_CLOCK CLOCK_GetFreq(kCLOCK_CpuClk)
void enableCpuCycleCounter(void)
{
/* Make sure the DWT trace fucntion is enabled. */
if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & DEMCR))
{
DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
}
/* CYCCNT not supported on this device. */
//assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk));
/* Read CYCCNT directly if CYCCENT has already been enabled, otherwise enable CYCCENT first. */
if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT_CTRL))
{
DWT_CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
}
uint32_t getCpuCycleCount(void)
{
return DWT_CYCCNT;
}
/*
core clock frequency.
内核时钟600Mhz,周期是1/600us,跳动一次时间是1/600us
假设现在要延时1us,则需要跳动1/(1/600)=600次,即CYCCNT累加了600
*/
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)(((uint64_t)(us) * (clockFreqInHz)) / 1000000U)
uint32_t get_distance_32(uint32_t ori,uint32_t cur )
{
return (uint32_t)(( ( ori ) > ( cur ) ) ? ( 0xFFFFFFFF - ( ori ) + ( cur ) + 1) : ( ( cur ) - ( ori ) ));
}
void delay_us(uint32_t delayTime_us, uint32_t coreClock_Hz)
{
uint32_t startTime,curTime,count;
if (delayTime_us > 0U)
{
count = USEC_TO_COUNT(delayTime_us, coreClock_Hz);
startTime = getCpuCycleCount();
while(1)
{
curTime = getCpuCycleCount();
if(get_distance_32(startTime,curTime)>count)
break;
}
}
}