Skip to content

Commit 4ede3ff

Browse files
Add attachInterruptParam (#602)
Fixed #601 Allows apps to provide a callback parameter in the `attachInterrupt` call to be passed back to the function when the interrupt happens.
1 parent a58154b commit 4ede3ff

File tree

1 file changed

+53
-15
lines changed

1 file changed

+53
-15
lines changed

cores/rp2040/wiring_private.cpp

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,40 @@ extern "C" void noInterrupts() {
4545
// Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
4646
// dispatch to the real callback manually
4747
auto_init_mutex(_irqMutex);
48-
static std::map<pin_size_t, voidFuncPtr> _map;
48+
class CBInfo {
49+
public:
50+
CBInfo(voidFuncPtr cb) : _cb(cb), _useParam(false), _param(nullptr) { };
51+
CBInfo(voidFuncPtrParam cbParam, void *param) : _cbParam(cbParam), _useParam(true), _param(param) { };
52+
void callback() {
53+
if (_useParam && _cbParam) {
54+
_cbParam(_param);
55+
} else if (_cb) {
56+
_cb();
57+
}
58+
}
59+
private:
60+
union {
61+
voidFuncPtr _cb;
62+
voidFuncPtrParam _cbParam;
63+
};
64+
bool _useParam;
65+
void *_param;
66+
};
67+
68+
69+
static std::map<pin_size_t, CBInfo> _map;
4970

5071
void _gpioInterruptDispatcher(uint gpio, uint32_t events) {
5172
(void) events;
5273
// Only need to lock around the std::map check, not the whole IRQ callback
53-
voidFuncPtr cb = nullptr;
54-
{
55-
CoreMutex m(&_irqMutex);
56-
if (m) {
57-
auto irq = _map.find(gpio);
58-
if (irq != _map.end()) {
59-
cb = irq->second;
60-
}
74+
CoreMutex m(&_irqMutex);
75+
if (m) {
76+
auto irq = _map.find(gpio);
77+
if (irq != _map.end()) {
78+
auto cb = irq->second;
79+
cb.callback();
6180
}
6281
}
63-
if (cb) {
64-
cb(); // Do the callback
65-
} else {
66-
// ERROR, but we're in an IRQ so do nothing
67-
}
6882
}
6983

7084
extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus mode) {
@@ -84,7 +98,31 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
8498
}
8599
noInterrupts();
86100
detachInterrupt(pin);
87-
_map.insert({pin, callback});
101+
CBInfo cb(callback);
102+
_map.insert({pin, cb});
103+
gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher);
104+
interrupts();
105+
}
106+
107+
void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus mode, void *param) {
108+
CoreMutex m(&_irqMutex);
109+
if (!m) {
110+
return;
111+
}
112+
113+
uint32_t events;
114+
switch (mode) {
115+
case LOW: events = 1; break;
116+
case HIGH: events = 2; break;
117+
case FALLING: events = 4; break;
118+
case RISING: events = 8; break;
119+
case CHANGE: events = 4 | 8; break;
120+
default: return; // ERROR
121+
}
122+
noInterrupts();
123+
detachInterrupt(pin);
124+
CBInfo cb(callback, param);
125+
_map.insert({pin, cb});
88126
gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher);
89127
interrupts();
90128
}

0 commit comments

Comments
 (0)