Отладчик µVision2. Пример использования пользовательских отладочных функций: определение времени выполнения участка программы
Александр Бельченко
20 мая 2003
В этой статье пойдет речь об использовании пользовательских отладочных функций на примере функции, которая вычисляет длительность выполнения участков отлаживаемой программы.
Пример иллюстрирует информацию из следующих документов:
GS51.pdf: глава 6 «Отладочные функции» (перевод), глава 5 параграф «Системные переменные» (перевод);
Dbg51.chm: команда DEFINE (перевод)
Я хочу рассказать о пользовательской отладочной функции, которую написал во время отладки одной из своих программ. При отладке некоторых алгоритмов этой программы для меня было важным достичь максимального быстродействия. Пусть даже в ущерб размеру программы.
Поставленную цель я достиг несколькими способами: выбором уровня оптимизации компилятора, оптимизацией циклов, переписыванием некоторых стандартных арифметических функций. Каждый раз, изменяя что-то в программе, я запускал симулятор и определял насколько быстрее (или медленее) становилось выполнение алгоритма.

Наверное, описание многих тонкостей такой оптимизации программы заслуживает отдельной статьи. В данный момент я перейду к обещанной отладочной функции. Я написал эту пользовательскую отладочную функцию, когда мне надоело каждый раз при прогонке программы в симуляторе вычислять на калькуляторе сколько же времени тратится на ту или иную часть алгоритма, и где еще есть узкие места, которые требуют более тщательной оптимизации. «Как бы эту нудную ручную работу поручить компьютеру?» подумал я. Решение сформировалось достаточно быстро, поскольку отладчик µVision2 позволяет создавать пользовательские отладочные функции. Если вы еще не знакомы с отладочными функциями, то можете прочитать про них в главе 6 документа GS51.pdf.
Для упрощения я решил ограничиться задачей определения времени в тактах процессора и в миллисекундах, которое прошло с момента последнего вызова этой функции. При каждом вызове функции запоминалось текущее состояние счетчика тактов процессора states, которое затем использовалось при последующих вызовах функции. Для определения прошедшего времени в миллисекундах достаточно использовать виртуальный регистр CLOCK, который показывает сколько инструкций выполняет процессор за одну секунду. Подробнее о системной переменной states и виртуальном регистре CLOCK вы можете прочитать в параграфе «Системные переменные» из главы 5 документа GS51.pdf (стр.113,114).
Вы можете взять пример (7кБ), в котором используется отладочная функция prog_time(), вычисляющая время в тактах процессора и в миллисекундах. Пример содержит один исходный Си-файл main.c, файл с кратким описанием проекта abstract.txt и файл инициализации p_time.ini для симулятора µVision2. В файле инициализации описывается пользовательская функция prog_time(). Рассмотрим его подробнее. Поясняющих комментариев маловато, но надеюсь, что разобраться в логике работы будет легко.
/*
Вычисление длительности выполнения в отладчике участков программы
(с) Александр Бельченко, 2003
*/
define long state_point
state_point = 0
func void prog_time()
{
long temp, len;
float timelen;
temp = states;
len = temp - state_point;
timelen = (float)len / (float)clock * 1000.0;
printf("Длина: %u такт %8.3f мс\n", len, timelen);
state_point = temp;
}
define button "Длина","prog_time()"
Как это все работает?
В этом файле определяется глобальный символ state_point, определяется пользовательская функция prog_time() и добавляется кнопка Длина на панель окна Toolbox отладчика.
Отладочные функции µVision2 не позволяют использовать статические переменные. Поэтому для сохранения предыдущего значения счетчика тактов между вызовами необходимо использовать глобальный символ state_point, который задается командой отладчика DEFINE. Ему присваивается начальное значение равное 0.
Логика работы пользовательской функции prog_time() достаточно проста: берем текущее значение счетчика тактов процессора states и вычитаем из него предыдущее сохраненное значение. Полученная разница будет искомым временем в тактах процессора. Для определения времени в миллисекундах используется виртуальный регистр clock. Вычисленные значения выводятся на странице Command окна отладчика Output Window при помощи встроенной функции форматированного вывода printf(). Текущее значение счетчика тактов states запоминается в глобальном символе state_point.
Для облегчения вызова пользовательской функции prog_time() командой отладчика DEFINE BUTTON определяется кнопка Длина.
Приведенный файл инициализации Вы можете использовать в своих отладочных сессиях. Для использования файла необходимо или указать его в опциях симулятора (
Options for Target - Debug - Initialization File), или включить его в свой файл инициализации либо загрузить во время отладочной сессии, используя команду отладчика
INCLUDE p_time.ini