天南地北客
发表于: 2017-2-7 16:26:03 | 显示全部楼层

一些ARM Cortex-M内核实现了DWT(数据观察点和跟踪)单元,该单元有一个很好的功能,在内部可以计算执行周期。 DWT通常在大多数Cortex-M3、M4和M7器件上都已经实现了,包括如恩智浦的Kinetis或LPC器件。

dwt-cycle-count-register.jpg


概览

执行分析工具,如SEGGER SystemView,使用DWT来测量代码执行所用的时间。 这篇文章主要介绍如何直接从应用程序代码使用,或启用周期计数并且在调试时进行监视。


寄存器和访问函数

DWT通常在Cortex-M3或更高版本中实现,但Cortex-M0(+)没有实现改功能。 要使用该功能,需要访问几个调试寄存器。 您可以使用CMSIS-Core头文件来实现此目的,但由于在不使用CMSIS-Core的情况时只有很少的寄存器,因此需要下面我将要使用的定义:

  1. /* DWT (Data Watchpoint and Trace) registers, only exists on ARM Cortex with a DWT unit */
  2.   #define KIN1_DWT_CONTROL             (*((volatile uint32_t*)0xE0001000))
  3.     /*!< DWT Control register */
  4.   #define KIN1_DWT_CYCCNTENA_BIT       (1UL<<0)
  5.     /*!< CYCCNTENA bit in DWT_CONTROL register */
  6.   #define KIN1_DWT_CYCCNT              (*((volatile uint32_t*)0xE0001004))
  7.     /*!< DWT Cycle Counter register */
  8.   #define KIN1_DEMCR                   (*((volatile uint32_t*)0xE000EDFC))
  9.     /*!< DEMCR: Debug Exception and Monitor Control Register */
  10.   #define KIN1_TRCENA_BIT              (1UL<<24)
  11.     /*!< Trace enable bit in DEMCR register */
复制代码

为了使用这些寄存器,我已经定义了一组“类似函数”的宏,可以在应用程序代码中使用:

  1. #define KIN1_InitCycleCounter() \
  2.   KIN1_DEMCR |= KIN1_TRCENA_BIT
  3.   /*!< TRCENA: Enable trace and debug block DEMCR (Debug Exception and Monitor Control Register */

  4. #define KIN1_ResetCycleCounter() \
  5.   KIN1_DWT_CYCCNT = 0
  6.   /*!< Reset cycle counter */

  7. #define KIN1_EnableCycleCounter() \
  8.   KIN1_DWT_CONTROL |= KIN1_DWT_CYCCNTENA_BIT
  9.   /*!< Enable cycle counter */

  10. #define KIN1_DisableCycleCounter() \
  11.   KIN1_DWT_CONTROL &= ~KIN1_DWT_CYCCNTENA_BIT
  12.   /*!< Disable cycle counter */

  13. #define KIN1_GetCycleCounter() \
  14.   KIN1_DWT_CYCCNT
  15.   /*!< Read cycle counter register */
复制代码


典型用法

要使用周期计数功能,必须配置和启用DWT。 如果使用调试器连接到目标,则DWT通常已经由调试器启用。 要使得它在没有活动的调试会话下工作正常,必须首先在代码中进行初始化。

  1. uint32_t cycles; /* number of cycles */

  2. KIN1_InitCycleCounter(); /* enable DWT hardware */
  3. KIN1_ResetCycleCounter(); /* reset cycle counter */
  4. KIN1_EnableCycleCounter(); /* start counting */
  5. foo(); /* call function and count cycles */
  6. cycles = KIN1_GetCycleCounter(); /* get cycle counter */
  7. KIN1_DisableCycleCounter(); /* disable counting if not used any more */
复制代码

周期计数器

在调试会话期间监视周期计数器很容易实现:在“Expressions”视图中添加以下表达式:

  1. (*((volatile uint32_t*)0xE0001004))
复制代码

通过这样,视图就可以显示当前的周期计数器了:

cycle-counter-in-expression-view.jpg


总结

如果您正在使用的ARM Cortex-M具有DWT功能,那么可以使用周期计数器来测量执行代码所花费的周期。这种方式可以用于延迟循环或者测量执行时间。


参考连接:

■    DEMCR寄存器:http://infocenter.arm.com/help/i ... 0337e/CEGHJDCF.html

■    DWT寄存器: http://infocenter.arm.com/help/i ... 0439b/BABJFFGJ.html

■    DWT控制寄存器:http://infocenter.arm.com/help/i ... 37e/ch11s05s01.html

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 12 | 回复: 14



手机版|

GMT+8, 2024-4-20 03:38 , Processed in 0.136265 second(s), 9 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表