Skip to content

Commit c546148

Browse files
committed
use shared pin FD cache
resolves #1026
1 parent 81b51b3 commit c546148

File tree

5 files changed

+33
-18
lines changed

5 files changed

+33
-18
lines changed

examples_pico/interruptConfigure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ void loop()
287287
*/
288288
void interruptHandler(uint gpio, uint32_t events)
289289
{
290-
if (gpio != IRQ_PIN && !(events | GPIO_IRQ_EDGE_FALL)) {
290+
if (gpio != IRQ_PIN && !(events & GPIO_IRQ_EDGE_FALL)) {
291291
// the gpio pin and event does not match the configuration we specified
292292
return;
293293
}

utility/SPIDEV/gpio.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,16 @@
1111
#include <sys/ioctl.h> // ioctl()
1212
#include <errno.h> // errno, strerror()
1313
#include <string.h> // std::string, strcpy()
14-
#include <map>
1514
#include "gpio.h"
1615

1716
// instantiate some global structs to setup cache
1817
// doing this globally ensures the data struct is zero-ed out
19-
typedef int gpio_fd; // for readability
20-
std::map<rf24_gpio_pin_t, gpio_fd> cachedPins;
2118
struct gpio_v2_line_request request;
2219
struct gpio_v2_line_values data;
2320

24-
// initialize static member.
21+
// initialize static members.
2522
int GPIOChipCache::fd = -1;
23+
std::map<rf24_gpio_pin_t, gpio_fd> GPIOChipCache::cachedPins = std::map<rf24_gpio_pin_t, gpio_fd>();
2624

2725
void GPIOChipCache::openDevice()
2826
{
@@ -97,8 +95,8 @@ void GPIO::open(rf24_gpio_pin_t port, int DDR)
9795
}
9896

9997
// check if pin is already in use
100-
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = cachedPins.find(port);
101-
if (pin == cachedPins.end()) { // pin not in use; add it to cached request
98+
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = gpioCache.cachedPins.find(port);
99+
if (pin == gpioCache.cachedPins.end()) { // pin not in use; add it to cached request
102100
request.offsets[0] = port;
103101
request.fd = 0;
104102
}
@@ -127,25 +125,25 @@ void GPIO::open(rf24_gpio_pin_t port, int DDR)
127125
throw GPIOException(msg);
128126
return;
129127
}
130-
cachedPins.insert(std::pair<rf24_gpio_pin_t, gpio_fd>(port, request.fd));
128+
gpioCache.cachedPins.insert(std::pair<rf24_gpio_pin_t, gpio_fd>(port, request.fd));
131129
}
132130

133131
void GPIO::close(rf24_gpio_pin_t port)
134132
{
135-
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = cachedPins.find(port);
136-
if (pin == cachedPins.end()) {
133+
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = gpioCache.cachedPins.find(port);
134+
if (pin == gpioCache.cachedPins.end()) {
137135
return;
138136
}
139137
if (pin->second > 0) {
140138
::close(pin->second);
141139
}
142-
cachedPins.erase(pin);
140+
gpioCache.cachedPins.erase(pin);
143141
}
144142

145143
int GPIO::read(rf24_gpio_pin_t port)
146144
{
147-
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = cachedPins.find(port);
148-
if (pin == cachedPins.end() || pin->second <= 0) {
145+
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = gpioCache.cachedPins.find(port);
146+
if (pin == gpioCache.cachedPins.end() || pin->second <= 0) {
149147
throw GPIOException("[GPIO::read] pin not initialized! Use GPIO::open() first");
150148
return -1;
151149
}
@@ -164,8 +162,8 @@ int GPIO::read(rf24_gpio_pin_t port)
164162

165163
void GPIO::write(rf24_gpio_pin_t port, int value)
166164
{
167-
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = cachedPins.find(port);
168-
if (pin == cachedPins.end() || pin->second <= 0) {
165+
std::map<rf24_gpio_pin_t, gpio_fd>::iterator pin = gpioCache.cachedPins.find(port);
166+
if (pin == gpioCache.cachedPins.end() || pin->second <= 0) {
169167
throw GPIOException("[GPIO::write] pin not initialized! Use GPIO::open() first");
170168
return;
171169
}

utility/SPIDEV/gpio.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <stdexcept>
1717
#include <cstdint>
18+
#include <map>
1819
#include "linux/gpio.h" // gpiochip_info
1920

2021
typedef uint16_t rf24_gpio_pin_t;
@@ -35,6 +36,8 @@ class GPIOException : public std::runtime_error
3536
}
3637
};
3738

39+
typedef int gpio_fd; // for readability
40+
3841
/// A struct to manage the GPIO chip file descriptor.
3942
/// This struct's destructor should close any cached GPIO pin requests' file descriptors.
4043
struct GPIOChipCache
@@ -48,6 +51,12 @@ struct GPIOChipCache
4851
/// struct use the same file descriptor.
4952
static int fd;
5053

54+
/// @brief The map of pin numbers to their corresponding file descriptors.
55+
///
56+
/// Because this member is static, all instances (& derivative instances) of this
57+
/// struct use the same mapping.
58+
static std::map<rf24_gpio_pin_t, gpio_fd> cachedPins;
59+
5160
/// Open the File Descriptor for the GPIO chip
5261
void openDevice();
5362

utility/SPIDEV/interrupt.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,21 @@ int attachInterrupt(rf24_gpio_pin_t pin, int mode, void (*function)(void))
133133
IrqPinCache irqPinCache;
134134
irqPinCache.fd = request.fd;
135135
irqPinCache.function = function;
136-
std::pair<std::map<rf24_gpio_pin_t, IrqPinCache>::iterator, bool> indexPair = irqCache.insert(std::pair<rf24_gpio_pin_t, IrqPinCache>(pin, irqPinCache));
137136

137+
std::pair<std::map<rf24_gpio_pin_t, IrqPinCache>::iterator, bool> indexPair = irqCache.insert(std::pair<rf24_gpio_pin_t, IrqPinCache>(pin, irqPinCache));
138138
if (!indexPair.second) {
139139
// this should not be reached, but indexPair.first needs to be the inserted map element
140140
throw IRQException("[attachInterrupt] Could not cache the IRQ pin with function pointer");
141141
return 0;
142142
}
143143

144+
std::pair<std::map<rf24_gpio_pin_t, gpio_fd>::iterator, bool> gpioPair = irqChipCache.cachedPins.insert(std::pair<rf24_gpio_pin_t, gpio_fd>(pin, request.fd));
145+
if (!gpioPair.second) {
146+
// this should not be reached, but indexPair.first needs to be the inserted map element
147+
throw IRQException("[attachInterrupt] Could not cache the GPIO pin's file descriptor");
148+
return 0;
149+
}
150+
144151
// create and start thread
145152
pthread_mutex_lock(&irq_mutex);
146153
pthread_create(&indexPair.first->second.id, nullptr, poll_irq, &indexPair.first->second);
@@ -157,8 +164,9 @@ int detachInterrupt(rf24_gpio_pin_t pin)
157164
}
158165
pthread_cancel(cachedPin->second.id); // send cancel request
159166
pthread_join(cachedPin->second.id, NULL); // wait till thread terminates
160-
close(cachedPin->second.fd);
161167
irqCache.erase(cachedPin);
168+
// reconfigure the pin for basic `digitalRead()`
169+
GPIO::open(pin, GPIO::DIRECTION_IN);
162170
return 1;
163171
}
164172

utility/SPIDEV/interrupt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct IrqPinCache
4646
int attachInterrupt(rf24_gpio_pin_t pin, int mode, void (*function)(void));
4747

4848
/**
49-
* Will cancel the interrupt thread, close the filehandle and release the pin.
49+
* Will cancel the interrupt thread and re-configure the pin for `digitalRead()` use.
5050
*/
5151
int detachInterrupt(rf24_gpio_pin_t pin);
5252

0 commit comments

Comments
 (0)