Счётчик тактов 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 и ITM | DEMCR, 0xE000EDFC | TRCENA (24) |
| 2. Обнулить счётчик | DWT_CYCCNT, 0xE0001004 | записать 0 |
| 3. Запустить | DWT_CTRL, 0xE0001000 | CYCCNTENA (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 МГц.
Источники
- 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
- 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
Нашли ошибку?
Смотрите также
- Как измерить время выполнения кода на микроконтроллере?Счётчик тактов CYCCNT, аппаратный таймер, импульс на выводе
- Точка остановаАдрес, на котором отладчик останавливает выполнение программы
- SysTick24-битный таймер ядра Cortex-M для системного тика
- Такт ожиданияЛишние такты при обращении к медленной памяти: частоты, настройка, кэш
- SWO (вывод трассировки)Однопроводный вывод трассировки и отладочных сообщений Cortex-M
- Cortex-M3Регистры, карта памяти, bit-banding, NVIC, SysTick, MPU, старт, пример