RT Kernel on Olinuxino A20

Started by margadon, November 20, 2015, 04:06:56 pm

Previous topic - Next topic

margadon

Hi, who tried t install RT-kernel on debian-linux for A20?
I couldn't get small jitter in UART using generic kernel..

MBR

November 21, 2015, 09:52:50 pm #1 Last Edit: November 21, 2015, 10:16:40 pm by MBR
Using a realtime kernel for a slow device like UART is an overkill, so unless you board is very heavy loaded and is doing a lot of I/O at the same time, you'll probably never run into problems with UART (unless the program is very badly designed). If you want a soft-realtime program, try a normal kernel and use realtime sheduling (using sched_setscheduler(), see http://linux.die.net/man/2/sched_setscheduler) for your program, and to avoid paging out, you may add the locking of all pages of process in the memory (using mlock(), see http://linux.die.net/man/2/mlock).

margadon

December 01, 2015, 04:47:40 pm #2 Last Edit: December 01, 2015, 04:59:03 pm by margadon
Thanks a lot for your explanation! May I clarify something?
I use USART5: PI10, PI11 pins, asynchronous mode. Permanently sending some data packets on speed 115200, I get unexpected delays between packets from 10 up to 20 ms long. I see It on logic analyser. I send different packets of 1-40 bytes long. And after 10-15 packets I get those delays. Here are the pictures from analyser
https://yadi.sk/i/vsKBa1UokQHAp
https://yadi.sk/i/lIzgcR5ekQHFD
In normal state the distance between packets is less than 1 ms - (approx.0.6~0.7ms). Is It because the USART Driver, or Linux, or what is the reason of those unexpected delays?
Do i have to send data from kernel space? Or Is it not such important?
The other processes run in my system also - GUI and so onБ at that
the common usage of CPU is not more then 30-50%, memory not more then 70%. 
I send data from python application using pyserial
here is the code snippet which sends and recieves:
def read(self, size=1):
        """Read size bytes from the serial port. If a timeout is set it may
           return less characters as requested. With no timeout it will block
           until the requested number of bytes is read."""
        if not self._isOpen: raise portNotOpenError
        read = bytearray()
        while len(read) < size:
            try:
                ready,_,_ = select.select([self.fd],[],[], self._timeout)
                # If select was used with a timeout, and the timeout occurs, it
                # returns with empty lists -> thus abort read operation.
                # For timeout == 0 (non-blocking operation) also abort when there
                # is nothing to read.
                if not ready:
                    break   # timeout
                buf = os.read(self.fd, size-len(read))
                # read should always return some data as select reported it was
                # ready to read when we get to this point.
                if not buf:
                    # Disconnected devices, at least on Linux, show the
                    # behavior that they are always ready to read immediately
                    # but reading returns nothing.
                    raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
                read.extend(buf)
            except select.error, e:
                # ignore EAGAIN errors. all other errors are shown
                # see also http://www.python.org/dev/peps/pep-3151/#select
                if e[0] != errno.EAGAIN:
                    raise SerialException('read failed: %s' % (e,))
            except OSError, e:
                # ignore EAGAIN errors. all other errors are shown
                if e.errno != errno.EAGAIN:
                    raise SerialException('read failed: %s' % (e,))
        return bytes(read)

    def write(self, data):
        """Output the given string over the serial port."""
        if not self._isOpen: raise portNotOpenError
        d = to_bytes(data)
        tx_len = len(d)
        if self._writeTimeout is not None and self._writeTimeout > 0:
            timeout = time.time() + self._writeTimeout
        else:
            timeout = None
        while tx_len > 0:
            try:
                n = os.write(self.fd, d)
                if timeout:
                    # when timeout is set, use select to wait for being ready
                    # with the time left as timeout
                    timeleft = timeout - time.time()
                    if timeleft < 0:
                        raise writeTimeoutError
                    _, ready, _ = select.select([], [self.fd], [], timeleft)
                    if not ready:
                        raise writeTimeoutError
                else:
                    # wait for write operation
                    _, ready, _ = select.select([], [self.fd], [], None)
                    if not ready:
                        raise SerialException('write failed (select)')
                d = d[n:]
                tx_len -= n
            except OSError, v:
                if v.errno != errno.EAGAIN:
                    raise SerialException('write failed: %s' % (v,))
        return len(data)


The same situation I get, when i tried to use GPIO to control TX/RT mode for RS 485 Driver chip (like st485). The moment of switching It to 1 was delays sometimes on the same 10-20 ms, what destroys the transmission session.

JohnS

December 01, 2015, 06:13:37 pm #3 Last Edit: December 01, 2015, 06:15:28 pm by JohnS
A normal process already sends from the kernel because the process asks the kernel to do the I/O.

I expect your process also does that but if not then do!

The kernel has buffers - again normally.

I would use C in case you are suffering something like a GC in a slow language.

If you get the same problem and have made the changes already suggested by others then something is wrong and needs finding, especially on a 2-cpu chip like the A20.

I take it you have already used tools like ps and top to find out what else your system is doing...

John

soenke

Try to start your process with priority -50 and check if that helps.

JohnS

You've not left the cpu governor unchanged I hope...

Various settings are utterly useless.  (google...)

John

margadon

December 02, 2015, 10:55:20 am #6 Last Edit: December 02, 2015, 11:17:54 am by margadon
QuoteYou've not left the cpu governor unchanged I hope...

Various settings are utterly useless.  (google...)

what mode i have to set from that list?

powersave userspace conservative interactive ondemand fantasy performance

JohnS

Only you have your hardware and needs so this is your chance to decide.

John

soenke

if you want minimal response times, use the performance governor, it will keep the CPU on maximum clock speed.

margadon

Quoteif you want minimal response times, use the performance governor, it will keep the CPU on maximum clock speed.

I checked. It was performance by default.