Программирование AVR: работа с USB Библиотека LUFA: как добавить поддержку собственной платы с чипом AVR USB Thu, October 10 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Библиотека LUFA: как добавить поддержку собственной платы с чипом AVR USB Печать
Добавил(а) microsin   

Библиотека LUFA предназначена для упрощения проектирования USB-устройств на чипах Atmel семейства AVR USB (AVR с аппаратным интерфейсом USB) различных серий. LUFA поддерживает очень много готовых макетных плат с чипами AVR USB, предлагаемых различными производителями [1, 2]. В этой статье описывается, как переконфигурировать библиотеку LUFA для использования различных макетных плат, и как добавить в библиотеку LUFA поддержку своей платы - на примере версии LUFA101122. Имейте в виду, что проект LUFA постоянно развивается, и в системе переключения поддержки плат могут появиться изменения. Все незнакомые термины (касательно USB), которые встретятся Вам, ищите в хорошей доке USB in the NutShell [4].

[Структура библиотеки LUFA, назначение файлов и папок]

Список поддерживаемых макетных плат в библиотеке LUFA впечатляет [2]. Ничего подобного нет ни в какой другой библиотеке, даже в библиотеках Atmel. В библиотеке имеется также много примеров проектов готовых USB-устройств, которые можно скомпилировать для любого чипа AVR USB.

at90usb162-04IMG_8330.jpg AVR-USB162MU_IMG_1139.JPG
AVR-USB162 AVR-USB162MU 

Все проекты, и исходный код самой библиотеки LUFA конфигурируются через настройку параметров файлов makefile. В каждой корневой папке проекта есть свой файл makefile. Библиотека LUFA имеет продуманную логическую структуру, упрощающую программисту разработку и поддержку проектов USB-устройств, однако для новичка эта структура может показаться излишне сложной и запутанной. Рассмотрим назначение отдельных каталогов библиотеки и находящихся в них файлов. Все, о чем будет написано далее, относится к библиотеке версии LUFA101122.

В корневой папке библиотеки LUFA101122 находится файл readme.txt, общий makefile для компиляции или очистки всех проектов и самой библиотеки, а также папки Bootloaders, Demos, LUFA, Projects.

Bootloaders - эта папка содержит два бутлоадера с открытым исходным кодом: CDC (бутлоадер на основе виртуального COM-порта, который поддерживается утилитами AVRDUDE и Atmel AVRPROG) и DFU (бутлоадер, поддерживающий открытый протокол DFU Flip Atmel, и работающей с утилитой программирования Atmel Flip).

Demos\Device - эта папка содержит демонстрационные примеры классических USB-устройств (клавиатуры, мыши, джойстики, флешки, устройства аудиоввода и аудиовывода, MIDI, виртуальные COM-порты, смешанные устройства, сетевые карты). Каждая реализация устройства находится в отдельной папке, причем почти все устройства реализованы в двух вариантах - с помощью драйвера класса (ClassDriver) и на низком уровне программирования (LowLevel). Для практического применения более просты и удобны в использовании варианты реализации на драйвере класса ClassDriver, а вариант LowLevel предоставляет больше возможностей для опытного разработчика.

Demos\DualRole - здесь расположен (пока только один) пример двухролевого контроллера, который может работать и как устройство USB, и как хост USB.

Demos\Host - здесь расположены примеры кода хостов USB (хосты джойстика, клавиатуры, мыши, MIDI, принтера, виртуального COM-порта, сетевой карты и проч.). Примеры хостов USB также реализованы в двух вариантах - ClassDriver и LowLevel, чтобы предоставить широкий выбор разработчику. Хосты USB разрабатывают на чипах AVR USB довольно редко, поэтому все проекты Demos\Host можно рассматривать как чисто академические примеры кода, которые не несут большого практического значения.

LUFA - это папка, в которой находятся основные файлы библиотеки. Обычно разработчику не нужно сюда заглядывать, поэтому подробно останавливаться на содержимом этой папки не будем. Исключение из этого правила как раз составляет добавление в библиотеку поддержки своей платы AVR USB, и эта процедура будет отдельно рассмотрена далее. Общая документация к библиотеке находится в папке LUFA\ManPages\, и она представлена в файлах txt, в формате DoxyGen [5].

Projects - тут имеется внушительный список проектов, которые выполнили на основе LUFA многие разработчики (программаторы, управление реле, логгер температуры, веб-сервер и другие).

[Как переконфигурировать LUFA на определенную макетную плату AVR USB]

Для того, чтобы переключить проект на использование платы, которая уже есть в списке поддерживаемых плат LUFA [3], нужно поменять значение параметра BOARD в файле makefile проекта (символ # превращает строку в комментарий - в этом примере раньше проект был настроен на плату USBTINYMKII, а теперь переключен на плату MICROSIN162MU, т. е. AVR-USB162). Макроопределение BOARD подключает использование макросов поддержки светодиодов и клавиатуры, относящихся к конкретному типу отладочной платы. Светодиодами в библиотеке LUFA отображаются возникновение различных событий, а кнопки могут использоваться для управления работой программы пользователя.

#BOARD = USBTINYMKII
BOARD = MICROSIN162

Проверьте также другие важные опции makefile, которые могут влиять на работоспособность проекта - это F_CPU (рабочая тактовая частота для программы) и MCU (тип используемого микроконтроллера AVR USB). В данном примере выбран микроконтроллер AT90USB162 (он установлен на макетной плате AVR-USB162).

MCU = at90usb162
F_CPU = 16000000 

Макроопределение MCU влияет на поддержку особенностей аппаратуры используемого микроконтроллера (периферийные устройства, количество и размер конечных точек USB и т. п.). F_CPU влияет на корректное вычисление задержек в программе, на работу таймеров, установку скорости UART.

Файлы makefile (как, впрочем, и все файлы исходного кода LUFA) снабжены качественными комментариями, так что не заблудитесь, и разобраться в назначении различных опций будет легко. Вы можете также скачать библиотеку LUFA101122 с переведенными на русский язык комментариями и документацией [6].

[Как добавить в LUFA поддержку своей платы AVR USB]

Здесь описан процесс по шагам на примере макетной платы AVR-USB162MU, которая аппаратно незначительно отличается от AVR-USB162 (по-другому подключен отладочный светодиод). Итак, процесс по шагам.

1. Откройте в текстовом редакторе файл LUFA101122\LUFA\Common\BoardTypes.h, и добавьте в конец файла макроопределение BOARD_MICROSIN162MU для новой добавляемой платы (выделено жирным шрифтом).

   /** Выбор драйверов платы Microsin AVR-USB162, включающих драйвер кнопки и светодиодов. */
   #define BOARD_MICROSIN162 24
 
   /** Выбор драйверов платы Microsin AVR-USB162MU, включающих драйвер кнопки и светодиодов. */
   #define BOARD_MICROSIN162MU 240

2. Зайдите в каталог LUFA101122\LUFA\Drivers\Board\ (здесь хранятся макросы поддержки кнопок и светодиодов в файлах Buttons.h и LEDs.h, рассортированные по папкам). Сделайте копию папки MICROSIN162 вместе со всем содержимым, и дайте копии новое имя MICROSIN162MU. Как Вы уже наверное догадались, новое имя папки должно совпадать с окончанием макроопределения, которое Вы создали на шаге 1.

3. Отредактируйте файлы файлах Buttons.h и LEDs.h, чтобы макросы в них они действительно управляли нужными Вам кнопками и светодиодами. Вот пример содержимого этих файлов для платы AVR-USB162MU.

[Buttons.h]

#ifndef __BUTTONS_MICROSIN162_H__
#define __BUTTONS_MICROSIN162_H__
 
    /* Включаемые файлы: */
        #include < avr/io.h >
        #include 
 
        #include "../../../Common/Common.h"
 
    /* Разрешение линкования C для компиляторов C++: */
        #if defined(__cplusplus)
            extern "C" {
        #endif
 
    /* Препроцессорные проверки: */
        #if !defined(__INCLUDE_FROM_BUTTONS_H)
            #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
        #endif
 
    /* Интерфейс Public - эти определения можно использовать в конечном приложении: */
        /* Макросы: */
            /** Маска для первой кнопки на макетной плате. */
            #define BUTTONS_BUTTON1 (1 << 7)
 
        /* Встраиваемые (inline) функции: */
        #if !defined(__DOXYGEN__)
            static inline void Buttons_Init(void)
            {
                DDRD  &= ~BUTTONS_BUTTON1;
                PORTD |=  BUTTONS_BUTTON1;
            }
 
            static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
            static inline uint8_t Buttons_GetStatus(void)
            {
                return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
            }
        #endif
 
    /* запрет линкования C для компиляторов C++: */
        #if defined(__cplusplus)
            }
        #endif
 
#endif

[LEDs.h]

#ifndef __LEDS_MICROSIN162MU_H__
#define __LEDS_MICROSIN162MU_H__
 
    /* Включаемые файлы: */
        #include < avr/io.h >
 
        #include "../../../Common/Common.h"
 
    /* Разрешение линкования C для компиляторов C++: */
        #if defined(__cplusplus)
            extern "C" {
        #endif
 
    /* Препроцессорные проверки: */
        #if !defined(__INCLUDE_FROM_LEDS_H)
            #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
        #endif
 
    /* Интерфейс Public - эти определения можно использовать в конечном приложении: */
        /* Макросы: */
            /** Маска для первого светодиода на макетной плате. */
            #define LEDS_LED1 (1 << 6)
 
            /** Маска для всех светодиодов на макетной плате. */
            #define LEDS_ALL_LEDS LEDS_LED1
 
            /** Маска для отсутствия светодиодов на макетной плате. */
            #define LEDS_NO_LEDS 0
 
        /* Встраиваемые (inline) функции: */
        #if !defined(__DOXYGEN__)
            static inline void LEDs_Init(void)
            {
                DDRD  |= LEDS_ALL_LEDS;
                PORTD |= LEDS_ALL_LEDS;
            }
 
            static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
            {
                PORTD &= ~LEDMask;
            }
 
            static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
            {
                PORTD |= LEDMask;
            }
 
            static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
            {
                PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
            }
 
            static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
                                               const uint8_t ActiveMask)
            {
                PORTD = ((PORTD | LEDMask) & ~ActiveMask);
            }
 
            static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
            {
                PORTD ^= LEDMask;
            }
 
            static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
            static inline uint8_t LEDs_GetLEDs(void)
            {
                return (~PORTD & LEDS_ALL_LEDS);
            }
        #endif
 
    /* запрет линкования C для компиляторов C++: */
        #if defined(__cplusplus)
            }
        #endif
 
#endif

[Ссылки]

1. LUFA - бесплатная библиотека USB для микроконтроллеров Atmel AVR.
2. Поддержка устройств и аппаратуры в библиотеке LUFA.
3. Board Types - типы плат, поддерживаемых библиотекой LUFA101122.
4. USB in a NutShell - путеводитель по стандарту USB (начало).
5. Генератор документации Doxygen - быстрый старт.
6. 110626LUFA101122.ZIP - пакет с русифицированной библиотекой LUFA (переведены комментарии в файлах и документация, добавлена поддержка платы AVR-USB162MU).

 

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


Защитный код
Обновить

Top of Page