Version v3.16: added wfi status for wiringPiISR and waitForInterrupt

This commit is contained in:
phylax2020
2025-02-20 11:29:30 +01:00
parent 44538850b4
commit 2f35ff5ec8
7 changed files with 157 additions and 61 deletions

View File

@@ -99,10 +99,10 @@ cd WiringPi
# build the package # build the package
./build debian ./build debian
mv debian-template/wiringpi-3.0-1.deb . mv debian-template/wiringpi-3.x.deb .
# install it # 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 ```sh
# unzip the archive # unzip the archive
tar -xfv wiringpi_3.0.tar.gz tar -xfv wiringpi_3.x.tar.gz
``` ```
Install the debian package: Install the debian package:
```sh ```sh
# install a dpkg # install a dpkg
sudo apt install ./wiringpi-3.0-1.deb sudo apt install ./wiringpi-3.x.deb
``` ```

View File

@@ -1 +1 @@
3.15 3.16

View File

@@ -291,7 +291,7 @@ Registriert eine Interrupt Service Routine (ISR) bzw. Funktion die bei Flankenwe
>>> >>>
```C ```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). ``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_FALLING ... Fallende Flanke
- INT_EDGE_BOTH ... Steigende und fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke
``*function``: Funktionspointer für ISR mit Rückgabeparameter pin und Zeitstempel: ``*function``: Funktionspointer für ISR mit Rückgabeparameter struct WPIWfiStatus:
> unsigned int: pin ```C
> long long int: Zeitstempel 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 ``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. Blockiert das Programm bis zum Eintreffen der auslösenden Flanke oder bis zum Ablauf des Timeouts.
>>> >>>
```C ```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). ``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. ``bouncetime``: Entprellzeit in Microsekunden, 0 schaltet Entprellen ab.
``Rückgabewert``: ``Rückgabewert``:
> \>0 ... Zeitstempel des Interrupt Ereignisses in Mikrosekunden ```C
> 0 ... Timeout struct WPIWfiStatus {
> \-1 ... GPIO Device Chip nicht erfolgreich geöffnet int status; // -1: error, 0: timeout, 1: valid values for edge and timeStamp_us
> \-2 ... ISR wurde nicht registriert 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:** **Beispiel:**
```C ```C
/* /*
* isr_debounce.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; // struct timeval now;
long long int timenow, diff; long long int timenow, diff;
struct timespec curr; struct timespec curr;
char *edgeType;
if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) { if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) {
printf("clock_gettime error"); printf("clock_gettime error");
return; return;
} }
timenow = curr.tv_sec * 1000000LL + curr.tv_nsec/1000L; // convert to microseconds timenow = curr.tv_sec * 1000000LL + curr.tv_nsec/1000L; // convert to microseconds
diff = timenow - timestamp; diff = timenow - wfiStatus.timeStamp_us;
if (wfiStatus.edge == INT_EDGE_RISING)
printf("gpio BCM = %d, IRQ timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", gpio, timestamp, timenow, diff); 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) { if (toggle == 0) {
digitalWrite (OUTpin, HIGH) ; digitalWrite (OUTpin, HIGH) ;
toggle = 1; toggle = 1;
@@ -425,7 +440,6 @@ static void wfi (unsigned int gpio, long long int timestamp) {
int main (void) int main (void)
{ {
int major, minor; int major, minor;
long long int ret;
wiringPiVersion(&major, &minor); wiringPiVersion(&major, &minor);
@@ -441,24 +455,27 @@ int main (void)
pinMode(OUTpin, OUTPUT); pinMode(OUTpin, OUTPUT);
digitalWrite (OUTpin, LOW) ; digitalWrite (OUTpin, LOW) ;
printf("Testing waitForInterrupt IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT);
ret = waitForInterrupt(IRQpin, INT_EDGE_FALLING, TIMEOUT, BOUNCETIME_WFI ); struct WPIWfiStatus wfiStatus = waitForInterrupt(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI );
if (ret < 0) { if (wfiStatus.status < 0) {
printf("waitForInterrupt returned error %lld\n", ret); printf("waitForInterrupt returned error\n");
pinMode(OUTpin, INPUT); pinMode(OUTpin, INPUT);
return 0; return 0;
} }
else if (ret == 0) { else if (wfiStatus.status == 0) {
printf("waitForInterrupt timed out %lld\n\n", ret); printf("waitForInterrupt timed out\n\n");
} }
else { else {
printf("waitForInterrupt: falling edge fired at %lld microseconds\n\n", ret); 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"); 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); getc(stdin);
@@ -469,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) ## Hardware PWM (Pulsweitenmodulation)
Verfügbare GPIOs: https://pinout.xyz/pinout/pwm 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++; globalCounter++;
if(globalCounter>=iterations) { if(globalCounter>=iterations) {
printgpio("finished\n"); printgpio("finished\n");

View File

@@ -1,3 +1,3 @@
#define VERSION "3.15" #define VERSION "3.16"
#define VERSION_MAJOR 3 #define VERSION_MAJOR 3
#define VERSION_MINOR 15 #define VERSION_MINOR 16

View File

@@ -482,7 +482,7 @@ static int isrFds [64] =
// ISR Data // ISR Data
static int chipFd = -1; 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 pthread_t isrThreads[64];
static int isrMode[64]; // irq on rising/falling edge static int isrMode[64]; // irq on rising/falling edge
static unsigned long isrDebouncePeriodUs [64]; // 0: debounce is off static unsigned long isrDebouncePeriodUs [64]; // 0: debounce is off
@@ -2637,28 +2637,32 @@ unsigned int digitalReadByte2 (void)
* This is actually done via the /dev/gpiochip interface regardless of * This is actually done via the /dev/gpiochip interface regardless of
* the wiringPi access mode in-use. Maybe sometime it might get a better * the wiringPi access mode in-use. Maybe sometime it might get a better
* way for a bit more efficiency. * way for a bit more efficiency.
* Returns timestamp in microseconds on interrupt * Returns struct WPIWfiStatus
********************************************************************************* *********************************************************************************
*/ */
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 struct WPIWfiStatus 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 ret;
int fd, attr, status, readret; int fd, attr, status, readret;
struct pollfd polls ; struct pollfd polls ;
struct gpio_v2_line_event evdata; struct gpio_v2_line_event evdata;
struct gpio_v2_line_config config; struct gpio_v2_line_config config;
struct gpio_v2_line_request req; struct gpio_v2_line_request req;
const char* strmode = ""; const char* strmode = "";
struct WPIWfiStatus wfiStatus;
if (wiringPiMode == WPI_MODE_PINS) if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ; pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS) else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ; pin = physToGpio [pin] ;
memset(&wfiStatus, 0, sizeof(wfiStatus));
/* open gpio */ /* open gpio */
if (wiringPiGpioDeviceGetFd()<0) { if (wiringPiGpioDeviceGetFd()<0) {
return -1; wfiStatus.status = -1;
return wfiStatus;
} }
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
@@ -2671,9 +2675,10 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb
default: default:
case INT_EDGE_SETUP: case INT_EDGE_SETUP:
if (wiringPiDebug) { 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: case INT_EDGE_FALLING:
config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING;
strmode = "falling"; strmode = "falling";
@@ -2705,11 +2710,12 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb
status = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); status = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req);
if (status == -1) { if (status == -1) {
ReportDeviceError("GPIO_V2_GET_LINE_IOCTL", pin , strmode, status); ReportDeviceError("GPIO_V2_GET_LINE_IOCTL", pin , strmode, status);
return -1; wfiStatus.status = -1;
return wfiStatus;
} }
if (wiringPiDebug) { 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) ;
} }
fd = req.fd; fd = req.fd;
@@ -2732,53 +2738,66 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb
polls.events = POLLIN | POLLPRI; polls.events = POLLIN | POLLPRI;
polls.revents = 0; polls.revents = 0;
ret = (long long int)poll(&polls, 1, mS); ret = poll(&polls, 1, mS);
if (ret < 0) { if (ret < 0) {
if (wiringPiDebug) if (wiringPiDebug) {
fprintf(stderr, "wiringPi: ERROR: poll returned=%lld\n", ret); fprintf(stderr, "waitForInterrupt: ERROR: poll returned=%d\n", ret);
}
wfiStatus.status = -1;
} else if (ret == 0) { } else if (ret == 0) {
if (wiringPiDebug) if (wiringPiDebug) {
fprintf(stderr, "wiringPi: timeout: poll returned=%lld\n", ret); fprintf(stderr, "waitForInterrupt: timeout: poll returned=%d\n", ret);
}
wfiStatus.status = 0;
} }
else { else {
if (wiringPiDebug) 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) { if (polls.revents & POLLIN) {
/* read event data */ /* read event data */
readret = read(isrFds [pin], &evdata, sizeof(evdata)); readret = read(isrFds [pin], &evdata, sizeof(evdata));
if (readret == sizeof(evdata)) { if (readret == sizeof(evdata)) {
if (wiringPiDebug) 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) { switch (evdata.id) {
case GPIO_V2_LINE_EVENT_RISING_EDGE: case GPIO_V2_LINE_EVENT_RISING_EDGE:
wfiStatus.edge = INT_EDGE_RISING;
if (wiringPiDebug) if (wiringPiDebug)
printf("wiringPi: rising edge\n"); printf("waitForInterrupt: rising edge\n");
break; break;
case GPIO_V2_LINE_EVENT_FALLING_EDGE: case GPIO_V2_LINE_EVENT_FALLING_EDGE:
wfiStatus.edge = INT_EDGE_FALLING;
if (wiringPiDebug) if (wiringPiDebug)
printf("wiringPi: falling edge\n"); printf("waitForInterrupt: falling edge\n");
break; break;
default: default:
wfiStatus.edge = INT_EDGE_SETUP; // edge = 0
if (wiringPiDebug) if (wiringPiDebug)
printf("wiringPi: unknown event\n"); printf("waitForInterrupt: unknown event\n");
break; 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 { else {
ret = -1; wfiStatus.status = -1;
} }
} }
else {
wfiStatus.status = -1;
}
} }
if (isrFds[pin] > 0) { if (isrFds[pin] > 0) {
close(isrFds [pin]); // release line close(isrFds [pin]); // release line
isrFds [pin] = -1; isrFds [pin] = -1;
isrDebouncePeriodUs[pin] = 0; isrDebouncePeriodUs[pin] = 0;
} }
return ret;
return wfiStatus;
} }
/* /*
@@ -2850,6 +2869,7 @@ void *interruptHandler (void *arg)
struct gpio_v2_line_config config; struct gpio_v2_line_config config;
struct gpio_v2_line_request req; struct gpio_v2_line_request req;
struct gpio_v2_line_event evdat[64]; struct gpio_v2_line_event evdat[64];
struct WPIWfiStatus wfiStatus;
struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */ struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */
pin = *(int *)arg; pin = *(int *)arg;
@@ -2957,7 +2977,27 @@ void *interruptHandler (void *arg)
if (isrFunctions [pin]) { if (isrFunctions [pin]) {
if (wiringPiDebug) 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); 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);
isrFunctions [pin] ((unsigned int)pin, evdat[i].timestamp_ns/1000LL) ; 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) ;
} }
} }
} }
@@ -2982,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(); const int maxpin = GetMaxPin();

View File

@@ -299,8 +299,16 @@ extern void digitalWriteByte2 (int value) ;
// Interrupts // Interrupts
// (Also Pi hardware specific) // (Also Pi hardware specific)
extern long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long debounce_period_us) ; // V3.14 phylax // status returned from waitForInterrupt V3.16
extern int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), unsigned long debounce_period_us) ; // v3.14 phylax 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 wiringPiISRStop (int pin) ; //V3.2
// Threads // Threads