PX4 / PX4-Autopilot

PX4 Autopilot Software
https://px4.io
BSD 3-Clause "New" or "Revised" License
8.57k stars 13.55k forks source link

/dev/ttyS5 dropping serial data #761

Closed jgoppert closed 10 years ago

jgoppert commented 10 years ago

Using /dev/ttyS5 for serial communication with roboclaw drops about half the data with poll while /dev/tty6 works flawlessly. With continuous spinning and collecting all data received, I can get most of the data, but this is not a solution. My thoughts are that either there is something else reading the data from /dev/ttyS5 or that the buffer is set to low. But the buffer is set too 512 in the config. I have searched the source code but have not found anythign reading from this port. I have even killed all processes on the board except my test program and sercon and this problem still exists. I have also tried to use JTAG to detect what is happening but I have had no luck.

Results on /dev/ttyS5

nsh> roboclaw test
starting new test.
roboclaw_test: setting up uart
requesting version
reading version with poll
nsh> poll msg: SB obola 2x5a 4.0
requesting version
reading version w/o poll
no poll msg: 2
{USB Roboclaw 2x15a v4.0.2

Results on /dev/ttyS6 Using /dev/ttyS6 for serial communication with roboclaw works.

nsh> roboclaw test /dev/ttyS6 128
starting new test.
roboclaw_test: setting up uart
requesting version
reading version with poll
nsh> poll msg: USB Roboclaw 2x15a v4.0.2

requesting version
reading version w/o poll
no poll msg: USB Roboclaw 2x15a v4.0.2

Test program.

int roboclaw_test_main(int argc, char *argv[])
{
    test_thread_running = true;
    // defaults
    const char * port = "/dev/ttyS5";
    uint8_t address = 128;
    uint32_t timeout = 10000; // 1 second
    bool doack = false; // do ack for writes

    // parse
    if (argc == 3) {
        port = argv[1];
        address = strtoul(argv[2], nullptr, 0);
    } else if (argc != 1) {
        errx(1, "wrong number of args");
    }

    printf("starting new test.\n");

    // open port
    int uart = open(port, O_RDWR | O_NONBLOCK | O_NOCTTY);
    if (uart < 0) {
        errx(1, "failed to open port: %s", port);
        return 0;
    }

    // setup uart
    warnx("setting up uart");
    struct termios uart_config;
    int ret = tcgetattr(uart, &uart_config);
    if (ret < 0) errx(1, "failed to get attr");
    uart_config.c_oflag &= ~ONLCR; // no CR for every LF
    ret = cfsetispeed(&uart_config, B38400);
    if (ret < 0) errx(1, "failed to set input speed");
    ret = cfsetospeed(&uart_config, B38400);
    if (ret < 0) errx(1, "failed to set output speed");
    ret = tcsetattr(uart, TCSANOW, &uart_config);
    if (ret < 0) errx(1, "failed to set attr");

    // clear old data
    tcflush(uart, TCIOFLUSH);

    // message data
    uint8_t get_version = 21;
    char msg[200];
    char buf[10];

    // request version
    printf("requesting version\n");
    write(uart, &address, 1);
    write(uart, &get_version, 1);

    // read version with poll
    printf("reading version with poll\n");
    struct pollfd uartPoll;
    uint32_t tout = 1000;
    uartPoll.fd = uart;
    uartPoll.events = POLLIN;
    msg[0] = '\0';
    while (true) {
        int pollrc = poll(&uartPoll, 1, tout);
        if (pollrc < 1) break;
        ret = ::read(uart, buf, sizeof(buf)); 
        if (ret < 1) break;
        strncat(msg,(const char *)buf,ret);
    }
    printf("poll msg: %s\n",msg);

    // request version
    printf("requesting version\n");
    write(uart, &address, 1);
    write(uart, &get_version, 1);

    // read version w/o poll
    printf("reading version w/o poll\n");
    msg[0] = '\0';
    for (int i=0;i<10000;i++) {
        ret = ::read(uart, buf, sizeof(buf)); 
        if (ret < 1) {
            continue;
        }
        strncat(msg,(const char *)buf,ret);
    }
    printf("no poll msg: %s\n",msg);

    // close uart
    close(uart);
    test_thread_running = false;
    return 0;
}
LorenzMeier commented 10 years ago

Fixed as far as I recall.