AVR. Учебный Курс. Оценка загрузки контроллера.
Автор DI HALT
Опубликовано 18 июня 2009
Рубрики: AVR. Учебный курс
Метки: AVR, RTOS, Отладка, Трюки, ЦАП
Как оценить загруженность микроконтроллера? С памятью все понятно — размеры занимаемого кода и оперативной памяти показывает компилятор, а что делать с процессорным временем? Конечно, в линейной программе можно взять и посчитать время выполнения каждой процедуры и станет ясно успеет микроконтроллер выполнить все на него повешанное или слажает в каком-нибудь критичном месте.
Куда сложней оценивать время в кооперативной операционной системе реального времени. Тут задачка получается нетривиальной — у нас куча процессов скачут через диспетчер. В ходе программирования задачи навешиваешь одну за другой, как бусинки на нить — каждый процесс обработки чего либо составляет подобную цепочку, а всего их может быть просто тьма. Ядро же у контроллера всего одно, а значит выполнять можно всего одну задачу за раз и если у нас в диспетчере скопится много критичных ко времени процессов (вообще их лучше развешивать на прерывания, но бывает и прерываний на всех не напасешься), то возможно либо переполнение очереди диспетчера, либо превышение времени ожидания, что тоже не праздник.
Самое западло в том, что умозрительно отлаживать такие вещи довольно сложно. Единственный вариант — рисовать временные диаграммы запуска каждой задачи и смотреть где у нас узкие места. Еще можно попробовать в AVR Studio поставить Break Point на переполнение диспетчера, но студия не сэмулирует всю ту прорву периферии, а в пошаговой отладке этого не увидеть — да и момент надо подобрать так, чтобы все навалилось.
В один момент мне пришла в голову одна идея — а почему бы не заставить рисовать временные диаграммы работы задач сам контроллер? Это же просто! Берем и в диспетчере, перед вызовом задачи выставляем бит порта в 1. А когда диспетчер задач опустошается полностью, то есть выполняется переход на Idle — сбрасываем бит в 0. В результате, у нас на выходе будет подобие ШИМ. Если постоянно крутится Idle — будут нули перманентно. Если же проц в поте лица гонит через себя непрерывно код, то будут высокий уровнь сплошняком. А если все прерывисто — что то ШИМообразное. Причем чем больше загрузка процессора тем выше заполнение. Можно поставить интегрирующую RC цепочку и получим аналоговый сигнал. Хоть на стрелочный индикатор заводи :). Сказано — сделано.
Получилось вот так:
![]() |
Пока задача шлет раз в секунду байт по UART, а остальное время Idle, т.е. бездельничает.
А вот мы добавили опрос клавиатуры. Стало бодрей — иголки увеличились числом. Каждая иголка запуск процесса.
![]() |
Вот одна иголка крупным планом.
![]() |
Вызваю процедуру записи в EEPROM — во как, сразу же сожралось куча времени на выполнение. А записалось всего 6 байт. Обратите внимание на масштаб времени. Насколько запись в EEPROM дольше выполнения обычного кода.
![]() |
Но одними иголками сыт не будешь. Не прикольно. Как бы задачки эти выделить. Чтобы можно было понять кто есть кто. Решение элементарное — выделить для отладочных целей не один бит, а поболее. У меня тут в запасе нашлось целых 8 ног. Соответственно я сразу же по заходу в задачу вывел в порт ее номер, а из порта загнал в R-2R ЦАП. Картина стала наглядней — теперь высота иголки у всех задач стала разной.
![]() |
Чем меньше номер, тем меньше напряжение с ЦАП. Мало того, если задачи вызываются последовательно, а не через очередь таймеров то будут не иголки, а лесенки.
![]() |
Вот что мы видим. Иголки номер 1 - это сканирование клавиатуры. Те что повыше, номер 2 — это пинг, отсыл одного байта по UART, а вот средние — отправка пачек данных через тот же UART.
Вообще применение осциллографа это могучее средство для реалтаймовой отладки. Не обязательно таким замудреным способом как у меня. Это я больше для прикола и наглядности всякие АЦП вешаю. Достаточно же просто бит выводить и смотреть на осциллографе. Еще можно добавлять программные ловушки. Например, переполнилась критическая переменная — выдали бит. А чтобы не ловить на экране осциллографа этих тараканов, проще этот бит завести на какую-либо следящую систему, да хоть на триггер. Взвел следилку и гоняй свою отлаживаемую программу в хвост и в гриву, нагружай пока не позеленеет от натуги. А если где то что то сорвет, то выскочит твой бит, триггер его запомнит и там хоть сирену включай — ахтунг! Error!!!
Для большей наглядности решил я записать видяшку с происходящим. Там я нагружаю микроконтроллер и показываю как меняется диаграмма загрузки. На некоторых кадрах есть сильная засветка — эт мой светлый лик, заметил уже когда залил на комп, а переснимать мне было влом. Да, думаю, и так все самое интересное видно. Также не смотрите на то, что диаграммы иногда плывут по оси Y — я забыл переключить осцилл на постоянное напряжение.
Однобитные иголки
Нагрузили еще немного. Шлю по UART, видно как растет нагрузка на конвеер
Применили R-2R ЦАП.
Комментарии
10 комментариев на «AVR. Учебный Курс. Оценка загрузки контроллера.»
Оставьте свой отзыв
Вы должны войти, чтобы оставлять комментарии.











Заманчивая идея… Я тоже сначала думал как такую шнягу можно замутить, а потом дошло что нужно менять уровень на ноге))) А вот чтобы делать иголки разные по высоте… не дошло. Хотя их смысл только на осциллографе есть, так как если выводить как аналоговый сигнал… Будет портиться картина=)
Надо будет тоже летом замутить, но после того как сделаю свою ОС, так как только там она имеет смысл (Я даже не смотрел код Вашей ОС=) ). У Вас же все под ОС работает?
Да это под ОС все сварганено
У меня большинство программ выполнено в виде главного цикла, в котором последовательно проводится проверка и исполнение задач. Вертится он постоянно, время выполнения зависит от нагрузки. С самого начала я прикидываю критическое время, за которое должен пробегать цикл, чтобы все успеть и ничего не потерять. От того, насколько он крутится быстрее, можно судить о запасе производительности.
В начале главного цикла аналогично выставляю 1 на какой - нибудь неиспользуемой ноге, в конце - снимаю, но чаще, чтобы не ловить “иголки”, просто в начале цикла инвертирую состояние ноги. Получаю почти меандр, частоту или период которого смотрю осциллографом, если нужна точность - частотомером. Часто для проверки выполнения какого-либо куска кода также делаю контрольный вывод. Отладочная информация - великая вещь, никакой симулятор не заменит отладки в реальном времени, на реальном железе. Поэтому я обычно прекрасно обхожусь без симуляторов и отладочных плат, отлаживая программу сразу на плате устройства.
Ну так в твой главный цикл все равно в случайном порядке вклиниваются куски кода в зависимости от флагов. Или ты просчитваешь максимально худший вариант развития событий?
Я обычно определяю критичные возможные ситуации (к примеру, время обработки байта, поступающего с канала связи, и связанных с ним действий, до поступления следующего), и исходя из этого просчитываю максимально допустимые времена. Потом просчитываю время прогона цикла, исходя их худшей ситуации (одновременная обработка всех событий). Если не укладываюсь - оптимизирую алгоритмы, ищу другие варианты, использую аппаратную поддержку некоторых функций. При отладке смотрю реальное время прогона, прикидывая, насколько велик запас. В общем, всегда исхожу из худшего из возможного, заранее избавляясь от кучи проблем в дальнейшем.
Кстати, в PIC очень удобно считать времена: все команды выполняются за один цикл (4 такта), переходы - за 2 цикла. На I8080 было сложнее, там команды выполнялись от 3 тактов до 18, от 1 до 5 циклов, причем машинный цикл мог содержать от 3 до 5 тактов… И ничего, считал.
Здравствуйте всем! Немного не в тему… DI HALT, ты обещал написать о самодельном JTAG ICE.
И напишу, когда доделаю. Жду прихода Мега16. Собственно уже готов девайс.
Привет, DI HALT, я вот смотрю на картинку и непонимаю, а как ты смог записать 6 байт в EEPROM за 4,5 мс, у меня запись одного байта длится 8,5 мс, как по даташиту. Посмотрел твой код записи, всё вроде то же самое, поделись секретом.
Ну вот так само получается О_о
Шью побайтно, с тупым ожиданием флага готовности. На выходе бит устанавливается в момент ухода на процедуру записи и сбрасывается в момент ухода на диспетчер. Получилась вот такая картинка.
хехе, гениальненко однако:)