Merge pull request #325 from phylax2020/development

waitForInterrupt and wiringPiISR with status
This commit is contained in:
Manfred Wallner
2025-03-29 18:41:56 +01:00
committed by GitHub
7 changed files with 286 additions and 243 deletions

View File

@@ -99,10 +99,10 @@ cd WiringPi
# build the package
./build debian
mv debian-template/wiringpi-3.0-1.deb .
mv debian-template/wiringpi-3.x.deb .
# install it
sudo apt install ./wiringpi-3.0-1.deb
sudo apt install ./wiringpi-3.x.deb
```
@@ -115,14 +115,14 @@ Unzip/use the portable prebuilt verison:
```sh
# unzip the archive
tar -xfv wiringpi_3.0.tar.gz
tar -xfv wiringpi_3.x.tar.gz
```
Install the debian package:
```sh
# install a dpkg
sudo apt install ./wiringpi-3.0-1.deb
sudo apt install ./wiringpi-3.x.deb
```

View File

@@ -1 +1 @@
3.14
3.16

View File

@@ -20,13 +20,13 @@ sudo apt install git
git clone https://github.com/WiringPi/WiringPi.git
cd WiringPi
./build debian
mv debian-template/wiringpi-3.13.deb .
mv debian-template/wiringpi-3.1x.deb .
```
**Debian-Paket installieren:**
```bash
sudo apt install ./wiringpi-3.13.deb
sudo apt install ./wiringpi-3.1x.deb
```
**Debian-Paket deinstallieren:**
@@ -291,7 +291,7 @@ Registriert eine Interrupt Service Routine (ISR) bzw. Funktion die bei Flankenwe
>>>
```C
int wiringPiISR(int pin, int edgeMode, void (*function)(unsigned int, long long int), unsigned long bouncetime);
int wiringPiISR(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long bouncetime);
```
``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer).
@@ -301,9 +301,15 @@ int wiringPiISR(int pin, int edgeMode, void (*function)(unsigned int, long long
- INT_EDGE_FALLING ... Fallende Flanke
- INT_EDGE_BOTH ... Steigende und fallende Flanke
``*function``: Funktionspointer für ISR mit Rückgabeparameter pin und Zeitstempel:
> unsigned int: pin
> long long int: Zeitstempel
``*function``: Funktionspointer für ISR mit Rückgabeparameter struct WPIWfiStatus:
```C
struct WPIWfiStatus {
int status; // -1: error, 0: timeout, 1: valid values for edge and timeStamp_us
unsigned int gpioPin; // gpio as BCM pin
int edge; // One of INT_EDGE_FALLING or INT_EDGE_RISING
long long int timeStamp_us; // time stamp in microseconds, when interrupt happened
};
```
``bouncetime``: Entprellzeit in Microsekunden, 0 ms schaltet das Entprellen ab
@@ -335,7 +341,7 @@ Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout und Entp
Blockiert das Programm bis zum Eintreffen der auslösenden Flanke oder bis zum Ablauf des Timeouts.
>>>
```C
long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long bouncetime)
struct WPIWfiStatus wfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned long bouncetime)
```
``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer).
@@ -353,18 +359,21 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long bo
``bouncetime``: Entprellzeit in Microsekunden, 0 schaltet Entprellen ab.
``Rückgabewert``:
> \>0 ... Zeitstempel des Interrupt Ereignisses in Mikrosekunden
> 0 ... Timeout
> \-1 ... GPIO Device Chip nicht erfolgreich geöffnet
> \-2 ... ISR wurde nicht registriert
```C
struct WPIWfiStatus {
int status; // -1: error, 0: timeout, 1: valid values for edge and timeStamp_us
unsigned int gpioPin; // gpio as BCM pin
int edge; // One of INT_EDGE_FALLING or INT_EDGE_RISING
long long int timeStamp_us; // time stamp in microseconds, when interrupt happened
};
```
**Beispiel:**
```C
/*
* isr_debounce.c:
* Wait for Interrupt test program WiringPi >=3.14 - ISR method
* Wait for Interrupt test program WiringPi >=3.16 - ISR method
*
*
*/
@@ -396,20 +405,26 @@ int toggle = 0;
*********************************************************************************
*/
static void wfi (unsigned int gpio, long long int timestamp) {
static void wfi (struct WPIWfiStatus wfiStatus) {
// struct timeval now;
long long int timenow, diff;
struct timespec curr;
char *edgeType;
if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) {
printf("clock_gettime error");
return;
}
timenow = curr.tv_sec * 1000000LL + curr.tv_nsec/1000L; // convert to microseconds
diff = timenow - timestamp;
printf("gpio BCM = %d, IRQ timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", gpio, timestamp, timenow, diff);
diff = timenow - wfiStatus.timeStamp_us;
if (wfiStatus.edge == INT_EDGE_RISING)
edgeType = "rising";
else if (wfiStatus.edge == INT_EDGE_FALLING)
edgeType = "falling";
else
edgeType = "none";
printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.gpioPin, edgeType, wfiStatus.timeStamp_us, timenow, diff);
if (toggle == 0) {
digitalWrite (OUTpin, HIGH) ;
toggle = 1;
@@ -425,7 +440,6 @@ static void wfi (unsigned int gpio, long long int timestamp) {
int main (void)
{
int major, minor;
long long int ret;
wiringPiVersion(&major, &minor);
@@ -441,27 +455,27 @@ int main (void)
pinMode(OUTpin, OUTPUT);
digitalWrite (OUTpin, LOW) ;
printf("Testing waitForInterrupt IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT);
ret = waitForInterrupt(IRQpin, INT_EDGE_FALLING, TIMEOUT, BOUNCETIME_WFI );
if (ret < 0) {
printf("waitForInterrupt returned error %lld\n", ret);
wiringPiISRStop (IRQpin) ;
printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT);
struct WPIWfiStatus wfiStatus = waitForInterrupt(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI );
if (wfiStatus.status < 0) {
printf("waitForInterrupt returned error\n");
pinMode(OUTpin, INPUT);
return 0;
}
else if (ret == 0) {
printf("waitForInterrupt timed out %lld\n\n", ret);
wiringPiISRStop (IRQpin) ;
else if (wfiStatus.status == 0) {
printf("waitForInterrupt timed out\n\n");
}
else {
printf("waitForInterrupt: falling edge fired at %lld microseconds\n\n", ret);
wiringPiISRStop (IRQpin) ;
if (wfiStatus.edge == INT_EDGE_FALLING)
printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us);
else
printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us);
}
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling edge and bouncetime %d microseconds. Toggle LED @ OUTpin on IRQ.\n\n", IRQpin, IRQpin, BOUNCETIME, OUTpin);
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ OUTpin on IRQ.\n\n", IRQpin, IRQpin, BOUNCETIME, OUTpin);
printf("To stop program hit return key\n\n");
wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi, BOUNCETIME) ;
wiringPiISR (IRQpin, INT_EDGE_BOTH, &wfi, BOUNCETIME) ;
getc(stdin);
@@ -472,6 +486,37 @@ int main (void)
}
```
Output auf dem Terminal:
```
pi@RaspberryPi:~/wiringpi-test-v3.16 $ gcc -o isr_debounce isr_debounce.c -l wiringPi
pi@RaspberryPi:~/wiringpi-test-v3.16 $ ./isr_debounce
ISR debounce test (WiringPi 3.16)
Testing waitForInterrupt on both edges IRQ @ GPIO16, timeout is 10000
waitForInterrupt: GPIO pin 16 falling edge fired at 256522528012 microseconds
Testing IRQ @ GPIO16 with trigger @ GPIO16 on both edges and bouncetime 3000 microseconds. Toggle LED @ OUTpin on IRQ.
To stop program hit return key
gpio BCM = 16, IRQ edge = rising, timestamp = 256522668010 microseconds, timenow = 256522668017, diff = 7
gpio BCM = 16, IRQ edge = falling, timestamp = 256536364014 microseconds, timenow = 256536364021, diff = 7
gpio BCM = 16, IRQ edge = rising, timestamp = 256536952011 microseconds, timenow = 256536952018, diff = 7
gpio BCM = 16, IRQ edge = falling, timestamp = 256537856010 microseconds, timenow = 256537856016, diff = 6
gpio BCM = 16, IRQ edge = rising, timestamp = 256538744011 microseconds, timenow = 256538744018, diff = 7
gpio BCM = 16, IRQ edge = falling, timestamp = 256539664010 microseconds, timenow = 256539664017, diff = 7
gpio BCM = 16, IRQ edge = rising, timestamp = 256540516010 microseconds, timenow = 256540516016, diff = 6
gpio BCM = 16, IRQ edge = falling, timestamp = 256541560013 microseconds, timenow = 256541560022, diff = 9
gpio BCM = 16, IRQ edge = rising, timestamp = 256542360010 microseconds, timenow = 256542360016, diff = 6
gpio BCM = 16, IRQ edge = falling, timestamp = 256543320012 microseconds, timenow = 256543320020, diff = 8
gpio BCM = 16, IRQ edge = rising, timestamp = 256544092021 microseconds, timenow = 256544092029, diff = 8
^C
pi@RaspberryPi:~/wiringpi-test-v3.16 $
```
## Hardware PWM (Pulsweitenmodulation)
Verfügbare GPIOs: https://pinout.xyz/pinout/pwm

View File

@@ -177,7 +177,7 @@ void printgpio(const char* text) {
}
}
static void wfi (unsigned int pin, long long int timestamp) {
static void wfi (UNU struct WPIWfiStatus wfiStatus) {
globalCounter++;
if(globalCounter>=iterations) {
printgpio("finished\n");

View File

@@ -1,3 +1,3 @@
#define VERSION "3.14"
#define VERSION "3.16"
#define VERSION_MAJOR 3
#define VERSION_MINOR 14
#define VERSION_MINOR 16

View File

@@ -75,6 +75,7 @@
#include <sys/utsname.h>
#include <linux/gpio.h>
#include <dirent.h>
#include <inttypes.h>
#include "softPwm.h"
#include "softTone.h"
@@ -143,7 +144,6 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ;
// maybe faster then piRP1Model
#define ISRP1MODEL (PI_MODEL_5==RaspberryPiModel || PI_MODEL_CM5==RaspberryPiModel|| PI_MODEL_500==RaspberryPiModel || PI_MODEL_CM5L==RaspberryPiModel)
//RP1 chip (@Pi5) RIO address
const unsigned int RP1_RIO_OUT = 0x0000;
const unsigned int RP1_RIO_OE = (0x0004/4);
@@ -482,7 +482,7 @@ static int isrFds [64] =
// ISR Data
static int chipFd = -1;
static void (*isrFunctions [64])(unsigned int, long long int) ;
static void (*isrFunctions [64])(struct WPIWfiStatus) ;
static pthread_t isrThreads[64];
static int isrMode[64]; // irq on rising/falling edge
static unsigned long isrDebouncePeriodUs [64]; // 0: debounce is off
@@ -2630,32 +2630,39 @@ unsigned int digitalReadByte2 (void)
/*
* waitForInterrupt:
* Pi Specific.
* Wait for Interrupt on a GPIO pin.
* This is actually done via the /dev/gpiochip interface regardless of
* the wiringPi access mode in-use. Maybe sometime it might get a better
* way for a bit more efficiency.
* Returns struct WPIWfiStatus
*********************************************************************************
*/
//--------------------------------------------------------------------
// waitForInteruptInit
// Prepares waitForInterrupt for edgeMode, and debounce_period_us
//
// returns -1 on error
// returns 0 on success
//--------------------------------------------------------------------
int waitForInterruptInit (int pin, int edgeMode, unsigned long debounce_period_us)
struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned long debounce_period_us) // ms < 0 wait infinite, = 0 return immediately, > 0 wait timeout
{
const char* strmode = "";
int ret;
int fd, attr, status, readret;
struct pollfd polls ;
struct gpio_v2_line_event evdata;
struct gpio_v2_line_config config;
struct gpio_v2_line_request req;
int attr, ret;
const char* strmode = "";
struct WPIWfiStatus wfiStatus;
if (wiringPiMode == WPI_MODE_PINS) {
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
} else if (wiringPiMode == WPI_MODE_PHYS) {
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
}
memset(&wfiStatus, 0, sizeof(wfiStatus));
/* open gpio */
// sleep(1);
if (wiringPiGpioDeviceGetFd()<0) {
return -1;
wfiStatus.status = -1;
return wfiStatus;
}
memset(&req, 0, sizeof(req));
@@ -2663,13 +2670,15 @@ int waitForInterruptInit (int pin, int edgeMode, unsigned long debounce_period_u
/* setup config */
config.flags = GPIO_V2_LINE_FLAG_INPUT;
switch(edgeMode) {
default:
case INT_EDGE_SETUP:
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ;
printf ("waitForInterrupt: edgeMode INT_EDGE_SETUP - exiting\n") ;
}
return -1;
wfiStatus.status = -1;
return wfiStatus;
case INT_EDGE_FALLING:
config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING;
strmode = "falling";
@@ -2686,11 +2695,11 @@ int waitForInterruptInit (int pin, int edgeMode, unsigned long debounce_period_u
strcpy(req.consumer, "wiringpi_gpio_irq");
if (debounce_period_us) {
attr = config.num_attrs;
config.num_attrs++;
gpiotools_set_bit(&config.attrs[attr].mask, 0);
config.attrs[attr].attr.id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE;
config.attrs[attr].attr.debounce_period_us = debounce_period_us;
attr = config.num_attrs;
config.num_attrs++;
gpiotools_set_bit(&config.attrs[attr].mask, 0);
config.attrs[attr].attr.id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE;
config.attrs[attr].attr.debounce_period_us = debounce_period_us;
}
req.num_lines = 1;
@@ -2698,124 +2707,129 @@ int waitForInterruptInit (int pin, int edgeMode, unsigned long debounce_period_u
req.event_buffer_size = 32;
req.config = config;
ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req);
if (ret == -1) {
ReportDeviceError("GPIO_V2_GET_LINE_IOCTL", pin , strmode, ret);
return -1;
status = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req);
if (status == -1) {
ReportDeviceError("GPIO_V2_GET_LINE_IOCTL", pin , strmode, status);
wfiStatus.status = -1;
return wfiStatus;
}
if (wiringPiDebug) {
printf ("wiringPi: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ;
printf ("waitForInterrupt: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ;
}
int fd_line = req.fd;
isrFds [pin] = fd_line;
fd = req.fd;
isrFds [pin] = fd;
isrDebouncePeriodUs[pin] = debounce_period_us;
/* set event fd nonbloack read */
/*
int flags = fcntl(fd_line, F_GETFL);
int flags = fcntl(fd, F_GETFL);
flags |= O_NONBLOCK;
ret = fcntl(fd_line, F_SETFL, flags);
if (ret) {
fprintf(stderr, "wiringPi: ERROR: fcntl set nonblock return=%d\n", ret);
status = fcntl(fd, F_SETFL, flags);
if (status) {
fprintf(stderr, "wiringPi: ERROR: fcntl set nonblock return=%d\n", status);
return -1;
}
*/
return 0;
}
/*
* waitForInterrupt:
* Pi Specific.
* Wait for Interrupt on a GPIO pin.
* This is actually done via the /dev/gpiochip interface regardless of
* the wiringPi access mode in-use. Maybe sometime it might get a better
* way for a bit more efficiency.
* Returns timestamp in microseconds on interrupt
*********************************************************************************
*/
long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long debounce_period_us) // ms < 0 wait infinite, = 0 return immediately, > 0 wait timeout
{
long long int ret;
int fd;
struct pollfd polls ;
struct gpio_v2_line_event evdata;
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
if (waitForInterruptInit (pin, edgeMode, debounce_period_us ) != 0)
return -1 ;
fd = isrFds[pin];
// Setup poll structure
polls.fd = fd;
polls.events = POLLIN | POLLERR ;
polls.events = POLLIN | POLLPRI;
polls.revents = 0;
ret = (long long int)poll(&polls, 1, mS);
ret = poll(&polls, 1, mS);
if (ret < 0) {
if (wiringPiDebug)
fprintf(stderr, "wiringPi: ERROR: poll returned=%lld\n", ret);
if (wiringPiDebug) {
fprintf(stderr, "waitForInterrupt: ERROR: poll returned=%d\n", ret);
}
wfiStatus.status = -1;
} else if (ret == 0) {
if (wiringPiDebug)
fprintf(stderr, "wiringPi: timeout: poll returned=%lld\n", ret);
if (wiringPiDebug) {
fprintf(stderr, "waitForInterrupt: timeout: poll returned=%d\n", ret);
}
wfiStatus.status = 0;
}
else {
if (wiringPiDebug)
printf ("wiringPi: IRQ line %d received %lld, fd=%d\n", pin, ret, isrFds[pin]) ;
printf ("waitForInterrupt: IRQ line %d received %d, fd=%d\n", pin, ret, isrFds[pin]) ;
if (polls.revents & POLLIN) {
/* read event data */
int readret = read(isrFds [pin], &evdata, sizeof(evdata));
readret = read(isrFds [pin], &evdata, sizeof(evdata));
if (readret == sizeof(evdata)) {
if (wiringPiDebug)
printf ("wiringPi: IRQ at PIN: %d, timestamp: %lld\n", evdata.offset, evdata.timestamp_ns) ;
printf ("waitForInterrupt: IRQ at PIN: %d, timestamp: %lld\n", evdata.offset, evdata.timestamp_ns) ;
switch (evdata.id) {
case GPIO_V2_LINE_EVENT_RISING_EDGE:
wfiStatus.edge = INT_EDGE_RISING;
if (wiringPiDebug)
printf("wiringPi: rising edge\n");
printf("waitForInterrupt: rising edge\n");
break;
case GPIO_V2_LINE_EVENT_FALLING_EDGE:
wfiStatus.edge = INT_EDGE_FALLING;
if (wiringPiDebug)
printf("wiringPi: falling edge\n");
printf("waitForInterrupt: falling edge\n");
break;
default:
wfiStatus.edge = INT_EDGE_SETUP; // edge = 0
if (wiringPiDebug)
printf("wiringPi: unknown event\n");
printf("waitForInterrupt: unknown event\n");
break;
}
ret = evdata.timestamp_ns / 1000LL; // nanoseconds u64 to microseconds
wfiStatus.timeStamp_us = evdata.timestamp_ns / 1000LL; // nanoseconds u64 to microseconds
wfiStatus.gpioPin = evdata.offset;
wfiStatus.status = 1;
}
else {
ret = -1;
wfiStatus.status = -1;
}
}
else {
wfiStatus.status = -1;
}
}
return ret;
if (isrFds[pin] > 0) {
close(isrFds [pin]); // release line
isrFds [pin] = -1;
isrDebouncePeriodUs[pin] = 0;
}
return wfiStatus;
}
/*
* wiringPiISRStop:
* stop interruptHandler thread and
* wait untill stopped.
* close isrFds[pin], reset isrFds[pin], isrFunction[pin] and isrDebouncePeriodUs[pin]
*
*********************************************************************************
*/
int waitForInterruptClose (int pin) {
if (isrFds[pin]>0) {
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptClose close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ;
}
int wiringPiISRStop (int pin) {
void *res;
if (isrFds[pin] > 0) {
if (wiringPiDebug)
printf ("wiringPiISRStop: close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ;
if (isrThreads[pin] != 0) {
if (pthread_cancel(isrThreads[pin]) == 0) {
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptClose thread canceled successfuly\n") ;
pthread_join(isrThreads[pin], &res);
if (res == PTHREAD_CANCELED) {
if (wiringPiDebug)
printf("wiringPiISRStop: thread was canceled\n");
}
else {
if (wiringPiDebug)
printf("wiringPiISRStop: thread was not canceled\n");
}
} else {
if (wiringPiDebug) {
fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n");
}
if (wiringPiDebug)
printf ("wiringPiISRStop: could not cancel thread\n");
}
}
close(isrFds [pin]);
@@ -2831,87 +2845,12 @@ int waitForInterruptClose (int pin) {
chipFd = -1;
*/
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptClose finished\n") ;
printf ("waitForInterruptClose: waitForInterruptClose finished\n") ;
}
return 0;
}
/*
* wfi:
* Pi Specific.
* Wait for Interrupt on a GPIO pin, called from interruptHandler
* Returns timestamp in microseconds on interrupt
*********************************************************************************
*/
long long int wfi(int pin)
{
long long int ret;
int fd;
struct pollfd polls ;
struct gpio_v2_line_event evdata;
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
if ((fd = isrFds [pin]) == -1)
return -2 ;
// Setup poll structure
polls.fd = fd;
polls.events = POLLIN | POLLERR ;
polls.revents = 0;
ret = (long long int)poll(&polls, 1, -1); // no timeout, wait forevver
if (ret < 0) {
if (wiringPiDebug)
fprintf(stderr, "wiringPi: ERROR: poll returned=%lld\n", ret);
} else if (ret == 0) {
if (wiringPiDebug)
fprintf(stderr, "wiringPi: timeout: poll returned=%lld\n", ret);
}
else {
if (wiringPiDebug)
printf ("wiringPi: IRQ line %d received %lld, fd=%d\n", pin, ret, isrFds[pin]) ;
if (polls.revents & POLLIN) {
/* read event data */
int readret = read(isrFds [pin], &evdata, sizeof(evdata));
if (readret == sizeof(evdata)) {
if (wiringPiDebug)
printf ("wiringPi: IRQ at PIN: %d, timestamp: %lld\n", evdata.offset, evdata.timestamp_ns) ;
switch (evdata.id) {
case GPIO_V2_LINE_EVENT_RISING_EDGE:
if (wiringPiDebug)
printf("wiringPi: rising edge\n");
break;
case GPIO_V2_LINE_EVENT_FALLING_EDGE:
if (wiringPiDebug)
printf("wiringPi: falling edge\n");
break;
default:
if (wiringPiDebug)
printf("wiringPi: unknown event\n");
break;
}
ret = evdata.timestamp_ns / 1000LL; // nanoseconds u64 to microseconds
}
else {
ret = -1;
}
}
}
return ret;
}
int wiringPiISRStop (int pin) {
return waitForInterruptClose (pin);
}
/*
* interruptHandler:
* This is a thread and gets started to wait for the interrupt we're
@@ -2923,17 +2862,18 @@ int wiringPiISRStop (int pin) {
void *interruptHandler (void *arg)
{
const char* strmode = "";
int pin, mode ;
int pin, mode, ret, fd, attr, i;
unsigned int readret;
unsigned long debounce_period_us;
struct pollfd polls ;
struct gpio_v2_line_config config;
struct gpio_v2_line_request req;
int attr, ret;
struct gpio_v2_line_event evdat[64];
struct WPIWfiStatus wfiStatus;
struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */
pin = *(int *)arg;
/* pin = pinPass ;
pinPass = -1 ;
*/
if (wiringPiGpioDeviceGetFd()<0) {
return NULL;
}
@@ -2954,7 +2894,7 @@ void *interruptHandler (void *arg)
default:
case INT_EDGE_SETUP:
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ;
printf ("interruptHandler: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ;
}
return NULL;
case INT_EDGE_FALLING:
@@ -2981,45 +2921,95 @@ void *interruptHandler (void *arg)
}
req.num_lines = 1;
req.event_buffer_size = 45;
req.offsets[0] = pin;
req.config = config;
ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req);
if (ret == -1) {
ReportDeviceError("get line event", pin , strmode, ret);
ReportDeviceError("interruptHandler: get line event", pin , strmode, ret);
return NULL;
}
/*
if (wiringPiDebug) {
printf ("wiringPi: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ;
}
*/
if (wiringPiDebug)
printf ("interruptHandler: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ;
/* set event fd */
int fd_line = req.fd;
isrFds [pin] = fd_line;
fd = req.fd;
isrFds [pin] = fd;
(void)piHiPri (55) ; // Only effective if we run as root
for (;;) {
long long int ret = wfi(pin); // poll for event and return timestamp
if ( ret> 0) { // return timestamp in microseconds
if (wiringPiDebug) {
printf ("wiringPi: call function\n") ;
}
if(isrFunctions [pin]) {
isrFunctions [pin] ((unsigned int)pin, ret) ;
}
// wait again - in the past forever - now can be stopped by waitForInterruptClose
} else if( ret< 0) {
break; // stop thread!
for (;;) { // check if event data is available, check if interruptHandler thread must be canceled
// Setup poll structure
polls.fd = fd;
polls.events = POLLIN | POLLPRI;
polls.revents = 0;
// get event data, this is also a cancelation point, when pthread_cancel is called
ret = ppoll(&polls, 1, &tspec, NULL); // returns -1 on error, 0 on timeout, >0 number of elements
if (ret < 0) { // we do not reach this point if canceled, ppoll does not return, is Cancellation Point
if (wiringPiDebug)
printf("interruptHandler: ERROR: poll returned=%d\n", ret);
pthread_exit(NULL);
return NULL; // never landing here
} else if (ret == 0) {
// if (wiringPiDebug)
// printf("interruptHandler: timeout: poll returned=%d\n", ret);
continue;
}
else {
if (wiringPiDebug)
printf ("interruptHandler: IRQ line %d received %d events, fd=%d\n", pin, ret, isrFds[pin]) ;
if (polls.revents & POLLIN) {
/* read event data */
readret = read(fd, &evdat, sizeof(evdat));
if (readret >= sizeof(evdat[0])) {
if (wiringPiDebug)
printf ("interruptHandler: IRQ at PIN: %d, events: %u\n", evdat[0].offset, readret/(unsigned int)sizeof(evdat[0])) ;
ret = readret/sizeof(evdat[0]); // number of events read from fd
if (wiringPiDebug)
printf ("interruptHandler: call function\n") ;
for (i = 0; i < ret; ++i) {
if (isrFunctions [pin]) {
if (wiringPiDebug)
printf( "interruptHandler: GPIO EVENT at %" PRIu64 " on line %d (%d|%d) \n", (uint64_t)evdat[i].timestamp_ns, evdat[i].offset, evdat[i].line_seqno, evdat[i].seqno);
wfiStatus.status = 1;
wfiStatus.gpioPin = pin;
switch (evdat[i].id) {
case GPIO_V2_LINE_EVENT_RISING_EDGE:
wfiStatus.edge = INT_EDGE_RISING;
if (wiringPiDebug)
printf("waitForInterrupt: rising edge\n");
break;
case GPIO_V2_LINE_EVENT_FALLING_EDGE:
wfiStatus.edge = INT_EDGE_FALLING;
if (wiringPiDebug)
printf("waitForInterrupt: falling edge\n");
break;
default:
wfiStatus.edge = INT_EDGE_SETUP; // edge = 0
if (wiringPiDebug)
printf("waitForInterrupt: unknown event\n");
break;
}
wfiStatus.timeStamp_us = evdat[i].timestamp_ns/1000LL;
isrFunctions [pin] (wfiStatus) ;
}
}
}
else { // if thread canceled we do not reach this point, read(...) does not return, is Cancellation Point
if (wiringPiDebug)
printf ("interruptHandler: reading events from fd received signal, exit thread\n");
pthread_exit(NULL);
return NULL; // never landing here
}
}
}
}
waitForInterruptClose (pin);
if (wiringPiDebug) {
printf ("wiringPi: interruptHandler finished\n") ;
}
return NULL ;
}
@@ -3032,7 +3022,7 @@ void *interruptHandler (void *arg)
*********************************************************************************
*/
int wiringPiISR (int pin, int edgeMode, void (*function)(unsigned int, long long int), unsigned long debounce_period_us)
int wiringPiISR (int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us)
{
const int maxpin = GetMaxPin();

View File

@@ -144,6 +144,7 @@ extern const char *piRevisionNames [16] ;
extern const char *piMakerNames [16] ;
extern const int piMemorySize [ 8] ;
// Intended for the GPIO program Use at your own risk.
// Threads
@@ -298,10 +299,17 @@ extern void digitalWriteByte2 (int value) ;
// Interrupts
// (Also Pi hardware specific)
extern long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long debounce_period_us) ; // V3.14 phylax
extern int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), unsigned long debounce_period_us) ; // v3.14 phylax
// status returned from waitForInterrupt V3.16
struct WPIWfiStatus {
int status; // -1: error, 0: timeout, 1: valud values for edge and timeStamp_us
unsigned int gpioPin; // gpio as BCM pin
int edge; // One of INT_EDGE_FALLING or INT_EDGE_RISING
long long int timeStamp_us; // time stamp in microseconds, when interrupt happened
};
extern struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned long debounce_period_us) ; // V3.16 phylax
extern int wiringPiISR (int pin, int mode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us) ; // v3.16 phylax
extern int wiringPiISRStop (int pin) ; //V3.2
extern int waitForInterruptClose(int pin) ; //V3.2
// Threads