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

时间:2016-04-02 20:22:04

标签: c arm embedded stm32f7

我正在使用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 Studio中使用调试器(使用VisualGDB),如果我将DWT-> CTRL的值更改为ON值,则循环计数器开始。除此之外,我似乎无法在代码中获得改变的价值。

编辑:可能导致这些代码行未执行任务而且不会崩溃并继续执行的行为。

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

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

E.G。 :

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

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

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

Before After

4 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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标头,您应该使用它们。这包括不使用幻数,而是使用定义的常量/宏。

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

答案 2 :(得分:3)

你正在做的一切正常,除了你缺少解锁对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 documentationARM documentation都有拼写错误,并将0xE0000FB0作为锁定访问寄存器的地址(请参阅here)。 使用提供的CMSIS核心注册表定义(core_cm7.h)可以避免这个问题,因为它们是正确的,当然可以像Olaf所说的那样更高效;)

答案 3 :(得分:-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