usb — НТЦ Метротек. Архив блога http://blog.metrotek.spb.ru заметки бывших разработчиков бывшего НТЦ Метротек Thu, 02 Oct 2025 13:52:15 +0000 ru-RU hourly 1 https://wordpress.org/?v=5.1.15 USB сеть на Cortex-M3 http://blog.metrotek.spb.ru/2011/07/07/usb-set-na-cortex-m3/ Thu, 07 Jul 2011 06:35:42 +0000 http://blog.metrotek.spb.ru/?p=2849 В процессе разработки наших мега-дивайсов возник вопрос о реализации захвата пакетов с карты и использования ip-utils (ping/traceroute и тд) с карты.  Из нескольких возможных вариантов, было решено пойти средствами операционной системы и реализовать в дополнение к основному последовательному интерфейсу ещё и два сетевых (по количеству ethernet-портов модуля b5-gbe, для которого мы сейчас пишем софт).

Такой подход позволяет использовать стандартные средства ping и traceroute.

Для реализации сетевого интерфейса (как собственно и консоли карты) использовался любимый нами USB-шный класс CDC (Communication Device Class). В этот класс входят подклассы позволяющие реализовать интерфейсы к телефонным линиям, модемы и сетевые карты (проводные и беспроводные). Большим плюсом использования стандартного класса USB-устройства, является отсутствие необходимости писать драйвера (в Linux/*nix, Windows всё равно требует хотя бы .inf файл).

Так вот сетевых устройств в классе CDC может быть несколько видов. Это подклассы ECM,EEM, NCM и вариации на тему ACM (вместе с rndis), которые так любит windows. Устройства отличаются степенью поддержки операционной системы, степенью документированности и некоторыми другими особенностями.

Итак:

  • Rndis — нестандартная вариация на тему ACM. Вообще-то подкласс ACM — это последовательный порт или модем, но microsoft, традиционно наплевав на все имеющиеся стандарты создала собственный. Rndis, по своей сути, представляет собой реализацию ndis API поверх usb. Используется microsoft-ом и в КПК под windows mobile для синхронизации и связи с компьютером. Так как этот класс не полностью документирован, да и не стандартен — это не наш путь.
  • ECM — Ethernet Control Model — это реализация сетевой карты (в стандарте есть поддержка проверка состояния линка, мак-адрес карты хранится в дескрипторе и тд). Данный стандарт требует двух интерфейсов: для передачи данных и управляющего. За терминологией обращаться на usb.org или сюда: http://www.beyondlogic.org/usbnutshell/usb1.shtml. Вторая ссылка намного короче и более просто расписана :).
  • EEM — это Ethernet Emulation Model — в этом случае USB используется исключительно как транспорт ethernet пакетов. Состояние линка не передаётся, скорость не настраивается и так далее. Зато интерфейс просто и для него нужно только 2 endpoint-а.

Отсюда мы и подходим к выбору варианта сетевого интерфейса. Тут всё оказалось совсем просто — для реализации ECM нам просто не хватило доступных endpoint-ов в контроллере. Так что выбор остановился на EEM. Даже с ним, доступные 6 endpoint-ов, разделились полностью, и пришлось слегка обмануть реализацию консоли, указав в дескрипторе несуществующий endpoint.

Так вот, в stm32f105 есть 6 доступных endpoint-ов, не считая нулевого (по 3 IN и OUT). В итоге хватает впритык и резерва не остаётся. Для ECM уже endpoint-ов не хватает, так как под эту модель требуется по 3 endpoint-а на интерфейс.

Передача данных в модели EEM, или как же это заставить работать….

Для того, чтобы сетевое устройство с классом EEM зарегистрировалось в системе, достаточно правильно написать USB дескриптор. Создаётся интерфейс состоящий из двух bulk endpoint-ов, одного IN и одного OUT, ему приписывается класс CDC (0x02), подкласс EEM (0x0c), и протокол EEM (0x07). На этом все тонкости и заканчиваются. Пакеты в EEM передаются как есть, в виде ethernet фреймов, с дописанным в начале двухбайтным заголовком.

Выглядит он так:

Биты
15 14 13-0
Команда/данные CRC — используется или  fake Длина кадра

Пятнадцатый бит определяет — является ли этот кадр данными идущими в интерфейс или служебной командой EEM. Всего есть 6 команд, из которых обязательными являются только Echo и Echo response. (Хотя как выяснилось, линуксовый драйвер, даже без реализации разбора этих команд вполне нормально работает).

Четырнадцатый бит определяет, используется ли реальный подсчёт CRC, или на месте CRC передаётся последовательносьт 0xdeadbeef.

Оставшиеся биты кодируют длину фрейма следующего за этими двумя байтами заголовка.

После реализации разбора заголовков, приём и передача заработали без проблем, за исключением того, что USB-шная библиотека от ST не позволяет реализовать USB-transfer длинее чем размер FIFO в stm32, а ethernet пакеты в EEM нельзя разбивать между transfer-ами.
Таким образом, сейчас реализован приём и передача пакетов до 254 байт длиной. Пропускная способность не измерялась.

]]>
USB: новый интерфейс и проблемы со скоростью. http://blog.metrotek.spb.ru/2010/12/01/usb-novyiy-interfeys-i-problemyi-so-skorostyu/ Wed, 01 Dec 2010 20:32:37 +0000 http://blog.metrotek.spb.ru/?p=2503 Вероятно, среди читателей нашего блога найдутся люди, которым в целях общего развития или из-за практических нужд будет интересно узнать: «Как организовать на USB-устройстве новый интерфейс?». На удивление, не так сложно. Сложнее заставить его работать как следует.

Про наши наработки в этом направлении сейчас и будет рассказано.

Приступить к созданию второго USB-интерфейса на нашей измерительной карте-анализаторе потока E1 для измерительного же прибора «Bercut MMT» b4.5 нас заставила, само собой, необходимость. Дело в том, что одна из функций b4.5 — это анализ протоколов сигнализации, таких как ОКС 7, EDSS. Сбором трейсов занимается карта, а их анализом — платформа b4.5. Анализ может проводиться и в реальном времени, а значит, перед нами встала задача организации интерфейса между картой и платформой. Этот интерфейс должен был позволять передавать в реальном времени данные со скоростью 120 кбайт/с. А физически карта и платформа могут общаться только посредством USB. И, на момент решения задачи, уже успешно общались! Так почему же новый интерфейс?

Дело в том, что:

  1. Интерфейс, который уже существовал, — текстовый. Он предназначен для обмена командами между картой и платформой, сбора результатов измерений и так далее. Но данные протоколов сигнализации изначально представлены в бинарном виде. Зачем их конвертировать в текстовый?
  2. Проблема скорости. Справедливости ради, 120 кбайт/с — не такая уж большая скорость, что-то около одного Мбит/с, однако существующий интерфейс USB Serial не давал и этого. USB, используемая на нашей карте, может работать в режиме full speed, то есть теоретический предел скорости для нее — 12 Мбит/с. Практическая же скорость — порядка 30-35 кбит/с. Разница — в 3 порядка, и этого совершенно недостаточно для решаемой задачи. К счастью, нет необходимости в двухстороннем обмене между платформой и картой, как подразумевается для USB serial. Нам необходим только поток от карты на b4.5.

Было решено все же организовать примитивный второй интерфейс и измерить скорость на нем.

Итак, как же создать интерфейс для USB? И что такое интерфейс в терминах USB? Хорошим подспорьем послужил вот этот ресурс.
Но здесь и сейчас в двух словах мы опишем основные моменты.

Основное понятие для USB — endpoint. Это окончание канала данных, которое может быть источником или приемником информации. Каждый endpoint работает только в одном направлении. Но для описания устройства одних endpoint’ов недостаточно.

Всякое USB-устройство описывается некоторой совокупностью дескрипторов. Эти дескрипторы образуют иерархию.
На самом высоком уровне иерархии — Device Descriptor. Здесь хранится информация о производителе устройства, серийном номере устройства и другая самая общая информация. Он у каждого устройства один.
Следующий — Config Descriptor. Здесь содержится в основном информация о режимах питания устройства. Их может быть несколько, но одновременно активный в каждый момент времени — один.
Config Descriptor’у соответствуют Interface Descriptor’ы — совокупность endpoint’ов, выполняющих определенную функцию. Вот почему речь и идет об организации еще одного интерфейса: обмен командами и сбор трейсов сигнализации — совершенно разные функции! Более понятный пример — МФУ принтер/сканер/копир, подключенное к PC по одному USB-интерфейсу. Каждой функции такого МФУ, очевидно, будет соответствовать свой Interface Descriptor. Понятно, что в пределах одной конфигурации Interface descriptor’ов может быть много, и нет ограничения на то, сколько из них будут активными.
И, наконец, каждый Interface Descriptor содержит в себе один или несколько Endpoint Descriptor’ов. Эти дескрипторы описывают, что за endpoint используется в составе данного интерфейса( то есть его номер ), каково его направление и режим работы.

Так вот, первое, что Вы должны сделать, чтобы организовать новый интерфейс — это создать соответствующие дескрипторы. Без них хост просто не узнает, какие возможности есть у вашего устройства.

Второе, что нужно, — собственно реализовать процедуры обмена по этому интерфейсу. В нашем случае это вылилось в дописывание драйвера для микроконтроллера карты. Это достаточно интересно, но здесь описываться не будет — все, в конечном итоге, упирается в изучение Datasheet’ов.

А третье — это драйвер на хосте. К счастью, тут на помощь пришла замечательная библиотека libusb. Она позволяет работать напрямую с endpoint’ами, которые в Linux отображаются в /dev/bus/usb/… К счастью, они там видны, если на устройстве есть нужный дескриптор. Кстати, при помощи libusb можно легко искать устройство по его изготовителю, серийному номеру, каким-то другим описанным в дескрипторах параметрам. Да и организация обмена тоже очень удобно реализуется.

В конечном итоге, тест все-таки был проведен. С нового endpoint’a безо всякой обвязки посылались двоичные данные на хост, и программа на хосте проверяла их целостность и измеряла скорость. Полученное значение приятно удивило — 500 кбайт/с. То есть не 12 Мбит/с, конечно, но на несколько порядков больше прошлого результата и вполне достаточно для передачи трейсов.
В последствии тестовая программа была доведена до ума, интегрирована в проект, и теперь второй интерфейс существует и работает.

В чем же была проблема? Источников несколько:

  1. USB Serial. Он очень тормозил передачу. К большому сожалению, на настоящий момент я не могу точно указать место в коде, которое приводило к такому замедлению обмена, но ясно одно — реализация USB Serial может быть улучшена, если понадобится.
  2. Способ вывода. Поскольку программа для измерения скорости была тестовой, перваой информацией, которая передавалась от карты к хосту, была фраза «Hello, world!» (думаю, никого это не удивит). Выводилась она в текстовом виде. И скорость обмена была порядка 375 кбайт/с. После того, как данные стали выдаваться в двоичном виде, она увеличилась до 500 кбайт/с. Весьма ощутимый прирост. Впрочем, это и неудивительно. Было ожидаемо, что вывод данных в текстовом виде создает большую нагрузку на процессор.
  3. Хостовая часть. После отладки на PC тест повторили с платформой b4.5, и скорость упала опять до 375 кбайт/с. ( на платформе Colibri PXA320, он послабее, чем почти 2-гигагерцовый Celeron ). Так что не во всем карта виновата.
  4. И, наконец, самое главное. Почему же не 12 Мбит/с. Дело в том, что USB-пакеты перед отправкой буферизируются. Максимальный размер пакета равен 64 байта, а буфер под хранения пакетов может вмещать в себе и 2, и 4, и 8, и так далее. До 16 килобайт. В самом простом случае буфер содержит в себе один пакет. При такой длине буфера упрощается процедура обмена по USB, но страдает скорость. И это как раз наш случай.

Что ж, для наших нужд скорости USB вполне хватает, а если нам потребуется больше — мы знаем, в каком направлении двигаться, и, если придется, заставим шину работать как следует. Но пока — есть к чему стремиться.

]]>
Загружаем прошивку в Stm32f105 по USB http://blog.metrotek.spb.ru/2010/04/14/zagruzhaem-proshivku-v-stm32f105-po-usb/ http://blog.metrotek.spb.ru/2010/04/14/zagruzhaem-proshivku-v-stm32f105-po-usb/#comments Wed, 14 Apr 2010 05:55:58 +0000 http://blog.metrotek.spb.ru/?p=1875 Отладочная плата После того, как фирма Atmel подкачала со сроками поставок процессоров Sam3U встал вопрос о выборе нового процессора. Выбор пал на семейство процессоров stm32f10x от фирмы ST Microelectronics, а конкретно — на процессор stm32f105. Одним из особенностей этого процессора является то, что он может загружать в себя прошивку через USB-интерфейс по протоколу DFU (используя собственный загрузчик, находящийся в ROM).

DFU — или Device Firmware Upgrade — это протокол для обновления прошивок по USB. Главные его преимущества в том, что он определён спецификацией USB и в том, что он достаточно прост. Вот только реализация этого протокола от ST оказалась не совсем стандартной. В результате вместо того, чтобы использовать готовую утилиту из проекта OpenMoko (dfu-util), её пришлось переписывать.

Утилита умеет загружать прошивку в RAM и FLASH, и запускать её на исполнение.

Ах, да, самое главное  — исходники лежат здесь.

]]>
http://blog.metrotek.spb.ru/2010/04/14/zagruzhaem-proshivku-v-stm32f105-po-usb/feed/ 4