From 2f35ff5ec84b41ae2b249f87edec589f87dc30ab Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Thu, 20 Feb 2025 11:29:30 +0100 Subject: [PATCH] Version v3.16: added wfi status for wiringPiISR and waitForInterrupt --- README.md | 8 +-- VERSION | 2 +- documentation/deutsch/functions.md | 100 +++++++++++++++++++++-------- gpio/gpio.c | 2 +- version.h | 4 +- wiringPi/wiringPi.c | 90 ++++++++++++++++++-------- wiringPi/wiringPi.h | 12 +++- 7 files changed, 157 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 7125be7..e08470c 100644 --- a/README.md +++ b/README.md @@ -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 ``` diff --git a/VERSION b/VERSION index 230693c..1bc446c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.15 \ No newline at end of file +3.16 \ No newline at end of file diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 82e94f8..6ff4933 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -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,24 +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); + 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); + else if (wfiStatus.status == 0) { + printf("waitForInterrupt timed out\n\n"); } 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"); - wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi, BOUNCETIME) ; + wiringPiISR (IRQpin, INT_EDGE_BOTH, &wfi, BOUNCETIME) ; 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) Verfügbare GPIOs: https://pinout.xyz/pinout/pwm diff --git a/gpio/gpio.c b/gpio/gpio.c index f79188b..1ee2c33 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -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"); diff --git a/version.h b/version.h index d7f42c6..5ea1e8c 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.15" +#define VERSION "3.16" #define VERSION_MAJOR 3 -#define VERSION_MINOR 15 +#define VERSION_MINOR 16 diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index a818945..0f2ea7d 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -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 @@ -2637,28 +2637,32 @@ unsigned int digitalReadByte2 (void) * 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 + * 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; struct pollfd polls ; struct gpio_v2_line_event evdata; struct gpio_v2_line_config config; struct gpio_v2_line_request req; const char* strmode = ""; + struct WPIWfiStatus wfiStatus; if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio [pin] ; else if (wiringPiMode == WPI_MODE_PHYS) pin = physToGpio [pin] ; + memset(&wfiStatus, 0, sizeof(wfiStatus)); + /* open gpio */ if (wiringPiGpioDeviceGetFd()<0) { - return -1; + wfiStatus.status = -1; + return wfiStatus; } memset(&req, 0, sizeof(req)); @@ -2671,9 +2675,10 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb 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"; @@ -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); if (status == -1) { ReportDeviceError("GPIO_V2_GET_LINE_IOCTL", pin , strmode, status); - return -1; + 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) ; } 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.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 */ 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; + } } - + if (isrFds[pin] > 0) { close(isrFds [pin]); // release line isrFds [pin] = -1; 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_request req; struct gpio_v2_line_event evdat[64]; + struct WPIWfiStatus wfiStatus; struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */ pin = *(int *)arg; @@ -2957,7 +2977,27 @@ void *interruptHandler (void *arg) 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); - 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(); diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index e299f99..be64b16 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -299,8 +299,16 @@ 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 // Threads