Компиляция и загрузка программы в AVR-USB162
После вынужденной паузы в проекте Catboard из-за отстутствия программатора, и времени на постоянные поездки в FabLab, нашёл в продаже готовую плату, идеально подходящую на роль клавиатурного контроллера, это макетная плата AVR-USB162, стоимостью 500 рублей. Она уже полностью собрана на заводе, проверена на работоспособность (по заявлению продавца), и имеет аппаратную реализацию USB2.0. Порты микроконтроллера выведены на удобные площадки, куда будет легко припаять провода от клавиш. Так же имеется дополнительная макетная площадка, на которой можно разместить дополнительные детали при необходимости, или можно просто отрезать её, уменьшив габариты платы.
В микроконтроллере уже присутствует загрузчик, с помощью которого будем заливать программы. Загрузчик активируется автоматически при очищенной памяти, либо его нужно активировать вручную по следующему алгоритму:
- нажимаем и удерживаем кнопку
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-а, за что ему большой респект и уважуха).