15

我正在使用 STM32F7-Discovery 开发板,并且一直在尝试启用 DWT 循环计数器。从我在网上看到的情况来看,这应该足以启用它:

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL  |= 1;

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

我尝试过指向内存中的地址并直接更改它们也无济于事。前任:

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;

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

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

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL  |= 1;

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

例如:

//DWT_CTRL_CYCCNTENA_Msk = 1
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk 

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

下面的图片是运行时发生的情况的示例。

之前前

之后后

4

4 回答 4

10

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

      CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
      DWT->LAR = 0xC5ACCE55; 
      DWT->CYCCNT = 0;
      DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
于 2016-05-20T11:45:55.157 回答
6

不确定这在 STM32F7 上是否相同,但这是如何使用 STM32F4 上的 CMSIS 标头正确执行此操作(实际上应该适用于提供此模块的任何 Cortex-M3/4(/7?)):

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

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

只要确保您的工具链不会干扰您的代码。OpenOCD/gdb 没有,不确定提供手动分析功能的工具怎么样。

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

更多信息可以在“架构参考手册”中找到。注意:还有一个“架构应用程序级别参考手册”,这不是您想要的。

于 2016-04-02T23:21:10.057 回答
4

你做的一切都是对的,除了你没有解锁对 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

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

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

于 2016-12-16T16:31:26.757 回答
-1

这对我有用:

//address of the register
volatile unsigned int *DWT_CYCCNT   = (volatile unsigned int *)0xE0001004;     

//address of the register
volatile unsigned int *DWT_CONTROL  = (volatile unsigned int *)0xE0001000;     

//address of the register
volatile unsigned int *DWT_LAR      = (volatile unsigned int *)0xE0001FB0;     

//address of the register
volatile unsigned int *SCB_DEMCR    = (volatile unsigned int *)0xE000EDFC;

...

*DWT_LAR = 0xC5ACCE55; // unlock (CM7)
*SCB_DEMCR |= 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CONTROL |= 1 ; // enable the counter

...

x = *DWT_CYCCNT;

...正在测试的代码:

y = *DWT_CYCCNT;
x = (y - x); // Elapsed clock ticks, at SystemCoreClock
于 2018-06-21T06:49:01.617 回答