Перейти к содержанию
    

Обнаружение ошибок чётности и др. при приёме ч/з COM порт

Всем доброго.

Ув. эксперты, поскажите, есть ли в виндовых осях возможность обнаруживать ошибки контроля чётности и другие (CE_FRAME, CE_OVERRUN) при получении данных побайтно по последовательному порту ? Пробую тестовую программу - внешним устройством (контроллером) посылается поток байт - часть с ошибкой чётности (точнее, просто с перевёрнутой чётностью), часть - без ошибок. Принимающая часть (программа под виндой) распознаёт только ошибку в самом первом испорченном байте, остальные почему-то молча пропускает - это при приёме через встроенный железный COM порт. При прохождении через виртуальный COM порт (переходник USB<->COM FT232) ещё хуже - не только пропускаются ошибочные байты, но и метятся ошибочными безошибочные данные.

Приём и проверка выполняется вот таким кодом:

static int read_byte (HANDLE handle, uint8_t * byte)
  {
  uint8_t b;
  DWORD ret;

  if (!ReadFile (handle, &b, 1, &ret, 0))
     return -1;

  if (0 == ret)
     return 0;

  DWORD err;
  ClearCommError (handle, &err, 0);

  if (err)
     {
     fprintf (stderr, "\nComm Error: ");
     fprintf (stderr, CE_FRAME & err ? "F" : "-");
     fprintf (stderr, CE_RXPARITY & err ? "P" : "-");
     fprintf (stderr, CE_IOE & err ? "I" : "-");
     fprintf (stderr, CE_OVERRUN & err ? "O" : "-");
     fprintf (stderr, CE_RXOVER & err ? "B" : "-");
     fprintf (stderr, " = %02X ", b);
     return -2;
     }

  *byte = b;
  return 1;
  }

 

Есть код аналогичного назначения под Linux - там всё чётко работает - обнаруживаются все заваленные байты, а правильно отправленные (безошибочные) байты не маркируются как ошибочные, при работе и через реальный и через виртуальный последовательный порт. Можно было бы достичь того же результата в винде ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть код аналогичного назначения под Linux - там всё чётко работает - обнаруживаются все заваленные байты, а правильно отправленные (безошибочные) байты не маркируются как ошибочные

Три раза ха.... железо 550 совместимого порта принципиально не способно в потоке, при включенном FIFO локализовать ошибку в конкретном байте. Посему, поставленная задача надежно не решима в принципе. Отключайте FIFO, принимайте меры по быстрому обслуживанию порта. При мееедленом потоке получите более-менее приближенный к правде результат.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость @Ark
Принимающая часть (программа под виндой) распознаёт только ошибку в самом первом испорченном байте, остальные почему-то молча пропускает - это при приёме через встроенный железный COM порт. При прохождении через виртуальный COM порт (переходник USB<->COM FT232) ещё хуже - не только пропускаются ошибочные байты, но и метятся ошибочными безошибочные данные.

Дело в том, что при получении ошибки приема одного байта в непрерывном потоке (не важно какой - по четности, или по отсутствию стоп-бита), дальнейшее декодирование потока не может быть признано достоверным. Так как не факт, что оно будет начинаться именно со стартового бита следующего байта, а не где-нибудь с середины. Причем, при таком неправильном приеме, могут случайно получиться и "правильные" байты с правильной четностью и корректным стоп-битом. Но нет ни каких гарантий, что это именно то, что передавалось...

По этому, после получения ошибки, не только буфер FIFO, но и весь дальнейший поток нужно проигнорировать - до появления паузы длительностью не менее передачи одного байта. Только после этого можно начать достоверный прием, с заведомо правильного стартового бита.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда можно было-бы переформулировать вопрос:

Если после вызова ClearCommError был получен результат, указывающий на ошибку, означает ли это, что ошибка была обнаружена при приёме хотя бы одного из всех полученных с момента предыдущего вызова ClearCommError байт? В этом случае можно было бы не парится с каждобайтной проверкой, а вызывать её раз в иногда, после получения очередного блока данных смотреть - не было ли ошибок в ходе приёма.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если после вызова ClearCommError был получен результат, указывающий на ошибку, означает ли это, что ошибка была обнаружена при приёме хотя бы одного из всех полученных с момента предыдущего вызова ClearCommError байт?

Именно так дело и обстоит если не приказали блокировать порт при возникновении ошибки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Только в том случае, если блоки разделяются паузой (соответственно, тайм-аутом при приеме).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только в том случае, если блоки разделяются паузой (соответственно, тайм-аутом при приеме).

С чего-бы это вдруг. Железу порта глубоко безразлично наличие пауз между какими-то там неведомыми ему блоками. Железом будут фиксироваться ошибки в байтах. По факту обнаружения ошибок будет взведен соответствующий флаг и (для 550), если приказано, прерывание. Локализация ошибки именно в конкретном блоке, естественно затруднена, по тем-же причинам, что и локализация ошибки в конкретном байте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну я тоже так же и предполагал.

Благодарю за то, что развеяли мои сомнения, в общем на этом можно считать вопрос решённым.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С чего-бы это вдруг.

Я говорил про ленивый и неспешный контроль ошибок. В других случаях, например, при отслеживании символов-разделитей пакета, без означенного прерывания - никак. Никто и не спорит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

железо 550 совместимого порта принципиально не способно в потоке, при включенном FIFO локализовать ошибку в конкретном байте.

Почему? Там ведь вроде как 2 FIFO. Одно на данные, а другое на их ошибки.

Другое дело, что в большинстве случаев то, к какому конкретно байту относится ошибка не имеет значения - всё равно перепередавать весь блок. Да и вообще, из ошибок актуальна только строка нулей, а вместо остальных CRC лучше работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему? Там ведь вроде как 2 FIFO. Одно на данные, а другое на их ошибки.

А может 3 FIFO? Или 4 FIFO? Там действительно 2 FIFO - одно для приема и второе для передачи. Давайте, Вы посмотрите документацию, и тогда не придется фантазировать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Давайте, Вы посмотрите документацию, и тогда не придется фантазировать.

Посмотреть документацию, а не заниматься фантазиями - это действительно хороший совет, но это не только ко мне относится...

Вот, что я вычитал в самом начале документа:

FIFO-буфер приёмника используется также для хранения трёх битов информации об ошибках для каждого символа. Ошибки чётности, кадрирования и BREAK-сигналы буферизируются вместе с символом, у которому они относятся.

Т.е. память меня не подвела и ошибки в FIFO-режиме хранятся на каждый принятый байт и, соответственно, железо позволяет локализовать ошибки с точностью до байта. Ведь собственно об этом был спор...

 

А так же в FIFO-режиме там в регистре LSR в 7-м бите имеется ошибка RFE, про которую написано:

В FIFO-режиме данный разряд устанавливается в 1 при появлении ошибки чётности, кадрирования или сигнала BREAK, которые связаны с одним или несколькими символами в FIFO-буфере приёмника.

Вот этот бит не позволят локализовать ошибки...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость @Ark
... ошибки в FIFO-режиме хранятся на каждый принятый байт и, соответственно, железо позволяет локализовать ошибки с точностью до байта. Ведь собственно об этом был спор...

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот, что я вычитал в самом начале документа:

Таки да - в классическом нейшиналовском 16550D такое поминается!

 

 

вплоть до появления паузы при приеме.

Гарантированные "Паузы" есть - это стоп-старт биты. При ошибках внутренняя логика UART рестартует и осуществляет поиск нового фрейма. Таким образом достоверность байта следующего за сбойным по анализу трех бит (start-parity-stop) гарантируется железом.

 

 

Вот этот бит не позволят локализовать ошибки...

Break это совершено не ошибка - это отдельный сигнал гарантированно детектируемый и при различии в скоростях UART-ов. Особая ценность в том, что детектируется без участия микроконтроллера и может быть использован для приведения в чувство контроллера или переключения режимов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость @Ark
Цитата(zltigo)

При ошибках внутренняя логика UART рестартует и осуществляет поиск нового фрейма. Таким образом достоверность байта следующего за сбойным по анализу трех бит (start-parity-stop) гарантируется железом.

Именно по этой причине:

Принимающая часть (программа под виндой) распознаёт только ошибку в самом первом испорченном байте, остальные почему-то молча пропускает - это при приёме через встроенный железный COM порт.

При прохождении через виртуальный COM порт (переходник USB<->COM FT232) ещё хуже - не только пропускаются ошибочные байты, но и метятся ошибочными безошибочные данные.

То есть все сделано правильно - так, чтобы гарантировать достоверность приема. Зачем автору темы потребовалось обходить это - мне не совсем понятно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...