title: How to fix timeout on rs232 serial port?
body: <p>I have a problem when reading from the serial port. 
  The problem is that for the last 2 bytes ( CRC bytes ) read from an <code>rs232</code> port the read waits until the timeout set in <code>timeval</code> ends, then returns. On <code>rs485</code>, with the same method used for reading, read returns fine. What I have seen while debbuging is that on <code>rs485</code> there is an extra byte with value <code>FF</code> after the 2 CRC bytes. I can't find another difference between the 2.</p>
  
  <p>Here are the relevant parts of code:</p>
  
  <p><strong>setting the port</strong></p>
  
  <pre><code>bool Serial::setup(){
  
  
      if(!openPort()){
          return false;
      }
  
      tcgetattr(fdPort, &amp;options);
  
      cfsetispeed(&amp;options, B115200);
      cfsetospeed(&amp;options, B115200);
  
      options.c_cflag &amp;= ~PARENB;
  
      options.c_cflag &amp;= ~CSTOPB;
      options.c_cflag &amp;= ~CSIZE;
      options.c_cflag |= CS8;
  
      options.c_cc[VMIN] = 0; 
      options.c_cc[VTIME] = 1;
  
      options.c_oflag &amp;= ~(OCRNL | ONLCR | ONLRET |
                           ONOCR | OFILL | OLCUC | OPOST);
  
      options.c_iflag &amp;= ~(IGNBRK | BRKINT | ICRNL | INLCR | 
                          PARMRK | INPCK | ISTRIP | IXON) ;
  
      options.c_lflag &amp;= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
  
      if(tcsetattr(this-&gt;fdPort, TCSANOW, &amp;options)){
          return false;
      }
  
      return true;
  
  }
  </code></pre>
  
  <p><strong>opening the port</strong></p>
  
  <pre><code>bool Serial::openPort(){
      this-&gt;fdPort = open(this-&gt;port, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
  
      if(fdPort == -1){
          return false;
      }
      else{
          //fcntl(fdPort, F_SETFL, 0);
          //fcntl(fdPort, F_SETFL, FNDELAY);
      }
  
      int status = 0;
  
      status |= TIOCM_RTS;
      ioctl(this-&gt;fdPort, TIOCMSET, &amp;status);
  
      return true;
  
  }
  </code></pre>
  
  <p><strong>The wait frame where data is interpreted and read in chunks.</strong></p>
  
  <pre><code>bool GlobalProtocol::WaitFrame(uint32_t timeOut) {
  
      int32_t bytesRec = 0;
      int32_t bytesToRec = 1;
      int recPhase = GC_PHASE_START;
  
      uint8_t *pData = m_RxBuff;
      bool commSuccess = true;
  
      m_LastError = boards::GCL_ERR_OK;
  
      while (readData(pData, bytesToRec, &amp;bytesRec, timeOut)) {
          if (bytesRec) {
              switch (recPhase) {
              case GC_PHASE_START:
                  if (*pData != GC_START_FRAME_BYTE) {
                      continue;
                  }
                  recPhase++;
                  pData++;
                  break;
              case GC_PHASE_DEST:
                  if (*pData != m_MasterAddr) {
                      commSuccess = false;
                      break;
                  }
                  recPhase++;
                  pData++;
                  break;
              case GC_PHASE_SRC:
                  recPhase++;
                  pData++;
                  break;
              case GC_PHASE_LEN_LO:
                  if (*pData &lt; 2 || *pData &gt; GC_MAX_COMM_DATA_LEN) {
                      commSuccess = false;
                      break;
                  }
                  recPhase++;
                  pData++;
                  break;
              case GC_PHASE_LEN_HI:
                  if (*pData != 0) {
                      commSuccess = false;
                      break;
                  }
                  recPhase++;
                  pData++;
                  bytesToRec = m_RxBuff[GC_PHASE_LEN_LO];
                  break;
              case GC_PHASE_DATA:
                  if (bytesRec != bytesToRec) {
                      commSuccess = false;
                      break;
                  }
                  recPhase++;
                  pData += bytesRec;
                  bytesToRec = 2;
                  break;
              case GC_PHASE_CRC_LO:
                  if (bytesRec != bytesToRec) {
                      commSuccess = false;
                      break;
                  }
                  if (CheckCRC(m_RxBuff, m_RxBuff[GC_PHASE_LEN_LO] + GC_PHASE_DATA + sizeof(uint16_t))) {
                      m_RecAddr = m_RxBuff[GC_PHASE_SRC];
                      return true;
                  }
                  commSuccess = false;
                  break;
              }
              if (!commSuccess) break;
          }
          else break;
      }
      m_LastError = boards::GCL_ERR_ANSWERNOTREC;
  
      return false;
  }
  </code></pre>
  
  <p><strong>And where the reading is done.</strong></p>
  
  <pre><code>bool Serial::readData(uint8_t *data, uint32_t length, int32_t *receivedDataBytes, int32_t timeoutVal){
      int32_t tempReceivedDataBytes = -1;
  
      fd_set readFd;
      FD_ZERO(&amp;readFd);
      FD_SET(fdPort, &amp;readFd);
      struct timeval timeout;
      timeout.tv_sec = 0;
      timeout.tv_usec = timeoutVal * 1000;
      int test = 0; 
      uint32_t bytesAvail = 0;
  
      QTime timer;
  
      timer.start();
  
      if(fcntl(fdPort, F_GETFD) != -1){
          while(((test = select(this-&gt;fdPort + 1, &amp;readFd, NULL, NULL, &amp;timeout)) == 1) &amp;&amp; (tempReceivedDataBytes == -1)){
  
              ioctl(fdPort, FIONREAD, &amp;bytesAvail);
  
              if(FD_ISSET(fdPort, &amp;readFd) &amp;&amp; bytesAvail &gt;= length){
                  tempReceivedDataBytes = read(fdPort, data, length);
              }
  
              if(timer.elapsed() &gt; (timeoutVal + 5)){ //fail-safe
                  logger[debug_log] &lt;&lt; "TIMEOUT" &lt;&lt; endl;
                  break;
              }
  
          }
  
          if(test == -1)
              logger[debug_log]&lt;&lt; strerror(errno) &lt;&lt; endl;
  
          if(tempReceivedDataBytes &lt; 0){
              return false;
          }
          if(tempReceivedDataBytes &gt;= 0){
              *receivedDataBytes = tempReceivedDataBytes;
              return true;
          }
  
      }
  
      return false;
  }
  </code></pre>
  
  <p>If I set the timeout to 100 ms, then it waits 100 ms to read the 2 bytes, if I set it to 10 ms, then it waits 10 ms to read the 2 bytes.</p>
  
  <p>I tried changing the port settings, but with no success.</p>
  
  <p>I have been trying to solve this for days but with no success.</p>
  
  <p><strong>Edit:</strong>
  I should add that <code>ioctl(fdPort, FIONREAD, &amp;bytesAvail);</code> is setting <code>bytesAvail</code> to 2, but <code>read</code> waits until timeout to read them.</p>
  
  <p><strong>Edit 2:</strong></p>
  
  <p><strong>Here is a log with a timeout set to 25 seconds so you can get an idea of what's the problem:</strong></p>
  
  <pre><code>04/17/2014 15:51:50:584,Main board start:
  04/17/2014 15:51:50:586,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:586,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:586,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:587,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:587,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:597,1 Received 110 Needed to receive 110
  04/17/2014 15:51:50:597,1 Received 2 Needed to receive 2
  04/17/2014 15:51:50:634,PID board start:
  04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
  04/17/2014 15:51:50:641,1 Received 70 Needed to receive 70
  04/17/2014 15:52:15:647,0 Received 2 Needed to receive 2
  04/17/2014 15:52:15:647,Set Leds board start:
  04/17/2014 15:52:15:649,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:649,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:652,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:652,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:652,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:652,1 Received 2 Needed to receive 2
  04/17/2014 15:52:15:652,1 Received 2 Needed to receive 2
  04/17/2014 15:52:15:652,Get state board start:
  04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:655,1 Received 1 Needed to receive 1
  04/17/2014 15:52:15:657,1 Received 30 Needed to receive 30
  04/17/2014 15:52:15:657,1 Received 2 Needed to receive 2
  </code></pre>
  
  <p><strong>The one with the problems is the PID board ( on a rs232), the others are on the same rs485.</strong></p>
  
  <p><strong>And here is one with a timeout set to around 30 ms ( I can't remember the exact value):</strong></p>
  
  <pre><code>04/17/2014 15:08:08:045,Main board start:
  04/17/2014 15:08:08:046,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:046,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:046,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:047,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:047,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:056,1 Received 110 Needed to receive 110
  04/17/2014 15:08:08:056,1 Received 2 Needed to receive 2
  04/17/2014 15:08:08:078,PID board start:
  04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:094,1 Received 70 Needed to receive 70
  04/17/2014 15:08:08:120,0 Received 2 Needed to receive 2
  04/17/2014 15:08:08:120,Set Leds board start:
  04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:122,1 Received 2 Needed to receive 2
  04/17/2014 15:08:08:122,1 Received 2 Needed to receive 2
  04/17/2014 15:08:08:123,Get state board start:
  04/17/2014 15:08:08:124,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:124,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:124,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:125,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:125,1 Received 1 Needed to receive 1
  04/17/2014 15:08:08:128,1 Received 30 Needed to receive 30
  04/17/2014 15:08:08:128,1 Received 2 Needed to receive 2
  </code></pre>
  
  <p><strong>Edit: I still can't figure out what is wrong. If I remove the extra byte on rs485 it is the same. Here is another log:</strong></p>
  
  <pre><code>06/24/2014 12:57:01:923,Set Leds board start:
  06/24/2014 12:57:06:701,Select value 1 Received: 1 Needed: 1 Bytes available: 9
  06/24/2014 12:57:06:701,Select value 1 Received: 1 Needed: 1 Bytes available: 8
  06/24/2014 12:57:06:702,Select value 1 Received: 1 Needed: 1 Bytes available: 7
  06/24/2014 12:57:06:702,Select value 1 Received: 1 Needed: 1 Bytes available: 6
  06/24/2014 12:57:06:702,Select value 1 Received: 1 Needed: 1 Bytes available: 5
  06/24/2014 12:57:06:702,Select value 1 Received: 2 Needed: 2 Bytes available: 4
  06/24/2014 12:57:06:752,Select value 0 Received: 2 Needed: 2 Bytes available: 2
  06/24/2014 12:57:06:752,Get state board start:
  06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 4
  06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 3
  06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 2
  06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 1
  06/24/2014 12:57:06:755,Select value 1 Received: 1 Needed: 1 Bytes available: 10
  06/24/2014 12:57:06:758,Select value 1 Received: 30 Needed: 30 Bytes available: 30
  06/24/2014 12:57:06:808,Select value 0 Received: 2 Needed: 2 Bytes available: 2
  06/24/2014 12:57:06:886,Main board start:
  06/24/2014 12:57:06:888,Select value 1 Received: 1 Needed: 1 Bytes available: 3
  06/24/2014 12:57:06:888,Select value 1 Received: 1 Needed: 1 Bytes available: 2
  06/24/2014 12:57:06:889,Select value 1 Received: 1 Needed: 1 Bytes available: 1
  06/24/2014 12:57:06:890,Select value 1 Received: 1 Needed: 1 Bytes available: 23
  06/24/2014 12:57:06:890,Select value 1 Received: 1 Needed: 1 Bytes available: 22
  06/24/2014 12:57:06:898,Select value 1 Received: 110 Needed: 110 Bytes available: 113
  06/24/2014 12:57:06:898,Select value 1 Received: 2 Needed: 2 Bytes available: 3
  </code></pre>
  
  <p>As you can see when the number of available bytes is equal with the number of bytes to read it waits in the read function until timeout and then returns.</p>