From 18295f0dfb86d657aaf4e337eb460af9c8ff73cc Mon Sep 17 00:00:00 2001 From: phylax2020 <61159697+phylax2020@users.noreply.github.com> Date: Tue, 28 Jan 2025 21:46:50 +0100 Subject: [PATCH 01/42] Update functions.md Vor Aufruf waitForInterrupt muss waitForInterruptInit aufgerufen werden. --- documentation/deutsch/functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 114faa3..d759b50 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -357,7 +357,7 @@ int waitForInterrupt (int pin, int mS) ``Rückgabewert``: Fehler > 0 ... Erfolgreich > -1 ... GPIO Device Chip nicht erfolgreich geöffnet -> -2 ... ISR wurde nicht registriert (wiringPiISR muss aufgerufen werden) +> -2 ... ISR wurde nicht registriert (waitForInterruptInit muss aufgerufen werden) ## Hardware PWM (Pulsweitenmodulation) @@ -564,4 +564,4 @@ if (fd>0) { ## SPI - Bus -... \ No newline at end of file +... From 3e1f99e24d581b9bc9a7589117203c6f1dedb6a5 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Tue, 28 Jan 2025 22:30:54 +0100 Subject: [PATCH 02/42] new example isr_debounce.c --- examples/isr_debounce.c | 118 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 examples/isr_debounce.c diff --git a/examples/isr_debounce.c b/examples/isr_debounce.c new file mode 100644 index 0000000..5c6ca8b --- /dev/null +++ b/examples/isr_debounce.c @@ -0,0 +1,118 @@ +/* + * isr_debounce.c: + * Wait for Interrupt test program WiringPi >=3.2 - ISR method + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +// #include +#include + +#define BOUNCETIME 300 +#define TIMEOUT 10000 +//************************************* +// BCM pins +// IRQpin : setup as input with internal pullup. Connected with push button to GND with 1K resistor in series. +// OUTpin : connected to a LED with 470 Ohm resistor in series to GND. Toggles LED with every push button pressed. +//************************************* +#define IRQpin 16 +#define OUTpin 12 + +int toggle = 0; + +/* + * myInterrupt: + ********************************************************************************* + */ + +static void wfi (unsigned int gpio, long long int timestamp) { +// struct timeval now; + long long int timenow, diff; + struct timespec curr; + + 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); + if (toggle == 0) { + digitalWrite (OUTpin, HIGH) ; + toggle = 1; + } + else { + digitalWrite (OUTpin, LOW) ; + toggle = 0; + } +} + + + +int main (void) +{ + int major, minor; + long long int ret; + + wiringPiVersion(&major, &minor); + + printf("\nISR debounce test (WiringPi %d.%d)\n\n", major, minor); + + wiringPiSetupGpio() ; + + pinMode(IRQpin, INPUT); + + // pull up/down mode (PUD_OFF, PUD_UP, PUD_DOWN) => down + pullUpDnControl(IRQpin, PUD_UP); + + pinMode(OUTpin, OUTPUT); + digitalWrite (OUTpin, LOW) ; + + // test waitForInterrupt + + ret = waitForInterruptInit (IRQpin, INT_EDGE_FALLING); + if (ret < 0) { + printf("waitForInterruptInit returned error %d\n", ret); + pinMode(OUTpin, INPUT); + return 0; + } + + printf("Testing waitForInterrupt IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); + ret = waitForInterrupt(IRQpin, TIMEOUT, 0); + if (ret < 0) { + printf("waitForInterrupt returned error %lld\n", ret); + wiringPiISRStop (IRQpin) ; + pinMode(OUTpin, INPUT); + return 0; + } + else if (ret == 0) { + printf("waitForInterrupt timed out %lld\n\n", ret); + wiringPiISRStop (IRQpin) ; + } + else { + printf("waitForInterrupt returned success. ret = %lld\n\n", ret); + wiringPiISRStop (IRQpin) ; + } + + printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling edge and bouncetime %d ms. 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) ; + +// sleep(30); + getc(stdin); + + wiringPiISRStop (IRQpin) ; + pinMode(OUTpin, INPUT); + + return 0 ; +} \ No newline at end of file From 349a5adb389ccc8c2baf649cfc7408401eb26e66 Mon Sep 17 00:00:00 2001 From: phylax2020 <61159697+phylax2020@users.noreply.github.com> Date: Tue, 28 Jan 2025 23:45:15 +0100 Subject: [PATCH 03/42] Update functions.md --- documentation/deutsch/functions.md | 38 ++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index d759b50..461e4b1 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 mode, void (*function)(void)); +int wiringPiISR(int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime); ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). @@ -300,7 +300,9 @@ int wiringPiISR(int pin, int mode, void (*function)(void)); - INT_EDGE_FALLING ... Fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke -``*function``: Funktionspointer für ISR +``*function``: Funktionspointer für ISR mit Rückgabeparameter pin: unsigned int und Zeitstempel: long long int + +``bouncetime``: Entprellzeit in ms, 0 ms schaltet das Entprellen ab ``Rückgabewert``: > 0 ... Erfolgreich @@ -345,21 +347,43 @@ int main (void) { ### waitForInterrupt -Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout. +Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout und Entprellzeit in Millisekunden. >>> ```C -int waitForInterrupt (int pin, int mS) +long long int waitForInterrupt (int pin, int mS, int bouncetime) ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). -``mS``: Timeout in Milisekunden. -``Rückgabewert``: Fehler -> 0 ... Erfolgreich +``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, >0 wartet maximal mS Millisekunden + +``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab + +``Rückgabewert``: +> >0 ... Zeitstempel des Interrupt Ereignisses +> 0 ... Timeout > -1 ... GPIO Device Chip nicht erfolgreich geöffnet > -2 ... ISR wurde nicht registriert (waitForInterruptInit muss aufgerufen werden) +### waitForInterruptInit + +Initiaölisiert die Funktion waitForInterrupt +>>> +```C +int waitForInterruptInit (int pin, int mode) +``` +``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer) + +``mode``: INT_EDGE_RISING,INT_EDGE_FALLING,INT_EDGE_BOTH + +``Rückgabewert``: + +> -1 ... Fehler +> +> 0 ... erfolgreich + + ## Hardware PWM (Pulsweitenmodulation) Verfügbare GPIOs: https://pinout.xyz/pinout/pwm From 12e3abab94b7b2c0066f1812cd19a428a424e7f4 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 09:34:49 +0100 Subject: [PATCH 04/42] functions.md --- documentation/deutsch/functions.md | 35 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index d759b50..7af3db9 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 mode, void (*function)(void)); +int wiringPiISR(int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime); ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). @@ -300,7 +300,8 @@ int wiringPiISR(int pin, int mode, void (*function)(void)); - INT_EDGE_FALLING ... Fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke -``*function``: Funktionspointer für ISR +``*function``: Funktionspointer für ISR mit Rückgabeparameter pin: unsigned int und Zeitstempel: long long int +``bouncetime``: Entprellzeit in ms, 0 ms schaltet das Entprellen ab ``Rückgabewert``: > 0 ... Erfolgreich @@ -345,21 +346,41 @@ int main (void) { ### waitForInterrupt -Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout. +Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout und Entprellzeit in Millisekunden. >>> ```C -int waitForInterrupt (int pin, int mS) +long long int waitForInterrupt (int pin, int mS, int bouncetime) ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). -``mS``: Timeout in Milisekunden. -``Rückgabewert``: Fehler -> 0 ... Erfolgreich +``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, \>0 wartet maximal mS Millisekunden +``bouncetime``: Entprellzeit in Millisekunden, 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 (waitForInterruptInit muss aufgerufen werden) +### waitForInterruptInit + +Initialisiert die Funktion waitForInterrupt, definiert, welche Flanke den Interrupt erzeugen soll + +>>> +```C +int waitForInterruptInit (int pin, int mode) +``` + +``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer) +``mode``: INT_EDGE_RISING, INT_EDGE_FALLING, INT_EDGE_BOTH + +``Rückgabewert``: +> -1 ... Fehler +> 0 ... erfolgreich + + ## Hardware PWM (Pulsweitenmodulation) Verfügbare GPIOs: https://pinout.xyz/pinout/pwm From cd65d29b14c867335cfd4bcea06dcc04f85d2016 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 09:40:37 +0100 Subject: [PATCH 05/42] functions.md --- documentation/deutsch/functions.md | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 16d9bc6..7af3db9 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -301,10 +301,6 @@ int wiringPiISR(int pin, int mode, void (*function)(unsigned int, long long int) - INT_EDGE_BOTH ... Steigende und fallende Flanke ``*function``: Funktionspointer für ISR mit Rückgabeparameter pin: unsigned int und Zeitstempel: long long int -<<<<<<< HEAD -======= - ->>>>>>> 349a5adb389ccc8c2baf649cfc7408401eb26e66 ``bouncetime``: Entprellzeit in ms, 0 ms schaltet das Entprellen ab ``Rückgabewert``: > 0 ... Erfolgreich @@ -358,20 +354,11 @@ long long int waitForInterrupt (int pin, int mS, int bouncetime) ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). -<<<<<<< HEAD ``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, \>0 wartet maximal mS Millisekunden ``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab ``Rückgabewert``: > \>0 ... Zeitstempel des Interrupt Ereignisses in Mikrosekunden -======= -``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, >0 wartet maximal mS Millisekunden - -``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab - -``Rückgabewert``: -> >0 ... Zeitstempel des Interrupt Ereignisses ->>>>>>> 349a5adb389ccc8c2baf649cfc7408401eb26e66 > 0 ... Timeout > -1 ... GPIO Device Chip nicht erfolgreich geöffnet > -2 ... ISR wurde nicht registriert (waitForInterruptInit muss aufgerufen werden) @@ -379,33 +366,18 @@ long long int waitForInterrupt (int pin, int mS, int bouncetime) ### waitForInterruptInit -<<<<<<< HEAD Initialisiert die Funktion waitForInterrupt, definiert, welche Flanke den Interrupt erzeugen soll -======= -Initiaölisiert die Funktion waitForInterrupt ->>>>>>> 349a5adb389ccc8c2baf649cfc7408401eb26e66 >>> ```C int waitForInterruptInit (int pin, int mode) ``` -<<<<<<< HEAD ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer) ``mode``: INT_EDGE_RISING, INT_EDGE_FALLING, INT_EDGE_BOTH ``Rückgabewert``: > -1 ... Fehler -======= -``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer) - -``mode``: INT_EDGE_RISING,INT_EDGE_FALLING,INT_EDGE_BOTH - -``Rückgabewert``: - -> -1 ... Fehler -> ->>>>>>> 349a5adb389ccc8c2baf649cfc7408401eb26e66 > 0 ... erfolgreich From c6945bb450b375d737ae51078f3ec441bb17efa3 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 09:45:16 +0100 Subject: [PATCH 06/42] functions.md --- documentation/deutsch/functions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 7af3db9..67008ea 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -354,7 +354,8 @@ long long int waitForInterrupt (int pin, int mS, int bouncetime) ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). -``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, \>0 wartet maximal mS Millisekunden +``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, \>0 wartet maximal mS Millisekunden. + ``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab ``Rückgabewert``: From 3370e8d137fc078e9bf001391ef7795615dfb89b Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 09:49:05 +0100 Subject: [PATCH 07/42] functions.md --- documentation/deutsch/functions.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 67008ea..b417c4c 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -354,8 +354,7 @@ long long int waitForInterrupt (int pin, int mS, int bouncetime) ``` ``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). -``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, \>0 wartet maximal mS Millisekunden. - +``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, 1...n wartet maximal mS Millisekunden. ``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab ``Rückgabewert``: From ff440b029f69361b4f07aac4c1763ce440c16db6 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 10:29:18 +0100 Subject: [PATCH 08/42] functions.md --- documentation/deutsch/functions.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index b417c4c..499edab 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -353,15 +353,18 @@ Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout und Entp long long int waitForInterrupt (int pin, int mS, int bouncetime) ``` -``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). -``mS``: Timeout in Milisekunden. -1 warten ohne timeout, 0 wartet nicht, 1...n wartet maximal mS Millisekunden. +``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). +``mS``: Timeout in Milisekunden. + - \-1 warten ohne timeout + - 0 wartet nicht + - 1...n wartet maximal mS Millisekunden ``bouncetime``: Entprellzeit in Millisekunden, 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 (waitForInterruptInit muss aufgerufen werden) +> \-1 ... GPIO Device Chip nicht erfolgreich geöffnet +> \-2 ... ISR wurde nicht registriert (waitForInterruptInit muss aufgerufen werden) ### waitForInterruptInit @@ -373,11 +376,11 @@ Initialisiert die Funktion waitForInterrupt, definiert, welche Flanke den Interr int waitForInterruptInit (int pin, int mode) ``` -``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer) +``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer) ``mode``: INT_EDGE_RISING, INT_EDGE_FALLING, INT_EDGE_BOTH ``Rückgabewert``: -> -1 ... Fehler +> \-1 ... Fehler > 0 ... erfolgreich From 554b83236b86f21c2dec37c7aefb8bac21b26cb8 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 10:53:35 +0100 Subject: [PATCH 09/42] functions.md --- documentation/deutsch/functions.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 499edab..6b79287 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -357,8 +357,8 @@ long long int waitForInterrupt (int pin, int mS, int bouncetime) ``mS``: Timeout in Milisekunden. - \-1 warten ohne timeout - 0 wartet nicht - - 1...n wartet maximal mS Millisekunden -``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab + - 1...n wartet maximal n mS Millisekunden +``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab ``Rückgabewert``: > \>0 ... Zeitstempel des Interrupt Ereignisses in Mikrosekunden @@ -376,12 +376,12 @@ Initialisiert die Funktion waitForInterrupt, definiert, welche Flanke den Interr int waitForInterruptInit (int pin, int mode) ``` -``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer) -``mode``: INT_EDGE_RISING, INT_EDGE_FALLING, INT_EDGE_BOTH +``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer) +``mode``: INT_EDGE_RISING, INT_EDGE_FALLING, INT_EDGE_BOTH ``Rückgabewert``: -> \-1 ... Fehler -> 0 ... erfolgreich +> \-1 ... Fehler +> 0 ... erfolgreich ## Hardware PWM (Pulsweitenmodulation) From 92793adf42e901d0c4d32ef5b3fc45eecc981871 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 11:03:34 +0100 Subject: [PATCH 10/42] functions.md --- documentation/deutsch/functions.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 6b79287..103641f 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -294,13 +294,16 @@ Registriert eine Interrupt Service Routine (ISR) bzw. Funktion die bei Flankenwe int wiringPiISR(int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime); ``` -``pin``: Der gewünschte Pin (BCM-, WiringPi- oder Pin-Nummer). -``mode``: Auslösende Flankenmodus +``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). +``mode``: Auslösende Flankenmodus - INT_EDGE_RISING ... Steigende Flanke - INT_EDGE_FALLING ... Fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke -``*function``: Funktionspointer für ISR mit Rückgabeparameter pin: unsigned int und Zeitstempel: long long int +``*function``: Funktionspointer für ISR mit Rückgabeparameter pin und Zeitstempel: + > unsigned int: pin + > long long int: Zeitstempel + ``bouncetime``: Entprellzeit in ms, 0 ms schaltet das Entprellen ab ``Rückgabewert``: > 0 ... Erfolgreich From 2e3dae0f72a6b23c20c3aa891e0a5f2434511c1e Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 11:40:41 +0100 Subject: [PATCH 11/42] functions.md --- documentation/deutsch/functions.md | 143 ++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 21 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 103641f..1fb5ccb 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -305,11 +305,12 @@ int wiringPiISR(int pin, int mode, void (*function)(unsigned int, long long int) > long long int: Zeitstempel ``bouncetime``: Entprellzeit in ms, 0 ms schaltet das Entprellen ab + ``Rückgabewert``: > 0 ... Erfolgreich -Beispiel siehe wiringPiISRStop. +Beispiel siehe waitForInterruptInit. ### wiringPiISRStop @@ -327,26 +328,6 @@ int wiringPiISRStop (int pin) -**Beispiel:** - -```C -static volatile int edgeCounter; - -static void isr(void) { - edgeCounter++; -} - -int main (void) { - wiringPiSetupPinType(WPI_PIN_BCM); - edgeCounter = 0; - wiringPiISR (17, INT_EDGE_RISING, &isr); - Sleep(1000); - printf("%d rinsing edges\n", ) - wiringPiISRStop(17) ; -} -``` - - ### waitForInterrupt Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout und Entprellzeit in Millisekunden. @@ -387,6 +368,126 @@ int waitForInterruptInit (int pin, int mode) > 0 ... erfolgreich +**Beispiel:** + +```C +/* + * isr_debounce.c: + * Wait for Interrupt test program WiringPi >=3.13 - ISR method + * + * + */ + +#include +#include +#include +#include +#include + +#include + +#define BOUNCETIME 300 +#define TIMEOUT 10000 +//************************************* +// BCM pins +// IRQpin : setup as input with internal pullup. Connected with push button to GND with 1K resistor in series. +// OUTpin : connected to a LED with 470 Ohm resistor in series to GND. Toggles LED with every push button pressed. +//************************************* +#define IRQpin 16 +#define OUTpin 12 + +int toggle = 0; + +/* + * myInterrupt: + ********************************************************************************* + */ + +static void wfi (unsigned int gpio, long long int timestamp) { +// struct timeval now; + long long int timenow, diff; + struct timespec curr; + + 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); + if (toggle == 0) { + digitalWrite (OUTpin, HIGH) ; + toggle = 1; + } + else { + digitalWrite (OUTpin, LOW) ; + toggle = 0; + } +} + + + +int main (void) +{ + int major, minor; + long long int ret; + + wiringPiVersion(&major, &minor); + + printf("\nISR debounce test (WiringPi %d.%d)\n\n", major, minor); + + wiringPiSetupGpio() ; + + pinMode(IRQpin, INPUT); + + // pull up/down mode (PUD_OFF, PUD_UP, PUD_DOWN) => down + pullUpDnControl(IRQpin, PUD_UP); + + pinMode(OUTpin, OUTPUT); + digitalWrite (OUTpin, LOW) ; + + // test waitForInterrupt + + ret = waitForInterruptInit (IRQpin, INT_EDGE_FALLING); + if (ret < 0) { + printf("waitForInterruptInit returned error %d\n", ret); + pinMode(OUTpin, INPUT); + return 0; + } + + printf("Testing waitForInterrupt IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); + ret = waitForInterrupt(IRQpin, TIMEOUT, 0); + if (ret < 0) { + printf("waitForInterrupt returned error %lld\n", ret); + wiringPiISRStop (IRQpin) ; + pinMode(OUTpin, INPUT); + return 0; + } + else if (ret == 0) { + printf("waitForInterrupt timed out %lld\n\n", ret); + wiringPiISRStop (IRQpin) ; + } + else { + printf("waitForInterrupt: falling edge fired at %lld microseconds\n\n", ret); + wiringPiISRStop (IRQpin) ; + } + + printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling edge and bouncetime %d ms. 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) ; + + getc(stdin); + + wiringPiISRStop (IRQpin) ; + pinMode(OUTpin, INPUT); + + return 0 ; +} +``` + ## Hardware PWM (Pulsweitenmodulation) Verfügbare GPIOs: https://pinout.xyz/pinout/pwm From b29831d563902535eb29426983785080186b2c27 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 11:47:07 +0100 Subject: [PATCH 12/42] functions.md --- documentation/deutsch/functions.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 1fb5ccb..a6ece16 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -338,17 +338,17 @@ long long int waitForInterrupt (int pin, int mS, int bouncetime) ``` ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). -``mS``: Timeout in Milisekunden. - - \-1 warten ohne timeout - - 0 wartet nicht +``mS``: Timeout in Milisekunden. + - \-1 warten ohne timeout + - 0 wartet nicht - 1...n wartet maximal n mS Millisekunden ``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab -``Rückgabewert``: -> \>0 ... Zeitstempel des Interrupt Ereignisses in Mikrosekunden +``Rückgabewert``: +> \>0 ... Zeitstempel des Interrupt Ereignisses in Mikrosekunden > 0 ... Timeout > \-1 ... GPIO Device Chip nicht erfolgreich geöffnet -> \-2 ... ISR wurde nicht registriert (waitForInterruptInit muss aufgerufen werden) +> \-2 ... ISR wurde nicht registriert (waitForInterruptInit muss aufgerufen werden) ### waitForInterruptInit @@ -363,7 +363,7 @@ int waitForInterruptInit (int pin, int mode) ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer) ``mode``: INT_EDGE_RISING, INT_EDGE_FALLING, INT_EDGE_BOTH -``Rückgabewert``: +``Rückgabewert``: > \-1 ... Fehler > 0 ... erfolgreich From b55101e013c0af8b2255b487a7d7c6e19ce515aa Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 11:50:28 +0100 Subject: [PATCH 13/42] isr_debounce.c --- examples/isr_debounce.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/isr_debounce.c b/examples/isr_debounce.c index 5c6ca8b..8ddc9c1 100644 --- a/examples/isr_debounce.c +++ b/examples/isr_debounce.c @@ -1,6 +1,6 @@ /* * isr_debounce.c: - * Wait for Interrupt test program WiringPi >=3.2 - ISR method + * Wait for Interrupt test program WiringPi >=3.13 - ISR method * * */ @@ -10,9 +10,7 @@ #include #include #include -#include -#include -// #include + #include #define BOUNCETIME 300 @@ -99,7 +97,7 @@ int main (void) wiringPiISRStop (IRQpin) ; } else { - printf("waitForInterrupt returned success. ret = %lld\n\n", ret); + printf("waitForInterrupt: falling edge fired at %lld microseconds\n\n", ret); wiringPiISRStop (IRQpin) ; } From 0bf457519da3178524945219247e62422e224ae3 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Wed, 29 Jan 2025 19:09:32 +0100 Subject: [PATCH 14/42] Version 3.13 : debounce time added for wiringPiISR and waitForInterrupt library functions. Documentation update --- VERSION | 2 +- documentation/deutsch/functions.md | 4 +- gpio/gpio.c | 4 +- version.h | 4 +- wiringPi/wiringPi.c | 97 +++++++++++++++++++++--------- wiringPi/wiringPi.h | 5 +- 6 files changed, 77 insertions(+), 39 deletions(-) diff --git a/VERSION b/VERSION index e4fba21..24ee5b1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.12 +3.13 diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index a6ece16..2093650 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -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.0-1.deb . +mv debian-template/wiringpi-3.13.deb . ``` **Debian-Paket installieren:** ```bash -sudo apt install ./wiringpi-3.0-1.deb +sudo apt install ./wiringpi-3.13.deb ``` **Debian-Paket deinstallieren:** diff --git a/gpio/gpio.c b/gpio/gpio.c index 3fc97a3..f79188b 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -177,7 +177,7 @@ void printgpio(const char* text) { } } -static void wfi (void) { +static void wfi (unsigned int pin, long long int timestamp) { globalCounter++; if(globalCounter>=iterations) { printgpio("finished\n"); @@ -217,7 +217,7 @@ void doWfi (int argc, char *argv []) timeoutSec = atoi(argv [5]); } - if (wiringPiISR (pin, mode, &wfi) < 0) + if (wiringPiISR (pin, mode, &wfi, 0) < 0) { fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ; exit (1) ; diff --git a/version.h b/version.h index 225bee7..35a3048 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.12" +#define VERSION "3.13" #define VERSION_MAJOR 3 -#define VERSION_MINOR 12 +#define VERSION_MINOR 13 diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 50d20fe..e3d6a25 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -473,9 +473,10 @@ static int isrFds [64] = // ISR Data static int chipFd = -1; -static void (*isrFunctions [64])(void) ; +static void (*isrFunctions [64])(unsigned int, long long int) ; static pthread_t isrThreads[64]; static int isrMode[64]; +static unsigned long long lastcall[64]; // Doing it the Arduino way with lookup tables... // Yes, it's probably more innefficient than all the bit-twidling, but it @@ -2566,16 +2567,26 @@ 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, when interrupt happened ********************************************************************************* */ -int waitForInterrupt (int pin, int mS) +long long int waitForInterrupt (int pin, int mS, int bouncetime) // bounctime in milliseconds { - int fd, ret; + long long int ret; + int fd; struct pollfd polls ; struct gpioevent_data evdata; //struct gpio_v2_line_request req2; + struct timeval tv_timenow; + unsigned long long timenow; + int finished = 0; + int initial_edge = 1; + if (wiringPiDebug) { + printf ("waitForInterrupt: mS = %d, bouncetime = %d\n", mS, bouncetime) ; + } + if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio [pin] ; else if (wiringPiMode == WPI_MODE_PHYS) @@ -2590,23 +2601,46 @@ int waitForInterrupt (int pin, int mS) polls.revents = 0; // Wait for it ... - ret = poll(&polls, 1, mS); - if (ret <= 0) { - fprintf(stderr, "wiringPi: ERROR: poll returned=%d\n", ret); - } else { - //if (polls.revents & POLLIN) - if (wiringPiDebug) { - printf ("wiringPi: IRQ line %d received %d, fd=%d\n", pin, ret, isrFds[pin]) ; - } - /* read event data */ - int readret = read(isrFds [pin], &evdata, sizeof(evdata)); - if (readret == sizeof(evdata)) { - if (wiringPiDebug) { - printf ("wiringPi: IRQ data id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp) ; + while (!finished) { + ret = (long long int)poll(&polls, 1, mS); + if (ret < 0) { + if (wiringPiDebug) { + fprintf(stderr, "wiringPi: ERROR: poll returned=%lld\n", ret); + } + break; + } else if (ret == 0) { + if (wiringPiDebug) { + fprintf(stderr, "wiringPi: timeout: poll returned=%lld\n", ret); + } + break; + } + else { + //if (polls.revents & POLLIN) + if (wiringPiDebug) { + printf ("wiringPi: IRQ line %d received %lld, fd=%d\n", pin, ret, isrFds[pin]) ; + } + if (initial_edge) { // first time triggers with current state, so ignore + initial_edge = 0; + } else { + /* read event data */ + int readret = read(isrFds [pin], &evdata, sizeof(evdata)); + if (readret == sizeof(evdata)) { + if (wiringPiDebug) { + printf ("wiringPi: IRQ data id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp) ; + } +// ret = evdata.id; + gettimeofday(&tv_timenow, NULL); + timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec; + if (bouncetime == 0 || timenow - lastcall[pin] > (unsigned int)bouncetime*1000 || lastcall[pin] == 0 || lastcall[pin] > timenow) { + lastcall[pin] = timenow; + finished = 1; + ret = evdata.timestamp / 1000LL; // nanoseconds u64 to microseconds + } + } else { + ret = -1; + break; + } } - ret = evdata.id; - } else { - ret = 0; } } return ret; @@ -2683,7 +2717,7 @@ int waitForInterruptClose (int pin) { if (wiringPiDebug) { printf ("wiringPi: waitForInterruptClose close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; } - if (pthread_cancel(isrThreads[pin]) == 0) { + if (isrThreads[pin] && pthread_cancel(isrThreads[pin]) == 0) { if (wiringPiDebug) { printf ("wiringPi: waitForInterruptClose thread canceled successfuly\n") ; } @@ -2696,7 +2730,7 @@ int waitForInterruptClose (int pin) { } isrFds [pin] = -1; isrFunctions [pin] = NULL; - + lastcall[pin] = 0; /* -not closing so far - other isr may be using it - only close if no other is using - will code later if (chipFd>0) { close(chipFd); @@ -2722,23 +2756,25 @@ int wiringPiISRStop (int pin) { ********************************************************************************* */ -static void *interruptHandler (UNU void *arg) +static void *interruptHandler (void *arg) { int pin ; - + int bouncetime; + (void)piHiPri (55) ; // Only effective if we run as root pin = pinPass ; + bouncetime = *(int *)arg; pinPass = -1 ; - + for (;;) { - int ret = waitForInterrupt(pin, -1); - if ( ret> 0) { + long long int ret = waitForInterrupt(pin, -1, bouncetime); + if ( ret> 0) { // return timestamp in microseconds if (wiringPiDebug) { printf ("wiringPi: call function\n") ; } if(isrFunctions [pin]) { - isrFunctions [pin] () ; + isrFunctions [pin] ((unsigned int)pin, ret) ; } // wait again - in the past forever - now can be stopped by waitForInterruptClose } else if( ret< 0) { @@ -2762,7 +2798,7 @@ static void *interruptHandler (UNU void *arg) ********************************************************************************* */ -int wiringPiISR (int pin, int mode, void (*function)(void)) +int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime) { const int maxpin = GetMaxPin(); @@ -2779,11 +2815,12 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) isrFunctions [pin] = function ; isrMode[pin] = mode; + lastcall[pin] = 0; if(waitForInterruptInit (pin, mode)<0) { if (wiringPiDebug) { fprintf (stderr, "wiringPi: waitForInterruptInit failed\n") ; } - }; + } if (wiringPiDebug) { printf ("wiringPi: mutex in\n") ; @@ -2793,7 +2830,7 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) if (wiringPiDebug) { printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]); } - if (pthread_create (&isrThreads[pin], NULL, interruptHandler, NULL)==0) { + if (pthread_create (&isrThreads[pin], NULL, interruptHandler, &bouncetime)==0) { if (wiringPiDebug) { printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]); } diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 79a895a..7659d84 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -289,10 +289,11 @@ extern void digitalWriteByte2 (int value) ; // Interrupts // (Also Pi hardware specific) -extern int waitForInterrupt (int pin, int mS) ; -extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; +extern long long int waitForInterrupt (int pin, int mS, int bouncetime) ; +extern int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime) ; extern int wiringPiISRStop (int pin) ; //V3.2 extern int waitForInterruptClose(int pin) ; //V3.2 +extern int waitForInterruptInit (int pin, int mode); //v3.2 // Threads From 92be5caccd8761b25d23ec1798b4acd04c8e0f39 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Tue, 11 Feb 2025 16:02:33 +0100 Subject: [PATCH 15/42] Version 3.14: WiringPi functions upgrade to GPIO_V2 IOCTL --- VERSION | 2 +- documentation/deutsch/functions.md | 60 +-- version.h | 4 +- wiringPi/wiringPi.c | 641 +++++++++++++++++++---------- wiringPi/wiringPi.h | 6 +- 5 files changed, 457 insertions(+), 256 deletions(-) diff --git a/VERSION b/VERSION index 24ee5b1..3767b4b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.13 +3.14 \ No newline at end of file diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 2093650..fbfc431 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -291,11 +291,11 @@ Registriert eine Interrupt Service Routine (ISR) bzw. Funktion die bei Flankenwe >>> ```C -int wiringPiISR(int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime); +int wiringPiISR(int pin, int edgeMode, void (*function)(unsigned int, long long int), unsigned long bouncetime); ``` ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). -``mode``: Auslösende Flankenmodus +``edgeMode``: Auslösende Flankenmodus - INT_EDGE_RISING ... Steigende Flanke - INT_EDGE_FALLING ... Fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke @@ -304,13 +304,13 @@ int wiringPiISR(int pin, int mode, void (*function)(unsigned int, long long int) > unsigned int: pin > long long int: Zeitstempel -``bouncetime``: Entprellzeit in ms, 0 ms schaltet das Entprellen ab +``bouncetime``: Entprellzeit in Microsekunden, 0 ms schaltet das Entprellen ab ``Rückgabewert``: > 0 ... Erfolgreich -Beispiel siehe waitForInterruptInit. +Beispiel siehe waitForInterrupt. ### wiringPiISRStop @@ -330,42 +330,29 @@ int wiringPiISRStop (int pin) ### waitForInterrupt -Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout und Entprellzeit in Millisekunden. - +Wartet auf einen Aufruf der Interrupt Service Routine (ISR) mit Timeout und Entprellzeit in Mikrosekunden. +Blockiert das Programm bis zum Eintreffen der auslösenden Flanke oder bis zum Ablauf des Timeouts. >>> ```C -long long int waitForInterrupt (int pin, int mS, int bouncetime) +long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long bouncetime) ``` ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). +``edgeMode``: Auslösende Flankenmodus + - INT_EDGE_RISING ... Steigende Flanke + - INT_EDGE_FALLING ... Fallende Flanke + - INT_EDGE_BOTH ... Steigende und fallende Flanke ``mS``: Timeout in Milisekunden. - \-1 warten ohne timeout - 0 wartet nicht - 1...n wartet maximal n mS Millisekunden -``bouncetime``: Entprellzeit in Millisekunden, 0 schaltet Entprellen ab +``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 (waitForInterruptInit muss aufgerufen werden) - - -### waitForInterruptInit - -Initialisiert die Funktion waitForInterrupt, definiert, welche Flanke den Interrupt erzeugen soll - ->>> -```C -int waitForInterruptInit (int pin, int mode) -``` - -``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer) -``mode``: INT_EDGE_RISING, INT_EDGE_FALLING, INT_EDGE_BOTH - -``Rückgabewert``: -> \-1 ... Fehler -> 0 ... erfolgreich +> \-2 ... ISR wurde nicht registriert **Beispiel:** @@ -373,7 +360,7 @@ int waitForInterruptInit (int pin, int mode) ```C /* * isr_debounce.c: - * Wait for Interrupt test program WiringPi >=3.13 - ISR method + * Wait for Interrupt test program WiringPi >=3.14 - ISR method * * */ @@ -382,11 +369,13 @@ int waitForInterruptInit (int pin, int mode) #include #include #include +#include #include #include -#define BOUNCETIME 300 +#define BOUNCETIME 3000 // microseconds +#define BOUNCETIME_WFI 300 #define TIMEOUT 10000 //************************************* // BCM pins @@ -447,18 +436,9 @@ int main (void) pinMode(OUTpin, OUTPUT); digitalWrite (OUTpin, LOW) ; - - // test waitForInterrupt - ret = waitForInterruptInit (IRQpin, INT_EDGE_FALLING); - if (ret < 0) { - printf("waitForInterruptInit returned error %d\n", ret); - pinMode(OUTpin, INPUT); - return 0; - } - printf("Testing waitForInterrupt IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); - ret = waitForInterrupt(IRQpin, TIMEOUT, 0); + ret = waitForInterrupt(IRQpin, INT_EDGE_FALLING, TIMEOUT, BOUNCETIME_WFI ); if (ret < 0) { printf("waitForInterrupt returned error %lld\n", ret); wiringPiISRStop (IRQpin) ; @@ -470,11 +450,11 @@ int main (void) wiringPiISRStop (IRQpin) ; } else { - printf("waitForInterrupt: falling edge fired at %lld microseconds\n\n", ret); + printf("waitForInterrupt: falling edge fired at %lld microseconds\n\n", ret); wiringPiISRStop (IRQpin) ; } - printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling edge and bouncetime %d ms. Toggle LED @ OUTpin on IRQ.\n\n", IRQpin, IRQpin, BOUNCETIME, OUTpin); + 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("To stop program hit return key\n\n"); wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi, BOUNCETIME) ; diff --git a/version.h b/version.h index 35a3048..c2da282 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.13" +#define VERSION "3.14" #define VERSION_MAJOR 3 -#define VERSION_MINOR 13 +#define VERSION_MINOR 14 diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index e3d6a25..1dafed5 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -471,12 +472,14 @@ static int isrFds [64] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } ; + + // ISR Data static int chipFd = -1; static void (*isrFunctions [64])(unsigned int, long long int) ; static pthread_t isrThreads[64]; -static int isrMode[64]; -static unsigned long long lastcall[64]; +static int isrMode[64]; // irq on rising/falling edge +static unsigned long isrDebouncePeriodUs [64]; // 0: debounce is off // Doing it the Arduino way with lookup tables... // Yes, it's probably more innefficient than all the bit-twidling, but it @@ -1734,11 +1737,14 @@ void releaseLine(int pin) { lineFlags[pin] = 0; close(lineFds[pin]); lineFds[pin] = -1; + isrDebouncePeriodUs[pin] = 0; } int requestLine(int pin, unsigned int lineRequestFlags) { - struct gpiohandle_request rq; - + struct gpio_v2_line_request req; + struct gpio_v2_line_config config; + int ret; + if (lineFds[pin]>=0) { if (lineRequestFlags == lineFlags[pin]) { //already requested @@ -1753,17 +1759,25 @@ int requestLine(int pin, unsigned int lineRequestFlags) { if (wiringPiGpioDeviceGetFd()<0) { return -1; // error } - rq.lineoffsets[0] = pin; - rq.lines = 1; - rq.flags = lineRequestFlags; - int ret = ioctl(chipFd, GPIO_GET_LINEHANDLE_IOCTL, &rq); - if (ret || rq.fd<0) { + + memset(&req, 0, sizeof(req)); + memset(&config, 0, sizeof(config)); + config.flags = lineRequestFlags; + strcpy(req.consumer, "wiringpi_gpio_req"); + + req.offsets[0] = pin; + req.num_lines = 1; + req.config = config; + + ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); + + if (ret || req.fd<0) { ReportDeviceError("get line handle", pin, "RequestLine", ret); return -1; // error } lineFlags[pin] = lineRequestFlags; - lineFds[pin] = rq.fd; + lineFds[pin] = req.fd; if (wiringPiDebug) printf ("requestLine succeeded: pin:%d, flags: %u, fd :%d\n", pin, lineRequestFlags, lineFds[pin]) ; return lineFds[pin]; @@ -1863,16 +1877,16 @@ void pinModeFlagsDevice (int pin, int mode, unsigned int flags) { if (wiringPiDebug) printf ("pinModeFlagsDevice: pin:%d mode:%d, flags: %u\n", pin, mode, flags) ; - lflag &= ~(GPIOHANDLE_REQUEST_INPUT | GPIOHANDLE_REQUEST_OUTPUT); + lflag &= ~(GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_OUTPUT); switch(mode) { default: fprintf(stderr, "pinMode: invalid mode request (only input und output supported)\n"); return; case INPUT: - lflag |= GPIOHANDLE_REQUEST_INPUT; + lflag |= GPIO_V2_LINE_FLAG_INPUT; break; case OUTPUT: - lflag |= GPIOHANDLE_REQUEST_OUTPUT; + lflag |= GPIO_V2_LINE_FLAG_OUTPUT; break; case PM_OFF: pinModeFlagsDevice(pin, INPUT, 0); @@ -2038,20 +2052,20 @@ void pinMode (int pin, int mode) */ void pullUpDnControlDevice (int pin, int pud) { unsigned int flag = lineFlags[pin]; - unsigned int biasflags = GPIOHANDLE_REQUEST_BIAS_DISABLE | GPIOHANDLE_REQUEST_BIAS_PULL_UP | GPIOHANDLE_REQUEST_BIAS_PULL_DOWN; + unsigned int biasflags = GPIO_V2_LINE_FLAG_BIAS_DISABLED | GPIO_V2_LINE_FLAG_BIAS_PULL_UP | GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; flag &= ~biasflags; switch (pud){ - case PUD_OFF: flag |= GPIOHANDLE_REQUEST_BIAS_DISABLE; break; - case PUD_UP: flag |= GPIOHANDLE_REQUEST_BIAS_PULL_UP; break; - case PUD_DOWN: flag |= GPIOHANDLE_REQUEST_BIAS_PULL_DOWN; break; + case PUD_OFF: flag |= GPIO_V2_LINE_FLAG_BIAS_DISABLED; break; + case PUD_UP: flag |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP; break; + case PUD_DOWN: flag |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; break; default: return ; /* An illegal value */ } // reset input/output - if (lineFlags[pin] & GPIOHANDLE_REQUEST_OUTPUT) { + if (lineFlags[pin] & GPIO_V2_LINE_FLAG_OUTPUT) { pinModeFlagsDevice (pin, OUTPUT, flag); - } else if(lineFlags[pin] & GPIOHANDLE_REQUEST_INPUT) { + } else if(lineFlags[pin] & GPIO_V2_LINE_FLAG_INPUT) { pinModeFlagsDevice (pin, INPUT, flag); } else { lineFlags[pin] = flag; // only store for later @@ -2135,7 +2149,33 @@ void pullUpDnControl (int pin, int pud) } } +/* + helper functions for gpio_v2_line_values bits +*/ +static inline void gpiotools_set_bit(__u64 *b, int n) +{ + *b |= _BITULL(n); +} +static inline void gpiotools_clear_bit(__u64 *b, int n) +{ + *b &= ~_BITULL(n); +} + +static inline void gpiotools_assign_bit(__u64 *b, int n, bool value) +{ + if (value) + gpiotools_set_bit(b, n); + else + gpiotools_clear_bit(b, n); +} + +static inline int gpiotools_test_bit(__u64 b, int n) +{ + return !!(b & _BITULL(n)); +} + +//********************************************* /* @@ -2145,19 +2185,23 @@ void pullUpDnControl (int pin, int pud) */ int digitalReadDevice (int pin) { // INPUT and OUTPUT should work - - if (lineFds[pin]<0) { + struct gpio_v2_line_values lv; + int ret; + + if (lineFds[pin]<0) { // line not requested - auto request on first read as input - pinModeDevice(pin, INPUT); + pinModeDevice(pin, INPUT); } + lv.mask = 0; + lv.bits = 0; if (lineFds[pin]>=0) { - struct gpiohandle_data data; - int ret = ioctl(lineFds[pin], GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); + gpiotools_set_bit(&lv.mask, 0); + ret = ioctl(lineFds[pin], GPIO_V2_LINE_GET_VALUES_IOCTL, &lv); if (ret) { ReportDeviceError("get line values", pin, "digitalRead", ret); return LOW; // error } - return data.values[0]; + return gpiotools_test_bit(lv.bits, 0); } return LOW; // error , need to request line before } @@ -2239,7 +2283,9 @@ unsigned int digitalRead8 (int pin) */ void digitalWriteDevice (int pin, int value) { - + int ret; + struct gpio_v2_line_values values; + if (wiringPiDebug) printf ("digitalWriteDevice: ioctl pin:%d value: %d\n", pin, value) ; @@ -2247,22 +2293,25 @@ void digitalWriteDevice (int pin, int value) { // line not requested - auto request on first write as output pinModeDevice(pin, OUTPUT); } - if (lineFds[pin]>=0 && (lineFlags[pin] & GPIOHANDLE_REQUEST_OUTPUT)>0) { - struct gpiohandle_data data; - data.values[0] = value; - if (wiringPiDebug) - printf ("digitalWriteDevice: ioctl pin:%d cmd: GPIOHANDLE_SET_LINE_VALUES_IOCTL, value: %d\n", pin, value) ; - int ret = ioctl(lineFds[pin], GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); - if (ret) { - ReportDeviceError("set line values", pin, "digitalWrite", ret); - return; // error - } + + if (lineFds[pin]>=0 && (lineFlags[pin] & GPIO_V2_LINE_FLAG_OUTPUT)>0) { + values.mask = 0; + values.bits = 0; + gpiotools_set_bit(&values.mask, 0); + gpiotools_assign_bit(&values.bits, 0, !!value); + + ret = ioctl(lineFds[pin], GPIO_V2_LINE_SET_VALUES_IOCTL, &values); + if (ret == -1) { + ReportDeviceError("digitalWriteDevice", pin, "GPIO_V2_LINE_SET_VALUES_IOCTL", ret); + return; // error + } } else { fprintf(stderr, "digitalWrite: no output (%d)\n", lineFlags[pin]); } return; // error } + void digitalWrite (int pin, int value) { struct wiringPiNodeStruct *node = wiringPiNodes ; @@ -2560,6 +2609,103 @@ unsigned int digitalReadByte2 (void) } + + +//-------------------------------------------------------------------- +// 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) +{ + const char* strmode = ""; + struct gpio_v2_line_config config; + struct gpio_v2_line_request req; + int attr, ret; + + if (wiringPiMode == WPI_MODE_PINS) { + pin = pinToGpio [pin] ; + } else if (wiringPiMode == WPI_MODE_PHYS) { + pin = physToGpio [pin] ; + } + + /* open gpio */ +// sleep(1); + if (wiringPiGpioDeviceGetFd()<0) { + return -1; + } + + memset(&req, 0, sizeof(req)); + memset(&config, 0, sizeof(config)); + + /* 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") ; + } + return -1; + case INT_EDGE_FALLING: + config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; + strmode = "falling"; + break; + case INT_EDGE_RISING: + config.flags |= GPIO_V2_LINE_FLAG_EDGE_RISING; + strmode = "rising"; + break; + case INT_EDGE_BOTH: + config.flags |= (GPIO_V2_LINE_FLAG_EDGE_FALLING | GPIO_V2_LINE_FLAG_EDGE_RISING); + strmode = "both"; + break; + } + 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; + } + + req.num_lines = 1; + req.offsets[0] = pin; + 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; + } + + if (wiringPiDebug) { + printf ("wiringPi: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; + } + + int fd_line = req.fd; + isrFds [pin] = fd_line; + isrDebouncePeriodUs[pin] = debounce_period_us; + +/* set event fd nonbloack read */ + /* + int flags = fcntl(fd_line, 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); + return -1; + } +*/ + return 0; +} + + /* * waitForInterrupt: * Pi Specific. @@ -2567,25 +2713,124 @@ 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, when interrupt happened + * Returns timestamp in microseconds on interrupt ********************************************************************************* */ -long long int waitForInterrupt (int pin, int mS, int bouncetime) // bounctime in milliseconds +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 gpioevent_data evdata; - //struct gpio_v2_line_request req2; - struct timeval tv_timenow; - unsigned long long timenow; - int finished = 0; - int initial_edge = 1; + struct gpio_v2_line_event evdata; + + if (wiringPiMode == WPI_MODE_PINS) + pin = pinToGpio [pin] ; + else if (wiringPiMode == WPI_MODE_PHYS) + pin = physToGpio [pin] ; - if (wiringPiDebug) { - printf ("waitForInterrupt: mS = %d, bouncetime = %d\n", mS, bouncetime) ; + if (waitForInterruptInit (pin, edgeMode, debounce_period_us ) != 0) + return -1 ; + + fd = isrFds[pin]; + // Setup poll structure + polls.fd = fd; + polls.events = POLLIN | POLLERR ; + polls.revents = 0; + + ret = (long long int)poll(&polls, 1, mS); + + 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 waitForInterruptClose (int pin) { + if (isrFds[pin]>0) { + if (wiringPiDebug) { + printf ("wiringPi: waitForInterruptClose 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") ; + } + } else { + if (wiringPiDebug) { + fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n"); + } + } + } + close(isrFds [pin]); + } + isrFds [pin] = -1; + isrFunctions [pin] = NULL; + isrDebouncePeriodUs[pin] = 0; + + /* -not closing so far - other isr may be using it - only close if no other is using - will code later + if (chipFd>0) { + close(chipFd); + } + chipFd = -1; + */ + if (wiringPiDebug) { + printf ("wiringPi: 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] ; @@ -2600,150 +2845,49 @@ long long int waitForInterrupt (int pin, int mS, int bouncetime) // bounctime i polls.events = POLLIN | POLLERR ; polls.revents = 0; - // Wait for it ... - while (!finished) { - ret = (long long int)poll(&polls, 1, mS); - if (ret < 0) { - if (wiringPiDebug) { - fprintf(stderr, "wiringPi: ERROR: poll returned=%lld\n", ret); + 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 } - break; - } else if (ret == 0) { - if (wiringPiDebug) { - fprintf(stderr, "wiringPi: timeout: poll returned=%lld\n", ret); - } - break; - } - else { - //if (polls.revents & POLLIN) - if (wiringPiDebug) { - printf ("wiringPi: IRQ line %d received %lld, fd=%d\n", pin, ret, isrFds[pin]) ; - } - if (initial_edge) { // first time triggers with current state, so ignore - initial_edge = 0; - } else { - /* read event data */ - int readret = read(isrFds [pin], &evdata, sizeof(evdata)); - if (readret == sizeof(evdata)) { - if (wiringPiDebug) { - printf ("wiringPi: IRQ data id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp) ; - } -// ret = evdata.id; - gettimeofday(&tv_timenow, NULL); - timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec; - if (bouncetime == 0 || timenow - lastcall[pin] > (unsigned int)bouncetime*1000 || lastcall[pin] == 0 || lastcall[pin] > timenow) { - lastcall[pin] = timenow; - finished = 1; - ret = evdata.timestamp / 1000LL; // nanoseconds u64 to microseconds - } - } else { - ret = -1; - break; - } + else { + ret = -1; } } } return ret; } -int waitForInterruptInit (int pin, int mode) -{ - const char* strmode = ""; - - if (wiringPiMode == WPI_MODE_PINS) { - pin = pinToGpio [pin] ; - } else if (wiringPiMode == WPI_MODE_PHYS) { - pin = physToGpio [pin] ; - } - - /* open gpio */ - sleep(1); - if (wiringPiGpioDeviceGetFd()<0) { - return -1; - } - - struct gpioevent_request req; - req.lineoffset = pin; - req.handleflags = GPIOHANDLE_REQUEST_INPUT; - switch(mode) { - default: - case INT_EDGE_SETUP: - if (wiringPiDebug) { - printf ("wiringPi: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ; - } - return -1; - case INT_EDGE_FALLING: - req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE; - strmode = "falling"; - break; - case INT_EDGE_RISING: - req.eventflags = GPIOEVENT_REQUEST_RISING_EDGE; - strmode = "rising"; - break; - case INT_EDGE_BOTH: - req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; - strmode = "both"; - break; - } - strncpy(req.consumer_label, "wiringpi_gpio_irq", sizeof(req.consumer_label) - 1); - - //later implement GPIO_V2_GET_LINE_IOCTL req2 - int ret = ioctl(chipFd, GPIO_GET_LINEEVENT_IOCTL, &req); - if (ret) { - ReportDeviceError("get line event", pin , strmode, ret); - return -1; - } - if (wiringPiDebug) { - printf ("wiringPi: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; - } - - /* set event fd nonbloack read */ - int fd_line = req.fd; - isrFds [pin] = fd_line; - int flags = fcntl(fd_line, 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); - return -1; - } - - return 0; -} - - -int waitForInterruptClose (int pin) { - if (isrFds[pin]>0) { - if (wiringPiDebug) { - printf ("wiringPi: waitForInterruptClose close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; - } - if (isrThreads[pin] && pthread_cancel(isrThreads[pin]) == 0) { - if (wiringPiDebug) { - printf ("wiringPi: waitForInterruptClose thread canceled successfuly\n") ; - } - } else { - if (wiringPiDebug) { - fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n"); - } - } - close(isrFds [pin]); - } - isrFds [pin] = -1; - isrFunctions [pin] = NULL; - lastcall[pin] = 0; - /* -not closing so far - other isr may be using it - only close if no other is using - will code later - if (chipFd>0) { - close(chipFd); - } - chipFd = -1; - */ - if (wiringPiDebug) { - printf ("wiringPi: waitForInterruptClose finished\n") ; - } - return 0; -} - - int wiringPiISRStop (int pin) { return waitForInterruptClose (pin); } @@ -2756,20 +2900,89 @@ int wiringPiISRStop (int pin) { ********************************************************************************* */ -static void *interruptHandler (void *arg) +void *interruptHandler (void *arg) { - int pin ; - int bouncetime; + const char* strmode = ""; + int pin, mode ; + unsigned long debounce_period_us; + struct gpio_v2_line_config config; + struct gpio_v2_line_request req; + int attr, ret; + + pin = *(int *)arg; + +/* pin = pinPass ; + pinPass = -1 ; +*/ + if (wiringPiGpioDeviceGetFd()<0) { + return NULL; + } + + mode = isrMode[pin]; + debounce_period_us = isrDebouncePeriodUs[pin]; + + if (wiringPiDebug) { + printf ("interruptHandler: GPIO line %d, mode %d, debounce_period_us %lu \n", pin, mode, debounce_period_us) ; + } + + memset(&req, 0, sizeof(req)); + memset(&config, 0, sizeof(config)); + + /* setup config */ + config.flags = GPIO_V2_LINE_FLAG_INPUT; + switch(mode) { + default: + case INT_EDGE_SETUP: + if (wiringPiDebug) { + printf ("wiringPi: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ; + } + return NULL; + case INT_EDGE_FALLING: + config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; + strmode = "falling"; + break; + case INT_EDGE_RISING: + config.flags |= GPIO_V2_LINE_FLAG_EDGE_RISING; + strmode = "rising"; + break; + case INT_EDGE_BOTH: + config.flags |= (GPIO_V2_LINE_FLAG_EDGE_FALLING | GPIO_V2_LINE_FLAG_EDGE_RISING); + strmode = "both"; + break; + } + 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; + } + + req.num_lines = 1; + 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); + return NULL; + } +/* + if (wiringPiDebug) { + printf ("wiringPi: 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; (void)piHiPri (55) ; // Only effective if we run as root - pin = pinPass ; - bouncetime = *(int *)arg; - pinPass = -1 ; - for (;;) { - long long int ret = waitForInterrupt(pin, -1, bouncetime); - if ( ret> 0) { // return timestamp in microseconds + 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") ; } @@ -2795,10 +3008,11 @@ static void *interruptHandler (void *arg) * Pi Specific. * Take the details and create an interrupt handler that will do a call- * back to the user supplied function. + * debounce_period_us in microseconds ********************************************************************************* */ -int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime) +int wiringPiISR (int pin, int edgeMode, void (*function)(unsigned int, long long int), unsigned long debounce_period_us) { const int maxpin = GetMaxPin(); @@ -2806,22 +3020,24 @@ int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-%d (%d)\n", maxpin, pin) ; if (wiringPiMode == WPI_MODE_UNINITIALISED) return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; + + if (wiringPiMode == WPI_MODE_PINS) { + pin = pinToGpio [pin] ; + } else if (wiringPiMode == WPI_MODE_PHYS) { + pin = physToGpio [pin] ; + } + if (wiringPiDebug) { - printf ("wiringPi: wiringPiISR pin %d, mode %d\n", pin, mode) ; + printf ("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode) ; } if (isrFunctions [pin]) { - printf ("wiringPi: ISR function alread active, ignoring \n") ; + printf ("wiringPi: ISR function already active, ignoring \n") ; } isrFunctions [pin] = function ; - isrMode[pin] = mode; - lastcall[pin] = 0; - if(waitForInterruptInit (pin, mode)<0) { - if (wiringPiDebug) { - fprintf (stderr, "wiringPi: waitForInterruptInit failed\n") ; - } - } - + isrMode[pin] = edgeMode; + isrDebouncePeriodUs[pin] = debounce_period_us; + if (wiringPiDebug) { printf ("wiringPi: mutex in\n") ; } @@ -2830,12 +3046,17 @@ int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int if (wiringPiDebug) { printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]); } - if (pthread_create (&isrThreads[pin], NULL, interruptHandler, &bouncetime)==0) { + if (pthread_create (&isrThreads[pin], NULL, interruptHandler, &pin)==0) { if (wiringPiDebug) { printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]); } - while (pinPass != -1) - delay (1) ; +/* while (pinPass != -1) + delay (1) ; */ + // wait so that interruptHandler is up und running. + // when interruptHandler is running, the calling function wiringPiISR + // must be still alive, otherwise the thread argument &pin points into nirwana, + // when it is picked up from interruptHandler. + delay (10); } else { if (wiringPiDebug) { printf("wiringPi: pthread_create failed\n"); @@ -3187,12 +3408,12 @@ int wiringPiSetup (void) /**/ if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1) // A, B, Rev 1, 1.1 { - pinToGpio = pinToGpioR1 ; + pinToGpio = pinToGpioR1 ; physToGpio = physToGpioR1 ; } else // A2, B2, A+, B+, CM, Pi2, Pi3, Zero, Zero W, Zero 2 W { - pinToGpio = pinToGpioR2 ; + pinToGpio = pinToGpioR2 ; physToGpio = physToGpioR2 ; } @@ -3201,7 +3422,7 @@ int wiringPiSetup (void) // Try /dev/mem. If that fails, then // try /dev/gpiomem. If that fails then game over. - const char* gpiomemGlobal = gpiomem_global; + const char* gpiomemGlobal = gpiomem_global; const char* gpiomemModule = gpiomem_BCM; if (PI_MODEL_5 == model) { @@ -3242,7 +3463,7 @@ int wiringPiSetup (void) printf ("wiringPi: access to %s succeded %d\n", usingGpioMem ? gpiomemModule : gpiomemGlobal, fd) ; } // GPIO: - if (PI_MODEL_5 != model) { + if (PI_MODEL_5 != model) { //Set the offsets into the memory interface. GPIO_PADS = piGpioBase + 0x00100000 ; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 7659d84..e7cbfb6 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -289,11 +289,11 @@ extern void digitalWriteByte2 (int value) ; // Interrupts // (Also Pi hardware specific) -extern long long int waitForInterrupt (int pin, int mS, int bouncetime) ; -extern int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), int bouncetime) ; +extern long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long debounce_period_us) ; +extern int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), unsigned long debounce_period_us) ; extern int wiringPiISRStop (int pin) ; //V3.2 extern int waitForInterruptClose(int pin) ; //V3.2 -extern int waitForInterruptInit (int pin, int mode); //v3.2 +// extern int waitForInterruptInit (int pin, int mode); //v3.2 // Threads From 9e105d1bb4a8169d0c61b045844674fd1ccb551a Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Tue, 11 Feb 2025 16:11:41 +0100 Subject: [PATCH 16/42] functions.md --- documentation/deutsch/functions.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index fbfc431..0267556 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -295,6 +295,7 @@ int wiringPiISR(int pin, int edgeMode, void (*function)(unsigned int, long long ``` ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). + ``edgeMode``: Auslösende Flankenmodus - INT_EDGE_RISING ... Steigende Flanke - INT_EDGE_FALLING ... Fallende Flanke @@ -338,14 +339,17 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long bo ``` ``pin``: Der gewünschte Pin (BCM\-, WiringPi\- oder Pin\-Nummer). + ``edgeMode``: Auslösende Flankenmodus - INT_EDGE_RISING ... Steigende Flanke - INT_EDGE_FALLING ... Fallende Flanke - INT_EDGE_BOTH ... Steigende und fallende Flanke + ``mS``: Timeout in Milisekunden. - \-1 warten ohne timeout - 0 wartet nicht - 1...n wartet maximal n mS Millisekunden + ``bouncetime``: Entprellzeit in Microsekunden, 0 schaltet Entprellen ab. ``Rückgabewert``: From a261ceb485acc55504d7af2a684aba77703d625f Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Tue, 11 Feb 2025 20:01:41 +0100 Subject: [PATCH 17/42] Pi500/CM5 support --- wiringPi/wiringPi.c | 75 ++++++++++++++++++++++++++++----------------- wiringPi/wiringPi.h | 67 ++++++++++++++++++++++------------------ 2 files changed, 85 insertions(+), 57 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 1dafed5..28bec24 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -141,6 +141,8 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; #define RP1_FSEL_NONE 0x09 #define RP1_FSEL_NONE_HW 0x1f //default, mask +// 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); @@ -337,7 +339,7 @@ volatile unsigned int *_wiringPiRio ; static volatile unsigned int piGpioBase = 0 ; -const char *piModelNames [24] = +const char *piModelNames [PI_MODELS_MAX] = { "Model A", // 0 "Model B", // 1 @@ -363,6 +365,9 @@ const char *piModelNames [24] = "CM4S", // 21 "Unknown22", // 22 "Pi 5", // 23 + "CM5", // 24 + "Pi 500", // 25 + "CM5 Lite", // 26 } ; const char *piProcessor [5] = @@ -396,10 +401,10 @@ const char *piRevisionNames [16] = const char *piMakerNames [16] = { - "Sony", // 0 + "Sony UK",// 0 "Egoman", // 1 "Embest", // 2 - "Unknown",// 3 + "Sony Japan",// 3 "Embest", // 4 "Stadium",// 5 "Unknown06", // 6 @@ -422,7 +427,7 @@ const int piMemorySize [8] = 2048, // 3 4096, // 4 8192, // 5 - 0, // 6 + 16384, // 6 0, // 7 } ; @@ -629,16 +634,27 @@ int piBoard40Pin() { } } +int piRP1Model() { + switch(RaspberryPiModel){ + case PI_MODEL_5: + case PI_MODEL_CM5: + case PI_MODEL_500: + case PI_MODEL_CM5L: + return 1; + default: + return 0; + } +} int GetMaxPin() { - return PI_MODEL_5 == RaspberryPiModel ? 27 : 63; + return piRP1Model() ? 27 : 63; } -#define RETURN_ON_MODEL5 if (PI_MODEL_5 == RaspberryPiModel) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; } +#define RETURN_ON_MODEL5 if (piRP1Model()) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; } int FailOnModel5(const char *function) { - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { return wiringPiFailure (WPI_ALMOST, "Function '%s' not supported on Raspberry Pi 5.\n" " Unable to continue. Keep an eye of new versions at https://github.com/wiringpi/wiringpi\n", function) ; } @@ -1210,6 +1226,9 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) break ; case PI_MODEL_5: + case PI_MODEL_CM5: + case PI_MODEL_500: + case PI_MODEL_CM5L: piGpioBase = GPIO_PERI_BASE_2712 ; piGpioPupOffset = 0 ; break ; @@ -1255,7 +1274,7 @@ int physPinToGpio (int physPin) ********************************************************************************* */ void setPadDrivePin (int pin, int value) { - if (PI_MODEL_5 != RaspberryPiModel) return; + if (!piRP1Model()) return; if (pin < 0 || pin > GetMaxPin()) return ; uint32_t wrVal; @@ -1275,7 +1294,7 @@ void setPadDrive (int group, int value) if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { value = value & 7; // 0-7 supported - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { if (-1==group) { printf ("Pad register:\n"); for (int pin=0, maxpin=GetMaxPin(); pin<=maxpin; ++pin) { @@ -1346,7 +1365,7 @@ int getAlt (int pin) else if (wiringPiMode != WPI_MODE_GPIO) return 0 ; - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { alt = (gpio[2*pin+1] & RP1_FSEL_NONE_HW); //0-4 function /* @@ -1406,7 +1425,7 @@ void pwmSetMode (int mode) { if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { if(mode != PWM_MODE_MS) { fprintf(stderr, "pwmSetMode: Raspberry Pi 5 missing feature PWM BAL mode\n"); } @@ -1445,7 +1464,7 @@ void pwmSetRange (unsigned int range) return; } int readback = 0x00; - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { pwm[RP1_PWM0_CHAN0_RANGE] = range; pwm[RP1_PWM0_CHAN1_RANGE] = range; pwm[RP1_PWM0_CHAN2_RANGE] = range; @@ -1482,7 +1501,7 @@ void pwmSetClock (int divisor) if (divisor > PWMCLK_DIVI_MAX) { divisor = PWMCLK_DIVI_MAX; // even on Pi5 4095 is OK } - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { if (divisor < 1) { if (wiringPiDebug) { printf("Disable PWM0 clock"); } clk[CLK_PWM0_CTRL] = RP1_CLK_PWM0_CTRL_DISABLE_MAGIC; // 0 = disable on Pi5 @@ -1717,7 +1736,7 @@ int OpenAndCheckGpioChip(int GPIONo, const char* label, const unsigned int lines int wiringPiGpioDeviceGetFd() { if (chipFd<0) { piBoard(); - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { chipFd = OpenAndCheckGpioChip(0, "rp1", 54); // /dev/gpiochip0 @ Pi5 since Kernel 6.6.47 if (chipFd<0) { chipFd = OpenAndCheckGpioChip(4, "rp1", 54); // /dev/gpiochip4 @ Pi5 with older kernel @@ -1808,7 +1827,7 @@ void pinModeAlt (int pin, int mode) else if (wiringPiMode != WPI_MODE_GPIO) return ; - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { //confusion! diffrent to to BCM! this is taking directly the value for the register int modeRP1; switch(mode) { @@ -1947,7 +1966,7 @@ void pinMode (int pin, int mode) shift = gpioToShift [pin] ; if (INPUT==mode || PM_OFF==mode) { - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { if (INPUT==mode) { pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; gpio[2*pin+1] = RP1_FSEL_GPIO | RP1_DEBOUNCE_DEFAULT; // GPIO @@ -1962,14 +1981,14 @@ void pinMode (int pin, int mode) if (PM_OFF==mode && !usingGpioMem && pwm && gpioToPwmALT[pin]>0) { //PWM pin -> reset pwmWrite(origPin, 0); int channel = gpioToPwmPort[pin]; - if (channel>=0 && channel<=3 && PI_MODEL_5 == RaspberryPiModel) { + if (channel>=0 && channel<=3 && piRP1Model()) { unsigned int ctrl = pwm[RP1_PWM0_GLOBAL_CTRL]; pwm[RP1_PWM0_GLOBAL_CTRL] = (ctrl & ~(1<0x%08X)\n", channel, ctrl, pwm[RP1_PWM0_GLOBAL_CTRL]); } } } else if (mode == OUTPUT) { - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; gpio[2*pin+1] = RP1_FSEL_GPIO | RP1_DEBOUNCE_DEFAULT; // GPIO rio[RP1_RIO_OE + RP1_SET_OFFSET] = 1<=0 && channel<=3) { // enable channel pwm m:s mode pwm[RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*channel+RP1_PWM0_CHAN_CTRL] = (RP1_PWM_TRAIL_EDGE_MS | RP1_PWM_FIFO_POP_MASK); @@ -2101,7 +2120,7 @@ void pullUpDnControl (int pin, int pud) break; } - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { unsigned int pullbits = pads[1+pin] & RP1_INV_PUD_MASK; // remove bits switch (pud){ case PUD_OFF: pads[1+pin] = pullbits; break; @@ -2233,7 +2252,7 @@ int digitalRead (int pin) break; } - if (PI_MODEL_5 == RaspberryPiModel) { + if (ISRP1MODEL) { switch(gpio[2*pin] & RP1_STATUS_LEVEL_MASK) { default: // 11 or 00 not allowed, give LOW! case RP1_STATUS_LEVEL_LOW: return LOW ; @@ -2341,7 +2360,7 @@ void digitalWrite (int pin, int value) break; } - if (PI_MODEL_5 == RaspberryPiModel) { + if (ISRP1MODEL) { if (value == LOW) { //printf("Set pin %d >>0x%08x<< to low\n", pin, 1<=0 && channel<=3) { unsigned int addr = RP1_PWM0_CHAN_START+RP1_PWM0_CHAN_OFFSET*channel+RP1_PWM0_CHAN_DUTY; pwm[addr] = value; @@ -3249,7 +3268,7 @@ int wiringPiUserLevelAccess(void) const char* gpiomemModule = gpiomem_BCM; piBoard(); - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { gpiomemModule = gpiomem_RP1; } @@ -3316,7 +3335,7 @@ int wiringPiGlobalMemoryAccess(void) unsigned int BaseAddr, PWMAddr; piBoard(); - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { GetRP1Memory(pciemem_RP1, sizeof(pciemem_RP1)); gpiomemGlobal = pciemem_RP1; MMAP_size = pciemem_RP1_Size; @@ -3339,7 +3358,7 @@ int wiringPiGlobalMemoryAccess(void) fprintf(stderr,"wiringPiGlobalMemoryAccess: mmap (GPIO 0x%X,0x%X) failed: %s\n", BaseAddr, MMAP_size, strerror (errno)) ; } else { munmap(lgpio, MMAP_size); - if (PI_MODEL_5 == RaspberryPiModel) { + if (piRP1Model()) { returnvalue = 2; // GPIO & PWM accessible (same area, nothing to mmap) } else { //check PWM area @@ -3425,7 +3444,7 @@ int wiringPiSetup (void) const char* gpiomemGlobal = gpiomem_global; const char* gpiomemModule = gpiomem_BCM; - if (PI_MODEL_5 == model) { + if (piRP1Model()) { GetRP1Memory(); gpiomemGlobal = pciemem_RP1; gpiomemModule = gpiomem_RP1; @@ -3463,7 +3482,7 @@ int wiringPiSetup (void) printf ("wiringPi: access to %s succeded %d\n", usingGpioMem ? gpiomemModule : gpiomemGlobal, fd) ; } // GPIO: - if (PI_MODEL_5 != model) { + if (!piRP1Model()) { //Set the offsets into the memory interface. GPIO_PADS = piGpioBase + 0x00100000 ; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index e7cbfb6..0b980e3 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -1,7 +1,7 @@ /* * wiringPi.h: * Arduino like Wiring library for the Raspberry Pi. - * Copyright (c) 2012-2017 Gordon Henderson + * Copyright (c) 2012-2025 Gordon Henderson *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ @@ -93,35 +93,44 @@ // Pi model types and version numbers // Intended for the GPIO program Use at your own risk. // https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#new-style-revision-codes +// https://github.com/raspberrypi/documentation/blob/develop/documentation/asciidoc/computers/raspberry-pi/revision-codes.adoc -#define PI_MODEL_A 0 -#define PI_MODEL_B 1 -#define PI_MODEL_AP 2 -#define PI_MODEL_BP 3 -#define PI_MODEL_2 4 -#define PI_ALPHA 5 -#define PI_MODEL_CM 6 -#define PI_MODEL_07 7 -#define PI_MODEL_3B 8 -#define PI_MODEL_ZERO 9 -#define PI_MODEL_CM3 10 -#define PI_MODEL_ZERO_W 12 -#define PI_MODEL_3BP 13 -#define PI_MODEL_3AP 14 -#define PI_MODEL_CM3P 16 -#define PI_MODEL_4B 17 -#define PI_MODEL_ZERO_2W 18 -#define PI_MODEL_400 19 -#define PI_MODEL_CM4 20 -#define PI_MODEL_CM4S 21 -#define PI_MODEL_5 23 +#define PI_MODEL_A 0 +#define PI_MODEL_B 1 +#define PI_MODEL_AP 2 +#define PI_MODEL_BP 3 +#define PI_MODEL_2 4 +#define PI_ALPHA 5 +#define PI_MODEL_CM 6 -#define PI_VERSION_1 0 +#define PI_MODEL_3B 8 +#define PI_MODEL_ZERO 9 +#define PI_MODEL_CM3 10 + +#define PI_MODEL_ZERO_W 12 +#define PI_MODEL_3BP 13 +#define PI_MODEL_3AP 14 + +#define PI_MODEL_CM3P 16 +#define PI_MODEL_4B 17 +#define PI_MODEL_ZERO_2W 18 +#define PI_MODEL_400 19 +#define PI_MODEL_CM4 20 +#define PI_MODEL_CM4S 21 + +#define PI_MODEL_5 23 +#define PI_MODEL_CM5 24 +#define PI_MODEL_500 25 +#define PI_MODEL_CM5L 26 + +#define PI_MODELS_MAX 27 + +#define PI_VERSION_1 0 #define PI_VERSION_1_1 1 #define PI_VERSION_1_2 2 -#define PI_VERSION_2 3 +#define PI_VERSION_2 3 -#define PI_MAKER_SONY 0 +#define PI_MAKER_SONY 0 #define PI_MAKER_EGOMAN 1 #define PI_MAKER_EMBEST 2 #define PI_MAKER_UNKNOWN 3 @@ -129,7 +138,7 @@ #define GPIO_LAYOUT_PI1_REV1 1 //Pi 1 A/B Revision 1, 1.1, CM #define GPIO_LAYOUT_DEFAULT 2 -extern const char *piModelNames [24] ; +extern const char *piModelNames [PI_MODELS_MAX] ; extern const char *piProcessor [ 5] ; extern const char *piRevisionNames [16] ; extern const char *piMakerNames [16] ; @@ -271,6 +280,7 @@ extern int piGpioLayout (void) ; extern int piBoardRev (void) ; // Deprecated, but does the same as piGpioLayout extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; extern int piBoard40Pin (void) ; // Interface V3.7 +extern int piRP1Model (void) ; // Interface V3.14 extern int wpiPinToGpio (int wpiPin) ; extern int physPinToGpio (int physPin) ; extern void setPadDrive (int group, int value) ; @@ -289,11 +299,10 @@ 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) ; -extern int wiringPiISR (int pin, int mode, void (*function)(unsigned int, long long int), unsigned long debounce_period_us) ; +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 extern int wiringPiISRStop (int pin) ; //V3.2 extern int waitForInterruptClose(int pin) ; //V3.2 -// extern int waitForInterruptInit (int pin, int mode); //v3.2 // Threads From a7e20b8bf7e2c63b26f991ab450f161bbf525b85 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Sun, 16 Feb 2025 22:53:08 +0100 Subject: [PATCH 18/42] wiringPi.c : memory leak in wiringPiISR and wiringPiISRStop fixed --- VERSION | 2 +- version.h | 4 +- wiringPi/wiringPi.c | 203 ++++++++++++++++++++------------------------ 3 files changed, 95 insertions(+), 114 deletions(-) diff --git a/VERSION b/VERSION index 3767b4b..230693c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.14 \ No newline at end of file +3.15 \ No newline at end of file diff --git a/version.h b/version.h index c2da282..d7f42c6 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.14" +#define VERSION "3.15" #define VERSION_MAJOR 3 -#define VERSION_MINOR 14 +#define VERSION_MINOR 15 diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 28bec24..ba684ea 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -75,6 +75,7 @@ #include #include #include +#include #include "softPwm.h" #include "softTone.h" @@ -2800,21 +2801,35 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb return ret; } +/* + * waitForInterruptClose: + * wait for thread interruptHandler to be 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]) ; - } + void *res; + + if (isrFds[pin] > 0) { + if (wiringPiDebug) + printf ("waitForInterruptClose: 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("waitForInterruptClose: thread was canceled\n"); + } + else { + if (wiringPiDebug) + printf("waitForInterruptClose: thread was not canceled\n"); } } else { - if (wiringPiDebug) { - fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n"); - } + if (wiringPiDebug) + printf ("waitForInterruptClose: waitForInterruptClose could not cancel thread\n"); } } close(isrFds [pin]); @@ -2830,87 +2845,23 @@ 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 + * wiringPiISRStop: + * stop thread interruptHandler + * ********************************************************************************* */ -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 @@ -2922,17 +2873,17 @@ 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 timespec tspec = {0, 1e6}; /* 0.5 ms timeout {0, 5e5} */ pin = *(int *)arg; - -/* pin = pinPass ; - pinPass = -1 ; -*/ + if (wiringPiGpioDeviceGetFd()<0) { return NULL; } @@ -2953,7 +2904,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: @@ -2980,45 +2931,75 @@ 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); + isrFunctions [pin] ((unsigned int)pin, evdat[i].timestamp_ns/1000LL) ; + } + } + } + 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 ; } From 3c3b69c88842a4101eee9a590a09a136cb9e9e64 Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Sun, 16 Feb 2025 23:02:24 +0100 Subject: [PATCH 19/42] wiringPi.c : memory leak in wiringPiISR and wiringPiISRStop fixed --- wiringPi/wiringPi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index f0438d4..ba684ea 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -144,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); From 04dc08e511ead3a6d41b72240aab7185b5e4e43a Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Mon, 17 Feb 2025 12:23:11 +0100 Subject: [PATCH 20/42] wiringPi.c: waitForInterrupt rewritten --- documentation/deutsch/functions.md | 7 +- wiringPi/wiringPi.c | 104 ++++++++++++----------------- 2 files changed, 44 insertions(+), 67 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 0267556..82e94f8 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -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:** @@ -445,17 +445,14 @@ int main (void) ret = waitForInterrupt(IRQpin, INT_EDGE_FALLING, TIMEOUT, BOUNCETIME_WFI ); if (ret < 0) { printf("waitForInterrupt returned error %lld\n", ret); - wiringPiISRStop (IRQpin) ; pinMode(OUTpin, INPUT); return 0; } else if (ret == 0) { printf("waitForInterrupt timed out %lld\n\n", ret); - wiringPiISRStop (IRQpin) ; } else { printf("waitForInterrupt: falling edge fired at %lld microseconds\n\n", ret); - wiringPiISRStop (IRQpin) ; } 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); diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index ba684ea..2b37812 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2630,30 +2630,33 @@ 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 timestamp in microseconds on interrupt + ********************************************************************************* + */ -//-------------------------------------------------------------------- -// 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) +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 { - const char* strmode = ""; + long long 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 = ""; - 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] ; - } /* open gpio */ -// sleep(1); if (wiringPiGpioDeviceGetFd()<0) { return -1; } @@ -2663,6 +2666,7 @@ 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: @@ -2686,11 +2690,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,9 +2702,9 @@ 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); + status = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); + if (status == -1) { + ReportDeviceError("GPIO_V2_GET_LINE_IOCTL", pin , strmode, status); return -1; } @@ -2708,54 +2712,24 @@ int waitForInterruptInit (int pin, int edgeMode, unsigned long debounce_period_u printf ("wiringPi: 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); @@ -2772,7 +2746,7 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb 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)); + 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) ; @@ -2798,6 +2772,12 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb } } } + + if (isrFds[pin] > 0) { + close(isrFds [pin]); // release line + isrFds [pin] = -1; + isrDebouncePeriodUs[pin] = 0; + } return ret; } @@ -2954,7 +2934,7 @@ void *interruptHandler (void *arg) // Setup poll structure polls.fd = fd; - polls.events = POLLIN | POLLPRI;; + polls.events = POLLIN | POLLPRI; polls.revents = 0; // get event data, this is also a cancelation point, when pthread_cancel is called From 7abeddde2d64005bd8c8bcfb023160d719f96b7c Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Mon, 17 Feb 2025 22:09:07 +0100 Subject: [PATCH 21/42] wiringPi.c ; waitForInterrupt releases fd and line itself, wiringPiISRStop not necessary to be called --- wiringPi/wiringPi.c | 26 ++++++++------------------ wiringPi/wiringPi.h | 2 +- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 2b37812..f1ac321 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2782,34 +2782,35 @@ long long int waitForInterrupt (int pin, int edgeMode, int mS, unsigned long deb } /* - * waitForInterruptClose: - * wait for thread interruptHandler to be stopped. + * wiringPiISRStop: + * stop interruptHandler thread and + * wait untill stopped. * close isrFds[pin], reset isrFds[pin], isrFunction[pin] and isrDebouncePeriodUs[pin] * ********************************************************************************* */ -int waitForInterruptClose (int pin) { +int wiringPiISRStop (int pin) { void *res; if (isrFds[pin] > 0) { if (wiringPiDebug) - printf ("waitForInterruptClose: close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; + printf ("wiringPiISRStop: close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; if (isrThreads[pin] != 0) { if (pthread_cancel(isrThreads[pin]) == 0) { pthread_join(isrThreads[pin], &res); if (res == PTHREAD_CANCELED) { if (wiringPiDebug) - printf("waitForInterruptClose: thread was canceled\n"); + printf("wiringPiISRStop: thread was canceled\n"); } else { if (wiringPiDebug) - printf("waitForInterruptClose: thread was not canceled\n"); + printf("wiringPiISRStop: thread was not canceled\n"); } } else { if (wiringPiDebug) - printf ("waitForInterruptClose: waitForInterruptClose could not cancel thread\n"); + printf ("wiringPiISRStop: could not cancel thread\n"); } } close(isrFds [pin]); @@ -2830,17 +2831,6 @@ int waitForInterruptClose (int pin) { return 0; } -/* - * wiringPiISRStop: - * stop thread interruptHandler - * - ********************************************************************************* - */ - -int wiringPiISRStop (int pin) { - return waitForInterruptClose (pin); -} - /* * interruptHandler: diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 964fed3..e299f99 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -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 @@ -301,7 +302,6 @@ extern void digitalWriteByte2 (int value) ; 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 extern int wiringPiISRStop (int pin) ; //V3.2 -extern int waitForInterruptClose(int pin) ; //V3.2 // Threads From 44538850b4db2690eb035bc7ca4ca3a24cdbc7eb Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Tue, 18 Feb 2025 10:46:08 +0100 Subject: [PATCH 22/42] WiringPi.c interrupthandler ppoll timeout reduced --- wiringPi/wiringPi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index f1ac321..a818945 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2850,7 +2850,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 timespec tspec = {0, 1e6}; /* 0.5 ms timeout {0, 5e5} */ + struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */ pin = *(int *)arg; From 2f35ff5ec84b41ae2b249f87edec589f87dc30ab Mon Sep 17 00:00:00 2001 From: phylax2020 Date: Thu, 20 Feb 2025 11:29:30 +0100 Subject: [PATCH 23/42] 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 From 38274fe6e89f0403f778af9e9ecba83002537861 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 2 May 2025 13:10:40 +0200 Subject: [PATCH 24/42] #346 GPIO Character Device Userspace API V2 - compatibility to old interface --- VERSION | 2 +- gpio/gpio.c | 4 +- version.h | 4 +- wiringPi/WiringpiV1.c | 246 +++++++++++++++++++++++ wiringPi/test/wiringpi_test1_sysfs.c | 1 + wiringPi/wiringPi.c | 287 ++++++++++++++++----------- wiringPi/wiringPi.h | 18 +- 7 files changed, 437 insertions(+), 125 deletions(-) create mode 100644 wiringPi/WiringpiV1.c diff --git a/VERSION b/VERSION index 1bc446c..230693c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.16 \ No newline at end of file +3.15 \ No newline at end of file diff --git a/gpio/gpio.c b/gpio/gpio.c index 1ee2c33..9ffb1b7 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -177,7 +177,7 @@ void printgpio(const char* text) { } } -static void wfi (UNU struct WPIWfiStatus wfiStatus) { +static void wfi (void) { globalCounter++; if(globalCounter>=iterations) { printgpio("finished\n"); @@ -217,7 +217,7 @@ void doWfi (int argc, char *argv []) timeoutSec = atoi(argv [5]); } - if (wiringPiISR (pin, mode, &wfi, 0) < 0) + if (wiringPiISR (pin, mode, &wfi) < 0) { fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ; exit (1) ; diff --git a/version.h b/version.h index 5ea1e8c..d7f42c6 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.16" +#define VERSION "3.15" #define VERSION_MAJOR 3 -#define VERSION_MINOR 16 +#define VERSION_MINOR 15 diff --git a/wiringPi/WiringpiV1.c b/wiringPi/WiringpiV1.c new file mode 100644 index 0000000..fe6b5ce --- /dev/null +++ b/wiringPi/WiringpiV1.c @@ -0,0 +1,246 @@ +#include "Wiringpi.h" + + +int requestLineV1(int pin, unsigned int lineRequestFlags) { + struct gpiohandle_request rq; + + if (lineFds[pin]>=0) { + if (lineRequestFlags == lineFlags[pin]) { + //already requested + return lineFds[pin]; + } else { + //different request -> rerequest + releaseLine(pin); + } + } + + //requested line + if (wiringPiGpioDeviceGetFd()<0) { + return -1; // error + } + rq.lineoffsets[0] = pin; + rq.lines = 1; + rq.flags = 0; + // MAP to V1 Flag + if (lineRequestFlags & WPI_FLAG_INPUT) { + rq.flags |= GPIOHANDLE_REQUEST_INPUT; + } + if (lineRequestFlags & WPI_FLAG_OUTPUT) { + rq.flags |= GPIOHANDLE_REQUEST_OUTPUT; + } + if (lineRequestFlags & WPI_FLAG_BIAS_OFF) { + rq.flags |= GPIOHANDLE_REQUEST_BIAS_DISABLE; + } + if (lineRequestFlags & WPI_FLAG_BIAS_UP) { + rq.flags |= GPIOHANDLE_REQUEST_BIAS_PULL_UP; + } + if (lineRequestFlags & WPI_FLAG_BIAS_DOWN) { + rq.flags |= GPIOHANDLE_REQUEST_BIAS_PULL_DOWN; + } + int ret = ioctl(chipFd, GPIO_GET_LINEHANDLE_IOCTL, &rq); + if (ret || rq.fd<0) { + ReportDeviceError("get line handle", pin, "RequestLineV1", ret); + return -1; // error + } + + lineFlags[pin] = lineRequestFlags; + lineFds[pin] = rq.fd; + if (wiringPiDebug) + printf ("requestLine succeeded: pin:%d, flags: %u, fd :%d\n", pin, lineRequestFlags, lineFds[pin]) ; + return lineFds[pin]; + } + + + int digitalReadDeviceV1(int pin) { // INPUT and OUTPUT should work + + if (lineFds[pin]<0) { + // line not requested - auto request on first read as input + pinModeDevice(pin, INPUT); + } + if (lineFds[pin]>=0) { + struct gpiohandle_data data; + int ret = ioctl(lineFds[pin], GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); + if (ret) { + ReportDeviceError("get line values", pin, "digitalRead", ret); + return LOW; // error + } + return data.values[0]; + } + return LOW; // error , need to request line before + } + + + void digitalWriteDeviceV1(int pin, int value) { + + if (wiringPiDebug) + printf ("digitalWriteDevice: ioctl pin:%d value: %d\n", pin, value) ; + + if (lineFds[pin]<0) { + // line not requested - auto request on first write as output + pinModeDevice(pin, OUTPUT); + } + if (lineFds[pin]>=0 && (lineFlags[pin] & GPIOHANDLE_REQUEST_OUTPUT)>0) { + struct gpiohandle_data data; + data.values[0] = value; + if (wiringPiDebug) + printf ("digitalWriteDevice: ioctl pin:%d cmd: GPIOHANDLE_SET_LINE_VALUES_IOCTL, value: %d\n", pin, value) ; + int ret = ioctl(lineFds[pin], GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); + if (ret) { + ReportDeviceError("set line values", pin, "digitalWrite", ret); + return; // error + } + } else { + fprintf(stderr, "digitalWrite: no output (%d)\n", lineFlags[pin]); + } + return; // error + } + + /* + * 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. + ********************************************************************************* + */ + +int waitForInterruptV1(int pin, int mS) +{ + int fd, ret; + struct pollfd polls ; + struct gpioevent_data evdata; + //struct gpio_v2_line_request req2; + + 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; + + // Wait for it ... + ret = poll(&polls, 1, mS); + if (ret <= 0) { + fprintf(stderr, "wiringPi: ERROR: poll returned=%d\n", ret); + } else { + //if (polls.revents & POLLIN) + if (wiringPiDebug) { + printf ("wiringPi: IRQ line %d received %d, fd=%d\n", pin, ret, isrFds[pin]) ; + } + /* read event data */ + int readret = read(isrFds [pin], &evdata, sizeof(evdata)); + if (readret == sizeof(evdata)) { + if (wiringPiDebug) { + printf ("wiringPi: IRQ data id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp) ; + } + ret = evdata.id; + } else { + ret = 0; + } + } + return ret; +} + +int waitForInterruptInitV1(int pin, int mode) +{ + const char* strmode = ""; + + if (wiringPiMode == WPI_MODE_PINS) { + pin = pinToGpio [pin] ; + } else if (wiringPiMode == WPI_MODE_PHYS) { + pin = physToGpio [pin] ; + } + + /* open gpio */ + sleep(1); + if (wiringPiGpioDeviceGetFd()<0) { + return -1; + } + + struct gpioevent_request req; + req.lineoffset = pin; + req.handleflags = GPIOHANDLE_REQUEST_INPUT; + switch(mode) { + default: + case INT_EDGE_SETUP: + if (wiringPiDebug) { + printf ("wiringPi: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ; + } + return -1; + case INT_EDGE_FALLING: + req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE; + strmode = "falling"; + break; + case INT_EDGE_RISING: + req.eventflags = GPIOEVENT_REQUEST_RISING_EDGE; + strmode = "rising"; + break; + case INT_EDGE_BOTH: + req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; + strmode = "both"; + break; + } + strncpy(req.consumer_label, "wiringpi_gpio_irq", sizeof(req.consumer_label) - 1); + + //later implement GPIO_V2_GET_LINE_IOCTL req2 + int ret = ioctl(chipFd, GPIO_GET_LINEEVENT_IOCTL, &req); + if (ret) { + ReportDeviceError("get line event", pin , strmode, ret); + return -1; + } + if (wiringPiDebug) { + printf ("wiringPi: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; + } + + /* set event fd nonbloack read */ + int fd_line = req.fd; + isrFds [pin] = fd_line; + int flags = fcntl(fd_line, 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); + return -1; + } + + return 0; +} + + +int waitForInterruptClose (int pin) { + if (isrFds[pin]>0) { + if (wiringPiDebug) { + printf ("wiringPi: waitForInterruptClose close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; + } + if (pthread_cancel(isrThreads[pin]) == 0) { + if (wiringPiDebug) { + printf ("wiringPi: waitForInterruptClose thread canceled successfuly\n") ; + } + } else { + if (wiringPiDebug) { + fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n"); + } + } + close(isrFds [pin]); + } + isrFds [pin] = -1; + isrFunctions [pin] = NULL; + + /* -not closing so far - other isr may be using it - only close if no other is using - will code later + if (chipFd>0) { + close(chipFd); + } + chipFd = -1; + */ + if (wiringPiDebug) { + printf ("wiringPi: waitForInterruptClose finished\n") ; + } + return 0; +} diff --git a/wiringPi/test/wiringpi_test1_sysfs.c b/wiringPi/test/wiringpi_test1_sysfs.c index a97f85e..cc2af6b 100644 --- a/wiringPi/test/wiringpi_test1_sysfs.c +++ b/wiringPi/test/wiringpi_test1_sysfs.c @@ -52,6 +52,7 @@ int main (void) { delayMicroseconds(600000); } + //Error wrong direction - only for fun digitalWrite(GPIO, LOW); diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 0f2ea7d..ee8fbb7 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -454,6 +454,15 @@ int wiringPiReturnCodes = FALSE ; int wiringPiTryGpioMem = FALSE ; +enum WPIFlag { + WPI_FLAG_INPUT = 0x04, + WPI_FLAG_OUTPUT = 0x08, + WPI_FLAG_BIAS_UP = 0x100, + WPI_FLAG_BIAS_DOWN= 0x200, + WPI_FLAG_BIAS_OFF = 0x400, +}; + + static unsigned int lineFlags [64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -482,10 +491,11 @@ static int isrFds [64] = // ISR Data static int chipFd = -1; -static void (*isrFunctions [64])(struct WPIWfiStatus) ; +static void (*isrFunctionsV2[64])(struct WPIWfiStatus) ; +static void (*isrFunctions [64])(void) ; static pthread_t isrThreads[64]; -static int isrMode[64]; // irq on rising/falling edge -static unsigned long isrDebouncePeriodUs [64]; // 0: debounce is off +static int isrEdgeMode[64]; // irq on rising/falling edge +static unsigned long isrDebouncePeriodUs[64]; // 0: debounce is off // Doing it the Arduino way with lookup tables... // Yes, it's probably more innefficient than all the bit-twidling, but it @@ -1760,7 +1770,8 @@ void releaseLine(int pin) { isrDebouncePeriodUs[pin] = 0; } -int requestLine(int pin, unsigned int lineRequestFlags) { + +int requestLineV2(int pin, const unsigned int lineRequestFlags) { struct gpio_v2_line_request req; struct gpio_v2_line_config config; int ret; @@ -1782,7 +1793,24 @@ int requestLine(int pin, unsigned int lineRequestFlags) { memset(&req, 0, sizeof(req)); memset(&config, 0, sizeof(config)); - config.flags = lineRequestFlags; + if (lineRequestFlags & WPI_FLAG_INPUT) { + config.flags |= GPIO_V2_LINE_FLAG_INPUT; + } + if (lineRequestFlags & WPI_FLAG_OUTPUT) { + config.flags |= GPIO_V2_LINE_FLAG_OUTPUT; + } + if (lineRequestFlags & WPI_FLAG_BIAS_OFF) { + config.flags |= GPIO_V2_LINE_FLAG_BIAS_DISABLED; + } + if (lineRequestFlags & WPI_FLAG_BIAS_UP) { + config.flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP; + } + if (lineRequestFlags & WPI_FLAG_BIAS_DOWN) { + config.flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; + } + if (wiringPiDebug) { + printf ("requestLine flags v2: %llu\n", config.flags); + } strcpy(req.consumer, "wiringpi_gpio_req"); req.offsets[0] = pin; @@ -1792,14 +1820,14 @@ int requestLine(int pin, unsigned int lineRequestFlags) { ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); if (ret || req.fd<0) { - ReportDeviceError("get line handle", pin, "RequestLine", ret); + ReportDeviceError("get line handle v2", pin, "RequestLine", ret); return -1; // error } lineFlags[pin] = lineRequestFlags; lineFds[pin] = req.fd; if (wiringPiDebug) - printf ("requestLine succeeded: pin:%d, flags: %u, fd :%d\n", pin, lineRequestFlags, lineFds[pin]) ; + printf ("requestLine succeeded: pin:%d, flags: 0x%u, fd :%d\n", pin, lineRequestFlags, lineFds[pin]) ; return lineFds[pin]; } @@ -1892,21 +1920,21 @@ void rp1_set_pad(int pin, int slewfast, int schmitt, int pulldown, int pullup, i pads[1+pin] = (slewfast != 0) | ((schmitt != 0) << 1) | ((pulldown != 0) << 2) | ((pullup != 0) << 3) | ((drive & 0x3) << 4) | ((inputenable != 0) << 6) | ((outputdisable != 0) << 7); } -void pinModeFlagsDevice (int pin, int mode, unsigned int flags) { +void pinModeFlagsDevice (int pin, int mode, const unsigned int flags) { unsigned int lflag = flags; - if (wiringPiDebug) + if (wiringPiDebug) { printf ("pinModeFlagsDevice: pin:%d mode:%d, flags: %u\n", pin, mode, flags) ; - - lflag &= ~(GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_OUTPUT); + } + lflag &= ~(WPI_FLAG_INPUT | WPI_FLAG_OUTPUT); switch(mode) { default: fprintf(stderr, "pinMode: invalid mode request (only input und output supported)\n"); return; case INPUT: - lflag |= GPIO_V2_LINE_FLAG_INPUT; + lflag |= WPI_FLAG_INPUT; break; case OUTPUT: - lflag |= GPIO_V2_LINE_FLAG_OUTPUT; + lflag |= WPI_FLAG_OUTPUT; break; case PM_OFF: pinModeFlagsDevice(pin, INPUT, 0); @@ -1914,7 +1942,7 @@ void pinModeFlagsDevice (int pin, int mode, unsigned int flags) { return; } - requestLine(pin, lflag); + requestLineV2(pin, lflag); } void pinModeDevice (int pin, int mode) { @@ -2072,20 +2100,20 @@ void pinMode (int pin, int mode) */ void pullUpDnControlDevice (int pin, int pud) { unsigned int flag = lineFlags[pin]; - unsigned int biasflags = GPIO_V2_LINE_FLAG_BIAS_DISABLED | GPIO_V2_LINE_FLAG_BIAS_PULL_UP | GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; + unsigned int biasflags = WPI_FLAG_BIAS_OFF | WPI_FLAG_BIAS_UP | WPI_FLAG_BIAS_DOWN; flag &= ~biasflags; switch (pud){ - case PUD_OFF: flag |= GPIO_V2_LINE_FLAG_BIAS_DISABLED; break; - case PUD_UP: flag |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP; break; - case PUD_DOWN: flag |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; break; + case PUD_OFF: flag |= WPI_FLAG_BIAS_OFF; break; + case PUD_UP: flag |= WPI_FLAG_BIAS_UP; break; + case PUD_DOWN: flag |= WPI_FLAG_BIAS_DOWN; break; default: return ; /* An illegal value */ } // reset input/output - if (lineFlags[pin] & GPIO_V2_LINE_FLAG_OUTPUT) { + if (lineFlags[pin] & WPI_FLAG_OUTPUT) { pinModeFlagsDevice (pin, OUTPUT, flag); - } else if(lineFlags[pin] & GPIO_V2_LINE_FLAG_INPUT) { + } else if(lineFlags[pin] & WPI_FLAG_INPUT) { pinModeFlagsDevice (pin, INPUT, flag); } else { lineFlags[pin] = flag; // only store for later @@ -2204,7 +2232,7 @@ static inline int gpiotools_test_bit(__u64 b, int n) ********************************************************************************* */ -int digitalReadDevice (int pin) { // INPUT and OUTPUT should work +int digitalReadDeviceV2(int pin) { // INPUT and OUTPUT should work struct gpio_v2_line_values lv; int ret; @@ -2244,11 +2272,11 @@ int digitalRead (int pin) pin = physToGpio [pin]; break; case WPI_MODE_GPIO_DEVICE_BCM: - return digitalReadDevice(pin); + return digitalReadDeviceV2(pin); case WPI_MODE_GPIO_DEVICE_WPI: - return digitalReadDevice(pinToGpio[pin]); + return digitalReadDeviceV2(pinToGpio[pin]); case WPI_MODE_GPIO_DEVICE_PHYS: - return digitalReadDevice(physToGpio[pin]); + return digitalReadDeviceV2(physToGpio[pin]); case WPI_MODE_GPIO: break; } @@ -2302,12 +2330,12 @@ unsigned int digitalRead8 (int pin) ********************************************************************************* */ -void digitalWriteDevice (int pin, int value) { +void digitalWriteDeviceV2(int pin, int value) { int ret; struct gpio_v2_line_values values; if (wiringPiDebug) - printf ("digitalWriteDevice: ioctl pin:%d value: %d\n", pin, value) ; + printf ("digitalWriteDeviceV2: ioctl pin:%d value: %d\n", pin, value) ; if (lineFds[pin]<0) { // line not requested - auto request on first write as output @@ -2320,13 +2348,13 @@ void digitalWriteDevice (int pin, int value) { gpiotools_set_bit(&values.mask, 0); gpiotools_assign_bit(&values.bits, 0, !!value); - ret = ioctl(lineFds[pin], GPIO_V2_LINE_SET_VALUES_IOCTL, &values); - if (ret == -1) { - ReportDeviceError("digitalWriteDevice", pin, "GPIO_V2_LINE_SET_VALUES_IOCTL", ret); - return; // error - } + ret = ioctl(lineFds[pin], GPIO_V2_LINE_SET_VALUES_IOCTL, &values); + if (ret == -1) { + ReportDeviceError("digitalWriteDeviceV2", pin, "GPIO_V2_LINE_SET_VALUES_IOCTL", ret); + return; // error + } } else { - fprintf(stderr, "digitalWrite: no output (%d)\n", lineFlags[pin]); + fprintf(stderr, "digitalWriteDeviceV2: no output (%d)\n", lineFlags[pin]); } return; // error } @@ -2349,13 +2377,13 @@ void digitalWrite (int pin, int value) pin = physToGpio [pin]; break; case WPI_MODE_GPIO_DEVICE_BCM: - digitalWriteDevice(pin, value); + digitalWriteDeviceV2(pin, value); return; case WPI_MODE_GPIO_DEVICE_WPI: - digitalWriteDevice(pinToGpio[pin], value); + digitalWriteDeviceV2(pinToGpio[pin], value); return; case WPI_MODE_GPIO_DEVICE_PHYS: - digitalWriteDevice(physToGpio[pin], value); + digitalWriteDeviceV2(physToGpio[pin], value); return; case WPI_MODE_GPIO: break; @@ -2631,17 +2659,13 @@ 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. + * waitForInterrupt2: + * Wait for Interrupt on a GPIO pin and use v2 of the character device API, need Kernel 5.1 * Returns struct WPIWfiStatus ********************************************************************************* */ -struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned long debounce_period_us) // ms < 0 wait infinite, = 0 return immediately, > 0 wait timeout +struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned long debounce_period_us) // ms < 0 wait infinite, = 0 return immediately, > 0 wait timeout { int ret; int fd, attr, status, readret; @@ -2675,7 +2699,7 @@ struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned lo default: case INT_EDGE_SETUP: if (wiringPiDebug) { - printf ("waitForInterrupt: edgeMode INT_EDGE_SETUP - exiting\n") ; + printf ("waitForInterrupt2: edgeMode INT_EDGE_SETUP - exiting\n") ; } wfiStatus.status = -1; return wfiStatus; @@ -2695,11 +2719,11 @@ struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned lo strcpy(req.consumer, "wiringpi_gpio_irq"); if (debounce_period_us) { - attr = config.num_attrs; - config.num_attrs++; + 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; + 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; @@ -2715,7 +2739,7 @@ struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned lo } if (wiringPiDebug) { - printf ("waitForInterrupt: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; + printf ("waitForInterrupt2: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; } fd = req.fd; @@ -2738,48 +2762,47 @@ struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned lo polls.events = POLLIN | POLLPRI; polls.revents = 0; - ret = poll(&polls, 1, mS); + ret = poll(&polls, 1, ms); if (ret < 0) { if (wiringPiDebug) { - fprintf(stderr, "waitForInterrupt: ERROR: poll returned=%d\n", ret); + fprintf(stderr, "waitForInterrupt2: ERROR: poll returned=%d\n", ret); } wfiStatus.status = -1; } else if (ret == 0) { if (wiringPiDebug) { - fprintf(stderr, "waitForInterrupt: timeout: poll returned=%d\n", ret); + fprintf(stderr, "waitForInterrupt2: timeout: poll returned zero\n"); } wfiStatus.status = 0; } else { - if (wiringPiDebug) - printf ("waitForInterrupt: IRQ line %d received %d, fd=%d\n", pin, ret, isrFds[pin]) ; + if (wiringPiDebug) { + printf ("waitForInterrupt2: 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 ("waitForInterrupt: IRQ at PIN: %d, timestamp: %lld\n", evdata.offset, evdata.timestamp_ns) ; - + if (wiringPiDebug) { + printf ("waitForInterrupt2: IRQ at PIN: %d, timestamp: %lld\n", evdata.offset, evdata.timestamp_ns) ; + } switch (evdata.id) { - case GPIO_V2_LINE_EVENT_RISING_EDGE: + 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: + if (wiringPiDebug) printf("waitForInterrupV2: 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: + if (wiringPiDebug) printf("waitForInterrupt2: falling edge\n"); + break; + default: wfiStatus.edge = INT_EDGE_SETUP; // edge = 0 - if (wiringPiDebug) - printf("waitForInterrupt: unknown event\n"); + if (wiringPiDebug) printf("waitForInterrupt2: unknown event\n"); break; - } + } wfiStatus.timeStamp_us = evdata.timestamp_ns / 1000LL; // nanoseconds u64 to microseconds - wfiStatus.gpioPin = evdata.offset; + wfiStatus.pin = evdata.offset; + wfiStatus.id = evdata.id; wfiStatus.status = 1; } else { @@ -2800,6 +2823,19 @@ struct WPIWfiStatus waitForInterrupt (int pin, int edgeMode, int mS, unsigned lo return wfiStatus; } +int waitForInterrupt (int pin, int ms) { + struct WPIWfiStatus status; + + int edgeMode = isrEdgeMode[pin]; + if (edgeMode==0) { + fprintf(stderr, "waitForInterrupt: ERROR: edge mode missing, legacy function, please use waitForInterrupt2!\n"); + return -1; + } + status = waitForInterrupt2(pin, edgeMode, ms, 0); + + return status.id; +} + /* * wiringPiISRStop: * stop interruptHandler thread and @@ -2835,7 +2871,8 @@ int wiringPiISRStop (int pin) { close(isrFds [pin]); } isrFds [pin] = -1; - isrFunctions [pin] = NULL; + isrFunctions[pin] = NULL; + isrFunctionsV2[pin] = NULL; isrDebouncePeriodUs[pin] = 0; /* -not closing so far - other isr may be using it - only close if no other is using - will code later @@ -2845,24 +2882,27 @@ int wiringPiISRStop (int pin) { chipFd = -1; */ if (wiringPiDebug) { - printf ("waitForInterruptClose: waitForInterruptClose finished\n") ; + printf ("wiringPiISRStop: wiringPiISRStop finished\n") ; } return 0; } +int waitForInterruptClose(int pin) { + return wiringPiISRStop(pin); +} /* - * interruptHandler: + * interruptHandlerV2: * This is a thread and gets started to wait for the interrupt we're * hoping to catch. It will call the user-function when the interrupt * fires. ********************************************************************************* */ -void *interruptHandler (void *arg) +void *interruptHandlerV2(void *arg) { const char* strmode = ""; - int pin, mode, ret, fd, attr, i; + int pin, EdgeMode, ret, fd, attr, i; unsigned int readret; unsigned long debounce_period_us; struct pollfd polls ; @@ -2878,11 +2918,11 @@ void *interruptHandler (void *arg) return NULL; } - mode = isrMode[pin]; + EdgeMode = isrEdgeMode[pin]; debounce_period_us = isrDebouncePeriodUs[pin]; if (wiringPiDebug) { - printf ("interruptHandler: GPIO line %d, mode %d, debounce_period_us %lu \n", pin, mode, debounce_period_us) ; + printf ("interruptHandlerV2: GPIO line %d, edge mode %d, debounce_period_us %lu \n", pin, EdgeMode, debounce_period_us) ; } memset(&req, 0, sizeof(req)); @@ -2890,11 +2930,11 @@ void *interruptHandler (void *arg) /* setup config */ config.flags = GPIO_V2_LINE_FLAG_INPUT; - switch(mode) { + switch(EdgeMode) { default: case INT_EDGE_SETUP: if (wiringPiDebug) { - printf ("interruptHandler: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ; + printf ("interruptHandlerV2: waitForInterruptMode edge mode INT_EDGE_SETUP - exiting\n") ; } return NULL; case INT_EDGE_FALLING: @@ -2927,12 +2967,12 @@ void *interruptHandler (void *arg) ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); if (ret == -1) { - ReportDeviceError("interruptHandler: get line event", pin , strmode, ret); + ReportDeviceError("interruptHandlerV2: get line event", pin , strmode, ret); return NULL; } if (wiringPiDebug) - printf ("interruptHandler: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; + printf ("interruptHandlerV2: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; /* set event fd */ fd = req.fd; @@ -2940,7 +2980,7 @@ void *interruptHandler (void *arg) (void)piHiPri (55) ; // Only effective if we run as root - for (;;) { // check if event data is available, check if interruptHandler thread must be canceled + for (;;) { // check if event data is available, check if interruptHandlerV2 thread must be canceled // Setup poll structure polls.fd = fd; @@ -2952,58 +2992,71 @@ void *interruptHandler (void *arg) 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); + printf("interruptHandlerV2: 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); +// printf("interruptHandlerV2: 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]) ; + printf ("interruptHandlerV2: 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])) ; + printf ("interruptHandlerV2: 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 (isrFunctionsV2[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); + printf( "interruptHandlerV2: GPIO EVENT at %llu on line %u (%u|%u) \n", evdat[i].timestamp_ns, evdat[i].offset, evdat[i].line_seqno, evdat[i].seqno); wfiStatus.status = 1; - wfiStatus.gpioPin = pin; + wfiStatus.pin = pin; switch (evdat[i].id) { case GPIO_V2_LINE_EVENT_RISING_EDGE: wfiStatus.edge = INT_EDGE_RISING; if (wiringPiDebug) - printf("waitForInterrupt: rising edge\n"); + printf("waitForInterrupt2: rising edge\n"); break; case GPIO_V2_LINE_EVENT_FALLING_EDGE: wfiStatus.edge = INT_EDGE_FALLING; if (wiringPiDebug) - printf("waitForInterrupt: falling edge\n"); + printf("waitForInterrupt2: falling edge\n"); break; default: wfiStatus.edge = INT_EDGE_SETUP; // edge = 0 if (wiringPiDebug) - printf("waitForInterrupt: unknown event\n"); + printf("waitForInterrupt2: unknown event\n"); break; } wfiStatus.timeStamp_us = evdat[i].timestamp_ns/1000LL; - isrFunctions [pin] (wfiStatus) ; + if (wiringPiDebug) { + printf( "interruptHandlerV2: call isr function\n"); + } + isrFunctionsV2[pin](wfiStatus); + if (wiringPiDebug) { + printf( "interruptHandlerV2: return from isr function\n"); + } + } + if (isrFunctions[pin]) { + if (wiringPiDebug) { + printf( "interruptHandlerV2: call isr function classic\n"); + } + isrFunctions[pin](); + if (wiringPiDebug) { + printf( "interruptHandlerV2: return from isr function classic\n"); + } } } } 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"); + printf ("interruptHandlerV2: reading events from fd received signal, exit thread\n"); pthread_exit(NULL); return NULL; // never landing here } @@ -3022,7 +3075,7 @@ void *interruptHandler (void *arg) ********************************************************************************* */ -int wiringPiISR (int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us) +int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus), void (*functionClassic)(void), unsigned long debounce_period_us) { const int maxpin = GetMaxPin(); @@ -3040,12 +3093,13 @@ int wiringPiISR (int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfi if (wiringPiDebug) { printf ("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode) ; } - if (isrFunctions [pin]) { + if (isrFunctions[pin] || isrFunctionsV2[pin] ) { printf ("wiringPi: ISR function already active, ignoring \n") ; } - isrFunctions [pin] = function ; - isrMode[pin] = edgeMode; + isrFunctionsV2[pin] = function; + isrFunctions[pin] = functionClassic; + isrEdgeMode[pin] = edgeMode; isrDebouncePeriodUs[pin] = debounce_period_us; if (wiringPiDebug) { @@ -3056,7 +3110,7 @@ int wiringPiISR (int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfi if (wiringPiDebug) { printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]); } - if (pthread_create (&isrThreads[pin], NULL, interruptHandler, &pin)==0) { + if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, &pin)==0) { if (wiringPiDebug) { printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]); } @@ -3084,6 +3138,15 @@ int wiringPiISR (int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfi return 0 ; } +int wiringPiISR (int pin, int mode, void (*function)(void)) +{ + return wiringPiISRInternal(pin, mode, NULL, function, 0); +} + +int wiringPiISR2(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us) +{ + return wiringPiISRInternal(pin, edgeMode, function, NULL, debounce_period_us); +} /* * initialiseEpoch: @@ -3116,12 +3179,12 @@ static void initialiseEpoch (void) ********************************************************************************* */ -void delay (unsigned int howLong) +void delay (unsigned int ms) { struct timespec sleeper, dummy ; - sleeper.tv_sec = (time_t)(howLong / 1000) ; - sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ; + sleeper.tv_sec = (time_t)(ms / 1000) ; + sleeper.tv_nsec = (long)(ms % 1000) * 1000000 ; nanosleep (&sleeper, &dummy) ; } @@ -3145,29 +3208,29 @@ void delay (unsigned int howLong) ********************************************************************************* */ -void delayMicrosecondsHard (unsigned int howLong) +void delayMicrosecondsHard (unsigned int us) { struct timeval tNow, tLong, tEnd ; gettimeofday (&tNow, NULL) ; - tLong.tv_sec = howLong / 1000000 ; - tLong.tv_usec = howLong % 1000000 ; + tLong.tv_sec = us / 1000000 ; + tLong.tv_usec = us % 1000000 ; timeradd (&tNow, &tLong, &tEnd) ; while (timercmp (&tNow, &tEnd, <)) gettimeofday (&tNow, NULL) ; } -void delayMicroseconds (unsigned int howLong) +void delayMicroseconds (unsigned int us) { struct timespec sleeper ; - unsigned int uSecs = howLong % 1000000 ; - unsigned int wSecs = howLong / 1000000 ; + unsigned int uSecs = us % 1000000 ; + unsigned int wSecs = us / 1000000 ; - /**/ if (howLong == 0) + /**/ if (us == 0) return ; - else if (howLong < 100) - delayMicrosecondsHard (howLong) ; + else if (us < 100) + delayMicrosecondsHard (us) ; else { sleeper.tv_sec = wSecs ; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index be64b16..6542caa 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -297,19 +297,21 @@ extern void digitalWriteByte (int value) ; extern void digitalWriteByte2 (int value) ; // Interrupts -// (Also Pi hardware specific) - -// status returned from waitForInterrupt V3.16 +// status returned from waitForInterruptV2 V3.16 struct WPIWfiStatus { + int id; int status; // -1: error, 0: timeout, 1: valud values for edge and timeStamp_us - unsigned int gpioPin; // gpio as BCM pin + unsigned int pin; // 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 waitForInterrupt (int pin, int ms) ; +extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; +extern struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned long debounce_period_us) ; // V3.16 phylax +extern int wiringPiISR2 (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 legacy use wiringPiISRStop // Threads @@ -323,8 +325,8 @@ extern int piHiPri (const int pri) ; // Extras from arduino land -extern void delay (unsigned int howLong) ; -extern void delayMicroseconds (unsigned int howLong) ; +extern void delay (unsigned int ms) ; +extern void delayMicroseconds (unsigned int us) ; extern unsigned int millis (void) ; extern unsigned int micros (void) ; From b71a2b688e5a6c0212d109e06c3946c80c218222 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 2 May 2025 19:50:44 +0200 Subject: [PATCH 25/42] #346 irq status var name ajust --- wiringPi/wiringPi.c | 28 +++++++++++++--------------- wiringPi/wiringPi.h | 15 +++++++-------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index ee8fbb7..d9b7c91 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2685,7 +2685,7 @@ struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned lo /* open gpio */ if (wiringPiGpioDeviceGetFd()<0) { - wfiStatus.status = -1; + wfiStatus.statusOK = -1; return wfiStatus; } @@ -2701,7 +2701,7 @@ struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned lo if (wiringPiDebug) { printf ("waitForInterrupt2: edgeMode INT_EDGE_SETUP - exiting\n") ; } - wfiStatus.status = -1; + wfiStatus.statusOK = -1; return wfiStatus; case INT_EDGE_FALLING: config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; @@ -2734,7 +2734,7 @@ struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned lo status = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); if (status == -1) { ReportDeviceError("GPIO_V2_GET_LINE_IOCTL", pin , strmode, status); - wfiStatus.status = -1; + wfiStatus.statusOK = -1; return wfiStatus; } @@ -2763,24 +2763,23 @@ struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned lo polls.revents = 0; ret = poll(&polls, 1, ms); - if (ret < 0) { if (wiringPiDebug) { fprintf(stderr, "waitForInterrupt2: ERROR: poll returned=%d\n", ret); } - wfiStatus.status = -1; + wfiStatus.statusOK = -1; } else if (ret == 0) { if (wiringPiDebug) { fprintf(stderr, "waitForInterrupt2: timeout: poll returned zero\n"); } - wfiStatus.status = 0; + wfiStatus.statusOK = 0; // timeout } else { if (wiringPiDebug) { printf ("waitForInterrupt2: IRQ line %d received %d, fd=%d\n", pin, ret, isrFds[pin]); } if (polls.revents & POLLIN) { - /* read event data */ + /* read event data */ readret = read(isrFds [pin], &evdata, sizeof(evdata)); if (readret == sizeof(evdata)) { if (wiringPiDebug) { @@ -2801,16 +2800,15 @@ struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned lo break; } wfiStatus.timeStamp_us = evdata.timestamp_ns / 1000LL; // nanoseconds u64 to microseconds - wfiStatus.pin = evdata.offset; - wfiStatus.id = evdata.id; - wfiStatus.status = 1; + wfiStatus.pinBCM = evdata.offset; + wfiStatus.statusOK = 1; } else { - wfiStatus.status = -1; + wfiStatus.statusOK = -1; } } else { - wfiStatus.status = -1; + wfiStatus.statusOK = -1; } } @@ -2833,7 +2831,7 @@ int waitForInterrupt (int pin, int ms) { } status = waitForInterrupt2(pin, edgeMode, ms, 0); - return status.id; + return status.statusOK; } /* @@ -3015,8 +3013,8 @@ void *interruptHandlerV2(void *arg) if (isrFunctionsV2[pin]) { if (wiringPiDebug) printf( "interruptHandlerV2: GPIO EVENT at %llu on line %u (%u|%u) \n", evdat[i].timestamp_ns, evdat[i].offset, evdat[i].line_seqno, evdat[i].seqno); - wfiStatus.status = 1; - wfiStatus.pin = pin; + wfiStatus.statusOK = 1; + wfiStatus.pinBCM = pin; switch (evdat[i].id) { case GPIO_V2_LINE_EVENT_RISING_EDGE: wfiStatus.edge = INT_EDGE_RISING; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 6542caa..1fe25e5 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -299,17 +299,16 @@ extern void digitalWriteByte2 (int value) ; // Interrupts // status returned from waitForInterruptV2 V3.16 struct WPIWfiStatus { - int id; - int status; // -1: error, 0: timeout, 1: valud values for edge and timeStamp_us - unsigned int pin; // 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 + int statusOK; // -1: error (return of 'poll' command), 0: timeout, 1: irq processed, next data values are valid if needed + unsigned int pinBCM; // gpio as BCM pin + int edge; // INT_EDGE_FALLING or INT_EDGE_RISING + long long int timeStamp_us; // time stamp in microseconds }; -extern int waitForInterrupt (int pin, int ms) ; +//extern int waitForInterrupt (int pin, int ms); unknown if still working, disabled for V3.16, please contact developer via github extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; -extern struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned long debounce_period_us) ; // V3.16 phylax -extern int wiringPiISR2 (int pin, int mode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us) ; // v3.16 phylax +extern struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned long debounce_period_us) ; // V3.16 +extern int wiringPiISR2 (int pin, int mode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us) ; // V3.16 extern int wiringPiISRStop (int pin) ; //V3.2 extern int waitForInterruptClose(int pin) ; //V3.2 legacy use wiringPiISRStop From 50908a31ebac4669a469701c66befeeb73883e66 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 2 May 2025 19:51:24 +0200 Subject: [PATCH 26/42] #346 unit test --- wiringPi/test/Makefile | 5 +- wiringPi/test/wiringpi_test61_isr2.c | 255 +++++++++++++++++++++++++++ 2 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 wiringPi/test/wiringpi_test61_isr2.c diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index 299dcb4..0b68f96 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = # Need BCM19 <-> BCM26, +PWM: BCM12 <-> BCM13, BCM18 <-> BCM17 connected (1kOhm) -tests = wiringpi_test0_version wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiringpi_test4_device_phys wiringpi_test5_default wiringpi_test6_isr wiringpi_test7_bench wiringpi_test8_pwm wiringpi_test9_pwm +tests = wiringpi_test0_version wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiringpi_test4_device_phys wiringpi_test5_default wiringpi_test6_isr wiringpi_test61_isr2 wiringpi_test7_bench wiringpi_test8_pwm wiringpi_test9_pwm # Need XO hardware xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 wiringpi_test8_pwm wiringpi_test9_pwm @@ -34,6 +34,9 @@ wiringpi_test5_default: wiringpi_test6_isr: ${CC} ${CFLAGS} wiringpi_test6_isr.c -o wiringpi_test6_isr -lwiringPi +wiringpi_test61_isr2: + ${CC} ${CFLAGS} wiringpi_test61_isr2.c -o wiringpi_test61_isr2 -lwiringPi + wiringpi_test7_bench: ${CC} ${CFLAGS} wiringpi_test7_bench.c -o wiringpi_test7_bench -lwiringPi diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c new file mode 100644 index 0000000..59e70e5 --- /dev/null +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -0,0 +1,255 @@ +// WiringPi test program: 3.16 new ISR2 function with Kernel char device interface / sysfs successor +// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi + +#include "wpi_test.h" +#include +#include +#include +#include + + +int GPIO = 19; +int GPIOIN = 26; +const int ToggleValue = 4; +float irq_timstamp_duration_ms = 0; + +static volatile int globalCounter; +volatile long long gStartTime, gEndTime; +struct WPIWfiStatus wfiStatusOld; + +static void ISR(void) { + struct timeval now; + + gettimeofday(&now, 0); + if (0==gStartTime) { + gStartTime = now.tv_sec*1000000LL + now.tv_usec; + } else { + gEndTime = now.tv_sec*1000000LL + now.tv_usec; + } + globalCounter++; +} + + +static void ISR2(struct WPIWfiStatus wfiStatus) { + struct timeval now; + char strEdge[3][10] = {"unknown", "falling", "raising"}; + int strEdgeidx = 0; //default + + gettimeofday(&now, 0); + if (0==gStartTime) { + gStartTime = now.tv_sec*1000000LL + now.tv_usec; + } else { + gEndTime = now.tv_sec*1000000LL + now.tv_usec; + } + globalCounter++; + switch(wfiStatus.edge) { + case INT_EDGE_FALLING: strEdgeidx = INT_EDGE_FALLING; break; + case INT_EDGE_RISING: strEdgeidx = INT_EDGE_RISING; break; + } + if (wfiStatusOld.statusOK>0 && wfiStatusOld.pinBCM==wfiStatus.pinBCM) { + irq_timstamp_duration_ms = (wfiStatus.timeStamp_us - wfiStatusOld.timeStamp_us) / 1000.0f; + } else { + irq_timstamp_duration_ms = 0.0f; + } + printf("ISR occured @ %lld us: statusOK=%d, pin=%u, edge=%s (%d), duration=%g ms\n", + wfiStatus.timeStamp_us, wfiStatus.statusOK, wfiStatus.pinBCM, strEdge[strEdgeidx], wfiStatus.edge, irq_timstamp_duration_ms); + wfiStatusOld = wfiStatus; +} + +void digitalWriteBounce(int OUTpin, int value, int bounce) { + digitalWrite(OUTpin, value); + if (bounce>0) { + delay(1); + digitalWrite(OUTpin, !value); + delay(1); + digitalWrite(OUTpin, value); + } +} + +double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { + int expected; + float timeExpected_ms; + float irq_timstamp_sum = 0.0f; + + gStartTime = 0; + gEndTime = 0; + globalCounter = 0; + printf("Start\n"); + digitalWriteBounce(OUTpin, HIGH, bounce); + delay(10); + delay(190); + digitalWriteBounce(OUTpin, LOW, bounce); + delay(10); + if (INT_EDGE_BOTH == Edge) { + irq_timstamp_sum += irq_timstamp_duration_ms; + } + delay(90); + digitalWriteBounce(OUTpin, HIGH, bounce); + delay(10); + if (INT_EDGE_RISING == Edge || INT_EDGE_BOTH == Edge) { + irq_timstamp_sum += irq_timstamp_duration_ms; + } + delay(190); + digitalWriteBounce(OUTpin, LOW, bounce); + delay(10); + if (INT_EDGE_FALLING == Edge || INT_EDGE_BOTH == Edge) { + irq_timstamp_sum += irq_timstamp_duration_ms; + } + delay(90); + printf("Stop\n"); + int globalCounterCopy = globalCounter; + + if (INT_EDGE_BOTH == Edge) { + expected = 4; + timeExpected_ms = bounce ? 508: 500; + } else { + expected = 2; + timeExpected_ms = bounce ? 304: 300; + } + + if (globalCounter==expected) { + char str[1024]; + float fTime = (gEndTime - gStartTime) / 1000.0; + sprintf(str, "IRQ measured %g msec (~%g expected)", fTime, timeExpected_ms); + CheckSameFloat(str, fTime, timeExpected_ms, timeExpected_ms*0.01); + sprintf(str, "IRQ timestamp %g msec (~%g expected)", irq_timstamp_sum, timeExpected_ms); + CheckSameFloat(str, irq_timstamp_sum, timeExpected_ms, timeExpected_ms*0.01); + // new data struct + CheckSame("GPIO IRQ pin", wfiStatusOld.pinBCM, INpin); + if (INT_EDGE_FALLING==Edge || INT_EDGE_RISING==Edge) { + CheckSame("GPIO IRQ edge", wfiStatusOld.edge, Edge); + } + CheckSame("GPIO IRQ status", wfiStatusOld.statusOK, 1); + return fTime; + } else { + printf("IRQ not worked got %d iterations (%d exprected)\n\n", globalCounterCopy, expected); + return 0; + } +} + + +double DurationTime(int Enge, int OUTpin, int IRQpin, int new) { + struct timeval now; + double fTime = 0.0; + + gStartTime = 0; + gEndTime = 0; + globalCounter = 0; + printf("Start\n"); + + if (INT_EDGE_RISING == Enge) { + digitalWrite(OUTpin, LOW); + if (new) { + wiringPiISR2(IRQpin, INT_EDGE_RISING, &ISR2, 0); + } else { + wiringPiISR(IRQpin, INT_EDGE_RISING, &ISR); + } + sleep(1); + gettimeofday(&now, 0); + gStartTime = now.tv_sec*1000000LL + now.tv_usec; + digitalWrite(OUTpin, HIGH); + delay(20); + digitalWrite(OUTpin, LOW); + } else if (INT_EDGE_FALLING == Enge) { + digitalWrite(OUTpin, HIGH); + if (new) { + wiringPiISR2(IRQpin, INT_EDGE_FALLING, &ISR2, 0); + } else { + wiringPiISR(IRQpin, INT_EDGE_FALLING, &ISR); + } + sleep(1); + gettimeofday(&now, 0); + gStartTime = now.tv_sec*1000000LL + now.tv_usec; + digitalWrite(OUTpin, LOW); + } + + sleep(1); + fTime = (gEndTime - gStartTime); + printf("IRQ detect time %g usec", fTime); + if (fTime<2000 && fTime>0) { + printf(" -> %spassed%s\n", COLORGRN, COLORDEF); + } else { + printf(" -> %sfailed%s\n", COLORRED, COLORDEF); + } + wiringPiISRStop(IRQpin); + + return fTime; +} + + +int main (void) { + + int major=0, minor=0; + + wiringPiVersion(&major, &minor); + + printf("WiringPi GPIO test program 6b (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); + printf("ISR and ISR2 test (WiringPi %d.%d)\n", major, minor); + + wiringPiSetupGpio() ; + if (!piBoard40Pin()) { + GPIO = 23; + GPIOIN = 24; + } + int IRQpin = GPIOIN; + int OUTpin = GPIO; + + wiringPiISR2(13, INT_EDGE_RISING, &ISR2, 0); // next pin + + memset(&wfiStatusOld, 0, sizeof(wfiStatusOld)); + + pinMode(IRQpin, INPUT); + pinMode(OUTpin, OUTPUT); + digitalWrite (OUTpin, LOW) ; + + /// -------------------- + for (int bounce=0; bounce<=1; bounce++) { + unsigned long bouncetime = 0; + if (0==bounce) { + printf("! --- default test (no bounce) --- !\n"); + } else { + bouncetime = 2000; //2 ms + printf("! --- test with bounce on input --- !\n"); + } + + printf("\nTesting IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); + wiringPiISR2(IRQpin, INT_EDGE_RISING, &ISR2, bouncetime); + sleep(1); + StartSequence2(INT_EDGE_RISING, OUTpin, IRQpin, bounce); + printf("Stopp IRQ\n"); + wiringPiISRStop(IRQpin); + + printf("\nTesting IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); + wiringPiISR2(IRQpin, INT_EDGE_FALLING, &ISR2, bouncetime); + sleep(1); + StartSequence2(INT_EDGE_FALLING, OUTpin, IRQpin, bounce); + printf("Stopp IRQ\n"); + wiringPiISRStop(IRQpin); + + printf("\nTesting IRQ @ GPIO%d with trigger @ GPIO%d both\n", IRQpin, OUTpin); + wiringPiISR2(IRQpin, INT_EDGE_BOTH, &ISR2, bouncetime); + sleep(1); + StartSequence2(INT_EDGE_BOTH, OUTpin, IRQpin, bounce); + printf("Stopp IRQ\n"); + wiringPiISRStop(IRQpin); + } + + for (int count=0; count<2; count++) { + printf("\nclassic function:\n"); + printf("=================\n"); + printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); + DurationTime(INT_EDGE_RISING, OUTpin, IRQpin, 0); + printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); + DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin, 0); + + printf("\nnew function:\n"); + printf("===============\n"); + printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); + DurationTime(INT_EDGE_RISING, OUTpin, IRQpin, 1); + printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); + DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin, 1); + } + pinMode(OUTpin, INPUT); + + return UnitTestState(); +} From 323f4d09f3df28d058cd9a3bb3d829d89089b039 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 3 May 2025 20:26:31 +0200 Subject: [PATCH 27/42] #346 ajust unit test for Pi1 --- wiringPi/test/wiringpi_test61_isr2.c | 62 ++++++++++++++++++---------- wiringPi/test/wiringpi_test7_bench.c | 2 +- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index 59e70e5..5f3bb3f 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -12,6 +12,7 @@ int GPIO = 19; int GPIOIN = 26; const int ToggleValue = 4; float irq_timstamp_duration_ms = 0; +float accuracy = 0.01; static volatile int globalCounter; volatile long long gStartTime, gEndTime; @@ -56,6 +57,7 @@ static void ISR2(struct WPIWfiStatus wfiStatus) { wfiStatusOld = wfiStatus; } + void digitalWriteBounce(int OUTpin, int value, int bounce) { digitalWrite(OUTpin, value); if (bounce>0) { @@ -66,6 +68,16 @@ void digitalWriteBounce(int OUTpin, int value, int bounce) { } } + +void DelayAndSumDuration(int ms, float* irq_timstamp_sum, const int doSum) { + delay(20); + if (doSum) { + *irq_timstamp_sum += irq_timstamp_duration_ms; + } + delay(ms-20); +} + + double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { int expected; float timeExpected_ms; @@ -76,26 +88,17 @@ double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { globalCounter = 0; printf("Start\n"); digitalWriteBounce(OUTpin, HIGH, bounce); - delay(10); - delay(190); + delay(200); + digitalWriteBounce(OUTpin, LOW, bounce); - delay(10); - if (INT_EDGE_BOTH == Edge) { - irq_timstamp_sum += irq_timstamp_duration_ms; - } - delay(90); + DelayAndSumDuration(100, &irq_timstamp_sum, INT_EDGE_BOTH == Edge); + digitalWriteBounce(OUTpin, HIGH, bounce); - delay(10); - if (INT_EDGE_RISING == Edge || INT_EDGE_BOTH == Edge) { - irq_timstamp_sum += irq_timstamp_duration_ms; - } - delay(190); + DelayAndSumDuration(200, &irq_timstamp_sum, INT_EDGE_RISING == Edge || INT_EDGE_BOTH == Edge); + digitalWriteBounce(OUTpin, LOW, bounce); - delay(10); - if (INT_EDGE_FALLING == Edge || INT_EDGE_BOTH == Edge) { - irq_timstamp_sum += irq_timstamp_duration_ms; - } - delay(90); + DelayAndSumDuration(100, &irq_timstamp_sum, INT_EDGE_FALLING == Edge || INT_EDGE_BOTH == Edge); + printf("Stop\n"); int globalCounterCopy = globalCounter; @@ -111,9 +114,9 @@ double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { char str[1024]; float fTime = (gEndTime - gStartTime) / 1000.0; sprintf(str, "IRQ measured %g msec (~%g expected)", fTime, timeExpected_ms); - CheckSameFloat(str, fTime, timeExpected_ms, timeExpected_ms*0.01); + CheckSameFloat(str, fTime, timeExpected_ms, timeExpected_ms*accuracy); sprintf(str, "IRQ timestamp %g msec (~%g expected)", irq_timstamp_sum, timeExpected_ms); - CheckSameFloat(str, irq_timstamp_sum, timeExpected_ms, timeExpected_ms*0.01); + CheckSameFloat(str, irq_timstamp_sum, timeExpected_ms, timeExpected_ms*accuracy); // new data struct CheckSame("GPIO IRQ pin", wfiStatusOld.pinBCM, INpin); if (INT_EDGE_FALLING==Edge || INT_EDGE_RISING==Edge) { @@ -186,7 +189,23 @@ int main (void) { printf("WiringPi GPIO test program 6b (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); printf("ISR and ISR2 test (WiringPi %d.%d)\n", major, minor); - wiringPiSetupGpio() ; + wiringPiSetupGpio(); + + int RaspberryPiModel, rev, mem, maker, overVolted; + piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); + CheckNotSame("Model: ", RaspberryPiModel, -1); + switch(RaspberryPiModel) { + case PI_MODEL_A: + case PI_MODEL_B: //ARM=800MHz + case PI_MODEL_BP: + case PI_MODEL_AP: + case PI_MODEL_CM: + accuracy = 0.02; + break; + default: + accuracy = 0.01; + break; + } if (!piBoard40Pin()) { GPIO = 23; GPIOIN = 24; @@ -194,7 +213,7 @@ int main (void) { int IRQpin = GPIOIN; int OUTpin = GPIO; - wiringPiISR2(13, INT_EDGE_RISING, &ISR2, 0); // next pin + //wiringPiISR2(13, INT_EDGE_RISING, &ISR2, 0); // next pin memset(&wfiStatusOld, 0, sizeof(wfiStatusOld)); @@ -202,7 +221,6 @@ int main (void) { pinMode(OUTpin, OUTPUT); digitalWrite (OUTpin, LOW) ; - /// -------------------- for (int bounce=0; bounce<=1; bounce++) { unsigned long bouncetime = 0; if (0==bounce) { diff --git a/wiringPi/test/wiringpi_test7_bench.c b/wiringPi/test/wiringpi_test7_bench.c index f3eb6e2..316c07e 100644 --- a/wiringPi/test/wiringpi_test7_bench.c +++ b/wiringPi/test/wiringpi_test7_bench.c @@ -66,7 +66,7 @@ int main (void) { case PI_MODEL_ZERO_W: //ARM=1000MHz fExpectTimedigitalWrite = 0.104; //us; fExpectTimedigitalRead = 0.135; //us - fExpectTimepinMode = 0.250; //us + fExpectTimepinMode = 0.280; //us break; case PI_MODEL_2: ToggleValue /= 4; From 31bf218a7c17ed663eedb5c9247e20d826184bf1 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 4 May 2025 12:20:48 +0200 Subject: [PATCH 28/42] #346 unit test irq dection time with debounce --- wiringPi/test/wiringpi_test61_isr2.c | 83 +++++++++++----------------- wiringPi/test/wpi_test.h | 20 +++++++ 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index 5f3bb3f..a2be628 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -131,51 +131,44 @@ double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { } -double DurationTime(int Enge, int OUTpin, int IRQpin, int new) { +double DurationTime(int Enge, int OUTpin, int IRQpin, int bounce) { struct timeval now; double fTime = 0.0; - + const char* strOp = INT_EDGE_RISING == Enge ? "rising" : "fallling"; gStartTime = 0; gEndTime = 0; globalCounter = 0; - printf("Start\n"); + //printf("Start\n"); - if (INT_EDGE_RISING == Enge) { - digitalWrite(OUTpin, LOW); - if (new) { - wiringPiISR2(IRQpin, INT_EDGE_RISING, &ISR2, 0); - } else { - wiringPiISR(IRQpin, INT_EDGE_RISING, &ISR); - } - sleep(1); - gettimeofday(&now, 0); - gStartTime = now.tv_sec*1000000LL + now.tv_usec; - digitalWrite(OUTpin, HIGH); - delay(20); - digitalWrite(OUTpin, LOW); - } else if (INT_EDGE_FALLING == Enge) { - digitalWrite(OUTpin, HIGH); - if (new) { - wiringPiISR2(IRQpin, INT_EDGE_FALLING, &ISR2, 0); - } else { - wiringPiISR(IRQpin, INT_EDGE_FALLING, &ISR); - } - sleep(1); - gettimeofday(&now, 0); - gStartTime = now.tv_sec*1000000LL + now.tv_usec; - digitalWrite(OUTpin, LOW); - } - - sleep(1); - fTime = (gEndTime - gStartTime); - printf("IRQ detect time %g usec", fTime); - if (fTime<2000 && fTime>0) { - printf(" -> %spassed%s\n", COLORGRN, COLORDEF); + digitalWrite(OUTpin, INT_EDGE_RISING == Enge ? LOW : HIGH); + if (bounce>=0) { + printf("\nnew function, bounce time %d ms, %s :\n", bounce, strOp); + wiringPiISR2(IRQpin, Enge, &ISR2, bounce*1000); } else { - printf(" -> %sfailed%s\n", COLORRED, COLORDEF); + printf("\nclassic function, %s :\n", strOp); + wiringPiISR(IRQpin, Enge, &ISR); + } + sleep(1); + gettimeofday(&now, 0); + gStartTime = now.tv_sec*1000000LL + now.tv_usec; + digitalWrite(OUTpin, INT_EDGE_RISING == Enge ? HIGH : LOW); + delay(20); + digitalWrite(OUTpin, LOW); + delay(20); + fTime = (gEndTime - gStartTime); + if (bounce<=0) { + printf("IRQ detection time %g usec", fTime); + } else { + printf("IRQ detection time %.1f msec", fTime/1000.0); + } + if (bounce>=0) { + // bounce time + 7ms (addtional bounce time) + 150 us (basic time) + CheckBetween("IRQ detection time with bounce [us]", fTime, 0, bounce*1000+ (bounce>0 ? 7000 : 0)+(15000*accuracy)); + } else { + CheckBetween("IRQ detection time [us]", fTime, 0, 15000*accuracy); } wiringPiISRStop(IRQpin); - + //printf("Stop\n"); return fTime; } @@ -252,20 +245,10 @@ int main (void) { wiringPiISRStop(IRQpin); } - for (int count=0; count<2; count++) { - printf("\nclassic function:\n"); - printf("=================\n"); - printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); - DurationTime(INT_EDGE_RISING, OUTpin, IRQpin, 0); - printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); - DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin, 0); - - printf("\nnew function:\n"); - printf("===============\n"); - printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); - DurationTime(INT_EDGE_RISING, OUTpin, IRQpin, 1); - printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); - DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin, 1); + printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising and falling\n", IRQpin, OUTpin); + for (int bounce=-1; bounce<=5; bounce++) { + DurationTime(INT_EDGE_RISING, OUTpin, IRQpin, bounce); + DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin, bounce); } pinMode(OUTpin, INPUT); diff --git a/wiringPi/test/wpi_test.h b/wiringPi/test/wpi_test.h index f2eb81a..1a76480 100644 --- a/wiringPi/test/wpi_test.h +++ b/wiringPi/test/wpi_test.h @@ -94,6 +94,15 @@ void CheckNotSame(const char* msg, int value, int expect) { } } +void CheckBetween(const char* msg, int value, int min, int max) { + if (value>=min && value<=max) { + printf("%39s (% 3d< % 3d <% 3d) -> %spassed%s\n", msg, min, value, max, COLORGRN, COLORDEF); + } else { + printf("%39s (% 3d< % 3d <% 3d) -> %sfailed%s\n", msg, min, value, max, COLORRED, COLORDEF); + globalError=1; + } +} + void CheckSameFloat(const char* msg, float value, float expect, float epsilon) { if (fabs(value-expect)=min && value<=max) { + printf("%39s (%g< %g <%g) -> %spassed%s\n", msg, min, value, max, COLORGRN, COLORDEF); + } else { + printf("%39s (%g< %g <%g) -> %sfailed%s\n", msg, min, value, max, COLORRED, COLORDEF); + globalError=1; + } +} + void CheckSameDouble(const char* msg, double value, double expect, double epsilon) { if (fabs(value-expect) %spassed%s \n", msg, value, expect, COLORGRN, COLORDEF); From 08033bc787bea11fa922b717415161b405318e7c Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 4 May 2025 13:42:35 +0200 Subject: [PATCH 29/42] #346 unit test adjust --- wiringPi/test/wiringpi_test61_isr2.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index a2be628..971ed95 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -12,7 +12,8 @@ int GPIO = 19; int GPIOIN = 26; const int ToggleValue = 4; float irq_timstamp_duration_ms = 0; -float accuracy = 0.01; +float accuracy = 0.012; +float bounce_acc = 1.0; static volatile int globalCounter; volatile long long gStartTime, gEndTime; @@ -162,10 +163,10 @@ double DurationTime(int Enge, int OUTpin, int IRQpin, int bounce) { printf("IRQ detection time %.1f msec", fTime/1000.0); } if (bounce>=0) { - // bounce time + 7ms (addtional bounce time) + 150 us (basic time) - CheckBetween("IRQ detection time with bounce [us]", fTime, 0, bounce*1000+ (bounce>0 ? 7000 : 0)+(15000*accuracy)); + // bounce time + 7ms (addtional bounce time) + 100 us (basic time) + CheckBetween("IRQ detection time with bounce [us]", fTime, 0, bounce*1000+ (bounce>0 ? 7000*bounce_acc : 0)+(100*bounce_acc)); } else { - CheckBetween("IRQ detection time [us]", fTime, 0, 15000*accuracy); + CheckBetween("IRQ detection time [us]", fTime, 0, 100*bounce_acc); } wiringPiISRStop(IRQpin); //printf("Stop\n"); @@ -194,9 +195,11 @@ int main (void) { case PI_MODEL_AP: case PI_MODEL_CM: accuracy = 0.02; + bounce_acc = 2.7; break; default: - accuracy = 0.01; + accuracy = 0.012; + bounce_acc = 1.0; break; } if (!piBoard40Pin()) { From d5f0ea06f47b4a79bc4cf321b53912025bbdad8d Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 4 May 2025 19:41:14 +0200 Subject: [PATCH 30/42] #337 ISr user datat and unit test --- wiringPi/test/wiringpi_test61_isr2.c | 35 +++++++++++++++++----------- wiringPi/wiringPi.c | 15 +++++++----- wiringPi/wiringPi.h | 2 +- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index 971ed95..9c37cc0 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -32,10 +32,12 @@ static void ISR(void) { } -static void ISR2(struct WPIWfiStatus wfiStatus) { + +static void ISR2(struct WPIWfiStatus wfiStatus, void* userdata) { struct timeval now; char strEdge[3][10] = {"unknown", "falling", "raising"}; int strEdgeidx = 0; //default + int* localCounter = (int*) userdata; gettimeofday(&now, 0); if (0==gStartTime) { @@ -44,6 +46,9 @@ static void ISR2(struct WPIWfiStatus wfiStatus) { gEndTime = now.tv_sec*1000000LL + now.tv_usec; } globalCounter++; + if (localCounter) { + (*localCounter)++; + } switch(wfiStatus.edge) { case INT_EDGE_FALLING: strEdgeidx = INT_EDGE_FALLING; break; case INT_EDGE_RISING: strEdgeidx = INT_EDGE_RISING; break; @@ -53,8 +58,8 @@ static void ISR2(struct WPIWfiStatus wfiStatus) { } else { irq_timstamp_duration_ms = 0.0f; } - printf("ISR occured @ %lld us: statusOK=%d, pin=%u, edge=%s (%d), duration=%g ms\n", - wfiStatus.timeStamp_us, wfiStatus.statusOK, wfiStatus.pinBCM, strEdge[strEdgeidx], wfiStatus.edge, irq_timstamp_duration_ms); + printf("ISR occured @ %lld us: statusOK=%d, pin=%u, edge=%s (%d), duration=%g ms, userdata=%p\n", + wfiStatus.timeStamp_us, wfiStatus.statusOK, wfiStatus.pinBCM, strEdge[strEdgeidx], wfiStatus.edge, irq_timstamp_duration_ms, userdata); wfiStatusOld = wfiStatus; } @@ -79,7 +84,7 @@ void DelayAndSumDuration(int ms, float* irq_timstamp_sum, const int doSum) { } -double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { +double StartSequence2(int Edge, int OUTpin, int INpin, int bounce, int* localCounter) { int expected; float timeExpected_ms; float irq_timstamp_sum = 0.0f; @@ -87,6 +92,7 @@ double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { gStartTime = 0; gEndTime = 0; globalCounter = 0; + *localCounter = 0; printf("Start\n"); digitalWriteBounce(OUTpin, HIGH, bounce); delay(200); @@ -101,7 +107,7 @@ double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { DelayAndSumDuration(100, &irq_timstamp_sum, INT_EDGE_FALLING == Edge || INT_EDGE_BOTH == Edge); printf("Stop\n"); - int globalCounterCopy = globalCounter; + int globalCounterCopy = globalCounter; if (INT_EDGE_BOTH == Edge) { expected = 4; @@ -111,6 +117,9 @@ double StartSequence2(int Edge, int OUTpin, int INpin, int bounce) { timeExpected_ms = bounce ? 304: 300; } + CheckSame("Global counted IRQ", globalCounter, expected); + CheckSame("Userdata pointer / Local counted IRQ ", *localCounter, expected); + if (globalCounter==expected) { char str[1024]; float fTime = (gEndTime - gStartTime) / 1000.0; @@ -144,7 +153,7 @@ double DurationTime(int Enge, int OUTpin, int IRQpin, int bounce) { digitalWrite(OUTpin, INT_EDGE_RISING == Enge ? LOW : HIGH); if (bounce>=0) { printf("\nnew function, bounce time %d ms, %s :\n", bounce, strOp); - wiringPiISR2(IRQpin, Enge, &ISR2, bounce*1000); + wiringPiISR2(IRQpin, Enge, &ISR2, bounce*1000, NULL); } else { printf("\nclassic function, %s :\n", strOp); wiringPiISR(IRQpin, Enge, &ISR); @@ -210,7 +219,7 @@ int main (void) { int OUTpin = GPIO; //wiringPiISR2(13, INT_EDGE_RISING, &ISR2, 0); // next pin - + int localCounter; memset(&wfiStatusOld, 0, sizeof(wfiStatusOld)); pinMode(IRQpin, INPUT); @@ -227,23 +236,23 @@ int main (void) { } printf("\nTesting IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); - wiringPiISR2(IRQpin, INT_EDGE_RISING, &ISR2, bouncetime); + wiringPiISR2(IRQpin, INT_EDGE_RISING, &ISR2, bouncetime, &localCounter); sleep(1); - StartSequence2(INT_EDGE_RISING, OUTpin, IRQpin, bounce); + StartSequence2(INT_EDGE_RISING, OUTpin, IRQpin, bounce, &localCounter); printf("Stopp IRQ\n"); wiringPiISRStop(IRQpin); printf("\nTesting IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); - wiringPiISR2(IRQpin, INT_EDGE_FALLING, &ISR2, bouncetime); + wiringPiISR2(IRQpin, INT_EDGE_FALLING, &ISR2, bouncetime, &localCounter); sleep(1); - StartSequence2(INT_EDGE_FALLING, OUTpin, IRQpin, bounce); + StartSequence2(INT_EDGE_FALLING, OUTpin, IRQpin, bounce, &localCounter); printf("Stopp IRQ\n"); wiringPiISRStop(IRQpin); printf("\nTesting IRQ @ GPIO%d with trigger @ GPIO%d both\n", IRQpin, OUTpin); - wiringPiISR2(IRQpin, INT_EDGE_BOTH, &ISR2, bouncetime); + wiringPiISR2(IRQpin, INT_EDGE_BOTH, &ISR2, bouncetime, &localCounter); sleep(1); - StartSequence2(INT_EDGE_BOTH, OUTpin, IRQpin, bounce); + StartSequence2(INT_EDGE_BOTH, OUTpin, IRQpin, bounce, &localCounter); printf("Stopp IRQ\n"); wiringPiISRStop(IRQpin); } diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index d9b7c91..b5bfbed 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -491,7 +491,8 @@ static int isrFds [64] = // ISR Data static int chipFd = -1; -static void (*isrFunctionsV2[64])(struct WPIWfiStatus) ; +static void* isrUserdata[64]; +static void (*isrFunctionsV2[64])(struct WPIWfiStatus, void* userdata) ; static void (*isrFunctions [64])(void) ; static pthread_t isrThreads[64]; static int isrEdgeMode[64]; // irq on rising/falling edge @@ -2871,6 +2872,7 @@ int wiringPiISRStop (int pin) { isrFds [pin] = -1; isrFunctions[pin] = NULL; isrFunctionsV2[pin] = NULL; + isrUserdata[pin] = NULL;; isrDebouncePeriodUs[pin] = 0; /* -not closing so far - other isr may be using it - only close if no other is using - will code later @@ -3036,7 +3038,7 @@ void *interruptHandlerV2(void *arg) if (wiringPiDebug) { printf( "interruptHandlerV2: call isr function\n"); } - isrFunctionsV2[pin](wfiStatus); + isrFunctionsV2[pin](wfiStatus, isrUserdata[pin]); if (wiringPiDebug) { printf( "interruptHandlerV2: return from isr function\n"); } @@ -3073,7 +3075,7 @@ void *interruptHandlerV2(void *arg) ********************************************************************************* */ -int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus), void (*functionClassic)(void), unsigned long debounce_period_us) +int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus, void* userdata), void (*functionClassic)(void), unsigned long debounce_period_us, void* userdata) { const int maxpin = GetMaxPin(); @@ -3096,6 +3098,7 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta } isrFunctionsV2[pin] = function; + isrUserdata[pin] = userdata; isrFunctions[pin] = functionClassic; isrEdgeMode[pin] = edgeMode; isrDebouncePeriodUs[pin] = debounce_period_us; @@ -3138,12 +3141,12 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta int wiringPiISR (int pin, int mode, void (*function)(void)) { - return wiringPiISRInternal(pin, mode, NULL, function, 0); + return wiringPiISRInternal(pin, mode, NULL, function, 0, NULL); } -int wiringPiISR2(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us) +int wiringPiISR2(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus, void* userdata), unsigned long debounce_period_us, void* userdata) { - return wiringPiISRInternal(pin, edgeMode, function, NULL, debounce_period_us); + return wiringPiISRInternal(pin, edgeMode, function, NULL, debounce_period_us, userdata); } /* diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 1fe25e5..9ae92d0 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -308,7 +308,7 @@ struct WPIWfiStatus { //extern int waitForInterrupt (int pin, int ms); unknown if still working, disabled for V3.16, please contact developer via github extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; extern struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned long debounce_period_us) ; // V3.16 -extern int wiringPiISR2 (int pin, int mode, void (*function)(struct WPIWfiStatus wfiStatus), unsigned long debounce_period_us) ; // V3.16 +extern int wiringPiISR2 (int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus, void* userdata), unsigned long debounce_period_us, void* userdata) ; // V3.16 extern int wiringPiISRStop (int pin) ; //V3.2 extern int waitForInterruptClose(int pin) ; //V3.2 legacy use wiringPiISRStop From 799b484af0b2c76fbb600f54d720a4c736945f28 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 10 May 2025 11:55:19 +0200 Subject: [PATCH 31/42] #346 gpio wfi unit test --- gpio/test/gpio_test7_wfi.sh | 96 +++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 gpio/test/gpio_test7_wfi.sh diff --git a/gpio/test/gpio_test7_wfi.sh b/gpio/test/gpio_test7_wfi.sh new file mode 100755 index 0000000..7f4ef39 --- /dev/null +++ b/gpio/test/gpio_test7_wfi.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # Reset color + +UNITTEST_OK=true +TIMEOUT=8 +iteration=0 + +wait_with_timeout() { + local pid=$1 + local timeout=$2 + iteration=0 + + while kill -0 "$pid" 2>/dev/null; do + if [ $iteration -ge $timeout ]; then + kill -9 "$pid" 2>/dev/null + echo -e "${RED}ERROR: timeout ${timeout}s reached ${NC}" + return -1 + fi + gpio -g write 19 1 + sleep 1 + echo -n . + gpio -g write 19 0 + iteration=$((iteration + 1)) + done + + wait "$pid" + return $? +} + +echo +echo Unit test gpio GPIO19 and GPIO26 - functions: mode, write, wfi +echo ------------------------------------------------------------------ +echo + +#prepare trigger out +gpio -g mode 19 out +gpio -g write 19 0 + +#wfi test +gpio -g wfi 26 rising & +GPIO_PID=$! +wait_with_timeout "$GPIO_PID" "$TIMEOUT" +EXIT_CODE=$? +echo +if [ $EXIT_CODE -eq 0 ]; then + echo -e "${GREEN}wfi passt (exit code 0)${NC}" +else + echo -e "${RED}wfi failed (exit code $EXIT_CODE)${NC}" + UNITTEST_OK=false +fi + +#wfi iteration test +gpio -g wfi 26 rising 4 & +GPIO_PID=$! +wait_with_timeout "$GPIO_PID" "$TIMEOUT" +EXIT_CODE=$? +echo +if [ $EXIT_CODE -eq 0 ]; then + if [ "$iteration" -eq 5 ]; then + echo -e "${GREEN}wfi iteration passt (exit code 0)${NC}" + else + echo -e "${RED}wfi failed, iteration $iteration wrong${NC}" + UNITTEST_OK=false + fi +else + echo -e "${RED}wfi failed (exit code $EXIT_CODE)${NC}" + UNITTEST_OK=false +fi + +gpio -g write 19 0 +gpio -g mode 19 in + +### #wfi timeout test +gpio -g wfi 26 rising 2 4 & +GPIO_PID=$! +wait_with_timeout "$GPIO_PID" "$TIMEOUT" +EXIT_CODE=$? +echo +if [ $EXIT_CODE -eq 0 ]; then + echo -e "${GREEN}wfi timeout passed (exit code 0)${NC}" +else + echo -e "${RED}wfi timeout failed (code $EXIT_CODE)${NC}" + UNITTEST_OK=false +fi + + +if [ ${UNITTEST_OK} = true ]; then + echo -e "\n\n${GREEN}Unit test result OK.${NC}" + exit 0 +else + echo -e "\n\n${RED}Unit test result failed.${NC}" + exit 1 +fi \ No newline at end of file From b1b896582ec696f235925c62d10ce7b726a61cfa Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 11 May 2025 20:21:39 +0200 Subject: [PATCH 32/42] #346 gpio wfidb command and unit test improvment --- gpio/gpio.c | 135 ++++++++++++++++++++++++++---------- gpio/test/gpio_test7_wfi.sh | 95 +++++++++++++++---------- 2 files changed, 158 insertions(+), 72 deletions(-) diff --git a/gpio/gpio.c b/gpio/gpio.c index 9ffb1b7..9fa5bf6 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -161,7 +161,7 @@ void LOAD_DEPRECATED(const char *progName) { ********************************************************************************* */ -static volatile int iterations ; +static volatile int globalIterations ; static volatile int globalCounter ; void printgpioflush(const char* text) { @@ -179,7 +179,7 @@ void printgpio(const char* text) { static void wfi (void) { globalCounter++; - if(globalCounter>=iterations) { + if(globalCounter>=globalIterations) { printgpio("finished\n"); exit (0) ; } else { @@ -187,40 +187,50 @@ static void wfi (void) { } } -void doWfi (int argc, char *argv []) -{ - int pin, mode; - int timeoutSec = 2147483647; - iterations = 1; +static void wfi2(struct WPIWfiStatus wfiStatus, void* userdata) { + (void)wfiStatus; + (void)userdata; + globalCounter++; + if (globalCounter>=globalIterations) { + printgpio("finished\n"); + exit(0); + } else { + printgpioflush("I"); + } +} + + +int get_wfi_edge(const char* arg_cmd, const char* arg_mode) { + if (strcasecmp (arg_mode, "rising") == 0) { + return INT_EDGE_RISING ; + } else if (strcasecmp (arg_mode, "falling") == 0) { + return INT_EDGE_FALLING ; + } else if (strcasecmp (arg_mode, "both") == 0) { + return INT_EDGE_BOTH ; + } else { + fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", arg_cmd, arg_mode) ; + exit (1); + } +} + + +void doWfiInternal(const char* cmd, int pin, int mode, int interations, int timeoutSec, int debounce) { + + globalIterations = interations; globalCounter = 0; - if (argc != 4 && argc != 5 && argc != 6) - { - fprintf (stderr, "Usage: %s wfi pin mode [interations] [timeout sec.]\n", argv [0]) ; - exit (1) ; - } - - pin = atoi (argv [2]) ; - - /**/ if (strcasecmp (argv [3], "rising") == 0) mode = INT_EDGE_RISING ; - else if (strcasecmp (argv [3], "falling") == 0) mode = INT_EDGE_FALLING ; - else if (strcasecmp (argv [3], "both") == 0) mode = INT_EDGE_BOTH ; - else - { - fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ; - exit (1) ; - } - if (argc>=5) { - iterations = atoi(argv [4]); - } - if (argc>=6) { - timeoutSec = atoi(argv [5]); - } - - if (wiringPiISR (pin, mode, &wfi) < 0) - { - fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ; - exit (1) ; + if (debounce>=0) { + // V2 function + if (wiringPiISR2(pin, mode, &wfi2, debounce, NULL) < 0) { + fprintf (stderr, "%s: Unable to setup ISR2: %s\n", cmd, strerror (errno)); + exit(1); + } + } else { + // classic function + if (wiringPiISR(pin, mode, &wfi) < 0) { + fprintf (stderr, "%s: Unable to setup ISR: %s\n", cmd, strerror (errno)); + exit(1); + } } printgpio("wait for interrupt function call\n"); @@ -229,7 +239,56 @@ void doWfi (int argc, char *argv []) delay (999); } printgpio("\nstopping wait for interrupt\n"); - wiringPiISRStop (pin); + wiringPiISRStop(pin); +} + + +void doWfi(int argc, char *argv []) +{ + int pin, mode, interations=1; + int timeoutSec = 2147483647; + + if (argc != 4 && argc != 5 && argc != 6) { + fprintf (stderr, "Usage: %s wfi pin mode [interations] [timeout sec.]\n", argv [0]) ; + exit (1) ; + } + + pin = atoi (argv[2]) ; + mode = get_wfi_edge(argv[1], argv[3]); + if (argc>=5) { + interations = atoi(argv[4]); + } + if (argc>=6) { + timeoutSec = atoi(argv[5]); + } + + doWfiInternal(argv[1], pin, mode, interations, timeoutSec, -1); +} + + +void doWfi2(int argc, char *argv []) +{ + int pin, mode, interations=1, debounce=50000; + int timeoutSec = 2147483647; + + if (argc != 4 && argc != 5 && argc != 6 && argc != 7) { + fprintf (stderr, "Usage: %s wfidb pin mode [debounce period microsec.] [interations] [timeout sec.]\n", argv [0]) ; + exit(1); + } + + pin = atoi (argv[2]) ; + mode = get_wfi_edge(argv[1], argv[3]); + if (argc>=5) { + debounce = atoi(argv[4]); + } + if (argc>=6) { + interations = atoi(argv[5]); + } + if (argc>=7) { + timeoutSec = atoi(argv[6]); + } + + doWfiInternal(argv[1], pin, mode, interations, timeoutSec, debounce); } @@ -896,6 +955,10 @@ static void doVersion (char *argv []) } +static void doIs40Pin () +{ + exit(piBoard40Pin()); +} /* * main: @@ -1130,7 +1193,9 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ; else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ; else if (strcasecmp (argv [1], "clock" ) == 0) doClock (argc, argv) ; + else if (strcasecmp (argv [1], "wfidb" ) == 0) doWfi2 (argc, argv) ; else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; + else if (strcasecmp (argv [1], "is40pin" ) == 0) doIs40Pin () ; else { fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ; diff --git a/gpio/test/gpio_test7_wfi.sh b/gpio/test/gpio_test7_wfi.sh index 7f4ef39..a5d2298 100755 --- a/gpio/test/gpio_test7_wfi.sh +++ b/gpio/test/gpio_test7_wfi.sh @@ -7,22 +7,26 @@ NC='\033[0m' # Reset color UNITTEST_OK=true TIMEOUT=8 iteration=0 +GPIOIN=26 +GPIOOUT=19 wait_with_timeout() { local pid=$1 local timeout=$2 iteration=0 + local toggle=0 while kill -0 "$pid" 2>/dev/null; do if [ $iteration -ge $timeout ]; then kill -9 "$pid" 2>/dev/null echo -e "${RED}ERROR: timeout ${timeout}s reached ${NC}" return -1 fi - gpio -g write 19 1 - sleep 1 echo -n . - gpio -g write 19 0 + sleep 1 + toggle=$((1 - toggle)) + gpio -g write $GPIOOUT $toggle + echo -n ${toggle} iteration=$((iteration + 1)) done @@ -30,51 +34,68 @@ wait_with_timeout() { return $? } +wfi_test() { + local edge=$1 + local set_iter=$2 + local set_iterOK=$3 + + #wfi test + if [ $iteration -eq 0 ]; then + gpio -g wfi $GPIOIN "$edge" & + else + gpio -g wfi $GPIOIN "$edge" "$set_iter" & + fi + GPIO_PID=$! + wait_with_timeout "$GPIO_PID" "$TIMEOUT" + EXIT_CODE=$? + echo + if [ $EXIT_CODE -eq 0 ]; then + if [ "$set_iter" -gt 0 ]; then + if [ "$iteration" -eq "$set_iterOK" ]; then + echo -e "${GREEN}wfi "$edge" $set_iter iteration passt (exit code 0)${NC}" + else + echo -e "${RED}wfi "$edge" failed, $iteration iterations of $set_iter is wrong${NC}" + UNITTEST_OK=false + fi + else + echo -e "${GREEN}wfi "$edge" passt (exit code 0)${NC}" + fi + else + echo -e "${RED}wfi "$edge" failed (exit code $EXIT_CODE)${NC}" + UNITTEST_OK=false + fi +} + echo -echo Unit test gpio GPIO19 and GPIO26 - functions: mode, write, wfi +echo Unit test gpio GPIO${GPIOOUT} and GPIO${GPIOIN} - functions: mode, write, wfi echo ------------------------------------------------------------------ echo #prepare trigger out -gpio -g mode 19 out -gpio -g write 19 0 +gpio -g mode $GPIOOUT out -#wfi test -gpio -g wfi 26 rising & -GPIO_PID=$! -wait_with_timeout "$GPIO_PID" "$TIMEOUT" -EXIT_CODE=$? -echo -if [ $EXIT_CODE -eq 0 ]; then - echo -e "${GREEN}wfi passt (exit code 0)${NC}" -else - echo -e "${RED}wfi failed (exit code $EXIT_CODE)${NC}" - UNITTEST_OK=false -fi +gpio -g write $GPIOOUT 0 +wfi_test "rising" 0 0 + +gpio -g write $GPIOOUT 1 +wfi_test "falling" 0 0 #wfi iteration test -gpio -g wfi 26 rising 4 & -GPIO_PID=$! -wait_with_timeout "$GPIO_PID" "$TIMEOUT" -EXIT_CODE=$? -echo -if [ $EXIT_CODE -eq 0 ]; then - if [ "$iteration" -eq 5 ]; then - echo -e "${GREEN}wfi iteration passt (exit code 0)${NC}" - else - echo -e "${RED}wfi failed, iteration $iteration wrong${NC}" - UNITTEST_OK=false - fi -else - echo -e "${RED}wfi failed (exit code $EXIT_CODE)${NC}" - UNITTEST_OK=false -fi -gpio -g write 19 0 -gpio -g mode 19 in +gpio -g write $GPIOOUT 0 +wfi_test "rising" 4 7 + +gpio -g write $GPIOOUT 1 +wfi_test "falling" 4 8 + +gpio -g write $GPIOOUT 0 +wfi_test "both" 4 4 + +gpio -g write $GPIOOUT 0 +gpio -g mode $GPIOOUT in ### #wfi timeout test -gpio -g wfi 26 rising 2 4 & +gpio -g wfi $GPIOIN rising 2 4 & GPIO_PID=$! wait_with_timeout "$GPIO_PID" "$TIMEOUT" EXIT_CODE=$? From 2f52fa27e5e119dd8d4490e82221341e0ff58364 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 16 May 2025 18:31:28 +0200 Subject: [PATCH 33/42] #264 gpio wfis & unit test --- gpio/gpio.c | 39 ++++--- .../{gpio_test7_wfi.sh => gpio_test6_wfi.sh} | 100 +++++++++++++++++- 2 files changed, 126 insertions(+), 13 deletions(-) rename gpio/test/{gpio_test7_wfi.sh => gpio_test6_wfi.sh} (52%) diff --git a/gpio/gpio.c b/gpio/gpio.c index 9fa5bf6..2f6b683 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -181,7 +181,7 @@ static void wfi (void) { globalCounter++; if(globalCounter>=globalIterations) { printgpio("finished\n"); - exit (0) ; + exit(0); } else { printgpioflush("I"); } @@ -193,15 +193,25 @@ static void wfi2(struct WPIWfiStatus wfiStatus, void* userdata) { (void)userdata; globalCounter++; if (globalCounter>=globalIterations) { - printgpio("finished\n"); - exit(0); + switch(wfiStatus.edge) { + case INT_EDGE_FALLING: + printgpio("finished falling\n"); + break; + case INT_EDGE_RISING: + printgpio("finished rising\n"); + break; + default: + printgpio("finished\n"); + break; + } + exit(wfiStatus.edge); } else { printgpioflush("I"); } } -int get_wfi_edge(const char* arg_cmd, const char* arg_mode) { +int get_wfi_edge(const char* arg_cmd, const char* arg_mode, int exitcode) { if (strcasecmp (arg_mode, "rising") == 0) { return INT_EDGE_RISING ; } else if (strcasecmp (arg_mode, "falling") == 0) { @@ -210,7 +220,7 @@ int get_wfi_edge(const char* arg_cmd, const char* arg_mode) { return INT_EDGE_BOTH ; } else { fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", arg_cmd, arg_mode) ; - exit (1); + exit(exitcode); } } @@ -236,7 +246,7 @@ void doWfiInternal(const char* cmd, int pin, int mode, int interations, int time printgpio("wait for interrupt function call\n"); for (int Sec=0; Sec=5) { interations = atoi(argv[4]); } @@ -272,12 +282,12 @@ void doWfi2(int argc, char *argv []) int timeoutSec = 2147483647; if (argc != 4 && argc != 5 && argc != 6 && argc != 7) { - fprintf (stderr, "Usage: %s wfidb pin mode [debounce period microsec.] [interations] [timeout sec.]\n", argv [0]) ; - exit(1); + fprintf (stderr, "Usage: %s wfis pin mode [debounce period microsec.] [interations] [timeout sec.]\n", argv [0]); + exit(-2); } pin = atoi (argv[2]) ; - mode = get_wfi_edge(argv[1], argv[3]); + mode = get_wfi_edge(argv[1], argv[3], -1); if (argc>=5) { debounce = atoi(argv[4]); } @@ -287,8 +297,13 @@ void doWfi2(int argc, char *argv []) if (argc>=7) { timeoutSec = atoi(argv[6]); } + if (timeoutSec<0 || interations<0 || debounce<0) { + fprintf (stderr, " invalid parameter\n"); + exit(-2); + } doWfiInternal(argv[1], pin, mode, interations, timeoutSec, debounce); + exit(-1); // timeout } @@ -1193,7 +1208,7 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ; else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ; else if (strcasecmp (argv [1], "clock" ) == 0) doClock (argc, argv) ; - else if (strcasecmp (argv [1], "wfidb" ) == 0) doWfi2 (argc, argv) ; + else if (strcasecmp (argv [1], "wfis" ) == 0) doWfi2 (argc, argv) ; else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; else if (strcasecmp (argv [1], "is40pin" ) == 0) doIs40Pin () ; else diff --git a/gpio/test/gpio_test7_wfi.sh b/gpio/test/gpio_test6_wfi.sh similarity index 52% rename from gpio/test/gpio_test7_wfi.sh rename to gpio/test/gpio_test6_wfi.sh index a5d2298..89f37e0 100755 --- a/gpio/test/gpio_test7_wfi.sh +++ b/gpio/test/gpio_test6_wfi.sh @@ -9,6 +9,7 @@ TIMEOUT=8 iteration=0 GPIOIN=26 GPIOOUT=19 +DEBOUNCE=100000 wait_with_timeout() { local pid=$1 @@ -27,6 +28,7 @@ wait_with_timeout() { toggle=$((1 - toggle)) gpio -g write $GPIOOUT $toggle echo -n ${toggle} + sleep 0.2 iteration=$((iteration + 1)) done @@ -39,7 +41,7 @@ wfi_test() { local set_iter=$2 local set_iterOK=$3 - #wfi test + #wfi call if [ $iteration -eq 0 ]; then gpio -g wfi $GPIOIN "$edge" & else @@ -66,6 +68,48 @@ wfi_test() { fi } +wfis_test() { + local edge=$1 + local set_iter=$2 + local set_iterOK=$3 + local set_EXITCODE=$4 + + #wfis call + if [ $iteration -eq 0 ]; then + gpio -g wfis $GPIOIN "$edge" $DEBOUNCE & + else + gpio -g wfis $GPIOIN "$edge" $DEBOUNCE "$set_iter" & + fi + GPIO_PID=$! + wait_with_timeout "$GPIO_PID" "$TIMEOUT" + EXIT_CODE=$? + echo + if [ $EXIT_CODE -lt 3 ]; then + + if [ $EXIT_CODE -eq "$set_EXITCODE" ]; then + + if [ "$set_iter" -gt 0 ]; then + if [ "$iteration" -eq "$set_iterOK" ]; then + echo -e "${GREEN}wfis "$edge" $set_iter iteration passt (exit code $EXIT_CODE)${NC}" + else + echo -e "${RED}wfis "$edge" failed, $iteration iterations of $set_iter is wrong${NC}" + UNITTEST_OK=false + fi + else + echo -e "${GREEN}wfi "$edge" passt (exit code $EXIT_CODE)${NC}" + fi + + else + echo -e "${RED}wfis "$edge" failed - wrong exit code $EXIT_CODE${NC}" + UNITTEST_OK=false + fi + + else # negativ + echo -e "${RED}wfis "$edge" failed (exit code $EXIT_CODE)${NC}" + UNITTEST_OK=false + fi +} + echo echo Unit test gpio GPIO${GPIOOUT} and GPIO${GPIOIN} - functions: mode, write, wfi echo ------------------------------------------------------------------ @@ -108,6 +152,60 @@ else fi +echo +echo Unit test gpio GPIO${GPIOOUT} and GPIO${GPIOIN} - functions: mode, write, wfis +echo ------------------------------------------------------------------ +echo + +#prepare trigger out +gpio -g mode $GPIOOUT out + +gpio -g write $GPIOOUT 1 +wfis_test "rising" 0 0 2 + +gpio -g write $GPIOOUT 0 +wfis_test "falling" 0 0 1 + +gpio -g write $GPIOOUT 1 +wfis_test "both" 0 0 1 + +gpio -g write $GPIOOUT 0 +wfis_test "both" 0 0 2 + + +#wfi iteration test + +gpio -g write $GPIOOUT 0 +wfis_test "rising" 4 7 2 + +gpio -g write $GPIOOUT 1 +wfis_test "falling" 4 8 1 + +gpio -g write $GPIOOUT 0 +wfis_test "both" 3 3 2 + +gpio -g write $GPIOOUT 1 +wfis_test "both" 3 4 1 + +gpio -g write $GPIOOUT 0 +gpio -g mode $GPIOOUT in + +### #wfi timeout test +gpio -g wfis $GPIOIN rising $DEBOUNCE 2 4 & +GPIO_PID=$! +wait_with_timeout "$GPIO_PID" "$TIMEOUT" +EXIT_CODE=$? +echo +if [ $EXIT_CODE -eq 255 ]; then + echo -e "${GREEN}wfi timeout passed (exit code $EXIT_CODE)${NC}" +else + echo -e "${RED}wfi timeout failed (code $EXIT_CODE)${NC}" + UNITTEST_OK=false +fi + + + + if [ ${UNITTEST_OK} = true ]; then echo -e "\n\n${GREEN}Unit test result OK.${NC}" exit 0 From 18fc04d7f268402399c4c0b1f1b5c8793f7cc72d Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 18 May 2025 21:17:09 +0200 Subject: [PATCH 34/42] #322 check pin numbers after convert to BCM --- wiringPi/test/Makefile | 5 +- wiringPi/test/wiringpi_test62_isr_wpin.c | 114 +++++++++++ wiringPi/wiringPi.c | 248 ++++++++++++----------- wiringPi/wiringPi.h | 4 +- 4 files changed, 254 insertions(+), 117 deletions(-) create mode 100644 wiringPi/test/wiringpi_test62_isr_wpin.c diff --git a/wiringPi/test/Makefile b/wiringPi/test/Makefile index 0b68f96..40cbd25 100644 --- a/wiringPi/test/Makefile +++ b/wiringPi/test/Makefile @@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = # Need BCM19 <-> BCM26, +PWM: BCM12 <-> BCM13, BCM18 <-> BCM17 connected (1kOhm) -tests = wiringpi_test0_version wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiringpi_test4_device_phys wiringpi_test5_default wiringpi_test6_isr wiringpi_test61_isr2 wiringpi_test7_bench wiringpi_test8_pwm wiringpi_test9_pwm +tests = wiringpi_test0_version wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiringpi_test4_device_phys wiringpi_test5_default wiringpi_test6_isr wiringpi_test61_isr2 wiringpi_test62_isr_wpin wiringpi_test7_bench wiringpi_test8_pwm wiringpi_test9_pwm # Need XO hardware xotests = wiringpi_xotest_test1_spi wiringpi_i2c_test1_pcf8574 wiringpi_test8_pwm wiringpi_test9_pwm @@ -37,6 +37,9 @@ wiringpi_test6_isr: wiringpi_test61_isr2: ${CC} ${CFLAGS} wiringpi_test61_isr2.c -o wiringpi_test61_isr2 -lwiringPi +wiringpi_test62_isr_wpin: + ${CC} ${CFLAGS} wiringpi_test62_isr_wpin.c -o wiringpi_test62_isr_wpin -lwiringPi + wiringpi_test7_bench: ${CC} ${CFLAGS} wiringpi_test7_bench.c -o wiringpi_test7_bench -lwiringPi diff --git a/wiringPi/test/wiringpi_test62_isr_wpin.c b/wiringPi/test/wiringpi_test62_isr_wpin.c new file mode 100644 index 0000000..7447c35 --- /dev/null +++ b/wiringPi/test/wiringpi_test62_isr_wpin.c @@ -0,0 +1,114 @@ +// WiringPi test program: Kernel char device interface / sysfs successor +// Compile: gcc -Wall wiringpi_test62_isr_wpin.c -o wiringpi_test62_isr_wpin -lwiringPi + +#include "wpi_test.h" +#include +#include +#include +#include + +//WPI pin numbers +int GPIO = 28; +int GPIOIN = 29; + +static volatile int globalCounter; + + +static void wfiup(void) { + + globalCounter++; + printf("I[%d] ", globalCounter); + fflush(stdout); +} + +static void wfidown(void) { + + globalCounter--; + printf("I[%d] ", globalCounter); + fflush(stdout); +} + + +void StartSequence (int Enge, int OUTpin, int count,int expected) { + /* + int expected = up ? count : 0; + globalCounter = up ? 0 : count; + */ + globalCounter = 0; + + printf("Start: "); + fflush(stdout); + for (int loop=0; loop 28\n"); + + printf("\nWiringPi %d.%d\n", major, minor); + + //printf("Error check - next call create fatal error with exit!\n"); + //CheckSame("wiringPiISRStop with wrong pin, result code:", wiringPiISRStop(5), 0); + + CheckSame("wiringPiSetupPinType(WPI_PIN_WPI)", wiringPiSetupPinType(WPI_PIN_WPI), 0); + + int rev, mem, maker, overVolted, RaspberryPiModel; + piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); + + CheckNotSame("piBoardId", RaspberryPiModel, 0); + + int IRQpin = GPIOIN; + int OUTpin = GPIO; + + if (RaspberryPiModel==PI_MODEL_4B) { + pinMode(IRQpin, INPUT); + pinMode(OUTpin, OUTPUT); + digitalWrite (OUTpin, LOW) ; + + printf("\nTesting IRQ @ WPI-GPIO%d with trigger @ WPI-GPIO%d rising\n", IRQpin, OUTpin); + CheckSame("wiringPiISR", wiringPiISR(IRQpin, INT_EDGE_RISING, &wfiup), 0); + sleep(1); + StartSequence(INT_EDGE_RISING, OUTpin, 3 , 3); + sleep(1); + CheckSame("wiringPiISRStop", wiringPiISRStop(IRQpin), 0); + printf("\n.IRQ off\n"); + sleep(1); + StartSequence(INT_EDGE_RISING, OUTpin, 2, 0); + + printf("\nTesting IRQ @ WPI-GPIO%d with trigger @ WPI-GPIO%d falling\n", IRQpin, OUTpin); + CheckSame("wiringPiISR", wiringPiISR(IRQpin, INT_EDGE_RISING, &wfidown), 0); + sleep(1); + StartSequence(INT_EDGE_FALLING, OUTpin, 4, -4); + sleep(1); + CheckSame("wiringPiISRStop", wiringPiISRStop(IRQpin), 0); + printf("\n.IRQ off\n"); + sleep(1); + StartSequence(INT_EDGE_RISING, OUTpin, 2, 0); + + printf("Error check - next call must be wrong!\n"); + CheckSame("wiringPiISRStop with wrong pin, result code:", wiringPiISRStop(5555), EINVAL); + + pinMode(OUTpin, INPUT); + } + + return UnitTestState(); +} diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index b5bfbed..f2e8252 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -646,6 +646,7 @@ int piBoard40Pin() { } } + int piRP1Model() { switch(RaspberryPiModel){ case PI_MODEL_5: @@ -658,8 +659,43 @@ int piRP1Model() { } } + int GetMaxPin() { - return piRP1Model() ? 27 : 63; + if (piRP1Model()) { + switch(wiringPiMode) { + case WPI_MODE_PHYS: + return 40; + case WPI_MODE_PINS: + return 31; + default: + return 27; + } + } else { + return 63; + } +} + + +int ToBCMPin(int* pin) { + if (*pin<0 || *pin>63) { + return FALSE; + } + switch(wiringPiMode) { + case WPI_MODE_PINS: + *pin = pinToGpio[*pin]; + break; + case WPI_MODE_PHYS: + *pin = physToGpio[*pin]; + break; + case WPI_MODE_GPIO: + return TRUE; + default: + return FALSE; + } + if (piRP1Model() && *pin>27) { + return FALSE; + } + return TRUE; } @@ -1286,8 +1322,9 @@ int physPinToGpio (int physPin) ********************************************************************************* */ void setPadDrivePin (int pin, int value) { - if (!piRP1Model()) return; - if (pin < 0 || pin > GetMaxPin()) return ; + if (!piRP1Model() || !ToBCMPin(&pin)) { + return; + } uint32_t wrVal; value = value & 3; // 0-3 supported @@ -1368,14 +1405,9 @@ int getAlt (int pin) { int alt; - pin &= 63 ; - - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return 0 ; + if (!ToBCMPin(&pin)) { + return 0; + } if (piRP1Model()) { alt = (gpio[2*pin+1] & RP1_FSEL_NONE_HW); //0-4 function @@ -1586,14 +1618,9 @@ void gpioClockSet (int pin, int freq) int divi, divr, divf ; FailOnModel5("gpioClockSet"); - pin &= 63 ; - - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; + if (!ToBCMPin(&pin)) { + return; + } divi = 19200000 / freq ; divr = 19200000 % freq ; @@ -1848,65 +1875,58 @@ void pinModeAlt (int pin, int mode) { setupCheck ("pinModeAlt") ; - if ((pin & PI_GPIO_MASK) == 0) // On-board pin - { - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; - - if (piRP1Model()) { - //confusion! diffrent to to BCM! this is taking directly the value for the register - int modeRP1; - switch(mode) { - case FSEL_ALT0: - modeRP1 = 0; - break; - case FSEL_ALT1: - modeRP1 = 1; - break; - case FSEL_ALT2: - modeRP1 = 2; - break; - case FSEL_ALT3: - modeRP1 = 3; - break; - case FSEL_ALT4: - modeRP1 = 4; - break; - case FSEL_ALT5: - modeRP1 = 5; - break; - case FSEL_ALT6: - modeRP1 = 6; - break; - case FSEL_ALT7: - modeRP1 = 7; - break; - case FSEL_ALT8: - modeRP1 = 8; - break; - case FSEL_OUTP: - case FSEL_INPT: - modeRP1 = RP1_FSEL_GPIO; - break; - default: - fprintf(stderr, "pinModeAlt: invalid mode %d\n", mode); - return; - } - //printf("pinModeAlt: Pi5 alt pin %d to %d\n", pin, modeRP1); - gpio[2*pin+1] = (modeRP1 & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time - } else { - int fSel = gpioToGPFSEL [pin] ; - int shift = gpioToShift [pin] ; - - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; - } - + if (!ToBCMPin(&pin)) { + return; } -} + + if (piRP1Model()) { + //confusion! diffrent to to BCM! this is taking directly the value for the register + int modeRP1; + switch(mode) { + case FSEL_ALT0: + modeRP1 = 0; + break; + case FSEL_ALT1: + modeRP1 = 1; + break; + case FSEL_ALT2: + modeRP1 = 2; + break; + case FSEL_ALT3: + modeRP1 = 3; + break; + case FSEL_ALT4: + modeRP1 = 4; + break; + case FSEL_ALT5: + modeRP1 = 5; + break; + case FSEL_ALT6: + modeRP1 = 6; + break; + case FSEL_ALT7: + modeRP1 = 7; + break; + case FSEL_ALT8: + modeRP1 = 8; + break; + case FSEL_OUTP: + case FSEL_INPT: + modeRP1 = RP1_FSEL_GPIO; + break; + default: + fprintf(stderr, "pinModeAlt: invalid mode %d\n", mode); + return; + } + //printf("pinModeAlt: Pi5 alt pin %d to %d\n", pin, modeRP1); + gpio[2*pin+1] = (modeRP1 & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time + } else { + int fSel = gpioToGPFSEL [pin] ; + int shift = gpioToShift [pin] ; + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; + } + } /* @@ -2447,12 +2467,9 @@ void pwmWrite (int pin, int value) if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; + if (!ToBCMPin(&pin)) { + return; + } /* would be possible on ms mode but not on bal, deactivated, use pwmc modify instead if (piGpioBase == GPIO_PERI_BASE_2711) { @@ -2677,15 +2694,9 @@ struct WPIWfiStatus waitForInterrupt2(int pin, int edgeMode, int ms, unsigned lo 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) { + if (wiringPiGpioDeviceGetFd()<0 || !ToBCMPin(&pin)) { wfiStatus.statusOK = -1; return wfiStatus; } @@ -2844,12 +2855,24 @@ int waitForInterrupt (int pin, int ms) { ********************************************************************************* */ -int wiringPiISRStop (int pin) { - void *res; - +int wiringPiISRStop(int pin) { + + if (wiringPiMode == WPI_MODE_UNINITIALISED) { + return wiringPiFailure(WPI_FATAL, "wiringPiISRStop: wiringPi has not been initialised. Unable to continue.\n"); + } + if (!ToBCMPin(&pin)) { + fprintf(stderr, "wiringPiISRStop: wrong pin %d (mode: %d) number!\n", pin, wiringPiMode); + return EINVAL; + } + if (wiringPiDebug) { + printf("wiringPiISRStop: pin %d\n", pin) ; + } + if (isrFds[pin] > 0) { + void *res; + if (wiringPiDebug) - printf ("wiringPiISRStop: close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; + printf("wiringPiISRStop: close thread 0x%lX\n", (unsigned long)isrThreads[pin]); if (isrThreads[pin] != 0) { if (pthread_cancel(isrThreads[pin]) == 0) { @@ -2864,10 +2887,13 @@ int wiringPiISRStop (int pin) { } } else { if (wiringPiDebug) - printf ("wiringPiISRStop: could not cancel thread\n"); + printf("wiringPiISRStop: could not cancel thread\n"); } } close(isrFds [pin]); + } else { + if (wiringPiDebug) + printf("wiringPiISRStop: Warning stop isr, but its not active\n"); } isrFds [pin] = -1; isrFunctions[pin] = NULL; @@ -2882,7 +2908,7 @@ int wiringPiISRStop (int pin) { chipFd = -1; */ if (wiringPiDebug) { - printf ("wiringPiISRStop: wiringPiISRStop finished\n") ; + printf("wiringPiISRStop: wiringPiISRStop finished\n"); } return 0; } @@ -3077,24 +3103,18 @@ void *interruptHandlerV2(void *arg) int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiStatus wfiStatus, void* userdata), void (*functionClassic)(void), unsigned long debounce_period_us, void* userdata) { - const int maxpin = GetMaxPin(); - - if (pin < 0 || pin > maxpin) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-%d (%d)\n", maxpin, pin) ; - if (wiringPiMode == WPI_MODE_UNINITIALISED) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; - - if (wiringPiMode == WPI_MODE_PINS) { - pin = pinToGpio [pin] ; - } else if (wiringPiMode == WPI_MODE_PHYS) { - pin = physToGpio [pin] ; + if (wiringPiMode == WPI_MODE_UNINITIALISED) { + return wiringPiFailure(WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n"); + } + if (!ToBCMPin(&pin)) { + fprintf(stderr, "wiringPiISRStop: wrong pin %d (mode: %d) number!\n", pin, wiringPiMode); + return EINVAL; } - if (wiringPiDebug) { - printf ("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode) ; + printf("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode); } - if (isrFunctions[pin] || isrFunctionsV2[pin] ) { - printf ("wiringPi: ISR function already active, ignoring \n") ; + if (isrFunctions[pin] || isrFunctionsV2[pin]) { + fprintf(stderr, "wiringPi: ISR function already active, ignoring \n"); } isrFunctionsV2[pin] = function; @@ -3104,7 +3124,7 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta isrDebouncePeriodUs[pin] = debounce_period_us; if (wiringPiDebug) { - printf ("wiringPi: mutex in\n") ; + printf("wiringPi: mutex in\n"); } pthread_mutex_lock (&pinMutex) ; pinPass = pin ; @@ -3129,12 +3149,12 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta } if (wiringPiDebug) { - printf ("wiringPi: mutex out\n") ; + printf("wiringPi: mutex out\n"); } pthread_mutex_unlock (&pinMutex) ; if (wiringPiDebug) { - printf ("wiringPi: wiringPiISR finished\n") ; + printf("wiringPi: wiringPiISR finished\n"); } return 0 ; } diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 9ae92d0..e9be5a2 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -281,8 +281,8 @@ extern int piBoardRev (void) ; // Deprecated, but does the sa extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; extern int piBoard40Pin (void) ; // Interface V3.7 extern int piRP1Model (void) ; // Interface V3.14 -extern int wpiPinToGpio (int wpiPin) ; -extern int physPinToGpio (int physPin) ; +extern int wpiPinToGpio (int wpiPin) ; // please don't use outside 0-63 and on RP1 +extern int physPinToGpio (int physPin) ; // please don't use outside 0-63 and on RP1 extern void setPadDrive (int group, int value) ; extern void setPadDrivePin (int pin, int value); // Interface V3.0 extern int getAlt (int pin) ; From b87ca97daf913a8190c803f5b980a427953d78af Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 23 May 2025 19:51:01 +0200 Subject: [PATCH 35/42] #264 adjust unit test and fix is40pin --- gpio/gpio.c | 2 +- gpio/test/gpio_test6_wfi.sh | 4 ++ wiringPi/test/wiringpi_test61_isr2.c | 2 +- wiringPi/test/wiringpi_test62_isr_wpin.c | 58 +++++++++++++----------- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/gpio/gpio.c b/gpio/gpio.c index 2f6b683..a420cd3 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -972,7 +972,7 @@ static void doVersion (char *argv []) static void doIs40Pin () { - exit(piBoard40Pin()); + exit(piBoard40Pin() ? EXIT_SUCCESS : EXIT_FAILURE); } /* diff --git a/gpio/test/gpio_test6_wfi.sh b/gpio/test/gpio_test6_wfi.sh index 89f37e0..5a0d6af 100755 --- a/gpio/test/gpio_test6_wfi.sh +++ b/gpio/test/gpio_test6_wfi.sh @@ -110,11 +110,15 @@ wfis_test() { fi } +gpio is40pin || { GPIOIN=17; GPIOOUT=18; echo "old 28 pin system"; } + + echo echo Unit test gpio GPIO${GPIOOUT} and GPIO${GPIOIN} - functions: mode, write, wfi echo ------------------------------------------------------------------ echo + #prepare trigger out gpio -g mode $GPIOOUT out diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index 9c37cc0..e0d21f5 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -12,7 +12,7 @@ int GPIO = 19; int GPIOIN = 26; const int ToggleValue = 4; float irq_timstamp_duration_ms = 0; -float accuracy = 0.012; +float accuracy = 0.015; float bounce_acc = 1.0; static volatile int globalCounter; diff --git a/wiringPi/test/wiringpi_test62_isr_wpin.c b/wiringPi/test/wiringpi_test62_isr_wpin.c index 7447c35..00a599a 100644 --- a/wiringPi/test/wiringpi_test62_isr_wpin.c +++ b/wiringPi/test/wiringpi_test62_isr_wpin.c @@ -79,35 +79,41 @@ int main (void) { int IRQpin = GPIOIN; int OUTpin = GPIO; - if (RaspberryPiModel==PI_MODEL_4B) { - pinMode(IRQpin, INPUT); - pinMode(OUTpin, OUTPUT); - digitalWrite (OUTpin, LOW) ; - - printf("\nTesting IRQ @ WPI-GPIO%d with trigger @ WPI-GPIO%d rising\n", IRQpin, OUTpin); - CheckSame("wiringPiISR", wiringPiISR(IRQpin, INT_EDGE_RISING, &wfiup), 0); - sleep(1); - StartSequence(INT_EDGE_RISING, OUTpin, 3 , 3); - sleep(1); - CheckSame("wiringPiISRStop", wiringPiISRStop(IRQpin), 0); - printf("\n.IRQ off\n"); - sleep(1); - StartSequence(INT_EDGE_RISING, OUTpin, 2, 0); + switch(RaspberryPiModel) { + case PI_MODEL_4B: + case PI_MODEL_5: + pinMode(IRQpin, INPUT); + pinMode(OUTpin, OUTPUT); + digitalWrite (OUTpin, LOW) ; - printf("\nTesting IRQ @ WPI-GPIO%d with trigger @ WPI-GPIO%d falling\n", IRQpin, OUTpin); - CheckSame("wiringPiISR", wiringPiISR(IRQpin, INT_EDGE_RISING, &wfidown), 0); - sleep(1); - StartSequence(INT_EDGE_FALLING, OUTpin, 4, -4); - sleep(1); - CheckSame("wiringPiISRStop", wiringPiISRStop(IRQpin), 0); - printf("\n.IRQ off\n"); - sleep(1); - StartSequence(INT_EDGE_RISING, OUTpin, 2, 0); + printf("\nTesting IRQ @ WPI-GPIO%d with trigger @ WPI-GPIO%d rising\n", IRQpin, OUTpin); + CheckSame("wiringPiISR", wiringPiISR(IRQpin, INT_EDGE_RISING, &wfiup), 0); + sleep(1); + StartSequence(INT_EDGE_RISING, OUTpin, 3 , 3); + sleep(1); + CheckSame("wiringPiISRStop", wiringPiISRStop(IRQpin), 0); + printf("\n.IRQ off\n"); + sleep(1); + StartSequence(INT_EDGE_RISING, OUTpin, 2, 0); - printf("Error check - next call must be wrong!\n"); - CheckSame("wiringPiISRStop with wrong pin, result code:", wiringPiISRStop(5555), EINVAL); + printf("\nTesting IRQ @ WPI-GPIO%d with trigger @ WPI-GPIO%d falling\n", IRQpin, OUTpin); + CheckSame("wiringPiISR", wiringPiISR(IRQpin, INT_EDGE_RISING, &wfidown), 0); + sleep(1); + StartSequence(INT_EDGE_FALLING, OUTpin, 4, -4); + sleep(1); + CheckSame("wiringPiISRStop", wiringPiISRStop(IRQpin), 0); + printf("\n.IRQ off\n"); + sleep(1); + StartSequence(INT_EDGE_RISING, OUTpin, 2, 0); - pinMode(OUTpin, INPUT); + printf("Error check - next call must be wrong!\n"); + CheckSame("wiringPiISRStop with wrong pin, result code:", wiringPiISRStop(5555), EINVAL); + + pinMode(OUTpin, INPUT); + break; + default: + printf("unit test not possible with this hardware, need connection between Wiringpi pin 28 and 29!\n"); + break; } return UnitTestState(); From 0b8eede1bd26c88177622c9dcbf68ab7f734d53b Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 23 May 2025 20:51:06 +0200 Subject: [PATCH 36/42] #346 adjust unit test --- wiringPi/test/wiringpi_test61_isr2.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index e0d21f5..06f73ee 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -189,6 +189,14 @@ int main (void) { wiringPiVersion(&major, &minor); + if (!piBoard40Pin()) { + printf("Old 28pin system\n"); + //GPIO = 23; + //GPIOIN = 24; + GPIO = 17; + GPIOIN = 18; + } + printf("WiringPi GPIO test program 6b (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); printf("ISR and ISR2 test (WiringPi %d.%d)\n", major, minor); @@ -206,6 +214,11 @@ int main (void) { accuracy = 0.02; bounce_acc = 2.7; break; + case PI_MODEL_ZERO: + case PI_MODEL_ZERO_W: //ARM=1000MHz + accuracy = 0.02; + bounce_acc = 2.5; + break; default: accuracy = 0.012; bounce_acc = 1.0; From bb0af182657762c6208cdc970b5af25ffde8482c Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 24 May 2025 12:23:02 +0200 Subject: [PATCH 37/42] #264 adjust unit test and autodetect unit test 6.2 irq --- wiringPi/test/wiringpi_test61_isr2.c | 25 ++++++++++----- wiringPi/test/wiringpi_test62_isr_wpin.c | 39 +++++++++++++++--------- wiringPi/test/wiringpi_test7_bench.c | 2 +- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index e0d21f5..a6b9a2f 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -1,5 +1,5 @@ -// WiringPi test program: 3.16 new ISR2 function with Kernel char device interface / sysfs successor -// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi +// WiringPi test program: 6.1 new ISR2 function with Kernel char device interface / sysfs successor +// Compile: gcc -Wall wiringpi_test61_isr2.c -o wiringpi_test61_isr2 -lwiringPi #include "wpi_test.h" #include @@ -189,7 +189,17 @@ int main (void) { wiringPiVersion(&major, &minor); - printf("WiringPi GPIO test program 6b (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); + int result = piBoard40Pin(); + CheckNotSame("40-Pin board: ", result, -1); + if (result==0) { + printf("Old 28pin system\n"); + //GPIO = 23; + //GPIOIN = 24; + GPIO = 17; + GPIOIN = 18; + } + + printf("WiringPi GPIO test program 6.2 (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); printf("ISR and ISR2 test (WiringPi %d.%d)\n", major, minor); wiringPiSetupGpio(); @@ -206,15 +216,16 @@ int main (void) { accuracy = 0.02; bounce_acc = 2.7; break; + case PI_MODEL_ZERO: + case PI_MODEL_ZERO_W: //ARM=1000MHz + accuracy = 0.02; + bounce_acc = 2.5; + break; default: accuracy = 0.012; bounce_acc = 1.0; break; } - if (!piBoard40Pin()) { - GPIO = 23; - GPIOIN = 24; - } int IRQpin = GPIOIN; int OUTpin = GPIO; diff --git a/wiringPi/test/wiringpi_test62_isr_wpin.c b/wiringPi/test/wiringpi_test62_isr_wpin.c index 00a599a..500e7c6 100644 --- a/wiringPi/test/wiringpi_test62_isr_wpin.c +++ b/wiringPi/test/wiringpi_test62_isr_wpin.c @@ -76,15 +76,24 @@ int main (void) { CheckNotSame("piBoardId", RaspberryPiModel, 0); - int IRQpin = GPIOIN; - int OUTpin = GPIO; - - switch(RaspberryPiModel) { - case PI_MODEL_4B: - case PI_MODEL_5: - pinMode(IRQpin, INPUT); - pinMode(OUTpin, OUTPUT); - digitalWrite (OUTpin, LOW) ; + int _is40pin = is40pin(); + CheckNotSame("is40pin", _is40pin, -1); + + if (_is40pin) { + + int IRQpin = GPIOIN; + int OUTpin = GPIO; + + pinMode(IRQpin, INPUT); + pinMode(OUTpin, OUTPUT); + digitalWrite(OUTpin, LOW); + delayMicroseconds(100); + CheckNotSame("Input", digitalRead(IRQpin), LOW); + digitalWrite(OUTpin, HIGH); + delayMicroseconds(100); + if (digitalRead(IRQpin)==HIGH) { + digitalWrite(OUTpin, LOW); + delayMicroseconds(100); printf("\nTesting IRQ @ WPI-GPIO%d with trigger @ WPI-GPIO%d rising\n", IRQpin, OUTpin); CheckSame("wiringPiISR", wiringPiISR(IRQpin, INT_EDGE_RISING, &wfiup), 0); @@ -108,12 +117,12 @@ int main (void) { printf("Error check - next call must be wrong!\n"); CheckSame("wiringPiISRStop with wrong pin, result code:", wiringPiISRStop(5555), EINVAL); - - pinMode(OUTpin, INPUT); - break; - default: - printf("unit test not possible with this hardware, need connection between Wiringpi pin 28 and 29!\n"); - break; + } else { + printf("Hardware connection for unit test missing!\n"); + printf("unit test, need connection between Wiringpi pin 28 and 29!\n"); + } + } else { + printf("unit test is for 40-pin hardware only!\n"); } return UnitTestState(); diff --git a/wiringPi/test/wiringpi_test7_bench.c b/wiringPi/test/wiringpi_test7_bench.c index 316c07e..9c0f221 100644 --- a/wiringPi/test/wiringpi_test7_bench.c +++ b/wiringPi/test/wiringpi_test7_bench.c @@ -66,7 +66,7 @@ int main (void) { case PI_MODEL_ZERO_W: //ARM=1000MHz fExpectTimedigitalWrite = 0.104; //us; fExpectTimedigitalRead = 0.135; //us - fExpectTimepinMode = 0.280; //us + fExpectTimepinMode = 0.360; //us break; case PI_MODEL_2: ToggleValue /= 4; From 545eb4f5ed64170aa54e028ecb75cda2c64e1912 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 24 May 2025 12:30:02 +0200 Subject: [PATCH 38/42] #264 adjust unit test and autodetect unit test 6.2 irq --- wiringPi/test/wiringpi_test61_isr2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiringPi/test/wiringpi_test61_isr2.c b/wiringPi/test/wiringpi_test61_isr2.c index 78a442a..67bb35f 100644 --- a/wiringPi/test/wiringpi_test61_isr2.c +++ b/wiringPi/test/wiringpi_test61_isr2.c @@ -219,7 +219,7 @@ int main (void) { case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: //ARM=1000MHz accuracy = 0.02; - bounce_acc = 2.5; + bounce_acc = 2.7; break; default: accuracy = 0.012; From e914bb230023f81033c082129132dd330e98b4e0 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 24 May 2025 12:31:00 +0200 Subject: [PATCH 39/42] #264 adjust unit test and autodetect unit test 6.2 irq --- wiringPi/test/wiringpi_test62_isr_wpin.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wiringPi/test/wiringpi_test62_isr_wpin.c b/wiringPi/test/wiringpi_test62_isr_wpin.c index 500e7c6..6132d21 100644 --- a/wiringPi/test/wiringpi_test62_isr_wpin.c +++ b/wiringPi/test/wiringpi_test62_isr_wpin.c @@ -76,10 +76,10 @@ int main (void) { CheckNotSame("piBoardId", RaspberryPiModel, 0); - int _is40pin = is40pin(); + int _is40pin = piBoard40Pin(); CheckNotSame("is40pin", _is40pin, -1); - if (_is40pin) { + if (_is40pin==1) { int IRQpin = GPIOIN; int OUTpin = GPIO; @@ -88,7 +88,7 @@ int main (void) { pinMode(OUTpin, OUTPUT); digitalWrite(OUTpin, LOW); delayMicroseconds(100); - CheckNotSame("Input", digitalRead(IRQpin), LOW); + CheckSame("Input", digitalRead(IRQpin), LOW); digitalWrite(OUTpin, HIGH); delayMicroseconds(100); if (digitalRead(IRQpin)==HIGH) { From f88e168b403490894e6ab3f225d6720aa6b23256 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 May 2025 19:06:30 +0200 Subject: [PATCH 40/42] #264 unit test for gpio wfis --- gpio/test/gpio_test61_wfi.sh | 140 +++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100755 gpio/test/gpio_test61_wfi.sh diff --git a/gpio/test/gpio_test61_wfi.sh b/gpio/test/gpio_test61_wfi.sh new file mode 100755 index 0000000..2576dec --- /dev/null +++ b/gpio/test/gpio_test61_wfi.sh @@ -0,0 +1,140 @@ +#!/bin/bash + +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # Reset color + +DEBOUNCE=100000 + +UNITTEST_OK=true +TIMEOUT=20 +iteration=0 +GPIOIN=26 +GPIOOUT=19 + +wait_with_timeout() { + local pid=$1 + local timeout=$2 + iteration=0 + + local toggle=0 + while kill -0 "$pid" 2>/dev/null; do + if [ $iteration -ge $timeout ]; then + kill -9 "$pid" 2>/dev/null + echo -e "${RED}ERROR: timeout ${timeout}s reached ${NC}" + return -1 + fi + echo -n . + sleep 1 + toggle=$((1 - toggle)) + gpio -g write $GPIOOUT $toggle + echo -n ${toggle} + sleep 0.2 + iteration=$((iteration + 1)) + done + + wait "$pid" + return $? +} + +wfis_test() { + local edge=$1 + local set_iter=$2 + local set_iterOK=$3 + local set_EXITCODE=$4 + + #wfi test + if [ $iteration -eq 0 ]; then + gpio -g wfis $GPIOIN "$edge" $DEBOUNCE & + else + gpio -g wfis $GPIOIN "$edge" $DEBOUNCE "$set_iter" & + fi + GPIO_PID=$! + wait_with_timeout "$GPIO_PID" "$TIMEOUT" + EXIT_CODE=$? + echo + if [ $EXIT_CODE -lt 3 ]; then + + if [ $EXIT_CODE -eq "$set_EXITCODE" ]; then + + if [ "$set_iter" -gt 0 ]; then + if [ "$iteration" -eq "$set_iterOK" ]; then + echo -e "${GREEN}wfis "$edge" $set_iter iteration passt (exit code $EXIT_CODE)${NC}" + else + echo -e "${RED}wfis "$edge" failed, $iteration iterations of $set_iter is wrong${NC}" + UNITTEST_OK=false + fi + else + echo -e "${GREEN}wfi "$edge" passt (exit code $EXIT_CODE)${NC}" + fi + + else + echo -e "${RED}wfis "$edge" failed - wrong exit code $EXIT_CODE${NC}" + UNITTEST_OK=false + fi + + else # negativ + echo -e "${RED}wfidb "$edge" failed (exit code $EXIT_CODE)${NC}" + UNITTEST_OK=false + fi +} + +echo +echo Unit test gpio GPIO${GPIOOUT} and GPIO${GPIOIN} - functions: mode, write, wfidb +echo ------------------------------------------------------------------ +echo + +#prepare trigger out +gpio -g mode $GPIOOUT out + +gpio -g write $GPIOOUT 1 +wfis_test "rising" 0 0 2 + +gpio -g write $GPIOOUT 0 +wfis_test "falling" 0 0 1 + +gpio -g write $GPIOOUT 1 +wfis_test "both" 0 0 1 + +gpio -g write $GPIOOUT 0 +wfis_test "both" 0 0 2 + + +#wfi iteration test + +gpio -g write $GPIOOUT 0 +wfis_test "rising" 4 7 2 + +gpio -g write $GPIOOUT 1 +wfis_test "falling" 4 8 1 + +gpio -g write $GPIOOUT 0 +wfis_test "both" 3 3 2 + +gpio -g write $GPIOOUT 1 +wfis_test "both" 3 4 1 + +gpio -g write $GPIOOUT 0 +gpio -g mode $GPIOOUT in + +### #wfi timeout test +gpio -g wfis $GPIOIN rising $DEBOUNCE 2 4 & +GPIO_PID=$! +wait_with_timeout "$GPIO_PID" "$TIMEOUT" +EXIT_CODE=$? +echo +if [ $EXIT_CODE -eq 255 ]; then + echo -e "${GREEN}wfi timeout passed (exit code $EXIT_CODE)${NC}" +else + echo -e "${RED}wfi timeout failed (code $EXIT_CODE)${NC}" + UNITTEST_OK=false +fi + + +if [ ${UNITTEST_OK} = true ]; then + echo -e "\n\n${GREEN}Unit test result OK.${NC}" + exit 0 +else + echo -e "\n\n${RED}Unit test result failed.${NC}" + exit 1 +fi From 18a6935530e460bf4d2b13820b56045d15112df4 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 May 2025 19:12:22 +0200 Subject: [PATCH 41/42] #264 unit test for gpio wfis --- gpio/test/gpio_test61_wfi.sh | 140 ----------------------------------- 1 file changed, 140 deletions(-) delete mode 100755 gpio/test/gpio_test61_wfi.sh diff --git a/gpio/test/gpio_test61_wfi.sh b/gpio/test/gpio_test61_wfi.sh deleted file mode 100755 index 2576dec..0000000 --- a/gpio/test/gpio_test61_wfi.sh +++ /dev/null @@ -1,140 +0,0 @@ -#!/bin/bash - -RED='\033[0;31m' -GREEN='\033[0;32m' -NC='\033[0m' # Reset color - -DEBOUNCE=100000 - -UNITTEST_OK=true -TIMEOUT=20 -iteration=0 -GPIOIN=26 -GPIOOUT=19 - -wait_with_timeout() { - local pid=$1 - local timeout=$2 - iteration=0 - - local toggle=0 - while kill -0 "$pid" 2>/dev/null; do - if [ $iteration -ge $timeout ]; then - kill -9 "$pid" 2>/dev/null - echo -e "${RED}ERROR: timeout ${timeout}s reached ${NC}" - return -1 - fi - echo -n . - sleep 1 - toggle=$((1 - toggle)) - gpio -g write $GPIOOUT $toggle - echo -n ${toggle} - sleep 0.2 - iteration=$((iteration + 1)) - done - - wait "$pid" - return $? -} - -wfis_test() { - local edge=$1 - local set_iter=$2 - local set_iterOK=$3 - local set_EXITCODE=$4 - - #wfi test - if [ $iteration -eq 0 ]; then - gpio -g wfis $GPIOIN "$edge" $DEBOUNCE & - else - gpio -g wfis $GPIOIN "$edge" $DEBOUNCE "$set_iter" & - fi - GPIO_PID=$! - wait_with_timeout "$GPIO_PID" "$TIMEOUT" - EXIT_CODE=$? - echo - if [ $EXIT_CODE -lt 3 ]; then - - if [ $EXIT_CODE -eq "$set_EXITCODE" ]; then - - if [ "$set_iter" -gt 0 ]; then - if [ "$iteration" -eq "$set_iterOK" ]; then - echo -e "${GREEN}wfis "$edge" $set_iter iteration passt (exit code $EXIT_CODE)${NC}" - else - echo -e "${RED}wfis "$edge" failed, $iteration iterations of $set_iter is wrong${NC}" - UNITTEST_OK=false - fi - else - echo -e "${GREEN}wfi "$edge" passt (exit code $EXIT_CODE)${NC}" - fi - - else - echo -e "${RED}wfis "$edge" failed - wrong exit code $EXIT_CODE${NC}" - UNITTEST_OK=false - fi - - else # negativ - echo -e "${RED}wfidb "$edge" failed (exit code $EXIT_CODE)${NC}" - UNITTEST_OK=false - fi -} - -echo -echo Unit test gpio GPIO${GPIOOUT} and GPIO${GPIOIN} - functions: mode, write, wfidb -echo ------------------------------------------------------------------ -echo - -#prepare trigger out -gpio -g mode $GPIOOUT out - -gpio -g write $GPIOOUT 1 -wfis_test "rising" 0 0 2 - -gpio -g write $GPIOOUT 0 -wfis_test "falling" 0 0 1 - -gpio -g write $GPIOOUT 1 -wfis_test "both" 0 0 1 - -gpio -g write $GPIOOUT 0 -wfis_test "both" 0 0 2 - - -#wfi iteration test - -gpio -g write $GPIOOUT 0 -wfis_test "rising" 4 7 2 - -gpio -g write $GPIOOUT 1 -wfis_test "falling" 4 8 1 - -gpio -g write $GPIOOUT 0 -wfis_test "both" 3 3 2 - -gpio -g write $GPIOOUT 1 -wfis_test "both" 3 4 1 - -gpio -g write $GPIOOUT 0 -gpio -g mode $GPIOOUT in - -### #wfi timeout test -gpio -g wfis $GPIOIN rising $DEBOUNCE 2 4 & -GPIO_PID=$! -wait_with_timeout "$GPIO_PID" "$TIMEOUT" -EXIT_CODE=$? -echo -if [ $EXIT_CODE -eq 255 ]; then - echo -e "${GREEN}wfi timeout passed (exit code $EXIT_CODE)${NC}" -else - echo -e "${RED}wfi timeout failed (code $EXIT_CODE)${NC}" - UNITTEST_OK=false -fi - - -if [ ${UNITTEST_OK} = true ]; then - echo -e "\n\n${GREEN}Unit test result OK.${NC}" - exit 0 -else - echo -e "\n\n${RED}Unit test result failed.${NC}" - exit 1 -fi From b5eac6062783903c9c35f180e497c165b4540737 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 31 May 2025 19:43:14 +0200 Subject: [PATCH 42/42] Release 3.16 --- VERSION | 2 +- version.h | 4 ++-- wiringPi/test/wiringpi_test9_pwm.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 230693c..5174c53 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.15 \ No newline at end of file +3.16 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/test/wiringpi_test9_pwm.c b/wiringPi/test/wiringpi_test9_pwm.c index a5605f5..88775fc 100644 --- a/wiringPi/test/wiringpi_test9_pwm.c +++ b/wiringPi/test/wiringpi_test9_pwm.c @@ -135,7 +135,7 @@ int main (void) { pinMode(PWM, PWM_OUTPUT); //Mode BAL, pwmr=1024, pwmc=32 printf("pwmc 4.8kHz\n"); pwmSetClock(2000); - delay(250); + delay(1000); printf("Register ISR@%d\n", PWM); // INT_EDGE_BOTH, INT_EDGE_FALLING, INT_EDGE_RISING only one ISR per input