В HTML      В PDF
микроэлектроника, микросхема, транзистор, диод, микроконтроллер, память, msp430, Atmel, Maxim, LCD, hd44780, t6963, sed1335, avr, mega128
Предприятия Компоненты Документация Применения Статьи Новости

 
Пересюхтюмя


13-я Международная выставка электронных компонентов и комплектующих для электронной промышленности





Выставка Передовые Технологии Автоматизации





Главная страница > Применение > Микроконтроллеров > AVR
Пересюхтюмя


13-я Международная выставка электронных компонентов и комплектующих для электронной промышленности





Выставка Передовые Технологии Автоматизации


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 шиной: хост или устройство.

Стандартная топология 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 устройство должно иметь по крайней мере те дескрипторы, что приведены на рисунке ниже, чтобы быть «узнанным» хостом:

Дескрипторы 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) представляет собой приложение высокого уровня, которое начинает свою работу после энумерации подключенного устройства.

Архитектура программного обеспечения USB AT90USBxxx для  приложения двойного назначения
Рисунок 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 Как добавить новый дескриптор?

Для того, чтобы добавить дескриптор в ваше приложение, вы должны выполнить следующие шаги:

  1. Определить значения параметров дескриптора и его структуру в файле 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;
  1. Добавить новый дескриптор в структуру 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;
  1. В файле 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
      }
    };
  1. Не забудьте добавить все необходимые для управления этим дескриптором функции.

7.1.5 Как добавить новую конечную точку?

Для конфигурирования новой конечной точки следуйте нижеприведенному порядку действий:

  1. Как объяснено в разделе Дескрипторы 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
  1. Следующий шаг – определить значения параметров дескриптора конечной точки. Эти значения должны быть определены в 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 для указания номера конечной точки, используемой в приложении.

  1. Добавить дескриптор новой конечной точки в дескриптор конфигурации (как объяснено в предыдущем пункте часто задаваемых вопросов).
  2. Добавить вызов функции инициализации аппаратного обеспечения в 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

Документация:

  229 Kb Engl Исходный файл