Измерение тактов на кортексе m7
Я измерял счетчик тактов на кортексе m4 и теперь хотел бы сделать это на кортексе m7. Я использую плату STM32F746ZG.
Для м4 все работало с:
volatile unsigned int *DWT_CYCCNT;
volatile unsigned int *DWT_CONTROL;
volatile unsigned int *SCB_DEMCR;
void reset_cnt(){
DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register
DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register
SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register
*SCB_DEMCR = *SCB_DEMCR | 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CONTROL = 0;
}
void start_cnt(){
*DWT_CONTROL = *DWT_CONTROL | 0x00000001 ; // enable the counter
}
void stop_cnt(){
*DWT_CONTROL = *DWT_CONTROL & 0xFFFFFFFE ; // disable the counter
}
unsigned int getCycles(){
return *DWT_CYCCNT;
}
Проблема в том, что регистр DWT_CTRL не изменяется при запуске на m7 и остается 0x40000000 вместо изменения 0x40000001, поэтому счетчик циклов всегда равен нулю. Из того, что я читал в других сообщениях, кажется, что вам нужно установить регистр FP_LAR в 0xC5ACCE55, чтобы иметь возможность изменять DWT_CTRL.
Я добавил эти определения (попробовал оба адреса FP_LAR_PTR ниже):
#define FP_LAR_PTR ((volatile unsigned int *) 0xe0000fb0) //according to reference
//#define FP_LAR_PTR ((volatile unsigned int *) 0xe0002fb0) //according to guy on the internet
// Lock Status Register lock status bit
#define DWT_LSR_SLK_Pos 1
#define DWT_LSR_SLK_Msk (1UL << DWT_LSR_SLK_Pos)
// Lock Status Register lock availability bit
#define DWT_LSR_SLI_Pos 0
#define DWT_LSR_SLI_Msk (1UL << DWT_LSR_SLI_Pos)
// Lock Access key, common for all
#define DWT_LAR_KEY 0xC5ACCE55
и эта функция:
void dwt_access_enable(unsigned int ena){
volatile unsigned int *LSR;
LSR = (volatile unsigned int *) 0xe0000fb4;
uint32_t lsr = *LSR;;
//printf("LSR: %.8X - SLI MASK: %.8X\n", lsr, DWT_LSR_SLI_Msk);
if ((lsr & DWT_LSR_SLI_Msk) != 0) {
if (ena) {
//printf("LSR: %.8X - SLKMASK: %.8X\n", lsr, DWT_LSR_SLK_Msk);
if ((lsr & DWT_LSR_SLK_Msk) != 0) { //locked: access need unlock
*FP_LAR_PTR = DWT_LAR_KEY;
printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
}
} else {
if ((lsr & DWT_LSR_SLK_Msk) == 0) { //unlocked
*FP_LAR_PTR = 0;
//printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
}
}
}
}
Когда я вызываю некомментированную печать, я получаю 0xC5ACCE55, но когда я печатаю ее после возврата функции, я получаю 0x00000000, и я понятия не имею, почему. Я на правильном пути или это совершенно неправильно?
Изменить: Я думаю, что было бы также хорошо упомянуть, что я пытался без всего дополнительного кода в функции и только пытался изменить регистр LAR.
Б.Р. Густав
2 ответа
Снова просматривая документы, я теперь невероятно подозрительно отношусь к ошибке опечатки или копирования-вставки в ARM TRM. 0xe0000fb0 задается как адрес ITM_LAR, DWT_LAR и FP_LSR (и эквивалентно для *_LSR). Поскольку все остальные регистры ITM находятся на странице 0xe0000000, это выглядит очень похоже на то, кто бы ни отвечал за эту часть документации Cortex-M7, взял определения регистров Cortex-M4, добавил новые LAR и LSR на страницу ITM, а затем скопировал их на страницы DWT и FPB, обновляющие имена, но пропускающие обновления адресов.
Держу пари, что вы невольно разблокируете ITM_LAR (или реальный FP_LAR), а DWT_LAR на самом деле 0xe0001 fb0.
РЕДАКТИРОВАТЬ по dwelch
Кто-то должен кому-то ужин.
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
PUT32(0xE000EDFC,0x01000000);
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
PUT32(0xE0001000,0x40000001);
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
PUT32(0xE0001FB0,0xC5ACCE55);
PUT32(0xE0001000,0x40000001);
hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));
выход
00000000
00000000
00000000
00000000
00000003
40000000
00000000
00000000
00000003
40000000
00000000
00000000
00000001
40000001
0000774F
0000B311
Таблица в TRM выглядит забавно, и, как показывает другая документация, вы добавляете 0xFB0 и 0xFB4 к базе, остальная часть DWT для Cortex-M7 - это 0xE0001xxx, и действительно кажется, что LAR и LSR являются 0xE0001FB0 и 0xE0001FB4.,
Я бы не советовал создавать собственные определения регистров, когда они определены как часть CMSIS - для этого требуется, чтобы как документация, так и ваша интерпретация были правильными. В этом случае кажется, что документация действительно неверна, но заголовки CMSIS верны. Намного проще автоматически проверять заголовки CMSIS, чем проверять правильность документации, поэтому я каждый раз доверял бы CMSIS.
Я не уверен, что зарегистрироваться FP_LAR
может относиться к, но ваше назначение адресов относится к ITM_LAR
, но кажется более вероятным, что вы намеревались DWT_LAR
которой не хватает Cortex-M4.
Несмотря на мой совет доверять этому, CMSIS 4.00 не определяет маски для DWT_LSR
/ SWT_LAR
, но я считаю, что они идентичны соответствующим маскам ITM.
Обратите внимание также, что LAR
регистр только для записи - любая попытка прочитать его не имеет смысла.
Ваш код с использованием CMSIS будет:
#include "core_cm7.h" // Applies to all Cortex-M7
void reset_cnt()
{
CoreDebug->DEMCR |= 0x01000000;
DWT->CYCCNT = 0; // reset the counter
DWT->CTRL = 0;
}
void start_cnt()
{
DWT->CTRL |= 0x00000001 ; // enable the counter
}
void stop_cnt()
{
DWT->CTRL &= 0xFFFFFFFE ; // disable the counter
}
unsigned int getCycles()
{
return DWT->CYCCNT ;
}
// Not defined in CMSIS 4.00 headers - check if defined
// to allow for possible correction in later versions
#if !defined DWT_LSR_Present_Msk
#define DWT_LSR_Present_Msk ITM_LSR_Present_Msk ;
#endif
#if !defined DWT_LSR_Access_Msk
#define DWT_LSR_Access_Msk ITM_LSR_Access_Msk ;
#endif
#define DWT_LAR_KEY 0xC5ACCE55
void dwt_access_enable( unsigned ena )
{
uint32_t lsr = DWT->LSR;;
if( (lsr & DWT_LSR_Present_Msk) != 0 )
{
if( ena )
{
if ((lsr & DWT_LSR_Access_Msk) != 0) //locked: access need unlock
{
DWT->LAR = DWT_LAR_KEY;
}
}
else
{
if ((lsr & DWT_LSR_Access_Msk) == 0) //unlocked
{
DWT->LAR = 0;
}
}
}
}