@@ -473,7 +473,7 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) {
|
||||
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);
|
||||
printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.pinBCM, edgeType, wfiStatus.timeStamp_us, timenow, diff);
|
||||
if (toggle == 0) {
|
||||
digitalWrite (OUTpin, HIGH);
|
||||
toggle = 1;
|
||||
@@ -500,19 +500,19 @@ int main (void)
|
||||
|
||||
printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT);
|
||||
struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI);
|
||||
if (wfiStatus.status < 0) {
|
||||
if (wfiStatus.statusOK < 0) {
|
||||
printf("waitForInterrupt returned error\n");
|
||||
pinMode(OUTpin, INPUT);
|
||||
return 0;
|
||||
}
|
||||
else if (wfiStatus.status == 0) {
|
||||
else if (wfiStatus.statusOK == 0) {
|
||||
printf("waitForInterrupt timed out\n\n");
|
||||
}
|
||||
else {
|
||||
if (wfiStatus.edge == INT_EDGE_FALLING)
|
||||
printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us);
|
||||
printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
|
||||
else
|
||||
printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us);
|
||||
printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
|
||||
}
|
||||
|
||||
printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin);
|
||||
@@ -809,8 +809,8 @@ int wiringPiSPISetupMode(int channel, int speed, int mode)
|
||||
int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode)
|
||||
```
|
||||
|
||||
``number``: SPI Nummer (typisch 0, bei Compute Modul 0-7).
|
||||
``channel``: SPI Kanal (typisch 0 oder 1, bei Compute Modul 0-3).
|
||||
``number``: SPI Nummer (typisch 0, bei Compute Modul 0-6).
|
||||
``channel``: SPI Kanal (typisch 0 oder 1, bei Compute Modul oder entsprechenden overlay 0-4).
|
||||
``speed``: SPI Taktrate.
|
||||
``mode``: SPI Modus (https://www.kernel.org/doc/Documentation/spi/spidev).
|
||||
``Rückgabewert``: Datei Handle zum SPI-Bus
|
||||
|
||||
@@ -470,7 +470,7 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) {
|
||||
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);
|
||||
printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.pinBCM, edgeType, wfiStatus.timeStamp_us, timenow, diff);
|
||||
if (toggle == 0) {
|
||||
digitalWrite (OUTpin, HIGH);
|
||||
toggle = 1;
|
||||
@@ -497,19 +497,19 @@ int main (void)
|
||||
|
||||
printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT);
|
||||
struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI);
|
||||
if (wfiStatus.status < 0) {
|
||||
if (wfiStatus.statusOK < 0) {
|
||||
printf("waitForInterrupt returned error\n");
|
||||
pinMode(OUTpin, INPUT);
|
||||
return 0;
|
||||
}
|
||||
else if (wfiStatus.status == 0) {
|
||||
else if (wfiStatus.statusOK == 0) {
|
||||
printf("waitForInterrupt timed out\n\n");
|
||||
}
|
||||
else {
|
||||
if (wfiStatus.edge == INT_EDGE_FALLING)
|
||||
printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us);
|
||||
printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
|
||||
else
|
||||
printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us);
|
||||
printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
|
||||
}
|
||||
|
||||
printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin);
|
||||
@@ -798,8 +798,8 @@ int wiringPiSPISetupMode(int channel, int speed, int mode);
|
||||
int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode);
|
||||
```
|
||||
|
||||
``number``: SPI number (typically 0, on Compute Module 0-7).
|
||||
``channel``: SPI channel (typically 0 or 1, on Compute Module 0-3).
|
||||
``number``: SPI number (typically 0, on Compute Module 0-6).
|
||||
``channel``: SPI channel (typically 0 or 1, on Compute Module or the corresponding overlay 0-4).
|
||||
``speed``: SPI clock speed in Hz (500,000 to 32,000,000).
|
||||
``mode``: SPI mode ([www.kernel.org/doc/Documentation/spi/spidev](https://www.kernel.org/doc/Documentation/spi/spidev)).
|
||||
``Return Value``: File handle to the SPI bus, or -1 on error.
|
||||
|
||||
@@ -282,7 +282,7 @@ Please report bugs to https://github.com/WiringPi/WiringPi/issues
|
||||
|
||||
.SH COPYRIGHT
|
||||
|
||||
Copyright (c) 2012-2025 Gordon Henderson and contributors
|
||||
Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
.br
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* gpio.c:
|
||||
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
|
||||
* Pi's GPIO.
|
||||
* Copyright (c) 2012-2025 Gordon Henderson and contributors
|
||||
* Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://github.com/WiringPi/WiringPi/
|
||||
@@ -916,7 +916,7 @@ static void doVersion (char *argv [])
|
||||
|
||||
wiringPiVersion (&vMaj, &vMin) ;
|
||||
printf ("gpio version: %d.%d\n", vMaj, vMin) ;
|
||||
printf ("Copyright (c) 2012-2025 Gordon Henderson and contributors\n") ;
|
||||
printf ("Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors\n") ;
|
||||
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
|
||||
printf ("For details type: %s -warranty\n", argv [0]) ;
|
||||
printf ("\n") ;
|
||||
@@ -1033,7 +1033,7 @@ int main (int argc, char *argv [])
|
||||
if (strcasecmp (argv [1], "-warranty") == 0)
|
||||
{
|
||||
printf ("gpio version: %s\n", VERSION) ;
|
||||
printf ("Copyright (c) 2012-2025 Gordon Henderson and contributors\n") ;
|
||||
printf ("Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors\n") ;
|
||||
printf ("\n") ;
|
||||
printf (" This program is free software; you can redistribute it and/or modify\n") ;
|
||||
printf (" it under the terms of the GNU Leser General Public License as published\n") ;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* readall.c:
|
||||
* The readall functions - getting a bit big, so split them out.
|
||||
* Copyright (c) 2012-2024 Gordon Henderson and contributors
|
||||
* Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://github.com/WiringPi/WiringPi/
|
||||
|
||||
90
gpio/test/gpio_test1_piface1.sh
Executable file
90
gpio/test/gpio_test1_piface1.sh
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo -e "🔧 Starting relay unit test for MCP23S17@Piface unit test hw\n\n"
|
||||
|
||||
# set pin 200–207 as output
|
||||
for i in {200..207}; do
|
||||
gpio -x mcp23s17:200:0:0 mode $i out
|
||||
done
|
||||
|
||||
# set pin 208–215 as input
|
||||
for i in {208..215}; do
|
||||
gpio -x mcp23s17:200:0:0 mode $i in
|
||||
gpio -x mcp23s17:200:0:0 mode $i up
|
||||
done
|
||||
|
||||
|
||||
# Define relay output addresses and corresponding feedback input addresses
|
||||
relay_addresses=(200 201 207 206)
|
||||
feedback_addresses=(214 215 212 213)
|
||||
|
||||
for round in {1..3}; do
|
||||
echo -e "🔄 Round $round / 3\n"
|
||||
|
||||
# Loop through each relay
|
||||
for i in "${!relay_addresses[@]}"; do
|
||||
out=${relay_addresses[$i]}
|
||||
in=${feedback_addresses[$i]}
|
||||
|
||||
echo "➡️ Relay/IO write test $((i+1)): Address $out → Feedback at $in"
|
||||
|
||||
# Turn ON
|
||||
gpio -x mcp23s17:200:0:0 write "$out" 1
|
||||
sleep 0.5
|
||||
feedback_on=$(gpio -x mcp23s17:200:0:0 read "$in")
|
||||
|
||||
if [ "$feedback_on" -eq 0 ]; then
|
||||
echo "✅ ON Test passed: Feedback is LOW as expected."
|
||||
else
|
||||
echo "❌ ON Test failed: Feedback is HIGH."
|
||||
fi
|
||||
|
||||
# Turn OFF
|
||||
gpio -x mcp23s17:200:0:0 write "$out" 0
|
||||
sleep 0.5
|
||||
feedback_off=$(gpio -x mcp23s17:200:0:0 read "$in")
|
||||
|
||||
if [ "$feedback_off" -eq 1 ]; then
|
||||
echo "✅ OFF Test passed: Feedback is HIGH as expected."
|
||||
else
|
||||
echo "❌ OFF Test failed: Feedback is LOW."
|
||||
fi
|
||||
|
||||
echo -e "\n"
|
||||
sleep 0.5
|
||||
|
||||
done
|
||||
for addr in {208..211}; do
|
||||
|
||||
echo "🔃 Pullup resistor test address $addr: "
|
||||
gpio -x mcp23s17:200:0:0 mode "$addr" up
|
||||
sleep 0.5
|
||||
feedback_on=$(gpio -x mcp23s17:200:0:0 read "$addr")
|
||||
|
||||
if [ "$feedback_on" -eq 1 ]; then
|
||||
echo "✅ PULLUP Test passed: Feedback is HIGH as expected."
|
||||
else
|
||||
echo "❌ PULLUP Test failed: Feedback is LOW."
|
||||
fi
|
||||
sleep 0.5
|
||||
|
||||
gpio -x mcp23s17:200:0:0 mode "$addr" down
|
||||
sleep 0.5
|
||||
feedback_on=$(gpio -x mcp23s17:200:0:0 read "$addr")
|
||||
|
||||
if [ "$feedback_on" -eq 1 ]; then
|
||||
echo "✅ PULLDOWN Test passed: Feedback is LOW as expected."
|
||||
else
|
||||
echo "❌ PULLDOW Test failed: Feedback is HIGH."
|
||||
fi
|
||||
|
||||
echo -e "\n"
|
||||
sleep 0.5
|
||||
|
||||
|
||||
done
|
||||
|
||||
done
|
||||
|
||||
#echo "🧹 Cleanup complete. All relays turned OFF."
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#define VERSION "3.16"
|
||||
#define VERSION "3.18"
|
||||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 16
|
||||
#define VERSION_MINOR 18
|
||||
|
||||
2
wiringPi/gtest/.gitignore
vendored
Normal file
2
wiringPi/gtest/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
googletest-main
|
||||
92
wiringPi/gtest/Makefile
Normal file
92
wiringPi/gtest/Makefile
Normal file
@@ -0,0 +1,92 @@
|
||||
CXX := g++
|
||||
CXXFLAGS := -std=c++17 -Wall -Wextra -Werror -g \
|
||||
-Igoogletest-main/googletest/include -Igoogletest-main/googlemock/include
|
||||
LDFLAGS := -pthread
|
||||
WIRING_PI_LIBS := -lwiringPi
|
||||
|
||||
# Where to download googletest
|
||||
GTEST_URL := https://github.com/google/googletest/archive/refs/heads/main.zip
|
||||
GTEST_ZIP := googletest.zip
|
||||
GTEST_DIR := googletest-main
|
||||
|
||||
# Output directory
|
||||
BIN_DIR := bin
|
||||
|
||||
# Helper program
|
||||
RUN_ISR_SRC := run_isr.cpp
|
||||
RUN_ISR_BIN := $(BIN_DIR)/run_isr
|
||||
|
||||
# Need BCM17 <-> BCM18 connection
|
||||
TEST_SRCS := \
|
||||
test_isr_both.cpp \
|
||||
test_isr_conflict_between_processes.cpp \
|
||||
test_isr_falling.cpp \
|
||||
test_isr_restart.cpp \
|
||||
test_isr_restart2.cpp \
|
||||
test_isr_rising.cpp \
|
||||
test_isr_rising2.cpp
|
||||
|
||||
# Derive test binaries (in bin/)
|
||||
TEST_BINS := $(addprefix $(BIN_DIR)/, $(TEST_SRCS:.cpp=))
|
||||
|
||||
# gtest/gmock sources
|
||||
GTEST_SRCS := $(GTEST_DIR)/googletest/src/gtest-all.cc
|
||||
GMOCK_SRCS := $(GTEST_DIR)/googlemock/src/gmock-all.cc
|
||||
GTEST_MAIN := $(GTEST_DIR)/googletest/src/gtest_main.cc
|
||||
GTEST_INCLUDES := -I$(GTEST_DIR)/googletest/include -I$(GTEST_DIR)/googlemock/include
|
||||
|
||||
GTEST_OBJS := $(GTEST_SRCS:.cc=.o)
|
||||
GMOCK_OBJS := $(GMOCK_SRCS:.cc=.o)
|
||||
GTEST_MAIN_OBJ := $(GTEST_MAIN:.cc=.o)
|
||||
|
||||
# Default: build everything
|
||||
all: $(GTEST_DIR) $(BIN_DIR) $(TEST_BINS) $(RUN_ISR_BIN)
|
||||
|
||||
# Rule: build normal test binaries
|
||||
$(filter-out $(BIN_DIR)/test_conflict_between_processes,$(TEST_BINS)): $(BIN_DIR)/%: %.cpp $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ)
|
||||
$(CXX) $(CXXFLAGS) $< $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) -o $@ $(LDFLAGS) $(WIRING_PI_LIBS)
|
||||
|
||||
# Special case: test_conflict_between_processes depends on run_isr
|
||||
$(BIN_DIR)/test_conflict_between_processes: test_conflict_between_processes.cpp $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) $(RUN_ISR_BIN)
|
||||
$(CXX) $(CXXFLAGS) $< $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) -o $@ $(LDFLAGS) $(WIRING_PI_LIBS)
|
||||
|
||||
# Build run_isr
|
||||
$(RUN_ISR_BIN): $(RUN_ISR_SRC) | $(BIN_DIR)
|
||||
$(CXX) $(CXXFLAGS) $< -o $@ $(WIRING_PI_LIBS)
|
||||
|
||||
# Ensure bin directory exists
|
||||
$(BIN_DIR):
|
||||
mkdir -p $(BIN_DIR)
|
||||
|
||||
# Download googletest if not already present
|
||||
$(GTEST_DIR):
|
||||
@echo "Downloading GoogleTest..."
|
||||
curl -L $(GTEST_URL) -o $(GTEST_ZIP)
|
||||
unzip -q $(GTEST_ZIP)
|
||||
rm -f $(GTEST_ZIP)
|
||||
|
||||
# Generic rules for compiling gtest/gmock sources
|
||||
%.o: %.cc
|
||||
$(CXX) $(CXXFLAGS) $(GTEST_INCLUDES) -I$(GTEST_DIR)/googletest -I$(GTEST_DIR)/googlemock -c $< -o $@
|
||||
|
||||
# Run all tests
|
||||
test: all
|
||||
@failed=0; \
|
||||
for t in $(TEST_BINS); do \
|
||||
echo "Running $$t..."; \
|
||||
./$$t || failed=1; \
|
||||
done; \
|
||||
if [ $$failed -eq 0 ]; then \
|
||||
echo "✅ All tests passed."; \
|
||||
else \
|
||||
echo "❌ Some tests failed."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
rm -f $(TEST_BINS) $(RUN_ISR_BIN)
|
||||
|
||||
distclean: clean
|
||||
rm -rf $(GTEST_DIR) $(BIN_DIR)
|
||||
|
||||
.PHONY: all clean distclean test
|
||||
26
wiringPi/gtest/README.md
Normal file
26
wiringPi/gtest/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
## Quick Start
|
||||
|
||||
g++ is required to build the test cases.
|
||||
|
||||
Connect wPi pin 1 (BCM 18) and wPi pin 0 (BCM 17) to run ISR tests.
|
||||
Also, wPi pin 6 (BCM 25) should be unconnected.
|
||||
|
||||
Run `make test` or do following to run the test:
|
||||
|
||||
```
|
||||
make googletest-main
|
||||
make -j 4
|
||||
make test
|
||||
```
|
||||
|
||||
To clean up the environment:
|
||||
|
||||
```
|
||||
make clean
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
Googletest is downloaded during
|
||||
the build for the first time. The downloaded items are in directory `googletest-main`. `make clean` keeps this directory. Run `make distclean`
|
||||
to erase all built images including googletest.
|
||||
31
wiringPi/gtest/run_isr.cpp
Normal file
31
wiringPi/gtest/run_isr.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Helper program of test_conflict_between_processes.
|
||||
*
|
||||
* The program configures ISR on pin 1 (BCM 18) and polls for a termination request.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
|
||||
static uint8_t ok_to_stop = 0;
|
||||
static void noop() {
|
||||
fprintf(stderr, "interrupted\n");
|
||||
ok_to_stop = 1;
|
||||
}
|
||||
|
||||
int main(int, char *[]) {
|
||||
fprintf(stderr, "start\n");
|
||||
wiringPiSetup();
|
||||
if (wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, noop)) {
|
||||
fprintf(stderr, "failed to start listener\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "start listening\n");
|
||||
|
||||
while (!ok_to_stop) {
|
||||
delay(1000);
|
||||
}
|
||||
fprintf(stderr, "bye\n");
|
||||
}
|
||||
51
wiringPi/gtest/test_isr_both.cpp
Normal file
51
wiringPi/gtest/test_isr_both.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <time.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define TRIGGER_PIN 0 // BCM 17
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
|
||||
/**
|
||||
* Tests ISR for both edges.
|
||||
*/
|
||||
class ISRBoth : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
wiringPiSetup();
|
||||
pinMode(TRIGGER_PIN, OUTPUT);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
wiringPiISR(LISTENER_PIN, INT_EDGE_BOTH, ISRBoth::TriggerCount);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
static uint32_t count;
|
||||
static void TriggerCount() { ++count; }
|
||||
|
||||
protected:
|
||||
virtual void SetUp() { count = 0; }
|
||||
|
||||
virtual void TearDown() {
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t ISRBoth::count = 0;
|
||||
|
||||
TEST_F(ISRBoth, Fundamental) {
|
||||
EXPECT_EQ(count, 0u);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 2u);
|
||||
}
|
||||
|
||||
TEST_F(ISRBoth, ThreeTriggers) {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
|
||||
delay(10);
|
||||
}
|
||||
EXPECT_EQ(count, 5u);
|
||||
}
|
||||
68
wiringPi/gtest/test_isr_conflict_between_processes.cpp
Normal file
68
wiringPi/gtest/test_isr_conflict_between_processes.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define TRIGGER_PIN 0 // BCM 17
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
#define ANOTHER_LISTENER_PIN 6 // BCM 25
|
||||
|
||||
static void *remote_isr(void *) {
|
||||
std::system("./bin/run_isr");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ISR setup conflict between two processes.
|
||||
*
|
||||
* Another program 'run_isr' starts first that occupies the pin 31 for an ISR.
|
||||
* This program should fail to start ISR on the same pin.
|
||||
*/
|
||||
class ISRConflict : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
wiringPiSetup();
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
|
||||
pthread_t tid;
|
||||
pthread_create(&tid, NULL, remote_isr, NULL);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
static uint32_t count;
|
||||
|
||||
static void TriggerCount() { ++count; }
|
||||
static void TriggerCount2(WPIWfiStatus, void *userdata) {
|
||||
++*(uint32_t *)userdata;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void SetUp() { count = 0; }
|
||||
|
||||
virtual void TearDown() {
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t ISRConflict::count = 0;
|
||||
|
||||
TEST_F(ISRConflict, TestConflictBetweenProcesses) {
|
||||
// The ISRs should fail to start because run_isr is listening on the
|
||||
// same port
|
||||
EXPECT_EQ(
|
||||
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRConflict::TriggerCount),
|
||||
-1);
|
||||
EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING,
|
||||
ISRConflict::TriggerCount2, 0, &ISRConflict::count),
|
||||
-1);
|
||||
|
||||
// to exit run_isr
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
}
|
||||
57
wiringPi/gtest/test_isr_falling.cpp
Normal file
57
wiringPi/gtest/test_isr_falling.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <time.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define TRIGGER_PIN 0 // BCM 17
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
|
||||
/**
|
||||
* Tests ISR for falling edges.
|
||||
*/
|
||||
class ISRFalling : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
wiringPiSetup();
|
||||
pinMode(TRIGGER_PIN, OUTPUT);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRFalling::TriggerCount);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() { digitalWrite(TRIGGER_PIN, LOW); }
|
||||
|
||||
static uint32_t count;
|
||||
static void TriggerCount() { ++count; }
|
||||
|
||||
protected:
|
||||
virtual void SetUp() { count = 0; }
|
||||
|
||||
virtual void TearDown() {
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t ISRFalling::count = 0;
|
||||
|
||||
TEST_F(ISRFalling, Fundamental) {
|
||||
EXPECT_EQ(count, 0u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
}
|
||||
|
||||
TEST_F(ISRFalling, ThreeTriggers) {
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
count = 0;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
delay(10);
|
||||
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
|
||||
}
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 3u);
|
||||
}
|
||||
68
wiringPi/gtest/test_isr_restart.cpp
Normal file
68
wiringPi/gtest/test_isr_restart.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <time.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define TRIGGER_PIN 0 // BCM 17
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
#define ANOTHER_LISTENER_PIN 6 // BCM 25
|
||||
|
||||
/**
|
||||
* Tests restarting ISR.
|
||||
*/
|
||||
class ISRRestart : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
wiringPiSetup();
|
||||
pinMode(TRIGGER_PIN, OUTPUT);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, ISRRestart::TriggerCount);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
static uint32_t count;
|
||||
|
||||
static void TriggerCount() { ++count; }
|
||||
|
||||
static void TriggerCountDown() { --count; }
|
||||
|
||||
protected:
|
||||
virtual void SetUp() { count = 0; }
|
||||
|
||||
virtual void TearDown() {
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t ISRRestart::count = 0;
|
||||
|
||||
TEST_F(ISRRestart, RestartISR) {
|
||||
// fundamental ISR test
|
||||
EXPECT_EQ(count, 0u);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
|
||||
// stop the ISR
|
||||
EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
|
||||
// start another ISR on the same pin
|
||||
EXPECT_EQ(
|
||||
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRRestart::TriggerCountDown),
|
||||
0);
|
||||
count=1;
|
||||
delay(100);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 0u);
|
||||
}
|
||||
109
wiringPi/gtest/test_isr_restart2.cpp
Normal file
109
wiringPi/gtest/test_isr_restart2.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <time.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define TRIGGER_PIN 0 // BCM 17
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
#define ANOTHER_LISTENER_PIN 26 // BCM 12
|
||||
|
||||
struct counters {
|
||||
int32_t *primary;
|
||||
int32_t *secondary;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests restarting ISR using function wiringPiISR2().
|
||||
*/
|
||||
class ISRRestart2 : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
wiringPiSetup();
|
||||
pinMode(TRIGGER_PIN, OUTPUT);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
counters_a.primary = &count;
|
||||
counters_a.secondary = &count2;
|
||||
counters_b.primary = &count;
|
||||
counters_b.secondary = &count3;
|
||||
wiringPiISR2(LISTENER_PIN, INT_EDGE_RISING, ISRRestart2::TriggerCount, 1000,
|
||||
&counters_a);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
static int32_t count;
|
||||
static int32_t count2;
|
||||
static int32_t count3;
|
||||
|
||||
static counters counters_a;
|
||||
static counters counters_b;
|
||||
|
||||
static void TriggerCount(WPIWfiStatus, void *userdata) {
|
||||
struct counters *counters = (struct counters *)userdata;
|
||||
++*counters->primary;
|
||||
++*counters->secondary;
|
||||
}
|
||||
|
||||
static void TriggerCountDown(WPIWfiStatus, void *userdata) {
|
||||
struct counters *counters = (struct counters *)userdata;
|
||||
++*counters->primary;
|
||||
--*counters->secondary;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
count = 0;
|
||||
count2 = 0;
|
||||
count3 = 0;
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
}
|
||||
};
|
||||
|
||||
int32_t ISRRestart2::count = 0;
|
||||
int32_t ISRRestart2::count2 = 0;
|
||||
int32_t ISRRestart2::count3 = 0;
|
||||
struct counters ISRRestart2::counters_a;
|
||||
struct counters ISRRestart2::counters_b;
|
||||
|
||||
TEST_F(ISRRestart2, RestartISR2) {
|
||||
// fundamental ISR2 test
|
||||
EXPECT_EQ(count, 0);
|
||||
EXPECT_EQ(count2, 0);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1);
|
||||
EXPECT_EQ(count2, 1);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1);
|
||||
EXPECT_EQ(count2, 1);
|
||||
|
||||
// stop the ISR
|
||||
EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0);
|
||||
delay(100);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1);
|
||||
EXPECT_EQ(count2, 1);
|
||||
EXPECT_EQ(count3, 0);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
|
||||
// start another ISR2 on the same pin
|
||||
EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING,
|
||||
ISRRestart2::TriggerCountDown, 0, &counters_b),
|
||||
0);
|
||||
delay(100);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1);
|
||||
EXPECT_EQ(count2, 1);
|
||||
EXPECT_EQ(count3, 0);
|
||||
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 2);
|
||||
EXPECT_EQ(count2, 1);
|
||||
EXPECT_EQ(count3, -1);
|
||||
}
|
||||
80
wiringPi/gtest/test_isr_rising.cpp
Normal file
80
wiringPi/gtest/test_isr_rising.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <time.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define TRIGGER_PIN 0 // BCM 17
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
#define ANOTHER_LISTENER_PIN 26 // BCM 12
|
||||
|
||||
/**
|
||||
* Tests ISR for rising edges.
|
||||
*/
|
||||
class ISRRising : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
wiringPiSetup();
|
||||
pinMode(TRIGGER_PIN, OUTPUT);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, ISRRising::TriggerCount);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
static uint32_t count;
|
||||
|
||||
static void TriggerCount() { ++count; }
|
||||
|
||||
static void TriggerCountDown() { --count; }
|
||||
|
||||
protected:
|
||||
virtual void SetUp() { count = 0; }
|
||||
|
||||
virtual void TearDown() {
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t ISRRising::count = 0;
|
||||
|
||||
TEST_F(ISRRising, Fundamental) {
|
||||
EXPECT_EQ(count, 0u);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
}
|
||||
|
||||
TEST_F(ISRRising, ThreeTriggers) {
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
count = 0;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
delay(10);
|
||||
digitalWrite(TRIGGER_PIN, i % 2);
|
||||
}
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 3u);
|
||||
}
|
||||
|
||||
TEST_F(ISRRising, ISRInitConflict) {
|
||||
// this initialization should fail for ISR conflict
|
||||
EXPECT_EQ(
|
||||
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRRising::TriggerCountDown),
|
||||
-1);
|
||||
// ensure the initialization above has released the mutex lock
|
||||
EXPECT_EQ(wiringPiISR(ANOTHER_LISTENER_PIN, INT_EDGE_RISING,
|
||||
ISRRising::TriggerCountDown),
|
||||
0);
|
||||
delay(100);
|
||||
|
||||
// ensure the existing ISR has not broken
|
||||
EXPECT_EQ(count, 0u);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
EXPECT_EQ(count, 1u);
|
||||
}
|
||||
136
wiringPi/gtest/test_isr_rising2.cpp
Normal file
136
wiringPi/gtest/test_isr_rising2.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <time.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
#define TRIGGER_PIN 0 // BCM 17
|
||||
#define LISTENER_PIN 1 // BCM 18
|
||||
#define ANOTHER_LISTENER_PIN 6 // BCM 25
|
||||
|
||||
struct counters {
|
||||
uint32_t *primary;
|
||||
uint32_t *secondary;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests ISR for rising edges.
|
||||
* Function wiringPiISR2 is used for the configuraiton.
|
||||
*/
|
||||
class ISRRising2 : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
wiringPiSetup();
|
||||
pinMode(TRIGGER_PIN, OUTPUT);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
counters_a.primary = &count;
|
||||
counters_a.secondary = &count2;
|
||||
counters_b.primary = &count;
|
||||
counters_b.secondary = &count3;
|
||||
wiringPiISR2(LISTENER_PIN, INT_EDGE_RISING, ISRRising2::TriggerCount, 1000,
|
||||
&counters_a);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
static uint32_t count;
|
||||
static uint32_t count2;
|
||||
static uint32_t count3;
|
||||
|
||||
static counters counters_a;
|
||||
static counters counters_b;
|
||||
|
||||
static void TriggerCount(WPIWfiStatus, void *userdata) {
|
||||
struct counters *counters = (struct counters *)userdata;
|
||||
++*counters->primary;
|
||||
++*counters->secondary;
|
||||
}
|
||||
|
||||
static void TriggerCountDown(WPIWfiStatus, void *userdata) {
|
||||
struct counters *counters = (struct counters *)userdata;
|
||||
++*counters->primary;
|
||||
--*counters->secondary;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
count = 0;
|
||||
count2 = 0;
|
||||
count3 = 0;
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(10);
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t ISRRising2::count = 0;
|
||||
uint32_t ISRRising2::count2 = 0;
|
||||
uint32_t ISRRising2::count3 = 0;
|
||||
struct counters ISRRising2::counters_a;
|
||||
struct counters ISRRising2::counters_b;
|
||||
|
||||
TEST_F(ISRRising2, Fundamental) {
|
||||
EXPECT_EQ(count, 0u);
|
||||
EXPECT_EQ(count2, 0u);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1u);
|
||||
EXPECT_EQ(count2, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1u);
|
||||
EXPECT_EQ(count2, 1u);
|
||||
}
|
||||
|
||||
TEST_F(ISRRising2, ThreeTriggers) {
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(10);
|
||||
count = 0;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
delay(20);
|
||||
digitalWrite(TRIGGER_PIN, i % 2);
|
||||
}
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 3u);
|
||||
}
|
||||
|
||||
TEST_F(ISRRising2, Debounce) {
|
||||
delay(20);
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
|
||||
}
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1u);
|
||||
}
|
||||
|
||||
TEST_F(ISRRising2, ISRInitConflict) {
|
||||
// this initialization should fail for ISR conflict
|
||||
EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING,
|
||||
ISRRising2::TriggerCountDown, 0, &counters_b),
|
||||
-1);
|
||||
// ensure the initialization above has released the mutex lock
|
||||
EXPECT_EQ(wiringPiISR2(ANOTHER_LISTENER_PIN, INT_EDGE_BOTH,
|
||||
ISRRising2::TriggerCountDown, 0, &counters_b),
|
||||
0);
|
||||
delay(100);
|
||||
|
||||
// ensure the existing ISR has not broken
|
||||
EXPECT_EQ(count, 0u);
|
||||
EXPECT_EQ(count2, 0u);
|
||||
digitalWrite(TRIGGER_PIN, HIGH);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1u);
|
||||
EXPECT_EQ(count2, 1u);
|
||||
digitalWrite(TRIGGER_PIN, LOW);
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1u);
|
||||
EXPECT_EQ(count2, 1u);
|
||||
|
||||
delay(20);
|
||||
count = 0;
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
delay(1);
|
||||
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
|
||||
}
|
||||
delay(20);
|
||||
EXPECT_EQ(count, 1u);
|
||||
}
|
||||
@@ -83,7 +83,8 @@ int main (void) {
|
||||
case PI_MODEL_400:
|
||||
case PI_MODEL_CM4:
|
||||
case PI_MODEL_CM4S:
|
||||
fExpectTimedigitalWrite = 0.020; //us
|
||||
//fExpectTimedigitalWrite = 0.020; //us - with kernel <6.12.47
|
||||
fExpectTimedigitalWrite = 0.016; //us
|
||||
fExpectTimedigitalRead = 0.038; //us
|
||||
fExpectTimepinMode = 0.121; //us
|
||||
fWriteReadDelayFactor = 1.86;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* wiringPi:
|
||||
* Arduino look-a-like Wiring library for the Raspberry Pi
|
||||
* Copyright (c) 2012-2025 Gordon Henderson and contributors
|
||||
* Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
* Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com>
|
||||
*
|
||||
* Thanks to code samples from Gert Jan van Loo and the
|
||||
@@ -2868,35 +2868,25 @@ int waitForInterruptClose(int pin) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* interruptHandlerInit:
|
||||
* Initializes an interrupt handler before starting the listener loop in a
|
||||
* separate thread.
|
||||
* Returns: >0 on successful initialization, 0 if the listener loop does not
|
||||
* have to start, -1 on error.
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
void *interruptHandlerV2(void *arg)
|
||||
static int interruptHandlerInit(int pin, int EdgeMode, unsigned long debounce_period_us)
|
||||
{
|
||||
const char* strmode = "";
|
||||
int pin, EdgeMode, ret, fd, attr, i;
|
||||
unsigned int readret;
|
||||
unsigned long debounce_period_us;
|
||||
struct pollfd polls ;
|
||||
int ret, attr;
|
||||
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;
|
||||
|
||||
if (wiringPiGpioDeviceGetFd() < 0) {
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
EdgeMode = isrEdgeMode[pin];
|
||||
debounce_period_us = isrDebouncePeriodUs[pin];
|
||||
|
||||
if (wiringPiDebug) {
|
||||
printf ("interruptHandlerV2: GPIO line %d, edge mode %d, debounce_period_us %lu \n", pin, EdgeMode, debounce_period_us) ;
|
||||
}
|
||||
@@ -2912,7 +2902,7 @@ void *interruptHandlerV2(void *arg)
|
||||
if (wiringPiDebug) {
|
||||
printf ("interruptHandlerV2: waitForInterruptMode edge mode INT_EDGE_SETUP - exiting\n") ;
|
||||
}
|
||||
return NULL;
|
||||
return 0;
|
||||
case INT_EDGE_FALLING:
|
||||
config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING;
|
||||
strmode = "falling";
|
||||
@@ -2944,14 +2934,44 @@ void *interruptHandlerV2(void *arg)
|
||||
ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req);
|
||||
if (ret == -1) {
|
||||
ReportDeviceError("interruptHandlerV2: get line event", pin , strmode, ret);
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wiringPiDebug)
|
||||
if (wiringPiDebug) {
|
||||
printf ("interruptHandlerV2: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd);
|
||||
}
|
||||
|
||||
return req.fd;
|
||||
}
|
||||
|
||||
struct interrupt_handler_params {
|
||||
int pin;
|
||||
int fd;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
static void *interruptHandlerV2(void *arg)
|
||||
{
|
||||
struct interrupt_handler_params *params;
|
||||
int pin, ret, fd, i;
|
||||
unsigned int readret;
|
||||
struct pollfd polls ;
|
||||
struct gpio_v2_line_event evdat[64];
|
||||
struct WPIWfiStatus wfiStatus;
|
||||
struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */
|
||||
|
||||
params = (struct interrupt_handler_params *)arg;
|
||||
pin = params->pin;
|
||||
fd = params->fd;
|
||||
|
||||
/* set event fd */
|
||||
fd = req.fd;
|
||||
isrFds [pin] = fd;
|
||||
|
||||
(void)piHiPri (55) ; // Only effective if we run as root
|
||||
@@ -3041,9 +3061,8 @@ void *interruptHandlerV2(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* wiringPiISR:
|
||||
* wiringPiISRInternal:
|
||||
* Pi Specific.
|
||||
* Take the details and create an interrupt handler that will do a call-
|
||||
* back to the user supplied function.
|
||||
@@ -3064,39 +3083,49 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta
|
||||
printf("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode);
|
||||
}
|
||||
if (isrFunctions[pin] || isrFunctionsV2[pin]) {
|
||||
fprintf(stderr, "wiringPi: ISR function already active, ignoring \n");
|
||||
fprintf(stderr, "wiringPi: ISR function already active\n");
|
||||
}
|
||||
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: mutex in\n");
|
||||
}
|
||||
pthread_mutex_lock (&pinMutex) ;
|
||||
struct interrupt_handler_params params = {
|
||||
.pin = pin,
|
||||
};
|
||||
params.fd = interruptHandlerInit(pin, edgeMode, debounce_period_us);
|
||||
if (params.fd < 0) {
|
||||
pthread_mutex_unlock (&pinMutex) ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// OK to start the new ISR. Update the table.
|
||||
isrFunctionsV2[pin] = function;
|
||||
isrUserdata[pin] = userdata;
|
||||
isrFunctions[pin] = functionClassic;
|
||||
isrEdgeMode[pin] = edgeMode;
|
||||
isrDebouncePeriodUs[pin] = debounce_period_us;
|
||||
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: mutex in\n");
|
||||
}
|
||||
pthread_mutex_lock (&pinMutex) ;
|
||||
pinPass = pin ;
|
||||
if (params.fd > 0) {
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]);
|
||||
}
|
||||
if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, &pin)==0) {
|
||||
if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, ¶ms)==0) {
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]);
|
||||
}
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
// wait so that interruptHandler is up und running.
|
||||
// when interruptHandler is running, the calling function wiringPiISRInternal
|
||||
// must be still alive, otherwise the thread argument ¶m points into nirwana,
|
||||
// when it is picked up from interruptHandlerV2.
|
||||
delay(10);
|
||||
}
|
||||
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: mutex out\n");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* wiringPi.h:
|
||||
* Arduino like Wiring library for the Raspberry Pi.
|
||||
* Copyright (c) 2012-2025 Gordon Henderson
|
||||
* Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://github.com/WiringPi/WiringPi/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* wiringPiI2C.c:
|
||||
* Simplified I2C access routines
|
||||
* Copyright (c) 2013-2024 Gordon Henderson and contributors
|
||||
* Copyright (c) 2013–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://github.com/WiringPi/WiringPi/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* wiringPiI2C.h:
|
||||
* Simplified I2C access routines
|
||||
* Copyright (c) 2013-2024 Gordon Henderson and contributors
|
||||
* Copyright (c) 2013–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://github.com/WiringPi/WiringPi/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* wiringPiSPI.c:
|
||||
* Simplified SPI access routines
|
||||
* Copyright (c) 2012-2025 Gordon Henderson and contributors
|
||||
* Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://github.com/WiringPi/WiringPi/
|
||||
@@ -44,9 +44,11 @@
|
||||
//static const char *spiDev1 = "/dev/spidev0.1" ;
|
||||
static const uint8_t spiBPW = 8 ;
|
||||
static const uint16_t spiDelay = 0 ;
|
||||
//https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf
|
||||
//https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf SPI0-6, CS0-2
|
||||
//cm5-datasheet.pdf SPI0-5, CS depend on SPInumber, can be up to 4
|
||||
//spi0-4cs.dts extention for supporting CS0-4
|
||||
const uint8_t WPI_MaxSPINumbers = 7 ;
|
||||
const uint8_t WPI_MaxSPIChannels = 3 ;
|
||||
const uint8_t WPI_MaxSPIChannels = 5 ;
|
||||
|
||||
|
||||
static uint32_t spiSpeeds [7][3] =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* wiringPiSPI.h:
|
||||
* Simplified SPI access routines
|
||||
* Copyright (c) 2012-2025 Gordon Henderson and contributors
|
||||
* Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://github.com/WiringPi/WiringPi/
|
||||
|
||||
Reference in New Issue
Block a user