Перейти к содержанию

Счётчик тактов DWT (CYCCNT)

Чтобы узнать, сколько выполняется функция, не нужен ни таймер, ни осциллограф: у ядер Cortex-M3 и Cortex-M4 есть счётчик, который прибавляет единицу на каждом такте процессора. Два чтения до и после участка кода — и время готово с точностью до такта.

Обновлено Редакция GAW

Счётчик тактов CYCCNT — 32-битный регистр DWT_CYCCNT в блоке DWT (data watchpoint and trace) ядер Cortex-M3 и Cortex-M4. Когда он включён, он увеличивается на каждом такте процессора и при переполнении прозрачно переходит в ноль (DDI 0403E, разд. C1.8.3). Это самый простой способ узнать время выполнения участка кода с точностью до такта.

Как включить

ШагРегистрБит
1. Разрешить DWT и ITMDEMCR, 0xE000EDFCTRCENA (24)
2. Обнулить счётчикDWT_CYCCNT, 0xE0001004записать 0
3. ЗапуститьDWT_CTRL, 0xE0001000CYCCNTENA (0)

Адреса — по DDI 0403E и таблице 8-1 Cortex-M3 TRM. Без шага 1 блок DWT выключен, и счётчик не идёт.

Замер выглядит так: прочитать CYCCNT, выполнить участок, прочитать снова и вычесть. Время равно разности, делённой на частоту ядра. Готовый пример с формулой — в ответе как измерить время выполнения кода.

Что попадает в замер

  • Такты ожидания флеш-памяти. Счётчик считает реальные такты, поэтому замер включает такты ожидания и промахи буфера предвыборки — то, чего нет в таблице тактов команд.
  • Прерывания. Если во время участка сработал обработчик, его время тоже попадёт в разность. Для чистого замера прерывания на это время запрещают или повторяют замер несколько раз и берут минимум.
  • Останов отладчиком. Пока ядро стоит на точке останова, счётчик не идёт.

Переполнение

Частота ядраПолный оборот 2³² тактов
72 МГц≈ 59,7 с
168 МГц≈ 25,6 с

Беззнаковое вычитание в 32 битах даёт верную разность, пока интервал короче оборота. Для длинных интервалов подходит SysTick или аппаратный таймер.

Где ещё используется

Тот же блок DWT строит точки наблюдения за данными и через SWO выдаёт трассировку, а компаратор 0 умеет сравнивать адрес не с адресом данных, а со значением CYCCNT. Состав отладочных блоков Cortex-M3 перечислен в статье о ядре Cortex-M3.

Частые вопросы

Почему DWT->CYCCNT всё время читается как ноль?

Блок DWT выключен. Сначала надо установить бит TRCENA (24) в регистре DEMCR по адресу 0xE000EDFC — это общее разрешение DWT и ITM, — затем бит CYCCNTENA (0) в DWT_CTRL (DDI 0403E, разд. C1.6.5 и C1.8.3). В CMSIS: CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk.

Есть ли CYCCNT в любом микроконтроллере на Cortex-M?

Нет. Даже в архитектуре Armv7-M, к которой относятся Cortex-M3 и M4, счётчик необязательный: есть ли он, показывает бит NOCYCCNT регистра DWT_CTRL — при наличии счётчика он читается как 0 (DDI 0403E, разд. C1.8.3). Если счётчика нет, время меряют аппаратным таймером или SysTick.

Как правильно считать разность, если счётчик переполнился?

Вычитать беззнаково в 32 битах: (uint32_t)(t1 − t0). Счётчик прозрачно переходит через ноль, и разность остаётся верной, если интервал короче одного полного оборота — 2³² тактов, около 25,6 с при 168 МГц и около 59,7 с при 72 МГц.

Источники

  1. Arm. Armv7-M Architecture Reference Manual, ARM DDI 0403E.e (ID021621) — разд. C1.8.3: CYCCNT — необязательный свободно бегущий 32-битный счётчик тактов, при наличии бит DWT_CTRL.NOCYCCNT читается как 0; увеличивается на каждом такте процессора, при переполнении прозрачно переходит в ноль; не считает, пока процессор остановлен в отладке; включается битом DWT_CTRL.CYCCNTENA, регистр DWT_CYCCNT можно читать и записывать; разд. C1.8.7: CYCCNTENA — бит 0 регистра DWT_CTRL; разд. C1.6.5: бит 24 TRCENA регистра DEMCR (0xE000EDFC) — общее разрешение блоков DWT и ITM; блок DWT занимает адреса 0xE0001000–0xE0001FFF
  2. Arm. Cortex-M3 Processor Technical Reference Manual, r2p1, ARM 100165_0201_02_en — разд. 8: DWT — счётчики тактов и событий, до четырёх компараторов, компаратор 0 может сравнивать со счётчиком тактов CYCCNT; табл. 8-1: DWT_CTRL по адресу 0xE0001000, DWT_CYCCNT — 0xE0001004, значение после сброса 0

Нашли ошибку?