5 Replies Latest reply on Nov 8, 2016 11:00 AM by Intel Corporation

    HSU (uart) parity check on receive not working?

    FerryT

      We might be doing something wrong here, but whatever we try we don't get parity errors detected.

       

      In our setup we are using base64 encoding to transfer binary data as text, so frames are started with STX (0x02) and terminated by ETX (0x03). We precede the STX by 2 PREAMBLES on transmit and require minimum 1 on receive. This way we can always correctly detect the start and end of a frame.

       

      In the ideal case a char with a FE or PE should be translated to 0x00, but whatever we try this doesn't happen.

       

      To test this we used 2 Edisons happily talking to each other at 8bit, 2Mb/s, 1 stop bit, however one is using parity EVEN, the other ODD. This means that a PE happens on every char received. This has been verified by our oscilloscope which has a very clever 'serial decode' function and shows PE for each decoded byte. But the Edisons are both ignoring the PE and not replacing the error byte by 0x00 (or prefixing by 0xFF 0x00, or discarding the char completely). We know the messages are received entirely without errors because we use a CRC32C on the message (after base64 decoding) and toggle a GPIO on success).

       

      I think the kernel code taking care of FE and PE is here; https://github.com/01org/edison-linux/blob/edison-3.10.17/drivers/tty/serial/mfd_core.c

       

      Apparently the HSU is not using n_tty.c line dicipline, but doing a new implementation.

       

      In lines 1341 is the serial_hsu_set_termios function, that should be taking care of IGNPAR, INPCK, PARMRK flags (line 1499 - 1517).

       

      We are using MRAA but using the following code to configure the port, because not everything can be set in MRAA (and because of bugs in MRAA we had earlier). I honestly can not see what we are doing wrong here, and I am starting to suspect a problem in the hsu kernel code (although I can't find that problem in the mfd_core.c ref'd above).

       

      The whole problem should be easily reproducible using 2 Edisons (with Arduino carrier) and connecting RX-TX and vice versa (as well as the GND). Our code is here https://github.com/htot/hs_uart. If you allow me a day or so, I will push our latest code, which in addition has a command line option to switch from parity ODD to EVEN so you only need to use a single executable on both edisons ./hs_uart for ODD and ./hs_uart -e for EVEN. I will post back here when that has happened.

       

      int

      set_interface_attribs (int fd, int speed, tcflag_t parity, int disableFlowControl)

      {

              struct termios tty;

              memset (&tty, 0, sizeof tty);

              if (tcgetattr (fd, &tty) != 0)

              {

                      printf ("error %d from tcgetattr", errno);

                      return -1;

              }

       

              cfsetospeed (&tty, speed);

              cfsetispeed (&tty, speed);

       

              tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars

              // disable IGNBRK for mismatched speed tests; otherwise receive break

              // as \000 chars

              tty.c_iflag &= ~IGNBRK;         // disable break processing

              tty.c_lflag = 0;                // no signaling chars, no echo,

                                              // no canonical processing

              tty.c_oflag = 0;                // no remapping, no delays

              tty.c_cc[VMIN]  = 0;            // read doesn't block

              tty.c_cc[VTIME] = 0;            // no timeout

       

              tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

              tty.c_iflag &= ~IGNPAR;         // do not ignore parity and framing errors

              tty.c_iflag &= ~PARMRK;         // parity or framing error char replaced with \0

              tty.c_iflag |= INPCK;           // enable parity checking

       

              tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,

                                              // enable reading

              tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity

              tty.c_cflag |= parity;

              tty.c_cflag &= ~CSTOPB;

              if(disableFlowControl)

                tty.c_cflag &= ~CRTSCTS; // no rts/cts

              else

                tty.c_cflag |= CRTSCTS; // enable rts/cts

       

              if (tcsetattr (fd, TCSANOW, &tty) != 0)

              {

                      printf ("error %d from tcsetattr", errno);

                      return -1;

              }

              return 0;

      }

       

      The function is called with parity = (PARENB | PARODD) or parity = PARENB, and flow control disabled (we gave up on that one).

       

      Ferry