From 8ca0819c0c154afbc395e42c5242c64ead9850c4 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 15 Mar 2024 15:37:54 +0100 Subject: [PATCH 1/7] #200 --- wiringPi/wiringPi.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 28dfe61..1541bdf 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -71,6 +71,7 @@ #include #include #include +#include #include "softPwm.h" #include "softTone.h" @@ -876,12 +877,26 @@ static void usingGpioMemCheck (const char *what) * ********************************************************************************* */ + const char* revfile = "/proc/device-tree/system/linux,revision"; void piGpioLayoutOops (const char *why) { - fprintf (stderr, "Oops: Unable to determine board revision from /proc/cpuinfo\n") ; - fprintf (stderr, " -> %s\n", why) ; - fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n") ; + fprintf (stderr, "Oops: Unable to determine Raspberry Pi board revision from %s and from /proc/cpuinfo\n", revfile) ; + struct utsname sys_info; + if (uname(&sys_info) == 0) { + fprintf (stderr, " system name = %s\n", sys_info.sysname); + //fprintf (stderr, " node name = %s\n", sys_info.nodename); + fprintf (stderr, " release = %s\n", sys_info.release); + fprintf (stderr, " version = %s\n", sys_info.version); + fprintf (stderr, " machine = %s\n", sys_info.machine); + } + if (strstr(sys_info.machine, "arm") == NULL && strstr(sys_info.machine, "aarch")==NULL) { + fprintf (stderr, " -> This is not an ARM architecture; it cannot be a Raspberry Pi.\n") ; + fprintf (stderr, " -> WiringPi is designed for Raspberry Pi and can only be used with a Raspberry Pi.\n\n") ; + } else { + fprintf (stderr, " -> %s\n", why) ; + fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n\n") ; + } exit (EXIT_FAILURE) ; } @@ -905,10 +920,6 @@ int piBoardRev (void) return piGpioLayout () ; } - -const char* revfile = "/proc/device-tree/system/linux,revision"; - - const char* GetPiRevision(char* line, int linelength, unsigned int* revision) { const char* c = NULL; @@ -1012,6 +1023,8 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) unsigned int revision = 0x00 ; int bRev, bType, bProc, bMfg, bMem, bWarranty ; + //piGpioLayoutOops ("this is only a test case"); + c = GetPiRevision(line, maxlength, &revision); // device tree if (NULL==c) { c = GetPiRevisionLegacy(line, maxlength, &revision); // proc/cpuinfo From 8408f3ce78b614d09043a025cbc7387329c446ba Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 15 Mar 2024 19:56:57 +0100 Subject: [PATCH 2/7] ubuntu reinstall --- reinstall | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/reinstall b/reinstall index cf20a0c..8f76758 100755 --- a/reinstall +++ b/reinstall @@ -1,11 +1,44 @@ #!/bin/sh vMaj=`cut -d. -f1 VERSION` vMin=`cut -d. -f2 VERSION` -DEBVERSION=$vMaj.$vMin -sudo apt -y remove wiringpi -./build clean -./build debian -mv debian-template/wiringpi_${DEBVERSION}_armhf.deb . -sudo apt install ./wiringpi_${DEBVERSION}_armhf.deb +WPIVERSION=$vMaj.$vMin +ARCH=$(dpkg-architecture -qDEB_HOST_ARCH) +if [ -f /etc/os-release ]; then + # load vars from /etc/os-release + . /etc/os-release + if [ "$ID" = "raspbian" ] || [ "$ID" = "debian" ] || [ "$ID" = "linuxmint" ]; then + if [ "$ID" = "raspbian" ]; then + echo OS: Raspberry Pi OS + else + echo OS: Debian + fi + echo using all in one deb-package + echo ============================ + echo + sudo apt -y remove wiringpi + ./build clean + ./build debian + mv debian-template/wiringpi_${WPIVERSION}_${ARCH}.deb . + sudo apt install ./wiringpi_${WPIVERSION}_${ARCH}.deb + + elif [ "$ID" = "debian" ] || [ "$ID" = "linuxmint" ]; then + echo OS: Ubuntu/Mint + echo using 3 deb-package + echo =================== + echo + + sudo apt -y remove libwiringpi2 + sudo apt -y remove libwiringpi3 + sudo apt -y remove wiringpi libwiringpi-dev + ./build clean + ./build ubuntu + #mv debian-template/wiringpi_${WPIVERSION}_armhf.deb . + #sudo apt install ./wiringpi_${WPIVERSION}_armhf.deb + fi + +else + echo OS unknown, exit + exit +fi \ No newline at end of file From c1a86f41f230da0d515336176467421ca251817a Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 22 Mar 2024 18:21:18 +0100 Subject: [PATCH 3/7] #204 --- VERSION | 2 +- gpio/gpio.c | 39 +++++-- version.h | 4 +- wiringPi/wiringPi.c | 288 ++++++++++++++++++++++++++++++++++------------------ wiringPi/wiringPi.h | 4 +- 5 files changed, 230 insertions(+), 107 deletions(-) diff --git a/VERSION b/VERSION index 8c50098..a3ec5a4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1 +3.2 diff --git a/gpio/gpio.c b/gpio/gpio.c index 680305a..5989fbf 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -556,16 +556,30 @@ void doExport (int argc, char *argv []) ********************************************************************************* */ -static void wfi (void) - { exit (0) ; } +static volatile int iterations ; +static volatile int globalCounter ; + +static void wfi (void) { + globalCounter++; + //printf("irq count %d/%d\n", globalCounter , iterations); + if(globalCounter>=iterations) { + printf("finished\n"); + exit (0) ; + } else { + printf("I"); fflush(stdout); + } +} void doWfi (int argc, char *argv []) { - int pin, mode ; + int pin, mode; + int timeoutSec = 2147483647; - if (argc != 4) + iterations = 1; + globalCounter = 0; + if (argc != 4 && argc != 5 && argc != 6) { - fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ; + fprintf (stderr, "Usage: %s wfi pin mode [interations] [timeout sec.]\n", argv [0]) ; exit (1) ; } @@ -579,6 +593,12 @@ void doWfi (int argc, char *argv []) 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) { @@ -586,8 +606,13 @@ void doWfi (int argc, char *argv []) exit (1) ; } - for (;;) - delay (9999) ; + printf("wait for interrupt function call \n"); + for (int Sec=0; Sec #include #include +#include #include "softPwm.h" #include "softTone.h" @@ -406,9 +407,10 @@ static int sysFds [64] = } ; // ISR Data - +static int chipFd = -1; static void (*isrFunctions [64])(void) ; - +static pthread_t isrThreads[64]; +static int isrMode[64]; // Doing it the Arduino way with lookup tables... // Yes, it's probably more innefficient than all the bit-twidling, but it @@ -2112,7 +2114,7 @@ unsigned int digitalReadByte2 (void) * waitForInterrupt: * Pi Specific. * Wait for Interrupt on a GPIO pin. - * This is actually done via the /sys/class/gpio interface regardless of + * This is actually done via the /dev/gpiochip interface regardless of * the wiringPi access mode in-use. Maybe sometime it might get a better * way for a bit more efficiency. ********************************************************************************* @@ -2120,11 +2122,12 @@ unsigned int digitalReadByte2 (void) int waitForInterrupt (int pin, int mS) { - int fd, x ; - uint8_t c ; + int fd, ret; struct pollfd polls ; + struct gpioevent_data evdata; + //struct gpio_v2_line_request req2; - /**/ if (wiringPiMode == WPI_MODE_PINS) + if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio [pin] ; else if (wiringPiMode == WPI_MODE_PHYS) pin = physToGpio [pin] ; @@ -2132,28 +2135,146 @@ int waitForInterrupt (int pin, int mS) if ((fd = sysFds [pin]) == -1) return -2 ; -// Setup poll structure + // 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, sysFds [pin]) ; + } + /* read event data */ + int readret = read(sysFds [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; +} - polls.fd = fd ; - polls.events = POLLPRI | POLLERR ; +const char DEV_GPIO_PI[] ="/dev/gpiochip0"; +const char DEV_GPIO_PI5[]="/dev/gpiochip4"; -// Wait for it ... +int waitForInterruptInit (int pin, int mode) +{ + const char* strmode = ""; - x = poll (&polls, 1, mS) ; + if (wiringPiMode == WPI_MODE_PINS) { + pin = pinToGpio [pin] ; + } else if (wiringPiMode == WPI_MODE_PHYS) { + pin = physToGpio [pin] ; + } -// If no error, do a dummy read to clear the interrupt -// A one character read appars to be enough. + /* open gpio */ + sleep(1); + const char* gpiochip = PI_MODEL_5 == RaspberryPiModel ? DEV_GPIO_PI5 : DEV_GPIO_PI; + if (chipFd < 0) { + chipFd = open(gpiochip, O_RDWR); + if (chipFd < 0) { + fprintf(stderr, "wiringPi: ERROR: %s open ret=%d\n", gpiochip, chipFd); + return -1; + } + } + if (wiringPiDebug) { + printf ("wiringPi: Open chip %s succeded, fd=%d\n", gpiochip, chipFd) ; + } - if (x > 0) - { - lseek (fd, 0, SEEK_SET) ; // Rewind - (void)read (fd, &c, 1) ; // Read & clear + 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); - return x ; + //later implement GPIO_V2_GET_LINE_IOCTL req2 + int ret = ioctl(chipFd, GPIO_GET_LINEEVENT_IOCTL, &req); + if (ret) { + fprintf(stderr, "wiringPi: ERROR: %s ioctl get line %d %s returned %d\n", gpiochip, 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; + sysFds [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: %s fcntl set nonblock read=%d\n", gpiochip, chipFd); + return -1; + } + + return 0; +} + + +int waitForInterruptClose (int pin) { + if (sysFds[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(sysFds [pin]); + } + sysFds [pin] = -1; + + /* -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); +} + /* * interruptHandler: * This is a thread and gets started to wait for the interrupt we're @@ -2164,17 +2285,30 @@ int waitForInterrupt (int pin, int mS) static void *interruptHandler (UNU void *arg) { - int myPin ; + int pin ; (void)piHiPri (55) ; // Only effective if we run as root - myPin = pinPass ; + pin = pinPass ; pinPass = -1 ; - for (;;) - if (waitForInterrupt (myPin, -1) > 0) - isrFunctions [myPin] () ; + for (;;) { + int ret = waitForInterrupt(pin, -1); + if ( ret> 0) { + if (wiringPiDebug) { + printf ("wiringPi: call function\n") ; + } + isrFunctions [pin] () ; + // wait again - in the past forever - now can be stopped by waitForInterruptClose + } else if( ret< 0) { + break; // stop thread! + } + } + waitForInterruptClose (pin); + if (wiringPiDebug) { + printf ("wiringPi: interruptHandler finished\n") ; + } return NULL ; } @@ -2189,93 +2323,55 @@ static void *interruptHandler (UNU void *arg) int wiringPiISR (int pin, int mode, void (*function)(void)) { - pthread_t threadId ; - const char *modeS ; - char fName [64] ; - char pinS [8] ; - pid_t pid ; - int count, i ; - char c ; - int bcmGpioPin ; 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) + if (wiringPiMode == WPI_MODE_UNINITIALISED) return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; - else if (wiringPiMode == WPI_MODE_PINS) - bcmGpioPin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - bcmGpioPin = physToGpio [pin] ; - else - bcmGpioPin = pin ; - -// Now export the pin and set the right edge -// We're going to use the gpio program to do this, so it assumes -// a full installation of wiringPi. It's a bit 'clunky', but it -// is a way that will work when we're running in "Sys" mode, as -// a non-root user. (without sudo) - - if (mode != INT_EDGE_SETUP) - { - /**/ if (mode == INT_EDGE_FALLING) - modeS = "falling" ; - else if (mode == INT_EDGE_RISING) - modeS = "rising" ; - else - modeS = "both" ; - - sprintf (pinS, "%d", bcmGpioPin) ; - - if ((pid = fork ()) < 0) // Fail - return wiringPiFailure (WPI_FATAL, "wiringPiISR: fork failed: %s\n", strerror (errno)) ; - - if (pid == 0) // Child, exec - { - /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) - { - execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else if (access ("/usr/bin/gpio", X_OK) == 0) - { - execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; - } - else - return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ; - } - else // Parent, wait - waitpid (pid, NULL, 0) ; + if (wiringPiDebug) { + printf ("wiringPi: wiringPiISR pin %d, mode %d\n", pin, mode) ; } - -// Now pre-open the /sys/class node - but it may already be open if -// we are in Sys mode... - - if (sysFds [bcmGpioPin] == -1) - { - int pinFS = GPIOToSysFS(bcmGpioPin); - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - if (pinFS>=0 && (sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ; + if (isrFunctions [pin]) { + printf ("wiringPi: ISR function alread active, ignoring \n") ; } -// Clear any initial pending interrupt - - ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ; - for (i = 0 ; i < count ; ++i) - read (sysFds [bcmGpioPin], &c, 1) ; - isrFunctions [pin] = function ; + isrMode[pin] = mode; + if(waitForInterruptInit (pin, mode)<0) { + if (wiringPiDebug) { + fprintf (stderr, "wiringPi: waitForInterruptInit failed\n") ; + } + }; + if (wiringPiDebug) { + printf ("wiringPi: mutex in\n") ; + } pthread_mutex_lock (&pinMutex) ; pinPass = pin ; - pthread_create (&threadId, NULL, interruptHandler, NULL) ; - while (pinPass != -1) - delay (1) ; + if (wiringPiDebug) { + printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]); + } + if (pthread_create (&isrThreads[pin], NULL, interruptHandler, NULL)==0) { + if (wiringPiDebug) { + printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]); + } + while (pinPass != -1) + delay (1) ; + } else { + if (wiringPiDebug) { + printf("wiringPi: pthread_create failed\n"); + } + } + + if (wiringPiDebug) { + printf ("wiringPi: mutex out\n") ; + } pthread_mutex_unlock (&pinMutex) ; + if (wiringPiDebug) { + printf ("wiringPi: wiringPiISR finished\n") ; + } return 0 ; } diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 0212016..d6ee11a 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -239,7 +239,7 @@ extern void piBoardId (int *model, int *rev, int *mem, int *m extern int wpiPinToGpio (int wpiPin) ; extern int physPinToGpio (int physPin) ; extern void setPadDrive (int group, int value) ; -extern void setPadDrivePin (int pin, int value); // Interface V2 +extern void setPadDrivePin (int pin, int value); // Interface V3.0 extern int getAlt (int pin) ; extern void pwmToneWrite (int pin, int freq) ; extern void pwmSetMode (int mode) ; @@ -256,6 +256,8 @@ extern void digitalWriteByte2 (int value) ; extern int waitForInterrupt (int pin, int mS) ; extern int wiringPiISR (int pin, int mode, void (*function)(void)) ; +extern int wiringPiISRStop (int pin) ; //V3.2 +extern int waitForInterruptClose(int pin) ; //V3.2 // Threads From ea2f2323c3ca479d63a0623233a4cc526ace6584 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 22 Mar 2024 19:42:16 +0100 Subject: [PATCH 4/7] #204 --- gpio/gpio.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/gpio/gpio.c b/gpio/gpio.c index 5989fbf..36d1fc1 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -43,6 +43,7 @@ #include "../version.h" extern int wiringPiDebug ; +int gpioDebug ; // External functions I can't be bothered creating a separate .h file for: @@ -559,14 +560,27 @@ void doExport (int argc, char *argv []) static volatile int iterations ; static volatile int globalCounter ; +void printgpioflush(const char* text) { + if (gpioDebug) { + printf(text); + fflush(stdout); + } +} + +void printgpio(const char* text) { + if (gpioDebug) { + printf(text); + fflush(stdout); + } +} + static void wfi (void) { globalCounter++; - //printf("irq count %d/%d\n", globalCounter , iterations); if(globalCounter>=iterations) { - printf("finished\n"); + printgpio("finished\n"); exit (0) ; } else { - printf("I"); fflush(stdout); + printgpioflush("I"); } } @@ -606,12 +620,12 @@ void doWfi (int argc, char *argv []) exit (1) ; } - printf("wait for interrupt function call \n"); + printgpio("wait for interrupt function call \n"); for (int Sec=0; Sec Date: Sun, 24 Mar 2024 11:08:12 +0100 Subject: [PATCH 5/7] new ISR example/test program --- examples/isr3.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 examples/isr3.c diff --git a/examples/isr3.c b/examples/isr3.c new file mode 100644 index 0000000..36fb7f2 --- /dev/null +++ b/examples/isr3.c @@ -0,0 +1,169 @@ +/* + * isr3.c: + * Wait for Interrupt test program WiringPi >=3.2 - ISR method + * + * + */ + +#include +#include +#include +#include +#include +#include +#include + #include + +// globalCounter: +// Global variable to count interrupts +// Should be declared volatile to make sure the compiler doesn't cache it. + +static volatile int globalCounter; +volatile long long gStartTime, gEndTime; + +/* + * myInterrupt: + ********************************************************************************* + */ + +static void wfi (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++; +} + +/* + ********************************************************************************* + * main + ********************************************************************************* + */ + +double StartSequence (int Enge, int OUTpin) { + int expected; + double timeExpected; + + gStartTime = 0; + gEndTime = 0; + globalCounter = 0; + printf("Start\n"); + digitalWrite(OUTpin, HIGH); + delay(200); + digitalWrite(OUTpin, LOW); + delay(100); + digitalWrite(OUTpin, HIGH); + delay(200); + digitalWrite(OUTpin, LOW); + delay(100); + printf("Stop\n"); + int globalCounterCopy = globalCounter; + + if (INT_EDGE_BOTH == Enge) { + expected = 4; + timeExpected = 500; + } else { + expected = 2; + timeExpected = 300; + } + + if(globalCounter==expected) { + double fTime = (gEndTime - gStartTime) / 1000000.0; + printf("IRQ worked %g sec (~%gs expected)\n\n", fTime, timeExpected/1000.0); + 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) { + struct timeval now; + double fTime = 0.0; + + gStartTime = 0; + gEndTime = 0; + globalCounter = 0; + printf("Start\n"); + + if (INT_EDGE_RISING == Enge) { + digitalWrite(OUTpin, LOW); + wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ; + 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); + wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ; + 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\n\n", fTime); + wiringPiISRStop (IRQpin) ; + + return fTime; +} + +int main (void) +{ + const int IRQpin = 22 ; + const int OUTpin = 25 ; + int major, minor; + + wiringPiVersion(&major, &minor); + + printf("\nISR test (WiringPi %d.%d)\n", major, minor); + + wiringPiSetupGpio() ; + + pinMode(IRQpin, INPUT); + pinMode(OUTpin, OUTPUT); + digitalWrite (OUTpin, LOW) ; + + + printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); + wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ; + sleep(1); + StartSequence (INT_EDGE_RISING, OUTpin); + printf("Testing close\n"); + + wiringPiISRStop (IRQpin) ; + + printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); + wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ; + sleep(1); + StartSequence (INT_EDGE_FALLING, OUTpin); + printf("Testing close\n"); + wiringPiISRStop (IRQpin) ; + + printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d both\n", IRQpin, OUTpin); + wiringPiISR (IRQpin, INT_EDGE_BOTH, &wfi) ; + sleep(1); + StartSequence (INT_EDGE_BOTH, OUTpin); + printf("Testing close\n"); + wiringPiISRStop (IRQpin) ; + + for (int count=0; count<2; count++) { + printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); + DurationTime(INT_EDGE_RISING, OUTpin, IRQpin); + + printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); + DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin); + } + pinMode(OUTpin, INPUT); + + return 0 ; +} From b832d204e50307a1bbbe648b6873b75de58082bc Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 24 Mar 2024 11:10:59 +0100 Subject: [PATCH 6/7] #204 fix message: ISR function alread active, ignoring --- wiringPi/wiringPi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index dc706ad..da1bef6 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2257,6 +2257,7 @@ int waitForInterruptClose (int pin) { close(sysFds [pin]); } sysFds [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) { @@ -2298,7 +2299,9 @@ static void *interruptHandler (UNU void *arg) if (wiringPiDebug) { printf ("wiringPi: call function\n") ; } - isrFunctions [pin] () ; + if(isrFunctions [pin]) { + isrFunctions [pin] () ; + } // wait again - in the past forever - now can be stopped by waitForInterruptClose } else if( ret< 0) { break; // stop thread! From 4046741cd7279b41fbe471627f10a29a1c7e721d Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Mon, 25 Mar 2024 16:38:18 +0100 Subject: [PATCH 7/7] #208 --- wiringPi/wiringPi.c | 165 ++++++++++++++-------------------------------- wiringPi/wiringPiLegacy.c | 65 +++++++++++++++++- 2 files changed, 115 insertions(+), 115 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index da1bef6..5c6a0f6 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -854,6 +854,36 @@ static void usingGpioMemCheck (const char *what) } +void PrintSystemStdErr () { + struct utsname sys_info; + if (uname(&sys_info) == 0) { + fprintf (stderr, " wiringpi = %d.%d\n", VERSION_MAJOR, VERSION_MINOR); + fprintf (stderr, " system name = %s\n", sys_info.sysname); + //fprintf (stderr, " node name = %s\n", sys_info.nodename); + fprintf (stderr, " release = %s\n", sys_info.release); + fprintf (stderr, " version = %s\n", sys_info.version); + fprintf (stderr, " machine = %s\n", sys_info.machine); + if (strstr(sys_info.machine, "arm") == NULL && strstr(sys_info.machine, "aarch")==NULL) { + fprintf (stderr, " -> This is not an ARM architecture; it cannot be a Raspberry Pi.\n") ; + } + } +} + + +void piFunctionOops (const char *function, const char* suggestion, const char* url) +{ + fprintf (stderr, "Oops: Function %s is not supported\n", function) ; + PrintSystemStdErr(); + if (suggestion) { + fprintf (stderr, " -> Please %s\n", suggestion) ; + } + if (url) { + fprintf (stderr, " -> See info at %s\n", url) ; + } + fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n\n") ; + exit (EXIT_FAILURE) ; +} + /* * piGpioLayout: @@ -884,21 +914,10 @@ static void usingGpioMemCheck (const char *what) void piGpioLayoutOops (const char *why) { fprintf (stderr, "Oops: Unable to determine Raspberry Pi board revision from %s and from /proc/cpuinfo\n", revfile) ; - struct utsname sys_info; - if (uname(&sys_info) == 0) { - fprintf (stderr, " system name = %s\n", sys_info.sysname); - //fprintf (stderr, " node name = %s\n", sys_info.nodename); - fprintf (stderr, " release = %s\n", sys_info.release); - fprintf (stderr, " version = %s\n", sys_info.version); - fprintf (stderr, " machine = %s\n", sys_info.machine); - } - if (strstr(sys_info.machine, "arm") == NULL && strstr(sys_info.machine, "aarch")==NULL) { - fprintf (stderr, " -> This is not an ARM architecture; it cannot be a Raspberry Pi.\n") ; - fprintf (stderr, " -> WiringPi is designed for Raspberry Pi and can only be used with a Raspberry Pi.\n\n") ; - } else { - fprintf (stderr, " -> %s\n", why) ; - fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n\n") ; - } + PrintSystemStdErr(); + fprintf (stderr, " -> %s\n", why) ; + fprintf (stderr, " -> WiringPi is designed for Raspberry Pi and can only be used with a Raspberry Pi.\n\n") ; + fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n\n") ; exit (EXIT_FAILURE) ; } @@ -1744,19 +1763,12 @@ void pullUpDnControl (int pin, int pud) int digitalRead (int pin) { - char c ; struct wiringPiNodeStruct *node = wiringPiNodes ; + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode - { - if (sysFds [pin] == -1) - return LOW ; - - lseek (sysFds [pin], 0L, SEEK_SET) ; - read (sysFds [pin], &c, 1) ; - return (c == '0') ? LOW : HIGH ; - } + if (wiringPiMode == WPI_MODE_GPIO_SYS) + return LOW ; else if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio [pin] ; else if (wiringPiMode == WPI_MODE_PHYS) @@ -1819,17 +1831,8 @@ void digitalWrite (int pin, int value) if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode - { - if (sysFds [pin] != -1) - { - if (value == LOW) - write (sysFds [pin], "0\n", 2) ; - else - write (sysFds [pin], "1\n", 2) ; - } + if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode return ; - } else if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio [pin] ; else if (wiringPiMode == WPI_MODE_PHYS) @@ -2000,13 +2003,8 @@ void digitalWriteByte (const int value) FailOnModel5(); - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + if (wiringPiMode == WPI_MODE_GPIO_SYS) { - for (pin = 0 ; pin < 8 ; ++pin) - { - digitalWrite (pinToGpio [pin], value & mask) ; - mask <<= 1 ; - } return ; } else @@ -2034,13 +2032,9 @@ unsigned int digitalReadByte (void) FailOnModel5(); - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + if (wiringPiMode == WPI_MODE_GPIO_SYS) { - for (pin = 0 ; pin < 8 ; ++pin) - { - x = digitalRead (pinToGpio [pin]) ; - data = (data << 1) | x ; - } + return 0; } else { @@ -2067,19 +2061,10 @@ unsigned int digitalReadByte (void) void digitalWriteByte2 (const int value) { - register int mask = 1 ; - register int pin ; - FailOnModel5(); - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + if (wiringPiMode == WPI_MODE_GPIO_SYS) { - for (pin = 20 ; pin < 28 ; ++pin) - { - digitalWrite (pin, value & mask) ; - mask <<= 1 ; - } - return ; } else { @@ -2090,18 +2075,12 @@ void digitalWriteByte2 (const int value) unsigned int digitalReadByte2 (void) { - int pin, x ; uint32_t data = 0 ; FailOnModel5(); - /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + if (wiringPiMode == WPI_MODE_GPIO_SYS) { - for (pin = 20 ; pin < 28 ; ++pin) - { - x = digitalRead (pin) ; - data = (data << 1) | x ; - } } else data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins @@ -2824,60 +2803,18 @@ int wiringPiSetupPhys (void) /* * wiringPiSetupSys: - * Must be called once at the start of your program execution. - * - * Initialisation (again), however this time we are using the /sys/class/gpio - * interface to the GPIO systems - slightly slower, but always usable as - * a non-root user, assuming the devices are already exported and setup correctly. + * GPIO Sysfs Interface for Userspace is deprecated + * https://www.kernel.org/doc/html/v5.5/admin-guide/gpio/sysfs.html + * The last Raspberry Pi Kernel with Sysfs was 6.1. + * If needed, please use WiringPi 3.1. + * */ int wiringPiSetupSys (void) { - char fName [128] ; - - if (wiringPiSetuped) - return 0 ; - - wiringPiSetuped = TRUE ; - - if (getenv (ENV_DEBUG) != NULL) - wiringPiDebug = TRUE ; - - if (getenv (ENV_CODES) != NULL) - wiringPiReturnCodes = TRUE ; - - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetupSys called\n") ; - - int model, rev, mem, maker, overVolted ; - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - - if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1) - { - pinToGpio = pinToGpioR1 ; - physToGpio = physToGpioR1 ; - } - else - { - pinToGpio = pinToGpioR2 ; - physToGpio = physToGpioR2 ; - } - -// Open and scan the directory, looking for exported GPIOs, and pre-open -// the 'value' interface to speed things up for later - - for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin) - { - int pinFS = GPIOToSysFS(pin); - if (pinFS>=0) { - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - sysFds [pin] = open (fName, O_RDWR) ; - } - } - - initialiseEpoch () ; - - wiringPiMode = WPI_MODE_GPIO_SYS ; + piFunctionOops("wiringPiSetupSys", + "use wringpi 3.1 (last version with GPIO Sysfs interface)", + "https://www.kernel.org/doc/html/v5.5/admin-guide/gpio/sysfs.html"); return 0 ; } diff --git a/wiringPi/wiringPiLegacy.c b/wiringPi/wiringPiLegacy.c index faedd4e..e14b45a 100644 --- a/wiringPi/wiringPiLegacy.c +++ b/wiringPi/wiringPiLegacy.c @@ -185,4 +185,67 @@ int piGpioLayoutLegacy (void) printf ("piGpioLayout: Returning revision: %d\n", gpioLayout) ; return gpioLayout ; -} \ No newline at end of file +} + + +/* + * wiringPiSetupSys: + * Must be called once at the start of your program execution. + * + * Initialisation (again), however this time we are using the /sys/class/gpio + * interface to the GPIO systems - slightly slower, but always usable as + * a non-root user, assuming the devices are already exported and setup correctly. + */ + +/* +int wiringPiSetupSys (void) +{ + char fName [128] ; + + if (wiringPiSetuped) + return 0 ; + + wiringPiSetuped = TRUE ; + + if (getenv (ENV_DEBUG) != NULL) + wiringPiDebug = TRUE ; + + if (getenv (ENV_CODES) != NULL) + wiringPiReturnCodes = TRUE ; + + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupSys called\n") ; + + int model, rev, mem, maker, overVolted ; + piBoardId (&model, &rev, &mem, &maker, &overVolted) ; + + if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1) + { + pinToGpio = pinToGpioR1 ; + physToGpio = physToGpioR1 ; + } + else + { + pinToGpio = pinToGpioR2 ; + physToGpio = physToGpioR2 ; + } + +// Open and scan the directory, looking for exported GPIOs, and pre-open +// the 'value' interface to speed things up for later + + for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin) + { + int pinFS = GPIOToSysFS(pin); + if (pinFS>=0) { + sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; + sysFds [pin] = open (fName, O_RDWR) ; + } + } + + initialiseEpoch () ; + + wiringPiMode = WPI_MODE_GPIO_SYS ; + + return 0 ; +} +*/