STM32 - Как включить счетчик циклов DWT

Я использую плату 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;

После выполнения этих строк кода все значения в этих ячейках памяти остаются неизменными и не изменяются с операциями, которые должны были быть выполнены.

EG:

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

Должно привести к значению DWT->CTRL, равному 0x40000001, но оно останется равным значению по умолчанию 0x40000000.

Изображения ниже являются примером того, что происходит во время выполнения.

До после

5 ответов

Может быть, не хватает, чтобы разблокировать 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, но вот как это сделать правильно, используя заголовки CMSIS на STM32F4 (на самом деле должно работать на любом Cortex-M3/4(/7?), Который предоставляет этот модуль):

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

Вы также должны включить модуль трассировки. Осторожно, код не защищен от прерываний! В общем, вы должны оставить счетчик только на свободном ходу и делать различия снимков времени.

Просто убедитесь, что ваш набор инструментов не использует помехи вашему коду. OpenOCD/ GDB не, не знаю, как насчет инструментов, которые обеспечивают функциональность ручного профилирования.

Как я уже подчеркивал в комментариях: не используйте некоторые доморощенные определения для регистров. ST (и ARM) предоставляют заголовки CMSIS для стандартных периферийных модулей (DWT и CoreDebug на самом деле являются IP-адресами ARM), которые вы должны использовать. Это включает в себя использование не магических чисел, а определенных констант / макросов.

Более подробную информацию можно найти в "Справочном руководстве по архитектуре". Предостережение: есть также "Справочное руководство по уровню архитектуры", которое вам не подходит.

Вы все делаете правильно, за исключением того, что вам не хватает, чтобы разблокировать доступ к регистру 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) позволило бы избежать этой проблемы, поскольку они правильные и, конечно, было бы более эффективным, как заявил Олаф;)

Я знаю, что немного опоздал, но если кто-то еще смотрит, как правильно настроить 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
Другие вопросы по тегам