Interrupts In Userspace¶
Manual Configuration¶
Request GPIO 26, and configure as input (see Intro: sysfs GPIO)
Configure interrupts
$ echo falling > /sys/class/gpio/gpio26/edge
And now?
⟶ Need programming; shell is not made for advanced concepts
C Program: Configuration, Event Loop¶
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/select.h>
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <GPIO#>" << endl;
return 1;
}
const char* GPIO = argv[1];
stoi(GPIO); // check if GPIO is int
// export GPIO
// -----------
//
// $ echo $GPIO > /sys/class/gpio/export
{
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd == -1) {
perror("open export file");
return 1;
}
ssize_t nwritten = write(fd, GPIO, strlen(GPIO));
if (nwritten == -1) {
perror("write to export file");
return 1;
}
close(fd);
}
// give system time to export GPIO (sadly, this is an asynchronous
// operation)
sleep(1);
// configure GPIO as input
// -----------------------
//
// $ echo in > /sys/class/gpio/gpio$GPIO/direction
{
char filename[64];
sprintf(filename, "/sys/class/gpio/gpio%s/direction", GPIO);
int fd = open(filename, O_WRONLY);
ssize_t nwritten = write(fd, "in", 2);
if (nwritten == -1) {
perror("configure direction");
return 2;
}
assert(nwritten == 2);
close(fd);
}
// edge detection: "rising"
// ------------------------
//
// $ echo rising > /sys/class/gpio/gpio$GPIO/direction/edge
{
char filename[64];
sprintf(filename, "/sys/class/gpio/gpio%s/edge", GPIO);
int fd = open(filename, O_WRONLY);
ssize_t nwritten = write(fd, "rising", 6);
if (nwritten == -1) {
perror("configure edge");
return 3;
}
assert(nwritten == 6);
close(fd);
}
// wait for value to change
// ------------------------
{
char filename[64];
sprintf(filename, "/sys/class/gpio/gpio%s/value", GPIO);
int fd = open(filename, O_RDONLY);
assert(fd != -1);
while (true) {
fd_set exc_fds;
FD_ZERO(&exc_fds);
FD_SET(fd, &exc_fds);
int nready = select(fd+1, nullptr, nullptr, &exc_fds, nullptr);
if (nready == -1) {
perror("select");
return 4;
}
assert(nready > 0);
if (FD_ISSET(fd, &exc_fds)) {
char value[2] = "x";
ssize_t nread = read(fd, value, 1);
if (nread == -1) {
perror("read value");
return 5;
}
off_t off = lseek(fd, 0, SEEK_SET);
if (off == -1) {
perror("lseek");
return 6;
}
cout << "EEK:" << value << endl;
}
}
}
return 0;
}