Программирование AVR: работа с USB AVR276: USB Software Library for AT90USBxxx Microcontrollers Tue, March 19 2024  

Поделиться

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

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

AVR276: USB Software Library for AT90USBxxx Microcontrollers Печать
Добавил(а) microsin   

В этой статье опубликован разбор документа "AVR276: USB Software Library for AT90USBxxx Microcontrollers" (doc7675.pdf с сайта Atmel). В документе есть мелкие ошибки (например, в количестве и названиях полей в дескрипторах), которые я постарался здесь исправить. Библиотека предназначена для облегчения разработки firmware USB-устройства на основе чипов AT90USBxxx (может применяться макетная плата Atmel STK526 или макетная плата AVR-USB162 [1]. и программного обеспечения компьютера (ПО хоста), работающего с этим устройством.

[Библиотека AT90USBxxx]

Может быть сконфигурирована для работы в 3 режимах:

- USB device - подчиненное устройство, работающее по командам ПО хоста
- USB reduced host - чип AT90USBxxx работает как хост, но может поддерживать только одно устройство
- USB dual role device - чип работает и как хост, и как подчиненное устройство. Какой режим активен в настоящий момент, зависит от уровня на сигнале USB ID (одна из пяти ног в разъеме miniUSB).

При замыкании на землю ножки ID (подсоединение к MiniA вилке) AT90USBxxx входит в режим USB reduced host mode. Если ножка ID не подсоединена (подсоединение к MiniB вилке), то AT90USBxxx работает как подчиненное устройство USB device.

[Дескрипторы USB]

Во время процесса энумерации хост запрашивает из устройства некоторые значения дескриптора (descriptor), чтобы идентифицировать его и загрузить подходящие драйвера. Каждое устройство USB должно иметь хотя бы минимальный набор дескрипторов, указанный на рисунке:

Рис. 3-3. USB Descriptors
AT90USBxxxLib01.PNG

Наиболее сложная часть приложения USB - определение, какие должны быть дескрипторы. Каждое устройство USB передает свои требования к хосту в особом процессе, называемом энумерацией (enumeration). Библиотека AT90USBxxx software library полностью поддерживает процесс энумерации для режимов USB device и USB reduced host. Во время энумерации дескрипторы устройства (device descriptors) передаются хосту, который назначает уникальный адрес устройству.

[Device Descriptor]

Устройство USB может иметь только один дескриптор устройства (DD), который описывает устройство целиком. Он передает информацию о версии USB, максимальный размер пакета для конечной точки (endpoint) 0, vendor ID, product ID, версию устройства (product version), количество возможных конфигураций для устройства и т. д. В таблице отображен формат DD:

Таблица 3-1. Device descriptor

 Поле  Описание
 bLength  Размер дескриптора в байтах
 bDescriptorType  Тип дескриптора. Здесь стоит величина,  указывающая,
что это дескриптор устройства.
 bcdUSB  Версия USB
 bDeviceClass  Код класса (если 0, то класс указывается для каждого
интерфейса, если 0xFF, то указывается для вендора)
 bDeviceSubClass  Код подкласса (назначается USB org)
 bDeviceProtocol  Код протокола (назначается USB org)
 bMaxPacketSize  Максимальный размер пакета в байтах для конечной
точки 0. Равен 8 для Low Speed и 16, 32, 64 для Full Speed
 idVendor  VID, идентификатор вендора (назначается USB org)
 idProduct  PID, идентификатор продукта (назначается производителем)
 bcdDevice  Версия устройства, обычно версия firmware
(назначается производителем)
 iManufacturer  Индекс - указатель на строковый массив, описывающий
производителя (manufacturer descriptor)
 iProduct  Индекс - указатель на строковый массив, описывающий
продукт (product descriptor)
 iSerialNumber  Индекс - указатель на строковый массив, описывающий
серийный номер (serial number descriptor)
 bNumConfiguration  Количество конфигураций устройства

Пример декларации DD можно найти в файле STK526-series2-hidio-2_0_1-doc\demo\STK526-series2-hidio\usb_descriptors.h.

[Configuration Descriptor]

Устройство USB может иметь несколько дескрипторов конфигурации (CD), но обычно имеется только один CD. Этот дескриптор задает режим питания (power-supply mode) - отдельное питание или питание от шины USB, максимальная потребляемая мощность, интерфейсы, принадлежащие устройству, общий размер всех дескрипторов данных (data descriptors) и т. д. Например, устройство может иметь две конфигурации - при питании от шины USB и при отдельном внешнем питании. Можно представить себе также конфигурации с разными режимами передачи.

Таблица 3-2. Configuration descriptor

 Поле  Описание
 bLength Размер дескриптора в байтах.
 bDescriptor Тут указывается, что это - configuration descriptor.
 wTotalLength Общая длина дескрипторов.
 bNuminterfaces Количество интерфейсов в конфигурации.
 bConfigurationValue Величина для запроса SetConfiguration.
 iConfiguration Индекс строкового дескриптора.
 bmAttributes Устройство питается от USB или отдельно, может ли
просыпаться (remote wake up).
 bMaxpower Максимальная потребляемая мощность - ток в единицах
2 мА.

Пример значений полей CD также можно увидеть в файле STK526-series2-hidio-2_0_1-doc\demo\STK526-series2-hidio\usb_descriptors.h.

[Interface Descriptor]

Одно устройство может иметь несколько интерфейсов. Общая информация, выдаваемая дескриптором Interface Descriptor (IntD) - количество конечных точек для интерфейса и USB class и subclass

Таблица 3-3. Interface descriptor

 Поле  Описание
 bLength  Размер дескриптора в байтах
 bDescriptorType  Тут указывается, что это - interface descriptor
 bInterfaceNumber  Номер интерфейса
 bAlternateSetting  Используется для выбора заменяемого интерфейса
 bNumEndpoints  Количество конечных точек (не считая endpoint 0)
 bInterfaceClass  Код класса (назначается USB org)
 bInterfaceSubClass  Код подкласса (назначается USB org)
0 - нет подкласса
1 - Boot interface subclass
 bInterfaceProtocol  Код протокола (назначается USB org)
 iInterface  Индекс - указатель на строковый массив, описывающий
используемый интерфейс

Пример значений полей IntD также можно увидеть в файле STK526-series2-hidio-2_0_1-doc\demo\STK526-series2-hidio\usb_descriptors.h.

[Endpoint Descriptor]

(ED). Описатель, предоставляющий параметры для конечной точки - направление передачи (IN или OUT), поддерживаемый режим передачи (Interrupt, Bulk, Isochronous), размер конечной точки, интервал передачи данных в случае interrupt transfer mode и т. д.

Таблица 3-4. Endpoint descriptor

 Поле  Описание
 bLength Размер дескриптора в байтах
 bDescriptorType Тут указывается, что это - endpoint descriptor
 bEndpointAddress Адрес конечной точки:
биты[0..3] - номер конечной точки
биты[4..6] - зарезервированы
бит 7 - направление передачи: 0 = OUT, 1 = IN
 bmAttributes биты[0..1] тип передачи:
00=Control,
01=Isochronous,
10=Bulk,
11=Interrupt
биты [2..7] зарезервированы, исключая Isochronous transfer.
Для Low Speed разрешены только режимы control и interrupt.
 wMaxPacketSize Максимальный размер данных, поддерживаемый конечной точкой
(сколько байт можно передать за один раз в пакете).
 bInterval Интервал времени для запроса передачи данных конечной точкой.
Указывается в количестве фреймов (длительность фрейма равна 1 мс).
Для передач bulk и control это поле игнорируется.
Установите это поле в величину
1..16 (мс) ;для  isochronous передач,
1..255 (мс) для interrupt transfer Full Speed и
10..255 (мс) для interrupt transfer Low Speed

Пример значений полей ED также можно увидеть в файле STK526-series2-hidio-2_0_1-doc\demo\STK526-series2-hidio\usb_descriptors.h.

Библиотека поддерживает следующие возможности:

1. Доступны скорости Low Speed (1.5Mbit/s) и Full Speed (12Mbit/s)
2. Типы передач Control, Bulk, Isochronous и Interrupt
3. До 6 конечных точек/каналов передачи данных.
4. Одиночная или двойная буферизация.
5. В режиме устройства USB (Device mode) - стандартные классы USB или классы пользователя (USB device classes). В режиме ограниченного хоста (мне этот режим пока не интересен, поэтому в статье он почти не рассмотрен) - автоконфигурация потоков хоста с дескрипторами устройства и поддержка композитных устройств.

Библиотека AT90USBxxx USB software library предназначена для облегчения написания разработчиками firmware для USB-устройств. В частности, всю заботу о процедурах энумерации (для тех, кто в танке - энумерацией называют процесс определения параметров USB устройства хостом в момент подключения USB устройства к хосту. При этом хост пытается подобрать нужный режим обмена с устройством, выбрать драйвер для устройства, а если драйвера нет - предлагает его установить) берет на себя библиотека, разработчику нужно только сконфигурировать параметры устройства (рассмотрено далее), определить каналы для передачи данных, а иногда и написать/поправить обработчики событий (прерываний). Есть также примеры ПО хоста (см. статью [2]).

[Архитектура firmware]

Архитектура firmware (см. рисунок 4-1. AT90USBxxx USB Firmware Architecture for dual role application) спроектирована так, чтобы разработчик как можно меньше соприкасался с железом (регистрами чипа AT90USBXXX) - слой drivers layer никак не должен модифицироваться разработчиком.

Рисунок 4-1. AT90USBxxx USB Firmware Architecture for dual role application

AT90USBxxxLib02

Firmware может работать либо как USB устройство, либо как USB хост (на картинке часть, относящаяся к хосту, показана розовеньким; нас это не интересует). Режим переключается (если двойная роль разрешена) с помощью специального контакта разъема USB (в пятиконтактной версии разъема) - сигнала USB ID. Такая "двойная роль" основывается на выполнении 3-х задач:

- usb_task (usb_task.c), задача выполнения процесса энумерации USB низкого уровня (либо в режиме устройства, либо в режиме хоста). После выполнения этой задачи обновляются различные флаги статуса, которые могут быть проверены на более высоком уровне программы, и USB-соединение становится полностью работоспособным.
- device template task (device_template_task.c) выполняет высокоуровневые операции приложения в режиме USB-устройства. Эта задача содержит запрограммированные пользователем действия, выполняемые однократно в тот момент, когда устройство USB проходит энумерацию.
- host template task (host_template_task.c) выполняет высокоуровневую операцию приложения хоста в тот момент, когда к нему подсоединено устройство и оно проходит энумерацию. Нас это не интересует.

[Описание примера firmware]

Пример приложения firmware показывает, как USB software library может работать в двух режимах (device или host). Примеры ищите на сайте Atmel:

- Пример, относящийся к этому документу (doc7675.pdf), есть в апноуте Atmel "AVR USB Series2 software library template".
- Пример, который мне показался намного полезнее (он работает только как некомпозитное USB device, и для него есть пример ПО хоста), USB HID Generic I/O for STK526. Пример ПО хоста для этого firmware есть в AVR USB Software Packages, а документация к нему находится в файле doc7645.pdf. См. также статью [2].
- Страничка со всеми ссылками на примеры для чипов AT90USB82 и AT90USB162 находится в пакете AVR USB Series2 Software Packages.

Режим устройства USB имеет 2 интерфейса:

- первый интерфейс (first interface) bulk IN/OUT interface, работающий как "обратная петля" (loop back data) - все данные, принятые от хоста через конечную точку OUT endpoint отправляются хосту обратно через конечную точку IN endpoint.
- второй интерфейс (second interface) передает данные хосту через interrupt IN endpoint.
Режим хоста я здесь не разбираю.

Рисунок 4-2. Обзор примера firmware

AT90USBxxxLib03.PNG

Замечание. Дескрипторы устройства B device, используемые в этом примере firmware, не могут быть напрямую использованы для энумерации стандартной подсистемой PC хоста (для ПО хоста, работающего на компьютере). Ищите на сайте Atmel "реальные" примеры приложений для устройств (HID mouse, HID keyboard, MassStorage, CDC ... ).

[Исходные файлы кода и их назначение]

lib_mcu\usb\usb_drv.c 
lib_mcu\usb\usb_drv.h
   низкоуровневые драйверы интерфейса USB (registers abstraction layer)
          
demo\template\conf\config.h
   глобальная конфигурация для firmware

demo\template\conf\conf_usb.h
   конфигурация для USB software library

demo\template\conf\conf_scheduler.h
   конфигурация шедулера (декларация задач, tasks declaration)

demo\template\main.c
   основной код (запускающий шедулер)

demo\template\usb_specific_request.c
demo\template\usb_specific_request.h
   User или class specific device enumeration requests (без standard enumeration requests)

demo\template\device_template_task.c
demo\template\device_template_task.h
   Приложение пользователя высокого уровня для режима USB device (sample device application)

demo\template\host_template_task.c
demo\template\host_template_task.h
   Приложение пользователя высокого уровня для режима USB host mode (sample host application)

demo\template\usb_descriptors.c
demo\template\usb_descriptors.h
   Структуры дескрипторов устройства (используются для процесса энумерации устройства)

modules\usb\device_chap9\usb_device_task.c
modules\usb\device_chap9\usb_device_task.h
   обслуживание устройства USB согласно документу USB org, часть 9 (соединение, разъединение, переход в режим приостановки (suspend), возобновления работы (resume) и вызовы для процесса энумерации)

modules\usb\device_chap9\usb_standard_request.c
modules\usb\device_chap9\usb_standard_request.h
   Процесс энумерации устройства USB (standard requests)

modules\usb\host_chap9\usb_host_task.c
modules\usb\host_chap9\usb_host_task.h
   обслуживание хоста USB согласно документу USB org, часть 9 (соединение, разъединение, переход в режим приостановки (suspend), возобновления работы (resume) и высокоуровневый процесс энумерации)

modules\usb\host_chap9\usb_host_enum.c
modules\usb\host_chap9\usb_host_enum.h

  низкоуровневые функции энумерации (проверка VID/PID, конфигурирование потока обмена хоста (host pipe) в соответствии с дескрипторами устройства USB)

modules\usb\host_chap9\usb_task.c
modules\usb\host_chap9\usb_task.h
   точка входа для обслуживания задач USB (USB task management)

lib_board\stk_525\stk_525.c
lib_board\stk_525\stk_525.c
lib_board\usb_key\usb_key.c
lib_board\usb_key\usb_key.h
   файлы, относящиеся к аппаратуре (макетной плате STK525)

[Конфигурирование USB software library]

Пример firmware сконфигурирован для поддержки двух режимов - reduced USB host и USB device. В зависимости от выбранного режима в качестве задачи USB (USB task) вызывается либо usb_host_task, либо usb_device_task для обработки запросов согласно стандарту USB org chapter 9. При этом соответствующие задачи template_device_task либо template_host_task могут быть удалены из scheduled tasks.
1. Глобальная конфигурация - все общие параметры приложения firmware задаются в файле config.h (тактовая частота чипа XTAL, его тип и т. п.). На самом деле тут задается только один параметр - тактовая частота в килогерцах FOSC. Библиотека может работать только с двумя значениями FOSC: 8000 (частота кварца 8 МГц) и 16000 (частота кварца 16 МГц). По умолчанию задано FOSC 8000. Параметры, относящиеся к модулям, задаются в соответствующих файлах.
2. Scheduler configuration (конфигурация планировщика) - conf_scheduler.h. В приложении примера firmware предоставлены простые задачи для шедулера, которые позволяют пользователю создать и добавить свои задачи без модификации общей архитектуры и организации firmware. Планировщик запускает все предопределенные задачи в указанном порядке без приоритета. Задача выполняется, пока не будет завершена, и потом шедулер запускает следующую задачу. Все задачи планировщика указаны в файле conf_scheduler.h, где пользователь может объявить собственные задачи.
Например, для firmware с двойной ролью (USB host и USB device) используются следующие параметры конфигурации:

#define Scheduler_task_1_init usb_task_init
#define Scheduler_task_1 usb_task
#define Scheduler_task_2_init device_template_task_init
#define Scheduler_task_2 device_template_task
#define Scheduler_task_4_init host_template_task_init
#define Scheduler_task_4 host_template_task

Функции scheduler_task_X_init выполняются один раз при запуске планировщика, тогда как функции Scheduler_task_X вызываются снова и снова в бесконечном цикле.

3. Конфигурация USB library - файл conf_usb.h. Этот файл содержит установки для обоих режимов USB host и USB device. Файл разбит на 3 секции - глобальные параметры, параметры device и параметры host. В глобальной секции можно выбрать либо режим USB host, либо USB device, либо и то, и другое, а также включение внутреннего регулятора сигналов USB (internal USB pads regulator), который должен быть включен или нет для firmware (в зависимости от используемого диапазона напряжения питания).
4. Конфигурация устройства (device configuration) состоит из нескольких подразделов - конфигурирование библиотеки (configuring the USB library) и дескрипторов. USB library поддерживает USB chapter 9 для B-устройства:
- соединение/рассоединение (мониторинг VBUS)
- приостановка (Suspend)
- возобновление (Resume)
- запросы энумерации (Enumeration requests)
Асинхронные события USB (connection, suspend, resume, reset) обслуживаются напрямую внутри подпрограммы прерывания USB (USB interrupt subroutine), размещенной в файле usb_task.c. Код функций пользователя может быть вызван во время событий прерывания благодаря действиям, заданным пользователем в файле conf_usb.h.

Запросы энумерации от хоста обрабатываются в режиме опроса файлами usb_device_task.c и usb_standard_request.c. Задача usb_task принадлежит к задачам планировщика, которая периодически проверяет новые управляющие запросы (control requests) от хоста.

Конфигурация USB library, относящаяся к USB device. Для включения обработки библиотекой режима USB device mode должно быть задано макроопределение USB_DEVICE_FEATURE в значении ENABLED. Секция файла conf_usb.h, относящаяся к устройству USB, содержит определения физических номеров конечных точек (physical endpoints numbers definition), используемых firmware устройства USB и набор специфических действий, которые пользователь может привязать к специальным событиям обмена USB. Для приложения-примера firmware:

#define NB_ENDPOINTS 4 //Общее количество конечных точек (EP) 
                          // в приложении, включая EP0.
#define EP_TEMP_IN 1
#define EP_TEMP_OUT 2
#define EP_TEMP_INT_IN 3
//Укажите здесь действие, ассоциируемое с каждым событием USB.
//Будьте внимательны с расходом времени выполнения этих функций 
// (они должны завершаться как можно скорее).
#define Usb_sof_action() sof_action();
#define Usb_wake_up_action()
#define Usb_resume_action()
#define Usb_suspend_action()
#define Usb_reset_action()
#define Usb_vbus_on_action()
#define Usb_vbus_off_action()
#define Usb_set_configuration_action()

Действия пользователя задают выполняемое поведение firmware на высоком уровне путем вызова нужных функций. Например, пользователь может привязать функцию к каждому событию USB start of frame event (SOF) или событию USB bus reset.

Для поддержки работы композитного USB device (которое работает как сразу несколько периферийных устройств, например как USB HID и USB MSD) необходимо задать несколько интерфейсов (более одного) в дескрипторе конфигурации (configuration descriptor). Каждый интерфейс имеет свой собственный протокол Class/SubClass/Protocol и связанное поведение приложения на высоком уровне (associated high level application behavior). В примере задано композитное устройство со следующими интерфейсами:

- первый интерфейс имеет две конечные точки типа bulk IN/bulk OUT
- второй интерфейс имеет одну конечную точку типа interrupt IN

Конфигурация USB library - дескрипторы устройства

Дескрипторы устройства (device descriptors) используются в процессе энумерации, и содержатся в файлах usb_descriptors.c и usb_descriptors.h (декларация структуры). Здесь пользователь должен объявить все параметры энумерации для конфигурации своего устройства USB.

Тип конфигурации дескриптора задан в конце файла usb_descriptors.h:

// Шаблон конфигурации дескриптора (Configuration descriptor template)
// Устройство имеет 2 интерфейса
// - первый имеет 2 bulk endpoints
// - второй имеет 1 interrupt IN endpoint
typedef struct
{
   S_usb_configuration_descriptor cfg_temp;
   S_usb_interface_descriptor ifc_temp;
   S_usb_endpoint_descriptor ep1_temp;
   S_usb_endpoint_descriptor ep2_temp;
   S_usb_interface_descriptor ifc_second_temp;
   S_usb_endpoint_descriptor ep3_temp;
}S_usb_user_configuration_descriptor;

Связанные интерфейсы и параметры конечных точек заданы в начале файла usb_descriptors.h.

// USB Device descriptor
#define USB_SPECIFICATION 0x0200
#define DEVICE_CLASS 0 //! каждая конфигурация имеет свой класс
#define DEVICE_SUB_CLASS 0 //! каждая конфигурация имеет свой подкласс
#define DEVICE_PROTOCOL 0 //! каждая конфигурация имеет свой протокол
#define EP_CONTROL_LENGTH 64
#define VENDOR_ID 0x03EB // Atmel vendor ID = 03EBh
#define PRODUCT_ID 0x0000
#define RELEASE_NUMBER 0x1000
#define MAN_INDEX 0x01
#define PROD_INDEX 0x02
#define SN_INDEX 0x03
#define NB_CONFIGURATION 1
// CONFIGURATION
#define NB_INTERFACE 2 //! Номер интерфейса для этой конфигурации
#define CONF_NB 1 //! Номер этой конфигурации
#define CONF_INDEX 0
#define CONF_ATTRIBUTES USB_CONFIG_SELFPOWERED
#define MAX_POWER 50 // 100 mA (в единицах 2mA)
// USB Interface descriptor gen
#define INTERFACE_NB_TEMP 0 //! Номер этого интерфейса 
#define ALTERNATE_TEMP 0 //! Альтернативная установка nb для этого интерфейса
#define NB_ENDPOINT_TEMP 2 //! Количество EP, которые имеет интерфейс
#define INTERFACE_CLASS_TEMP 0x00 //! Класс
#define INTERFACE_SUB_CLASS_TEMP 0x00 //! Подкласс
#define INTERFACE_PROTOCOL_TEMP 0x00 //! Протокол
#define INTERFACE_INDEX_TEMP 0
// USB Endpoint 1 descriptor FS
#define ENDPOINT_NB_TEMP1 (EP_TEMP_IN | 0x80)
#define EP_ATTRIBUTES_TEMP1 0x02 // BULK = 0x02, INTERRUPT = 0x03
#define EP_IN_LENGTH_TEMP1 64
#define EP_SIZE_TEMP1 EP_IN_LENGTH_TEMP1
#define EP_INTERVAL_TEMP1 0x00 //Интервал опроса хостом (Interrupt 
                                   // polling interval from host).
// USB Endpoint 2 descriptor FS
#define ENDPOINT_NB_TEMP2 EP_TEMP_OUT
#define EP_ATTRIBUTES_TEMP2 0x02 // BULK = 0x02, INTERRUPT = 0x03
#define EP_IN_LENGTH_TEMP2 64
#define EP_SIZE_TEMP2 EP_IN_LENGTH_TEMP2
#define EP_INTERVAL_TEMP2 0x00 //Интервал опроса хостом (Interrupt
                                   // polling interval from host)
// USB Second Interface descriptor gen
#define INTERFACE_NB_SECOND_TEMP 1 //! Номер этого интерфейса 
#define ALTERNATE_SECOND_TEMP 0 //! Альтернативная установка nb для него
#define NB_ENDPOINT_SECOND_TEMP 1 //! Количество EP, которые имеет интерфейс
#define INTERFACE_CLASS_SECOND_TEMP 0x00 //! Класс
#define INTERFACE_SUB_CLASS_SECOND_TEMP 0x55 //! Подкласс
#define INTERFACE_PROTOCOL_SECOND_TEMP 0xAA //! Протокол
#define INTERFACE_INDEX_SECOND_TEMP 0
// USB Endpoint 2 descriptor FS
#define ENDPOINT_NB_TEMP3 (EP_TEMP_INT_IN | 0x80)
#define EP_ATTRIBUTES_TEMP3 0x03 // BULK = 0x02, INTERRUPT = 0x03
#define EP_IN_LENGTH_TEMP3 64
#define EP_SIZE_TEMP3 EP_IN_LENGTH_TEMP2
#define EP_INTERVAL_TEMP3 20 //Интервал опроса хостом (Interrupt 
                                   // polling interval from host).

Все эти параметры энумерации используются для заполнения полей дескриптора, заданном в файле usb_descriptors.c. Когда контроллер хоста выполняет процесс энумерации, он запрашивает и декодирует параметры благодаря функциям энумерации standard_request.c и предварительно заданным дескрипторам, данные которых отправляются контроллеру хоста.

5. Reduced host configuration
    Это пропускаем, пока не интересно.
   
6. Использование USB software library внутри приложения firmware на высоком уровне

Device application
Приложение пользователя "знает" о том, что устройство USB было должным образом опрошено благодаря функцииIs_device_enumerated(), которая возвращает TRUE, когда запрос SET_CONFIGURATION был принят от хоста.

void device_template_task(void)
{
    //.. Первая проверка состояния энумерации устройства
    if (Is_device_enumerated())
    {
        //.. Тут запускается код приложения USB DEVICE
    }
}

Файл device_template_task.c, включенный в приложение-пример firmware показывает, как использовать совместно конечные точки bulk IN/OUT и interrupt, связанные с интерфейсами, объявленными в configuration descriptors.

Host application
    Пропускаем...
   
7. FAQ
7.1 Device mode
7.1.1 Как поменять VID и PID?

VID (Vendor ID) и PID (Product ID) позволяют идентифицировать устройство программе ПО хоста. Каждый производитель должен иметь собственный VID, который будет одинаков для всех его продуктов (он назначается организацией USB org по специальному запросу). Каждый отдельный продукт должен иметь свой собственный PID (он назначается производителем). Величины VID и PID заданы в usb_descriptor.h. Чтобы их поменять, отредактируйте следующие параметры:

// USB Device descriptor (дескриптор устройства USB)
#define VENDOR_ID 0x03EB // Atmel vendor ID = 03EBh
#define PRODUCT_ID 0x201C

7.1.2 Как поменять значение строковых описателей (string descriptors value)?

Значения строковых описателей заданы в usb_descriptor.h. Например, чтобы поменять значение имени продукта, поменяйте следующие параметры.

//Длина строки:
#define USB_PN_LENGTH 18

//Сама строка:
#define USB_PRODUCT_NAME 
{
   Usb_unicode('A'),
   Usb_unicode('V'),
   Usb_unicode('R'),
   Usb_unicode(' '),
   Usb_unicode('U'),
   Usb_unicode('S'),
   Usb_unicode('B'),
   Usb_unicode(' '),
   Usb_unicode('M'),
   Usb_unicode('O'),
   Usb_unicode('U'),
   Usb_unicode('S'),
   Usb_unicode('E'),
   Usb_unicode(' '),
   Usb_unicode('D'),
   Usb_unicode('E'),
   Usb_unicode('M'),
   Usb_unicode('O')
}

7.1.3 Как можно сконфигурировать режим питания устройства - self-powered или bus-powered?

Это параметр задается в файле usb_descriptor.h. Ниже дано определение каждого режима.

// USB Configuration descriptor, bus-power mode
// (дескриптор конфигурации, режим питания от шины USB)
#define CONF_ATTRIBUTES USB_CONFIG_BUSPOWERED
 
// USB Configuration descriptor, self-power mode
// (дескриптор конфигурации, питание от дополнительного собственного источника)
#define CONF_ATTRIBUTES USB_CONFIG_SELFPOWERED

7.1.4 Как добавить новый дескриптор?

Процесс по шагам:

1. Задайте значение параметров дескриптора и его структуру в файле usb_descriptors.h.
Например, HID descriptor и его структура должна быть задана в файле usb_descriptors.h, как показано ниже:

/* ____HID descriptor___________________________________________________*/
#define HID 0x21
#define REPORT 0x22
#define SET_REPORT 0x02
#define HID_DESCRIPTOR 0x21
#define HID_BDC 0x1001
#define HID_COUNTRY_CODE 0x00
#define HID_CLASS_DESC_NB 0x01
#define HID_DESCRIPTOR_TYPE 0x22
/*_____ USB HID DESCRIPTOR______________________________________________*/
typedef struct 
{
   U8 bLength;             /* Размер этого дескриптора в байтах */
   U8 bDescriptorType;     /* HID descriptor type */
   U16 bscHID;             /* закодированный двоично Decimal Spec. release */
   U8 bCountryCode;        /* Страна для использования устройства */
   U8 bNumDescriptors;     /* Количество следующих далее дескрипторов HID class */
   U8 bRDescriptorType;    /* Report descriptor type */
   U16 wDescriptorLength;  /* Общая длина Report descriptor */
}S_usb_hid_descriptor;

2. Добавьте новый дескриптор в структуру s_usb_user_configuration_descriptor, в файле usb_descriptors.h:

typedef struct
{
   S_usb_configuration_descriptor cfg_mouse;
   S_usb_interface_descriptor ifc_mouse;
   S_usb_hid_descriptor hid_mouse;
   S_usb_endpoint_descriptor ep1_mouse;
}S_usb_user_configuration_descriptor;

3. В файле usb_descriptors.c добавьте размер нового дескриптора к параметру wTotalLength дескриптора конфигурации configuration descriptor и добавьте значение дескриптора (см. пример ниже):

code S_usb_user_configuration_descriptor usb_conf_desc =
{
   {
      sizeof(S_usb_configuration_descriptor),
      CONFIGURATION_DESCRIPTOR,
      Usb_write_word_enum_struc(sizeof(S_usb_configuration_descriptor)
          +sizeof(S_usb_interface_descriptor) 
          +sizeof(S_usb_hid_descriptor) 
          +sizeof(S_usb_endpoint_descriptor)),
      NB_INTERFACE,
      CONF_NB,
      CONF_INDEX,
      CONF_ATTRIBUTES,
      MAX_POWER
   },
   {
      sizeof(S_usb_interface_descriptor),
      INTERFACE_DESCRIPTOR,
      INTERFACE_NB_MOUSE,
      ALTERNATE_MOUSE,
      NB_ENDPOINT_MOUSE,
      INTERFACE_CLASS_MOUSE,
      INTERFACE_SUB_CLASS_MOUSE,
      INTERFACE_PROTOCOL_MOUSE,
      INTERFACE_INDEX_MOUSE
   },
   {
      sizeof(S_usb_hid_descriptor),
      HID_DESCRIPTOR,
      HID_BDC,
      HID_COUNTRY_CODE,
      HID_CLASS_DESC_NB,
      HID_DESCRIPTOR_TYPE,
      Usb_write_word_enum_struc(sizeof(S_usb_hid_report_descriptor_mouse))
   },
   {
      sizeof(S_usb_endpoint_descriptor),
      ENDPOINT_DESCRIPTOR,
      ENDPOINT_NB_1,
      EP_ATTRIBUTES_1,
      Usb_write_word_enum_struc(EP_SIZE_1),
      EP_INTERVAL_1
   }
};

4. Не забудьте добавить все связанные функции для обработки нового дескриптора.

7.1.5 Как добавить новую конечную точку?
Процесс по шагам:
1. Как было рассказано в секции USB descriptors, конечная точка принадлежит интерфейсу. Первое, что надо сделать, чтобы добавить EP - инкрементировать на 1 величину параметра NB_ENDPOINT. Эта величина задана в файле usb_descriptor.h и она принадлежит параметрам interface descriptor.

// USB Interface descriptor (дескриптор интерфейса USB)
#define INTERFACE_NB xx
#define ALTERNATE xx
#define NB_ENDPOINT xx                //Этот параметр = числу endpoints
                                      // интерфейса. Его меняем.
#define INTERFACE_CLASS xx
#define INTERFACE_SUB_CLASS xx
#define INTERFACE_PROTOCOL xx
#define INTERFACE_INDEX xx

2. Следующий шаг - задание величин EP дескриптора. Они заданы в in usb_descriptors.h.

#define ENDPOINT_NB_1 (EP_MOUSE_IN | 0x80)
#define EP_ATTRIBUTES_1 0x03          // BULK = 0x02, INTERRUPT = 0x03
#define EP_IN_LENGTH_1 8
#define EP_SIZE_1 EP_IN_LENGTH_1
#define EP_INTERVAL_1 0x02            // Интервал опроса конечной точки хостом

EP_MOUSE_IN задано в conf_USB.h для указания номера EP, используемого приложением.

3. Добавьте новый endpoint descriptor к configuration descriptor (как описано в предыдущем вопросе FAQ).

4. Добавьте вызов инициализации железа (hardware initialization call) в usb_specific_request.c:

void usb_user_endpoint_init(U8 conf_nb)
{
   usb_configure_endpoint(EP_MOUSE_IN, 
                          TYPE_INTERRUPT, 
                          DIRECTION_IN, 
                          SIZE_8, 
                          ONE_BANK, 
                          NYET_ENABLED);
}

[Ссылки]

1. Макетная плата AVR-USB162.
2. AVR-USB162: где найти рабочие примеры кода firmware и ПО хоста.

 

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


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

Top of Page