1

I am reading NMEA data from the usb input of an Intel Edison. Everything is working fine except for one problem. If I disconnect the RS232 to USB cable from the other two cables that lead to the bulkhead connector, I get a flood of characters sent to the software. They seem to be a large repetition of the last character sent before the cable was disconnected. I assume this is from some kind of interference introduced on the 10 inches or so of open cable. I would like to write some code so that the software can recover but as it is, I need to power cycle the box. Killing and restarting the software does not work. I have tried to just read and dump all the characters coming in until I get a valid pair but this does not work. Here is what I have tried:

    while(1){
    while (new_nmea_read_sentence == 0){
        while(read(tty_fd, &aa, 1) == -1);   // read 1 character from stream (blocking call)
        if(aa != '\n')  {
            local_buffer[idx++] = aa;
            if(idx > 400){
                idx = 0;// prevent segmentation faults
                printf("\nlocal_buffer overflow in read nmea.\n");
                int flag = 1;
                char old = 'x';
                while (flag == 1){
                    read(tty_fd, &aa, 1);
                    if (aa == '\n'  && old == '\r') flag = 0;
                    //printf("<%c>",aa);
                    old = aa;
                }
            }
        }
        else{// deal with valid nmea sentence

This thread is a forever loop reading the data. Other threads deal with it and they pass a volatile flag back and fourth. When this problem happens, the first thing I see is an overflow and I trap that in the code if(idx > 400). Without that I get a segmentation fault. The code below while (flag == 1) is looking for a which I would get if I got any valid data. If the input is an endless string of characters, I continue to get characters even after reconnecting the cable. Restarting the software produces no input.

My only solution is to tell the user to power cycle the box. Not very nice.

0andriy
  • 4,183
  • 1
  • 24
  • 37
Allen Edwards
  • 1,488
  • 1
  • 27
  • 44
  • I would still be interested in a way to clear the port by software. What I ended up doing was 1) Change from an external cable to a cable inside the box so that it cannot be unplugged. 2) Use a metal box and add a filter to my engine to keep engine noise from causing this same problem. 3) If the port does freeze, I open the connection on a different port. But with the first two solutions, the port doesn't freeze so this last part is not necessary. I never did find a way to reset the port in software once it is frozen. – Allen Edwards Feb 03 '17 at 15:14

2 Answers2

0

There is zero error handling in this line:

while(read(tty_fd, &aa, 1) == -1);   // read 1 character from stream (blocking call)

This code read the last character in all error cases, because the return value of read() will be different from -1 and is never checked otherwise. The code above will take it as a sucessful read, but aa will just keep its old value.

Yanking the USB-to-serial cable causes read() to return some error code like EIO or EBADF.

Turbo J
  • 7,563
  • 1
  • 23
  • 43
  • What are you suggesting I do? I should have said I tried closing the connection and re-opening it but it still doesn't clear and allow reads when the data returns. There is error checking later in the code where any sentences read have their checksum verified. – Allen Edwards Dec 23 '14 at 21:34
0

What are you suggesting I do? I should have said I tried closing the connection and re-opening it but it still doesn't clear and allow reads when the data returns. There is error checking later in the code where any sentences read have their checksum verified.

You have to handle errors where they occur, not at some later point where you already processed wrong (i. e. inexistent) data. Change at least

                    read(tty_fd, &aa, 1);

to

        while (read(tty_fd, &aa, 1) < 1) /* perhaps sleep(awhile) */;
Armali
  • 18,255
  • 14
  • 57
  • 171
  • Thanks for replying but I didn't have read(tty_fd, &aa, 1);. I had while(read(tty_fd, &aa, 1) == -1); which I think is similar to what you are suggesting. In any event, I just don't use a cable and don't unplug it any more so problem never comes up. I never did find a way to reset the port in software, which was the question. – Allen Edwards Feb 03 '17 at 15:10
  • @Allen Edwards - You _didn't have read(tty_fd, &aa, 1);_? Look at the twelfth line of the code you posted. – Armali Feb 06 '17 at 07:09