В статье рассказывается, как быстро встроить в firmware AVR отладочный вывод на текстовую консоль терминала.
Немногие программисты (особенно начинающие) имеют в своем распоряжении аппаратный отладчик (типа JTAGICE mkII или AVR Dragon). Поэтому светодиод, осциллограф и текстовый вывод остаются актуальным средством отладки и поиска ошибок. Однако даже при наличии аппаратного отладчика часто нужно в реальном времени видеть, что делает выполняющийся код. Для этого в консоль терминала выводят так называемую отладочную информацию - данные, которые должен увидеть программист.
Самый простой способ реализации такого вывода - использование аппаратного UART, который имеется почти во всех моделях AVR. Вывод получается быстрый и нересурсоемкий (т. е. он не занимает много процессорного времени ядра AVR). Для вывода через UART для AVR есть уже готовые подпрограммы и макросы, один из них - модуль oddebug, который есть в составе библиотеки V-USB.
[Использование модуля oddebug.c для отладки]
1. Скачайте библиотеку V-USB [1].
2. В папке vusb-20120109\usbdrv возьмите файлы usbportability.h, oddebug.c и oddebug.h, и скопируйте их в папку своего проекта.
3. Добавьте в проект компиляцию модуля oddebug.c.
Если у Вас проект AVR GCC, то добавьте модуль oddebug.c в список компиляции и линковки makefile:
SRC = $(TARGET).c \ Descriptors.c \ oddebug.c \ $(LUFA_SRC_USB) \ $(LUFA_SRC_USBCLASS)
Если у Вас проект IAR, то добавьте модуль oddebug.c в дерево модулей проекта.
4. Добавьте в модули, где нужно использовать отладочный вывод, подключение заголовка oddebug.h (директивой include).
#include "GenericHID.h" #include < avr/io.h > #include "oddebug.h" /* Макросы для отладочного вывода через UART */
5. Задайте глобальное макроопределение DEBUG_LEVEL, не равное 0. Если у Вас проект AVR GCC, лучше всего это сделать в makefile проекта:
DEBUG_LEVEL = 1 .. CDEFS += -DDEBUG_LEVEL=$(DEBUG_LEVEL)
Если у Вас проект IAR, то добавьте определение DEBUG_LEVEL в свойствах проекта (Options -> Compiler -> Preprocessor -> Defined symbols).
Модуль oddebug написан таким образом, что значение макроопределения DEBUG_LEVEL может быть либо 0, либо 1, либо 2: DEBUG_LEVEL=0 отладка через UART не активна, код oddebug не компилируется, и макросы DBG1 и DBG2 не работают (хотя они могут присутствовать в коде пользователя). DEBUG_LEVEL=1 работает только макрос DBG1, DBG2 не работает (хотя DBG2 может встречаться в коде пользователя). DEBUG_LEVEL=2 работает и DBG1, и DBG2.
6. Перед главным циклом main сделайте вызов odDebugInit().
int main(void) { SetupHardware();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); odDebugInit(); DBG1(0x00, 0, 0); /* вывод debug: запуск цикла main */ sei();
for (;;) { HID_Device_USBTask(&Generic_HID_Interface); USB_USBTask(); } }
Макрос odDebugInit настраивает UART на скорость 19200 бит/сек, 8 бит данных, один стоп-бит, без четности (19200 baud rate, 8 bit data, 1 stop bit, no parity) - имейте это в виду при подключении к порту отладки.
7. Для отладочного вывода используйте макросы DBG1() и DBG2(). Первый параметр макроса - байт префикса, он выведется в HEX-виде (и за ним будет двоеточие), второй параметр - если не 0, то адрес памяти, откуда будут выведены значения байт (указатель), а третий параметр - если не ноль, то количество байт для вывода. Примеры использования:
DBG1(0x00, 0, 0); //выведется "00:"
u16 var16; var16 = 0x1234; DBG1(0x01, &var16, 2); //выведется "01: 34 12" - HEX значения двух байт переменной var16
Как Вы уже наверное догадались, использование макросов DBG1 и DBG2 позволяет вести отладку на 2 уровнях, в зависимости от значения DEBUG_LEVEL. Если DEBUG_LEVEL = 2, то вывод может быть максимально подробным, так как будут выводить инфу и DBG1, и DBG2. Если DEBUG_LEVEL = 1, то отладочного вывода может быть меньше (будет выводится только макрос DBG1).
[Устранение проблем]
1. oddebug.h:39:5: warning: #warning "Debugging disabled because device has no UART"
Наверное, Вы забыли подключить заголовок, который задает символические имена Вашего микроконтроллера - oddebug.h не нашел имена TXEN или TXEN0, подключите нужный заголовок перед подключением oddebug.h. В проекте AVR GCC нужно подключить файл io.h:
#include < avr/io.h > #include "oddebug.h"
2. Если у Вас чип, у которого нет имен TXEN или TXEN0, но задано имя TXEN1 или другое (например, так у чипа AT90USB162), то поправьте файл oddebug.h примерно так:
#if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */
исправьте на
#if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0 || defined TXEN1) /* no UART in device */
а также
#if defined UCR # define ODDBG_UCR UCR #elif defined UCSRB # define ODDBG_UCR UCSRB #elif defined UCSR0B # define ODDBG_UCR UCSR0B #endif
исправьте на
#if defined UCR # define ODDBG_UCR UCR #elif defined UCSRB # define ODDBG_UCR UCSRB #elif defined UCSR0B # define ODDBG_UCR UCSR0B #elif defined UCSR1B # define ODDBG_UCR UCSR1B #endif
Аналогичным образом поправьте условия определения ODDBG_TXEN, ODDBG_UBRR, ODDBG_USR USR, ODDBG_UDRE UDRE, ODDBG_UDR UDR.
Готовый oddebug.h с внесенными исправлениями можете скачать по ссылке [2].
[Как подключить AVR к компьютеру]
Для согласования уровней TTL RS232 (0..+5V) и стандартного RS232, который использовался на PC (+-12V), нужен специальный адаптер, наподобие [3]. По минимуму нужно соединить с инверсией TTL TXD отлаживаемого микроконтроллера с RXD компьютера. Сложность тут в необходимости обеспечить инверсию, сделать изолирующую развязку от статического электричества и одновременно обеспечить двухполярный сигнал TXD. На рисунке показан вариант такого подключения, обеспечивающий электрическую изоляцию отлаживаемого устройства и компьютера. Оптрон 6H2017C можно заменить на любой другой фототранзисторный. Напряжения +12V и -12V можно снять с коннектора ATX блока питания компьютера.
[Адаптер USB - TTL RS232]
Если в Вашем компьютере нет порта RS232, то нужен переходник USB - TTL RS232 (его еще называют VCP переходник, Virtual COM port). Его можно собрать на чипе FTDI [7], а можно на микроконтроллере AVR. На фото показан пример такого адаптера, сделанного из макетной платы AVR-USB162MU [6], и подключенного к отлаживаемой макетной плате AVR-USB-MEGA16 (на которой, кстати, можно сделать точно такой же адаптер USB - TTL RS232). Вверху - плата AVR-USB-MEGA16, программа которой отлаживается, а внизу - адаптер USB - TTL RS232, собранный на плате AVR-USB162.
Сама плата AVR-USB162 физически уже готовый адаптер, который нужно просто прошить программой USB CDC (см. [2], папка bin) и подключить тремя проводками - GND, TXD, RXD (проводок TXD использовать необязательно, если нужен только отладочный вывод):
При первом подключении к компьютеру адаптера USB - TTL RS232 операционная система Windows запросит драйвер, укажите мастеру установки оборудования папку driver из архива [2].
Подключение адаптера USB - TTL RS232 к макетной плате AVR-USB-MEGA16 (микроконтроллер ATmega32A).
Подключение адаптера USB - TTL RS232 к макетной плате AVR-USB162 (микроконтроллер AT90USB162).
Подключение адаптера USB - TTL RS232 к макетной плате AVR-USB162MU (микроконтроллер AT90USB162MU).
[Переходники USB - TTL RS232 на аппаратных чипах]
Переходник USB TTL COM-port (он подключается с одной стороны к 6-pin коннектору FTDI, а с другой стороны к компьютеру по USB) можно купить готовый. Обычно такой переходник сделан по простейшей схеме на основе чипа FT232 (компания FTDI) или CP210x (компания Silicon Labs). Драйвер для переходника можно скачать с сайта соответствующей компании. Хорошие переходники USB to TTL Serial Cable FTDI (или на чипе CP210x) можно купить на eBay, dealextreme или aliexpress, есть даже предложения с бесплатной доставкой. При покупке выбирайте 5V версию (иногда бывают версии на 3.3V). Самый лучший вариант – когда можно выбрать перемычкой рабочие уровни порта TTL RS-232 (3.3V или 5V). Если уровни сигналов на переходнике USB to TTL и отлаживаемом устройстве не совпадают, то понадобятся последовательно включенные резисторы номиналом около 1…2 кОм.
[Использование класса USB CDC для отладки]
Если Ваше устройство на AVR имеет интерфейс USB (как например макетные платы AVR-USB-MEGA16 или AVR-USB162), то Вы можете запустить на них программное обеспечение класса USB CDC, что дает возможность работать USB-устройству в качестве виртуального COM-порта. В этом случае переходник USB - TTL RS232 вообще не нужен. Пример использования виртуального COM-порта для AVR-USB-MEGA16 см. в [4] и для AVR-USB162 в библиотеке LUFA [5].
[Отладка кода в среде программирования Arduino IDE]
Переходник VCP можно также использовать для отладочного вывода и загрузки кода скетча (в платах Arduino, которые не оборудованы собственным портом VCP), что может помочь в отладке кода программы [2]. В Arduino IDE для этой цели используется оператор println.
int x = 0;
void setup()
{
Serial.begin(9600);
Serial.println("Hello world");
delay(2000); //Задержка, чтобы можно было увидеть вывод.
}
void loop()
{
Serial.println(x);
delay(500);
x=x+1;
if (x>5) {x=0;};
}
[Назначение файлов и папок архива по ссылке [2]]
bin готовые прошивки переходника USB - TTL RS232 (проект LUFA-110528\Projects\USBtoSerial), скомпилированные для плат AVR-USB162, AVR-USB162MU (чип AT90USB162) на частоты кварца 8 и 16 МГц. doc даташиты на микроконтроллеры AT90USB162 (макетные платы AVR-USB162, AVR-USB162MU) и ATmega32A (макетная плата AVR-USB-MEGA16). download скачанные пакеты библиотек LUFA, V-USB, пакет утилит разработки WinAVR. driver inf-файл для переходника USB - TTL RS232, который нужно предоставить мастеру установки оборудования Windows. LUFA-110528 библиотека LUFA LUFA-110528\Projects\USBtoSerial проект USBtoSerial, из которого скомпилированы прошивки переходника USB - TTL RS232. LUFA-110528\Demos\Device\ClassDriver\GenericHID проект, в котором в качестве примера используется отладочный вывод через USART (применен модуль oddebug). См. также пример LUFA-110528\Demos\Device\LowLevel\GenericHID. LUFA-110528\Demos\Device\ClassDriver\GenericHID\oddebug.h исправленный файл oddebug.h, в который добавлена поддержка микроконтроллера AT90USB162.
Как компилировать прошивки переходника USB - TTL RS232 (у Вас должен быть установлен пакет разработки WinAVR):
1. Перейдите в каталог LUFA-110528\Projects\USBtoSerial\. 2. Проверьте в makefile опции MCU, BOARD, F_CPU - они должны соответствовать используемому микроконтроллеру, макетной плате, частоте кварца. 3. Выполните команду make clean. 4. Выполните команду make, получите файл USBtoSerial.hex - это и будет скомпилированный файл прошивки для переходника USB - TTL RS232.
Проект USBtoSerial можно скомпилировать для всех 8-битных микроконтроллеров Atmel AVR USB (микроконтроллеры Atmel, имеющие на борту аппаратную поддержку интерфейса USB).
[Часто задаваемые вопросы, FAQ]
120428. Сделал вывод отладочной информации через преобразователь уровней, заработало. Однако в PuTTY отображаются иероглифы (кракозябры и псевдографика). Скриншот прилагаю.
Наверное, где-то не совпадает кодировка, не подскажете ли - что нужно подправить?
Ответ: причин может быть две. Первая - несовпадение кодировок текста, кодировка отладочного вывода и кодировка отображения в puTTY. Исправить просто - свойства сессии puTTY -> Window ->Translation. Попробуйте кодировку Win1251 (Cyrillic) или другие русскоязычные кодировки. Вторая возможная причина (в том случае, если используется физический UART AVR, что наверное имеет место у Вас) - несовпадение параметров приема / передачи (скорость, число бит, количество стоп-битов, наличие бита четности). Настраивается через свойства сессии puTTY -> Connection -> Serial. Параметры должны соответствовать настройкам UART AVR.
[Ссылки]
1. V-USB download site:obdev.at - библиотека V-USB, ссылки на загрузку. 2. 120214USART-debug.zip - примеры проектов с использованием oddebug (в библиотеке vusb-20121206), исходный код для адаптера USBtoSerial и готовые прошивки (скомпилированные для плат AVR-USB162, AVR-USB162MU, AVR-USB32U4, userial, USBKEY) для виртуального COM-порта USB CDC (в библиотеке LUFA-130901). 3. Сопряжение микроконтроллера с компьютером без MAX232. 4. USB консоль для управления радиолюбительскими приборами. 5. LUFA - бесплатная библиотека USB для микроконтроллеров Atmel AVR. 6. AVR-USB162MU: VCP переходник (TTL virtual COM port). 7. Плата FT232R-Breakout. |