Ruslan1 17 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба Здравствуйте! Есть 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. куда копать? Сильно надеюсь что моя программа виновата. На другом железе пробовал- эффект тот же, то есть это не электроника глючит. С приоритетами игрался, никакого эффекта. Заранее спасибо за любые советы (по существу). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 22 мая, 2017 Опубликовано 22 мая, 2017 (изменено) · Жалоба Есть поток, принимающий все байты по прерываниям и валящий в большой кольцевой буфер. И другой поток периодически выгребает байты из буфера и делит на пакеты для обработки, проверяет валидность. Вот это место непонятно - для каждого порта свой буфер, или общий на все порты? выпадание байта определяете по сбою crc? Что Вы называете "приемом по прерыванию"? У выни свои прекрасные дрова для КОМ, и даже целый специальный апи в ядро встроен под устройства Comm - модемы проще. все известные мне либы в борланде являются прокладкой к этому стандартному АПИ. напрямую с прерыванием никто не работает. проблем с потерями не было, хотя обмен бывал интенсивный - мегабод. можно посоветовать покрутить : 1)объем буфферов кома (я делал 8кб) 2)приоритет нитки приемника сделать выше нормального 3)если у вас между пакетами есть пауза более 1мс, настроить ее в свойствах таймингов кома. в запросах асинхронного чтения возможно оно поможет АПИ возвращать целиком пакет а не куски случайно презанные. 4)какая может быть гарантия что порт вашего ПК видит ваш поток без потерь, даже если ваш снифер прекрасен? Вы в качестве снифера тот же самый ПК используете? 5) можно поставить прокси с журналированием на ком (я пользовал com0project, но их вроде множество разных), и уже к нему подключать вашу программу. в этом случае вы сможете сравнить поток принятый прокси с потоком принятым вашей софтиной. 6) вы журналировали поток считанный из порта, сравнить его с финальными нарезанными пакетами? точно эти байты не считываются из порта? Изменено 22 мая, 2017 пользователем AlexRayne Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба Начинать надо с того, что COM порт вообще и его реализация в Windows в частности, не гарантирует безошибочной передачи данных. То есть рассчитывать на это нельзя, и контроль и/или обеспечение целостности данных надо реализовывать в протоколе обмена. Поврежненный пакед должен отбрасываться и если нужно передаваться повторно. По возможным причинам. У стандартного аппаратного СОМ порта есть внутренний буфер, как правило размером 15 байт. Это не тот буфер, который задается в SetupComm. Если драйвер порта по каким-то причинам не успеет прочитать этот буфер, то принятые байты теряются, о чем извещают соответствующие флаги возвращаемые ClearCommError. Приоритет пользовательского процесса не влиет на приоритет драйвера СОМ порта при обработке прерываний. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба Начинать надо с того, что COM порт вообще и его реализация в Windows в частности, не гарантирует безошибочной передачи данных. То есть рассчитывать на это нельзя, и контроль и/или обеспечение целостности данных надо реализовывать в протоколе обмена. Поврежненный пакед должен отбрасываться и если нужно передаваться повторно. Парень сборется с другой проблемой - у него не пропадание сигнала на линии (этим он займется видимо позже, когда жареный петух клюнет), а пропадание байтов прямо на порте. можно это списать на особенности железа, но вероятность невелика Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей! Что именно Вы имеете в виде когда говорите про "прекрасные дрова для КОМ, и даже целый специальный апи в ядро встроен под устройства Comm"? Что именно советуете почитать-посмотреть, может даже применительно к простоте прикручивания в Билдер? Я раньше работал по поллингу, и задачи другие были. А сейчас решил по прерываниям сделать, нашел понятное мне описание в интернете(ссылка в моем письме)- по нему и сделал. Если уже есть компонент а или просто апишная функция "брать все байты из порта и кидать в большой пользовательский кольцевой буфер" - было бы замечательно. В пятом Билдере ставил пакет TurboPower Async Professional, но использовал по поллингу. Сейчас на новый (хихи) 6-й билдер перешел и думал без сторонних компонентов обойтись. И это не железо, я пробовал на другом компьютере- эффект тоже имеет место быть. И это действительно потеря в машине- прямо на порт включал независимый лог анализатор, и после сравнивал содержимое буферов его и моей программы. Очень хочется для начала локализовать проблему, и Ваши советы мне отлично подходят- не подумал про независимый сниффер-программу прямо на этой машине. Очень надеюсь что проблема в моем коде- тогда есть большая вероятность ее решения :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба Что Вы называете "приемом по прерыванию"? У выни свои прекрасные дрова для КОМ, и даже целый специальный апи в ядро встроен под устройства Comm - модемы проще. все известные мне либы в борланде являются прокладкой к этому стандартному АПИ. напрямую с прерыванием никто не работает. Нда, последнее сообщение автора прояснило что прерывание это не то прерывание о котором все подумали, а прерывание есть прерывание потока, по крайней мере так описано по ссылке :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба Начинать надо с того, что COM порт вообще и его реализация в Windows в частности, не гарантирует безошибочной передачи данных. То есть рассчитывать на это нельзя, и контроль и/или обеспечение целостности данных надо реализовывать в протоколе обмена. Поврежненный пакед должен отбрасываться и если нужно передаваться повторно. По возможным причинам. У стандартного аппаратного СОМ порта есть внутренний буфер, как правило размером 15 байт. Это не тот буфер, который задается в SetupComm. Если драйвер порта по каким-то причинам не успеет прочитать этот буфер, то принятые байты теряются, о чем извещают соответствующие флаги возвращаемые ClearCommError. Приоритет пользовательского процесса не влиет на приоритет драйвера СОМ порта при обработке прерываний. Тоже думаю, что проблема просто в переполнении ФИФО аппаратного приёмника. Потому, что винда тупо не успевает выгребать данные. Но тогда надо проверить, флаг переполнения должен быть установлен. Может, стоит попробовать адаптер COM->USB, там аппаратная буферизация может быть лучше, и ошибок не будет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rx3apf 0 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба 1. Дурацкий вопрос - а порты вообще с FIFO ? И оно включено ? 2. Как вариант, запустить какую-нибудь терминалку, залоггировать, а потом посмотреть - потери есть ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Raven 11 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба Если Wind'а иногда не успевает выгребать данные из аппаратного буфера, может стоит подумать в сторону аппаратного управления потоком (RTS/CTS)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DS 0 22 мая, 2017 Опубликовано 22 мая, 2017 · Жалоба В 7 похоже, есть баг в COM драйвере. Многие программы, нормально работавшие с XP, глючат с ком-портами на 7. Единственное, что надежно под ней работает -USB-COM адаптер, причем с FTDI чипом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 мая, 2017 Опубликовано 23 мая, 2017 · Жалоба Я пересылал в комп пакеты данных на скорости 115200, сбоев не замечал. Формат был 8N2. Вот его и посоветую попробовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
V_G 8 23 мая, 2017 Опубликовано 23 мая, 2017 · Жалоба Я пересылал в комп пакеты данных на скорости 115200, сбоев не замечал. Формат был 8N2. Вот его и посоветую попробовать. Да я тоже много чего пересылал, и на 480 кБод, и без сбоев. Насколько я понял, особенность проблем ТС в том, что данные идут постоянно, что в моей практике не встречается. Хотя я Билдер не пользую, пишу в MSVC++ с отдельным потоком на прием и WaitCommEvent в том потоке с ивентом по каждому пришедшему байту... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 мая, 2017 Опубликовано 23 мая, 2017 · Жалоба Возможно, фантазирую, детально не вникал, полагаю, если стопов 2 или 1,5 то синхронизироваться по следующему старту можно точнее. Будет больше запаса на неравенство тактовых частот. А также увеличивается время для работы процессора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 23 мая, 2017 Опубликовано 23 мая, 2017 · Жалоба AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей! Что именно Вы имеете в виде когда говорите про "прекрасные дрова для КОМ, и даже целый специальный апи в ядро встроен под устройства Comm"? Что именно советуете почитать-посмотреть, может даже применительно к простоте прикручивания в Билдер? Вот это именно и имел ввиду - что вы путаете всех использованием слова "драйвер". В венде уже написаны дрова под множество материнок и уж тем более под известные стандартные контроллеры УАРТ. Вот они как раз напрямую с железом и прерыванием работают. писать их не требуется - они готовы и встроены в Ось. Овь прелагает довольно простое стандартное АПИ для работы с Сомм портами. Если вы поставили борланд - покурите их хелпы Win32 SDK или чтото вроде этого. Это огромный хелп по всем ресурсам венды. и в частности там описан и Comm интерфейс. Если вы полезете в изходники АсинкПро - то наглядно увидите как вендовые вызовы используются. АсинкПро - это обертка вендовых вызовов. Когда я говорю "прекрасные" - значит они есть работают, отлажены, и проверены. (и удобны) AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей! Если уже есть компонент а или просто апишная функция "брать все байты из порта и кидать в большой пользовательский кольцевой буфер" - было бы замечательно. В пятом Билдере ставил пакет TurboPower Async Professional, но использовал по поллингу. Сейчас на новый (хихи) 6-й билдер перешел и думал без сторонних компонентов обойтись. Большой буфер уже предоставляет Сомм интерфейс, размер его можно настраивать, по моей памяти он по умолчанию 4кБ делается. собственно из него и читается данные порта обычными файловыми чтениями. По моему опыту - оказалось проще работать без оболочек, напрямую. это не требует стороннего кода и возни со сторонними пакетами. требует освоения навыка работы с асинхронными вызовами венды чтения\записи файла - там их называют почемуто overlaped AlexRayne, большое спасибо за конструктивный ответ с кучей хороших идей! И это не железо, я пробовал на другом компьютере- эффект тоже имеет место быть. И это действительно потеря в машине- прямо на порт включал независимый лог анализатор, и после сравнивал содержимое буферов его и моей программы. но чтобы окончательно убедиться снифьте ваш траффик на этой же самой машине, либо через прокси, либо тупо на другой порт палралельно сигнал заведите и с него все в журнал. Вам уже посоветовали использовать 1,5-2 стопбита. это хорошее предложение, если оно конечно возможно для ваших абонентов. С адаптерами КОМ-УСБ советую не играться если есть нормальный порт на матери или PCI плате ввода вывода. Я встретил кривой адаптер от МОХи, народ жаловался на ФТДИ - у обоих проблемы с буфером приемника на больших трафиках. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
V_G 8 23 мая, 2017 Опубликовано 23 мая, 2017 · Жалоба Кстати, о больших трафиках. Так ли они необходимы? Очень много встречал профессиональных программистов, которые для своего личного удобства используют большие скорости и постоянно кидают в порт повторяющиеся данные (типа проверки связи и информации "я живой"). Причем в ситуациях, когда достаточно скорости 9600 и работы по принципу "запрос-ответ". А потом еще переносят эти принципы на радиоканал и забивают все вокруг. Может, все-таки сначала подумать о минимизации трафика? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться