- 简述:
- 时间戳主要用来测试任务时行时长,以此来判断该段代码的执行效率;如果时间过长就可以优化调整代码;
- 本质上就是一个任务起始——>终止的时间点;
- 测试方式:
- 比如测量任务A的执行效率,在A任务运行前记录一个时间点TimeStart,运行完记录一个时间点TimeEnd;那么这段代码的运行时长TimeUse = TimeEnd - TimeStart;这两个时间点就叫做时间戳
- 实现方式:
- 以Crtotex-M3为例,任务的执行时长是ns级的;但通常的硬件定时器只有us级,远远达不到测量几条代码运行时长的精度;
- 但在Crotex-M内核中,有一个DWT,该外设有一个32的寄存器叫CYCCNT,它是一个向上的计数器,记录内核时钟HCLK运行的个数,溢出自动清零重新向上计数,该计数器正好可以用来实现时间戳的功能;
- 以M3为例,HCLK时钟最高为72Mhz,单个时钟周期 = 1/72M = 14ns;CYCCNT最大记录时间为2^32 * 14 = 60S;
- 例程:
/* ************************************************************************************************************************ * 时间戳 ************************************************************************************************************************ */ #if (OS_CFG_TS_EN == 1u) #define OS_TS_GET() (CPU_TS)CPU_TS_TmrRd() #else #define OS_TS_GET() (CPU_TS)0u #endif /********************************************************* * 函数名:void CPU_Init (void); * 描述 :CPU初始化,包含如下 1、初始化时间戳 2、初始化中断使能时间测量 3、初始化CPU名字 本实验只写第一个功能 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ void CPU_Init (void) { #if((CPU_CFG_TS_EN == DEF_ENABLED) || (CPU_CFG_TS_TMR_EN == DEF_ENABLED)) CPU_TS_Init(); //初始化时间戳 #endif } /********************************************************* * 函数名:static void CPU_TS_Init (void); * 描述 : 1、初始化时间戳 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ #if((CPU_CFG_TS_EN == DEF_ENABLED) || (CPU_CFG_TS_TMR_EN == DEF_ENABLED)) static void CPU_TS_Init(void) { #if(CPU_CFG_TS_TMR_EN == DEF_ENABLED) CPU_TS_TmrFreq_Hz = 0u; CPU_TS_TmrInit(); //初始化时间戳定时器 #endif } #endif /********************************************************* * 函数名:void CPU_TS_TmrInit (void); * 描述 : 1、初始化时间戳定时器 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED) void CPU_TS_TmrInit (void) { CPU_INT32U fclk_freq; fclk_freq = BSP_CPU_ClkFreq(); //使能DWT外设 BSP_REG_DEM_CR |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA; //DWT CYCCNT寄存器计数器清0 BSP_REG_DWT_CYCCNY = (CPU_INT32U)0; /*注意:当使用软件仿真全速运行的时候,会先停在这里, 就好像在这里设置了一个断点一样,需要手动运行才能跳过, 当使用硬件仿真的时候却不会; */ BSP_REG_DWT_CR |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA; //设置时间戳定时器频率为系统频率 CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq); } #endif /********************************************************* * 函数名:CPU_INT32U BSP_CPU_ClkFreq (void); * 描述 : 1、获取CPU的HCLK时钟 2、软件仿真,直接返回25Mhz; * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ CPU_INT32U BSP_CPU_ClkFreq (void) { CPU_INT32U CPU_HCLK; //软件仿真用的25Mhz; CPU_HCLK = 25000000; return CPU_HCLK; } /********************************************************* * 函数名:void CPU_TS_TmrFreqSet (CPU_TS_TMR_FREQ freq_hz); * 描述 : 1、设置时间戳定时器时钟频率(默认等于系统时钟) * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ #if (CPU_CFG_TS_TMR_EN == DEF_ENABLED) void CPU_TS_TmrFreqSet (CPU_TS_TMR_FREQ freq_hz) { CPU_TS_TmrFreq_Hz = freq_hz; } #endif /********************************************************* * 函数名:CPU_TS_TMR CPU_TS_TmrRd (void); * 描述 : 1、获取时间戳当前时间 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ #if(CPU_CFG_TS_TMR_EN == DEF_ENABLED) CPU_TS_TMR CPU_TS_TmrRd (void) { CPU_TS_TMR ts_tmr_cnts; ts_tmr_cnts = (CPU_TS_TMR)BSP_REG_DWT_CYCCNY; return ts_tmr_cnts; } #endif
- 总结:
- 本例程需要硬件仿真;
- 实际用到;时间戳初始化CPU_Init();
- 获取当前时间:OS_TS_GET();