AVR276
Программная библиотека USB для микроконтроллеров
Свойства:
- скорости передачи данных: Low Speed (1.5Mbit/s) и Full Speed (12Mbit/s);
- типы передач данных: управляющая, изохронная, передача массивов данных и по прерываниям;
- до 6 конечных точек/каналов;
- одинарная или двойная буферизация;
- режим устройства:
- стандартные или специальные классы USB устройств с использованием программной библиотеки USB;
- сокращенный режим хоста:
- автоконфигурация каналов хоста в соответствии с дескрипторами устройства;
- поддержка сложных устройств (с несколькими интерфейсами)
1. Описание
Этот документ описывает программную библиотеку USB для микроконтроллеров AT90USBxxx и иллюстрирует разработку USB устройства или сокращенного хоста с помощью этой библиотеки.
Этот документ написан для разработчиков программного обеспечения для облегчения реализации их приложений (и USB устройства и сокращенного хоста) для AT90USBxxx. Предполагается, что читатель знаком с архитектурой AT90USBxxx. Также для понимания содержания этого документа требуется, как минимум, знание 9 главы спецификации USB 2.0 (www.usb.org)
1.1 Обзор
Программная библиотека AT90USBxxx разработана для того, чтобы скрыть от разработчиков сложность реализации USB (особенно стадии энумерации).
Цель этого документа — описать программное обеспечение USB и дать обзор архитектуры. Основные файлы описаны в таком порядке, который позволяет пользователю очень просто подогнать программное обеспечение под свое собственное приложение.
В программной библиотеке AT90USBxx также приводится пример (демонстрационный шаблон программного обеспечения) приложения двойного назначения (устройство или сокращенный хост) для иллюстрации использования этой библиотеки.
1.2 Ограничения
Пока не интегрирована полная поддержка совместимости с OTG (On the Go) (обработка запросов SRP/HNP).
1.3 Терминология
- VID: USB идентификатор производителя (Vendor Identifier)
- PID: USB идентификатор продукта (Product Identifier)
2. Стиль кода
Для понимания программного обеспечения важно нижеприведенное описание стиля кода:
- определенные константы обозначаются заглавными буквами:
#define FOSC 8000;
- макросы обозначаются первой заглавной буквой, а далее строчными:
#define Is_usb_sof() ((UDINT & MSK_SOFI) ? TRUE: FALSE)
- Приложение пользователя может выполнять свои собственные команды по каждому событию USB благодаря специальным меткам, определенным следующим образом в файле usb_conf.h.
#define Usb_sof_action() sof_action();
Замечание: пользовательские функции должны осуществлять только кратковременные операции!
- Макро-функция Usb_unicode() должна использоваться везде (строковые дескрипторы…), где требуется передача символа в кодировке Unicode по протоколу USB.
3. Шина USB
3.1 Топология USB
Спецификация USB определяет два различных вида точек соединения с USB шиной: хост или устройство.
Рисунок 3-1. Стандартная топология USB
- USB хост:
- существует только один хост в любой USB системе и он является мастером шины USB;
- USB интерфейс по отношению к хосту называется хост контроллером;
- USB устройство:
- USB устройство является slave-устройством на шине USB;
- Благодаря USB хабу (который также является устройством) до 127 устройств сожжет быть подключено к USB шине. Каждое устройство уникально идентифицируется с помощью адреса устройства.
Микроконтроллеры AT90USBxxx могут работать как в режиме USB устройства, так и в режиме USB хоста, причем в этом режиме AT90USBxxx работает как сокращенный хост. У сокращенного хост контроллера один USB порт и он не поддерживает полную древовидную структуру с хабами. Это означает, что сокращенный хост контроллер разрабатывается только для осуществления связи «точка-точка» с одним USB устройством. Сокращенный хост поддерживает только известный список устройств (список VID/PID). Только устройства, содержащиеся в этом списке, поддерживаются хостом. Дополнительно программная библиотека USB поддерживает список со следующими параметрами устройств: CLASS/SUBCLASS/PROTOCOL.
Рисунок 3-2. Топология сокращенного хоста
Программная библиотека AT90USBxxx может быть сконфигурирована для поддержки одного из следующих режимов работы USB:
- USB устройство
- USB сокращенный хост
- USB устройство двойного назначения — этот режим позволяет поддерживать оба вышеопределенных режима.
Режим работы определяется с помощью внешнего вывода USB ID. Если он соединен с землей (соединен с разъемом MiniA), то AT90USBxxx входит в режим сокращенного хоста. Если ID вывод не соединен ни с чем (соединен с разъемом mini B), то AT90USBxxx работает в режиме устройства.
3.2 USB дескрипторы
Во время процесса энумерации хост запрашивает у устройства несколько различных значений дескрипторов для идентификации устройства и загрузки подходящих драйверов. Каждое USB устройство должно иметь по крайней мере те дескрипторы, что приведены на рисунке ниже, чтобы быть «узнанным» хостом:
Рисунок 3-3. Дескрипторы USB
Наиболее сложная часть разработки USB приложения — это определение, какими должны быть дескрипторы устройства. Каждое USB устройство «сообщает» свои требования хосту в течение процесса, называемого энумерацией. Программная библиотека AT90USBxxx обеспечивает полный процесс энумерации и для устройства и для сокращенного хоста.
В течение энумерации дескрипторы устройства отправляются в хост, а хост присваивает устройству уникальный адрес. Дескрипторы подробно описаны в девятой главе спецификации USB 2.0
3.2.1 Дескриптор устройства (Device Descriptor)
У устройства USB может быть только один дескриптор устройства. Этот дескриптор описывает все устройство. Он дает информацию о версии USB, максимальном размере пакета для нулевой конечной точки, идентификаторе производителя, идентификаторе продукта, версии продукта, количестве возможных конфигураций устройства и т.д.
Нижеприведенная таблица иллюстрирует структуру этого дескриптора.
Таблица 3-1. Дескриптор устройства
Поле |
Описание |
bLength |
Размер дескриптора |
bDescriptorType |
Дескриптор устройства |
bcdUSB |
Версия USB |
bDeviceClass |
Код класса ( если 0, то класс будет определен для каждого из интерфейсов, если 0xff, то класс определяется производителем) |
bDeviceSubClass |
Код подкласса (присваивается USB org) |
bDeviceProtocol |
Код протокола (присваивается USB org) |
bMaxPacketSize |
Максимальный размер пакета для 0 конечной точки в байтах. Он должен быть равен 8 (Low Speed) и 16, 32 или 64 (Full Speed). |
idVendor |
Идентификатор производителя (присваивается USB org) |
idProduct |
Идентификатор продукта (присваивается производителем) |
bcdDevice |
Версия устройства (присваивается производителем) |
iManufacturer |
Индекс строкового дескриптора производителя |
iProduct |
Индекс строкового дескриптора продукта |
iSerialNumber |
Индекс строкового дескриптора серийного номера |
bNumConfiguration |
Количество конфигураций |
3.2.2 Дескриптор конфигурации (Configuration Descriptor)
USB устройство модет иметь более одного дескриптора конфигурации, однако, большинство устройств имеют только одну конфигурацию. Этот дескриптор определяет режим питания устройства (с собственным источником питания или с питанием от шины), максимальный ток потребления устройства, интерфейсы, которые поддерживает устройство, общий размер данных дескрипторов и т.д.
Например, у одного устройства может быть 2 конфигурации, одна с питанием от шины и другая с собственным источником питания. Также можно представить себе, что в разных конфигурациях устройство использует различные режимы передачи данных.
Нижеприведенная таблица иллюстрирует структуру этого дескриптора.
Таблица 3-2. Дескриптор конфигурации
Поле |
Описание |
bLength |
Размер дескриптора |
bDescriptor |
Дескриптор конфигурации |
wTotalLength |
Полный размер дескриптора |
bNuminterface |
Количество интерфейсов |
bConfigurationValue |
Количество конфигураций |
bmAttributes |
Собственный источник питания или питание от шины, удаленное пробуждение |
bMaxpower |
В единицах 2мА |
3.2.3 Дескриптор интерфейса (Interface Descriptor)
Одно устройство может иметь несколько дескрипторов интерфейса. Основная информация, содержащаяся в этом дескрипторе, - количество конечных точек, используемых этим интерфейсом и класс и подкласс USB.
Нижеприведенная таблица иллюстрирует структуру этого дескриптора.
Таблица 3-3. Дескриптор интерфейса
Поле |
Описание |
bLength |
Размер дескриптора |
bDescriptorType |
Дескриптор интерфейса |
bInterfaceNumber |
Номер интерфейса |
bAltenativeSetting |
Используется для выбора заменяющего интерфейса |
bNumEndpoint |
Количество конечных точек (за исключением нулевой конечной точки)Number of endpoints (excluding endpoint 0) |
bInterfaceClass |
Код класса (присваивается USB org) |
bInterfaceSubClass |
Код подкласса (присваивается USB org)
0 нет подкласса
1 подкласс загрузочного устройства |
iInterface |
Индекс строкового дескриптора интерфейса |
3.2.4 Дескриптор конечной точки (Endpoint Descriptor)
Этот дескриптор используется для описания таких параметров конечной точки, как:
направление (IN или OUT), поддерживаемый тип передачи (по прерываниям, передача массивов данных, изохронный), размер конечной точки, интервал передачи данных, в случае передачи по прерываниям, и т.д.
Нижеприведенная таблица иллюстрирует структуру этого дескриптора.
Таблица 3-4. Дескриптор Конечной точки
Поле |
Описание |
bLength |
Размер дескриптора |
bDescriptorType |
Дескриптор конечной точки |
bEndpointAdress |
Адрес конечной точки
Биты [0..3] номер конечной точки
Биты[4..6] зарезервированы, установлены в 0
Бит 7: Направление: 0 = OUT, 1 = IN |
bmAttributes |
Биты [0..1] Тип передачи:
00=управляющая,
01=изохронная,
10=передача массивов данных,
11 =по прерываниям
Биты [2..7] зарезервировано для всех типов передач кроме изохронной
В режиме Low Speed разрешены только 2 типа передачи: по прерываниям и управляющая |
wMaxPacketSize |
Максимальный размер данных, поддерживаемый конечной точкой |
bInterval |
Это интервал запроса данных у конечной точки. Значение задается в количестве фреймов (мс).
Игнорируется передачами массивов данных и управляющими передачами
Установите значение между 1 и 16 (мс) для изохронных передач
Установите значение между 1 и 255 (мс) для передач по прерываниям в Full Speed
Установите значение между 10 и 255 (мс) для передач по прерываниям в Low Speed |
4. Архитектура программного обеспечения
Как показано на рисунке 4-1, архитектура программного обеспечения USB разработана так, чтобы избежать любого сопряжения с аппаратным обеспечением (уровень драйверов не должен изменяться пользователем). Программная библиотека USB может обеспечить процесс энумерации и USB устройства и USB хоста согласно главе 9 спецификации USB 2.0. Общая структура программной библиотеки USB иллюстрируется примером реализации устройства двойного назначения «шаблон», который позволяет AT90USBxxх работать как в режиме устройства, так и в режиме хоста в зависимости от вывода USB ID.
Пример приложения двойного назначения базируется на трех различных задачах:
- usb_task (usb_task.c) – задача, реализующая нижний уровень процесса энумерации USB устройства или хоста. Когда эта задача «обнаруживает» полностью работоспособное соединение с USB шиной, она изменяет различные флаги статуса, которые могут быть проверены с помощью задач приложения высокого уровня.
- Шаблонная задача устройства (device_template_task.c) осуществляет работу приложения высокого уровня. Эта задача содержит USB приложение пользователя, которое может выполняться по завершению процесса энумерации.
- Шаблонная задача хоста (host_template_task.c) представляет собой приложение высокого уровня, которое начинает свою работу после энумерации подключенного устройства.
Рисунок 4-1. Архитектура программного обеспечения USB AT90USBxxx для приложения двойного назначения
4.1 О шаблонном приложении
Шаблонное приложение используется для иллюстрации возможности использования программной библиотеки USB для реализации двух режимов работы USB приложений (устройство или хост).
В режиме устройства существует два интерфейса:
- Первый интерфейс использует IN/OUT передачи массивов данных в закольцованном режиме (все получаемые в OUT конечную точку данные посылаются обратно через IN конечную точку).
- Второй интерфейс отправляет данные через IN конечную точку по прерываниям.
Хост в шаблонном приложении распознает, энумерует и использует оба интерфейса устройства.
Рисунок 4-2. Обзор шаблонного приложения
Замечание: Дескрипторы B-устройства, используемые в шаблонном приложении, не могут напрямую использоваться при энумерации в стандартной хост системе ПК. Пожалуйста, обратитесь на сайт Atmel для «реальных» примеров устройств USB (HID мышка, HID клавиатура, MassStorage, CDC)
4.2 Архитектура исходных файлов
Рисунок 4-3. Организация исходных файлов
5. Конфигурирование программной библиотеки USB
Шаблонное приложение уже сконфигурировано для реализации функциональности хоста и функциональности устройства. Также оно может быть сконфигурировано для работы только в качестве устройства или только в качестве сокращенного хоста. В зависимости от выбранного режима работы задача USB будет вызывать или usb_host_task, или задачу USB устройства для обработки запросов согласно главе 9 спецификации USB. В таком случае соответствующая template_device_task или template_host_task может быть удалена из планировщика задач.
5.1 Общая конфигурация
Все общие параметры конфигурации приложения определены в файле "config.h" (частота XTAL, тип ЦПУ… ).
Специфические параметры для каждого из модулей определены в соответствующих им файлах конфигурации.
5.2 Конфигурация планировщика
Шаблонное приложение содержит простой планировщик задач, который позволяет пользователю создавать и добавлять собственные задачи без изменения общей архитектуры и организации приложения. Этот планировщик вызывает все предопределенные задачи в предопределенном порядке без приоритетных прерываний обслуживания. Задача выполняется до конца, затем планировщик вызывает другую задачу.
Задачи для планировщика определяются в файле “conf_scheduler.h”, в который пользователь может добавлять свои задачи.
Для шаблонного приложения USB двойного назначения используются следующие параметры конфигурации планировщика:
#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 выполняются в бесконечном цикле.
5.3 Конфигурация библиотеки USB
Библиотека USB может быть сконфигурирована с помощью файла "conf_usb.h". Этот файл содержит параметры для конфигурации двух режимов: и режима устройства и режима хоста. Конфигурационный файл разделен на три части: общие конфигурационные параметры, конфигурационные параметры хоста и устройства.
В разделе общих параметров конфигурации можно выбрать какой режим работы осуществляет библиотека устройство и/или хост, и используется или нет внутренний регулятор напряжения выводов USB (в зависимости от напряжения питания приложения).
5.4 Конфигурация устройства
Программная библиотека USB обеспечивает выполнения следующих требований главы 9 спецификации USB для устройства B:
- подключение/отключение (наблюдение за VBUS);
- приостановку (suspend);
- возобновление работы (resume);
- обработку запросы энумерации.
Асинхронные события на шине USB (подключение, приостановка, возобновление работы, сброс) обрабатываются с помощью подпрограммы обработки прерываний USB, находящейся в файле "usb_tak.c". Благодаря определяемым пользователям действиям в файле "conf_usb.h" приложение пользователя может выполнять другие функции по этим событиям.
Запросы энумерации от хоста обрабатываются в режиме опроса функциями, содержащимися в файлах "usb_device_task.c" и "usb_standard_request.c». usb_task, которая принадлежит к задачам планировщика, периодически проверяет наличие новой управляющей посылки от хоста.
5.4.1 Конфигурирование библиотеки USB
Для работы в режиме USB устройства в библиотеке параметр USB_DEVICE_FEATURE должен быть определен как ENABLED.
Раздел файла "conf_usb.h", посвященный конфигурации устройства, содержит физические номера используемых в приложении конечных точек и набор определяемых пользователем функций, которые могут выполняться по специальным событиям во время связи по USB.
Для шаблонного приложения:
#define NB_ENDPOINTS 4 //number of EP in the application including EP0
#define EP_TEMP_IN 1
#define EP_TEMP_OUT 2
#define EP_TEMP_INT_IN 3
// write here the action to associate to each USB event
// be carefull not to waste time in order not disturbing the functions
#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()
|
Определяемые пользователем функции позволяют приложению высокого уровня выполнять специфические операции. Например, пользователь может определить функцию, которая будет выполняться при каждом получении маркера начала фрейма и сброса на USB шине.
5.4.2 О сложных устройствах
Сложное устройство USB может определяться на шине USB в качестве различной периферии. Таким образом, в дескрипторе конфигурации сложного устройства должно быть более одного интерфейса. Каждый из интерфейсов имеет свои значения параметров Class/SubClass/Protocol и соответствующее им «поведение» программного обеспечения высокого уровня (например, сложное устройство может работать как HID устройство и как MassStorage приложение).
Сложное USB устройство, которое иллюстрирует применение программной библиотеки USB (и рассматривается в этих «рекомендациях»), обладает двумя интерфейсами:
- первый интерфейс использует конечные точки IN/OUT в режиме передачи массивов данных;
- второй интерфейс использует одну IN конечную точку по прерываниям.
5.4.3 Конфигурирование дескрипторов устройства
Дескрипторы устройства, используемые для энумерации хранятся в файлах "usb_descriptors.c и usb_descriptors.h".
Типы структур дескрипторов объявляются в файле "usb_descriptors.h", здесь пользователь должен задать все параметры устройства необходимые для конфигурации при энумерации.
Тип дескриптора конфигурации объявлен в конце файла "usb_descriptors.h":
// Configuration descriptor template
// The device has two interfaces
// - First interface has 2 bulk endpoints
// - Second interface has 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 //! each configuration has its own class
#define DEVICE_SUB_CLASS 0 //! each configuration has its own sub-class
#define DEVICE_PROTOCOL 0 //! each configuration has its own protocol
#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 //! The number of interface for this configuration
#define CONF_NB 1 //! Number of this configuration
#define CONF_INDEX 0
#define CONF_ATTRIBUTES USB_CONFIG_SELFPOWERED
#define MAX_POWER 50 // 100 mA (2mA unit !)
// USB Interface descriptor gen
#define INTERFACE_NB_TEMP 0 //! The number of this interface
#define ALTERNATE_TEMP 0 //! The alt settting nb of this interface
#define NB_ENDPOINT_TEMP 2 //! The number of endpoints this this
interface have
#define INTERFACE_CLASS_TEMP 0x00 //! Class
#define INTERFACE_SUB_CLASS_TEMP 0x00 //! Sub Class
#define INTERFACE_PROTOCOL_TEMP 0x00 //! Protocol
#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, INTERUPT = 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, INTERUPT = 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 //! The number of this interface
#define ALTERNATE_SECOND_TEMP 0 //! The alt settting nb of this
interface
#define NB_ENDPOINT_SECOND_TEMP 1 //! The number of endpoints this this
interface have
#define INTERFACE_CLASS_SECOND_TEMP 0x00 //! Class
#define INTERFACE_SUB_CLASS_SECOND_TEMP 0x55 //! Sub Class
#define INTERFACE_PROTOCOL_SECOND_TEMP 0xAA //! Protocol
#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, INTERUPT = 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.5 Конфигурирование сокращенного хоста
Программная библиотека USB удовлетворяет следующие требования к сокращенному хост контроллеру изложенные в 9 главе спецификации USB:
- формирование и мониторинг VBUS;
- подключение периферии;
- отключение периферии;
- энумерация и идентификация подключенной периферии;
- конфигурирование каналов хост контроллера в соответствии с дескрипторами подключенной периферии;
- приостановка активности USB;
- обеспечение возобновления работы и удаленного пробуждения.
Также, как при реализации USB устройства с помощью этой библиотеки, асинхронные события на шине USB (подключение, отключение, обнаружение удаленного пробуждения) обрабатываются напрямую обработчиком прерываний USB, который находится в файле "usb_tak.c". Приложение пользователя может выполнять определенные им функции при возникновении этих событий благодаря определяемым пользователем действиям в файле "conf_usb.h".
Состояние подключенного устройства и процесс энумерации осуществляется в режиме опроса с помощью функций в файлах "usb_host_task.c" и "usb_host_enum.c files". Только критические и асинхронные события такие, как отключение устройства и обнаружение удаленного пробуждения, обслуживаются по прерыванию (файл "usb_task.c").
Для работы в режиме USB хоста в библиотеке параметр USB_HOST_FEATURE должен быть определен как ENABLED.
Раздел файла "conf_usb.h", посвященный конфигурированию хоста, позволяет выбрать следующие параметры:
- таблицу VID/PID известных устройств, поддерживаемых хостом;
- таблицу class/subclass/protocol поддерживаемых хостом интерфейсов;
- максимальное число поддерживаемых интерфейсов подключенного сложного устройства;
- максимальное количество конечных точек в соответствии с интерфейсом;
- параметры ожидания для передач данных по USB (количество NAK или временная задержка).
Пример для шаблонного приложения:
//! This table contains the VID/PID that are supported by the reduced host application
//! VID_PID_TABLE format definition:
//!
//! #define VID_PID_TABLE {VID1, number_of_pid_for_this_VID1, PID11_value,...,
PID1X_Value \n
//! ...\n
//! ,VIDz, number_of_pid_for_this_VIDz, PIDz1_value,...,
PIDzX_Value}
#define VID_PID_TABLE {0x03EB, 2, 0x201C, 0x2014 \
,0x0123, 3, 0x2000, 0x2100, 0x1258}
//! @brief CLASS/SUBCLASS_PROTOCOL supported table list
//!
//! This table contains the CLASS/SUBCLASS/PROTOCOL that is supported by the reduced host
application
//! This table definition allows to extended the reduced application device support to an
entire Class/
//! /subclass/protocol instead of a simple VID/PID table list.
//!
//! CLASS_SUBCLASS_PROTOCOL format definition: \n
//! #define CLASS_SUBCLASS_PROTOCOL {CLASS1, SUB_CLASS1,PROTOCOL1, \n
//! ...\n
//! CLASSz, SUB_CLASSz,PROTOCOLz}
#define CLASS_SUBCLASS_PROTOCOL {\
0x00, 0x00, 0x00,\
0x00,0x55,0xAA}
//! The size of RAM buffer reserved of descriptors manipulation
#define SIZEOF_DATA_STAGE 250
//! The address that will be assigned to the connected device
#define DEVICE_ADDRESS 0x05
//! The maximum number of interface that can be supported (composite device)
#define MAX_INTERFACE_SUPPORTED 0x02
//! The maximum number of endpoints per interface supported
#define MAX_EP_PER_INTERFACE 3
//! The host controller will be limited to the strict VID/PID list.
//! When enabled, if the device PID/VID does not belongs to the supported list,
//! the host controller library will not go to deeper configuration, but to error state.
#define HOST_STRICT_VID_PID_TABLE DISABLE
//! Try to configure the host pipes according to the device descriptors received
#define HOST_AUTO_CFG_ENDPOINT ENABLE
//! Host start of frame interrupt always enable
#define HOST_CONTINUOUS_SOF_INTERRUPT DISABLE
//! When Host error state detected, goto unattached state
#define HOST_ERROR_RESTART ENABLE
//! USB host pipes transfers use USB communication interrupt (allows to use none blocking
functions)
#define USB_HOST_PIPE_INTERRUPT_TRANSFER ENABLE
//! Force WDT reset upon ID pin change
#define ID_PIN_CHANGE_GENERATE_RESET ENABLE
//! Enable Timeout delay (time) for host transfer
#define TIMEOUT_DELAY_ENABLE ENABLE
//! delay 1/4sec (250ms) before timeout value
#define TIMEOUT_DELAY 1
//! Enable cpt NAK Timeout for host transfer
#define NAK_TIMEOUT_ENABLE ENABLE
//! Number of NAK handshake before timeout for transmit functions (up to 0xFFFF)
#define NAK_SEND_TIMEOUT 0x0010
//! NAKNumber of NAK handshake before timeout for receive functions (up to 0xFFFF)
#define NAK_RECEIVE_TIMEOUT 0x0010
//! For reduced host only allows to control VBUS generator with PIO PE.7
#define SOFTWARE_VBUS_CTRL ENABLE
#if (HOST_AUTO_CFG_ENDPOINT==FALSE)
//! If no auto configuration of EP, map here user function
#define User_configure_endpoint()
#endif
//! @defgroup host_cst_actions USB host custom actions
//!
//! @{
// write here the action to associate to each USB host event
// be carefull not to waste time in order not disturbing the functions
#define Usb_id_transition_action()
#define Host_device_disconnection_action()
#define Host_device_connection_action()
#define Host_sof_action()
#define Host_suspend_action()
#define Host_hwup_action()
#define Host_device_not_supported_action()
#define Host_device_class_not_supported_action()
#define Host_device_supported_action()
#define Host_device_error_action()
//! @}
|
6. Использование программной библиотеки USB с приложениями высокого уровня
6.1 Устройство
Задача, обеспечивающая работу приложения пользователя в режиме USB устройства, «знает», что устройство успешно прошло процесс энумерации, благодаря функции "Is_device_enumerated()", которая возвращает TRUE, когда получен SETCONFIGURATION запрос от хоста.
void device_template_task(void)
{
//.. FIRST CHECK THE DEVICE ENUMERATION STATE
if (Is_device_enumerated())
{
//.. HERE START THE USB DEVICE APPLICATIVE CODE
}
} |
Файл "device_template_task.c", включенный в код шаблонного приложения, иллюстрирует, как использовать и конечные точки IN/OUT в режиме передачи массивов данных и конечную точку по прерываниям, соответствующие интерфейсам в дескрипторах конфигурации.
6.2 Хост приложение
Приложение пользователя, реализующее USB хост, соответствует 9 главе спецификации USB благодаря специальным функциям по событиям, которые позволяют:
- определять подключение/отключение устройства;
- получатьосновные характеристики устройства (VID, PID, Класс, Подкласс, Протокол, количество интерфейсов, максимальный потребляемый ток …);
- приостанавливать/ возобновлять работу шины USB.
В дополнение к требованиям главы 9 спецификации USB, библиотека хоста также содержит набор функций, которые позволяют реализовывать поток данных IN/OUT в режиме передачи массивов данных (функции отправки и получения данных и в режиме опроса (блокирующие) и не блокирующие по прерываниям)
6.2.1 Обнаружение устройства
6.2.1.1 Подключение устройства
Функция "Is_new_device_connection_event()" возвращает TRUE, когда новое устройство прошло процесс энумерации и сконфигурировано (послан запрос Set Configuration) в соответствии с 9 главой спецификации USB.
6.2.1.2 Отключение устройства
Функция "Is_device_disconnection_event()" возвращает TRUE, когда сконфигурированное ранее устройство отключается от USB порта хоста.
6.2.2 Характеристики сконфигурированного устройства
Хост библиотека содержит набор функций, позволяющих получать USB характеристики сконфигурированного устройства.
6.2.2.1 Общая информация
"Get_VID()": возвращает VID сконфигурированного устройства."Get_ PID ()": возвращает PID сконфигурированного устройства.
"Get_maxpower()" возвращает максимальный ток потребления устройства (в единицах 2мА).
"Is_device_self_powered()" возвращает TRUE, если сконфигурированное устройство имеет собственный источник питания.
"Is_device_supports_remote_wakeup()" возвращает TRUE, если сконфигурированное устройство поддерживает возможность удаленного пробуждения. "Is_host_full_speed()" возвращает TRUE, если сконфигурированное устройство подключено в режиме full speed. Если подключено low speed устройство, функция возвращает FALSE.
6.2.2.2 Интерфейсы, конечные точки
Хост библиотека поддерживает устройства с несколькими объявленными интерфейсами (сложные устройства) и может конфигурировать каналы хоста в соответствии с полученными дескрипторами устройства. Параметры интерфейса сконфигурированного устройства хранятся в массиве структур, который содержит характеристики интерфейса.
S_interface interface_supported[MAX_INTERFACE_SUPPORTED]
// with
typedef struct
{
U8 interface_nb;
U8 altset_nb;
U16 class;
U16 subclass;
U16 protocol;
U8 nb_ep;
U8 ep_addr[MAX_EP_PER_INTERFACE];
} S_interface; |
Хост библиотека содержит набор функций для доступа к этим параметрам:
- "Get_nb_supported_interface()" возвращает количество поддерживаемых интерфейсов сконфигурированных для подключенного устройства;
- "Get_class(interface)" возвращает класс заданного интерфейса;
- "Get_subclass(interface)" возвращает подкласс заданного интерфейса;
- "Get_protocol(interface)" возвращает протокол заданного интерфейса;
- "Get_nb_ep(s_interface)" возвращает количество конечных точек заданного номера интерфейса;
- "Get_interface_number(s_interface)"возвращает номер заданного интерфейса согласно дескриптору устройства;
- "Get_alts_s(s_interface)"возвращает номер альтернативной конфигурации для заданного интерфейса;
- "Get_ep_addr(s_interface,n_ep)" возвращает логический адрес конечной точки заданного интерфейса и заданной конечной точки.
Хост библиотека позволяет конфигурировать каналы «на лету». В соответствии с полученным дескриптором устройства библиотека назначает каналы для каждой конечной точки устройства. Таблица ("ep_table") позволяет связать физический адрес канала хоста с логическим адресом конечной точки.
Следующие функции могут быть использованы для получения перекрестных ссылок:
- "Get_ep_addr(s_interface,n_ep)" возвращает логический адрес конечной точки соответствующий заданному интерфейсу и номеру конечной точки;
- "host_get_hwd_pipe_nb(ep_addr)" возвращает физический номер канала соответствующий логическому адресу конечной точки.
6.2.3 Управление активностью шины
6.2.3.1 Приостановка USB шины
Вызванная из хост приложения пользователя функция "Host_request_suspend()" переводит шину USB в состояние приостановки. Если сконфигурированное устройство поддерживает удаленное пробуждение, то USB хост перед переходом в режим приостановки посылает устройству запрос "Set Feature Enable Remote Wake Up".
Функция "Is_host_suspended()" возвращает TRUE, когда шина USB приостановлена, и может быть использована хост приложением высокого уровня для определения состояния USB.
6.2.3.2 Возобновление работы шины USB
Вызвав функцию "Host_request_resume()", хост приложение может возобновить активность USB.
6.2.3.3 Удаленное пробуждение
Если сконфигурированное приложение поддерживает удаленное пробуждение, то эта функция позволяет возобновить активность USB хоста.
6.2.4 Функции передачи данных
Хост библиотека содержит 2 типа функций, которые позволяют посылать и получать данные через IN/OUT каналы передачи массивов данных в режиме опроса или по прерыванию.
6.2.4.1 Функции передачи данных в режиме опроса
- Функция передачи данных:
U8 host_send_data(U8 pipe, U16 nb_data, U8 *buf);
Эта функция посылает nb_data, на которые указывает *buf через канал с заданным физическим номером.
- Функция получения данных:
U8 host_get_data(U8 pipe, U16 *nb_data, U8 *buf);
Эта функция получает nb_data, на которые указывает *buf через заданный канал. Количество байт является параметром функции, таким образом, функция возвращает количество успешно принятых байт.
6.2.4.2 Неблокирующие функции передачи данных
Для использования этих функций параметр "USB_HOST_PIPE_INTERRUPT_TRANSFER" в разделе конфигурации хоста должен быть определен как ENABLE. Эти функции аналогичны вышеописанным блокирующим функциям, но они возвращают данные немедленно, без активного ожидания конца передачи/приема данных. Когда передача/прием данных завершен или возникает ошибка, вызывается функция возврата, которая является параметром типа указатель, причем статус возврата и количество полученных/принятых байт являются параметрами этой функции.
- Функция передачи данных
U8 host_sent_data_interrupt(U8 pipe, U16 nb_data, U8 *buf, void
(*handle)(U8 status, U16 nb_byte));
Эта функция посылает nb_data, на которые указывает *buf через канал с заданным физическим номером.
- Функция получения данных
U8 host_get_data_interrupt(U8 pipe, U16 nb_data, U8 *buf, void (*handle)(U8
status, U16 nb_byte));
Эта функция получает nb_data, на которые указывает *buf через заданный канал.
6.2.4.3 Возвращаемые значения
Функции обмена данными возвращают следующие значения статуса:
#define PIPE_GOOD 0 //Transfer OK
#define PIPE_DATA_TOGGLE 0x01 //Data toggle error
#define PIPE_DATA_PID 0x02 //PID error
#define PIPE_PID 0x04
#define PIPE_TIMEOUT 0x08 //Time out error (no handshake received)
#define PIPE_CRC16 0x10 //CRC error
#define PIPE_STALL 0x20 //STALL handshake received
#define PIPE_NAK_TIMEOUT 0x40 //Maximum number of NAK handshake received
#define PIPE_DELAY_TIMEOUT 0x80 //Timeout error |
6.2.5 Шаблон хост приложения высокого уровня
Следующий код из шаблона хост задачи приложения иллюстрирует типичную реализацию хост приложения высокого уровня с использованием программной библиотеки USB:
void host_template_task(void)
{
U16 *ptr_nb;
U16 nb;
U8 i;
ptr_nb=&nb;
// First check the host controller is in full operating mode with the B device
// attached and enumerated
if(Is_host_ready())
{
// New device connection (executed only one time after device connection)
if(Is_new_device_connection_event())
{
for(i=0;i<Get_nb_supported_interface();i++)
{
// First interface with two bulk IN/OUT pipes
if(Get_class(i)==0x00 && Get_subclass(i)==0x00 && Get_protocol(i)==0x00)
{
//Get correct physical pipes associated to IN/OUT Endpoints
if(Is_ep_addr_in(Get_ep_addr(i,0)))
{ //Yes associate it to the IN pipe
pipe_in=host_get_hwd_pipe_nb(Get_ep_addr(i,0));
pipe_out=host_get_hwd_pipe_nb(Get_ep_addr(i,1));
}
else
{ //No, invert...
pipe_in=host_get_hwd_pipe_nb(Get_ep_addr(i,1));
pipe_out=host_get_hwd_pipe_nb(Get_ep_addr(i,0));
}
}
// Seconf interface with interrupt IN pipe
if(Get_class(i)==0x00 && Get_subclass(i)==0x55 && Get_protocol(i)==0xAA)
{
pipe_interrupt_in=host_get_hwd_pipe_nb(Get_ep_addr(i,0));
Host_select_pipe(pipe_interrupt_in);
Host_continuous_in_mode();
Host_unfreeze_pipe();
}
}
}
// Firt interface (bulk IN/OUT) management
// In polling mode
// The sample task sends 64 byte through pipe nb2...
sta=host_send_data(pipe_out,64,tab);
// And receives 64bytes from pipe nb 1...
*ptr_nb=64;
sta=host_get_data(pipe_in,ptr_nb,tab);
// Second interface management (USB interrupt IN pipe)
Host_select_pipe(pipe_interrupt_in);
if(Is_host_in_received())
{
if(Is_host_stall()==FALSE)
{
i=Host_read_byte();
Host_read_byte();
}
Host_ack_in_received(); Host_send_in();
}
// Here an example of an applicative request to go to USB suspend ...
if(Is_hwb())
{
Host_request_suspend();
}
}
// Here an applicative example of resume request...
if(Is_host_suspended() && Is_joy_select())
{
Host_request_resume();
}
//Device disconnection...
if(Is_device_disconnection_event())
{
//Put here code to be executed upon device disconnection...
}
} |
7. Часто задаваемые вопросы
7.1 Режим устройства
7.1.1 Как поменять VID и PID
VID (идентификатор производителя) и PID (идентификатор продукта) позволяют хосту идентифицировать устройство. У каждого производителя должен быть свой VID, общий для всех продуктов (он присваивается USB org). Каждый продукт должен иметь свой PID (он присваивается производителем). Значения VID и PID определяются в файле usb_descriptor.h. Для их изменения вам нужно изменить нижеприведенные переменные:
// USB Device descriptor
#define VENDOR_ID 0x03EB // Atmel vendor ID = 03EBh
#define PRODUCT_ID 0x201C |
7.1.2 Как поменять значения строковых дескрипторов?
Значения строковых дескрипторов определены в usb_descriptor.h. Например, для изменения названия производителя вы должны изменить следующие переменные:
Длину строки:
Значение строки:
#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 Как сконфигурировать устройство с собственным источником питания и с питанием от шины?
Параметр, который определяет, имеет устройство собственное питание или питается от шины, определен в файле usb_descriptor.h. Ниже приведены определения для каждого режима:
bus-power mode:
// USB Configuration descriptor
#define CONF_ATTRIBUTES USB_CONFIG_BUSPOWERED |
Self-power mode:
// USB Configuration descriptor
#define CONF_ATTRIBUTES USB_CONFIG_SELFPOWERED |
7.1.4 Как добавить новый дескриптор?
Для того, чтобы добавить дескриптор в ваше приложение, вы должны выполнить следующие шаги:
- Определить значения параметров дескриптора и его структуру в файле usb_descriptors.h file.
Например, HID дескриптор и его структура должны быть определены в файле 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
/*_____ U S B H I D D E S C R I P T O R
_________________________________*/
typedef struct {
U8 bLength; /* Size of this descriptor in bytes */
U8 bDescriptorType; /* HID descriptor type */
U16 bscHID; /* Binay Coded Decimal Spec. release */
U8 bCountryCode; /* Hardware target country */
U8 bNumDescriptors; /* Number of HID class descriptors to follow */
U8 bRDescriptorType; /* Report descriptor type */
U16 wDescriptorLength; /* Total length of Report descriptor */
} S_usb_hid_descriptor; |
- Добавить новый дескриптор в структуру s_usb_user_configuration_descriptor в файле usb_descriptors.h file:
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; |
- В файле usb_descriptors.c прибавить размер нового дескриптора к параметру wTotalLength в дескрипторе конфигурации и добавить значение дескриптора (см. пример ниже):
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
}
}; |
- Не забудьте добавить все необходимые для управления этим дескриптором функции.
7.1.5 Как добавить новую конечную точку?
Для конфигурирования новой конечной точки следуйте нижеприведенному порядку действий:
- Как объяснено в разделе Дескрипторы USB, конечная точка принадлежит интерфейсу. Первое, что нужно сделать, чтобы добавить новую конечную точку, это увеличить на 1 значение параметра NB_ENDPOINT. Эта переменная определена в файле usb_descriptor.h и принадлежит к параметрам дескриптора интерфейса.
// USB Interface descriptor
#define INTERFACE_NB xx
#define ALTERNATE xx
#define NB_ENDPOINT xx//This parameter=the endpoints number of the
interface
#define INTERFACE_CLASS xx
#define INTERFACE_SUB_CLASS xx
#define INTERFACE_PROTOCOL xx
#define INTERFACE_INDEX xx |
- Следующий шаг – определить значения параметров дескриптора конечной точки. Эти значения должны быть определены в usb_descriptors.h.
// USB Endpoi
nt 1 descriptor FS
#define ENDPOINT_NB_1 (EP_MOUSE_IN | 0x80)
#define EP_ATTRIBUTES_1 0x03 // BULK = 0x02, INTERUPT = 0x03
#define EP_IN_LENGTH_1 8
#define EP_SIZE_1 EP_IN_LENGTH_1
#define EP_INTERVAL_1 0x02 // Interrupt polling interval from host |
EP_MOUSE_IN определена в conf_USB.h для указания номера конечной точки, используемой в приложении.
- Добавить дескриптор новой конечной точки в дескриптор конфигурации (как объяснено в предыдущем пункте часто задаваемых вопросов).
- Добавить вызов функции инициализации аппаратного обеспечения в 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);
}qsd |
Документация: