Почему чтение из последовательного порта с использованием `poll ()` иногда возвращает `0x00` вместо фактического байта?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Почему чтение из последовательного порта с использованием `poll ()` иногда возвращает `0x00` вместо фактического байта?

Сообщение Anonymous »

Я работаю над приложением Linux, которое связано с модемом HART над последовательным портом , в частности, с использованием модема FTDI USB-to-Serial . Приложение использует boost.asio для асинхронной последовательной связи. Например, когда устройство отправляет {0x0a, 0x0b, 0x0c} , приложение получает {0x0a, 0x0b, 0x00} .
Для изучения я создал упрощенную тестовую программу (не используя Boost.asio), что MIMICS поведение с низкими системами системы Live-Level System. Вот минимальный воспроизводимый пример < /strong>, который повторяет проблему.

Код: Выделить всё

int fd = open(comPort.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);

while (true) {
uint8_t byte;
ssize_t n = read(fd, &byte, 1);

if (n > 0) {
SPDLOG_INFO("Read byte: 0x{:02X}", byte);
} else if (n == -1 && errno != EAGAIN) {
SPDLOG_ERROR("Read error: {}", strerror(errno));
break;
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}

close(fd);
< /code>
Эта версия работает надежно-все байты принимаются правильно, включая контрольную сумму. < /p>

 ❌ Проблемная версия (с использованием poll () < /code>): < /h3>
 0) {
SPDLOG_INFO("Read byte: 0x{:02X}", byte);
} else if (n == -1 && errno != EAGAIN) {
SPDLOG_ERROR("Read error: {}", strerror(errno));
break;
} else {
pollfd pfd{};
pfd.fd = fd;
pfd.events = POLLIN;

int ret = poll(&pfd, 1, -1);
if (ret == -1) {
SPDLOG_ERROR("poll() error: {}", strerror(errno));
break;
} else if (ret > 0 && (pfd.revents & POLLIN) == 0) {
SPDLOG_ERROR("revents[{}] != POLLIN[{}]", pfd.revents, POLLIN);
break;
}

// No delay here
}
}

close(fd);
Эта версия работает Большинство времени, но очень время отредка последний байт сообщения принимается как 0x00 . Обычно это происходит на контрольной сумме byte < /strong>, что приводит к ошибкам проверки сообщений.

Код: Выделить всё

// Inside the poll() block
std::this_thread::sleep_for(std::chrono::microseconds(1));
Добавление даже 1-Microsecond Dolempt [/b] после опроса () постоянно предотвращает проблему. Все байты, включая контрольную сумму, получены правильно.

Код: Выделить всё

asio::io_context ioContext;

asio::serial_port serial(ioContext);
serial.open(comPort);
serial.set_option(asio::serial_port_base::baud_rate(1200));
serial.set_option(asio::serial_port_base::character_size(8));
serial.set_option(asio::serial_port_base::parity(asio::serial_port_base::parity::odd));
serial.set_option(asio::serial_port_base::flow_control(asio::serial_port_base::flow_control::none));
serial.set_option(asio::serial_port_base::stop_bits(asio::serial_port_base::stop_bits::one));

uint8_t byte;
asio::error_code ec;
while (true) {
size_t len = asio::read(serial, asio::buffer(&byte, 1), ec);
if (ec) {
SPDLOG_ERROR("Error reading from serial port: {}", ec.message());
break;
}
SPDLOG_INFO("Read byte: 0x{:02X}", byte);
}

serial.close();
< /code>

 🔍 Мои вопросы < /h2>

  [b] Почему это происходит? />    это известная проблема или условие гонки [/b] при использовании olp () 
с неблокирующим последовательным вводом/выводом на серийных устройствах USB FTDI (или в целом)? oppl () ? Или есть более надежный подход - особенно при использовании boost.asio?>

Подробнее здесь: https://stackoverflow.com/questions/795 ... 0x00-inste
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»