Skip to content

Commit a7cf5cd

Browse files
authored
Fix GPIO interrupt on freeRTOS (#959)
1 parent 4e6e1d6 commit a7cf5cd

File tree

5 files changed

+31
-6
lines changed

5 files changed

+31
-6
lines changed

cores/rp2040/CoreMutex.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@
2424
#include "Arduino.h"
2525
#include "CoreMutex.h"
2626

27-
CoreMutex::CoreMutex(mutex_t *mutex, bool debugEnable) {
27+
CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) {
2828
_mutex = mutex;
2929
_acquired = false;
30+
_option = option;
3031
if (__isFreeRTOS) {
3132
auto m = __get_freertos_mutex_for_ptr(mutex);
32-
__freertos_mutex_take(m);
33+
if (_option & FromISR) {
34+
__freertos_mutex_take_from_isr(m);
35+
} else {
36+
__freertos_mutex_take(m);
37+
}
3338
} else {
3439
uint32_t owner;
3540
if (!mutex_try_enter(_mutex, &owner)) {
3641
if (owner == get_core_num()) { // Deadlock!
37-
if (debugEnable) {
42+
if (_option & DebugEnable) {
3843
DEBUGCORE("CoreMutex - Deadlock detected!\n");
3944
}
4045
return;
@@ -49,7 +54,11 @@ CoreMutex::~CoreMutex() {
4954
if (_acquired) {
5055
if (__isFreeRTOS) {
5156
auto m = __get_freertos_mutex_for_ptr(_mutex);
52-
__freertos_mutex_give(m);
57+
if (_option & FromISR) {
58+
__freertos_mutex_give_from_isr(m);
59+
} else {
60+
__freertos_mutex_give(m);
61+
}
5362
} else {
5463
mutex_exit(_mutex);
5564
}

cores/rp2040/CoreMutex.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,14 @@
2626
#include "pico/mutex.h"
2727
#include "_freertos.h"
2828

29+
enum {
30+
DebugEnable = 1,
31+
FromISR = 1 << 1,
32+
};
33+
2934
class CoreMutex {
3035
public:
31-
CoreMutex(mutex_t *mutex, bool debugEnable = true);
36+
CoreMutex(mutex_t *mutex, uint8_t option = DebugEnable);
3237
~CoreMutex();
3338

3439
operator bool() {
@@ -38,4 +43,5 @@ class CoreMutex {
3843
private:
3944
mutex_t *_mutex;
4045
bool _acquired;
46+
u_int8_t _option;
4147
};

cores/rp2040/_freertos.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ extern "C" {
4141
extern SemaphoreHandle_t _freertos_recursive_mutex_create() __attribute__((weak));
4242

4343
extern void __freertos_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak));
44+
extern void __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx) __attribute__((weak));
4445
extern int __freertos_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak));
4546
extern void __freertos_mutex_give(SemaphoreHandle_t mtx) __attribute__((weak));
47+
extern void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx) __attribute__((weak));
4648

4749
extern void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) __attribute__((weak));
4850
extern int __freertos_recursive_mutex_try_take(SemaphoreHandle_t mtx) __attribute__((weak));

cores/rp2040/wiring_private.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static std::map<pin_size_t, CBInfo> _map;
7777
void _gpioInterruptDispatcher(uint gpio, uint32_t events) {
7878
(void) events;
7979
// Only need to lock around the std::map check, not the whole IRQ callback
80-
CoreMutex m(&_irqMutex);
80+
CoreMutex m(&_irqMutex, (FromISR | DebugEnable));
8181
if (m) {
8282
auto irq = _map.find(gpio);
8383
if (irq != _map.end()) {

libraries/FreeRTOS/src/variantHooks.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,10 @@ extern "C" {
414414
xSemaphoreTake(mtx, portMAX_DELAY);
415415
}
416416

417+
void __freertos_mutex_take_from_isr(SemaphoreHandle_t mtx) {
418+
xSemaphoreTakeFromISR(mtx, NULL);
419+
}
420+
417421
int __freertos_mutex_try_take(SemaphoreHandle_t mtx) {
418422
return xSemaphoreTake(mtx, 0);
419423
}
@@ -422,6 +426,10 @@ extern "C" {
422426
xSemaphoreGive(mtx);
423427
}
424428

429+
void __freertos_mutex_give_from_isr(SemaphoreHandle_t mtx) {
430+
xSemaphoreGiveFromISR(mtx, NULL);
431+
}
432+
425433
void __freertos_recursive_mutex_take(SemaphoreHandle_t mtx) {
426434
xSemaphoreTakeRecursive(mtx, portMAX_DELAY);
427435
}

0 commit comments

Comments
 (0)