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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOV5 训练

YOLOV5训练过程 CUDA 和cuDnnan 安装教程 windows上安装可以参考这篇知乎文章 数据集准备 自己准备数据集 可以使用 labelImg 工具&#xff0c;直接 pip install labelimg 就可以安装了。 命令行中输入 labelImg 就可以运行 标注数据的输出结果有多种过格式&#xff0c;V…

前端什么最难学?

前言 个人认为是JS&#xff0c;无论是在平时的项目或者找工作时候JS都是大头&#xff0c;相比起其他的部分&#xff0c;它相对而言是难一点&#xff0c;同时也是十分重要的一部分&#xff0c;学好原生JS&#xff0c;后续的学习才能基于此循序渐进&#xff0c;下面是我总结的关…

GIT学习笔记

团队使用GIT有些时间了&#xff0c;也遇到一些问题&#xff1a; 遇到大量冲突&#xff0c;解决完之后&#xff0c;没有修改的代码也变成蓝色了&#xff0c;如果不push&#xff0c;代码将会丢失代码丢失&#xff08;具体情况&#xff0c;我暂时记不清了&#xff09;git push失败…

数据库入门下篇(如何安装和登录MYSQL数据库)

在这篇文章里&#xff0c;笔者将着重讲解如何在win和Linux系统上安装自己的MySQL数据库软件&#xff0c;以及安装好数据库软件后如何启动和登录&#xff0c;忘了密码怎么办&#xff1f;如何创建一个数据库&#xff0c;如何在数据库中创建一个表等内容 目录 在windows系统上安装…

HNU计算机体系结构-实验一:RISC-V指令理解

HNU计算机体系结构-实验一 前言1.实验目的2.实验步骤1.安装模拟器Ripes2.生成汇编指令3.思考问题1&#xff09;指令add x15, x14, x152&#xff09;指令bge x15 x14 -683&#xff09;指令lw x15, -20 x84&#xff09;指令sw x15, -20 x85&#xff09;简述BranchE信号的作用6&am…

中级前端笔试面试题总结

typeof null 的结果是什么&#xff0c;为什么&#xff1f; typeof null 的结果是Object。 在 JavaScript 第一个版本中&#xff0c;所有值都存储在 32 位的单元中&#xff0c;每个单元包含一个小的 类型标签(1-3 bits) 以及当前要存储值的真实数据。类型标签存储在每个单元的…

(浙大陈越版)数据结构 第三章 树(中) 二叉搜索树和平衡二叉树

目录 4.1.1 二叉搜索树及查找 什么是二叉搜索树 定义 二叉搜索树特殊函数集&#xff1a; 查找操作&#xff1a;Find 算法思想 代码实现 补&#xff1a;查找最大和最小元素 4.1.2 二叉搜索树的插入 插入操作&#xff1a;Insert 算法思想 代码实现 例题 4.1.3 二叉…

吴恩达老师《机器学习》课后习题1之线性回归

在学习这些内容之前&#xff0c;需要学习python数据分析相关内容&#xff1a; numpy&#xff1a;科学计算库&#xff0c;处理多维数组&#xff0c;进行数据分析 pandas&#xff1a;基于numpy的一种工具&#xff0c;该工具是为了解决数据分析任务而创建的 matplotlib&#xff1a…

如何进行微服务测试?

微服务测试是一种特殊的测试类型&#xff0c;因为它涉及到多个独立的服务。以下是进行微服务测试的一般性步骤&#xff1a; 1. 确定系统架构 了解微服务架构对成功测试至关重要。确定每个微服务的职责、接口、依赖项和通信方式。了解这些信息可以帮助您更好地规划测试用例和测…

Aop详解

AOP简介 AOP是一种编程思想&#xff0c;就如同面向对象这种编程思想一样&#xff0c;是一种编程范式&#xff0c;用来指导开发者如何组织程序更好的运行 AOP&#xff08;面向切面编程&#xff09; 作用&#xff1a;在不改变原代码的前提下&#xff0c;为其增加功能。 连接点…

Apikit 自学日记:导入第三方产品 API 数据

除了手动创建API文档&#xff0c;系统也提供了一键导入 Swagger、Postman、RAP、YAPI 等产品数据的功能。方便从其他平台进行迁移。 产品支持度导入文件的后缀名Eolinker API 研发管理完全支持.jsonPostman V2.1支持导入API基础信息&#xff0c;超过10级分组的API数据将不会被导…

git在windows及linux(源码编译)环境下安装

git在windows及linux(源码编译)环境下安装 环境信息: 系统版本:CentOS Linux release 7.9.2009 (Core) git指令安装: yum install -y git 一、git在windows下安装 下载地址:https://git-scm.com/ 默认安装即可 验证 git --version 二、git在linux下安装 下载地址…

游戏场景的转换——状态模式

状态模式 游戏比较复杂时&#xff0c;通常会设计成多个场景。 切换场景的好处 1、重复使用场景 跳转切换场景的代码有两种一种是旧版的方法 Application.LoadLevel(“SampleScene”);另一种是新版的方法 SceneManager.LoadScene(“SampleScene”); 例子1&#xff1a;通过场景…

【QT】TCP/UDP详解及实现

TCP/UDP TCP/IP模型TCP协议头部格式三次握手四次挥手 UDP协议头部格式 Socket编程tcpudp代码实现服务端&#xff1a;客户端&#xff1a; 总结 TCP/IP模型 TCP模型是一个常见的网络协议参考模型&#xff0c;也称为TCP/IP模型或互联网模型。它是指TCP/IP协议族中的一组协议&…

Creating Add-in Hooks (C#)

本文介绍如何使一个文件在添加、检入、检出到库时&#xff0c;让add-in 程序在SOLIDWORKS PDM Professional 中通知到你。 注意&#xff1a; 因为 SOLIDWORKS PDM Professional 无法强制重新加载Add-in程序 &#xff0c;必须重新启动所有客户端计算机&#xff0c;以确保使用最…

【Python开发】FastAPI 09:middleware 中间件及跨域

FastAPI 提供了一些中间件来增强它的功能&#xff0c;类似于 Spring 的切面编程&#xff0c;中间件可以在请求处理前或处理后执行一些操作&#xff0c;例如记录日志、添加请求头、鉴权等&#xff0c;跨域也是 FastAPI 中间件的一部分。 目录 1 中间件 1.1 创建中间件 1.2 使…

MySQL常见问题

优化慢查询 慢查询可能出现的情况&#xff1a; 聚合查询多表查询表数据量过大深度分页查询 表象&#xff1a;页面加载过慢&#xff0c;接口压测响应时间过长&#xff08;超过1s&#xff09; 如何定位慢查询&#xff1f; 方案一&#xff1a;开源工具 可以使用相应的调试工具&a…

EMC学习笔记(三)滤波

滤波 1.概述2.滤波器件2.1 电阻2.2 电感2.3 电容2.4 铁氧体磁珠2.5 共模电感 3.滤波电路3.1 滤波电路的形式3.2 滤波电路的布局与布线 4.电容在PCB的EMC设计中的应用4.1 滤波电容的种类4.2 电容自谐振问题4.3 ESR对并联电容幅频特性的影响4.4 ESL对并联电容幅频特性的影响4.5 电…

LarkXR知识库 | 开发者社区FAQ合集(二)

LarkXR是一套基于GPU云化、图形容器、音视频实时编解码、网络传输优化等核心技术的通用型实时云渲染解决方案&#xff0c;帮助XR领域企业级用户及开发者快速搭建XR应用上云通道&#xff0c;使其在各类智能终端上流畅的运行、使用及传播。 平行云开发者社区上线以来&#xff0c…

【计算机网络复习之路】运输层(谢希仁第八版)万字详解 主打基础

专栏&#xff1a;计算机网络复习之路 运输层是OSI七层模型中最重要最关键的一层&#xff0c;是唯一负责总体数据传输和控制的一层。运输层要达到两个主要目的&#xff1a;第一&#xff0c;提供可靠的端到端的通信&#xff08;“端到端的通信” 是应用进程之间的通信&#xff09…