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.9k 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
    #5

    [quote author="kuzulis" date="1405088316"]
    Move the QSerialPort to separate QThread and set "thread priority": http://qt-project.org/doc/qt-4.8/qthread.html#setPriority.

    [/quote]

    Sounds like quite some piece of work since I have no experience with QThread .. never used before.

    Thanks

    1 Reply Last reply
    0
    • 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