Posts: 4
Joined: Sun Oct 22, 2017 5:46 pm

ISR preemption of wiringPi ISR

Sun Oct 22, 2017 6:19 pm

I am using wiringPi library to process interrupts in C++ on a RaspberryPi 3. Using a logic analyzer on the GPIO pins I find that latency from GPIO edge to my ISR being called varies from about 45 to 70 us. I would like it faster but my application can tolerate this latency, but occasionally (about once a ms) latency increases to over 150 us and rarely to over 1 ms causing me to lose events. Most often the delay is before my ISR is called but occasionally it is in the middle of my ISR (my ISR usually takes about 4 us).

I assume that the processes involved are being preempted by something running at higher priority. I have tried running using the highest read-time priority and this does not seem to make a difference. I am guessing that the preemption is something in the kernel and that the only solution would be to write a kernel module which I had hoped to avoid.

Does anyone know what might be causing this? I see it when even when no other user processes are running. Will I still have this issue in even in kernel space? I do not need many of the standard services on a Pi (bluetooth, WiFi, HDMI, ...) and wonder if one of them preempts and by removing one of them I can avoid this.

To be a little more specific, my ISR toggles another GPIO at the beginning and again at the end so that I can see its lifetime on my logic analyzer. The interrupts I am handling are nearly perfectly periodic but on different runs vary from 600-16000 times a second.

Posts: 18
Joined: Wed Nov 05, 2014 8:24 pm

Re: ISR preemption of wiringPi ISR

Mon Oct 23, 2017 7:45 pm

Linux is no realtime operating system, so there is no guarantee how long it may take until e.g. an ISR is called. Even if you write a kernel driver and reduce the load on the system by uninstalling not needed services, it can still happen.
Depending on your requirements there are some possible solutions:

If you need to know when the interrupt occurred but you don't need to react quickly, then have a look at pigpio. This library uses DMA to sample the gpio, so even if the cpu is busy doing other stuff, you'll later still know when it happened.

If you need to react quickly on the interrupt, but it is OK to miss one occasionally, then reducing the system load by disabling/uninstalling services and/ writing a kernel driver may be enough.

If you need to react quickly at all times, then there is no way around a realtime os. There are realtime patches for the linux kernel, but even if a realtime linux has a way more deterministic reaction time to ISRs it may not be fast enough for your application (realtime is not equal to fast).

Posts: 4
Joined: Sun Oct 22, 2017 5:46 pm

Re: ISR preemption of wiringPi ISR

Mon Oct 23, 2017 11:06 pm

Part of my problem is avoiding privileged mode (root or sudo). Measurement show that reads and writes with wiringPi library using wiringPiSetupSys which uses /sys/class/gpio psuedo filesystem driver are much slower and more likely to be preempted than use wiringPiSetupGpio which more directly access the GPIOs (presumably by memory mapping). My reads and writes are at least 5x faster. I believe that the interrupts registered through wiringPi always use the /sys/class/gpio and that is why they are so latent and vulnerable to preemption. I found that by running as root, using wiringPiSetupGpio and polling my GPIO pin every 15 or 20 us gives me much less latency, and I have not missed one yet even when the pin is being driven at 16000 Hz (62 us period). I don't like running this in privileged mode but it looks like it will be necessary. Polling puts a lot more load on the cpu but I have little else I need to do so it is acceptable.

I also tried using the /sys/class/gpio driver, opening the pseudo file and using linux poll(), and it had almost exactly the latency of the interrupt method. wiringPi library might actually be doing that to trigger the interrupts it uses.

Posts: 147
Joined: Mon Jun 13, 2016 11:39 am

Re: ISR preemption of wiringPi ISR

Tue Oct 24, 2017 3:09 am

As already said above, there is no real-time guarantee in Linux userland. Your process can get suspended any time and there is nothing you can do. However, you can improve your odds: you may try to run your program on a core that isn't used by the kernel to deal with interrupts (see taskset and /proc/interrupts); you can give your process a real-time priority (see chrt); you can prevent system calls by reading the GPIO peripheral address space directly.

This is related to signal edge/level detection on GPIO pins: viewtopic.php?f=44&t=190108&e=1&view=unread#p1196082

Return to “C/C++”