22
22
#include < CoreMutex.h>
23
23
#include < hardware/gpio.h>
24
24
#include < hardware/sync.h>
25
- #include < map>
26
25
#include " _freertos.h"
27
26
28
27
@@ -59,58 +58,34 @@ extern "C" void noInterrupts() {
59
58
}
60
59
}
61
60
62
- // Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
63
- // dispatch to the real callback manually
64
61
auto_init_mutex (_irqMutex);
65
- class CBInfo {
66
- public:
67
- CBInfo (voidFuncPtr cb) : _cb(cb), _useParam(false ), _param(nullptr ) { };
68
- CBInfo (voidFuncPtrParam cbParam, void *param) : _cbParam(cbParam), _useParam(true ), _param(param) { };
69
- void callback () {
70
- if (_useParam && _cbParam) {
71
- _cbParam (_param);
72
- } else if (_cb) {
73
- _cb ();
74
- }
75
- }
76
- private:
77
- union {
78
- voidFuncPtr _cb;
79
- voidFuncPtrParam _cbParam;
80
- };
81
- bool _useParam;
82
- void *_param;
83
- };
84
-
85
-
86
- static std::map<pin_size_t , CBInfo> _map;
62
+ static uint64_t _gpioIrqEnabled = 0 ; // Sized to work with RP2350B, 48 GPIOs
63
+ static uint64_t _gpioIrqUseParam;
64
+ void *_gpioIrqCB[__GPIOCNT];
65
+ void *_gpioIrqCBParam[__GPIOCNT];
87
66
67
+ // Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
68
+ // dispatch to the real callback manually
88
69
void _gpioInterruptDispatcher (uint gpio, uint32_t events) {
89
70
(void ) events;
90
-
91
- // Only need to lock around the std::map check, not the whole IRQ callback
92
- CBInfo *cb;
93
- {
94
- CoreMutex m (&_irqMutex);
95
- if (m) {
96
- auto irq = _map.find (gpio);
97
- if (irq == _map.end ()) {
98
- return ;
99
- }
100
- cb = &irq->second ;
71
+ uint64_t mask = 1LL << gpio;
72
+ if (_gpioIrqEnabled & mask) {
73
+ if (_gpioIrqUseParam & mask) {
74
+ voidFuncPtr cb = (voidFuncPtr)_gpioIrqCB[gpio];
75
+ cb ();
101
76
} else {
102
- return ;
77
+ voidFuncPtrParam cb = (voidFuncPtrParam)_gpioIrqCB[gpio];
78
+ cb (_gpioIrqCBParam[gpio]);
103
79
}
104
80
}
105
- cb->callback ();
106
81
}
107
82
108
83
// To be called when appropriately protected w/IRQ and mutex protects
109
84
static void _detachInterruptInternal (pin_size_t pin) {
110
- auto irq = _map. find ( pin) ;
111
- if (irq != _map. end () ) {
85
+ uint64_t mask = 1LL << pin;
86
+ if (_gpioIrqEnabled & mask ) {
112
87
gpio_set_irq_enabled (pin, 0x0f /* all */ , false );
113
- _map. erase (pin) ;
88
+ _gpioIrqEnabled &= ~mask ;
114
89
}
115
90
}
116
91
@@ -119,7 +94,7 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
119
94
if (!m) {
120
95
return ;
121
96
}
122
-
97
+ uint64_t mask = 1LL << pin;
123
98
uint32_t events;
124
99
switch (mode) {
125
100
case LOW: events = 1 ; break ;
@@ -131,8 +106,9 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
131
106
}
132
107
noInterrupts ();
133
108
_detachInterruptInternal (pin);
134
- CBInfo cb (callback);
135
- _map.insert ({pin, cb});
109
+ _gpioIrqEnabled |= mask;
110
+ _gpioIrqUseParam &= ~mask; // No parameter
111
+ _gpioIrqCB[pin] = (void *)callback;
136
112
gpio_set_irq_enabled_with_callback (pin, events, true , _gpioInterruptDispatcher);
137
113
interrupts ();
138
114
}
@@ -142,7 +118,7 @@ void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus m
142
118
if (!m) {
143
119
return ;
144
120
}
145
-
121
+ uint64_t mask = 1LL << pin;
146
122
uint32_t events;
147
123
switch (mode) {
148
124
case LOW: events = 1 ; break ;
@@ -154,8 +130,10 @@ void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus m
154
130
}
155
131
noInterrupts ();
156
132
_detachInterruptInternal (pin);
157
- CBInfo cb (callback, param);
158
- _map.insert ({pin, cb});
133
+ _gpioIrqEnabled |= mask;
134
+ _gpioIrqUseParam &= ~mask; // No parameter
135
+ _gpioIrqCB[pin] = (void *)callback;
136
+ _gpioIrqCBParam[pin] = param;
159
137
gpio_set_irq_enabled_with_callback (pin, events, true , _gpioInterruptDispatcher);
160
138
interrupts ();
161
139
}
0 commit comments