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;

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

E.G. :

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

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

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

До: До

После: После


person KenQueso    schedule 02.04.2016    source источник
comment
значения не изменены или операции пропущены - Почему бы вам не узнать, прежде чем спрашивать? И используйте заголовки CMSIS. Не определяйте свои собственные регистры. Кстати. Определения будут генерировать гораздо больше кода, поскольку вы определяете указатели как переменные. (Даже не думайте о квалификаторе const, они все равно будут переменными.)   -  person too honest for this site    schedule 02.04.2016
comment
Что ж, я прошел через это, и операции выглядят так, как будто они происходят, но значения не меняются ни для одной области памяти, которую я хочу отредактировать. Я безуспешно пытался выяснить это, поэтому я решил, что следующим логическим шагом будет спросить.   -  person KenQueso    schedule 02.04.2016
comment
Должен работать в соответствии с этим. Обратите внимание, что когда вы используете отладчик, отладчик будет использовать DWT для своих целей. Таким образом, вы не можете использовать отладчик с этим кодом.   -  person user3386109    schedule 02.04.2016
comment
@ user3386109: Это зависит от отладчика. OpenOCD не использует счетчик и отлично работает по крайней мере на STM32F4.   -  person too honest for this site    schedule 03.04.2016
comment
@Olaf Олаф Да, вы правы, я должен был сказать, что отладчик может использовать DWT в своих целях.   -  person user3386109    schedule 03.04.2016
comment
Только что перепроверил, OpenOCD его не использует. Но даже без отладчика значение не меняется. Любые другие идеи или вещи, которые я мог бы попытаться выяснить, что происходит?   -  person KenQueso    schedule 03.04.2016
comment
@KenQueso: это не совсем правильно. OpenOCD очень хорошо использует модуль DWT, например. для полухостинга он использует регистр для обмена данными между хостом и целью. Он просто не использует счетчики циклов.   -  person too honest for this site    schedule 03.04.2016
comment
@ Олаф, это приятно знать. С 32F4 у вас когда-нибудь возникали проблемы с запуском модуля DWT?   -  person KenQueso    schedule 03.04.2016
comment
@KenQueso: вообще нет. Но я использую заголовок CMSIS. Обратите внимание, что ваши переменные могут быть переопределены неправильным кодом (и, как я уже писал), они немного увеличивают код.   -  person too honest for this site    schedule 03.04.2016
comment
Хорошо, я посмотрел, как я это сделал в F4. Посмотрите мой ответ и, пожалуйста, оставьте комментарий к ответу (!), Если он работает и для F7. Потом отредактирую для других читателей.   -  person too honest for this site    schedule 03.04.2016


Ответы (4)


Возможно, отсутствует возможность разблокировать регистры dbg (DWT-> LAR = 0xC5ACCE55): последовательность ниже решена pb для меня:

      CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
      DWT->LAR = 0xC5ACCE55; 
      DWT->CYCCNT = 0;
      DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
person Howard Plouch    schedule 20.05.2016
comment
Любая идея, где документация, объясняющая это волшебное слово доступа: DWT->LAR = 0xC5ACCE55? - person Gabriel Staples; 29.11.2018
comment
@GabrielStaples См. Справочное руководство по архитектуре ARMv7-M в разделе D1. Компонент CoreSight имеет эти специальные регистры, один из которых является программной блокировкой. Затем вам нужно просмотреть спецификацию архитектуры ARM CoreSight, в разделе B2.3.10 есть представляет собой описание регистров LSR и LAR вместе с ключом. - person Enbyted; 20.11.2020

Не уверен, что это идентично на 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), которые вы должны использовать. Это включает не использование магических чисел, а использование определенных констант/макросов.

Дополнительную информацию можно найти в «Справочном руководстве по архитектуре». Внимание! существует также "Справочное руководство по архитектуре уровень приложения", которое вам не нужно.

person too honest for this site    schedule 02.04.2016
comment
Я пробовал вышеописанное, используя предопределенные заголовки определений, но, похоже, у меня все еще возникла та же проблема, когда значения не могут быть отредактированы. CoreDebug->DEMCR тоже не изменится, что очень странно. Единственная другая вещь, о которой я могу думать, это использовать ли FreeRTOS или LwIP заголовок CMSIS, но если бы это было так, разве я не увидел бы, что значение CYCCNT увеличивается по мере выполнения программы? - person KenQueso; 03.04.2016
comment
@KenQueso: это не причина отрицать мой ответ! Не уверен, что вы имеете в виду в своем комментарии, AFIK IP-адреса идентичны в этих аспектах. Что вы имеете в виду, когда значения нельзя редактировать? Это совершенно неясно. И это не связано с FreeRTOS и т. д. Заголовки можно использовать без какой-либо ОС, только с соответствующим компилятором. Возможно, вам не хватает некоторых основ использования вашей цепочки инструментов. Предоставьте минимально воспроизводимый пример. - person too honest for this site; 03.04.2016
comment
Я не минусовал ваш ответ, у меня даже не хватило баллов, чтобы проголосовать за вопросы. В любом случае, я добавил изображения до и после в исходный пост, чтобы попытаться прояснить, что происходит. - person KenQueso; 03.04.2016
comment
См. Как спросить. Вы должны публиковать текст как текст, а не как внешние ссылки или изображения! - person too honest for this site; 03.04.2016
comment
Я снова почистил редактирование. Изображения — это часы в разные моменты времени выполнения. Я подумал, что будет легче увидеть это, чем мне напечатать это. - person KenQueso; 03.04.2016
comment
Я все еще не вижу MCVE. Я пока оставлю свой ответ как есть. Заставьте заголовки работать (все еще не ясно, что имел в виду ваш комментарий). Извините, это не служба отладки, и у меня нет времени обучать вас. RTFineM. - person too honest for this site; 03.04.2016
comment
Я не знаю, как я могу быть более ясным. Я точно изложил свою проблему и сказал конкретно, в чем она заключается. Я не прошу репетитора. Я спрашиваю, что может быть причиной поведения, которое я четко изложил выше. - person KenQueso; 03.04.2016

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

person paolok17    schedule 16.12.2016

Это сработало для меня:

//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
person Prashant Namekar    schedule 21.06.2018