Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. QSerialPort: delayed signal on new received bytes
Forum Updated to NodeBB v4.3 + New Features

QSerialPort: delayed signal on new received bytes

Scheduled Pinned Locked Moved Mobile and Embedded
15 Posts 2 Posters 7.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • McLionM Offline
    McLionM Offline
    McLion
    wrote on last edited by
    #6

    What I don't get is the difference between QextSerialPort and QSerialPort. since they both rely on the native Linux IO functions (AFAIK, wrapped by QIO device) how comes they have such a huge difference in emitting the readyRead signal?

    I am not really sure putting the serial port in a seperate thread is the best solution. It is also recommended "Best Practice" to not put it in a separate thread for asynchronous communication. When I see that QextSerialPort does not have this delay and emits the readyRead like immediately, I strongly feel that something with the QSerialPort code is wrong.

    1 Reply Last reply
    0
    • K Offline
      K Offline
      kuzulis
      Qt Champions 2020
      wrote on last edited by
      #7

      bq. I strongly feel that something with the QSerialPort code is wrong.

      You can itself try to find a problem place. The main places (difference) at which I would to check, is:

      1. Try to add this code (from the QextSerialPort "sources":https://code.google.com/p/qextserialport/source/browse/src/qextserialport_unix.cpp ,line 86):

      @
      const long vdisable = ::fpathconf(fd, _PC_VDISABLE);
      currentTermios.c_cc[VINTR] = vdisable;
      currentTermios.c_cc[VQUIT] = vdisable;
      currentTermios.c_cc[VSTART] = vdisable;
      currentTermios.c_cc[VSTOP] = vdisable;
      currentTermios.c_cc[VSUSP] = vdisable;
      @

      at initialization of device.

      1. Try to change the QSocketNotifier's event handling from the direct events to the signal/slot. The QSerialPort override the QSocketNotifier::event() method, but the QextSerialPort use the QSocketNotifier::activated(int) signal.

      2. Maybe something excessively in QSerialPortPrivate::readNotification() method. Maybe is reasonable to simplify it up to:

      @
      // Always buffered, read data from the port into the read buffer
      qint64 newBytes = readBuffer.size();
      qint64 bytesToRead = policy == QSerialPort::IgnorePolicy ? ReadChunkSize : 1;

      if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
          bytesToRead = readBufferMaxSize - readBuffer.size();
          if (bytesToRead == 0) {
              // Buffer is full. User must read data from the buffer
              // before we can read more from the port.
              return false;
          }
      }
      
      char *ptr = readBuffer.reserve(bytesToRead);
      const qint64 readBytes = readFromPort(ptr, bytesToRead);
      
      if (readBytes <= 0) {
          QSerialPort::SerialPortError error = decodeSystemError();
          if (error != QSerialPort::ResourceError)
              error = QSerialPort::ReadError;
          else
              setReadNotificationEnabled(false);
          q->setError(error);
          readBuffer.chop(bytesToRead);
          return false;
      }
      
      readBuffer.chop(bytesToRead - qMax(readBytes, qint64(0)));
      
      newBytes = readBuffer.size() - newBytes;
      
      // If read buffer is full, disable the read port notifier.
      if (readBufferMaxSize && readBuffer.size() == readBufferMaxSize)
          setReadNotificationEnabled(false);
      
      // only emit readyRead() when not recursing, and only if there is data available
      const bool hasData = newBytes > 0;
      
      if (!emittedReadyRead && hasData) {
          emittedReadyRead = true;
          emit q->readyRead();
          emittedReadyRead = false;
      }
      
      if (!hasData)
          setReadNotificationEnabled(true);
      

      @

      1 Reply Last reply
      0
      • McLionM Offline
        McLionM Offline
        McLion
        wrote on last edited by
        #8

        I'll read through that.
        One additional question: I assume it doesn't make a difference if I use
        @QByteArray read(qint64 maxSize)@

        instead of
        @virtual qint64 readData(char * data, qint64 maxSize)@

        to read out data, though readData seems to read from a ringbuffer and read reads from IODevice?

        1 Reply Last reply
        0
        • K Offline
          K Offline
          kuzulis
          Qt Champions 2020
          wrote on last edited by
          #9

          The readData(() it is protected method of QIODevice. You can't use it in your user code. The common chain is following: read() -> readData() -> read from ring buffer.

          The implementation of QSerialPort::readData() always read data from the internal ring buffer, but implementation of QextSerialPort try to read from the internal buffer + read directly from device.

          So, it make difference between read() and readData(). :)

          1 Reply Last reply
          0
          • McLionM Offline
            McLionM Offline
            McLion
            wrote on last edited by
            #10

            Arrgghh ... trying to modify code of QSerialPort as you suggested.
            Last week I could build successfully on Windows and Linux, now I crash even building on windows with a
            @DEVINST was not declared in this scope @

            1 Reply Last reply
            0
            • K Offline
              K Offline
              kuzulis
              Qt Champions 2020
              wrote on last edited by
              #11

              Try to replace the DEVINST by DWORD. Most likely your compiler do not contains the "cfgmgr32.h" file (or file has other place).

              1 Reply Last reply
              0
              • McLionM Offline
                McLionM Offline
                McLion
                wrote on last edited by
                #12

                Solved the DEVINST issue and added the termios settings. No change in the behaviour. There are only 3 diffs left from stty --a --F /dev/ttyS1 between QextSerialPort and QSerialPort. The following 3 option are deactivated (-) with QextSerialPort and activated with QSerialPort:
                @ignpar
                echoe
                echok
                @

                and I don't think that this will make the difference. Now going to look into your further suggestions.

                1 Reply Last reply
                0
                • McLionM Offline
                  McLionM Offline
                  McLion
                  wrote on last edited by
                  #13

                  Found that I have bytes dropping with QSerial as well. Seems to be some issue with underlying native linux or alike.
                  Coming back ...

                  1 Reply Last reply
                  0
                  • K Offline
                    K Offline
                    kuzulis
                    Qt Champions 2020
                    wrote on last edited by
                    #14

                    bq. Found that I have bytes dropping with QSerial as well.

                    There can't be.

                    Btw: this is an other issue not related with this thread.

                    1 Reply Last reply
                    0
                    • McLionM Offline
                      McLionM Offline
                      McLion
                      wrote on last edited by
                      #15

                      You're right, it's not exactly related to the topic of this thread.
                      I just wanted to update this thread with the fact that I am not further investigating the delayed readyRead as long as I have bytes dropping.
                      I actually implemented QSerial on my 4.6.3 because I thought that the bytes dropping was an issue of QextSerialPort. As it turns out, the issue is somewhere else (HW / underlying Linux).

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved