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.8k 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
    #3

    kuzulius, thanks for trying to help.

    To 1:
    As far as I can see, QSerialPort does not run any parts of its code in a separate thread under Linux, or did I miss something?
    How would I increase priority in this case?

    To 2:
    I'v read out the values with stty -a -F /dev/ttyS1 which returned 0 for min and 0 for time. As far as I can tell, this already is the best setting.

    To 3:
    Sorry, I'm not sure what you mean exactly.

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

      bq. How would I increase priority in this case?

      Move the QSerialPort to separate QThread and set "thread priority": http://qt-project.org/doc/qt-4.8/qthread.html#setPriority.

      bq. As far as I can tell, this already is the best setting.

      Quite possibly that these 0/0 remained from QSerialPort. You can re-start your board and try do run the stty (before use of QSerialPort), to see an default VMIN/VTIME. So, you can change VMIN/VTIME as you want.

      bq. Sorry, I’m not sure what you mean exactly.

      I mean: do not use of heavy QtSerialPort && Qt on an applications which required precise time for communications (I/O) issues. E.g. use the pure C/C++ code && others lite GUI toolkits.. :)

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