/* Interrupts functions extruded from wiringPi library by Oitzu. wiringPi Copyright (c) 2012 Gordon Henderson https://projects.drogon.net/raspberry-pi/wiringpi wiringPi is free software: GNU Lesser General Public License see */ #include #include #include #include #include #include #include #include #include #include #include #include "interrupt.h" #include //#define delay(x) bcm2835_delay(x) static pthread_mutex_t pinMutex = PTHREAD_MUTEX_INITIALIZER; static volatile int pinPass = -1; pthread_t threadId[64]; // sysFds: // Map a file descriptor from the /sys/class/gpio/gpioX/value static int sysFds[64] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,}; // ISR Data static void (* isrFunctions[64])(void); int waitForInterrupt(int pin, int mS) { int fd, x; uint8_t c; struct pollfd polls; if ((fd = sysFds[pin]) == -1) { return -2; } // Setup poll structure polls.fd = fd; polls.events = POLLPRI; // Urgent data! // Wait for it ... x = poll(&polls, 1, mS); // Do a dummy read to clear the interrupt // A one character read appars to be enough. // Followed by a seek to reset it. (void) read(fd, &c, 1); lseek(fd, 0, SEEK_SET); return x; } int piHiPri(const int pri) { struct sched_param sched; memset(&sched, 0, sizeof(sched)); if (pri > sched_get_priority_max(SCHED_RR)) { sched.sched_priority = sched_get_priority_max(SCHED_RR); } else { sched.sched_priority = pri; } return sched_setscheduler(0, SCHED_RR, &sched); } void* interruptHandler(void* arg) { int myPin; (void) piHiPri(55); // Only effective if we run as root myPin = pinPass; pinPass = -1; for (;;) { if (waitForInterrupt(myPin, -1) > 0) { pthread_mutex_lock(&pinMutex); isrFunctions[myPin](); pthread_mutex_unlock(&pinMutex); pthread_testcancel(); //Cancel at this point if we have an cancellation request. } } return NULL; } int attachInterrupt(int pin, int mode, void (* function)(void)) { const char* modeS; char fName[64]; char pinS[8]; pid_t pid; int count, i; char c; int bcmGpioPin; bcmGpioPin = pin; if (mode != INT_EDGE_SETUP) { /**/ if (mode == INT_EDGE_FALLING) { modeS = "falling"; } else if (mode == INT_EDGE_RISING) { modeS = "rising"; } else { modeS = "both"; } sprintf(pinS, "%d", bcmGpioPin); if ((pid = fork()) < 0) { // Fail return printf("wiringPiISR: fork failed: %s\n", strerror(errno)); } if (pid == 0) // Child, exec { /**/ if (access("/usr/local/bin/gpio", X_OK) == 0) { execl("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); } else if (access("/usr/bin/gpio", X_OK) == 0) { execl("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); } else { return printf("wiringPiISR: Can't find gpio program\n"); } } else { // Parent, wait wait(NULL); } } if (sysFds[bcmGpioPin] == -1) { sprintf(fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin); if ((sysFds[bcmGpioPin] = open(fName, O_RDWR)) < 0) { return printf("wiringPiISR: unable to open %s: %s\n", fName, strerror(errno)); } } ioctl(sysFds[bcmGpioPin], FIONREAD, &count); for (i = 0; i < count; ++i) { read(sysFds[bcmGpioPin], &c, 1); } isrFunctions[pin] = function; pthread_mutex_lock(&pinMutex); pinPass = pin; pthread_create(&threadId[bcmGpioPin], NULL, interruptHandler, NULL); while (pinPass != -1) delay (1); pthread_mutex_unlock(&pinMutex); return 0; } int detachInterrupt(int pin) { char pinS[8]; const char* modeS = "none"; pid_t pid; if (!pthread_cancel(threadId[pin])) //Cancel the thread { return 0; } if (!close(sysFds[pin])) //Close filehandle { return 0; } /* Set wiringPi to 'none' interrupt mode */ sprintf(pinS, "%d", pin); if ((pid = fork()) < 0) { // Fail return printf("wiringPiISR: fork failed: %s\n", strerror(errno)); } if (pid == 0) // Child, exec { /**/ if (access("/usr/local/bin/gpio", X_OK) == 0) { execl("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); } else if (access("/usr/bin/gpio", X_OK) == 0) { execl("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char*) NULL); return printf("wiringPiISR: execl failed: %s\n", strerror(errno)); } else { return printf("wiringPiISR: Can't find gpio program\n"); } } else { // Parent, wait wait(NULL); } return 1; } void rfNoInterrupts() { pthread_mutex_lock(&pinMutex); } void rfInterrupts() { pthread_mutex_unlock(&pinMutex); }