Usb msc что это

Настройки связи через USB: что такое режим MSC?

Не знаете, когда использовать режим MSC?

Это метод связи (протокол), используемый для передачи файлов. MSC специально разработан для передачи данных через интерфейс USB. Обычно это используется между USB-устройством (например, MP3-плеером) и компьютером.

Просматривая настройки вашего портативного устройства, вы, возможно, уже видели эту опцию. Если ваш MP3-плеер/портативное устройство поддерживает его, вы обычно найдете его в меню настроек USB. Не все устройства, которые вы подключаете к USB-портам вашего компьютера, будут поддерживать MSC. Вы можете обнаружить, что вместо этого используется какой-то другой протокол, например, MTP.

Несмотря на то, что стандарт MSC более старый и менее функциональный, чем более интуитивный протокол MTP, на рынке все еще есть множество потребительских электронных устройств, которые его поддерживают.

Этот режим передачи через USB иногда называют UMS (сокращение от USB Mass Storage ), что может сбивать с толку. Но это одно и то же.

Какие типы оборудования могут поддерживать режим MSC?

Примерами типов потребительских электронных устройств, которые обычно поддерживают MSC, являются:

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

Когда вы подключаете USB-устройство к вашему компьютеру, который находится в режиме MSC, оно будет отображаться как простое устройство хранения, которое, скорее всего, будет отображаться только с назначенной ему буквой диска. Это отличается от режима MTP, когда аппаратное устройство контролирует соединение и отображает удобное для пользователя имя, такое как: Sansa Clip +, 8Gb iPod Touch и т. Д.

Недостатки режима MSC для цифровой музыки

Как упоминалось ранее, устройство, находящееся в режиме передачи MSC, будет рассматриваться как обычное запоминающее устройство, например флэш-накопитель. Если вы хотите синхронизировать цифровую музыку, тогда это не лучший режим USB для использования.

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

Еще одним недостатком MSC является то, что он не поддерживает защиту от копирования DRM. Для воспроизведения песен с защитой от копирования DRM, которые вы загрузили из онлайновой службы подписки на музыку, вам нужно будет использовать режим MTP на портативном медиаплеере, а не на MSC.

Это связано с тем, что метаданные по лицензированию музыки необходимо будет синхронизировать с портативным компьютером, чтобы воспроизводить песни по подписке, аудиокниги и т. Д. Без этого файлы не будут воспроизводиться.

Преимущества использования MSC

Есть моменты, когда вы захотите использовать устройство в режиме MSC, а не более полнофункциональный протокол MTP. Например, если вы случайно удалили некоторые из своих файлов песен, вам понадобится программа для восстановления файлов, чтобы восстановить ваши MP3. Однако устройство, находящееся в режиме MTP, будет контролировать соединение, а не операционную систему вашего компьютера. Это не будет выглядеть как обычное устройство хранения данных, поэтому ваша программа восстановления, вероятно, не будет работать.

MSC имеет преимущество в этом сценарии, потому что его файловая система будет доступна так же, как обычный съемный диск.

Другое преимущество использования режима MSC состоит в том, что он более универсально поддерживается различными операционными системами, такими как Mac и Linux. Для использования более продвинутого протокола MTP на компьютере, отличном от Windows, может потребоваться установка стороннего программного обеспечения. Использование режима MSC устраняет необходимость в этом.

Источник

USB Mass Storage Device — что это?

Usb msc что это. 190901064238. Usb msc что это фото. Usb msc что это-190901064238. картинка Usb msc что это. картинка 190901064238USB Mass Storage Device — устройство, которое чаще всего является флешкой. Быстрый запуск диспетчера устройств: зажмите Win + R, введите команду devmgmt.msc, нажмите ОК.

Данное устройство вы можете увидеть в диспетчере задач, может быть например в разделе Universal Serial Bus controllers:

Usb msc что это. 190901063007. Usb msc что это фото. Usb msc что это-190901063007. картинка Usb msc что это. картинка 190901063007

Если напротив нет восклицательного знака, значит винда флешку нормально увидела и проблем нет. Однако бывает что проблем нет, винда определила.. но неправильно.. в таком случае нужно шаманить с драйверами..

Хм, есть мысль, что если устройство неправильно обнаружено или если оно с воскликом — тогда может попробовать прогу по автоматической установки драйверов? Нет, я не рекламирую и не предлагаю какую-то ерундовину. Я лично пользовался DevID Agent, мне понравилось — вроде нет рекламы, все понятно, прога небольшая. Если будете ставить, то смотрите чтобы вместе с ней и Яндекс-софт не установился..

Нашел скриншот — получается USB Mass Storage Device может представлять из себя меню, раскрыв которое, вы увидите модель флешки:

Usb msc что это. 190901063409. Usb msc что это фото. Usb msc что это-190901063409. картинка Usb msc что это. картинка 190901063409

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

Usb msc что это. 190901063527. Usb msc что это фото. Usb msc что это-190901063527. картинка Usb msc что это. картинка 190901063527

Надеюсь кому-то инфа помогла. Удачи и добра, до новых встреч господа!

Источник

Передача данных в портативных мультимедиа-плеерах: Mass Storage

В предыдущей статье мы попытались описать тот хаос, который творился в 1998-2003 гг. в области протоколов сопряжения плееров с ПК. Период 2003-2004 гг. стал для отрасли временем упорядочения. Множество ручейков проприетарных протоколов сменилось тремя стройными потоками. Точнее, двумя с половиной, т.к. два из этих потоков представляли собой вариации одного и того же протокола.

Чистый Mass Storage использовался наибольшим количеством производителей, особенно компаниями небольшого калибра из Кореи или Китая. В России он стал наиболее популярным протоколом. О нем наш сегодняшний рассказ.

Для обозначения Mass Storage «в быту» используются две аббревиатуры – MSC и UMS. MSC (Mass Storage Class) является официальной, а UMS (возможны варианты расшифровки: USB/Universal Mass Storage) – «народной». Друг другу они не противоречат, а скорее дополняют.

MSC сообщает о том, что протокол входит в число утвержденных стандартных «классов устройств» в рамках спецификации USB и тем самым является индустриальным стандартом де-юре. UMS говорит об универсальности протокола, который на сегодня поддерживается большинством операционных систем и бесчисленным множеством конечных устройств, что делает его стандартом и де-факто. Вариант расшифровки UMS как USB Mass Storage дополняет эту информацию, уточняя, что в качестве физической линии используется интерфейс USB. Буквы MS (Mass Storage), общие для всех аббревиатур, показывают, что перед нами протокол, предназначенный для работы с устройствами хранения больших объемов данных. Именно для них и был разработан данный стандарт – для «флэшек», карт-ридеров, мобильных HDD-накопителей. Как он попал в портативные плееры?

Usb msc что это. MassStorage. Usb msc что это фото. Usb msc что это-MassStorage. картинка Usb msc что это. картинка MassStorage

Протокол Mass Storage задумывался в первую очередь для подобных устройств. Его появление в MP3-плеерах было вынужденным шагом

В прошлых материалах мы неоднократно говорили о том, как стихийно, неожиданно появились и начали развиваться портативные аудиоплееры. Индустрия просто не хотела их замечать, сначала в силу их маргинальности, позже – из-за надуманной связи этих устройств с цифровым пиратством. Это имело много последствий, и одним из них было то, что плееры «обошли» при раздаче классов устройств USB.

Взглянем на список этих классов: тут есть и внешние звуковые карты, и коммуникационные устройства, и отдельный класс для периферии типа мышей и клавиатур, есть свои классы для принтеров, USB-хабов, вэб-камер, адаптеров беспроводной связи. Свой класс есть и для цифровых камер. И только аудио- и мультимедиа-плееры остались в категории «прочие».

Usb msc что это. classes. Usb msc что это фото. Usb msc что это-classes. картинка Usb msc что это. картинка classes

Среди стандартных классов USB нашлось место для самых разных устройств. Но только не для мультимедиа плееров

Добрых лет пять никто не задумывался о разработке отдельного класса для них. Производителям оставалось выбирать из того, что есть.

На этом фоне MSC/UMS был единственным универсальным решением. Если ограничивать задачи исключительно «тупой» загрузкой контента в плеер, то ничего больше и не нужно. К тому же, протокол позволял превратить плеер в мобильный накопитель. Простые продавцы и покупатели и сейчас описывают плееры с данным протоколом как «работающие как флешка», «подключающиеся как флеш-накопитель» «программы ставить никакие не надо», «можно файлы хранить» и т.д. и т.п.

Usb msc что это. MP3stick. Usb msc что это фото. Usb msc что это-MP3stick. картинка Usb msc что это. картинка MP3stick

Простенький плейдрайв – «MP3-Stick» и Mass Storage протокол – созданы друг для друга

Эта дополнительная возможность хорошо вписывалась в подход «много-в-одном», выбранный азиатскими производителями MP3-плееров. Именно они стали пионерами в адаптации MSC/UMS в аудиоплееры. Они и компания Sigmatel, чья платформа STMP3400 в начале 2003 года начала поддерживать этот протокол.

Usb msc что это. STMP3400. Usb msc что это фото. Usb msc что это-STMP3400. картинка Usb msc что это. картинка STMP3400

Январь 2003 года – Sigmatel объявляет о поддержке Mass Storage в своих платформах D-Major

Достоинства протокола. Главное – простота: все операции осуществляются через стандартные файловые оболочки, в т.ч. Windows Explorer (Проводник), никакие дополнительные знания или обучение для работы с ним не требуются.

Распространенность – уже Windows Me и 2000 имели базовую поддержку протокола, Windows XP поддерживал его полностью. Множество других ОС – MacOS, Linux и т.п. – совместимы с Mass Storage.

Usb msc что это. OS support. Usb msc что это фото. Usb msc что это-OS support. картинка Usb msc что это. картинка OS support

ОС, в том или ином виде поддерживающие Mass Storage протокол

Сегодня сложнее найти ПК, не поддерживающий этот протокол. Поддержка в данном случае означает наличие драйверов протокола в составе операционной системы.

Usb msc что это. drivers. Usb msc что это фото. Usb msc что это-drivers. картинка Usb msc что это. картинка drivers

Mass Storage плеер на 1.8” жестком диске Toshiba подключен к ПК. Как MSC-устройство он использует стандартный драйвер USBSTOR.SYS, входящий в состав ОС. Как накопитель он также использует стандартные драйверы Windows. Установка дополнительных драйверов не требуется.

Так как вся работа с контентом также ведется стандартными средствами, через Windows Explorer (Проводник), у пользователя вообще не возникает необходимости в установке чего бы то ни было: вся поддержка протокола уже встроена в ОС.

Usb msc что это. storage. Usb msc что это фото. Usb msc что это-storage. картинка Usb msc что это. картинка storage

Плеер виден в Проводнике Windows как еще один жесткий диск. Вся работа с контентом ведется в Проводнике или любом файловом менеджере на выбор пользователя. Установка дополнительного программного обеспечения не требуется

Получается настоящий Plug-and-Play: вынул из коробки, подключил и пользуйся. По таким параметрам, как прозрачность, невидимость для пользователя этот протокол просто не имеет равных.

С точки зрения совместимости с портативными устройствами у нас тоже все хорошо: протокол не зависит от файловых систем и может работать с любой из них, если она поддерживается ОС.

Немаловажным является существование спецификации USB host (on the go), позволяющей подключать Mass Storage устройства к другим портативным (и не портативным) аппаратам. Сегодня MSC-совместимый плеер можно подключить к обширному перечню устройств, будь то игровая приставка, стереосистема, автомагнитола, FM-трансмиттер, другой плеер.

Usb msc что это. FM transmitter. Usb msc что это фото. Usb msc что это-FM transmitter. картинка Usb msc что это. картинка FM transmitter

Набирают популярность автомобильные FM-трансмиттеры, позволяющие подключать к себе любой Mass Storage плеер

Недостатки протокола являются продолжением его достоинств. Его функциональность является базовой, примитивной. Фактически он не способен ни на что, кроме копирования данных взад-вперед.

Но данные, с которыми имеет дело плеер, являются больше чем просто набором двоичных символов, это контент. У каждой единицы контента, будь то песня или файл, есть целый ряд свойств, таких, как название, формат, автор, продолжительность и т.п. Отдельные единицы могут быть частью более сложных совокупностей, таких, как альбом, плей-лист.

Ни о чем подобном Mass Storage знать не знает, что возлагает все заботы о менеджменте контента либо на пользователя, либо на встроенное ПО плеера. Последнее же чаще всего не способно эффективно справляться с задачей управления большим количеством контента. Как следствие, большинство MSC/UMS-плееров имеют крайне бедный механизм навигации – по папкам, аналогично навигации в Windows Explorer. При этом не используется значительный объем информации, содержащийся в метаданных, тэгах, который удобен для классификации контента.

Usb msc что это. id3. Usb msc что это фото. Usb msc что это-id3. картинка Usb msc что это. картинка id3

Информация, которая может содержаться в тэгах (на примере программы MP3tag). Мало что из этого используется в Mass Storage плеерах

Пользователь вынужден организовывать свой контент самостоятельно, с помощью системы вложенных папок. При этом, избрав, к примеру, систему классификации «песня-альбом-автор», он не сможет быстро и безболезненно перейти к системе «песня-жанр» или «песня-год записи», ему придется перетряхивать всю библиотеку.

Очень слаба по своим возможностям организация таких плеерах плей-листов. Плей-лист обычно возможен только один. Работа с плей-листами возложена исключительно на само устройство, и если через ПК в режиме MSC/UMS был удален один из файлов, входящих в плей-лист, это может нарушить работу всего листа в целом. Такая премиум-возможность, как отображение обложки альбома (Album Art или Jacket), «чистым» MSC/UMS-плеерам недоступна в принципе. Теоретически ее можно реализовать загрузкой графического файла из папки, но на практике никто этого пока не сделал. А если сделает, пользователю придется вручную рассовывать во все папки соответствующие картинки. Некоторые плееры имеют возможность отображения слов песни (Lyrics), но берутся эти слова не из метаданных: пользователю приходится самостоятельно подготавливать их с помощью специальной программы.

Во всем этом главная проблема Mass Storage. Плеер – это больше, чем просто мобильный накопитель, для эффективной работы он должен иметь глубокое понимание того, что, собственно, хранится в его памяти. Будучи современным мультимедийным устройством, рассчитанным на самый широкий круг пользователей, он не может просто пробубнить подряд все, что на него записано. Он должен уметь рассказать о том, что мы смотрим или слушаем, причем кратко, исчерпывающе и ненавязчиво, как высококлассный конферансье. Он, словно опытный библиотекарь, должен помочь нам быстро найти среди тысяч песен именно то, что нам нужно, даже если мы подзабыли название. Во всем этом предельно ограниченный в своих возможностях протокол MSC/UMS ему не помощник. И свежий зажигательный шлягер, и кандидатская диссертация, и своп-файл Windows для него являются лишь безликими массивами данных. Это превращает протокол в своего рода обезличивающее «бутылочное горлышко» между двумя мощными мультимедиа-системами – плеером и ПК. На плечи последних падает вся тяжесть преобразования безликого потока информации в удобную для пользователя форму.

На ПК все зависит от самого пользователя: проявит он усидчивость и изобретательность – организует музыкальную библиотеку на зависть всем. А может и просто сваливать все в одну папку, пока там не станет совершенно невозможно что-то найти.

На плеере же все зависит от разработчика, а они вовсе не горят желанием прилагать большие усилия для разработки мощной программной начинки. В результате конферансье из таких плееров так себе – монотонным голосом он прочитает название песни, автора, в лучшем случае – альбома. А может и вовсе только имя файла.

Usb msc что это. MSC face 1. Usb msc что это фото. Usb msc что это-MSC face 1. картинка Usb msc что это. картинка MSC face 1

Интерфейс iPod по сравнению с интерфейсом Mass Storage плеера iriver h300 выглядит более спартанским, но при этом отображает значительно больше информации о проигрываемом треке. При этом плеер от iriver – это еще относительно удачный пример Mass Storage плеера

И библиотекарь он никудышный – так, рукой направление укажет, где искать, но не более.

Usb msc что это. MSC face 2. Usb msc что это фото. Usb msc что это-MSC face 2. картинка Usb msc что это. картинка MSC face 2

Пользователь Mass Storage плеера (Cowon X5 в данном случае, слева) при поиске интересующей композиции может руководствоваться только логикой папок и файлов, созданной им самим. В случае применения иных решений (как в Creative Zen Touch, справа) у них есть возможность свободного поиска по параметрам

Есть отдельные исключения (например, плееры от Archos), но их не много.

Эта ситуация имеет очень простое следствие. Пользователи, которые с компьютером «на ты», привыкшие к концепции файлов и папок, не сильно требовательные к внешним эффектам и быстро приспосабливающиеся к новому, стоят горой за чистый Mass Storage. Прозрачность, открытость и распространенность протокола для них преимущества, рядом с которыми меркнут все минусы.

Usb msc что это. MSC legends. Usb msc что это фото. Usb msc что это-MSC legends. картинка Usb msc что это. картинка MSC legends

Компании iriver и Cowon своей популярностью среди определенных слоев покупателей обязаны не в последнюю очередь поддержке «свободного» Mass Storage

А вот пресловутые «обычные» пользователи не очень довольны. Для них плеер – это все-таки не флэшка, не хранилище для файлов, а плеер. Аккуратно сооружать пирамиду файлов и папок музыкальной библиотеки у них нет никакого желания, бродить в недрах этой пирамиды на экране плеера, ориентируясь лишь на названия папок, – тоже. Навигация по метаданным, проигрывание с красивым Album Art, автоматическая загрузка на плеер новых песен – все это им гораздо ближе. Значительное количество возвращенных в магазин и обменянных на iPod-ы MSC/UMS-плееров в тех же Соединенных Штатах – тому подтверждение.

Usb msc что это. NonMSC leaders. Usb msc что это фото. Usb msc что это-NonMSC leaders. картинка Usb msc что это. картинка NonMSC leaders

И все же тон в отрасли задают производители, не использующие чистый Mass Storage

Есть и еще одна категория недовольных протоколом. Это студии звукозаписи и киностудии. Безразличный ко всему, Mass Storage уж точно никак не сможет отличить «пиратский» трек от честно приобретенного. Производитель, плееры которого поддерживают загрузку контента через «чистый» Mass Storage, вряд ли могут рассчитывать на плодотворное сотрудничество с крупными лейблами. Конечно, небольшим компаниям оно не очень-то и нужно. Но крупные корпорации, желающие дать пользователям вертикальное решение, включая приобретение контента, вынуждены принимать этот фактор во внимание.

В результате производитель, желающий создать плеер, который:

– вынужден искать решения за рубежами возможностей «чистого» Mass Storage.

Источник

CDC+MSC USB Composite Device на STM32 HAL

Usb msc что это. image loader. Usb msc что это фото. Usb msc что это-image loader. картинка Usb msc что это. картинка image loader

Мне хотелось бы верить, что хотя бы половина читателей может расшифровать хотя бы половину названия статьи 🙂 Кто не в курсе — поясню. Мое устройство должно реализовывать сразу две USB функции:

Я буду описывать создание композитного USB устройства на базе микроконтроллера STM32, но сам подход будет также применим и для других микроконтроллеров. В статье я детально разберу каждый из классов по отдельности, так и принцип построения композитных устройств. Но обо все по порядку.

Немного теории

Интерфейс USB очень сложный, многоуровневый и многогранный. С наскоку его не осилить. В одной из статей (забыл, правда, в какой) видел фразу в стиле “прочитайте эту статью 2 раза, а потом на утро еще раз”. Да, он такой, с первого раза точно не осилишь. Лично у меня интерфейс более-менее разложился по полочкам только через пару месяцев активного копания и чтения спецификаций.

Я по прежнему не являюсь экспертом в USB, а потому рекомендовал бы обратиться к статьям, которые бы детальнее рассказали суть происходящего. Я лишь укажу на самые важные места и вкратце поясню как оно работает — по большей части во что вляпался сам. В первую очередь я бы рекомендовал Usb in a nutshell (перевод), а также USB Made Simple (сам не читал, но многие рекомендуют). Также нам понадобятся спецификации для конкретных классов USB устройств.

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

Устройство описывает себя с помощью нескольких дескрипторов разного типа:

Еще нужно понимать, что USB это хост ориентированный протокол. Настройка устройства, прием, передача — все в USB управляется со стороны хоста. Для нас это означает, что со стороны микроконтроллера нет никакого потока управления — вся работа с USB построена на прерываниях и обратных вызовах (callback). А это, в свою очередь, означает что нам не желательно запускать долгоиграющие операции и нужно быть очень аккуратными при взаимодействии с другими прерываниями (учитывать приоритет, и все такое прочее). Впрочем, попробуем не опускаться на такой низкий уровень.

Также хост-ориентированность проявляется еще и в названии функций. В терминологии USB направление от хоста к устройству называется OUT, хотя для контроллера это прием. И наоборот, направление от устройства к хосту называется IN, хотя для нас это означает отправку данных. Так что в микроконтроллере функция DataOut() на самом деле принимает данные, а DataIn() — отправляет. Но это так, к слову — мы будем пользоваться уже готовым кодом.

CDC — виртуальный COM порт

Наверное взять и сразу наваять композитное устройство целиком не выйдет — слишком много нюансов и подводных камней. Я думаю лучше будет сначала отладить каждый интерфейс в отдельности, а потом переходить к композитному устройству. Начну с CDC, т.к. он не требует никаких зависимостей.

Я недавно переехал на STM32 Cube — пакет низкоуровневых драйверов для STM32. В нем есть код по управлению USB с реализацией отдельных классов USB устройств. Возьмем шаблонные реализации USB Core и CDC и начнем пилить под себя. Заготовки лежат в директории \Middlewares\ST\STM32_USB_Device_Library. Я использую Cube для контроллеров серии STM32F1, версия Cube — 1.6 (Апрель 2017), версия библиотеки USB из комплекта — 2.4.2 (декабрь 2015)

Шаблонная реализация библиотеки подразумевает написание собственного кода в файлах с названием template. Без понимания всей библиотеки и принципов работы USB это сделать достаточно сложно. Но мы пойдем проще — сгенерируем эти файлы с помощью графического конфигуратора CubeMX.

Реализация предоставленная CubeMX готова к работе прямо из коробки. Аж даже немного обидно, что не пришлось писать никакого кода. Придется изучать CDC на примере полностью готовой реализации. Давайте взглянем на самые интересные места в сгенерированном коде.

Для начала заглянем в дескрипторы, которые находятся в файлах usbd_desc.c (дескриптор устройства) и usbd_cdc.c (дескрипторы конфигурации, интерфейсов, конечных точек). В статье usb in a nutshell (на русском) есть очень детальное описание всех дескрипторов. Не буду описывать каждое поле в отдельности, остановлюсь лишь на самых важных и интересных полях.

Тут нас интересуют такие поля:

Тут нам интересно следующее:

В этом интерфейсе живет только одна конечная точка (bNumEndpoints). Но прежде идет серия функциональных дескрипторов — настроек специфичных для данного класса устройств.

Тут сказано, что наше устройство не знает о понятии “звонок” (в смысле звонок по телефону), но при этом понимает команды параметров линии (скорость, стоп биты, DTR/CTS биты). Последний дескриптор описывает какой из двух интерфейсов CDC является управляющим, а где бегают данные. В общем, тут нам ничего не интересно и менять мы ничего не будем.

Тут сказано, что эта конечная точка используется для прерываний. Хост будет опрашивать устройство раз в 0x10 (16) мс с вопросом а не требует ли устройство внимания. Также через эту конечную точку будут ходить управляющие команды.

Описание второго интерфейса (там где данные бегают) будет попроще

В интерфейсе живут 2 конечные точки типа bulk — одна на прием, вторая на передачу. На самом деле в терминологии USB это одна конечная точка, просто двухсторонняя.

Как это все работает объяснять не буду, хотя бы потому что сам до конца не понимаю (например как хост узнает сколько данных нужно забирать со стороны устройства). Самое главное, что библиотека все реализует за нас. Давайте лучше посмотрим на архитектуру.

Библиотека USB от ST весьма слоиста. Я бы выделил такие архитектурные уровни

Эта функция инициализирует USB периферию микроконтроллера. Интереснее всего тут серия вызовов функции HAL_PCDEx_PMAConfig(). Дело в том, что на борту микроконтроллера находится цельных 512 байт памяти отведенных специально под буферы USB (эта память называется PMA — Packet Memory Area). Но поскольку заранее устройству неизвестно сколько будет конечных точек и какие будут их параметры, то эта память не распределена. Поэтому перед работой с USB память нужно распределить согласно выбранным параметрам.

Но вот что странно, объявляли только 2 конечные точки, а вызовов 5. Откуда взялись лишние? На самом деле лишних тут нет. Дело в том, что у каждого USB устройства обязательно должна быть одна двусторонняя конечная точка, через которую устройство инициализируется, а потом управляется. Эта конечная точка всегда имеет номер 0. Этой функции инициализируются не конечные точки, а буфера. Для нулевой конечной точки создаются 2 буфера — 0x00 на прием и 0x80 на передачу (старший бит указывает направление передачи, младшие — номер конечной точки). Оставшиеся 3 вызова описывают буфера для конечной точки 1 (прием и передача данных) и конечной точки 2 (прием команд и отсылка статуса — это происходит синхронно, поэтому буфер один)

Последний параметр в каждом вызове указывает смещение буфера конечной точки в общем буфере. На форумах видел вопросы «а что это за магическая константа 0x18 (начальный адрес первого буфера)?». Я детально рассмотрю этот вопрос позже. Сейчас лишь скажу, что первые 0x18 байт PMA памяти занимает таблица распределения буферов.

Но это все кишки и другие внутренности. А что снаружи?

Пользовательский код оперирует функциями приема и передачи, которые находятся в файле usbd_cdc_if.c. Чтобы устройство могло отправлять данные в виртуальный COM порт в сторону хоста нам предоставили функцию CDC_Transmit_FS()

С приемом чуть сложнее: ядро USB будет дергать функцию CDC_Receive_FS() по мере приема данных. В эту функцию нужно дописать свой код, который будет обрабатывать принятые данные. Или вызывать коллбек, который будет заниматься обработкой, например так:

Обращаю внимание, что эти функции работают с массивами байт без какой либо структуры. В моем случае мне нужно было отправлять строки. Чтобы это было делать удобно я написал аналог функции printf, которая форматировала строку и отправляла ее в порт. Чтобы повысить скорость я также озадачился двойной буферизацией. Подробнее тут в разделах “USB с двойной буферизацией” и “printf”.

Еще в этом же файле находятся функции инициализации/деинициализации виртуального COM порта, а также функция изменения параметров порта (скорость, четность, стоп биты и прочее). Реализация по умолчанию не ограничивает себя в скорости и это меня устраивает. Инициализация так же хороша. Оставим все как есть.

Финальный штрих — код, который это все запускает

Тут по очереди инициализируются разные уровни драйвера. Последняя команда включает USB прерывания. Важно понимать, что вся работа с USB происходит по запросу от хоста. В этом случае внутри драйвера вызывается прерывание, которое в свою очередь либо само обрабатывает запрос, либо делегирует это другому коду через коллбек.

Чтобы это все заработало нужен драйвер со стороны операционной системы. Как правило это стандартный драйвер и система может подхватить устройство без особой процедуры инсталляции. Насколько я понимаю у меня в системе уже был установлен Virtual COM Port драйвер от STM (поставился с ST Flash Utility) и мое устройство подхватилось самостоятельно. На линуксе также все завелось с полпинка.

MSC — запоминающее устройство

С драйвером CDC было все просто — устройство, как правило, само является конечным потребителем данных (например получает от хоста команды) или же генератором (например отправляет хосту показания датчиков).

С Mass Storage Class будет чуток сложнее. Драйвер MSC является всего лишь прослойкой между хостом и шиной USB с одной стороны, и запоминающим устройством с другой. Это может быть SD карта подключенная по SDIO, SPI Flash, может быть RAM Drive, дисковый накопитель, а может быть даже сетевой диск. В общем, в большинстве случаев запоминающее устройство будет представлено неким драйвером (как правило нетривиальным), который нам нужно будет состыковать с реализацией MSC.

В моем устройстве используется SD карта, подключенная через SPI. Для доступа к файлом на этой карте я использую библиотеку SdFat. Она также разделена на несколько уровней абстракции:

Реализация MSC требует от хранилища определенного интерфейса — уметь читать и писать, отдавать свой размер и статус. Примерно такие же возможности предоставляет интерфейс драйвера SD карты библиотеки SdFat. Остается лишь написать адаптер, который приведет один интерфейс к другому.

С направлением движения определились. Займемся реализацией. Я опять воспользовался конфигуратором CubeMX и сгенерировал нужные файлы для компонента USB. Изучение начнем, конечно же, с дескрипторов.

Дескриптор устройства практически не изменился. Разница только в полях, определяющих класс устройства — теперь класс устройства в целом не задан (нули в bDeviceClass), а будет задаваться на уровне интерфейса (это требование спецификации ).

Очень похоже на аналогичный дескриптор из CDC — определяется количество интерфейсов (1) и параметры питания от шины (до 100 мА)

Дескриптор интерфейса объявляет 2 конечных точки (по одной в каждую сторону передачи). Также дескриптор определяет какой именно это подкласс Mass Storage — Bulk Only Transport. Я не нашел толкового описания что же именно это за подкласс такой. Предполагаю, что это устройство, которое общается только посредством двусторонней передачи данных через 2 конечные точки (тогда как другие модели могут использовать еще и прерывания). Протоколом в этом общении являются SCSI команды.

Тут определяются 2 конечные точки типа Bulk — интерфейс USB не гарантирует скорость по таким конечным точкам, зато гарантирует доставку данных. Размер пакета устанавливается в 64 байта.

Раз уж мы говорим про конечные точки, то стоит заглянуть в файл usbd_conf.c где определяются соответствующие PMA буфера

Теперь посмотрим на MSC с другой стороны. Этот USB класс принимает от хоста команды на чтение/запись и транслирует их специализированный интерфейс — USBD_StorageTypeDef. Нам остается только подставить свою реализацию.

Поскольку это C, а не C++, то каждая их этих записей — указатель на соответствующую функцию. Как я уже говорил, нам нужно написать адаптер, который будет приводить интерфейс MSC к интерфейсу SD карты.

Начнем реализовывать интерфейс. Первой идет функция инициализации

Так SD карту можно было бы инициализировать прямо отсюда, если бы это была быстрая операция. Но в случае SD карты это может быть не всегда так. К тому же не стоит забывать, что эти все функции являются коллбеками и вызываются из прерывания USB, а прерывания надолго блокировать не стОит. Поэтому я вызвают функцию initSD() прямо из main() перед инициализацией USB, а SD_MSC_Init() у меня ничего не делает

Может показаться, что слишком много разных драйверов, но позвольте я напомню архитектуру. Класс SdSpiCard из библиотеки SdFat знает как общаться с SD картой через SPI, когда и какую команду послать и какой ждать ответ. Но он не знает как работать с самим SPI. Для этих целей я написал класс SdFatSPIDriver, который реализует общение с картой по SPI и передачу данных через DMA.

Реализация SD_MSC_GetCapacity() тривиальна — SdSpiCard умеет возвращать размер карты сразу в блоках

Чтение и запись также реализована вполне просто.

Карта у нас всегда готова (хотя в будущем я буду пристальнее смотреть на статус) и не защищена от записи.

LUN — Logic Unit Number. Теоретически наше запоминающее устройство может состоять из нескольких носителей (например жесткие диски в рейде). Все функции SCSI протокола указывают с каким носителем оно хочет работать. Функция GetMaxLun возвращает номер последнего устройства (количество устройств минус 1). Флешка у нас одна потому возвращаем 0.

Если честно, я особо не разобрался зачем оно нужно. Заглянув в спецификацию SCSI я увидел очень много полей смысла, которых я не понял. Из того, что я осилил – тут описывается стандартное устройство с прямым (не секвентальным) доступом, причем которое может быть извлечено (removable). Благо во всех примерах, которые я видел этот массив совпадает, так что пускай будет. Отлажено ведь.

Теперь все это нужно правильно проинициализировать

Подключаем, проверяем. Все работает, правда очень медленно — подключенный диск открывается секунд 50. Отчасти это из-за того, что линейная скорость чтения флешки через такой интерфейс получается около 200кб/с. Когда USB Mass Storage устройство подключается к компьютеру, операционная система вычитывает таблицу FAT. Я использую флешку на 8 гиг, а там FAT аж 7.5 мегабайт. Плюс чтение MBR, бут сектора, таблицы файлов — вот и получается почти 50 сек.

Также мне пришлось отключить DMA при работе с SD картой – там не все так просто с его включением. Дело в том, что моя реализация драйвера (как оказалось) не может работать из прерывания, а в USB все только через прерывания и работает. Не работает даже банальный HAL_Delay() т.к. он тоже завязан на прерывания, не говоря уже о синхронизации с использованием FreeRTOS. Это нужно будет переделать, но это отдельная история и к USB composite device она не относится. Как переделаю — обязательно напишу об этом статью и оставлю тут линку.

UPDATE: как и обещал вот линка. Удалось прокачать скорость до 650кб/с

CDC + MSC Composite Device

А теперь со всей этой фигней мы попробуем взлететь (С) анекдот

Итак, мы уже знаем как строить USB устройства, которые могут реализовывать либо CDC либо MSC. Попробуем сделать композитное устройство, которое реализует оба интерфейса одновременно. Я посмотрел несколько других проектов, которые реализовывали композитное USB устройство и, как мне кажется, их подход имеет смысл. А именно: реализовать собственный драйвер класса, который будет реализовывать и ту и ту функциональность.

Структура USB устройства будет такая:

Для удобства использования объявим в коде номера конечных точек и интерфейсов.

Нумерация конечных точек повторяет нумерацию интерфейсов. Будем использовать №1 для MSC, №2 для управления CDC, №3 для передачи данных через CDC. Есть еще нулевая конечная точка для общего управления устройством, но она обрабатывается в недрах ядра USB и объявлять эти номера не обязательно.

Интерфейс USB библиотеки от ST оставляет желать лучшего. В некоторых случаях номера конечных точек используются с флагом направления передачи — установленный старший бит означает направление IN — в сторону хоста (я для этого завел константу IN_EP_DIR). При этом другие функции используют просто номер конечной точки. В отличии от оригинального дизайна я предпочел разделить эти все номера и использовать правильные константы в нужных местах. Там где используются константы с суффиксом EP_IDX флаг направления передачи не используется.

ВАЖНО! Хоть по спецификации USB номера конечных точек могут быть какими угодно, все же лучше расположить их последовательно и в том же порядке, в котором они объявляются в дескрипторах. Мне это знание далось неделей жесткого дебага, когда виндовый USB драйвер упорно ломился не в ту конечную точку и ничего не работало.

Начнем как обычно с дескрипторов. Большая часть дескрипторов будут жить в нашей реализации класса (usbd_msc_cdc.c), но дескриптор устройства и кое какие глобальные штуки определены в ядре USB в файле usbd_desc.c

В целом тут все тоже самое, отличаются только поля, которые определяют класс устройства (bDeviceClass). Теперь эти поля указывают, что это композитное устройство. Хосту нужно будет потрудится, разобраться во всех остальных дескрипторах и подгрузить правильные драйвера для каждого из компонентов. Поле bDeviceProtocol означает, что части композитного устройства будут описываться специальным дескриптором – дескриптором ассоциации интерфейсов (Interface Association Descriptor). О нем чуть ниже.

Дескриптор конфигурации примерно такой же как и раньше, разница только в количестве интерфейсов. Теперь у нас их 3

Далее идет объявление интерфейса и конечных точек для MSC. Не знаю почему именно в таком порядке (сначала MSC потом CDC). Так было в одном из примеров, которые я нашел, оттуда и скопировал. По идее порядок интерфейсов не имеет значения. Главное, чтобы они возили все свои дополнительные дескрипторы рядом. Ну и приколы с нумерацией конечных точек также имеют значение.

Дескрипторы MSC ничем не отличаются от тех, что были в предыдущем разделе.

А вот дальше идет новый тип дескриптора — IAD (Interface Association Descriptor) – дескриптор ассоциации интерфейсов. Ассоциация тут не в смысле организации, а в смысле какой интерфейс с какой функцией ассоциировать.

Этот хитрый дескриптор говорит хосту что описание предыдущей функции USB устройства (MSC) закончилось и сейчас будет совсем другая функция. Причем тут же указано какая именно — CDC. Также указано количество связанных с ней интерфейсов и индекс первого из них.

IAD дескриптор не нужен для MSC, т.к. там всего один интерфейс. Но IAD нужен для CDC чтобы сгруппировать 2 интерфейса в одну функцию. Об этом сказано в спецификации этого дескриптора

Наконец дескрипторы CDC. Они полностью соответствуют дескрипторам для одиночной CDC функции с точностью до номеров интерфейсов и конечных точек

Когда все дескрипторы готовы можно посчитать суммарный размер конфигурации.

Перейдем к написанию кода. Ядро USB общается с драйверами классов используя вот такой интерфейс

В зависимости от состояния или события на шине USB ядро вызывает соответствующую функцию.

Любую архитектурную проблему можно решить введением дополнительного абстрактного слоя… (С) еще один анекдот

Разумеется мы не будем реализовывать весь функционал целиком — за реализацию классов CDC и MSC будет отвечать существующий код. Мы лишь напишем прослойку, которая будет перенаправлять вызовы либо в одну, либо в другую реализацию.

Тут все просто: инициализируем (деинициализируем) оба класса. Вызываемые функции сами займутся созданием/удалением своих конечных точек.

Пожалуй самой сложной функцией будет Setup.

Это коллбек на один из стандартных запросов по шине USB, но этот запрос очень многогранный. Это может быть как получение данных (get), так и установка (Set). Это может быть запрос к устройству в целом, к одному из его интерфейсов или конечных точек. Также тут может приплыть как стандартный запрос, определенный базовой спецификацией USB, так и специфичный для определенного устройства или класса. Подробнее тут (Раздел “Пакет Setup”).

Из-за обилия разных случаев структура обработчика пакета Setup весьма сложна. Тут не получается написать один if или switch. В коде ядра USB обработка размазана по 3-4 большим функциям и в определенных случаях передается отдельному специализированному обработчику (коих там еще с десяток). Радует только то, что на уровень драйвера класса передается только незначительная часть запросов.

Я подсмотрел какие пакеты ходят через эту функцию и, похоже, можно ориентироваться по получателю. Если получатель пакета интерфейс — в поле wIndex будет номер интерфейса, если конечная точка, то в wIndex будет номер конечной точки. Исходя из этого перенаправляем запросы в соответствующий обработчик.

Кстати, чтобы это работало нужно не забыть поменять дефайн, определяющий количество интерфейсов, а то запрос просто не дойдет и срежется внутри ядра USB

Коллбеками DataIn и DataOut все проще. Там есть номер конечной точки — по ней и определим куда запрос перенаправлять

Обратите внимание, что флаг направления передачи в номере конечной точки не используется. Т.е. даже если некоторые функции используют MSC_IN_EP (0x81), то в этой функции нужно использовать MSC_EP_IDX (0x01).

Иногда данные приходят в нулевую конечную точку и для этого есть специальный коллбек. Я не знаю что бы я делал, если бы оба класса (и CDC и MSC) имели обработчики на этот случай – в таком запросе не указан интерфейс или номер конечной точки. Было бы невозможно понять кому адресован запрос. Благо такой запрос умеет обрабатывать только класс CDC – вот ему и отправим

Больше у нас не будет нетривиальных обработчиков. Есть еще парочка геттеров для дескрипторов, но их код стандартный и не представляет интереса. Заполним «таблицу виртуальных функций»

Теперь код инициализации

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

Дело вот в чем. Каждый класс имеет некоторое количество приватных данных – состояние драйвера, какие то переменные, которые должны быть доступны в разных функциях драйвера. Причем это не могут быть просто глобальные переменные – они привязаны к конкретному USB устройству (иначе невозможно было бы оперировать сразу с несколькими устройствами, если такое необходимо). Поэтому в хендле USB завели сразу несколько полей для такого случая

Проблема в том, что каждый класс считает эти поля своей собственностью и цепляет туда свою структуру.

Решать это можно несколькими способами. Товарищи отсюда вообще затолкали в свою реализацию класса весь код из обоих драйверов (CDC и MSC) чтобы на ходу разбираться что к чему. Другой подход в том, что в эти поля класть структуры, в которых есть место для данных обоих классов. Тут частично использован этот подход, вдобавок еще часть данных перенесена в глобальные переменные (что ок, если у нас только один USB порт)

Мы, пожалуй, пойдем путем попроще. Если драйверы классов хотят эксклюзивных полей – дадим им эти поля

Во-первых, я дал каждому классу свои поля – пусть терзают их как хотят. Во-вторых, я назвал эти поля согласно тому что в них реально лежит – никакая там не UserData, а указатель на интерфейс.

Конечно же на плюсах это было бы красивее и элегантнее (при том же расходе памяти и проца). но и на C можно сделать по человечески. Раз уж я запустил свои ручонки в структуру хендла, то и поменял непонятные void * на человеческие типы (кстати, поле void * pData теперь оно по человечески называется pPCDHandle с соответствующим типом). И const тоже расставил где надо. Пришлось, правда, повозиться с forward declarations.

Про организацию проекта. В некоторых IDE проект может быть построен следующим образом. Библиотека USB и исходники драйверов классов поставляются вместе с STM32 Cube, но часть файлов предлагается написать пользователю. Может так случится, что библиотека лежит где нибудь в общей локации и используется несколькими проектами. Стоит понимать, что я сейчас мы меняем код библиотеки USB и потому лучше иметь собственную копию, чтобы никому не мешать.

Конечно же переименования полей должны отразится в коде драйвера. Но тут как раз все просто – контекстная замена решает проблему.

Тут главное не переборщить. Я вот менял руками, просматривая каждое использование. Там я нашел «баг» в коде, зачинил его а потом 3 дня дебажился в попытке понять почему оно не работает.

Вот тут было все правильно – проверяем pClassData, а обращаемся к pClass. Если «починить» (проверять pClass), то работать не будет. Т.е. pClassData является своеобразным маркером того, что класс проинициализирован.

Возвращаясь к нашему драйверу. Поскольку Init() инициализирует обе переменные pClassDataXXX, то в этом коде можно проверять любую.

UPDATE: Важный нюанс, подмеченный пользователем fronders.
В оригинальных реализациях классов (CDC, HID, MSC, и почти всех остальных) в функциях инициализации (например USBD_CDC_Init() ) буфер для поля pClassDataXXX выделяется с помощью USBD_malloc(), который в шаблонной реализации является дефайном на malloc(). Вроде как ничего особенного — выделили кусок и используем его адрес.

Но, в некоторых проектах (в т.ч. в примерах от самой STMicroelectronics) решили сэкономить на памяти и написали свою реализацию аллокатора

В принципе такой подход работать будет, но только пока у нас только один класс устройства. Как только несколько классов попробуют «выделить» память через такой аллокатор — все сломается, т.к. несколько классов будут терзать один и тот же буфер.

На самом деле именно выделять память нужно будет только в случае если вы строите устройство с несколькими одинаковыми функциями — например устройство которое реализует два и более CDC. Ну может быть это еще понадобится в некоторых экзотических случаях, когда интерфейсы создаются и удаляются на лету. Во всех остальных случаях (коих подавляющее большинство) я бы не заморачивался с выделением памяти и распределил буфер статически. У себя в проекте я сделал так (заодно и типы данных побелил-покрасил):

Финальный штрих – распределение PMA буферов

Для наших конечных точек потребуется 7 буферов — 2 на нулевую конечную точку (точку управления), 2 на MSC и 3 на CDC. Но самое интересное тут — начальные адреса (последний параметр). По непонятной причине этот нюанс тщательно обходится всеми туториалами. В даташите написано про распределение буферов в PMA и как это выглядит на на уровне регистров, но вот как пользоваться соответствующими функциями из HAL информации нет. Восполним этот пробел.

Итак. У контроллера есть специальная память — PMA (Packet Memory Area). Это такая память куда программа может записать данные, а USB периферия их прочитать (и наоборот). Память эта заранее не распределена, т.к. разные конечные точки могут быть настроены на разный размер пакета. Поэтому существует таблица BTABLE в которой указано где какой буфер размещается. Причем сама эта таблица также размещается в PMA. Таблицу можно двигать и размещать в любом месте PMA, но HAL умеет ее размещать только в самом начале.

Usb msc что это. image loader. Usb msc что это фото. Usb msc что это-image loader. картинка Usb msc что это. картинка image loader
Картинка из Reference Manual микроконтроллеров серии STM32F103

Итак, как же высчитать смещения буферов? Размер таблицы напрямую зависит от количества используемых конечных точек. Каждая конечная точка в таблице представлена записью из 4 16-битных значений (по 2 на прием и 2 на передачу, даже если одно из направлений не используется). У нас используется 4 конечных точки — нулевая, MSC и две для CDC (не путайте с количеством буферов — у нас их 7 — по два на конечную точку, но одна точка однонаправленная, поэтому у нее только один буфер). Значит размер таблицы будет 4 точки * 4 записи * 2 байта = 32 байта.

Как я уже сказал HAL умеет располагать только вначале PMA области. Значит первый буфер мы можем расположить только по смещению 0x20 (32 байта — размер таблицы). Буферы для конечных точек можно размещать где угодно в PMA памяти, лишь бы они не налазили друг на друга. Каждая конечная точка определяет максимальный размер пакета, который она готова обрабатывать, буфер должен быть равен или больше этого размера.

Я расположил буфера с шагом 64 байта (максимальный рекомендуемый размер буфера для устройств USB Full Speed), но для некоторых конечных точек можно было бы и меньше. Так по управляющей CDC конечной точке много данных не бегает (CDC_CMD_PACKET_SIZE равно 8 байт), поэтому и буфер можно делать всего на 8 байт. Впрочем, мне было не жалко и 32 байт — просто чтобы круглые цифры получались.

Пора компилировать и запускать. Моя винда сразу определила само устройство, увидела также и 2 составляющие. Это хорошая новость. Но есть и плохая. Если Mass Storage устройство определилось сразу, то CDC — нет.

Usb msc что это. image loader. Usb msc что это фото. Usb msc что это-image loader. картинка Usb msc что это. картинка image loader

Не беда — нужно просто подсунуть винде правильный драйвер. Вообще-то устройство стандартное и специальный драйвер не нужен. Достаточно просто связать это устройство со стандартным драйвером (в нашем случае это будет usbser.sys)

На самом деле я в этой кухне не очень разбираюсь. По идее нужно скачать STMicroelectronics Virtual COM Port драйвер с сайта ST. Драйвер устанавливается в C:\Program Files (x86)\STMicroelectronics\Software\Virtual comport driver, а внутри есть файлик stmcdc.inf — вот он то нам и нужен. В этом файле в двух секциях есть строка вида

Вот она то и связывает наш VID/PID c драйвером устройства. Только этого мало — нужно еще указать номер интерфейса, который управляет CDC. В моем случае это первый интерфейс (нулевой отвечает за MSC). Для этого строка должна выглядеть так

На самом деле оригинальную строку можно не менять, а просто
добавлять строки в соответствующие секции.

После всех приготовлений находим нерабочее устройство в списке устройств, просим обновить драйвер, указываем директорию где лежит inf файл и вуаля — драйвер установлен. Винда сама присвоит этому устройство имя COMxx — можно брать любимую терминалку и открывать этот COM порт.

С линуксом все проще — там все заводится без танцев с бубном драйверами.

UPDATE от fronders: в Windows10 также все заводится самостоятельно. Более того, сами ST не рекомендуют для 10ки свой vcp драйвер а предлагают использовать стандартный.

Заключение

На некоторых форумах видел сообщения вроде “как все в этом USB сложно, какие-то драйверы… Я щас лучше на регистрах нафигачу”. Ребят, не все так просто. Уровень регистров это, наверное, самая простая часть. Но помимо нее есть огромный пласт логики, которую должно реализовывать устройство. И вот тут уже без знаний протоколов и многих сотен страниц спецификаций никак.

Но не все так плохо. Люди уже позаботились и написали всю логику. В большинстве случаев остается только подставить нужные значения и подправить некоторые параметры. Да, библиотека от ST — тот еще монстр. Но после вдумчивого прочтения USB In A Nutshell, парочки спецификаций конкретного класса устройств и работы со сниффером многие вещи становятся на свои места. Библиотека начинает выглядеть более-менее стройно. Можно даже сравнительно небольшими усилиями сделать кастомный драйвер класса, что мы с успехом и сделали.

Я делал реализацию композитного CDC+MSC устройства, но примерно такой же подход можно применить и для других комбинаций — CDC+HID, MSC+Audio, CDC+MSC+HID и других. Моя реализация предназначена для работы на микроконтроллерах серии STM32F103, но сам принцип может быть адаптирован и для других микроконтроллеров (в т.ч. и не STM32).

В этой статье я не ставил себе задачу рассказать как работает USB во всех деталях — во-первых есть статьи и книги, которые рассказывают это лучше (я затронул лишь малую часть), а во-вторых очень много вещей лучше черпать из первоисточников (спецификаций).

Вместо пересказа спецификаций я попробовал описать как работает реализация USB стека от ST. Также я постарался обратить внимание на особые моменты и рассказать почему делается именно так.

Я долго сомневался ставить ли галочку “Tutorial”. С одной стороны я даю рекомендации и пошаговые инструкции, обращаю внимание на особые моменты и даю ссылки на первоисточники. С другой стороны я не могу предоставить готовую библиотеку для скачивания и встраивания в свои проекты.

Дело в том, что в процессе работы над своим проектом я хорошенько поработал напильником, лобзиком и другими инструментами над этой библиотекой. Я выкинул много кода, который в моем устройстве не нужен, часть поменял, починил некоторые вещи, которые мне не нравились. Теперь библиотека USB весьма серьезно отличается от той, что выложена на сайте ST. Некоторые из изменений специфичны для моего проекта и могут не подойти для других ситуаций. Впрочем, добро пожаловать в мой репозиторий — изучайте, копируйте к себе, задавайте вопросы, предлагайте улучшения.

Напоследок хочу высказать благодарность всем тем, кто мне так или иначе помогал с моей реализацией. Спасибо, ребята!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *