wjwwood / serial

Cross-platform, Serial Port library written in C++
http://wjwwood.github.com/serial/
MIT License
2.11k stars 1.02k forks source link

readline strange behavior, dropping message parts #282

Closed mnissov closed 1 year ago

mnissov commented 1 year ago

I have a strange behavior with readline which I can't seem to trouble shoot myself, connected to a teensy I've found that it will, quite often, drop most of the message and only read the EOL character when using the normal read with an expected size of 10 bytes gets everything and consistently reports arrays which end with "\n"

Serial port /dev/ttyACM0
read buffer length: 10
ffffff8f4e147affffff8f4e147a000a
...
ffffffc156fffffffbffffffd4ffffffc156fffffffbffffffd4000a
read buffer length: 1
0a
read buffer length: 4
ffffffe0ffffff8effffffd80a
read buffer length: 5
ffffffe0ffffff8effffffd8000a

In my minimal case, I fill up a 10-byte buffer with the current cycle count and send it. See the attached code below, the example is quite simple. Note, I have tried this with baud 9600, 12e6, and 480e6; this problem persists in all three

C++ script

#include <serial/serial.h>
#include <unistd.h>
#include <iomanip>
#include <iostream>
#include <string>

int main(int argc, char * argv[])
{
  serial::Serial serial_conn("/dev/ttyACM0", 480000000, serial::Timeout::simpleTimeout(100));

  if (serial_conn.isOpen()) {
    std::cout << "Serial port "
              << "/dev/ttyACM0" << std::endl;
  } else {
    return 0;
  }

  std::string buffer;
  while (true) {
    if (serial_conn.available()) {
      // serial_conn.read(buffer, 10);
      serial_conn.readline(buffer);
      std::cout << "read buffer length: " << (int)buffer.size() << std::endl;

      for (const auto & c : buffer) {
        std::cout << std::hex << std::setfill('0') << std::setw(2) << (unsigned)c;
      }
      std::cout << std::endl;

      buffer.clear();
    }
  }
}

teensy code

#include <Arduino.h>

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
  }
}

const size_t buffer_length = 10;
uint8_t buffer[buffer_length];
void loop()
{
  const uint32_t cycles = ARM_DWT_CYCCNT;
  memcpy(&buffer[0], &cycles, sizeof(uint32_t));
  memcpy(&buffer[4], &cycles, sizeof(uint32_t));
  buffer[8] = 0;
  buffer[9] = '\n';

  Serial.write(buffer, buffer_length);
  Serial.send_now();

  delay(100);
}
mnissov commented 1 year ago

didn't consider to think that a newline character (0x0a) could just happen to be in the data. That's on me