打印
[应用相关]

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

[复制链接]
917|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
coshi|  楼主 | 2023-7-12 10:59 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
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这种比较牛X的处理器,最长能记录的时间为: 8.13s=2的32次方/528000000 (假设内核频率为528M,内核跳一次的时间大概为1/528M=1.9ns) 。当CYCCNT溢出之后,会清0重新开始向上计数。

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



DWT介绍:




2、寄存器
要实现延时的功能,总共涉及到三个寄存器:DEMCR 、DWT_CTRL、DWT_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 */

————————————————
版权声明:本文为CSDN博主「zhang-ge」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40837318/article/details/131174772

使用特权

评论回复
沙发
qsl200100| | 2023-8-25 09:08 | 只看该作者
请问ARM Cortex-M23内核也有DWT吗?操作做的地址是否也一样??

使用特权

评论回复
板凳
jtracy3| | 2023-9-5 10:04 | 只看该作者
在Cortex-M中,可以使用System Timer (SysTick)中断来获取周期性事件。

使用特权

评论回复
地板
elsaflower| | 2023-9-5 13:15 | 只看该作者
主要设置包括启用DWT周期计数器和选择适当的时钟源。

使用特权

评论回复
5
mmbs| | 2023-9-5 15:43 | 只看该作者
可以使用DWT_Cmd函数设置计数器为计数模式,然后使用DWT_Start函数开始计时,最后使用DWT_Stop函数停止计时。

使用特权

评论回复
6
plsbackup| | 2023-9-5 15:55 | 只看该作者
WT寄存器提供了一个用于测量程序执行时间的硬件计时器。

使用特权

评论回复
7
maudlu| | 2023-9-5 16:47 | 只看该作者
需要考虑DWT的功耗和资源占用情况。

使用特权

评论回复
8
pentruman| | 2023-9-5 17:27 | 只看该作者
Cortex-M微控制器中的Data Watchpoint and Trace (DWT) 是一个用于跟踪指令执行的硬件单元。虽然它的主要功能是用于调试,但也可以利用它来实现高精度计时。

使用特权

评论回复
9
janewood| | 2023-9-5 19:39 | 只看该作者
需要启用DWT寄存器,以便我们能够使用它来进行计时

使用特权

评论回复
10
Bowclad| | 2023-9-5 21:25 | 只看该作者
本帖最后由 Bowclad 于 2023-9-5 21:29 编辑
qsl200100 发表于 2023-8-25 09:08
请问ARM Cortex-M23内核也有DWT吗?操作做的地址是否也一样??

感觉M23就是M0增加个安全扩展

使用特权

评论回复
11
zwll| | 2023-9-5 22:11 | 只看该作者
也有DWT?

使用特权

评论回复
12
uptown| | 2023-9-7 10:15 | 只看该作者
得到的时间精度取决于所选择的周期性事件。

使用特权

评论回复
13
51xlf| | 2023-9-7 12:09 | 只看该作者
每当需要获取计时值时,可以读取DWT中的cycle counter寄存器。这个寄存器记录了周期事件的次数,因此可以将其转换为时间。

使用特权

评论回复
14
plsbackup| | 2023-9-7 12:25 | 只看该作者
DWT需要跟踪周期事件,所以它会消耗一定的功耗并占用一定的资源。

使用特权

评论回复
15
belindagraham| | 2023-9-7 16:29 | 只看该作者
Cortex-M中的DWT实现高精度计时需要使用DWT提供的计时器,同时需要注意DWT的配置和计时器的配置。

使用特权

评论回复
16
Undshing| | 2023-9-7 22:24 | 只看该作者
是不是M核都有啊

使用特权

评论回复
17
sdCAD| | 2023-9-9 20:35 | 只看该作者
在需要计时的代码的起始和结束位置,通过读取DWT寄存器的值来进行计时

使用特权

评论回复
18
benjaminka| | 2023-9-9 20:51 | 只看该作者
使用DWT提供的计时器,包括设置计时器启动时间、设置计时器周期、设置计时器中断标志等参数。

使用特权

评论回复
19
Henryko| | 2023-9-11 22:26 | 只看该作者
Bowclad 发表于 2023-9-5 21:25
感觉M23就是M0增加个安全扩展

那这个M23和M3哪个性能强啊

使用特权

评论回复
20
sdCAD| | 2023-9-12 20:16 | 只看该作者
对于Cortex-M中的DWT实现高精度计时的开发,需要使用DWT提供的计时器,同时需要注意DWT的配置和计时器的配置。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

95

主题

3308

帖子

4

粉丝