|
STM32F4 USB CDC, Передаёт не более 32 байт за раз |
|
|
|
Mar 7 2013, 08:53
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Понимаю, что может быть избитая и изъезженная тема тема, но всё же. Короче, взял пример COM-порта отсюда - http://we.easyelectronics.ru/STM32/primery...4-discovey.htmlПорт опознаётся, устанавливается, всё ок. Данные принимает, передаёт. Но. Не могу передать на комп более 32 байт. Комп просто ничего не принимает. Когда 32 байта и меньше всё в порядке. Это ж отстой полный, хуже чем даже USB HID Generic - 64 байта туда-сюда-обратно. И тот кстати не получается. Примеры - сплошные мыши и джойстики  ... Это что, норма? И как этого избежать? Размер буферов в прошивке вроде 2 кила - макрос APP_RX_DATA_SIZE = 2048. И ещё. Не хочется, чтобы железка торчала в списке COM-портов. Взял финский пример отсюда - http://forum.easyelectronics.ru/viewtopic....=35&t=10245Он пошёл без проблем, комп его увидел. Но где взять драйвер? Нашёл libusb, драйвер им сгенерил, но как с ним дальше работать не понял... Может ли кто-нибудь помочь? Спасибо.
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
 |
Ответов
(15 - 29)
|
Mar 2 2014, 11:58
|
Местный
  
Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188

|
Цитата(rudy_b @ Mar 2 2014, 14:46)  Мне просто важно понять - это что-то не то у меня или это действительно ошибка либы. Никто не гонял пакеты с такой длиной? Я слепил свой bulk-девайс на основе ST-шной либы. Обмен только пакетами, кратными 64 байтам. Никаких проблем не отмечал. В предыдущих проектах с LPC17 - та же ситуация (в смысле все нормально).
|
|
|
|
|
Mar 2 2014, 13:41
|
Знающий
   
Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458

|
А какой именно либы? Я использовал stm32_f105-07_f2_f4_usb-host-device_lib_v2.1.0 (файлы V1.1.0 19-March-2012) и сравнивал с верией от 2011 (нет существенных различий). Программа в контроллере (режим эхо) ничего не знает о размерах пакетов. К ней на вход валятся блоки по 64 байта или менее. Разбивку пакетов на блоки делает драйвер виндюков (пакеты заданного размера отправляются по WriteFile прогой в компе), а контроллер только перекладывает принятые блоки из буфера приемника в буфер передатчика. И я вижу, что все пакеты нормально приходят в контроллер (стоит счетчик принятых байт) и, скорее всего, нормально отправляются в комп. А вот прога в компе (ReadFile с заданным размером) не получает ничего, даже при нескольких перезапросах если длина отправленного пакета кратна 64. Поскольку это VirtualCom, то драйвер в контроллере должен передавать любое количество байт. Но если в буфер передатчика положено сразу 64 байта, то, после их передачи, он, похоже, не отправляет пакета нулевой длины несмотря на то, что буфер пуст. И вот тут-то ReadFile (usdser.sys) похоже считает передачу незавершенной и сбрасывает весь пакет - не приходит ни одного байта при любом количестве перезапросов. Ну или что-то в этом роде, хотя и непонятно как такого можно добиться. Цитата(Golikov A. @ Mar 2 2014, 17:11)  балк обменивается не по контрольной конечной точке, и у него размер буфера больше 64 байт. CDC работает через контрольную конечную точку, у которой буфер как раз 64 байта (про slow speed не говорим), потому при посылке пакета кратного 64 байтам, последняя передача идет с полным буфером, и требует по стандарту USB досылки еще одного пакета 0 длинны, как признак окончания.
думаю в этом подвох, странно что либа сама не добавляет 0 посылку, а исходники либы есть? может просто посмотреть глазьями есть там проверка на кратность длинны и досылка 0 пакета? Балк в FS все равно работает пакетами с максимальным размером 64 байта. Я это смотрел. Происходит прмерно так, если правильно понял исходники. По фрейму происходит проверка на наличие данных в пользовательском буфере. Если данные есть то из них выкусывается блок размером до 64 байт и устанавливается размер для передачи и указатель данных. После этого в более глубоких потрохах драйвера происходит его загрузка в фифо и передача в данном фрейме. А вот однократной передачи пустого блока при переходе буфера из полностью заполненного состояния в пустое я не увидел. Но может плохо смотрел, да и разбираться в ST-шных либах и их изумительном харде при отсутствии внятных описаний - проблема еще та. Но исходники есть, могу послать если нужно, размер-порядка 4 метров (с примерами).
|
|
|
|
|
Mar 2 2014, 14:27
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
не надо мешать все в одну кашу. балк, изохронный, прерывания, и контрольные обмены. Что какой то из них тоже использует буфер 64 байта это ничего не значит.
Правда заключается в том что контрольная точка может послать максимум 64 байта. Когда на компьютер приходит пакет длинной меньше 64 байт - это конец послания. И вам становится доступно сообщение по ReadFile в винде. Если же приходит пакет длинной 64 байта, то не понятно это все сообщение, или нет, так как ограничение длинны может быть из-за максимального размера конечной точки. Поэтому драйвер винды кладет себе это сообщение и ждет следующего пакета, если придет пакет длинной меньше, он поймет что это конец и все вам отдаст, потому по стандарту пакеты длинной в макс буфер конечной точки обязательно должны быть дополнены пакетом 0 длины.
Если вы монитором USB порта после прихода пакета длинной 64 байта, не видите закрывающего пакета 0 длинны (его иногда могут как АКК воспринимать мониторы порта), то это явная ошибка процедуры посылки данных, и эти данные вы не получите, в винде. Проверяйте либу
|
|
|
|
|
Mar 2 2014, 16:36
|
Знающий
   
Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458

|
Угу, еще раз посмотрел внимательно. При приеме из компа в контроллер все аккуратно. А вот при передаче из контроллера в комп - все криво. До конца еще не разобрался, но, похоже, понял в чем дело.
Эта зараза рассчитана на то, что приходящие снаружи (на СОМ) данные никогда не достигнут 64 за один фрейм, т.е. за 1 мсек. И, поэтому, она вообще не заботится о полном размере посылки, а тупо посылает все, рассчитывая, что число посланных байт всегда меньше 64 и проблем с завершением пакета не возникнет.
Это в чем-то обосновано, 64 байта за 1 мсек - это примерно 640кбит - намного выше стандартных скоростей СОМ порта.
Похоже, что для обмена пакетами нельзя использовать CDC, нужно брать что-то другое или не допускать размера пакетов кратного 64.
Конечно можно и драйвер поправить, но для этого прийдется полностью разбираться в структуре драйвера и, фактически, переписать его. Как-то лениво, но, может, прийдется.
Да, это не контрольная точка - это реальный балк.
|
|
|
|
|
Mar 2 2014, 18:16
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
очень странно что это балк, мне казалась что стандартный виндовый драйвер через контрольную работает, ну да ладно...
На самом деле вам не надо разбирать всю библиотеку, можно сделать внешний модуль обертку который будет следить за данными, в нем сделать фифо, и пусть он все выдавливает наружу, и если вдруг случиться что данных больше 64 байт, то пусть давит их наружу, и проверяет последний пакет.
Собственно когда я сам писал USB у меня так и была организованна посылка, получала данные, и слала, проверяя длину последнего пакета, дополняя нулем если что.
И еще одна вещь которую вам надо знать про USB, это то что в винде реально боле менее поддержаны только CDC и HID, все остальное потребует от вас в реальности написания собственного драйвера.
|
|
|
|
|
Mar 2 2014, 18:46
|
Знающий
   
Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458

|
Они, почему-то, используют EP1 для приема и передачи данных в режиме балк, а EP2 - для команд (BaudRate и т.п.) в режиме interrupt. А EP0 не используют совсем. Она используется только в режиме HS и странным образом. #define CDC_IN_EP 0x81 /* EP1 for data IN */ //USB_OTG_EP_BULK #define CDC_OUT_EP 0x01 /* EP1 for data OUT */ //USB_OTG_EP_BULK #define CDC_CMD_EP 0x82 /* EP2 for CDC commands */ //USB_OTG_EP_INT Цитата На самом деле вам не надо разбирать всю библиотеку, можно сделать внешний модуль обертку который будет следить за данными, в нем сделать фифо, и пусть он все выдавливает наружу, и если вдруг случиться что данных больше 64 байт, то пусть давит их наружу, и проверяет последний пакет. Тут, похоже, и это может не помочь. Возможно возникнут еще и проблемы с виндюковым usbser.sys - он ведь тоже VirtualComPort и не должен реагировать на отсутствие общего размера посылки, только на длину конкретного блока данных. И проблемы у него есть - редкие ошибки при трансляции пакетов с размером более 64 байт связаны именно с его глюками, я специально поигрался. А если пакет меньше 64 байт - ошибок нет вообще. Цитата И еще одна вещь которую вам надо знать про USB, это то что в винде реально боле менее поддержаны только CDC и HID, все остальное потребует от вас в реальности написания собственного драйвера. Вот этого я и боюсь. HID тоже не рассчитан на передачу блоков данных и фиг знает, что нам накручено. А в аудио и вообще лезть не хочется. Ну а писать свой драйвер под виндюки жутко не хочется, мои мозги не в состоянии воспринять их идеологию, хотя под нормальную ОС раньше писал без проблем. Похоже прийдется обойтись пакетами 63 байта. Правда скорость при этом получается порядка 200 кбит, но, надеюсь, мне этого хватит.
|
|
|
|
|
Mar 2 2014, 19:35
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Да нет никакой проблемы, все равно для уравнивания скоростей надо делать ФИФО, и никто не мешает выдавать данные из этого фифо не более чем по 63 байта, и скорость будет 63 КБайта. Неудобство в сборе пакета потом, сom port - это потоковый протокол, а не пакетный, пакеты все равно придется собирать.
А вот что касается HID, то там как раз прям пакетно ориентированная идея. Основная единица обмена информацией у HID - это отчет. Отчет это фиксированная структура данных, определяемой вами длинны. Причем отчетов может быть несколько типов, так что можно определить несколько видов структур.
Обмен отчетам происходит по 2 конечным точкам интерапт типа, входной и выходной, или через контрольную, в контрольной будут теже сложности с делением пакета на 8-64 байта, но по интерапт точкам данные ходят одним куском. И проблем с драйверами HID сильно меньше, судя по отзывам...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|