GPIO Edge

If setting /sys/class/gpio/gpioxx/edge creates an interrupt in the /proc/interrupts file, why is there no event file associated with it? What is the best way to use a gpio pin to count the number of times a switch is toggled? I really need to do it on two separate pins in order to ensure two motors are spinning at the same rate.

If setting /sys/class/gpio/gpioxx/edge creates an interrupt in the
/proc/interrupts file, why is there no event file associated with it? What
is the best way to use a gpio pin to count the number of times a switch is
toggled? I really need to do it on two separate pins in order to ensure two
motors are spinning at the same rate.

There are counters on the eQEP blocks that can do the counting for you. (
https://github.com/Teknoman117/beaglebot/tree/master/encoders)

https://developer.ridgerun.com/wiki/index.php/How_to_use_GPIO_signals has a
nice discussion on sysfs GPIO interrupts, which I believe you accurately
point out don't have associated event files.

If you want to generate real events, use the gpio-keys driver instead. With
device tree overlays, it should be simple enough to load the gpio-keys
driver.

Device tree bindings:
https://www.kernel.org/doc/Documentation/devicetree/bindings/gpio/gpio_keys.txt
Nice overall post:
http://hipstercircuits.com/capture-input-events-via-gpio-on-beaglebone-black/

I tried the gpio-keys driver. I was able to count the interrupts, but was not able to determine which pin. I tried the following code, but when I hooked up switches to two pins the first switch I triggered would give the correct code, but when I triggered the second switch it would give the code for the first switch 4-5 times before it began giving the correct code.

using namespace std;

volatile int fd1 = 0;
volatile int counter1 = 0;
volatile int code = 0;
//volatile int value;
FILE *ifp_gpio30_value;
struct input_event event;

void IRQHandler(int sig){
counter1 ++;

read(fd1, &event, sizeof(struct input_event));
code = event.code;
counter1 ++;

}

int main(void){
struct sigaction saio;
fd1 = open("/dev/input/event1", O_RDWR|O_NONBLOCK);

saio.sa_handler = IRQHandler;
//saio.sa_mask = 0;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
fcntl(fd1, F_SETOWN, getpid());
fcntl(fd1, F_SETFL, FASYNC);
while(1){
cout << counter1;
cout << “\t”;
cout << code;
cout << “\n”;
}

}

libsoc has an implementation that will allow you to count interrupts by
using poll on the sysfs standard GPIO implementation. You can take a
look to see if that would help you.

https://github.com/jackmitch/libsoc

Cheers,
Jack.

I actually tried using the sysfs gpio interrupts before writing the eQEP driver. They just weren’t fast enough for my application. The motors I have generate a 4096 ticks per revolution and rotate at like 120 rpm. The gpio interrupts just couldn’t keep up. They stopped working (as in missing pulses) at above ~25 Hz input signal. I chalked it up to sysfs and the first iteration of the eQEP driver used GPIO interrupts in the kernel. I could handle about a 100 Hz input signal there. Still nowhere near the 8.192 KHz i needed. The driver I ended up writing uses the hardware controller for encoders. If you have encoders with decent resolution, unless the user space interrupt system has improved in the last 9 months, it won’t work very well.