STM32 - счётчик DWT - микросекундные паузы





Здравствуйте.

Маленькая заметка, с примером, об очень прикольной и полезной вещице входящей в состав модуля DWT (Data Watchpoint and Trace unit) имеющегося у stm32.

Сам по себе модуль DWT достаточно сложная штуковина (почитать можно тут стр. 75), а отвечает он за отладку. Однако рассматривать этот модуль полностью у меня нет желания, во всяком случае в данный момент, а коснуться хотелось одной из его составляющих — счётчика тактов (далее счётчик DWT).

По сути, счётчик DWT это просто 32-х битный регистр, значение в котором увеличивается на единичку с каждым последующим тактом. Мы можем писать в этот регистр и читать из него, а значит можем с его помощью измерять время выполнения каких-то кусков программы в тактах, и организовывать микросекундные задержки. Этот счётчик полностью независимый, то есть щёлкает и щелкает не смотря ни на прерывания, ни на другие задержки…




Чтоб измерить время выполнения какого-либо участка программы или функции, нужно сделать так…


  #define    DWT_CYCCNT    *(volatile uint32_t*)0xE0001004
  #define    DWT_CONTROL   *(volatile uint32_t*)0xE0001000
  #define    SCB_DEMCR     *(volatile uint32_t*)0xE000EDFC

  char str[16] = {0,};
  uint32_t count_tic = 0;

  SCB_DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;// разрешаем использовать DWT
  DWT_CONTROL|= DWT_CTRL_CYCCNTENA_Msk; // включаем счётчик
  DWT_CYCCNT = 0;// обнуляем счётчик

  // здесь кусок измеряемого участка программы

  count_tic = DWT_CYCCNT; // кол-во тактов
  snprintf(str, 16, "Takt %lu\n", count_tic);
  HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), 1000);



Измерил HAL_Delay(1000) на частоте 72МГц. Функция HAL_Delay() всегда немного подвирает в большую сторону, в данном случае на 33326 тактов, то есть приблизительно на 470 мкс.



Для организации микросекундных пауз создаём пару функций…

#define DWT_CONTROL *(volatile unsigned long *)0xE0001000
#define SCB_DEMCR   *(volatile unsigned long *)0xE000EDFC


void DWT_Init(void)
{
    SCB_DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // разрешаем использовать счётчик
    DWT_CONTROL |= DWT_CTRL_CYCCNTENA_Msk;   // запускаем счётчик
}

void delay_micros(uint32_t us)
{
    uint32_t us_count_tic =  us * (SystemCoreClock / 1000000); // получаем кол-во тактов за 1 мкс и умножаем на наше значение
    DWT->CYCCNT = 0U; // обнуляем счётчик
    while(DWT->CYCCNT < us_count_tic);
}


Перед бесконечным циклом инициализируем DWT…

/* USER CODE BEGIN 2 */
DWT_Init();
/* USER CODE END 2 */


И там где нужно, вставляем задержку, например 100 микросекунд…

delay_micros(100);



Пример в виде «библиотеки», а точнее в виде одного файла


Это всё, всем спасибо


Телеграм-чат istarik

Телеграм-чат STM32

Форум


  • 0
  • 1960
Поддержать автора




Telegram-чат istarik

Задать вопрос по статье
Telegram-канал istarik

Известит Вас о новых публикациях






Комментарии (0)

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.