Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: как передать максимум данных по USB ?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Интерфейсы
NikP
В описании работы USB в режиме Bulk сказано, что макс. размер пакета 64 байта для этого режима. Мне надо передать 4 К данных. Так как данные передаются фреймами 1 мс, то получается, что на передачу 64 байтов уходит 2 мс (фрейм 1 мс - запрос от хоста, фрейм 1 мс - пакет данных), т.е. на 4096 байтов -128 мс. Другими словами, максимальная реальная скорость передачи данных - 32 К / сек. И это всё, что можно выжать из заявленных 12 Мбит/с для full speed? Явно что-то я не учёл, где ошибка, как на практике передавать данные с максимальной скоростью?
aaarrr
Цитата(NikP @ Dec 15 2012, 21:57) *
Явно что-то я не учёл, где ошибка, как на практике передавать данные с максимальной скоростью?

В одном фрейме не обязательно передается только один пакет.
Xenia
Цитата(NikP @ Dec 15 2012, 21:57) *
В описании работы USB в режиме Bulk сказано, что макс. размер пакета 64 байта для этого режима.


Это видимо про контрольную точку было сказано, а у той, что данные сливает, должно быть больше.

Даже старушка AT90USB647, и та имеет размер буфера под 1-ю end-point до 256 байт. И это, заметьте, в режиме двойного буферования! Т.е. на самом деле там по меньшей мере два таких буфера, что позволяет одному заполняться в то время, пока с другого идет передача. А у современных МК предельный размер буфера должен быть еще больше.

Впрочем, про своё железо вы ничего не пишите, а стало быть и обуждать этот вопрос нечего.
Pat
Цитата(NikP @ Dec 15 2012, 19:57) *
Так как данные передаются фреймами 1 мс, то получается, что на передачу 64 байтов уходит 2 мс (фрейм 1 мс - запрос от хоста, фрейм 1 мс - пакет данных), т.е. на 4096 байтов -128 мс.


А зачем запрос от хоста? Настраиваете канал передачи типа BULK и Хост будет сам ловить ваши данные и запихивать их в буфер потом только успевай их из буфера доставать и новый подсовывать.
По крайней мере это так для реализации Хоста типа OHCI.

Хост контроллер планирует транзакции в кадре (фрейме) и распределяет полосу.
Полоса распределяется следующим образом.
Вначале идут до определенного времени непереиодические передачи типа Controlи BULK.
Затем передачи прерываний после них изохронные передачи и если еще осталось время в кадре то снова передаем BULK и Control.

Другими словами если у вас на хосте висит одно устройство и оно передает только BULK то весь канал будет отдан ему и только ему.
Поэтому вы получите Full Speed за минусом накладных расходов на заголовки пакетов и прочее.


=AK=
Цитата(NikP @ Dec 16 2012, 04:27) *
В описании работы USB в режиме Bulk сказано, что макс. размер пакета 64 байта для этого режима. Мне надо передать 4 К данных. Так как данные передаются фреймами 1 мс, то получается, что на передачу 64 байтов уходит 2 мс


В течении одного фрейма устройство может передать по балку до 19 пакетов данных, т.е. до 1.2к. Для этого должны выполняться два условия:
- Другие устройства, если они есть, молчат и не пытаются передать что-то свое в то же время
- Устройство обслуживает запросы быстро. Если устройство замешкается, то планировщик хоста отложит обмен и продолжит его в следующем фрейме.

Второе условие является наиболее критическим. Чтобы его выполнить, желательно обрабатывать запросы по прерываниям и использовать двойной буфер ("пинг-понг"), мгновенно подставляя заранее подготовленый пакет.
NikP
Я делаю устройство на SiLabs C8051F320 (для определённости). В принципе, там есть ЕР3 с буфером 512 байт (можно использовать двойную буферизацию - 2х256). Прошу подсказать , как организуется передача нескольких пакетов за фрейм? И что за это отвечает - драйвер или компьтерная программа , которая работает с устройством? Я считал до сих пор, что передачу инициирует хост своим запросом. В ответ устройство передаёт из In Еndpoint пакет данных объёмом , который задаётся при конфигурировании устройства, т.е. это задаёт программист . И объём этот не может быть больше величины фифо Еndpoint, из которой идёт передача. Или это не так?
Задача возникла из того, что сделали систему сбора информации, где 4 К данных собираются за 10 мкс в микросхему памяти. Как то обидно , когда основное время устройство тратит на передачу, а не на сбор и первичную обработку данных. Фирмвару и программу писали по образцу примера, который был приведён фирмой Cygnal (непосредственным разработчиком C8051F320).
=AK=
Цитата(NikP @ Dec 17 2012, 03:38) *
там есть ЕР3 с буфером 512 байт (можно использовать двойную буферизацию - 2х256).

Вот и используйте двойную, режим "пинг-понг". Тогда ваш проц автоматически будет по очереди подставлять буфера по мере поступления запросов.

Цитата(NikP @ Dec 17 2012, 03:38) *
как организуется передача нескольких пакетов за фрейм? И что за это отвечает - драйвер или компьтерная программа , которая работает с устройством?

Хост контроллер. Это организовано на программном и аппаратном уровне, максимально близко к железу. Еще до всяких драйверов, на более низком уровне. Пользователя к этому ни под каким видом не подпускают.

Цитата(NikP @ Dec 17 2012, 03:38) *
Я считал до сих пор, что передачу инициирует хост своим запросом. В ответ устройство передаёт из In Еndpoint пакет данных объёмом , который задаётся при конфигурировании устройства, т.е. это задаёт программист . И объём этот не может быть больше величины фифо Еndpoint, из которой идёт передача. Или это не так?

Это так. Вот только запросов за один фрейм может быть много, на FS - до 19 штук, см. спецификацию USB 2.0 Table 5-9. Full-speed Bulk Transaction Limits. И если устройство в ответ на запрос мгновенно начинает выдавать пакет, то планировщик хоста не выкидывает его из очереди, а перекачивает пакет и дает новый запрос. А пока пакет перекачивается, устройство должно успеть заполнить второй буфер. Если не успеет, то в ответ на очередной запрос хоста оно (т.е. его SIU, тоже на низком уровне, аппаратно) ответит NACK-ом, и планировщик хоста в этом фрейме данных с него больше запрашивать не будет.

При 12 Мбит/сек пакет в 64 байта передается за 42.6 мкс. Если ваш девайс жует сопли и не успевает заполнять второй буфер за это время, то вместо 1.2 Мбайт в секунду будете иметь скорость перекачки 64 кбайт в секунду, или даже меньше.
Alex11
И еще надо учитывать, как работает верхняя программа в PC. Если она запрашивает 64 байта, дожидается ответа и запрашивает следующие, то скорость также будет очень маленькая. Для большой скорости передачи нужно сразу запрашивать данные большим куском.
NikP
Спасибо за советы! Дело сдвинулось после конфигурирования под двойную буферизацию ЕР3 (пробовали 2х128 и 2х256) и изменения верхней программы, всё заработало , скорость возросла . Не так, как хотелось, но с этим будем разбираться дальше. При этом проявилась новая напасть. При запросе верхней программой 1К и 2К (а мне надо 4К) всё работает, при запросе 4К - комп падает в синий экран. По сообщению - ошибка обслуживания USB. Посмотрели исходник драйвера (предоставленный Силабом) - там заполняется некий буфер 4096 байт - вроде должно хватать. Попробовали немного подредактировать драйвер - эффект остался. В чём может быть причина?
=AK=
Цитата(NikP @ Dec 19 2012, 03:32) *
комп падает в синий экран.

Наверняка это баг в драйвере. Написать драйвер без ошибок очень сложно. Поэтому я предпочитаю использовать драйверы класса, которые входят в комплект поставки Винды. Судя по всему ваша задача нормально ляжет под CDC. Тогда ваша прикладуха будет просто работать с виртуальным COM портом. Правда, в Винде и этот драйвер не без греха, он начинает портить данные при передаче массивов размером более 8К. Но он хотя бы не падает.
геннадий75
Цитата(=AK= @ Dec 19 2012, 07:06) *
Наверняка это баг в драйвере.

А почему сразу баг. Если вы передаёте пакеты по 64 байта, драйвер их собирает и ждёт окончания запросов (неполный пакет или нулевой пакет) если его небудет он заполнит свой буфер (по умолчанию 4к) и только после этого отдаст данные в windows. Данные нужно выставлять на отправку сразу после пакета sof и заканчивать нулевым пакетом в пределах кадра.
NikP
Мы пробовали передавать пакеты по 128 и 256 байт. По идее, драйвер должен набрать заданные разработчиком драйвера 4К (или меньше- сколько запросили из прикладной программы) и отдать их прикладной программе. Я писал, что когда программа просит 1К и 2К - всё работает (при пакетах и 128, и 256 байт). При запросе 4К- синий экран. Проверили "кривой" вариант- запросили 3К - всё рухнуло. Что может происходить?
=AK=
Цитата(геннадий75 @ Dec 19 2012, 13:29) *
А почему сразу баг.

По статистике вообще большинство BSOD происходит из-за багов в драйверах,. А уж когда падает при отладке девайса с каким-то подозрительным драйвером - то уж точно из-за бага в драйвере. Иначе не получишь BSOD.

Цитата(геннадий75 @ Dec 19 2012, 13:29) *
Если вы передаёте пакеты по 64 байта, драйвер их собирает и ждёт окончания запросов (неполный пакет или нулевой пакет) если его небудет он заполнит свой буфер (по умолчанию 4к) и только после этого отдаст данные в windows.

Это где-то описано СиЛабсом, или вы из головы придумываете?

Цитата(геннадий75 @ Dec 19 2012, 13:29) *
Данные нужно выставлять на отправку сразу после пакета sof и заканчивать нулевым пакетом в пределах кадра.

С нормальными драйверами таких ограничений нет.

Цитата(NikP @ Dec 19 2012, 14:28) *
Мы пробовали передавать пакеты по 128 и 256 байт.

Пакеты должны быть того размера, какой прописан в дескрипторе и задан при настройке. Если вы задали 64 байта, то и посылать должны кусками не более 64 байт. Трудно предсказать что произойдет, если вы будете стараться впихнуть пакеты 128 или 256 байт в трубу размером 64 байта. У вас, наверное, в процессоре SIU с ума сходит, после чего и драйвер в конце концов падает. Ведь вы же на FS работаете, а не на HS? На FS максимальный размер пакета 64 байта.

При трубе 64 байта вы свой файл 4К должны кусочками по 64 байта закидывать в буфера. Последний кусок должен иметь длину 0 байт, это означает, что транзакция закончена.
NikP
Все варианты сделаны честно: при переходе на другой размер пакета переделываем всё ( т.е. для пакета 128 байт перешиваем контроллер и переделываем прикладную программу и т.д.). Во всех вариантах с разными размерами пакетов пока верхняя программа требует 2 К и меньше - работа идёт, требует 4К - синий экран.
=AK=
Цитата(NikP @ Dec 19 2012, 20:06) *
Все варианты сделаны честно: при переходе на другой размер пакета переделываем всё ( т.е. для пакета 128 байт перешиваем контроллер и переделываем прикладную программу и т.д.).

Я в принципе не способен понятть, что это за "честность" такая, если вы в трубу с размером пакета 64 байта (а в FS больше этого не бывает в принципе) пытаетесь всунуть пакет 128 байт. Хост контороллер ни при каких обстоятельствах не будет запрашивать пакет размером больше 64 байт. А у вас в буфере после этого останется еще кусок информационного мусора в 64 байта. И как SIU вашего микроконтроллера будет себя после этого вести - никто вам не скажет, разве что к гадалкам пойдете.

Неудивительно, что СиЛабовский драйвер в ситуации, когда SIU девайса ведет себя неадекватно, не способен долго жить и в конце концов падает. Формально говоря это баг, но я их понимаю - они не могут разруливать все варианты варварского изнасилования USB.
NikP
Ну эксперименты с размером пакета мы начали после ответа :
Цитата(Xenia @ Dec 15 2012, 22:26) *
Это видимо про контрольную точку было сказано, а у той, что данные сливает, должно быть больше.

По-моему, если бы было принципиальное ограничение на 64 байта в пакете, то все другие варианты просто-напросто не работали бы, а у нас данные идут при различных вариантах конфигурирования контроллера и соответствующих изменений программы.
Но суть не в этом. При размере пакета 64 байта - та же ерунда: предельный размер остаётся 2К.
=AK=
Цитата(NikP @ Dec 19 2012, 22:16) *
Ну эксперименты с размером пакета мы начали после ответа :

В FS размера трубы больше 64 байт нет в принципе, читайте спецификацию USB. Это в HS можно назначить трубы большего размера. А ваш проц работает на FS, так что завязывайте с экспериментами.

Цитата(NikP @ Dec 19 2012, 22:16) *
По-моему, если бы было принципиальное ограничение на 64 байта в пакете, то все другие варианты просто-напросто не работали бы, а у нас данные идут при различных вариантах конфигурирования контроллера и соответствующих изменений программы.

Чтобы понять, почему изначально нелегальные конфигурации почему-то вдруг как-то работают, надо влезть в самое нутро вашей МС, в аппаратную реализацию USB на уровне VHDL/Verilog, заодно копая исходники хоста и драйвера. Тогда, возможно, за несколько месяцев в этом вопросе разберетесь. А оно хоть кому-нибудь надо?

Или, может быть, вам кто-то обещал, что нелегальные конфигурации вообще работать не будут? Увы, никто вам этого не обещал. Вам обещали, что правильно сконфигурированное устройство будет работать, и не более того.

Цитата(NikP @ Dec 19 2012, 22:16) *
При размере пакета 64 байта - та же ерунда: предельный размер остаётся 2К.

Описывайте все что делаете в подробностях. Вы там где-то в деталях напортачили.
NikP
=АК= Спасибо за науку: установили размер пакета 64 байта, сделали запрос 16К , убрали несколько косяков и передача пошла на хорошей скорости.
Ten04
Цитата(NikP @ Dec 20 2012, 20:42) *
=АК= Спасибо за науку: установили размер пакета 64 байта, сделали запрос 16К , убрали несколько косяков и передача пошла на хорошей скорости.


У меня была та-же проблема - не получалось оправлять/принимать больше одного пакета за фрейм. На девайсе (STM32F3Discovery) бесконечным циклом устанавливаю кол-во на отправку 64байта (SetEPTxCount((EP1_IN & 0x7F), 64) и валидность данных (SetEPTxValid(ENDP1)). Данные в буфере пока не обновляю для избежания задержки. По идее задержка на отправку должна быть минимальная и пакеты непрерывно отправляться, но в клиенте на PC за секунду принималось только 1000 пакета по 64байта, то есть шёл один пакет на фрейм. На PC в качестве драйвера использую DriverWizard WinDriver 10.10. Ситуация исправилась тем, что на PC стал принимать пакеты не по 64байта, а оптом значительно большее количество (к примеру 8192байта). Так что сделал вывод, что то самое тормозное место обрывающее транзакцию, это вызов процедуры принятия данных на ПК, и лучше за один вызов принять как можно больше данных. Фактически вызов функции - транзакция. У меня сейчас получается принять за фрейм не более 15 пакетов по 64байта - скорость 960000байт в сек.
Ten04
Не могу сделать режим двойной буферизации. Отправляется первый пакет и затыкается. До обработчика прерывания завершения отправки (EP1_IN_Callback) не доходит. Может есть пример у кого? Просматривая исходники библиотеки USB, складывается впечатление, что она слабо приспособлена для режима двойной буферизации.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.