回答

收藏

【野火i.MX RT1052】4.RT1052之内核计数器DWT

其他 其他 4358 人阅读 | 0 人回复 | 2018-05-26

本帖最后由 小马哥-1650185 于 2018-5-26 12:17 编辑

这一贴文主要来说说rt1052的内核计数器部分

DWT,全称是The Debug Watchpoint and Trace (DWT) unit,用于系统调试及跟踪,详细的介绍可以参考ARM官方文档:ARMv7-M Architecture Reference Manual


在Cortex-M里面有一个外设叫DWT(Data Watchpoint and Trace), 该外设有一个32位的寄存器叫CYCCNT,它是一个向上的计数器, 记录的是内核时钟运行的个数,最长能记录的时间为: 8.13s=2的32次方/528000000 (假设内核频率为528M,内核跳一次的时间大概为1/528M=1.9ns) 当CYCCNT溢出之后,会清0重新开始向上计数。

使能CYCCNT计数的操作步骤:
1、先使能DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1使能
2、使能CYCCNT寄存器之前,先清0
3、使能CYCCNT寄存器,这个由DWT_CTRL(代码上宏定义为DWT_CR)的位0控制,写1使能

要实现延时的功能,总共涉及到三个寄存器:DEMCR 、DWT_CTRL、DWT_CYCCNT,分别用于开启DWT功能、开启CYCCNT及获得系统时钟计数值。


  1. #define  DWT_CR            *(__IO uint32_t *)0xE0001000
  2. #define  DWT_CYCCNT     *(__IO uint32_t *)0xE0001004
  3. #define  DEM_CR            *(__IO uint32_t *)0xE000EDFC
复制代码
看手册上 (如下图所示)
DEM_CR 我们只需要关注其第24位引脚TRCENA,该寄存器的TRCENA位置位,使能DWT功能

寄存器DWT_CR是控制寄存器  
DWT_CYCCNT   是循环计数寄存器 我们只开启循环计数功能,当DWT的CYCCNTENA位置位后,该寄存器的值与系统周期计数值保持同步,我们可以用它的值来实现一个延时的功能      



实现代码如下
  1. //寄存器基地址
  2. #define    DWT_CR    *(uint32_t*)0xE0001000
  3. #define    DWT_CYCCNT    *(uint32_t*)0xE0001004
  4. #define    DEM_CR    *(uint32_t*)0xE000EDFC

  5. //定义需使能位
  6. #define    DEM_CR_TRCENA    (1<<24)
  7. #define    DWT_CR_CYCCNTENA    (1<<0)

  8. <blockquote>/**
复制代码

采用CPU的内部计数实现精确延时,32位计数器,使用本函数前必须先调用CPU_TS_TmrInit函数使能计数器,  或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION, 最大延时值为8秒,即8*1000*1000

复制代码
  1. #define  DWT_CR      *(__IO uint32_t *)0xE0001000
  2. #define  DWT_CYCCNT  *(__IO uint32_t *)0xE0001004
  3. #define  DEM_CR      *(__IO uint32_t *)0xE000EDFC


  4. #define  DEM_CR_TRCENA                   (1 << 24)
  5. #define  DWT_CR_CYCCNTENA                (1 <<  0)


  6. /**
  7.   * @brief  初始化时间戳
  8.   * @param  无
  9.   * @retval 无
  10.   * @note   使用延时函数前,必须调用本函数
  11.   */
  12. void CPU_TS_TmrInit(void)
  13. {
  14.     /* 使能DWT外设 */
  15.     DEM_CR |= (uint32_t)DEM_CR_TRCENA;               

  16.     /* DWT CYCCNT寄存器计数清0 */
  17.     DWT_CYCCNT = (uint32_t)0u;

  18.     /* 使能Cortex-M DWT CYCCNT寄存器 */
  19.     DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
  20. }


  21. /**
  22.   * @brief  读取当前时间戳
  23.   * @param  无
  24.   * @retval 当前时间戳,即DWT_CYCCNT寄存器的值
  25.   */
  26. uint32_t CPU_TS_TmrRd(void)
  27. {        
  28.   return ((uint32_t)DWT_CYCCNT);
  29. }
复制代码


使用函数void CPU_TS_Tmr_Delay_US(uint32_t us)可以实现精确的延时,延时不受代码优化影响。
例如延时1us
#define LED_DELAY   CPU_TS_Tmr_Delay_S(1)
本例程替换前面的延时函数delay(),使用LED_DELAY   达到精确延时。

在main函数中首先初始化dwt
  1.       //使用时间戳延时函数前必须先使能计数器
  2.       CPU_TS_TmrInit();
复制代码
在主循环中实现延时点亮rgb灯
  1.     while(1)
  2.                 {                           
  3.                         /* LED亮 */
  4.                         CORE_BOARD_LED_ON;
  5.                         /* 延时 */
  6.                         LED_DELAY;
  7.       
  8.       /* 独立操作红灯 */
  9.                         RGB_RED_LED_ON;
  10.                         LED_DELAY;
  11.                         
  12.                         RGB_RED_LED_OFF;
  13.                         LED_DELAY;
  14.       
  15.       /* 独立操作绿灯 */
  16.       RGB_GREEN_LED_ON;
  17.                         LED_DELAY;
  18.                         
  19.                         RGB_GREEN_LED_OFF;
  20.                         LED_DELAY;
  21.       
  22.       /* 独立操作蓝灯 */
  23.       RGB_BLUE_LED_ON;
  24.                         LED_DELAY;
  25.                         
  26.                         RGB_BLUE_LED_OFF;
  27.                         LED_DELAY;               

  28.       /* 整体操作红色 */
  29.                         RGB_LED_COLOR_RED;
  30.                         LED_DELAY;               
  31.       
  32.       /* 整体操作绿色 */
  33.       RGB_LED_COLOR_GREEN;
  34.                         LED_DELAY;               
  35.       
  36.       /* 整体操作蓝色 */
  37.       RGB_LED_COLOR_BLUE;
  38.                         LED_DELAY;               
  39.       
  40.       /* 整体操作黄色 */
  41.       RGB_LED_COLOR_YELLOW;
  42.                         LED_DELAY;               
  43.       
  44.       /* 整体操作紫色 */
  45.       RGB_LED_COLOR_PURPLE;
  46.                         LED_DELAY;               
  47.       
  48.       /* 整体操作青色 */
  49.       RGB_LED_COLOR_CYAN;
  50.                         LED_DELAY;               
  51.       
  52.       /* 整体操作白色 */
  53.       RGB_LED_COLOR_WHITE;
  54.                         LED_DELAY;               
  55.       
  56.       /* 整体操作黑色(全关闭) */
  57.       RGB_LED_COLOR_OFF;
  58.                         LED_DELAY;               
  59.                 }
复制代码


效果如下图


分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条