User avatar
yasriady
Posts: 27
Joined: Wed Apr 08, 2015 2:37 am
Location: Indonesia
Contact: Website

Reading GPIO input triggered by IRQ

Mon Oct 19, 2015 3:25 am

Dear colleagues,

Do you have any sample c++ code for GPIO input reading by interrupt request (IRQ). Mostly codes I found in internet are about pooling method, that could lead to slowdown the system.

Note Added 151027:
Hardware IRQ has better realtime response rather than pooling method.

Also, I found this codes is about Kernel level interrupt: http://morethanuser.blogspot.co.id/2013 ... ernel.html, if possible could you explain about c++ codes in user space .

Thank you ...
Last edited by yasriady on Tue Oct 27, 2015 1:11 pm, edited 1 time in total.
MyRaspberryPi : Cross Compile, wxWidgets/C++ and Linux Journal at http://yasriady.blogspot.com

User avatar
Hove
Posts: 1205
Joined: Sun Oct 21, 2012 6:55 pm
Location: Cotswolds, UK
Contact: Website

Re: Reading GPIO input triggered by IRQ

Mon Oct 19, 2015 6:47 am

In a real operating system, IRQ's are tightly integrated into the kernel scheduling; this is so that interrupts don't disrupt the operation of all the user space apps that are running. In user space, the code typically uses poll() or epoll(); this doesn't actually poll and does not slow the system down. Instead it registers its interest in an IRQ with the kernel and blocks i.e the kernel takes this process out of its user space app scheduling. When the interrupt happens, the kernel adds the app back into the user space scheduling, unblocking the (e)poll() call, and allowing the user space software to process it.

So the polling things you found _are_ what you need for user space handling of hardware interrupts.
www.pistuffing.co.uk - Raspberry Pi and other stuffing!

User avatar
yasriady
Posts: 27
Joined: Wed Apr 08, 2015 2:37 am
Location: Indonesia
Contact: Website

Re: Reading GPIO input triggered by IRQ

Tue Oct 20, 2015 12:47 am

Hi Hove,
Thank you for the information and that give some hints on gpio accessing. Anyway, could you point me some url for both userspace and kernelspace codes? So I could make exact comparison on them.
MyRaspberryPi : Cross Compile, wxWidgets/C++ and Linux Journal at http://yasriady.blogspot.com

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 20, 2015 1:36 am

yasriady wrote:Hi Hove,
Thank you for the information and that give some hints on gpio accessing. Anyway, could you point me some url for both userspace and kernelspace codes? So I could make exact comparison on them.
This is all standard stuff. Hove gave a very good explanation. If you google for linux interrupts you will find plenty of tutorials.

User avatar
yasriady
Posts: 27
Joined: Wed Apr 08, 2015 2:37 am
Location: Indonesia
Contact: Website

Re: Reading GPIO input triggered by IRQ

Wed Oct 21, 2015 9:38 am

Ok thanks,
After googling, I found to wrote kernel module codes in c.
But then I have no idea what is the best practice to make irq handler in user space function... Could you show some sample ..?

Again, thank you for your kindness...................
MyRaspberryPi : Cross Compile, wxWidgets/C++ and Linux Journal at http://yasriady.blogspot.com

User avatar
gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Re: Reading GPIO input triggered by IRQ

Thu Oct 22, 2015 8:51 pm

The poll() system call blocks the calling program until the supplied file-descriptor has something to read - the user program consumes 0 cpu resources until the thing is ready. It is not a busy-loop poll.

The GPIO can be plumbed into a state that allows you to poll a pin - to effectively wait for an interrupt.
This is not as efficient as doing it inside the kernel, but it allows a user program to simulate receiving an interrupt from a signal on a pin. There is some latency - more than on (say) an 8-bit microcontroller but it's a usable resource.

Have a look at the wiringPi sources for the waitForInterrupt() and wiringPiISR() functions for more information on doing it that way.

-Gordon
--
Gordons projects: https://projects.drogon.net/

User avatar
yasriady
Posts: 27
Joined: Wed Apr 08, 2015 2:37 am
Location: Indonesia
Contact: Website

Re: Reading GPIO input triggered by IRQ

Fri Oct 23, 2015 8:25 am

Gordon, thanks a lot for your information.
I will look into your functions and adopt some codes into my program as well...
MyRaspberryPi : Cross Compile, wxWidgets/C++ and Linux Journal at http://yasriady.blogspot.com

User avatar
yasriady
Posts: 27
Joined: Wed Apr 08, 2015 2:37 am
Location: Indonesia
Contact: Website

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 12:53 am

Hi,

I'm trying to make GPIO interrupt handler inside lkm. I know how to make a call to kernel space function call_usermodehelper, this function will invoke user space application as well. Besides this way, is there any other method we can use to call user space function from LKM space?
Any suggests will be appreciated .....................
MyRaspberryPi : Cross Compile, wxWidgets/C++ and Linux Journal at http://yasriady.blogspot.com

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 8:38 am

yasriady wrote:Hi,

I'm trying to make GPIO interrupt handler inside lkm. I know how to make a call to kernel space function call_usermodehelper, this function will invoke user space application as well. Besides this way, is there any other method we can use to call user space function from LKM space?
Any suggests will be appreciated .....................
Kernel modules operate differently to userspace modules. The methods are not transferable. Look for kernel examples.

User avatar
yasriady
Posts: 27
Joined: Wed Apr 08, 2015 2:37 am
Location: Indonesia
Contact: Website

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 8:49 am

Yes, that's what I'm understood about.
Do you have any idea what is best practice to have advanced irq handler? Because my function consist of c++ codes which only available in userspace...

Thanks in Advance ...
MyRaspberryPi : Cross Compile, wxWidgets/C++ and Linux Journal at http://yasriady.blogspot.com

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 9:03 am

hey,
I am alo intersted in implementing timer or hardware IRQs underneath the user space to achieve a better real-time performance for time-critical events, which must not be delayed by Linux tasks or daemons.

E.g., polling exactly (!) each 100µs 8-12 different digital input pins, or watching those 8-12 pins in real-time for pinchange events.

Having once asked that in a different forum with respect to Gordon's wiringPi functions, I was told
Note that wiring Pi Pinchange-IRQ only suggests to provide an interrupt. In fact, there is just a flank change latched from Broadcom which is polled by thread. With genuine Interrupt that has nothing to do. Similar things is providing the MCP23017 as well. By doing this you will be notified in a jittered way just like threads used to jitter. And the thread is only setting it's nice level higher. There is also no RT thread here which is polling actually.
(translated by Google-Translate, revised)

Is this correct or not?
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 9:29 am

davenull wrote: Is this correct or not?
Are you working in userspace under Linux? If so then Linux handles all interrupts. Linux will notify userspace when the interrupt occurs if you have registered a callback. There will be an average latency of 50 µs between the interrupt being triggered and the userspace callback being called. There is NO polling going on.

What are you trying to do? In particular if a GPIO changes level how is your software meant to react? Does it simply record the event or does it trigger a series of outputs?

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 9:42 am

I am programming in gpp C++, using pthread and wiringPi.
I personally want to poll dPins quickly for rotary encoder reading, but there are lots of different parallel tasks running, particularly very calculation- intensive and time-consuming ones, e.g. analog reading, UART- and i2c reading, PID control for 8 motors, odometry, FFT, Astar, bug2, and a heuristic abstraction layer for a neural net.
On a Arduino Due (ARM cortex M3) everything is running fine, but there I have real hardware IRQs and Timer IRQs on MCU level. For the Due, I'm using 100µs timer IRQs which is perfect for my motor rotation speed (2 encoder ticks per degree, rotation speed up to 200 degrees per 100ms, unfortunately limited to 4 motors because of MCU restrictions)
Last edited by davenull on Tue Oct 27, 2015 10:01 am, edited 1 time in total.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 10:01 am

davenull wrote:I personally want to poll dPins quickly for rotary encoder reading, but there are lots of different parallel tasks running, particularly very calculation- intensive and time-consuming ones, e.g. PID control for 8 motors, odometry, FFT, Astar, bug2, and a heuristic abstraction layer for a neural net.
On a Arduino Due (ARM cortex M3) everything is running fine, but there I have real hardware IRQs and Timer IRQs on MCU level. For the Due, I'm using 100µs timer IRQs which is perfect for my motor rotation speed (2 encoder ticks per degree, rotation speed up to 200 degrees per 100ms, unfortunately limited to 4 motors because of MCU restrictions)
Have you tried reading the encoder using interrupts? I suspect that you will start missing pulses at one every 250 µs or less.

My pigpio library should do what you want.

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 10:04 am

I'm using wiringPi, by this it's fine if I'm using just the encoder reading tasks but I have been warned that readings get lost or corrupted and jitter when dozens of tasks and daemons are running parallel additionally.
So I would prefer to have real hardware interrupts instead, not at pthread or user space level.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
yasriady
Posts: 27
Joined: Wed Apr 08, 2015 2:37 am
Location: Indonesia
Contact: Website

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 10:07 am

Yes, hardware interrrupt to achieve better realtime response ..
MyRaspberryPi : Cross Compile, wxWidgets/C++ and Linux Journal at http://yasriady.blogspot.com

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 10:09 am

davenull wrote:I'm using wiringPi, by this it's fine if I'm using just the encoder reading tasks but I have been warned that readings get lost or corrupted and jitter when dozens of tasks and daemons are running parallel additionally.
So I would prefer to have real hardware interrupts instead, not at pthread or user space level.
If you want accurate timing you will have to use pigpio.

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 10:20 am

no problem, but pigpio doesn't provide no hardware IRQ neither, does it?
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 10:48 am

davenull wrote:no problem, but pigpio doesn't provide no hardware IRQ neither, does it?
No it doesn't. You'd have to go bare level (no operating system) to use hardware IRQ.

It does sample the GPIOs 200 thousand times a second (default) using hardware so the samples are pretty much immune from jitter. That gives 5 µs timing resolution.

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 10:59 am

which one is sampling 200 thousand times a second at 5µs resolution, by no jitter?

pigpio?
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 11:03 am

davenull wrote:which one is sampling 200 thousand times a second at 5µs resolution, by no jitter?

pigpio?
Yes, pigpio.

There will be jitter, but you'll probably need a logic analyser to see how much. The jitter will be insignificant in proportion to the timing resolution.

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 11:17 am

ok, but 5µs will be no issue at all, that's really perfect.

Now I'm just curious about how wiringPi would perform, because I'm usually prefering it so far as I'm more used to it's API syntax (already since I was programming by Arduino Wiring/Sketch)
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 14077
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 11:49 am

davenull wrote:ok, but 5µs will be no issue at all, that's really perfect.

Now I'm just curious about how wiringPi would perform, because I'm usually prefering it so far as I'm more used to it's API syntax (already since I was programming by Arduino Wiring/Sketch)
It's not so much about how wiringPi will perform, it's about how the underlying Linux interrupts perform. I'll run some tests again when I get the chance. I'm fairly sure pulses are lost at a sustained rate of 200 µs (the closest I tested to 250 µs). I don't know how long the burst has to be.

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Tue Oct 27, 2015 2:09 pm

I see, thank you, so wiringPi is supposed to be triggered by pthread while pigpio is using hardware access, is this reproduced correctly?

Anyway, pigpio actually seems to be the better choice then. Could you please give me a hint how to access pinchange or timer interrupts?
For wiringPi, my code is from this git source so far: https://github.com/astine/rotaryencoder ... yencoder.c

Code: Select all

//rotaryencoder.h
//17 pins / 2 pins per encoder = 8 maximum encoders
#define max_encoders 8

struct encoder
{
    int pin_a;
    int pin_b;
    volatile long value;
    volatile int lastEncoded;
};

//Pre-allocate encoder objects on the stack so we don't have to
//worry about freeing them
struct encoder encoders[max_encoders];

/*
  Should be run for every rotary encoder you want to control
  Returns a pointer to the new rotary encoder structer
  The pointer will be NULL is the function failed for any reason
*/

#include "rotaryencoder.h"

struct encoder *encoder = setupencoder(pin_a, pin_b);

long encval = encoder->value; 
That’s all there is to it.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: Reading GPIO input triggered by IRQ

Wed Oct 28, 2015 6:45 pm

now are there encoder libs for pigpio providing quick IRQ-triggered pin reading?
(100µs for timer IRQs should fit actually, for pinchange interrupts perhaps quicker)
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

Return to “C/C++”