[英]STM32 - How to enable DWT Cycle counter
我使用的是 STM32F7-Discovery 開發板,一直試圖啟用 DWT 循環計數器。 從我在網上看到的情況來看,這應該足以啟用它:
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= 1;
但是,每當我運行該代碼時,值都不會更改或操作會被跳過(我不太確定發生了什么)。
我試過指向 memory 中的地址並直接更改它們也無濟於事。 前任:
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;
運行這些代碼行后,那些 memory 位置的所有值都保持不變,並且不會因應該執行的操作而改變。
例如:
//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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.