Тестовая последовательность для usb
Шина USB обеспечивает обмен данными между хост-компьютером и множеством периферийных устройств (ПУ). USB является единой централизованной аппаратно-программной системой массового обслуживания множества устройств и множества прикладных программных процессов. Связь программных процессов со всеми устройствами обеспечивает хост-контроллер с многоуровневой программной поддержкой. Этим USB существенно отличается от традиционных периферийных интерфейсов (портов LPT, COM, GAME, клавиатуры, мыши и т. п.), сравнение этих типов подключений приводится в таблице.
Таблица. Сравнение шины USB с традиционными периферийными интерфейсами
Традиционные интерфейсы (COM, LPT, Game…) | Шина USB |
Подключение каждого устройства в общем случае требует присутствия собственного контроллера (адаптера) 1 | Все устройства подключены через один хостконтроллер |
Каждый контроллер занимает свои ресурсы (области в пространстве памяти, ввода/вывода, а также запросы прерывания) | Ресурсы занимает только хост-контроллер |
Малое количество устройств, которые возможно одновременно подключить к компьютеру | Возможность подключения до 127 устройств |
Драйверы устройств могут обращаться непосредственно к контроллерам своих устройств, независимо друг от друга | Драйверы устройств обращаются только к общему драйверу хост-контроллера |
Независимость драйверов оборачивается непредсказуемостью результата одновременной работы с множеством устройств, отсутствием гарантий качества обслуживания (возможность задержек и уменьшения скорости передачи) для различных устройств | Централизованный планируемый обмен обеспечивает гарантии качества обслуживания, что позволяет передавать мультимедийные изохронные данные наряду с обычным асинхронным обменом |
Разнообразие интерфейсов, разъемов и кабелей, специфичных для каждого типа устройств | Единый удобный и дешевый интерфейс для подключения устройств всех типов. Возможность выбора скорости работы устройства (1,5–15–480 Мбит/с) в зависимости от потребности |
Отсутствие встроенных средств обнаружения подключения/отключения и идентификации устройств, сложность поддержки PnP | Возможность «горячего» подключения/отключения устройств, полная поддержка PnP, динамическое конфигурирование |
Отсутствие средств контроля ошибок | Встроенные средства обеспечения надежной передачи данных |
Отсутствие штатного питания устройств | Возможность питания устройств от шины, а также наличие средств управления энергопотреблением |
1 — Возможностью подключения к одному контроллеру множества устройств обладает и шина SCSI, но ее параллельный интерфейс по сравнению с USB слишком дорог, громоздок и более ограничен в топологии.
Подтверждения, управление потоком и сигнализация ошибок устройства
Для подтверждений приема, управления потоком и сигнализации ошибок используются пакеты квитирования (handshake packets). Из этих пакетов хост-контроллер может посылать устройству только пакет ACK, подтверждающий безошибочный прием пакета данных. Устройство для ответа хосту использует следующие пакеты квитирования:
Управление потоком при выводе данных, основанное только на возможности ответа NAK в случае неготовности устройства, весьма неэффективно расходует пропускную способность шины: чтобы убедиться в неготовности устройства, по шине впустую передается большой пакет данных. В USB 2.0 этой неприятности в транзакциях Bulk-OUT и Control избегают, применив протокол проб (Ping Protocol). Хост может опросить готовность устройства к приему пакета максимального размера, послав ему маркер-пробник PING. На этот маркер устройство может ответить подтверждением ACK (при готовности) или NAK (если не способно принять пакет максимального размера). Отрицательный ответ заставит хост повторить пробу позже, положительный разрешит ему выполнить транзакцию вывода данных. На транзакцию вывода после положительного ответа на пробу ответы устройства более разнообразны:
- ACK означает успешный прием и готовность принять следующий полноразмерный пакет;
- NYET означает успешный прием, но неготовность к следующему пакету;
- NAK — неожиданный ответ (он противоречит успеху пробы), но он возможен, если устройство внезапно стало временно не готово.
Высокоскоростное устройство в дескрипторах конечных точек сообщает о возможной интенсивности посылок NAK: поле bInterval для конечных точек типа Bulk и Control указывает число микрокадров, приходящееся на один NAK (0 означает, что устройство никогда не ответит NAK’ом на транзакцию вывода).
UPD-II
1. Дескрипторы устройств, доступные для просмотра с помощью различных информационных утилит индицируют потенциальные возможности устройства. Скоростной режим, установленный для USB порта при подключении устройства, не всегда соответствует возможностям, декларированным в дескрипторах.
Устройство, декларирующее поддержку USB 3.0, может работать в режиме USB 2.0 из-за заводских недоработок, неисправного кабеля и многих других причин. При этом содержимое дескрипторов может указывать на поддержку режима USB 3.0.
Спецификацией USB рекомендовано, чтобы устройство выдавало разный набор дескрипторов в зависимости от реальной установленной скорости. Но у нас нет гарантии, что эта рекомендация соблюдена разработчиками флешки.
Конечно, содержимое дескрипторов устройства — это более достоверный источник информации, чем надпись на флешке и клятвы продавца. Но по причинам, указанным выше, достоверность отлична от 100 процентов.
Именно стремление довести достоверность до 100% побудила нас на экстремально низкоуровневые исследования.
2. Другой метод – проследить в диспетчере устройств, какой контроллер является родительским для флешки (USB 2.0 EHCI или USB 3.0 XHCI), также неэффективен, так как, согласно спецификации, контроллер USB 3.0 XHCI может поддерживать все виды устройств: от Low-Speed до Super Speed. Поэтому, из того, что для флешки родительским контроллером является xHCI не следует, что устройство работает в режиме Super Speed.
Иллюстрированная проекция модели сетевого взаимодействия OSI на универсальную последовательную шину.
Три «замечательных» уровня стека USB
Меня не устроил вид стека USB, который можно встретить чаще всего на просторах сети:
Уровень шины, логический, функциональный… Это, конечно, замечательные абстракции, но они скорее для тех, кто собирается делать драйвер или прикладной софт для хоста. На стороне же микроконтроллера я ожидаю шаблонный конечный автомат, в узлы которого мы обычно встраиваем свой полезный код, и он сперва будет по всем законам жанра глючить. Или же глючить будет софт на хосте. Или драйвер. В любом случае кто-то будет глючить. В библиотеках МК тоже с наскока не разобраться. И вот я смотрю на трафик по шине USB анализатором, где происходящие события на незнакомом языке с тремя замечательными уровнями вообще не вяжутся. Интересно, это у меня от гриппозной лихорадки в голове такой диссонанс?
Если у читателя бывали сходные ощущения, предлагаю альтернативное, явившееся мне неожиданно ясно в перегретом мозгу видение стека USB, по мотивам любимой 7-уровневой модели OSI. Я ограничился пятью уровнями:
Я не хочу сказать, что весь софт и библиотеки уже сделаны или должны проектироваться, исходя из этой модели. Из инженерных соображений код c уровнями будет сильно перемешан. Но я хочу помочь тем, кто начинает своё знакомство с шиной USB, кто хочет понять протоколы обмена устройств и терминологию предметной области, подобраться поближе к готовым примерам, библиотекам и лучше ориентироваться в них. Эта модель не для загрузки в МК, но в ваши блестящие умы, дорогие друзья. А ваши золотые руки потом всё сами сделают, я не сомневаюсь:)
Итак, поехали, поправляйте, если увидите косяки. Это draft-версия, и если уже такое где-то было нарисовано, прошу простить, я не нашёл и потому скрутил сам. Думаю, картинка никуда не убежит, а я пока объясню почтенной публике, зачем вообще взялся за эту публикацию.
Свой первый баг из чужого кода я вытряхнул в конце девяностых, будучи студентом на подработках. Это был pppd под FreeBSD, который мы тогда прикрутили на модемный пул. Мотороловские модемы залипали в отбое, дозвониться никто не мог, линия пропадала зазря, и единственный оставшийся способ через PPP keep-alive почему-то глючил. Вот тогда я и выяснил, что pppd зачем-то ждёт шесть ответных байтов LCP вместо положенных четырёх. Почувствовал я себя тогда эдаким лихим жукотрясом из девяностых:-) При чём тут PPP? Просто он на USB похож: пакетный и двухточечный. Правда, в отличие от USB 2.0, полнодуплексный.
Как пройти в библиотеку?
Получив на GitHub любезно выложенный автором проект RHIDDemo для Em::Blocks, я начал портировать его в Keil (мой отладчик CoLink на базе FTDI; кто-нибудь, подскажите плагин от Coocox для Em::Blocks). Но никак не мог понять: где, чёрт возьми, автор раздобыл SPL 3.6.1 выпуска 2012г, если на сайте выложен 3.5.0 от 2011г? Я прошёл довольно скучный квест, который к моему удивлению привёл… прямо на готовый проект Custom HID для Keil в составе библиотеки USB FS 4.0.0. Лежит у всех на виду, как мышь под веником. Ну и ладно. Зато я раскурил, наконец, релизы STMicroelectronics, нашёл описание библиотеки USB FS STSW-STM32121 (UM0424) и пресёк попытки разработчика свести меня с ума. Вот скажите, это нормально подкладывать винтажный CMSIS 1.30 образца 2009г в набор SPL 3.5.0 выпуска 2011г, новый SPL 3.6.1 релиза 2012г прятать в USB-FS 4.0.0 релиза 2013г (подложив туда же и CMSIS 3.0.1 от 2012г), при том, что у них же выложена актуальная версия CMSIS 3.30 релиза 2014г? Кстати, в SPL 3.6.x для STM32F10X исправили пару багов с USART, касающихся сигналов о переполнении буфера. Спасибо, хоть release notes оставили…
HID vs SNMP
Итак, взявшись за STM32F103C8T6, я тоже решил слегка задвинуться по теме USB HID, уж больно хорошо абстракция USB HID укладывается в концепцию всяческих датчиков, сенсоров и прочих ШИМ-управляемых драйверов питания. Чем-то напомнило мне SNMP, только в сильно упрощённом виде: дескрипторы HID играют роль SNMP MIB. Когда устройство инициализируется хостом: «Привет, хост! Я кофеварка. У меня есть кнопка [старт], регуляторы [сливки], [сахар], датчики [остаток кофе], [остаток воды], [остаток сахара], [остаток сливок]. Подтягивай драйвера, дави на кнопку, кофейку попьём». Ничего не напоминает? Пример диалога по SNMP: «Ну, привет, управляющая станция с софтом за $100000. А я шасси коммутатора за $200000, и на мне сидят ещё 4 модуля по $100000 за штуку; в каждом ещё по 16 портов с неприличной скоростью, и всех функций тут просто не перечислить… спрашивай отдельно по каждому пункту; ах, да загрузка процессора такая-то, памяти столько-то…». И ещё на дюжину страниц в таком же духе.
Ещё одна замечательная схема
На просторах сети встретил ещё такую иллюстрацию (лежало в формате BMP, без шуток):
Сперва выглядит оптимистично. Наконец-то, стек в разобранном виде. Кадры, правда, обозначены неудачно: я бы нарисовал их вертикальными пунктирными линиями, а EOF — это просто пауза, реально данные не передаются. Но начинаем читать контекст и теряем понимаем истинный замысел автора (запутать нас):
Хост-контроллер интерфейса шины USB формирует кадры;
Кадры передаются последовательной передачей бит по методу NRZI.
каждый кадр состоит из наиболее приоритетных посылок, состав которых формирует драйвер хоста;
каждая передача состоит из одной или нескольких транзакций;
каждая транзакция состоит из пакетов;
каждый пакет состоит из идентификатора пакета, данных (если они есть) и контрольной суммы.
Вроде бы и нарисовано всё правильно, но по мере прочтения вопросов становится всё больше. Минимальная передаваемая структура данных по шине — это кадр или пакет? Вообще, это сверху вниз надо смотреть или наоборот? И что кодируется по методу NRZI — кадры, пакеты или просто весь битовый поток по шине? Из транзакций состоит посылка, передача, или, может быть, ценная бандероль какая?
Почему нельзя просто: хост группирует пакеты в транзакции и распределяет их по временным квантам, именуемым кадрами, чтобы давать приоритет критичным по времени данным (видео, аудио) исходя из текущей пропускной способности шины? Да, в USB есть нюансы с планированием передачи пакетов, я их пока не затрагиваю.
Моё видение стека USB
Хорошей документацией считаю упоминавшийся тут на хабре USB in a NutShell (ура, перевод), а также USB Made Simple. По ним я и собрал свою версию стека USB, нарисую её ещё раз.
Физический уровень
На физическом уровне используется набор электрических режимов дифференциальной пары проводников (вместе с землёй) для обозначения состояний, с помощью которых кодируется битовый поток по методу NRZI со вставкой битов (bit stuffing): здесь после шести идущих подряд «1» (ну захотелось передать, скажем, 0xffff) вставляется «0», чтобы приёмник подолгу не залипал в одном состоянии; приёмник узнает вставленный «0» и как данные не засчитает, это довольно распространённый приём в кодировании для лучшей автоподстройки частот. Пара проводов вместе с землёй даёт возможность сформировать, как минимум, четыре статических состояния (они обозначаются J, K, SE0, SE1). В USB 2.0 SE1 не используется, а три оставшихся дополнительно разыгрываются в динамике (с часами и переходами) для передачи ещё нескольких управляющих символов (границы пакетов, сброс, подключение/отключение, энергосбережение/выход). Хорошие иллюстрации есть в USB Made Simple, Part 3 — Data Flow.
Т.е. в итоге передаются данные в виде ноликов и единичек, плюс всякие управляющие символы, чтобы можно было из всей этой электродинамической кухни готовить нормальные пакеты данных.
(дополнено по просьбе читателей)
Пакетный уровень
На пакетном уровне между хостом и устройством передаются безадресные пакеты (пара устройств на полудуплексной линии может обойтись и без адресации). Пакет состоит из маркера SYNC для синхронизации тактов приёмника, последовательности байт и символа EOP. Длина пакета переменная, но оговаривается через верхние уровни стека. Первый байт называется Packet Identifier (PID), имеет простой избыточный формат для помехоустойчивости и пригоден для скармливания автомату следующего уровня (для сборки транзакций из пакетов). Пакеты с начинкой (длиннее одного байта PID) снабжаются контрольной суммой (короткой CRC5 или длинной CRC16, в зависимости от типа пакета). Анализатор протоколов должен, как минимум, показывать нам пакеты.
Уровень транзакций
На следующем уровне из пакетов собираются транзакции. Транзакция — это малый набор пакетов (в Full Speed USB 1, 2 или 3), следующих строго друг за другом, которыми (в полудуплексном режиме) хост обменивается с оконечной точкой (endpoint), и только с одной. Очень важно, что транзакцию открывает только хост, это специфика USB (нам в прошивке МК меньше мороки). На уровне транзакций можно говорить о канале (pipe) между хостом и одной из оконечных точек устройства, но я намеренно избегаю термина «канальный уровень» (Data Link) из модели OSI. Анализатор протоколов должен хотя бы декодировать транзакции.
Уровень передач
Поверх транзакций расположим уровень передач (transfers). Их в USB используется четыре типа: контрольные с оконечной точкой №0 (control transfers), передачи с прерываниями (interrupt transfers), изохронные (isochronous transfers) и крупноблочные передачи (bulk transfers). Последние три являются вариантами потоковых каналов (stream pipe), про которые я ещё скажу несколько слов. Этот уровень тоже должен отобразить хороший анализатор протоколов.
Прикладной уровень
Венчает стек, как обычно, прикладной уровень. Здесь происходят: установка адреса устройству хостом, рассказ устройства о себе на языке дескрипторов, команды хоста на выбор конфигурации (контрольные передачи), обмен данными с HID-устройствами (в примерах пока нашёл передачу с прерываниями, хочу попробовать контрольную), печать на принтере и сканирование, доступ к накопителю USB (крупноблочные), общение через гарнитуры и веб-камеры (изохронные) и многие другие замечательные вещи.
Последний штрих
Смотрим на трафик по USB
Итак, транзакция всегда инициируется хостом в отношении одной выбранной оконечной точки на устройстве (помимо специальной точки с номером 0, их может быть ещё до 15 штук на одном устройстве, например, комбинированная клавиатура с мышью, термометром, флэшкой, кофеваркой и кнопкой вызова сантехника заказа пиццы).
В случае приёма хостом данных с устройства последнее не может само открыть транзакцию, но может только дождаться нужного момента и поучаствовать в ней. Хост открывает транзакцию устройству пакетом с PID = IN (группа Token) и гарантирует на нужное время свободу шины, устройство вбрасывает пакет из группы Data, в зависимости от типа транзакции хост может подтвердить успех третьим пакетом из группы Handshake (ACK, NAK, STALL, NYET), транзакция закрыта.
При отправке данных на устройство (PID = OUT, группа Token) хост открывает транзакцию, отправляет пакет с данными (Data), также в зависимости от режима может принять пакет Handshake с подтверждением успешности транзакции.
По окончании транзакции всё вернётся на круги своя, устройство снова будет ждать управляющих пакетов от хоста.
Режимы передачи USB в примерах STM32 USB FS
DISCLAIMER
Дальше будут упоминаться примеры из той самой библиотеки UM0424 для работы с Full Speed USB от STMicroelectronics, но они рассчитаны под их родные демоплаты. Берите пример с автора Raja, проявляйте инженерную смекалку в адаптации проектов под свою демоплату.
По софту всё понятно: это примеры не для промышленного использования, там могут быть баги, некоторые части (типа таблицы ссылок в примере Mass storage) защищены патентом, и вы не имеете прав их использовать в коммерческом проекте. Но это ещё ничего, китайцы ухитряются потом продавать на рынке USB-изделия, у которых даже библиотечные VID и PID не удосужились поменять.
По железу, как я понял, надо начинать с кварца. У меня челябинский PinBoard II с кварцем 12Мгц (все библиотеки заточены под 8МГц), я менял умножитель ФАПЧ с 9 на 6 (ссылка с разъяснениями), иначе МК разгонится до 108МГц вместо 72МГц, а USB на 72МГц вместо положенных 48МГц вообще не поедет. Можно ещё сбавить обороты МК до 48МГц, поменяв делитель шины USB с полутора до единицы. Использовать внутренний генератор МК HSI спецы не любят: частота может слегка уплыть от нагрева, последствия для USB предсказать затрудняюсь. Ну и не забываем о периферии, конечно. Без флэш-памяти SPI/SDIO из примера Mass storage можно сделать разве что аналог /dev/null, но его ведь хрен отформатируешь:-)
Передачи с прерываниями
Эта разновидность (interrupt transfer) предназначена для обмена небольшими транзакциями, сходными с контрольными. Нет, устройство не может прерывать хоста, оно ждёт опроса, их частота и размеры пакетов оговариваются заранее в дескрипторе устройства. Хорошо подходят для всевозможных пультов, датчиков, сенсоров, мышек, светодиодов и прочих HID-кофеварок. Канал с прерываниями каждой точки однонаправленный.
Примеры: Custom HID, Joystick mouse, Virtual COM port
Передачи изохронные
Передачи крупноблочные
Что осталось нераскрытым
Я не имею цель сделать ещё один учебник по USB, их и без меня хватает, и там хорошо описаны: электрическая часть, подробности протоколов, работа с концентраторами, дескрипторный язык и уровень абстракции HID, проблемы с уникальностью VID/PID, USB 3.0 и многие другие замечательные возможности шины USB, как полезные нам, так и не очень. Айтишникам особо рекомендую экскурсию на тёмную сторону с обзором вражеских девайсов (флэшка с замаскированной HID-клавиатурой, которая будет делать страшные вещи).
Ссылки
P.S.
Читая публикации на хабре, посвящённые в той или иной степени микроэлектронике, я разглядел две инженерных касты, назовём их условно: Промэлектронщики и Айтишники. Это своего рода инженерный Инь и Ян, в каждом из нас есть доля того и другого.
Промэлектронщики имеют блестящие знания и навыки по железу, паяют радиодетали толщиной с волос левой рукой с закрытыми глазами (причём потом это работает). Взглянув на электронную схему, почти физически начинают ощущать все её токи с потенциалами, работают также и с силовыми схемами, и с (большими, быстрыми, опасными) промышленными изделиями. Подход к программированию МК соответствующий: он просто должен выдать нужные логические уровни на нужные ножки в нужное время, не столь важно каким способом. Консервативны в технологиях (не влезай — работает), тяжёлую периферию МК не особо жалуют. При обсуждении объектно-ориентированного программирования, информационной безопасности, гигантских проектов в миллион строк кода и всяких навороченных графических интерфейсов скучнеют. Вместо пакетно-ориентированной шины USB предпочитают потоковый режим USART, усиленный либо привычным RS-232, либо более брутальным RS-485 (последовательная шина для промышленных применений, до 10Мбит/с на 15м, до 100кБит/с на 1200м, до 32 устройств).
Айтишники воспитаны на понимании операционных систем, сетевой инфраструктуры и сложных взаимодействий, элита хорошо подкована в информационной безопасности и разбирается во всяких незримых способах проникновения в чужую систему. Некоторые при этом очень любят котиков (ну как их можно не любить? я, правда, не держу, не развожу и не готовлю:-). Многие любят свободу информации, ругать корпорации/правительства и побеждать силы природы усилием мысли. Паталогически ленивы, но обожают новые технологии и закрученные инженерные ребусы с дорогими игрушками (желательно решаемые на уровне софта или, в крайнем случае, перемычек). Отношения с паяльником настороженные: не спрашивайте у айтишника, любит ли он паяльник, может неправильно понять; лучше спросите, любит ли он паять электронные схемы.
К чему я? Мы просто видим этот мир по-разному… Ведь ядро Linux кроили такие же ребята, из модулей на С и ассемблерных вставок для конкретных платформ, и без холиваров вроде обошлись. По-настоящему серьёзный проект я вижу как многоядерную систему, сочетающую современнейшие МК с тяжёлой периферией, но не исключаю связки с классическими моделями типа AVR: ими можно обвесить какие-нибудь критичные быстровращающиеся острия технического прогресса. Если код проверенный годами, то почему нет?
Протокол шины USB обеспечивает обмен данными между хостом и устройством. На протокольном уровне решаются такие задачи, как обеспечение достоверности и надежности передачи, управление потоком. Весь трафик на шине USB передается посредством транзакций, в каждой транзакции возможен обмен только между хостом и адресуемым устройством (его конечной точкой).
Все транзакции (обмены) с устройствами USB состоят из двух-трех пакетов, типовые последовательности пакетов в транзакциях приведены на рис. 1. Каждая транзакция планируется и начинается по инициативе хост-контроллера, который посылает пакет-маркер транзакции (token packet). Маркер транзакции описывает тип и направление передачи, адрес выбранного устройства USB и номер конечной точки. Адресуемое маркером устройство распознает свой адрес и готовится к обмену. Источник данных, определенный маркером, передает пакет данных. На этом этапе транзакции, относящиеся к изохронным передачам, завершаются — здесь нет подтверждения приема пакетов. Для остальных типов передач работает механизм подтверждения, обеспечивающий гарантированную доставку данных. Форматы пакетов приведены на рис. 2, типы пакетов — в таблице. Во всех полях пакетов, кроме поля CRC, данные передаются младшим битом вперед (на временных диаграммах младший бит изображается слева). Пакет начинается с синхропоследовательности Sync и завершается признаком конца — EOP. Тип пакета определяется полем PID. Назначение остальных полей раскрывается далее. Длина полей Sync и EOP указана для передач на FS/LS, для высокоскоростных передач поле Sync удлинено до 32 битовых интервалов, а EOP до 8 (в пакетах SOF поле EOP имеет длину 40 бит).
Таблица. Типы пакетов и их идентификаторы PID
Имя | Код PID | Содержимое и назначение |
Пакеты-маркеры (Token) | ||
OUT | 0001 | Маркер транзакции вывода, несет идентификатор конечной точки (адрес устройства и номер точки; направление точки определяется кодом PID) |
IN | 1001 | Маркер транзакции ввода, несет идентификатор конечной точки (адрес устройства и номер точки; направление точки определяется кодом PID) |
SETUP | 1101 | Маркер транзакции управления, несет идентификатор конечной точки (адрес устройства и номер точки) |
SOF | 0101 | Маркер начала микрокадра, несет 11-битный номер кадра (вместо полей Addr и EndP) |
PING | 0100 | Пробный маркер управления потоком (в USB 2.0) |
Пакеты данных | ||
DATA0 | 0011 | Пакеты данных; чередование PID позволяет различать четные и нечетные пакеты для контроля правильности подтверждения |
DATA1 | 1011 | |
DATA2 | 0111 | Дополнительные типы пакетов данных, используемые в транзакциях с широкополосными изохронными точками (в USB 2.0 для HS) |
MDATA | 1111 | |
Пакеты квитирования (Handshake) | ||
ACK | 0010 | Подтверждение безошибочного приема пакета |
NAK | 1010 | Индикация занятости (неготовности конечной точки к обмену данными, незавершенности обработки транзакции управления) |
STALL | 1110 | Конечная точка требует вмешательства хоста |
NYET | 0110 | Подтверждение безошибочного приема, но указание на отсутствие места для приема следующего пакета максимального размера (в USB 2.0) |
Специальные пакеты (Special) | ||
PRE | 1100 | Преамбула (маркер) передачи на низкой скорости (разрешает трансляцию данных на низкоскоростной порт хаба) |
ERR | 1100 | Сигнализация ошибки в расщепленной транзакции (в USB 2.0) |
SPLIT (SS и CS) | 1000 | Маркер расщепленной транзакции (в USB 2.0). В зависимости от назначения обозначается как SS (маркер запуска) и CS (маркер завершения), назначение определяется битом SC в теле маркера |
Каналы
Коммуникационные каналы USB разделяются на два типа:
С каналами связаны характеристики, соответствующие конечной точке (полоса пропускания, тип сервиса, размер буфера и т. п.). Каналы организуются при конфигурировании устройств USB. Полоса пропускания шины делится между всеми установленными каналами. Выделенная полоса закрепляется за каналом, и если установление нового канала требует такой полосы, которая не вписывается в уже существующее распределение, запрос на выделение канала отвергается.
Каналы различаются и по назначению:
Интерфейс устройства, с которым работает клиентский драйвер, представляет собой связку клиентских каналов (pipe’s bundle). Для этих каналов драйверы устройств являются единственными источниками и потребителями передаваемых данных.
Контроль и обработка ошибок передачи
Все принимаемые пакеты проверяются на наличие ошибок, что позволяют принятые форматы пакета и некоторые соглашения:
- пакет начинается с синхронизирующей последовательности, за которой следует его идентификатор PID (Packet Identificator). За идентификатором следует его инверсная копия — Check. Несовпадение двух копий считается признаком ошибки;
- тело пакета (все поля пакета, исключая PID и признак EOP) защищается CRCкодом: 5-битным для пакетов-маркеров, 16-битным — для пакетов данных. Несовпадение CRC с ожидаемым значением считается признаком ошибки;
- пакет завершается специальным сигналом EOP; если в пакете оказывается не целое число байт, он считается ошибочным. Ложный EOP, даже на границе байта, не позволит принять пакет из-за практически неизбежной в данной ситуации ошибки по CRC-контролю;
- на физический уровень (в шину) данные пакета передаются с использованием вставки бит (bit stuffing, после шести единичных бит вставляется нолик), что предотвращает потерю битовой синхронизации при монотонном сигнале. Прием более шести единичных бит подряд считается ошибкой (на HS — признаком конца кадра).
Обнаружение любой из перечисленных ошибок в пакете заставляет приемник считать его недействительным. На пакеты, принятые с ошибкой, ни устройство, ни хост-контроллер никак не отвечают. При изохронной передаче данные недействительного пакета должны просто игнорироваться (они теряются); для остальных типов передач используются средства обеспечения надежной доставки.
Для обнаружения отсутствия ответа партнера на пакет каждое устройство имеет счетчик тайм-аута, который прерывает ожидание ответа по истечении некоторого времени. В USB имеется ограничение на время оборота по шине (roundtrip time): время от конца EOP сформированного пакета до получения начала ответного пакета. Для конечного устройства (и хост-контроллера) нормируется максимальная задержка ответа (response time) от конца увиденного EOP до введения им начала пакета. Для хабов нормируется задержка трансляции пакетов, для кабелей — задержка распространения сигналов. Счетчик тайм-аута должен учитывать максимальную задержку, возможную для допустимой конфигурации шины: до 5 промежуточных хабов, до 5 метров каждый кабель. Допустимое значение тайм-аута, выражаемое в битовых интервалах (bt), зависит от скорости:
- для скоростей FS/LS задержка, вводимая одним кабельным сегментом, по сравнению с битовым интервалом (bt) невелика. Исходя из этого в USB 1.0 для расчета допустимых задержек принимается следующая модель. На каждый кабельный сегмент отводится допустимая задержка 30 нс, на хаб — 40 нс. Таким образом, пять промежуточных хабов со своими кабелями вносят во время двойного оборота задержку 700 нс, что на FS соответствует примерно 8,5 bt. Для FS-устройства задержка ответа не должна превышать 6,5 bt (а с учетом его кабеля — 7,5 bt). Исходя из этого спецификация предписывает передатчикам на FS использовать счетчик тайм-аута на 16–18 bt;
- на скорости HS задержка в кабельном сегменте много больше битового интервала, и в USB 2.0 модель расчета несколько иная. Здесь на каждый кабельный сегмент отводится по 26 нс, а на хаб — по 4 нс плюс 36 bt. Таким образом, двукратное прохождение 6 кабельных сегментов (2×6×26 = 312 нс ≈ 150 bt) и пять хабов (2×5×4 = 40 нс ≈ 19 bt плюс 2×5×36 = 360 bt) занимает до 529 bt. Задержка ответа устройства допустима до 192 bt, а полная задержка с учетом кабелей и хабов будет до 721 bt. Исходя из этого спецификация предписывает передатчикам на HS использовать счетчик тайм-аута на 736–816 bt.
У хост-контроллера с каждой конечной точкой всех устройств связан свой счетчик ошибок, обнуляемый при планировании каждой транзакции. Этот счетчик считает все протокольные ошибки (включая и ошибки по тайм-ауту), и если число ошибок превышает порог (3), то канал с данной конечной точкой останавливается, о чем уведомляется его владелец (драйвер устройства или USBD). До превышения порога хост отрабатывает ошибки для неизохронных передач попытками повтора транзакций, без уведомления клиентского ПО. Изохронные передачи не повторяются, об обнаружении ошибок хост сообщает сразу.
Модель передачи данных
Каждая единица клиентского ПО (обычно представляемая драйвером) связывается с одним интерфейсом своего устройства (функции) монопольно и независимо (см. рисунок ниже). Связи на этом рисунке обозначают коммуникационные каналы (communication pipes), которые устанавливаются между драйверами устройств и их конечными точками. Каналы устанавливаются только с конечными точками устройств, относящимися к выбранным (из альтернативных) вариантам интерфейсов активной конфигурации. Другие конечные точки недоступны.
Источники информации
В качестве «подопытного кролика» использовался девайс Kingston DataTraveler 100 G3, объемом 16 GB:
Основные понятия
Архитектура USB допускает четыре базовых типа передач данных между хостом и периферийными устройствами:
Аппаратная часть USB включает:
- периферийные устройства USB, несущие полезные функции (USB-functions);
- хост-контроллер (Host Controller), обеспечивающий связь шины с центром компьютера, объединенный с корневым хабом (Root Hub), обеспечивающим точки подключения устройств USB. Существует два варианта хост-контроллеров USB 1.x — UHC (Universal Host Controller) и OHC (Open Host Controller), поддерживающие скорости FS/LS; высокую скорость шины USB 2.0 (HS и только) поддерживает EHC (Enhanced Host Controller);
- хабы USB (USB Hubs), обеспечивающие дополнительные точки подключения устройств;
- кабели USB, соединяющие устройства с хабами.
Программная часть USB включает:
- клиентское ПО (CSw, Client Software) — драйверы устройств USB, обеспечивающие доступ к устройствам со стороны прикладного ПО. Эти драйверы взаимодействуют с устройствами только через программный интерфейс с общим драйвером USB (USBD). Непосредственного обращения к каким-либо регистрам аппаратных средств драйверы устройств USB не выполняют;
- драйвер USB (USBD, USB Driver), «заведующий» всеми USB-устройствами системы, их нумерацией, конфигурированием, предоставлением служб, распределением пропускной способности шины, мощности питания и т. п.;
- драйвер хост-контроллера (HCD, Host Controller Driver), преобразующий запросы ввода/вывода в структуры данных, размещенные в коммуникационной области оперативной памяти, и обращающийся к регистрам хост-контроллера. Хост-контроллер выполняет физические транзакции, руководствуясь этими структурами данных.
Драйверы USBD и HCD составляют хост-часть ПО USB; спецификация USB очерчивает круг их задач, но не описывает интерфейс между ними. Физическое устройство USB должно иметь интерфейс USB, обеспечивающий полную поддержку протокола USB, выполнение стандартных операций (конфигурирование и сброс) и предоставление информации, описывающей устройство. Физические устройства USB могут быть комбинированными (compound devices): включать в себя несколько устройств-функций, подключенных к внутреннему хабу, а также предоставлять своим внутренним хабом дополнительные внешние точки подключения.
Работой всех устройств шины USB управляет хост-контроллер (host controller), являющийся программно-аппаратной подсистемой хост-компьютера. Хост-контроллер является интеллектуальным устройством шины PCI или составной частью «южного» хаба (моста) системной платы, интенсивно взаимодействующим с оперативной памятью.
Физическая топология шины USB — многоярусная звезда (см. рисунок, а). Ее вершиной является хост-контроллер, объединенный с корневым хабом (root hub). Хаб является устройством-разветвителем, он может служить и источником питания для подключенных к нему устройств. К каждому порту хаба может непосредственно подключаться периферийное устройство или промежуточный хаб; шина допускает до пяти уровней (ярусов) каскадирования хабов (не считая корневого). Поскольку комбинированные устройства содержат внутри себя хаб, их подключение к хабу пятого яруса уже недопустимо. Каждый промежуточный хаб имеет несколько нисходящих (downstream) портов для подключения периферийных устройств (или нижележащих хабов) и один восходящий (upstream) порт для подключения к корневому хабу или нисходящему порту вышестоящего хаба.
Логическая топология USB — звезда. Хабы (включая корневой) создают иллюзию непосредственного подключения каждого логического устройства к хост-контроллеру (см. рисунок ниже, б). В этой звезде устанавливаются сугубо подчиненные отношения по системе опроса-ответа: хост-контроллер по своей инициативе передает данные к выбранному устройству или принимает их. Устройство по своей инициативе передавать данные не может; непосредственные передачи данных между устройствами невозможны. Устройство по своей инициативе может лишь сигнализировать о «пробуждении» (wakeup), для чего используется специальная сигнализация, но не передача данных.
Физический интерфейс USB прост и изящен. Конструкция кабелей и коннекторов USB не дает возможности ошибиться при подключении устройств (см. рисунок ниже, а и б). Для распознавания разъема USB на корпусе устройства ставится стандартное символическое обозначение (см. рисунок ниже, в). Гнезда типа «A» устанавливаются только на нисходящих портах хабов, вилки типа «A» — на шнурах периферийных устройств или восходящих портов хабов. Гнезда и вилки типа «B» используются только для шнуров, отсоединяемых от периферийных устройств и восходящих портов хабов (от «мелких» устройств — мышей, клавиатур и т. п. кабели, как правило, не отсоединяются). Для малогабаритных устройств имеются разъемы mini-B, а для поддержки OTG (On-the-Go) имеются и вилки mini-A, и розетки miniAB. Хабы и устройства обеспечивают возможность «горячего» подключения и отключения с сигнализацией об этих событиях хосту.
При планировании соединений следует учитывать способ питания устройств: устройства, питающиеся от шины, как правило, подключают к хабам, питающимся от сети. К хабам, питающимся от шины, подключают лишь маломощные устройства — так, к клавиатуре USB, содержащей внутри себя хаб, подключают мышь USB и другие устройства-указатели (трекбол, планшет).
Логическое устройство USB представляет собой набор независимых конечных точек (Endpoint, EP), с которыми хост-контроллер (и клиентское ПО) обменивается информацией. Каждому логическому устройству USB (как функции, так и хабу) конфигурационная часть ПО хоста назначает свой адрес (1–127), уникальный на данной шине USB. Каждая конечная точка логического устройства идентифицируется своим номером (0–15) и направлением передачи (IN — передача к хосту, OUT — от хоста). Точки IN4 и OUT4, к примеру, представляют собой разные конечные точки, с которыми могут общаться даже модули клиентского ПО. Набор конечных точек зависит от устройства, но всякое устройство USB обязательно имеет двунаправленную конечную точку 0 (EP0), через которую осуществляется его общее управление. Для прикладных целей используются конечные точки с номерами 1–15 (1–2 для низкоскоростных устройств). Адрес устройства, номер и направление конечной точки однозначно идентифицируют приемник или источник информации при обмене хост-контроллера с устройствами USB. Каждая конечная точка имеет набор характеристик, описывающих поддерживаемый тип передачи данных (изохронные данные, массивы, прерывания, управляющие передачи), размер пакета, требования к частоте обслуживания.
Устройство может выполнять несколько различных функциональных задач: например, привод CD-ROM может обеспечивать проигрывание аудиодисков и работать как устройство хранения данных. Для решения каждой задачи в устройстве определяется интерфейс — набор конечных точек, предназначенных для выполнения данной задачи, и правила их использования. Таким образом, каждое устройство должно обеспечивать один или несколько интерфейсов. Наличие нескольких интерфейсов позволяет нескольким драйверам, каждый из которых обращается только к своему интерфейсу (представляющему часть устройства USB), работать с одним и тем же устройством USB. Каждый интерфейс может иметь один или несколько альтернативных вариантов (альтернативных установок — alternate settings), из которых в данный момент активным может быть только один. Варианты различаются наборами (возможно, и характеристиками) используемых конечных точек.
Набор одновременно поддерживаемых интерфейсов составляет конфигурацию устройства. Устройство может иметь одну или несколько возможных конфигураций, из которых на этапе конфигурирования хост выбирает одну, делая ее активной. От выбранной конфигурации зависит доступная функциональность, и зачастую — потребляемая мощность. Пока устройству не назначен номер выбранной конфигурации, оно не может функционировать в прикладном смысле и ток потребления от шины не должен превышать 100 мА. Хост выбирает конфигурацию исходя из доступности всех ресурсов, затребованных данной конфигурацией, включая и ток потребления от шины.
Кадры и микрокадры
Хост организует обмены с устройствами согласно своему плану распределения ресурсов. Для этого хост-контроллер циклически с периодом 1 мс формирует кадры (frames), в которые укладываются все запланированные транзакции (cм. рисунок ниже). Каждый кадр начинается с посылки пакета-маркера SOF (Start Of Frame), который является синхронизирующим сигналом для изохронных устройств, а также для хабов. Кадры нумеруются последовательно, в маркере SOF передаются 11 младших бит номера кадра. В режиме HS каждый кадр делится на 8 микрокадров, и пакеты SOF передаются в начале каждого микрокадра (с периодом 125 мкс). При этом во всех восьми микрокадрах SOF несет один и тот же номер кадра; новое значение номера кадра передается в нулевом микрокадре. В каждом микрокадре может быть выполнено несколько транзакций, их допустимое число зависит от скорости, длины поля данных каждой из них, а также от задержек, вносимых кабелями, хабами и устройствами. Все транзакции кадров должны быть завершены до начала интервала времени EOF (End of Frame). Период (частота) генерации микрокадров может немного варьироваться с помощью специального регистра хост-контроллера, что позволяет подстраивать частоту для изохронных передач.
Кадрирование используется и для обеспечения живучести шины. В конце каждого микрокадра выделяется интервал времени EOF (End Of Frame), на время которого хабы запрещают передачу по направлению к контроллеру. Если хаб обнаружит, что с какого-то порта в это время ведется передача данных (к хосту), этот порт отключается, изолируя «болтливое» устройство, о чем информируется USBD.
Счетчик микрокадров в хост-контроллере используется как источник индекса при обращении к таблице дескрипторов кадров. Обычно драйвер USB составляет таблицу дескрипторов для 1024 последовательных кадров1, к которой он обращается циклически. С помощью этих дескрипторов хост планирует загрузку кадров так, чтобы кроме запланированных изохронных транзакций и прерываний в них всегда находилось место для транзакций управления. Свободное время кадров может заполняться передачами массивов. Спецификация USB позволяет занимать под периодические транзакции (изохронные и прерывания) до 90% пропускной способности шины, то есть времени в каждом микрокадре.
В современной IT-индустрии часто случается так, что заверения производителя устройства относительно его функциональности не соответствуют действительности. От скепсиса по этому поводу перейдем к решению конкретной технической задачи…
Запросы, пакеты и транзакции
Для передачи или приема данных клиентское ПО посылает к каналу пакет запроса ввода/вывода — IRP (Input/Output Request Packet) и ждет уведомления о завершении его отработки. Формат IRP определяется реализацией драйвера USBD в конкретной ОС. В IRP имеются только сведения о запросе (местоположение буфера передаваемых данных в оперативной памяти и длина передачи); от свойств конкретного текущего подключения (скорость, допустимый размер пакета) драйвер устройства абстрагируется. Отработкой запроса в виде транзакций на шине USB занимается драйвер USBD; при необходимости он разбивает на части длинные запросы (пакеты), пригодные для передачи за одну транзакцию. Транзакция на шине USB — это последовательность обмена пакетами между хостом и ПУ, в ходе которой может быть передан или принят один пакет данных (возможны транзакции, в которых данные не передаются). Отработка запроса считается завершенной, когда успешно выполняются все связанные с ним транзакции. «Временные трудности», встречающиеся при их выполнении (неготовность к обмену данными), до сведения клиентского драйвера не доводятся — ему остается только ждать завершения обменов (или выхода по тайм-ауту). Однако устройство может сигнализировать о серьезных ошибках (ответом STALL), что приводит к аварийному завершению запроса, о чем уведомляется клиентский драйвер. В этом случае отбрасываются и все последующие запросы к данному каналу. Возобновление работы с данным каналом возможно лишь после явного уведомления об обработке ошибочной ситуации, которое драйвер устройства делает с помощью специального запроса (тоже вызова USBD).
Длинные запросы разбиваются на транзакции так, чтобы использовать максимальный размер пакета. Последний пакет с остатком может оказаться короче максимального размера. Хост-контроллер имеет средства обнаружения приема от устройства «неполновесного» пакета, размер которого меньше ожидаемого. В запросе IRP указывается, следует ли особым образом реагировать на это событие. Особая реакция может быть двоякой:
- считать короткий пакет разделителем, указывающим на конец блока данных. При этом данный IRP завершается нормально и исполняются следующие запросы к данному каналу;
- считать короткий пакет признаком ошибки, по которому канал останавливается (все его последующие ожидающие запросы сбрасываются).
При передаче массивов использование укороченных пакетов в качестве разделителей наиболее естественно. Таким образом, например, в одном из вариантов протоколов для устройств хранения данных укороченные пакеты известной длины используются в качестве управляющих.
Программный тест
Эксперимент выполняем на достаточно новой, еще не исследованной плате Tyan S5533, построенной на чипсете Denlow.
Рис 1. Системная плата Tyan S5533 в ITX-формате
Чтобы исключить влияние драйверов, запускаемых в сеансе операционной системы, наш тест будет «экстремально низкоуровневым», запускаться будем под DOS, а результаты контролировать путем просмотра дампа Memory Mapped I/O регистров контроллера USB.
Последовательность действий такова.
1) Воспользовавшись бета-версией утилиты USB.EXE разработки IC Book Labs, определим адрес блока конфигурационных регистров контроллера XHCI, в нашем примере это bus=0, device=14h, function=0. Также определим базовый адрес блока операционных регистров в пространстве Memory Mapped I/O, в нашем примере он равен F7500000h.
Рис 2. Результаты работы утилиты USB.EXE. Адрес блока конфигурационных регистров XHCI: bus=0, device=14h, function=0. Базовый адрес операционных регистров XHCI равен F7500000h.
2) Как известно, в целях совместимости с программным обеспечением, не поддерживающим контроллер USB 3.0 XHCI, на данной платформе, по умолчанию, порты USB 3.0 обслуживаются контроллером USB 2.0 EHCI. Наша задача – перевести их в режим обслуживания контроллером USB 3.0 XHCI. Воспользуемся документацией Intel 8 Series / С220 Series Chipset Family Platform Controller Hub Datasheet и любой утилитой, позволяющей редактировать содержимое регистров системной логики.
Программируем регистр USB 3.0 Port Routing Mask Register. Записываем по адресу bus=0, device=14h, function=0, register=0DCh байт со значением 0FFh.
Программируем регистр USB 3.0 Port Super Speed Enable Register. Записываем по адресу bus=0, device=14h, function=0, register=0D8h байт со значением 0FFh.
Рис.3. Регистр USB 3.0 Port Routing Mask Register
Рис.4. Регистр USB 3.0 Port Super Speed Enable Register
3) Считываем и расшифровываем согласно рис.5 и рис.6 исходное состояние нескольких битовых полей из младших 16-битов 32-битного регистра PORTSCNUSB3 до подключения устройства к исследуемому порту. Регистр находится по смещению 0570h от базового адреса блока операционных регистров контроллера, его адрес F7500000h+0570h=F7500570h
Прочитанное значение = 02A0h = 0000.0010.1010.0000b
D0=Current Connect Status=0. Устройство не подключено.
D1=Port Enabled/Disabled=0. Порт не используется.
D13=Port Speed=0000b. Скорость не определена.
Рис.5. Регистр USB 3.0 Port Status and Control Register, биты 4
Рис.6. Регистр USB 3.0 Port Status and Control Register, биты 13
4) Подключаем USB 3.0 флэшку, затем повторно считываем регистр и расшифровываем те же битовые поля.
Прочитанное значение = 1203h = 0001.0010.0000.0011b
D0=Current Connect Status=1. Устройство подключено.
D1=Port Enabled/Disabled=1. Порт используется.
D13=Port Speed=0100b. Скорость равна 5.0 Gbit/S, режим USB 3.0 Super Speed работает.
5) Для самоконтроля, подключаем USB 2.0 флэшку к тому же порту, затем повторно считываем регистр и расшифровываем те же битовые поля. Прочитанное значение = 02A0h, что соответствует отсутствию подключения. Так и должно быть, регистр PORTSCNUSB3 «не видит» USB 2.0 устройство, так как оно обслуживается другой подсистемой и статус подключения доступен посредством другого регистра – PORTSCNUSB2, рассмотрение которого выходит за рамки наших исследований.
Транзакции изохронных передач
Изохронные транзакции обеспечивают гарантированную скорость обмена, но не обеспечивают надежности доставки. По этой причине в протоколе отсутствуют подтверждения, поскольку повтор пакета приведет к сбою в планах доставки данных. Управление потоком, основанное на подтверждениях, отсутствует — устройство обязано выдерживать темп обмена, заявленный в дескрипторе изохронной конечной точки.
Транзакции изохронного вывода состоят из двух пакетов, посылаемых хост-контроллером, — маркера OUT и пакета данных DATA. В транзакции ввода хост посылает маркер IN, на который устройство отвечает пакетом данных, возможно, и с нулевой длиной поля данных (если нет готовых данных). Любой другой ответ устройства (как и «молчание») хостом расценивается как ошибка, приводящая к остановке данного канала.
При изохронном обмене имеется контроль достоверности (отбрасывание пакетов с ошибками) и целостности данных (обнаружение факта пропажи пакета). Контроль целостности основан на строгой детерминированности темпа обмена — в соответствии со своим дескриптором точка ожидает транзакцию с периодом 2bInterval–1 микрокадров. Для обычной изохронной конечной точки в микрокадре возможна лишь одна транзакция, и ошибка при приеме пакета выражается в отсутствии принятых данных в микрокадре, в котором они ожидаются. Таким образом, нумерация пакетов (переключатель Toggle Bit) не требуется. Полноскоростные устройства и хостконтроллеры должны посылать пакеты только типа DATA01. Для широкополосных изохронных конечных точек (USB 2.0) в каждом микрокадре возможна передача до трех пакетов данных. Любой из этих пакетов может потеряться, и для обнаружения этой ситуации требуется нумерация пакетов внутри микрокадра. Для этой нумерации введено два новых типа пакетов данных: DATA2 и MDATA. Многообразие типов пакетов кроме нумерации позволяет еще и информировать партнера по связи о своих планах на данный микрокадр. В транзакциях IN идентификатором пакета устройство указывает, сколько еще пакетов оно собирается выдать в том же микрокадре, что позволяет хосту не делать лишних попыток ввода. Так, если в микрокадре передается один пакет, то это будет DATA0; если два — последовательность будет DATA1, DATA0; три — DATA2, DATA1, DATA0. В транзакциях OUT для вывода не последнего пакета в микрокадре используется пакет MDATA (More Data), а идентификатор последнего пакета показывает, сколько было до него передано пакетов. Так, при одной транзакции вывода используется пакет DATA0, при двух — последовательность MDATA, DATA1, при трех — MDATA, MDATA, DATA2. Во всех транзакциях, кроме последней в микрокадре, должны использоваться пакеты максимального размера. Отметим, что между широкополосными транзакциями в микрокадре могут вклиниваться другие транзакции.
Аппаратный тест
Присмотревшись к разъему, за четырьмя «ближними» контактами, обеспечивающими поддержку USB 2.0, мы, как и ожидалось, обнаружили пять «дальних» контактов, используемых только в режиме USB 3.0 Super Speed. Измеряем сопротивление сигнальных линий USB 3.0 относительно земли, получаем значения, отличные от бесконечности. Вывод: контакты USB 3.0 физически присутствуют и не заканчиваются тупиком. Измерение выполнялось омметром на пределе, используемом для проверки полупроводниковых диодов. Для доступа к «дальним» контактам разъема USB 3.0 можно сконструировать переходник или воспользоваться тонким и длинным щупом, например иглой. Полученный результат является необходимым, но не достаточным условием функционирования устройства в режиме USB 3.0 Super Speed. Может случиться так, что сигнальные цепи заканчиваются терминирующими резисторами, но не подключены к контроллеру. Поэтому переходим к следующему тесту – программному.
Постановка задачи
В нашей тестовой лаборатории оказался USB Flash накопитель Kingston DataTraveler 3.0. Согласно информации производителя, устройство поддерживает USB 3.0. Проверим, так ли это на самом деле, не разбирая флешку и не нарушая гарантию.
Надёжность и транзакции для разных типов передач
Передачи массивов, прерываний и управления обеспечивают надежную доставку данных. После успешного приема пакета приемник данных посылает подтверждение — пакет квитирования ACK. Если приемник данных обнаружил ошибку, пакет игнорируется и никакого ответа на него не посылается. Источник данных считает, что очередной пакет передан успешно, когда получает от приемника подтверждение ACK. Если подтверждение не приходит, то в следующей транзакции источник повторяет посылку того же пакета. Однако пакет подтверждения может быть потерян из-за помехи; чтобы в этом случае повторная посылка пакета приемником не воспринималась как следующая порция данных, пакеты данных нумеруются. Нумерация ведется по модулю 2 (1-битный номер): пакеты делятся на четные (с идентификатором DATA0) и нечетные (DATA1). Для каждой конечной точки (кроме изохронных) у хоста и в устройстве имеются биты-переключатели (Toggle Bit), их начальные состояния тем или иным способом согласуются. В транзакциях IN и OUT передаются и ожидаются пакеты данных с идентификаторами DATA0 или DATA1, соответствующими текущему состоянию этих бит. Приемник данных переключает свой бит в случае безошибочного приема данных с ожидаемым идентификатором, источник данных — по приему подтверждения. Если приемник получает безошибочный пакет с неожидаемым идентификатором, он посылает подтверждение ACK, но данные пакета игнорирует, поскольку этот пакет — повторная посылка уже принятых данных.
Транзакции для различных типов передач имеют протокольные различия, обусловленные гарантированием или не гарантированием пропускной способности, времени отклика, надежности доставки и синхронизированности ввода и вывода. В зависимости от этих характеристик в транзакциях используются те или иные из вышеописанных протокольных механизмов. Отметим, что обнаружение ошибок передачи работает во всех транзакциях, так что данные, принятые с ошибкой, всегда игнорируются. Какие именно протокольные механизмы используются в текущей транзакции, «знает» и хост-контроллер (по ранее полученному дескриптору конечной точки), и устройство USB, в котором эта конечная точка реализована.
Резюме
Испытуемая флэшка действительно поддерживает режим USB 3.0.
Если формализовать и запрограммировать описанные действия в виде DOS-программы или UEFI-приложения, получится небольшая утилита, позволяющая быстро определить, в каком скоростном режиме работает USB устройство. Для упрощения нашего примера, мы реализовали его для частного случая – подсистемы USB платы Tyan S5533 и использования первого порта, поэтому адрес регистра PORTSCNUSB3 в нашем примере – константа. В общем случае, для того, чтобы программа была работоспособна на всех платформах, адрес регистра PORTSCNUSB3 должен вычисляться на основании содержимого полей XHCI Capabilities, в соответствии со спецификацией USB 3.0 XHCI. С другой стороны, достигнуть универсальности можно значительно проще и изящнее, используя UEFI-протоколы вместо прямого взаимодействия с регистрами контроллера.
Запросы, пакеты и транзакции
Читайте также: