From 2cfe8339a37a110caad322b40ffe5e404116ddc9 Mon Sep 17 00:00:00 2001 From: romaricr Date: Tue, 12 Mar 2024 21:30:29 +0100 Subject: [PATCH 1/3] Bug fix for GPIO under recent Linux kernel versions Using libgpiod --- Makefile | 2 +- MyConfig.h | 2 +- configure | 3 +- .../Linux/drivers/core/interrupt.cpp | 102 ++++++++---------- .../Linux/drivers/core/interrupt.h | 3 + 5 files changed, 49 insertions(+), 63 deletions(-) diff --git a/Makefile b/Makefile index 5b2ef8bde..e02134bb5 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ $(ARDUINO): $(ARDUINO_LIB_OBJS) # Gateway Build $(GATEWAY): $(GATEWAY_OBJECTS) $(ARDUINO_LIB_OBJS) - $(CXX) $(LDFLAGS) -o $@ $(GATEWAY_OBJECTS) $(ARDUINO_LIB_OBJS) + $(CXX) $(LDFLAGS) -o $@ $(GATEWAY_OBJECTS) $(ARDUINO_LIB_OBJS) $(LATE_LDFLAGS) # Include all .d files -include $(DEPS) diff --git a/MyConfig.h b/MyConfig.h index c26ffdde2..4bf753658 100755 --- a/MyConfig.h +++ b/MyConfig.h @@ -442,7 +442,7 @@ * - RF24_PA_MAX = 0dBm */ #ifndef MY_RF24_PA_LEVEL -#define MY_RF24_PA_LEVEL (RF24_PA_HIGH) +#define MY_RF24_PA_LEVEL (RF24_PA_MAX) #endif /** diff --git a/configure b/configure index 2f30e98de..1281ebe3c 100755 --- a/configure +++ b/configure @@ -318,7 +318,7 @@ signing=none signing_request_signatures=false encryption=false -params="SOC CFLAGS CXXFLAGS CPPFLAGS LDFLAGS PREFIX CC CXX ARDUINO_LIB_DIR BUILDDIR BINDIR GATEWAY_DIR INIT_SYSTEM SPI_DRIVER TYPE" +params="SOC CFLAGS CXXFLAGS CPPFLAGS LDFLAGS LATE_LDFLAGS PREFIX CC CXX ARDUINO_LIB_DIR BUILDDIR BINDIR GATEWAY_DIR INIT_SYSTEM SPI_DRIVER TYPE" for opt do if [ "$opt" = "-h" ] || [ "$opt" = "--help" ]; then @@ -707,6 +707,7 @@ fi LDFLAGS="-pthread $LDFLAGS" CPPFLAGS="$CPUFLAGS $CPPFLAGS" +LATE_LDFLAGS="-Wl,-Bstatic -lgpiod -Wl,-Bdynamic" printf " ${OK} CPPFLAGS: $CPPFLAGS\n" printf " ${OK} CXXFLAGS: $CXXFLAGS\n" diff --git a/hal/architecture/Linux/drivers/core/interrupt.cpp b/hal/architecture/Linux/drivers/core/interrupt.cpp index f57c4cb7a..d11920fed 100644 --- a/hal/architecture/Linux/drivers/core/interrupt.cpp +++ b/hal/architecture/Linux/drivers/core/interrupt.cpp @@ -37,6 +37,7 @@ struct ThreadArgs { void (*func)(); int gpioPin; + struct gpiod_line *line; }; volatile bool interruptsEnabled = true; @@ -87,10 +88,10 @@ int piHiPri(const int pri) void *interruptHandler(void *args) { int fd; - struct pollfd polls; char c; struct ThreadArgs *arguments = (struct ThreadArgs *)args; int gpioPin = arguments->gpioPin; + struct gpiod_line *line = arguments->line; void (*func)() = arguments->func; delete arguments; @@ -101,28 +102,26 @@ void *interruptHandler(void *args) return NULL; } - // Setup poll structure - polls.fd = fd; - polls.events = POLLPRI | POLLERR; - while (1) { // Wait for it ... - int ret = poll(&polls, 1, -1); + // New version + int ret = gpiod_line_event_wait(line, NULL); if (ret < 0) { logError("Error waiting for interrupt: %s\n", strerror(errno)); break; } - // Do a dummy read to clear the interrupt - // A one character read appars to be enough. - if (lseek (fd, 0, SEEK_SET) < 0) { - logError("Interrupt handler error: %s\n", strerror(errno)); - break; - } - if (read (fd, &c, 1) < 0) { - logError("Interrupt handler error: %s\n", strerror(errno)); - break; + struct gpiod_line_event event; + if (gpiod_line_event_read(line, &event) == 0) { + if (event.event_type == GPIOD_LINE_EVENT_RISING_EDGE) { + logInfo("RISING Edge\n"); + } else { + logInfo("FALLING Edge\n"); + } } + // Call user function. + logError("Calling user function\n"); + pthread_mutex_lock(&intMutex); if (interruptsEnabled) { pthread_mutex_unlock(&intMutex); @@ -131,6 +130,8 @@ void *interruptHandler(void *args) pthread_mutex_unlock(&intMutex); } } + // Adding gpiod closing instructions + gpiod_line_release(line); close(fd); @@ -153,72 +154,53 @@ void attachInterrupt(uint8_t gpioPin, void (*func)(), uint8_t mode) usleep(1000); } - // Export pin for interrupt - if ((fd = fopen("/sys/class/gpio/export", "w")) == NULL) { - logError("attachInterrupt: Unable to export pin %d for interrupt: %s\n", gpioPin, strerror(errno)); - exit(1); - } - fprintf(fd, "%d\n", gpioPin); - fclose(fd); + char *chipname = "gpiochip0"; + unsigned int line_num = gpioPin; + struct gpiod_line_event event; + struct gpiod_chip *chip; + struct gpiod_line *line; - // Wait a bit the system to create /sys/class/gpio/gpio - usleep(1000); - snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/direction", gpioPin) ; - if ((fd = fopen (fName, "w")) == NULL) { - logError("attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n", - gpioPin, strerror(errno)); - exit(1) ; + chip = gpiod_chip_open_by_name(chipname); + if (!chip) { + logError("Open chip failed\n"); + exit(1); } - fprintf(fd, "in\n") ; - fclose(fd) ; - - snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/edge", gpioPin) ; - if ((fd = fopen(fName, "w")) == NULL) { - logError("attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", gpioPin, - strerror(errno)); - exit(1) ; + + line = gpiod_chip_get_line(chip, line_num); + if (!line) { + logError("Get line failed\n"); + exit(1); } switch (mode) { case CHANGE: - fprintf(fd, "both\n"); + gpiod_line_request_both_edges_events(line, "gpiointerrupt"); break; case FALLING: - fprintf(fd, "falling\n"); + gpiod_line_request_falling_edge_events(line, "gpiointerrupt"); break; case RISING: - fprintf(fd, "rising\n"); + gpiod_line_request_rising_edge_events(line, "gpiointerrupt"); break; case NONE: - fprintf(fd, "none\n"); break; default: logError("attachInterrupt: Invalid mode\n"); - fclose(fd); return; } - fclose(fd); if (sysFds[gpioPin] == -1) { - snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/value", gpioPin); - if ((sysFds[gpioPin] = open(fName, O_RDONLY)) < 0) { + if ((sysFds[gpioPin] = gpiod_line_event_get_fd(line)) < 0) { logError("Error reading pin %d: %s\n", gpioPin, strerror(errno)); exit(1); } } - // Clear any initial pending interrupt - ioctl(sysFds[gpioPin], FIONREAD, &count); - for (int i = 0; i < count; ++i) { - if (read(sysFds[gpioPin], &c, 1) == -1) { - logError("attachInterrupt: failed to read pin status: %s\n", strerror(errno)); - } - } - struct ThreadArgs *threadArgs = new struct ThreadArgs; threadArgs->func = func; threadArgs->gpioPin = gpioPin; + threadArgs->line = line; // Create a thread passing the pin and function pthread_create(threadIds[gpioPin], NULL, interruptHandler, (void *)threadArgs); @@ -239,13 +221,13 @@ void detachInterrupt(uint8_t gpioPin) sysFds[gpioPin] = -1; } - FILE *fp = fopen("/sys/class/gpio/unexport", "w"); - if (fp == NULL) { - logError("Unable to unexport pin %d for interrupt\n", gpioPin); - exit(1); - } - fprintf(fp, "%d", gpioPin); - fclose(fp); +// FILE *fp = fopen("/sys/class/gpio/unexport", "w"); +// if (fp == NULL) { +// logError("Unable to unexport pin %d for interrupt\n", gpioPin); +// exit(1); +// } +// fprintf(fp, "%d", gpioPin); +// fclose(fp); } void interrupts() diff --git a/hal/architecture/Linux/drivers/core/interrupt.h b/hal/architecture/Linux/drivers/core/interrupt.h index b1589251b..b382e31ba 100644 --- a/hal/architecture/Linux/drivers/core/interrupt.h +++ b/hal/architecture/Linux/drivers/core/interrupt.h @@ -24,6 +24,9 @@ #include +// Ajout RRO +#include + #define CHANGE 1 #define FALLING 2 #define RISING 3 From 3dba00fd7a8050225e4e8278f7364c7ef2375d93 Mon Sep 17 00:00:00 2001 From: romaricr Date: Sat, 16 Mar 2024 16:49:55 +0100 Subject: [PATCH 2/3] Updated for style and minors non functional changes --- MyConfig.h | 2 +- hal/architecture/Linux/drivers/core/interrupt.cpp | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/MyConfig.h b/MyConfig.h index 4bf753658..c26ffdde2 100755 --- a/MyConfig.h +++ b/MyConfig.h @@ -442,7 +442,7 @@ * - RF24_PA_MAX = 0dBm */ #ifndef MY_RF24_PA_LEVEL -#define MY_RF24_PA_LEVEL (RF24_PA_MAX) +#define MY_RF24_PA_LEVEL (RF24_PA_HIGH) #endif /** diff --git a/hal/architecture/Linux/drivers/core/interrupt.cpp b/hal/architecture/Linux/drivers/core/interrupt.cpp index d11920fed..6fc50fe3f 100644 --- a/hal/architecture/Linux/drivers/core/interrupt.cpp +++ b/hal/architecture/Linux/drivers/core/interrupt.cpp @@ -131,7 +131,7 @@ void *interruptHandler(void *args) } } // Adding gpiod closing instructions - gpiod_line_release(line); + gpiod_line_release(line); close(fd); @@ -220,14 +220,6 @@ void detachInterrupt(uint8_t gpioPin) close(sysFds[gpioPin]); sysFds[gpioPin] = -1; } - -// FILE *fp = fopen("/sys/class/gpio/unexport", "w"); -// if (fp == NULL) { -// logError("Unable to unexport pin %d for interrupt\n", gpioPin); -// exit(1); -// } -// fprintf(fp, "%d", gpioPin); -// fclose(fp); } void interrupts() From f157ed03048705d629d078fe3e421926cc77d2f7 Mon Sep 17 00:00:00 2001 From: romaricr Date: Sat, 16 Mar 2024 16:51:23 +0100 Subject: [PATCH 3/3] Minor changes --- hal/architecture/Linux/drivers/core/interrupt.h | 1 - 1 file changed, 1 deletion(-) diff --git a/hal/architecture/Linux/drivers/core/interrupt.h b/hal/architecture/Linux/drivers/core/interrupt.h index b382e31ba..d503fbcd9 100644 --- a/hal/architecture/Linux/drivers/core/interrupt.h +++ b/hal/architecture/Linux/drivers/core/interrupt.h @@ -24,7 +24,6 @@ #include -// Ajout RRO #include #define CHANGE 1