STM32 - 如何启用DWT循环计数器

Ken*_*eso 10 c embedded arm stm32f7

我正在使用STM32F7-Discovery板,并且一直试图启用DWT循环计数器.从我在网上看到的,这应该足以启用它:

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= 1;
Run Code Online (Sandbox Code Playgroud)

但是,当我运行该代码时,不会更改值或跳过操作(我不太确定发生了什么).

我已经尝试过指向内存中的地址并直接修改它们,但也无济于事.例如:

volatile uint32_t *DWT_CONTROL = (uint32_t *) 0xE0001000;
volatile uint32_t *DWT_CYCCNT = (uint32_t *) 0xE0001004;
volatile uint32_t *DEMCR = (uint32_t *) 0xE000EDFC;
*DEMCR = *DEMCR | 0x01000000;
*DWT_CYCCNT = 0;
*DWT_CONTROL = *DWT_CONTROL | 1;
Run Code Online (Sandbox Code Playgroud)

目前,我获得的唯一方法是在Visual Studio中使用调试器(使用VisualGDB)时,如果我将DWT-> CTRL的值更改为ON值,则循环计数器开始.除此之外,我似乎无法获得改变代码的价值.

编辑:可能导致这些代码行没有执行任务但也没有崩溃和继续的行为.

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= 1;
Run Code Online (Sandbox Code Playgroud)

在运行这些代码行之后,这些内存位置的所有值都保持不变,并且不会随着应该执行的操作而改变.

EG:

//DWT_CTRL_CYCCNTENA_Msk = 1
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk 
Run Code Online (Sandbox Code Playgroud)

应该导致DWT-> CTRL的值为0x40000001,但它保持默认值0x40000000

下面的图片是运行时期间发生的事情的示例.

之前 之后

小智 7

也许缺少解锁dbg regs(DWT-> LAR = 0xC5ACCE55):下面的序列为我解决了pb:

      CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
      DWT->LAR = 0xC5ACCE55; 
      DWT->CYCCNT = 0;
      DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
Run Code Online (Sandbox Code Playgroud)


too*_*ite 6

不知道在STM32F7上是否相同,但这是如何使用STM32F4上的CMSIS标头正确地做到这一点(实际上应在提供此模块的任何Cortex-M3 / 4(/ 7?)上工作):

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
Run Code Online (Sandbox Code Playgroud)

您还必须启用跟踪模块。注意代码不是中断安全的!通常,您应该让计数器自由运行,并拍摄快照快照以进行计时。

只要确保您的工具链不使用会干扰您的代码。OpenOCD / gdb不需要,也不知道提供手动配置功能的工具如何。

正如我在评论中已经强调的那样:不要对寄存器使用一些自制的定义。ST(和ARM)为您应使用的标准外围模块(DWT和CoreDebug实际上是ARM IP)提供了CMSIS标头。这包括不使用幻数,而是定义的常量/宏。

有关更多信息,请参见“体系结构参考手册”。警告:还有“架构应用程序级别参考手册”,这不是您想要的。

  • 我不知道该如何清楚。我准确地概述了我的问题,并具体说明了它的含义。我不是要老师。我在问什么可能导致上面我明确概述的行为。 (4认同)

小智 5

您所做的一切都是正确的,除了您缺少解锁对 DWT 寄存器的访问权限(正如霍华德指出的那样)。在你的代码中它会是这样的:

volatile uint32_t *DWT_CONTROL = (uint32_t *) 0xE0001000;
volatile uint32_t *DWT_CYCCNT = (uint32_t *) 0xE0001004;
volatile uint32_t *DEMCR = (uint32_t *) 0xE000EDFC;
volatile uint32_t *LAR  = (uint32_t *) 0xE0001FB0;   // <-- added lock access register

*DEMCR = *DEMCR | 0x01000000;     // enable trace
*LAR = 0xC5ACCE55;                // <-- added unlock access to DWT (ITM, etc.)registers 
*DWT_CYCCNT = 0;                  // clear DWT cycle counter
*DWT_CONTROL = *DWT_CONTROL | 1;  // enable DWT cycle counter
Run Code Online (Sandbox Code Playgroud)

需要注意的是,正如ARMv7-M架构参考手册中所述,锁定机制仅适用于软件访问。始终允许 DAP 访问(这就是您可以使用调试器启用周期计数器的原因)。

请注意,STM32F7 文档ARM 文档都有一个拼写错误,并将 0xE0000FB0 作为锁定访问寄存器的地址(请参阅此处)。使用提供的 CMSIS 核心寄存器定义(core_cm7.h)可以避免这个问题,因为它们是正确的,当然,正如 Olaf 所说的那样,效率会更高;)