|
|
  |
Windows7: прием байтов через COM-порт без потерь, Кто-то имеет личный опыт? чем побороть потерю отдельных байтов? |
|
|
|
May 22 2017, 06:27
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Здравствуйте! Есть Windows7 Pro, 32-bit, компьютер- китайский одноплатник на Intel 1037U, 4GB RAM. СОМ-порты- 4 штуки прямо на материнке. И есть внешний передатчик, посылающий в COM-порт пакеты. Скорость- 115200, стандартный формат 8N1. Длина пакета- не более 255 байт, межпакетный интервал- не менее 4 байт, часто гораздо больше (десятки миллисекунд). Каждый пакет имеет контрольную сумму (crc16), по которой и принимается решение о валидности пакета. Общая загрузка канала где-то 5-8 килобайт в секунду, то есть до 80%. Загрузка CPU около 10-15%. И есть самописная программа на С++Билдере (6), данный вариант делался по прерываниям, с несколькими потоками (базой был вот этот документ). Есть поток, принимающий все байты по прерываниям и валящий в большой кольцевой буфер. И другой поток периодически выгребает байты из буфера и делит на пакеты для обработки, проверяет валидность. Только прием, никаких переключений на передачу. В результате приемник иногда пропускает байты. То есть все принятые байты всегда совпадают с переданными, но некоторые байты пропущены. Всегда пропущено не более одного байта за раз, в любом месте пакета. Часто бывает что пропущено по одному байту в двух следующих друг за другом пакетах. Обычно фактов потери байта где-то 10-20 в сутки. Корреляция с действиями Виндоуса пока не найдена, очень уж все случайно. Потери именно в компьютере- подключенный прямо к этому же разъему логический анализатор исправно ловит все байты, никакого криминала или отклонений во времянке не обнаружено (по уровню тоже все без проблем) Вопросов два: 1. Кто-то в подобных условиях добивался абсолютно безошибочного приема потока через COM-порт в Виндоус (7) на 115200? 2. куда копать? Сильно надеюсь что моя программа виновата. На другом железе пробовал- эффект тот же, то есть это не электроника глючит. С приоритетами игрался, никакого эффекта. Заранее спасибо за любые советы (по существу).
|
|
|
|
|
May 22 2017, 08:15
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(Ruslan1 @ May 22 2017, 10:27)  Есть поток, принимающий все байты по прерываниям и валящий в большой кольцевой буфер. И другой поток периодически выгребает байты из буфера и делит на пакеты для обработки, проверяет валидность. Вот это место непонятно - для каждого порта свой буфер, или общий на все порты? выпадание байта определяете по сбою crc? Что Вы называете "приемом по прерыванию"? У выни свои прекрасные дрова для КОМ, и даже целый специальный апи в ядро встроен под устройства Comm - модемы проще. все известные мне либы в борланде являются прокладкой к этому стандартному АПИ. напрямую с прерыванием никто не работает. проблем с потерями не было, хотя обмен бывал интенсивный - мегабод. можно посоветовать покрутить : 1)объем буфферов кома (я делал 8кб) 2)приоритет нитки приемника сделать выше нормального 3)если у вас между пакетами есть пауза более 1мс, настроить ее в свойствах таймингов кома. в запросах асинхронного чтения возможно оно поможет АПИ возвращать целиком пакет а не куски случайно презанные. 4)какая может быть гарантия что порт вашего ПК видит ваш поток без потерь, даже если ваш снифер прекрасен? Вы в качестве снифера тот же самый ПК используете? 5) можно поставить прокси с журналированием на ком (я пользовал com0project, но их вроде множество разных), и уже к нему подключать вашу программу. в этом случае вы сможете сравнить поток принятый прокси с потоком принятым вашей софтиной. 6) вы журналировали поток считанный из порта, сравнить его с финальными нарезанными пакетами? точно эти байты не считываются из порта?
Сообщение отредактировал AlexRayne - May 22 2017, 08:22
|
|
|
|
|
May 22 2017, 08:37
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(neiver @ May 22 2017, 12:25)  Начинать надо с того, что COM порт вообще и его реализация в Windows в частности, не гарантирует безошибочной передачи данных. То есть рассчитывать на это нельзя, и контроль и/или обеспечение целостности данных надо реализовывать в протоколе обмена. Поврежненный пакед должен отбрасываться и если нужно передаваться повторно. Парень сборется с другой проблемой - у него не пропадание сигнала на линии (этим он займется видимо позже, когда жареный петух клюнет), а пропадание байтов прямо на порте. можно это списать на особенности железа, но вероятность невелика
|
|
|
|
|
May 22 2017, 12:23
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей! Что именно Вы имеете в виде когда говорите про "прекрасные дрова для КОМ, и даже целый специальный апи в ядро встроен под устройства Comm"? Что именно советуете почитать-посмотреть, может даже применительно к простоте прикручивания в Билдер? Я раньше работал по поллингу, и задачи другие были. А сейчас решил по прерываниям сделать, нашел понятное мне описание в интернете(ссылка в моем письме)- по нему и сделал. Если уже есть компонент а или просто апишная функция "брать все байты из порта и кидать в большой пользовательский кольцевой буфер" - было бы замечательно. В пятом Билдере ставил пакет TurboPower Async Professional, но использовал по поллингу. Сейчас на новый (хихи) 6-й билдер перешел и думал без сторонних компонентов обойтись. И это не железо, я пробовал на другом компьютере- эффект тоже имеет место быть. И это действительно потеря в машине- прямо на порт включал независимый лог анализатор, и после сравнивал содержимое буферов его и моей программы. Очень хочется для начала локализовать проблему, и Ваши советы мне отлично подходят- не подумал про независимый сниффер-программу прямо на этой машине. Очень надеюсь что проблема в моем коде- тогда есть большая вероятность ее решения
|
|
|
|
|
May 22 2017, 13:48
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(neiver @ May 22 2017, 12:25)  Начинать надо с того, что COM порт вообще и его реализация в Windows в частности, не гарантирует безошибочной передачи данных. То есть рассчитывать на это нельзя, и контроль и/или обеспечение целостности данных надо реализовывать в протоколе обмена. Поврежненный пакед должен отбрасываться и если нужно передаваться повторно. По возможным причинам. У стандартного аппаратного СОМ порта есть внутренний буфер, как правило размером 15 байт. Это не тот буфер, который задается в SetupComm. Если драйвер порта по каким-то причинам не успеет прочитать этот буфер, то принятые байты теряются, о чем извещают соответствующие флаги возвращаемые ClearCommError. Приоритет пользовательского процесса не влиет на приоритет драйвера СОМ порта при обработке прерываний. Тоже думаю, что проблема просто в переполнении ФИФО аппаратного приёмника. Потому, что винда тупо не успевает выгребать данные. Но тогда надо проверить, флаг переполнения должен быть установлен. Может, стоит попробовать адаптер COM->USB, там аппаратная буферизация может быть лучше, и ошибок не будет?
|
|
|
|
|
May 22 2017, 19:49
|
Гуру
     
Группа: СуперМодераторы
Сообщений: 3 096
Регистрация: 16-01-06
Из: Москва
Пользователь №: 13 250

|
В 7 похоже, есть баг в COM драйвере. Многие программы, нормально работавшие с XP, глючат с ком-портами на 7. Единственное, что надежно под ней работает -USB-COM адаптер, причем с FTDI чипом.
--------------------
Не бойтесь тюрьмы, не бойтесь сумы, не бойтесь мора и глада, а бойтесь единственно только того, кто скажет - "Я знаю как надо". А. Галич.
|
|
|
|
|
May 23 2017, 09:20
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(Ruslan1 @ May 22 2017, 16:23)  AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей! Что именно Вы имеете в виде когда говорите про "прекрасные дрова для КОМ, и даже целый специальный апи в ядро встроен под устройства Comm"? Что именно советуете почитать-посмотреть, может даже применительно к простоте прикручивания в Билдер? Вот это именно и имел ввиду - что вы путаете всех использованием слова "драйвер". В венде уже написаны дрова под множество материнок и уж тем более под известные стандартные контроллеры УАРТ. Вот они как раз напрямую с железом и прерыванием работают. писать их не требуется - они готовы и встроены в Ось. Овь прелагает довольно простое стандартное АПИ для работы с Сомм портами. Если вы поставили борланд - покурите их хелпы Win32 SDK или чтото вроде этого. Это огромный хелп по всем ресурсам венды. и в частности там описан и Comm интерфейс. Если вы полезете в изходники АсинкПро - то наглядно увидите как вендовые вызовы используются. АсинкПро - это обертка вендовых вызовов. Когда я говорю "прекрасные" - значит они есть работают, отлажены, и проверены. (и удобны) Цитата(Ruslan1 @ May 22 2017, 16:23)  AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей!
Если уже есть компонент а или просто апишная функция "брать все байты из порта и кидать в большой пользовательский кольцевой буфер" - было бы замечательно. В пятом Билдере ставил пакет TurboPower Async Professional, но использовал по поллингу. Сейчас на новый (хихи) 6-й билдер перешел и думал без сторонних компонентов обойтись. Большой буфер уже предоставляет Сомм интерфейс, размер его можно настраивать, по моей памяти он по умолчанию 4кБ делается. собственно из него и читается данные порта обычными файловыми чтениями. По моему опыту - оказалось проще работать без оболочек, напрямую. это не требует стороннего кода и возни со сторонними пакетами. требует освоения навыка работы с асинхронными вызовами венды чтения\записи файла - там их называют почемуто overlaped Цитата(Ruslan1 @ May 22 2017, 16:23)  AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей! И это не железо, я пробовал на другом компьютере- эффект тоже имеет место быть. И это действительно потеря в машине- прямо на порт включал независимый лог анализатор, и после сравнивал содержимое буферов его и моей программы. но чтобы окончательно убедиться снифьте ваш траффик на этой же самой машине, либо через прокси, либо тупо на другой порт палралельно сигнал заведите и с него все в журнал. Вам уже посоветовали использовать 1,5-2 стопбита. это хорошее предложение, если оно конечно возможно для ваших абонентов. С адаптерами КОМ-УСБ советую не играться если есть нормальный порт на матери или PCI плате ввода вывода. Я встретил кривой адаптер от МОХи, народ жаловался на ФТДИ - у обоих проблемы с буфером приемника на больших трафиках.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|