AVR. Учебный Курс. Отладка программ. Часть 2

Метод 2. Моргалки (Работа портами Ввода-вывода)

Трассировка и аналитика это все замечательно, но когда мы начинаем отлаживать что то внешнее, то тут трассировка нам поможет мало. Т.к. глючить может не внутри, а снаружи.
 

Либо у нас будет не глюк, а банальное непонимание ситуации. Фразу из даташита, например, неправильно перевел или глаз замылился. Что то забыл или не туда припаял. Да мало ли как можно накосячить.
 

В общем, правильный алгоритм может работать из-за кривой аппаратной реализации. А чтобы понять где косяк надо проследить и знать как это работает внутри. В общем, заглянуть в код программы.
 

Причем нам не обязательно точно следить за тем, что там происходит покомандно — это мы или трейсом или туплением отладим. Интересней знать куда ушла прога.
 

Самым простым методом тут будет отладочный вывод. Все просто — мы берем и определяем один из выводов под отладку. Причем даже если у нас какая-нибудь крошечная тинька и все выводы расписаны буквально по нескольку раз, то все равно можно найти один лишний вывод — достаточно закомментить код который его использует, но в данный момент его правильность нас не интересует.
 

А у вывода может быть три состояния — Hi, Lo и Hi-Z. Так что рекомендую скреативить такой вот пробничек:
 

 

Тогда если у нас Hi-Z то будут тускленько гореть оба диода. Ну, а на соответствующий уровень свой диод в гордом одиночестве.
 

А в код пихаем дебажные секции вида:
 

1
2
3
;Set Hi
	SBI	DEBUGDDR,DEBUG
	SBI	DEBUGPORT,DEBUG
1
2
3
;Set Lo
	SBI	DEBUGDDR,DEBUG
	CBI	DEBUGPORT,DEBUG
1
2
3
;Set Hi-Z
	CBI	DEBUGDDR,DEBUG
	CBI	DEBUGPORT,DEBUG

 

Можно их в макросы завернуть. Удобней будет.
 

По состоянию дебаг вывода мы можем увидеть в каком месте программа прошла. А комбинируя нашу троичную систему получим целых 9 возможных комбинаций на 2 вывода.
 

Однако если у нас надо отследить последовательность, то мы можем и не успеть разглядеть переимгивание светиков. Но никто не мешает воткнуть в код после смены состояния дебагвывода тупую задержку вида:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	PUSHF			; Макрос сохранения флагов
	PUSH 	R16
	PUSH	R17
	PUSH	R18
 
	LDI	R16,255	; Грузим три байта
	LDI	R17,255	; Нашей выдержки
	LDI	R18,255
 
Dloop:	SUBI	R16,1		; Вычитаем 1
	SBCI	R17,0		; Вычитаем только С
	SBCI	R18,0		; Вычитаем только С
 
	BRCC	DLoop 		; Если нет переноса - переход
 
	POP	R18
	POP	R17
	POP	R16
	POPF			; Макрос восстановления флагов

 

Оформляется как прерывание для того, чтобы иметь минимальное влияние на код. Можно тоже оформить в виде макроса и втыкать его одной строчкой. Запрет прерываний опционально.
 

Либо вставлять затуп:

1
	RJMP 	PC

 

Контроллер на этой команде встанет и дальше никуда не пойдет (правда если включен вачдог, то он ребутнется по вачдогу).
 

А можно же сразу после задержки перевести отладочный вывод в режим входа PullUp и просить кнопку пробника. Если нажата, можно идти дальше. Можно и без задержки, сделать, но надо смотреть, чтобы дребезг не помешал.
 

1
2
3
4
5
6
;STOP DB_BTN
	CBI	DEBUGDDR,DEBUG
	SBI	DEBUGPORT,DEBUG	
 
	SBIC	DEBUGPIN,DEBUG
	RJMP	PC-1

 

Можно просто наставить таких кнопочных чекпоинтов. И пускать программу по ним своей могучей волевой рукой. А пока программа тупит на задержках или ожиданиях кнопок, можно спокойно замерить напряжения/пощупать лог уровни, состояние других выводов, да просто подумать.
 

Разумеется, если в схеме уже присутствуют светодиоды и кнопки, то и пробник тут не нужен — обойдемся имеющимися средствами — переназначив их на время отладки конкретного участка.
 

Правда в случаях отладки асинхронных устройств, работающих на четких временных выдержках данная затея может не прокатить, но для них есть другие варианты, о них позже.

34 thoughts on “AVR. Учебный Курс. Отладка программ. Часть 2”

  1. Di HALT как всегда просто нереально угадал, и мне именно этой информации сейчас и не хватало. Как раз вконтакте вопрос связанный с этой темой задавал. Ди даже в том топике поучаствовал. =)) А теперь думаю у меня все вопросы отпадут.

    1. я обычно интуитивно отлаживаю светиками.. правда хитрые схемы на >2 «уровней» не делаю :) ибо ног у меги16 хватает за глаза..

      кстати, ещё как вариант: если отлаживается какая-то периодическая функция, можно каждый проход (либо в каком-либо условии) инвертировать свободную ногу и щупать её осциллографом.. за неимением оного я цепляю миниатюрный а-ля «pc speaker», которым обычно биос пикает :) занижается частота МК, и можно послушать, ровномерно ли оно пищит, либо где-то залипает..
      да способов отладки масса, если задуматься..

      1. Про осциллограф тоже будет, чуть дальше :)))) Кстати, со спикером классная идея. На слух колебания частоты можно очень хорошо спалить.

        1. так началось же всё изучение микропремудростей как раз со всяких мигалок, пищалок и дрыгалок =) из подобных простейших элементов взаимодействия с окружающей средой и строятся отладки, т.к. уже точно известно, как оно работает.. а, например, при отлаженном и связанным с компом USARTе, можно вообще слать на терминал (или в отладочную прогу, для этого написанную) байтики проходов.. и по ним смотреть, куда и при каких условиях он туда залез.. «#define debug» и «#ifdef debug … #endif» творят чудеса, как уже где-то говорилось, только в асмовском диалекте :)
          мда, сказывается опыт отладки «через жопу» пхпшных скриптов без дебаггера, что поделать.. %))

          1. ГыГы… и я тоже когда-то давно, намного раньше, чем занялся контроллерами, убил уйму времени на отладку ПХПшных скриптов «через жопу» без дебаггера. =) Полезный, однако, опыт. С тех пор я дебаггером вообще не пользуюсь, даже когда пишу большие программы для большого компа =).

            1. ну с одной стороны конечно можно понавставлять «отлажочных шоумесседжей», как я их обычно называю %) но с другой стороны, иногда всё-таки проще смотреть на состояние памяти, переменных, стэка и пр.. так решается больше проблем за более короткий срок.. просто лично меня от подобного на МК сдерживает во-первых отсутствие JTAG-а, а во-вторых, лень установки эмулятора %) тут мне проще извратиться.. а когда занимаешься системным программированием, то уж гораздо лучше тыкать F7 и F8 :)

        2. До сих пор периодически , как отладочный инструмент использую щуп с высокоомным наушником и последовательно соединенным конденсатором. не раз спасал, начиная со звуковых схем. просто и доступною. у спикера оказалось низкое сопротивление.

  2. А нет макрооператоров вида «.ifdef DEBUG код код код .enddef»

    смысл в том, что если определена константа DEBUG в начале программы, то компилятор оставит строки кода внутри «.ifdef DEBUG код код код .enddef», иначе же выкинет автоматом и их не придется удалять руками. В С++ есть еще такое.
    Архиполезно — пол программы переворотишь с ног на голову, пока разберешься где глюк, а потом вспоминай что ты поправил удалил или закомментил…

    1. Есть, но я их не люблю. С этими дебажными сессиями исходный код превращается в полную помойку. Ну нах. Я обычно дебаг тычки ставлю без табуляций и выделяю яркими маркерами комментов, чтобы точно найти.

  3. > Однако если у нас надо отследить последовательность, то мы можем и не успеть разглядеть переимгивание светиков.Но никто не мешает воткнуть в код после смены состояния дебагвывода тупую задержку

    а ещё можно тактировать МК при помощи кнопки (с фильтром дребезга) =)

    1. Я предпочитаю делать это с помощью МК. Причем система такая — этот МК дает такты автоматически, но следит за отладочной линией. И если линия уходит в 0 то тут же прекращает дрыгать ножкой, переходя в ручной режим. Своего рода аппаратные точки останова.

      1. А можно организовать DEBUG в программе таким образом, чтобы он переводил контроллер в режим тактирования от кнопки с антидребезгом? Совместить два ваших метода?
        А по еще одной кнопке — возвращать тактирование в нормальный режим до следующего DEBUG
        Чтобы не лепить ещё один контроллер?

        1. Нельзя. Тактирование задается один раз и навсегда фузами. Единственно ты можешь сделать сразу тактирование от кнопки, но тогда тебе придется вслепую этой кнопкой «проматывать» программу вручную до нужного места :)

          1. ну так я не предлагаю ограничиваться jtag или debugwire, можно просто через уарт слать логи.

            Я вообще в любую вещь (если совсем не припрёт) делаю возможность перевода девайса в «сервисный режим» чтобы девайс слал логи в юарт. Очень помогает если на боевом девайсе что-то случилось не так

  4. А я вместо диодов использовал 7сегментик.
    Еще круто было бы увидеть подробную статью по отладке через УАРТ.

  5. Я для аппаратной отладки использую маленький девайс — 7-ми сегментный индикатор + PCF8574 (8bit I/O I2C). Подключается 4-мя проводками (2 питание + 2 шина I2C)Использую готовые куски кода для работы с PCF8574. В нужном месте отлаживаемого кода вставляю макрос, например CheckPoint_1, который зажигает «1». Итого использую до 16 точек 0…9, A…F + еще можно кучу придумать.

    1. У меня примерно тоже, но по уарту или по спи. Банально быстрей и проще чем гонять ииц автомат.

  6. Мужики привет. Меня ОЧЕНЬ сильно заинтересовал по тексту макрос флагов pushf.

    1.В каких случаях нужно его использовать?
    2.Идет речь сугубо только лишь о регистре SREG?
    3.Или что то еще?
    4.Я только знаю что входя в прерывание нужно его сохранить в стеке, а выходя извлечь. Это я читал здесь на сайте.
    5.Нужно ли так же поступать со SREG входя в подпрограммы?

    Раньше я не сохранял sreg перед входом в прерывания постоянно глюки были, пока DIHALT не объяснил что нужно. В общем уточните мое понимание или скиньте ссылку где об этом можно на сайте почитать.

    1. 1) Обычно в прерываниях или когда мы не хотим чтобы срег изменился.
      2) Нет, там попутно емнип еще и R16 сохраняется
      5) Можно, но не обязательно

      В меню сайта есть АВР. Учебный курс. Тыкни туда и прочитай первые несколько, одна из них Подпрограммы и прерывания зовется или как то так. Вот там этот момент расписан максимально подробно, с описанием того зачем это надо и что будет если это не сделать.

Добавить комментарий

Ваш e-mail не будет опубликован.

Перед отправкой формы:
Human test by Not Captcha