我正在使用 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;
运行这些代码行后,这些内存位置的所有值都保持不变,并且不会因应该执行的操作而改变。
EG :
//DWT_CTRL_CYCCNTENA_Msk = 1
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk
应导致 DWT->CTRL 的值为
0x40000001
,但仍保持默认值 0x40000000
下图是运行时发生的情况的示例。
可能缺少解锁 dbg regs(DWT->LAR = 0xC5ACCE55): 下面的序列为我解决了 pb :
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->LAR = 0xC5ACCE55;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
不确定这在 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 标头。这包括不使用幻数,而是使用定义的常量/宏。
更多信息可以在《架构参考手册》中找到。 注意:还有一本《架构应用级别参考手册》,这不是你想要的。
你做的一切都是正确的,除了你缺少解锁对 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 所说的那样,效率会更高;)
我知道我有点晚了,但如果其他人想了解如何正确设置 DWT,你可以看看 https://developer.arm.com/documentation/ddi0337/e/ch11s05s01
在我使用 stm32f1 的示例中,将 DWT 设置为足以满足我的需要
DWT->CTRL = DWT_CTRL_CYCEVTENA_Msk | DWT_CTRL_CYCCNTENA_Msk;
DWT->CYCCNT = 0;
这对我有用:
//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
STM32H563xx Cortex M33方式(无软件锁)使用CMSIS:
// DWT and ITM blocks are enabled if TRCENA is 1
SET_BIT(DCB->DEMCR, DCB_DEMCR_TRCENA_Msk);
// Enable cycle counter
SET_BIT(DWT->CTRL, DWT_CTRL_CYCCNTENA_Msk);