一个实用的单片机调试组件--DWT

一起学嵌入式 2023-06-13 07:50

扫描关注一起学嵌入式,一起学习,一起成长

DWT跟踪组件

 跟踪组件:数据观察点与跟踪(DWT)

DWT 中有剩余的计数器,它们典型地用于程序代码的“性能速写”(profiling)。通过编程它们,就可以让它们在计数器溢出时发出事件(以跟踪数据包的形式)。

最典型地,就是使用 CYCCNT寄存器来测量执行某个任务所花的周期数,这也可以用作时间基准相关的目的(操作系统中统计 CPU使用率可以用到它)。

Cortex-M中的DWT

在 Cortex-M 里面有一个外设叫 DWT(Data Watchpoint and Trace),是用于系统调试及跟踪。

它有一个32位的寄存器叫CYCCNT,它是一个向上的计数器,记录的是内核时钟运行的个数,内核时钟跳动一次,该计数器就加1,精度非常高,如果内核时钟是72M,那精度就是1/72M = 14ns,而程序的运行时间都是微秒级别的,所以14ns的精度是远远够的。

最长能记录的时间为:59.65s。计算方法为2的32次方/72000000。

当CYCCNT溢出之后,会清0重新开始向上计数。

使用方法

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

DEMCR

想要使能DWT外设,需要由另外的内核调试寄存器DEMCR的位24控制,写1使能(划重点啦,要考试!!)。DEMCR的地址是0xE000 EDFC

关于DWT_CYCCNT

使能DWT_CYCCNT寄存器之前,先清0。让我们看看DWT_CYCCNT的基地址,从ARM-Cortex-M手册中可以看到其基地址是0xE000 1004,复位默认值是0,而且它的类型是可读可写的,我们往0xE000 1004这个地址写0就将DWT_CYCCNT清0了。

关于CYCCNTENA

CYCCNTENA Enable 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. 

它是DWT控制寄存器的第一位,写1使能,则启用CYCCNT计数器,否则CYCCNT计数器将不会工作。

https://developer.arm.com/documentation/ddi0337/e/system-debug/dwt/summary-and-description-of-the-dwt-registers?lang=en

综上所述

想要使用DWT的CYCCNT步骤:

  1. 先使能DWT外设,这个由另外内核调试寄存器 DEMCR 的位24控制,写1使能

  2. 使能CYCCNT寄存器之前,先清 0。

  3. 使能CYCCNT寄存器,这个由DWT的CYCCNTENA 控制,也就是DWT控制寄存器的位0控制,写1使能

寄存器定义:

//0xE000EDFC DEMCR RW Debug Exception and Monitor Control Register.  
//使能DWT模块的功能位
#define DEMCR           ( *(unsigned int *)0xE000EDFC )  
#define TRCENA          ( 0x01 << 24) // DEMCR的DWT使能位  
  
//0xE0001000 DWT_CTRL RW The Debug Watchpoint and Trace (DWT) unit  
//使能CYCCNT计数器开始计数
#define DWT_CTRL        ( *(unsigned int *)0xE0001000 )  
#define CYCCNTENA       ( 0x01 << 0 ) // DWT的SYCCNT使能位
 
//0xE0001004 DWT_CYCCNT RW Cycle Count register,   
//CYCCNT计数器的内部值(32位无符号)
#define DWT_CYCCNT      ( *(unsigned int *)0xE0001004) //显示或设置处理器的周期计数值  

用法示例:

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 
    ...
}

示例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
****/

示例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)
 
/* 初始化时间戳 */
 
void CPU_TS_TmrInit(void)
{
        /* 使能DWT外设 */
        DEM_CR |= (uint32_t)DEM_CR_TRCENA;               
 
        /* DWT CYCCNT寄存器计数清0 */
        DWT_CYCCNT = (uint32_t)0u;
       
 
        /* 使能Cortex-M3 DWT CYCCNT寄存器 */
        DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
 
}
 
uint32_t OS_TS_GET(void)
{
     return ((uint32_t)DWT_CYCCNT);
}


原文:https://blog.csdn.net/booksyhay/article/details/109028712

文章来源于网络,版权归原作者所有,如有侵权,请联系删除。



个人微信开放,扫码添加,进高质量嵌入式交流群

关注我【一起学嵌入式】,一起学习,一起成长。



觉得文章不错,点击“分享”、“”、“在看” 呗!

一起学嵌入式 公众号【一起学嵌入式】,RTOS、Linux编程、C/C++,以及经验分享、行业资讯、物联网等技术知
评论
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 172浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 830浏览
  • 故障现象 一辆2007款日产天籁车,搭载VQ23发动机(气缸编号如图1所示,点火顺序为1-2-3-4-5-6),累计行驶里程约为21万km。车主反映,该车起步加速时偶尔抖动,且行驶中加速无力。 图1 VQ23发动机的气缸编号 故障诊断接车后试车,发动机怠速运转平稳,但只要换挡起步,稍微踩下一点加速踏板,就能感觉到车身明显抖动。用故障检测仪检测,发动机控制模块(ECM)无故障代码存储,且无失火数据流。用虹科Pico汽车示波器测量气缸1点火信号(COP点火信号)和曲轴位置传感器信
    虹科Pico汽车示波器 2025-01-23 10:46 97浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 137浏览
  • 书接上回:【2022年终总结】阳光总在风雨后,启航2023-面包板社区  https://mbb.eet-china.com/blog/468701-438244.html 总结2019,松山湖有个欧洲小镇-面包板社区  https://mbb.eet-china.com/blog/468701-413397.html        2025年该是总结下2024年的喜怒哀乐,有个好的开始,才能更好的面对2025年即将
    liweicheng 2025-01-24 23:18 47浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 398浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 162浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 209浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 749浏览
  • 飞凌嵌入式基于瑞芯微RK3562系列处理器打造的FET3562J-C全国产核心板,是一款专为工业自动化及消费类电子设备设计的产品,凭借其强大的功能和灵活性,自上市以来得到了各行业客户的广泛关注。本文将详细介绍如何启动并测试RK3562J处理器的MCU,通过实际操作步骤,帮助各位工程师朋友更好地了解这款芯片。1、RK3562J处理器概述RK3562J处理器采用了4*Cortex-A53@1.8GHz+Cortex-M0@200MHz架构。其中,4个Cortex-A53核心作为主要核心,负责处理复杂
    飞凌嵌入式 2025-01-24 11:21 99浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦