QSerialPort - waitForReadyRead/clear issues Win10/Keyspan



  • Hi All,

    I've run into a strange problem with QSerialPort. As our company purchases new devices for an instrument we are building I'm called upon to create a small test program for each.

    We recently received a motorized valve that has a TTL level serial port on it. I built a level converter and interfaced it to my Keyspan 19 HS USB to serial adapter. I first verified that I could talk to the valve using Putty terminal. I was able to send/receive data from the value without issues.

    I then set to creating a small Qt widgets program to allow our mechanical engineer to control the valve. The serial protocol is very simple: 19200,N,8,1 no flow, simple commands like M <CR>, P## <CR> etc. No packeting or headers etc.

    So I borrowed something I already have running. I have a SendCmdGetResponse() function that looks like this:

      bool dev_valve::SendCmdGetResponse( QByteArray &array, int msec )
      {
        bool Result = false;
        int  wmsec  = 0;
        bool HaveResponse = false;
    
        m_lastresponse.clear();
    
          if( isOpen()==false )
            open();
          if( isOpen() )
          {
            clear();
    
            qint64 numwritten = m_serialport.write( array );
            qDebug() << "wrote:" << numwritten;
            if( waitForBytesWritten(50) )
            {
              while( (wmsec<=msec) && (HaveResponse==false) )
              {
                wmsec += 50;
                if( m_serialport.waitForReadyRead(50) )
                  HaveResponse = GetResponse();
    
                if( HaveResponse )
                {
                  Result = true;
                  break;
                }
              }
            }
          }
        return Result;
      }
    

    This basic code is working just fine for another serial device we have. In short the function blasts out the command, waits to ensure it is written, then loops for some predefined timeout looking for incoming response and returns if the response was received.

    If the loop times out then we return false.

    This code has been running in our main software diagnostics for a long time. Everyday some of our people are driving a serial pump around using this same command structure from a widgets program.

    However in creating my little test program for this new valve I began to get big time hangs to the point where I could not kill the program and eventually windows would blue screen.

    The debugger was not much help and eventually I tracked this down statement by statement to the call to waitForReadyRead(). It seems if I use that call in this test program every thing heads off into the weeds and dies.

    For completeness sake, GetResponse() is below:

      bool dev_valve::GetResponse()
      {
        bool Result  = false;
        bool HaveCR  = false;
    
        if( isOpen() )
        {
          if( m_serialport.bytesAvailable() )
          {
            m_lastresponse.append( m_serialport.readAll() );
            qDebug() << "m_lastresponse after readAll:" << m_lastresponse;
          }
    
          // See if we have CR
          HaveCR  = m_lastresponse.contains( 0x0D );
          if( HaveCR )
          {
            qDebug() << "m_lastresponse has CR";
    
            // Set result
            Result = HaveCR && (m_lastresponse.length()>=2);
    
            int pos = m_lastresponse.indexOf( 0x0D );
            if( pos>=0 )
              m_lastresponse.remove( pos, 1 );
    
            // m_lastresponse.append( QChar(0x0) );
    
            qDebug() << "m_lastresponse without CR:" << m_lastresponse;
          }
        }
      }
    
      qDebug() << "GetResponse() returning result:" << Result;
      return Result;
    }
    

    This code, running on Qt5.5, MSVC2013, 32bit, under Windows 10 will hang and you cannot even task manager kill the program. Eventually windows blue screens and reboots.

    I have downloaded and installed the latest Windows 10 compatible Keyspan driver but that didn't help. The outbound command DOES get to the device and it acts on it but in trying to get the response things go south in a hurry.

    I am able to get around this issue by NOT calling waitForReadyRead(). I replaced this call with a QElapsedTimer and making calls to the GetResponse() each loop. This works. No hang, no issue.

    I have had some trouble with garbage in the response so I added a call back in to m_serialport.clear() to clear the buffers in both directions. Instant hang.

    So it seems like if I use waitForReadyRead() or clear() on the QSerialPort it just dies.

    I even tried changing m_serialport to a pointer and creating it as part of the object construction. No change in behavior.

    I am not connecting any of the QSerialPort signals to anything but I didn't do that in my other test programs and had no issues.

    Any idea on what might cause the BSOD and program hang?

    I should also mention I've tried this on two different Win10 computers and get the same behavior.

    Thanks in advance.



  • Any idea on what might cause the BSOD and program hang?

    A bad driver.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.