Jump to content

    

Принять данные через COM порт и сохранить в файл

On 11/6/2018 at 5:12 PM, zombi said:

нет, не поломали. Работает, но тоже байты теряет (

Берите Device Monitoring Studio включайте снифинг USB и фильтруйте пакеты со статусом  NTstatus != 0  

Наверняка будет где-то статус 0x00000102. 

Share this post


Link to post
Share on other sites
2 часа назад, Arlleex сказал:

P.S. Запорол - это не поставил высокий приоритет потоку чтения в процессе клиентского приложения на персоналке. Сейчас выставил - уже 50 мегабайт скачалось - нет ни одного пропущенного байта. Но мне пора домой - завтра поставлю скачку на мегабайт 500 и отпишусь о результатах.

Без контроля целостности переданных данных - это не тест. Да и контроль скорости передачи (на стороне ПК) тоже нужен. Может там вовсе и не 2Мб/сек?  :)

 

1 час назад, kovigor сказал:

"Большая наука" на ровном месте. И все это вместо того, чтобы подпаять два провода и реализовать RTS/CTS ...

RTS/CTS тут вообще как бы не к месту. При нормальной реализации приёма в ПК, должно работать без всяких CTS/RTS.

И ТС всех обманул: поток у него не 2 Мб/сек, а всего лишь 2048/.015 = 136533 КБ/сек.

Share this post


Link to post
Share on other sites
3 часа назад, Arlleex сказал:

Пока что приложуха выглядит как-то так:

Вы реально там выставляете 2000000 бод??? Думаете UART на ПК потянет без глюков такой делитель, не кратный стандартному ряду скоростей?

Лучше уж тестить на корректной скорости: 1843200 бод. Для задачи ТСа такой скорости достаточно.

Share this post


Link to post
Share on other sites
Quote

 

Управлению потоком не один десяток лет. И не я его придумал. И придумали его не от нечего делать. Так что ...

P.S. Не хотите - не делайте. Но лучше один раз сделать нормально, чем постоянно ловить и исправлять проблемы. И еще, не забудьте проинформировать вашего заказчика/потребителя/работодателя, что работа сделана "на авось" и надежность обмена данными не гарантируется ...

 

А я не вижу пока проблем сделать нормально и безглючно без управления потоком. И да - если заказчику нужна выкачка больших объемов данных, то я никак не UART буду использовать. Хотя, если уж на то пошло, то да - сверху, естественно, протокол будет. Это само собой разумеющееся. И никаких "авось" =)

 

29 minutes ago, jcxz said:

Без контроля целостности переданных данных - это не тест. Да и контроль скорости передачи (на стороне ПК) тоже нужен. Может там вовсе и не 2Мб/сек?  :)

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

 

11 minutes ago, jcxz said:

Вы реально там выставляете 2000000 бод??? Думаете UART на ПК потянет без глюков такой делитель, не кратный стандартному ряду скоростей?

Лучше уж тестить на корректной скорости: 1843200 бод. Для задачи ТСа такой скорости достаточно.

Да, реально 2000000 бод. ПК тянет такой делитель. Только это не от ПК зависит, а от железа. Железо у меня - FT232RL, как связующее звено USB-UART. А у этой микросхемы можно задавать как стандартные, так и не стандартные битовые скорости. Поэтому я и говорил про драйвер FTDI - я его слегка поправил (пара чисел, как раз настраивающих битрейт). Можно было поставить и 1843200, но скорость ТС была именно 2000000 - тем интереснее задача.

Share this post


Link to post
Share on other sites
13 часов назад, Arlleex сказал:

Да, реально 2000000 бод. ПК тянет такой делитель. Только это не от ПК зависит, а от железа. Железо у меня - FT232RL, как связующее звено USB-UART. А у этой микросхемы можно задавать как стандартные, так и не стандартные битовые скорости. Поэтому я и говорил про драйвер FTDI - я его слегка поправил (пара чисел, как раз настраивающих битрейт). Можно было поставить и 1843200, но скорость ТС была именно 2000000 - тем интереснее задача.

ТСу там вовсе и не нужно именно 2e6. А насчёт - позволяет или нет FT232: всё-таки думаю на стандартном ряде скоростей - надёжнее, больше вероятность, что вся цепочка драйверов и железа будет работать правильно. Да и на кой задирать и так не маленькую скорость, если с запасом хватает меньшей? Разве что у ТСа источник данные генерит с частотой 2e6 бит/сек и он работает совсем без буферизации?  ;)   Ну так в этом случае никакой flow control в принципе нельзя употреблять.

Share this post


Link to post
Share on other sites

Ну, в общем, потестировал немного.

 

1. Замер скорости.

image.png.b01007767ce319be8dae344de3fbbf04.png

Как видно, расчетная скорость от 2 мегабитного потока (2000000 бит/с) соответствует цифрам. Измерял так: завел таймер на 5с, по истечении времени оцениваю количество пришедших за эти 5с данных и рассчитываю скорость.

 

2. Контроль передачи.

Тут возникла проблема. Отправляю посылки по 2048 байт, без случайной задержки между посылками (фактически, сплошной поток). Часть данных (от единиц до десятков байт) на 100 мегабайтном файле теряется.

Скорость 2000000 ровно выбрана из-за того, что:

1) она допустима производителем (а допустимое значение вплоть до 3000000);

2) в документации на FT232 параметры предделителей исходят из целого значения 3000000. Из него получаются все скорости, в том числе стандартные.

3) в документации на FT232 скорость 2000000 настраивается не общим способом, а выделенным диапазоном отведенных бит, что, теоретически, подтверждает, что скорость там будет действительно такой.

4) в используемом МК частота периферийной шины не кратна ряду стандартных скоростей. И даже дробный делитель дает ошибку порядка 10% при высоких стандартных скоростях. А на 2000000 ошибка очень мала - порядка 2%. Я и в файле полученных данных вижу именно то, что отправлял. Ошибка заключается именно в пропаже части байт (а не в их порче). До этого еще дойдем.

 

3. Правки файлов конфигурации драйвера.

Есть такой замечательный документ: https://www.ftdichip.com/Support/Documents/AppNotes/AN232B-04_DataLatencyFlow.pdf.

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

Максимально стабильно данные читаются с бОльшими значениями объема приемных буферов USB.

Исследовал, почему выставляется флаг EV_ERR: https://msdn.microsoft.com/en-us/library/ms810467.aspx.

Quote
EV_ERR A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. To find the cause of the error, ClearCommError should be called.

Считываю регистр ошибок функцией ClearCommError и вижу один установленный бит: CE_OVERRUN. По этой же ссылке написано, что этот флаг устанавливается тогда, когда именно драйвер не успевает работать с контроллером USB-Host.

 

4. Предположения.

Могу предположить, что из-за наличия в системе множества процессов (даже несмотря на то, что я выставил приоритет процесса уровня REALTIME_PRIORITY_CLASS (самый высокий для процесса) и для потока THREAD_PRIORITY_HIGHEST), CPU физически не успевает переключиться на обслуживание USB-контроллера и результирующая задержка между опросом USB-VCP составляет больше 1,28мс (время заполнения 256-байтного буфера UART в FT232 микроконтроллером). Отсюда и происходит переполнение, после чего хост-контроллер USB читает статусные биты транзакции и видит переполнение входящего буфера - соответственно, это уведомление доходит и до моего приложения.

Можно, конечно, взять осциллограф, и посмотреть на обмен по USB, если между пачками будет больше 1,28мс, то мое предположение верно.

Также убирал процедуру записи в файл (думал, что она громоздкая внутри и задерживает выполнение процесса) - результат не меняется: драйвер не успевает вовремя обслуживать устройство.

Для последнего эксперимента (косвенно подтверждающего мое предположение о хреновой своеобразной работе хост-контроллера USB на ПК) можно действительно снизить (немного) скорость битового потока, например, до стандартной скорости 1843200 бит/с, как предлагалось ув. jcxz. Придется перенастроить PLL и предделителями синхронизации на МК, чтобы получить маленькие погрешности для стандартного битрейта UART.

 

5. Хотелки.

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

 

6. Заключение.

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

Edited by Arlleex

Share this post


Link to post
Share on other sites
13 minutes ago, Arlleex said:

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

Почему "как"? WireShark и USB умеет.

Share this post


Link to post
Share on other sites
Just now, aaarrr said:

Почему "как"? WireShark и USB умеет.

Оу. Не знал. Обычно только Ethernet и смотрел. Спасибо!

Share this post


Link to post
Share on other sites

К сожалению, на 1843200 бит/с проверить не удастся. Дело в том, что в FT232RL формула битовой скорости:

BR = 3000000 / Prescaler,

где Prescaler - от 2 до 16384. Число 0 и 1 зарезервированы для 3МБод и 2МБод, соответственно.

Чтобы получить 1843200 бит/с, мне нужен предделитель 1,62760416... Целая часть равна 1 - а это выбирает ровно 2000000 бит/с.

Таким образом, получить скорость из ряда стандартных в диапазоне от 1000000 бит/с не представляется возможным. Только не ровные скорости (например, 1500000 бит/с).

Share this post


Link to post
Share on other sites
40 минут назад, Arlleex сказал:

CPU физически не успевает переключиться на обслуживание USB-контроллера и результирующая задержка между опросом USB-VCP составляет больше 1,28мс

Информация ценная, но недостаточно полная - использованная OS, процессор ?

Share this post


Link to post
Share on other sites
46 минут назад, Arlleex сказал:

Как видно, расчетная скорость от 2 мегабитного потока (2000000 бит/с) соответствует цифрам. Измерял так: завел таймер на 5с, по истечении времени оцениваю количество пришедших за эти 5с данных и рассчитываю скорость.

Что значит "по истечении времени"? GetTickCount()?

Для точных замеров времени на ПК лучше использовать TSC (processor's time stamp counter). См. описание QueryPerformanceFrequency() и QueryPerformanceCounter().

 

46 минут назад, Arlleex сказал:

можно действительно снизить (немного) скорость битового потока, например, до стандартной скорости 1843200 бит/с, как предлагалось ув. jcxz. Придется перенастроить PLL и предделителями синхронизации на МК, чтобы получить маленькие погрешности для стандартного битрейта UART

Как я уже писал выше: ТС-у достаточно 2048/.015 = 136533 КБ/сек. Так что если, как Вы пишете, FT232 умеет 1.5e+6 бод, то можно тогда на ней.

Share this post


Link to post
Share on other sites
Just now, rx3apf said:

Информация ценная, но недостаточно полная - использованная OS, процессор ?

Windows 7, 64-битная. CPU Intel Core-I5-4570, 3.2ГГц, 4 ядра.

 

Just now, jcxz said:

Что значит "по истечении времени"? GetTickCount()?

Нет, обычным компонентным таймером. Главное было понять, что расчетная скорость верна. (2000000 бит/с) / (10 бит в байте на UART-кадр) = 200 кбайт/с реальной скорости. Благодарю за TSC на ПК, попробую.

 

А теперь внимание: я никогда ранее не работал с USB на уровне программирования под МК, соответственно мало что понимаю. У меня записался лог-файл сниффера от USB. В начале идут какие-то BULK, IN, OUT транзакции, но потом идут чисто данные.

Вот host что-то запросил (выделенная строчка) и потом делает транзакции IN, где наши данные уже лежат:

image.png.3c5252fb634c67555e8eb437a305f9d9.png

Обращаю особое внимание на время между OUT и первой IN транзакциями (да как и на время между любыми соседними транзакциями): ~1мс (пренебрегаем 6-м знаком после запятой, спишем на несоответствие тактовых генераторов).

 

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

image.png.70f0aeef2e6fd540006058499d682435.png

Что-то определенно с временами (смотрите, до OUT транзакции все по 1мс было, а начиная с нее началась бредовая импровизация контроллера).

Теория о недостатке времени на обслуживании хост-контроллера верна?

 

Edited by Arlleex

Share this post


Link to post
Share on other sites
10 minutes ago, Arlleex said:

Вот host что-то запросил (выделенная строчка) и потом делает транзакции IN, где наши данные уже лежат:

...

Что-то определенно с временами (смотрите, до OUT транзакции все по 1мс было, а начиная с нее началась бредовая импровизация контроллера)

Обратите внимание на адрес USB-устройства, с которым общается хост. Ваше, судя по всему, имеет адрес 3.1.1, остальные лучше отфильтровать.

В последних пакетах от устройства проверьте значение первого бита во втором байте - это флаг переполнения.

Share this post


Link to post
Share on other sites
15 minutes ago, aaarrr said:

Обратите внимание на адрес USB-устройства, с которым общается хост. Ваше, судя по всему, имеет адрес 3.1.1, остальные лучше отфильтровать.

В последних пакетах от устройства проверьте значение первого бита во втором байте - это флаг переполнения.

Сделал фильтрацию. Нашел переломный момент:

image.png.2febc2e4d67d31fb67a4a5bb95c87c41.png

После выделенной строки количество данных изменилось в 2 раза в BULK-пакетах, и, кроме того, изменился шаг опроса устройств на шине USB - через 2мс стал опрашивать...

 

А после 28 таких пакетов снова нормально:

image.png.6f1559f1bd4f5f0538620be09a1f2cde.png

Edited by Arlleex

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now