mcu:利用Cortex-M中的DWT实现高精度计时

news2025/2/13 4:58:42

1、Cortex-M中的DWT

在Cortex-M里面有一个外设叫DWT(Data Watchpoint and Trace),是用于系统调试及跟踪。
它有一个32位的寄存器叫CYCCNT,它是一个向上的计数器,记录的是内核时钟运行的个数,内核时钟跳动一次,该计数器就加1,精度非常高,决定内核的频率是多少,如果是F103系列,内核时钟是72M,那精度就是1/72M = 14ns,而程序的运行时间都是微秒级别的,所以14ns的精度是远远够的。最长能记录的时间为:60s=2的32次方/72000000(假设内核频率为72M,内核跳一次的时间大概为1/72M=14ns),而如果是H7这种400M主频的芯片,那它的计时精度高达2.5ns(1/400000000 = 2.5),而如果是 i.MX RT1052这种比较牛逼的处理器,最长能记录的时间为: 8.13s=2的32次方/528000000 (假设内核频率为528M,内核跳一次的时间大概为1/528M=1.9ns) 。当CYCCNT溢出之后,会清0重新开始向上计数。

Cortex-M3权威指南中有这样一句话——“DWT 中有剩余的计数器,它们典型地用于程序代码的“性能速写”(profiling)。通过编程它们,就可以让它们在计数器溢出时发出事件(以跟踪数据包的形式)。最典型地,就是使用 CYCCNT寄存器来测量执行某个任务所花的周期数,这也可以用作时间基准相关的目的(操作系统中统计 CPU使用率可以用到它)。”

在这里插入图片描述

DWT介绍:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

2、寄存器

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

  • 1、DEMCR
    想要使能DWT外设,需要由另外的内核调试寄存器DEMCR的位24控制,写1使能。如下:
    在这里插入图片描述

  • 2、DWT_CYCCNT

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

  • 3、CYCCNTENA

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

  • 4、总结
    想要使用DWT的CYCCNT步骤:
  • 先使能DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1使能。
  • 使能CYCCNT寄存器之前,先清0。
  • 使能CYCCNT寄存器,这个由DWT的CYCCNTENA 控制,也就是DWT控制寄存器的位0控制,写1使能。

3、代码实现

#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)

volatile static uint32_t cpuclkfeq = 0;

void dwt_init(uint32_t cpuclk)
{
    cpuclkfeq = clk;

    CoreDebug->DEMCR |= DEM_CR_TRCENA;
    DWT->CYCCNT = 0;
    DWT->CTRL |= DWT_CR_CYCCNTENA;
}

uint32_t get_dwt_us(void)
{
    return DWT->CYCCNT / (cpuclkfeq / 1000000);
}

void delay_us(uint32_t nus)
{
    volatile uint32_t startts, endts, ts;

    ts = nus * (cpuclkfeq / (1000 * 1000));

    startts = DWT->CYCCNT;
    endts = startts + ts;

    if (endts > startts)
    {
        while (DWT->CYCCNT < endts);
    }
    else
    {
        while (DWT->CYCCNT > endts);
        while (DWT->CYCCNT < endts);
    }
}

CoreDebug寄存器定义如下:

#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */

/**
  \brief  Structure type to access the Core Debug Register (CoreDebug).
 */
typedef struct
{
  __IOM uint32_t DHCSR;    /*!< Offset: 0x000 (R/W)  Debug Halting Control and Status Register */
  __OM  uint32_t DCRSR;    /*!< Offset: 0x004 ( /W)  Debug Core Register Selector Register */
  __IOM uint32_t DCRDR;    /*!< Offset: 0x008 (R/W)  Debug Core Register Data Register */
  __IOM uint32_t DEMCR;    /*!< Offset: 0x00C (R/W)  Debug Exception and Monitor Control Register */
} CoreDebug_Type;

#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE)   /*!< Core Debug configuration struct */

DWT寄存器定义:

#define DWT_BASE (0xE0001000UL)    /*!< DWT Base Address */

/**
  \brief  Structure type to access the Data Watchpoint and Trace Register (DWT).
 */
typedef struct
{
  __IOM uint32_t CTRL;                   /*!< Offset: 0x000 (R/W)  Control Register */
  __IOM uint32_t CYCCNT;                 /*!< Offset: 0x004 (R/W)  Cycle Count Register */
  __IOM uint32_t CPICNT;                 /*!< Offset: 0x008 (R/W)  CPI Count Register */
  __IOM uint32_t EXCCNT;                 /*!< Offset: 0x00C (R/W)  Exception Overhead Count Register */
  __IOM uint32_t SLEEPCNT;               /*!< Offset: 0x010 (R/W)  Sleep Count Register */
  __IOM uint32_t LSUCNT;                 /*!< Offset: 0x014 (R/W)  LSU Count Register */
  __IOM uint32_t FOLDCNT;                /*!< Offset: 0x018 (R/W)  Folded-instruction Count Register */
  __IM  uint32_t PCSR;                   /*!< Offset: 0x01C (R/ )  Program Counter Sample Register */
  __IOM uint32_t COMP0;                  /*!< Offset: 0x020 (R/W)  Comparator Register 0 */
  __IOM uint32_t MASK0;                  /*!< Offset: 0x024 (R/W)  Mask Register 0 */
  __IOM uint32_t FUNCTION0;              /*!< Offset: 0x028 (R/W)  Function Register 0 */
        uint32_t RESERVED0[1U];
  __IOM uint32_t COMP1;                  /*!< Offset: 0x030 (R/W)  Comparator Register 1 */
  __IOM uint32_t MASK1;                  /*!< Offset: 0x034 (R/W)  Mask Register 1 */
  __IOM uint32_t FUNCTION1;              /*!< Offset: 0x038 (R/W)  Function Register 1 */
        uint32_t RESERVED1[1U];
  __IOM uint32_t COMP2;                  /*!< Offset: 0x040 (R/W)  Comparator Register 2 */
  __IOM uint32_t MASK2;                  /*!< Offset: 0x044 (R/W)  Mask Register 2 */
  __IOM uint32_t FUNCTION2;              /*!< Offset: 0x048 (R/W)  Function Register 2 */
        uint32_t RESERVED2[1U];
  __IOM uint32_t COMP3;                  /*!< Offset: 0x050 (R/W)  Comparator Register 3 */
  __IOM uint32_t MASK3;                  /*!< Offset: 0x054 (R/W)  Mask Register 3 */
  __IOM uint32_t FUNCTION3;              /*!< Offset: 0x058 (R/W)  Function Register 3 */
        uint32_t RESERVED3[981U];
  __OM  uint32_t LAR;                    /*!< Offset: 0xFB0 (  W)  Lock Access Register */
  __IM  uint32_t LSR;                    /*!< Offset: 0xFB4 (R  )  Lock Status Register */
} DWT_Type;

#define DWT ((DWT_Type *) DWT_BASE)   /*!< DWT configuration struct */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/639604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

node-red 部署案例指导

配置node-red静态资源目录 找到 node-red 的设置文件 可以在启动日志中看到 以我的为例 C:\Users\fizz\.node-red\settings.js 我们在.node-red目录创建一个static目录。用于存放静态文件。 然后修改setting.js的 httpStatic: ‘C:/Users/fizz/.node-red/static/’, 重启…

探索戴森在科技行业的统治地位:分析其后吹风机的成功

2016年&#xff0c;戴森&#xff08;Dyson&#xff09;公司推出重新定义审美与功能的吹风机Supersonic&#xff0c;定价为3000元&#xff0c;七年来&#xff0c;Supersonic不仅没有因其价格远高于竞品而被市场淘汰&#xff0c;反而稳居国内市场吹风机的“龙头宝座“&#xff0c…

低秩矩阵(Low-Rank)的意义

&#xff11;&#xff0e;回顾基础&#xff1a; 矩阵的秩度量的是矩阵行列之间的相关性&#xff0c;如果各行各列都是线性无关的&#xff0c;矩阵就是满秩。非零元素的行或列决定了秩的大小。&#xff0f;&#xff0f;划重点&#xff0c;秩可以度量矩阵自身相关性 讲个小故事…

调用阿里API实现全国快递物流查询

作者介绍 王梅(姓名)&#xff0c;女&#xff08;性别&#xff09;&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生 研究方向&#xff1a;机器视觉与人工智能 电子邮件&#xff1a;1095647386qq.com 王泽宇&#xff0c;男&#xff0c;西安工程大学电子信息学院…

一文让你轻松拿捏 Spring MVC

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

高完整性系统——霍尔逻辑

文章目录 霍尔三元组案例1案例2 逻辑推导规则forward v.s. backwardforwardbackward rule of assignmentrules of consequence结合上述两个 rulerule of sequencing更大的程序案例skip ruleconditional rule案例 要证明这个程序需要从上往下进行&#xff0c;先单独证明 f:1, i:…

你“被”全链路了么?全链路压测实践之理论

要说当下研发领域最热门的几个词&#xff0c;全链路压测 肯定跑不了。最近的几次大会上&#xff0c;也有不少关于全链路的议题。之前有朋友在面试过程中也有被问到了什么是全链路压测&#xff0c;如何有效的开展全链路压测。今天我们就来聊聊全链路压测&#xff0c;但本文不会涉…

Redis.conf 详解

我们启动 Redis&#xff0c;一般都是通过 Redis.conf 启动。 因此&#xff0c;我们必须了解 Redis.conf 的配置&#xff0c;才能更好理解和使用 Redis。 单位 单位注意事项&#xff1a;当需要内存大小时&#xff0c;可以指定为1k 5GB 4M等 通常形式&#xff1a; 1k > 1000字…

搜索在计算机中的地位十分重要

无论是在内部系统还是在外部的互联网站上&#xff0c;都少不了检索系统。数据是为了用户而服务。计算机在采集数据&#xff0c;处理数据&#xff0c;存储数据之后&#xff0c;各种客户端的操作pc机或者是移动嵌入式设备都可以很好的获取数据&#xff0c;得到 想要的数据服务。 …

k8s学习-CKS考试必过宝典

目录 CKS考纲集群安装&#xff1a;10%集群强化&#xff1a;15%系统强化&#xff1a;15%微服务漏洞最小化&#xff1a;20%供应链安全&#xff1a;20%监控、日志记录和运行时安全&#xff1a;20% 报名模拟考试考试注意事项考前考中考后 参考 CKS考纲 集群安装&#xff1a;10% 使…

数据库技术及应用小科普(附部分例题)

数据库的基础 介绍 &#xff08;手机撰写&#xff0c;多有不便&#xff0c;求铁铁们多多包涵&#xff09;图书目录部分期末习题 介绍 &#xff08;手机撰写&#xff0c;多有不便&#xff0c;求铁铁们多多包涵&#xff09; 内容简介 《数据库技术及应用教程》系统地介绍了数据库…

【每日挠头算法题(5)】重新格式化字符串|压缩字符串

欢迎~ 一、重新格式化字符串思路1&#xff1a;构造模拟具体代码如下&#xff1a; 思路2&#xff1a;双指针法具体代码如下&#xff1a; 二、字符串压缩思路1&#xff1a;简单替换 总结 一、重新格式化字符串 点我直达~ 思路1&#xff1a;构造模拟 1.遍历字符串&#xff0c;…

iOS横竖屏切换

基础概念UIDeviceOrientationUIInterfaceOrientationUIInterfaceOrientationMaskUIViewController相关AppDelegate相关工程配置相关 横竖屏切换实例竖屏界面如何present横屏界面竖屏界面如何push横屏界面横屏竖切换机制分析系统如何知道App对界面朝向的支持不同界面的朝向控制自…

Qt学习06:QPainter绘画

文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 Qt学习06&#xff1a;QPainter绘画 Qt绘图 Paint System Qt的绘制系统支持在屏幕和打印设备上使用相同的API进行绘制&#xff0c;主要基于QPainter、QPaintDevice和QPaintEngine类。 QPainter用于执行绘图操作&#xff…

JAVA基础 - SPI机制使用详解(三)

简述 SPI&#xff08;Service Provider Interface的缩写&#xff09; 意思是&#xff1a;“服务提供者的接口”&#xff0c;专门提供给服务提供者或者扩展框架功能的开发者去使用的接口。SPI 将服务接口和服务实现分离开来&#xff0c;将服务调用方和服务实现方进行解耦&#…

Rocketmq面试(四)RocketMQ 的推模式和拉模式有什么区别?

一、PUSH模式 public class Consumer {public static void main(String[] args) throws InterruptedException, MQClientException {// 初始化consumer&#xff0c;并设置consumer group nameDefaultMQPushConsumer consumer new DefaultMQPushConsumer("please_rename_…

基于STM32的重力感应售货机系统设计

一、项目介绍 随着智能物联网技术的不断发展&#xff0c;人们的生活方式和消费习惯也正在发生改变。如今越来越多的人习惯于在线购物、自助购物等新型消费模式&#xff0c;因此智能零售自助柜应运而生。 本项目设计开发一款基于STM32主控芯片的智能零售自助柜&#xff0c;通过…

哪吒汽车,莫做“普信男”

作者 | 魏启扬 来源 | 洞见新研社 今年初&#xff0c;哪吒汽车创始人方运舟和张勇联合发表新年致辞&#xff0c;文末总结说 “2023-2025年&#xff0c;必将是一场艰难的挑战&#xff0c;也是哪吒汽车的生死存亡之战。” 哪吒汽车或许过于敏感了&#xff0c;就今年以来的市场表…

Tensorflow两步安装(超简单)

一、查看python版本&#xff0c;下载对应tensorflow文件 1.Anaconda已安装&#xff0c;找到Anaconda3文件夹&#xff0c;双击打开anaconda prompt&#xff0c;输入python&#xff0c;查看python版本 可以看到我的版本是3.9的 2.进入下面的网站&#xff0c;选择你需要的cpu或g…

【appium】appium自动化入门之API(下)——两万字API长文,建议收藏

目录 Appium API 前言 1.contexts &#xff08;返回当前会话中的上下文&#xff0c;使用后可以识别 H5 页面的控件&#xff09; 2.current_context &#xff08;返回当前会话的当前上下文 &#xff09; 3. context &#xff08;返回当前会话的当前上下文&#xff09; 4.find_e…