Можно ли отслеживать блок кода и определять количество тактовых циклов процессора, которое код выполнял на процессоре Armelino и / или AVR Atmel? или лучше отслеживать микросекунды, прошедшие до и после выполнения кода? Примечание: меня не интересует реальное время (например, сколько реальных секунд прошло), а то, что я "сколько тактовых циклов требует этот код от процессора"
Текущее решение, которое я могу придумать - это time.c:
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
wiring.c добавляет:
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
По этой учетной записи я мог бы рассчитать тактовые циклы, пройденные путем мониторинга пройденных микросекунд, а затем передать их в microsecondsToClockCycles (). У меня вопрос, есть ли лучший способ?
sidenote: есть ли хорошие ресурсы для мониторинга производительности AVR. lmgtfy.com и различные поиски на форумах не дают никаких очевидных результатов, кроме исследования таймеров.
Спасибо
Что вы подразумеваете под «монитором»?
Не должно быть сложно рассчитывать тактовые циклы для AVR для небольших фрагментов кода сборки.
Вы также можете установить порт до того, как код будет выполнен, и сбросить его после этого, и отслеживать его с помощью логического анализатора или осциллографа, чтобы получить время.
И вы могли бы также прочитать время из быстродействующего таймера, как вы говорите.
источник
Это пример того, как Arduino использует функцию clockCyclesPerMicrosecond () для вычисления прошедших часов. Этот код будет ждать 4 секунды, а затем печатать время, прошедшее с момента запуска программы. Левые 3 значения - это общее время (микросекунды, миллисекунды, общее количество тактов), а самые правые 3 - истекшее время:
Выход:
Я уверен, что есть разумное объяснение, почему первые циклы тоже имели более короткие истекшие тактовые циклы, чем большинство, и почему все остальные циклы переключаются между двумя длинами тактовых циклов.
Код:
Sidenote: если вы уберете 4-секундную задержку, вы начнете видеть эффекты Serial.print () гораздо более четко. Обратите внимание, здесь сравниваются 2 прогона. Я только включил 4 образца рядом друг с другом из их соответствующих журналов.
Прогон 1:
Прогон 2:
Истекшее время увеличивается в течение всего времени выполнения. Через секунду часы увеличиваются в среднем с 40 до 44 тысяч. Это происходит последовательно через несколько миллисекунд после 1 секунды, и истекшие часы остаются около 44k в течение по крайней мере следующих 10 секунд (я не проверял это далее). Вот почему мониторинг полезен или необходим. Возможно, снижение эффективности связано с конфигурацией или ошибками в последовательном соединении? Или, возможно, код неправильно использует память и имеет утечку, которая влияет на производительность и т. Д.
источник
Поскольку каждая строка кода, добавленная в ваш источник, будет влиять на производительность и может изменить применяемые оптимизации. Изменения должны быть минимальными, необходимыми для выполнения задачи.
Я только что нашел плагин Atmel Studio под названием «Отладчик аннотированных сборочных файлов». http://www.atmel.com/webdoc/aafdebugger/pr01.html Похоже, что вы перебираете фактический сгенерированный язык ассемблера, хотя, вероятно, утомительно покажет вам, что именно происходит. Возможно, вам все равно придется декодировать, сколько циклов требуется для каждой инструкции, но это будет намного ближе, чем некоторые другие опубликованные параметры.
Для тех, кто не знает, в папке Output вашего проекта есть файл с расширением LSS. Этот файл содержит весь ваш исходный код в виде комментариев, а под каждой строкой находится язык ассемблера, который был сгенерирован на основе этой строки кода. Генерацию файла LSS можно отключить, поэтому проверьте следующие настройки.
Свойства проекта | Toolchain | AVR / GNU Common | OutputFiles
Флажок ".lss (Создать файл lss)
источник
Вы можете использовать один из встроенных таймеров. Получите все настройки prescaller = 1 и TCNT = 0 перед кадром. Затем включите таймер на линии перед блоком и отключите его на линии после блока. TCNT теперь будет хранить количество циклов, которое принял блок, за вычетом фиксированных циклов для кода включения и отключения.
Обратите внимание, что TNCT переполнится после 65535 тактов на 16-битном таймере. Вы можете использовать флаг переполнения, чтобы удвоить время выполнения. Если вам все еще нужно больше, вы можете использовать прескалер, но получите меньшее разрешение.
источник