2222#include < CoreMutex.h>
2323#include < hardware/gpio.h>
2424#include < hardware/sync.h>
25- #include < map>
2625#include " _freertos.h"
2726
2827
@@ -59,58 +58,34 @@ extern "C" void noInterrupts() {
5958 }
6059}
6160
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
6461auto_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];
8766
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
8869void _gpioInterruptDispatcher (uint gpio, uint32_t events) {
8970 (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 ();
10176 } else {
102- return ;
77+ voidFuncPtrParam cb = (voidFuncPtrParam)_gpioIrqCB[gpio];
78+ cb (_gpioIrqCBParam[gpio]);
10379 }
10480 }
105- cb->callback ();
10681}
10782
10883// To be called when appropriately protected w/IRQ and mutex protects
10984static 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 ) {
11287 gpio_set_irq_enabled (pin, 0x0f /* all */ , false );
113- _map. erase (pin) ;
88+ _gpioIrqEnabled &= ~mask ;
11489 }
11590}
11691
@@ -119,7 +94,7 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
11994 if (!m) {
12095 return ;
12196 }
122-
97+ uint64_t mask = 1LL << pin;
12398 uint32_t events;
12499 switch (mode) {
125100 case LOW: events = 1 ; break ;
@@ -131,8 +106,9 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
131106 }
132107 noInterrupts ();
133108 _detachInterruptInternal (pin);
134- CBInfo cb (callback);
135- _map.insert ({pin, cb});
109+ _gpioIrqEnabled |= mask;
110+ _gpioIrqUseParam &= ~mask; // No parameter
111+ _gpioIrqCB[pin] = (void *)callback;
136112 gpio_set_irq_enabled_with_callback (pin, events, true , _gpioInterruptDispatcher);
137113 interrupts ();
138114}
@@ -142,7 +118,7 @@ void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus m
142118 if (!m) {
143119 return ;
144120 }
145-
121+ uint64_t mask = 1LL << pin;
146122 uint32_t events;
147123 switch (mode) {
148124 case LOW: events = 1 ; break ;
@@ -154,8 +130,10 @@ void attachInterruptParam(pin_size_t pin, voidFuncPtrParam callback, PinStatus m
154130 }
155131 noInterrupts ();
156132 _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;
159137 gpio_set_irq_enabled_with_callback (pin, events, true , _gpioInterruptDispatcher);
160138 interrupts ();
161139}
0 commit comments