Boost :: asio мешает моему последовательному порту? - PullRequest
0 голосов
/ 21 октября 2019

Короткая версия:

  • У меня был код A, позволяющий мне читать / записывать байты через последовательный порт (UART), который прошел модульное тестирование
  • Я написал некоторый код B для чтения / записи байтов по TCP / IP с использованием boost asio (ну, технически, автономного asio), который также прошел модульное тестирование
  • Когда я пытаюсь соединить A и B вместе,A начинает получать сообщения, когда ни одно из них не отправлено
  • Я хочу знать, почему, и что я могу с этим сделать

Подробнее о коде A:

Код A - это в основном код C, использующий ioctl, fnctl и unistd.

Сначала я открываю сериал:

// Flag explanation:
//  - O_RDWR
//     = read & write
//     (O_RDONLY = read-only)
//     (O_WRONLY = write-only)
//  - O_NOCTTY
//     = if the path points to a terminal, that terminal will
//       not become the controlling terminal for the process
//  - O_NONBLOCK
//     = read/write requests are non-blocking, and return failure status instead of waiting
_filestream = ::open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NONBLOCK);

После проверки того, что сериалбыл успешно открыт, я настраиваю UART

// Get options currently used by the USART
termios options;
tcgetattr(_filestream, &options);

// Set control options
{
    // Set baudrate
    cfsetispeed(&options, static_cast<speed_t>(baudrate));
    cfsetospeed(&options, static_cast<speed_t>(baudrate));

    // Enable receiver (those flags must always be set)
    //  CLOCAL  = ignore modem status lines
    //  CREAD   = enable receiver
    options.c_cflag |= (CLOCAL | CREAD);

    // Set character size
    //  CSIZE   = bitmask for all sizes
    //  CS8     = specific flag for 8-bit
    options.c_cflag &= ~static_cast<unsigned int>(CSIZE);
    options.c_cflag |= CS8;

    // Disable parity bit
    //  PARENB = parity enable flag
    options.c_cflag &= ~static_cast<unsigned int>(PARENB);

    // Set number of stop bits
    //  CSTOPB = use 2 stop bits insteqd of 1
    options.c_cflag &= ~static_cast<unsigned int>(CSTOPB);
}


// Set local options
{
    // Make sure to use raw input (pass character exactly as they are received)
    // and not canonical input (which is line-oriented)
    //  ICANON  = enable canonical input
    //  ECHO    = enable echoing input characters
    //  ECHOE   = make echo erases some characters
    //  ISIG    = enable some signals
    options.c_lflag &= ~static_cast<unsigned int>(ICANON | ECHO | ECHOE | ISIG);
}


// Set input options
{
    // Enable software flow control
    //  IXON    = Enable software flow control (outgoing)
    //  IXOFF   = Enable software flow control (incoming)
    //  IXOFF   = Allow any character to start flow again
    options.c_iflag |= (IXON | IXOFF | IXANY);
}


// Set output options
{
    // Choose raw output
    //  OPOST = choose postprocess output
    options.c_oflag &= ~static_cast<unsigned int>(OPOST);
}


// Set options to use for the USART
//  TCSANOW = change attributes immediately
tcsetattr(_filestream, TCSANOW, &options);

Чтобы записать материал в сериал, я делаю это:

int status = write(_filestream, &byte_array, array_size);

и просматриваю статус, чтобы убедиться, что все прошло хорошо.

Чтобы узнать, сколько байтов доступно для чтения, я делаю это:

int nbAvailable = 0;
ioctl(_filestream, FIONREAD, &nbAvailable);

Чтобы фактически прочитать эти байты, я делаюэто:

uint8_t c;
auto status = ::read(_filestream, &c, 1);

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

Когда я закончу, я просто закрою поток файлов:

close(_filestream);

Подробнее о коде B:

Не так много, чтобы сказать, сначала я делаю это:

asio::io_context _ioContext;
asio::ip::tcp::resolver::query query(remoteIP, remotePort);
asio::ip::tcp::resolver resolver (_ioContext);

asio::error_code errCode;
asio::ip::tcp::resolver::results_type _endPoints = resolver.resolve(query, errCode);

if (errCode)
{
    std::cerr << "Cannot resolve IP/port for the connection" << std::endl;
        exit(0);
}

Затем я подключаюсь вот так

asio::error_code errCode;
asio::connect(_socket, _endPoints, errCode);
if (!errCode)
{
        launch_thread();
}

Сам поток представляет собой цикл, в котором байты считываются с использованием _socket.read_some(), затем перемещаются в массив с защитой мьютекса или перемещаются из другого массива с защитой мьютекса, а затем отправляются с использованием _socket.write_some()


Что происходит, когда я соединяю два кода:

Устройство с последовательным портом в настоящий момент отключено, я ожидаю, что nbAvailable будет 0 каждый раз, когда я проверяю, сколько байтовдоступны через последовательный порт, но это не так, и многие байты принимаются, когда их не должно быть.

Насколько я могу судить, это, кажется, результат asio выполнения действийна сериал я использую. Это не так уж надумано, поскольку asio также включает средства ввода-вывода с последовательным портом в дополнение к их средствам TCP / IP, и все свидетельства указывают на это:

  • проблемы только возникаюткогда начинается соединение TCP / IP
  • комментирование вызовов _socket.write_some () устраняет проблему

Что я хочу знать:

Почему asio мешает моей связи через последовательный порт, когда я использую только его средства TCP / IP? Есть ли способ решить эту проблему?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...