|
Простой и прозрачный способ отладки программ, (особенно для начинающих) |
|
|
|
Dec 11 2007, 15:32
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Время от времени слышатся просьбы о помощи в отладке программы. Ниже предлагается простой способ отладки через уарт путём внесения отладочной информации в отлаживаемую программу, т.е. по мере необходимости в исследуемые ветви отлаживаемого кода вставляются две строчки с определённым текстом, например, таким Код rcall debug .db "some datum to be sent",0 или таким Код rcall debug .db "первая точка пройдена",0 Программа вывода отладочной информации имеет следующий вид Код debug: pop zh pop zl lsl zl rol zh deb1: lpm temp,z+ tst temp brne deb2 lsr zh ror zl ijmp deb2: sbis ucsr0a,udre0 rjmp deb2 out udr0,temp rjmp deb1 и занимает всего 14 слов кода. Интересно бы пообсуждать данный метод и узнать заодно, кто-нибудь пользуется подобным способом отладки?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
2 страниц
< 1 2
|
 |
Ответов
(15 - 29)
|
Dec 12 2007, 10:53
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(adc @ Dec 12 2007, 08:45)  Странно, почему ув. =GM= не написал такой код сразу?! (с добавлением lsr,ror и т.д.) или это подразумеевалось само сабой?! Не, я забыл вставить, извините, писал по памяти. Для LPM нужна байтовая адресация, а для IJMP - словная. Для удобства использования поправил в исходном посте (добавил недостающие lsr, ror, lsl, rol). Не ругайте меня сильно(:-).
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Dec 12 2007, 12:59
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(sla000 @ Dec 12 2007, 07:39)  ИМХО вывод длинных строк для отладки - непозволительная роскошь если отлаживается какой-то быстрый алгоритм. Несомненно. Цитата(sla000 @ Dec 12 2007, 07:39)  Я в таких случаях использую буфер - массив байт на 50, который заполняю отладочной информацией в критических к времени выполнения участках кода, а потом, когда этот участок кончится выстреливаю в ком-порт все данные из этого буфера. Один из возможных вариантов, весьма удобен. В крайнем случае туде можно и после сброса "заглянуть", посмертное вскрытие, так сказать. В реалтаймовых вещах иногда полезно и просто махание лапками, чтобы скопом или логическим пробником посмотреть, светодиод "на борту" тоже может серьезно облегчить работу.
|
|
|
|
|
Dec 12 2007, 13:27
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Вставлю и свои 5 коп  Тоже uart, но с прерываниями. В памяти формируется строка, но не ASCIIZ а первый байт = кол-во байтов. Ещё нужен счётчик адреса (1 байт), если нет желания получать строку задом наперёд. Строка формируется в программе, где надо. Когда можно начать отправку, жду UDRE и пишу байт в UDR, например, '@' - "начало сообщения". Дальше оно самО: по прерыванию UDRIE если счётчик+1=длине то выходим; иначе UDR = байт с адреса строки+счётчик. В прерывании TXCIE обнуляем счётчик (на будущее). Здесь не надо ждать, программа выполняется в фоне, прерывания происходят 1 раз на байт и занимают немного времени.
|
|
|
|
|
Dec 12 2007, 16:48
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
To rx3apf Посмотрел ваш код, неплохо написано, все используемые регистры сохраняются, только немного тяжеловесно из-за этого. А вот эти две инструкции Цитата(rx3apf @ Dec 11 2007, 16:54)  Код msg2: sbrc ZL,0 adiw ZL,1 ; коррекция для нечетного адреса по большому счёту не нужны, поскольку при чётном числе байт asciz-строки делать ничего не нужно, а при нечётном числе байт в последнем слове asciz-строки будет 0х0000, а это код команды nop. Поэтому в моём варианте и нет коррекции нечётного адреса. Ещё одно соображение по поводу сохранения регистров. Мне кажется, в фоне должны быть доступны все регистры регистрового файла. Тут главное не дойти до абсурда, например сохранить два регистра, участвующих в сложении, сохранить результат, а затем восстановить оба регистра. Возможно, выбран не самый удачный пример, но смысл наглядно видно. Само собой разумеется, что многое зависит от задачи.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Dec 13 2007, 13:00
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(mse @ Dec 13 2007, 09:59)  А зачем так долбаться, если можно тупо поставить брякпойнт и, тормознувшись, посмотреть содержимое кишечника впрямую, а не через замочную скажину Добавлю к тому, что сказал rx3apf. Не все аврки имеют джейтаг или дибагвайе. А если и имеют, то не всякий начинающий программер имеет соответствующий отладчик.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Dec 14 2007, 08:28
|

Местный
  
Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317

|
Хм... Я тоже использую вывод отладочной информации в терминал - уж очень это просто и удобно. Правда использую для этого стандартный сишный printf или его модификацию printf_P. Правда совершенно недопустимо делать такой вывод в прерываниях - убедился наступив неоднократно на грабли. Здесь верную мысль подал sla000: Цитата(sla000 @ Dec 12 2007, 07:39)  Я в таких случаях использую буфер - массив байт на 50, который заполняю отладочной информацией в критических к времени выполнения участках кода, а потом, когда этот участок кончится выстреливаю в ком-порт все данные из этого буфера. Как я сам до этого не додумался... Разного рода ICE-отладчикам я не доверяю, вернее не люблю их. Отладить вычислительный алгоритм можно и на комповской программе при помощи обычного сишного компилятора. Так недавно я писал сравнительно большой код для канального уровня ком-порта после чего его перенес на контроллер, внеся небольшие изменения в хидере исходника. Тем не менее пару раз делал некое подобие пошаговой отладки через терминал: Код uint8_t break_flag = 0; void break_point(char *message) { break_flag = 0; if (message != 0) printf("BREAK_POINT: %s\n",message); while(!bit_is_set(break_flag,0)); }
SIGNAL(SIG_UART_RECV) { uart_rec(); // = void uart_rec(void) {while (!(UCSRA & (1<<RXC)) ); return UDR; } break_flag = 1; } Потом в нужном месте кода вставляю строчку Код break_point("Break point"); на которой исполнение останавливается, ожидая нажатия кнопки на клавиатуре. Да, это можно делать, только когда код не загроможден другими задачами, и применимость такого метода его крайне узкая. Тем не менее, я так вполне успешно отлаживал генерацию JTAG сигнала с пошаговым его анализом.
Сообщение отредактировал Aesthete Animus - Dec 14 2007, 08:30
|
|
|
|
|
Dec 15 2007, 09:12
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(=GM= @ Dec 14 2007, 23:32)  А что вы имеете в виду под условными? Откуда брать условия и какие? Самому задавать в прерывании? Так вот, пока уважаемый, но свирепый =AVR= учит нас выбирать велосипед  , представим себе ситуацию, когда разбираться в отладчике невозможно ввиду огромного кода. А у Вас все ОК, кроме того, что где-то подленько сваливается STACK, или какая-л. ячейка памяти живет своей жизнью. Таким методом пишете поллинг памяти или указателя стека. Обратите внимание на то,приоритет INT0 ISR наивысший. Если же надо залезть в другие ISR, ставите SEI при входе в прерывание. Единственное неудобство - сохранение контекста.
|
|
|
|
|
Dec 16 2007, 09:32
|
Группа: Новичок
Сообщений: 9
Регистрация: 27-11-07
Пользователь №: 32 731

|
Я отлаживаю так проги 1 в разных функциях с помощью флагов типа flag |= 1 << 3; выставляю флаги и запускаю программу с брек поинтом в нужной точке программы используя при этом JTAG 2 он пошустрее будит и чего то он мне больше нравится чем 1 , 2 и в результате у меня идет еще и трассировка программного кода что в 8 разрядных контроллерах большая редкость выявляются сложные ошибки типа мерцающих неисправностей это типа на работе все работает у клиента поставили и раз в четыре дня сбои ну или что то вроде этого, вообще пользуюсь отладочными средствами Атмеля чего и вам желаю - удобно, быстро и с комфортом разработка на микроконтроллерах превращается не в работу а что то типа игры и если есть цифровой осциллограф (я использую veleman 500A генератор и разные считыватели интерфейсов которые вы используете в работе) то все должно быть прекрасно а одними руками головой и паяльником конечно можно сделать устройство на микроконтроллере но это может занять годы это мое мнение не более
Я отлаживаю так проги 1 в разных функциях с помощью флагов типа flag |= 1 << 3; выставляю флаги и запускаю программу с брек поинтом в нужной точке программы используя при этом JTAG 2 он пошустрее будит и чего то он мне больше нравится чем 1 , 2 и в результате у меня идет еще и трассировка программного кода что в 8 разрядных контроллерах большая редкость выявляются сложные ошибки типа мерцающих неисправностей это типа на работе все работает у клиента поставили и раз в четыре дня сбои ну или что то вроде этого, вообще пользуюсь отладочными средствами Атмеля чего и вам желаю - удобно, быстро и с комфортом разработка на микроконтроллерах превращается не в работу а что то типа игры и если есть цифровой осциллограф (я использую veleman 500A генератор и разные считыватели интерфейсов которые вы используете в работе) то все должно быть прекрасно а одними руками головой и паяльником конечно можно сделать устройство на микроконтроллере но это может занять годы это мое мнение не более
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|