Jump to content

    
Sign in to follow this  
msn

Как побороть большие паузы между запросами к USB драйверу

Recommended Posts

Суть проблемы такая:

Есть МК (Cygnal C8051F32x) используется одна EP (64+64) с двойной буферизацией передачи типа Bulk на Full Speed в сторону Хоста. К МК должен быть подключен внешний АЦП и Cygnal непрерывно передает данные в сторону хоста. АЦП тактируется примерно 600 КГц и имеет разрядность 12 бит, т.е. Cygnal должен передавать поток 600*1,5 = 900 Кбайт / сек. Если запрос DeviceIoContro(,,,,,0x10000,,) к драйверу (пробовал на WinDriver, USBIO и дровах от Cypress) идет с размером буфера 64К то средняя скорость чтения из EP примерно 1020-1040 Кбайт / сек, т.е. хватает. Но есть ложка дегтя. Если вместо данных АЦП передавать значение внутреннего таймера МК, для проверки задержек, то получается следующая неприятная картина:

 

[ Пакет №1 – 64 Байта]

6 us – начала записи данных в EP (условно начало передачи пакета)

48 us – окончание записи данных в EP (условно окончание передачи пакета)

Время записи = 42 us

 

[Пауза №1]

48 us … 50 us, dT = 2 us

 

[ Пакет №2 – 64 Байта]

50 us … 93 us, dT = 43 us

 

[Пауза №2]

93 us … 3015 us, dT = 2922 us

Длина определяется тем, что сначала было записаны первые два пакета в EP (двойная буферизация) после получения команды (по Pipe 00), а дальше пошли IN транзакции от DeviceIoContro(,,,,,0x10000,,).

 

[ Пакет №3 – 64 Байта]

3015 us … 3057 us, dT = 42 us

 

[Пауза №3]

3057 us … 3070 us, dT = 13 us

 

[ Пакет №4 – 64 Байта]

3070 us … 3113 us, dT = 43 us

 

[Пауза №4]

3113 us … 3128 us, dT = 15 us

 

Дальше пауз больше нескольких десятков us нет.

 

[ Пакет №1025 – 64 Байта, т.е. это уже начался новый DeviceIoContro(,,,,,0x10000,,)]

dT = 43 us

 

[Пауза №1025]

dT = 10 us

 

[ Пакет №1026 – 64 Байта]

dT = 42 us

 

[Пауза №1026]

>>>>>>>>>>> dT = ~3000 us <<<<<<<<<<<<<

 

!!! А вот тут не понятно, почему такая огромная пауза? DeviceIoContro(,,,,,0x10000,,) идут просто в цикле кроме этого МК ни чего не получает, неужто драйверу нужно аж 3 ms что бы сформировать DeviceIoContro(,,,,,0x10000,,), причем такая же ситуация на разных драйверах, на разных компах (с 98, 2k и XP c USB1.1. и USB2.0 на борту). Такие большие задержки приводят к тому, что 3000 us / (1/600КГц) = 1800 отсчетов АЦП пролетают, т.е. средняя скорость хорошая, но передачи идут рывками. Если снижать размер буфера, например 8К, задержки в среднем уменьшаются (есть много ~1 ms, но 5% наоборот растут аж до 3-5 ms) и средняя скорость падает почти в 2 раза до ~600 Кбайт / сек

 

Кто-то сталкивался с такими проблемами? Может кто-то подскажет из-за чего происходят таки большие задержки и как их можно уменьшить?

 

Пока вижу только один вариант – использовать FIFO.

 

Спасибо.

Share this post


Link to post
Share on other sites

Не до конца вник, но вопрос такой: т.е. на ПК выполняеется программа:

 

do{DeviceIOControl} while ()

 

А как же насчет вытесняющей многозадачности Windows. Т.е. между этими двумя строками программы рально могут выплняться другие процессы с задержками до нескольких десятков мс.

 

Выход - только FIFO.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Спасибо за помощь.

 

>do{DeviceIOControl} while ()

 

Я даже об этом не подумал, смотрел что загрузка CPU ~2-3%, и предполагал, что драйвер и Хаб сам все буферизирует на аппаратном уровне чтобы исключить влияние переключение на другие процессы.

Заметил если повысить приоритет оболочке, то задержки примерено, постоянны им равны 1,8 мс.

Интересно такое пройдет в Win98/ME.

Вы не подскажите можно катко поднять приоритет драйверу?

 

>В подобных случаях используют изохронный режим

 

Я бы с радостью использовал изохронный режим если бы C8051F32x имел EP большего размера, а то на нем только ~400 KB/s. К сожалению на сайпрес пока не перешел, да и драйвер у них не дружит с Win98/ME.

 

>буферизация приходящих пакетов производится драйвером

Подскажите, пожалуйста, это только для Iso? Драйвер буферизирует все сам или только когда к нему идут запросы, т.е. DeviceIOControl [пауза в проге 3-5 мс] DeviceIOControl, в момент паузы и при отсутствии запроса драйвер будет продолжать принимать пакеты и сохранять их в своем FIFO?

Share this post


Link to post
Share on other sites

Да действительно - сигнал не подойдет для длинных изохронных передач. При двойной буферизации размер одного фрейма не более 256 байт. Обратите внимание на TUSB от TI и на сайпресовские изделия. В них поток данных можно пустить мимо процессора через ПДП между буфером эндпоинта и периферией.

Про EzUsb. В этом драйвере можно запустить отдельный поток, которому выделить память для кольцевого буфера на приходящие пакеты только по изохронным каналам. Драйвер будет вызывать коллбек при наличии данных. Частота вызова коллбека настраивается при запуске. Можно вызывать например каждый 32 фрейм, то есть раз в 32 мс. Пока перерабатываешь, текущие пакеты складываются самим драйвером. Но, к сожалению такой режим возможен только для ISO IN PIPES.

Share this post


Link to post
Share on other sites
>В подобных случаях используют изохронный режим

 

Я бы с радостью использовал изохронный режим если бы C8051F32x имел EP большего размера, а то на нем только ~400 KB/s. К сожалению на сайпрес пока не перешел, да и драйвер у них не дружит с Win98/ME.

 

 

Тот драйвер от Cypress, с которым я начинал в 2001, компилировался в VC6 + DDK98, соответственно под Win98/МЕ. Но неплохо работает и на ХР. Возможно, с тех пор у них появился другой.

А нельзя поменять процессор на тот же CYPRESS? Все-таки производительность у него в два раза выше, да и возможностей по прамой передаче АЦП -> USB Engine у CYPRESS'а намного больше. Можно FX2 взять с USB2.0

 

>буферизация приходящих пакетов производится драйвером

Подскажите, пожалуйста, это только для Iso? Драйвер буферизирует все сам или только когда к нему идут запросы, т.е. DeviceIOControl [пауза в проге 3-5 мс] DeviceIOControl, в момент паузы и при отсутствии запроса драйвер будет продолжать принимать пакеты и сохранять их в своем FIFO?

 

В CYPRESS-овом драйвере для ISO организуется очередь IRP-запросов и принятые данные сохраняются в выделенном буфере. Оттуда их можно считать отдельной командой. Т. е., все принятые данные сохраняются в FIFO. Кстати, есть одна особенность - после подачи команды на закрытие потока(IOCTL_EZUSB_STOP_ISO_STREAM), перед повторным запуском чтения надо выдержать время, чтобы все IRP-запросы завершились.

Для bulk такого механизма нет, запрос на чтение отправляется сразу в USBD, соответственно паузы между запросами остаются. В других драйверах, я думаю, с bulk поступают аналогичным образом.

Edited by Johny

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this