Компиляция и загрузка программы в AVR-USB162

После вынужденной паузы в проекте Catboard из-за отстутствия программатора, и времени на постоянные поездки в FabLab, нашёл в продаже готовую плату, идеально подходящую на роль клавиатурного контроллера, это макетная плата AVR-USB162, стоимостью 500 рублей. Она уже полностью собрана на заводе, проверена на работоспособность (по заявлению продавца), и имеет аппаратную реализацию USB2.0. Порты микроконтроллера выведены на удобные площадки, куда будет легко припаять провода от клавиш. Так же имеется дополнительная макетная площадка, на которой можно разместить дополнительные детали при необходимости, или можно просто отрезать её, уменьшив габариты платы.

AVR-USB162

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

  • нажимаем и удерживаем кнопку Reset;
  • нажимаем и удерживаем кнопку HWB;
  • отпускаем кнопку Reset;
  • делаем паузу порядка 1-2 секунд (всё ещё удерживая кнопку HWB);
  • отпускаем кнопку HWB.

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

Установка программ

Загрузчик FLIP, написанный на Java, в линуксе не видит макетную плату, возможно требуется дополнительная настройка, не радует то, что требуется ручная настройка даже для запуска, в виндовсе эта программа однако работает, хоть у меня и получилось прошить программу не сразу, а вот линуксовая программа dfu-programmer заработала сразу и без проблем. Поэтому будем использовать имеющиеся в Ubuntu Linux консольные инструменты для работы с этим микроконтроллером, ставим все программы только из репозитория.

Инсталлируем библиотечные файлы, без которых не получится ничего толкового скомпилировать, сам компилятор, и загрузчик.

$ sudo apt-get install avr-libc gcc-avr dfu-programmer

Компиляция программ на Си

Собираем исходник, пока так, потом напишу Makefile, когда разберусь с ним.

$ avr-gcc -g -Os -mmcu=at90usb162 main.c -o main.elf
$ avr-objcopy -j .text -j .data -O ihex main.elf main.hex

Работа с внутрисхемным программатором

Очищаем внутреннюю память, заливаем программу, и стартуем. Также стартовать можно кнопкой Reset.

$ sudo dfu-programmer at90usb162 erase
$ sudo dfu-programmer at90usb162 flash main.hex
$ sudo dfu-programmer at90usb162 start

При нажатии на кнопку SW2 светодиод VD1 начинает мигать, при отпускании кнопки - перестаёт.


Информация о USB

Просто проверяем видна ли наша плата в линуксе:

$ lsusb | grep Atmel
Bus 003 Device 015: ID 03eb:2ffa Atmel Corp. 

$ sudo lsusb -vs3:15
Bus 003 Device 015: ID 03eb:2ffa Atmel Corp. 
Device Descriptor:
bLength                18
bDescriptorType         1
bcdUSB               2.00
bDeviceClass          255 Vendor Specific Class
bDeviceSubClass         1 
bDeviceProtocol         0 
bMaxPacketSize0        32
idVendor           0x03eb Atmel Corp.
idProduct          0x2ffa 
bcdDevice            0.00
iManufacturer           1 ATMEL
iProduct                2 AT90USB162 DFU
iSerial                 3 1.0.5
bNumConfigurations      1
Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           18
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
    (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
    bLength                 9
    bDescriptorType         4
    bInterfaceNumber        0
    bAlternateSetting       0
    bNumEndpoints           0
    bInterfaceClass         0 (Defined at Interface level)
    bInterfaceSubClass      0 
    bInterfaceProtocol      0 
    iInterface              0 
Device Status:     0x0000
(Bus Powered)

Тестируемая программа

Немного измененная тестовая программа опроса нажатия кнопки и мигания светодиодом. Код писался впопыхах на основе примеров, просто требовалось по-быстрому отработать технологию компиляции программ и заливки их в микроконтроллер.

main.c:

#include "avr/io.h"

void PORT_Init()
{
    PORTB = 0b00000000;
    DDRB = 0b00000000;

    PORTC = 0b00000000;
    DDRC = 0b00000000;

    PORTD = 0b00000000;
    DDRD = 0b00010000; //set Led as output
}
int i;
int main(void)
{
    PORT_Init();

    asm("WDR"); //Watchdog Timer Reset
    MCUSR= ~(1<<WDRF);
    WDTCSR = (1<<WDCE) | (1<<WDE);
    WDTCSR = 0x00;
    WDTCKD = 0x00;

    while (1)
    {
        if (!(PIND & 0b10000000)) {
            for (i = 15000; i; i--) { // пустой цикл оптимизируется компилятором и не делает паузы
                PORTD = PORTD | 0b00010000;
            }
            for (i = 15000; i; i--) {
                PORTD = PORTD & 0b11101111;
            }
        } else {
            PORTD = PORTD & 0b11101111;
        }
    }
    return 0;
}

П.С.: прошил тестовую программу клавиатуры из примеров LUFA, и вот первое слово, напечатанное единственной кнопкой (пока) на плате контроллера: AAAAAAA, и на русской раскладке: ФФФФФФФ (шифт сам набирает). Чтобы пример скомпилировался и заработал, необходимо убрать упоминания джойстика из его кода, и правильно настроить makefile, подробные рекомендации есть в блоге Kevin-а в статье "Minimus usb and LUFA", разве что нужно только указать другую плату, в моём случае это: BOARD = MICROSIN162 (ага, в библиотеке LUFA присутствует код Microsin-а, за что ему большой респект и уважуха).

01 декабря 2012