Программная библиотека 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. Стиль кода
Для понимания программного обеспечения важно нижеприведенное описание стиля кода:
- определенные константы обозначаются заглавными буквами:
- макросы обозначаются первой заглавной буквой, а далее строчными:
- Приложение пользователя может выполнять свои собственные команды по каждому событию USB благодаря специальным меткам, определенным следующим образом в файле usb_conf.h.
- Макро-функция Usb_unicode() должна использоваться везде (строковые дескрипторы…), где требуется передача символа в кодировке Unicode по протоколу USB.
#define FOSC 8000;
#define Is_usb_sof() ((UDINT & MSK_SOFI) ? TRUE: FALSE)
#define Usb_sof_action() sof_action();
Замечание: пользовательские функции должны осуществлять только кратковременные операции!
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") позволяет связать физический адрес канала хоста с логическим адресом конечной точки.
U8 ep_table[MAX_EP_NB]; |
Следующие функции могут быть использованы для получения перекрестных ссылок:
- "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_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 Как сконфигурировать устройство с собственным источником питания и с питанием от шины?
Параметр, который определяет, имеет устройство собственное питание или питается от шины, определен в файле 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 |
Связанные документы
ТелекоммуникацииAVR276 (223.7 Кб), 30.11.2009
Программная библиотека USB для микроконтроллеров
Автор документа: Мария |
Дата публикации: 30.08.2009 Дата редактирования: 30.11.2009 |
Кол-во просмотров 4693 | |
Все новости одной лентой |