Skip to content

Commit

Permalink
Use recursive mutex for USB
Browse files Browse the repository at this point in the history
  • Loading branch information
anrp committed Jun 12, 2023
1 parent 7eb176c commit 519e704
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 11 deletions.
48 changes: 43 additions & 5 deletions cores/rp2040/CoreMutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,47 @@
#include "Arduino.h"
#include "CoreMutex.h"

CoreMutex::CoreMutex(recursive_mutex_t *mutex, uint8_t option) {
_mutex = mutex;
_acquired = false;
_option = option;
_pxHigherPriorityTaskWoken = 0; // pdFALSE
_recursive = true;
if (__isFreeRTOS) {
auto m = __get_freertos_mutex_for_ptr(reinterpret_cast<mutex_t*>(mutex), true);

if (__freertos_check_if_in_isr()) {
if (!__freertos_mutex_take_from_isr(m, &_pxHigherPriorityTaskWoken)) {
return;
}
// At this point we have the mutex in ISR
} else {
// Grab the mutex normally, possibly waking other tasks to get it
__freertos_mutex_take(m);
}
} else {
uint32_t owner;
if (!recursive_mutex_try_enter(reinterpret_cast<recursive_mutex_t*>(_mutex), &owner)) {
if (owner == get_core_num()) { // Deadlock!

This comment has been minimized.

Copy link
@anrp-tri

anrp-tri Jun 12, 2023

Owner

Likely dead code

if (_option & DebugEnable) {
DEBUGCORE("CoreMutex - Deadlock detected!\n");
}
return;
}
recursive_mutex_enter_blocking(reinterpret_cast<recursive_mutex_t*>(_mutex));
}
}
_acquired = true;
}

CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) {
_mutex = mutex;
_acquired = false;
_option = option;
_pxHigherPriorityTaskWoken = 0; // pdFALSE
_recursive = false;
if (__isFreeRTOS) {
auto m = __get_freertos_mutex_for_ptr(mutex);
auto m = __get_freertos_mutex_for_ptr(reinterpret_cast<mutex_t*>(mutex));

if (__freertos_check_if_in_isr()) {
if (!__freertos_mutex_take_from_isr(m, &_pxHigherPriorityTaskWoken)) {
Expand All @@ -43,14 +77,14 @@ CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) {
}
} else {
uint32_t owner;
if (!mutex_try_enter(_mutex, &owner)) {
if (!mutex_try_enter(reinterpret_cast<mutex_t*>(_mutex), &owner)) {
if (owner == get_core_num()) { // Deadlock!
if (_option & DebugEnable) {
DEBUGCORE("CoreMutex - Deadlock detected!\n");
}
return;
}
mutex_enter_blocking(_mutex);
mutex_enter_blocking(reinterpret_cast<mutex_t*>(_mutex));
}
}
_acquired = true;
Expand All @@ -59,14 +93,18 @@ CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) {
CoreMutex::~CoreMutex() {
if (_acquired) {
if (__isFreeRTOS) {
auto m = __get_freertos_mutex_for_ptr(_mutex);
auto m = __get_freertos_mutex_for_ptr(reinterpret_cast<mutex_t*>(_mutex), _recursive);
if (__freertos_check_if_in_isr()) {
__freertos_mutex_give_from_isr(m, &_pxHigherPriorityTaskWoken);
} else {
__freertos_mutex_give(m);
}
} else {
mutex_exit(_mutex);
if (_recursive) {
recursive_mutex_exit(reinterpret_cast<recursive_mutex_t*>(_mutex));
} else {
mutex_exit(reinterpret_cast<mutex_t*>(_mutex));
}
}
}
}
4 changes: 3 additions & 1 deletion cores/rp2040/CoreMutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum {

class CoreMutex {
public:
CoreMutex(recursive_mutex_t *mutex, uint8_t option = DebugEnable);
CoreMutex(mutex_t *mutex, uint8_t option = DebugEnable);
~CoreMutex();

Expand All @@ -40,7 +41,8 @@ class CoreMutex {
}

private:
mutex_t *_mutex;
bool _recursive;
void *_mutex;
bool _acquired;
uint8_t _option;
BaseType_t _pxHigherPriorityTaskWoken;
Expand Down
8 changes: 4 additions & 4 deletions cores/rp2040/RP2040USB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

// Big, global USB mutex, shared with all USB devices to make sure we don't
// have multiple cores updating the TUSB state in parallel
mutex_t __usb_mutex;
recursive_mutex_t __usb_mutex;

// USB processing will be a periodic timer task
#define USB_TASK_INTERVAL 1000
Expand Down Expand Up @@ -360,9 +360,9 @@ static void usb_irq() {
// if the mutex is already owned, then we are in user code
// in this file which will do a tud_task itself, so we'll just do nothing
// until the next tick; we won't starve
if (mutex_try_enter(&__usb_mutex, nullptr)) {
if (recursive_mutex_try_enter(&__usb_mutex, nullptr)) {
tud_task();
mutex_exit(&__usb_mutex);
recursive_mutex_exit(&__usb_mutex);
}
}

Expand All @@ -382,7 +382,7 @@ void __USBStart() {
__SetupDescHIDReport();
__SetupUSBDescriptor();

mutex_init(&__usb_mutex);
recursive_mutex_init(&__usb_mutex);

tusb_init();

Expand Down
2 changes: 1 addition & 1 deletion cores/rp2040/RP2040USB.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extern void __USBInstallMassStorage() __attribute__((weak));

// Big, global USB mutex, shared with all USB devices to make sure we don't
// have multiple cores updating the TUSB state in parallel
extern mutex_t __usb_mutex;
extern recursive_mutex_t __usb_mutex;

// HID report ID inquiry (report ID will vary depending on the number/type of other HID)
int __USBGetKeyboardReportID();
Expand Down

0 comments on commit 519e704

Please sign in to comment.