Skip to content

Commit 005cba3

Browse files
Stop random crashes while writing to flash (#730)
FreeRTOS SMP was updated to: a) Move ths SYSTICK handler, which cannot be disabled and can fire even with IRQs disabled, to RAM b) Add a flag from the core to the SYSTICK handler to hold off on any PendSV (task switch) calls while we are doing the idleOtherCore. The core now sets this flag, _holdPendSV, and adds add'l FreeRTOS SMP calls to really, really tell the OS we can't, don't, and better not be swapped out while writing to flash. Fixes #719
1 parent bb029cc commit 005cba3

File tree

5 files changed

+26
-10
lines changed

5 files changed

+26
-10
lines changed

cores/rp2040/RP2040Support.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@
3232

3333
extern "C" volatile bool __otherCoreIdled;
3434

35+
// Halt the FreeRTOS PendSV task switching magic
36+
extern "C" int __holdUpPendSV;
37+
38+
// FreeRTOS weak functions, to be overridden when we really are running FreeRTOS
39+
extern "C" {
40+
extern void vTaskSuspendAll() __attribute__((weak));
41+
extern int32_t xTaskResumeAll() __attribute__((weak));
42+
typedef struct tskTaskControlBlock * TaskHandle_t;
43+
extern void vTaskPreemptionDisable(TaskHandle_t p) __attribute__((weak));
44+
extern void vTaskPreemptionEnable(TaskHandle_t p) __attribute__((weak));
45+
}
46+
3547
class _MFIFO {
3648
public:
3749
_MFIFO() { /* noop */ };
@@ -86,6 +98,11 @@ class _MFIFO {
8698
if (!_multicore) {
8799
return;
88100
}
101+
__holdUpPendSV = 1;
102+
if (__isFreeRTOS) {
103+
vTaskPreemptionDisable(nullptr);
104+
vTaskSuspendAll();
105+
}
89106
mutex_enter_blocking(&_idleMutex);
90107
__otherCoreIdled = false;
91108
multicore_fifo_push_blocking(_GOTOSLEEP);
@@ -98,6 +115,12 @@ class _MFIFO {
98115
}
99116
mutex_exit(&_idleMutex);
100117
__otherCoreIdled = false;
118+
if (__isFreeRTOS) {
119+
xTaskResumeAll();
120+
vTaskPreemptionEnable(nullptr);
121+
}
122+
__holdUpPendSV = 0;
123+
101124
// Other core will exit busy-loop and return to operation
102125
// once __otherCoreIdled == false.
103126
}

cores/rp2040/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
RP2040 rp2040;
2929
extern "C" {
3030
volatile bool __otherCoreIdled = false;
31+
int __holdUpPendSV = 0;
3132
};
3233

3334
mutex_t _pioMutex;

libraries/FreeRTOS/src/FreeRTOSConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define configSUPPORT_DYNAMIC_ALLOCATION 1
2727
#define configSUPPORT_STATIC_ALLOCATION 0
2828
#define configSTACK_DEPTH_TYPE uint32_t
29+
#define configUSE_TASK_PREEMPTION_DISABLE 1
2930

3031
#define configUSE_NEWLIB_REENTRANT 1
3132
#define configNEWLIB_REENTRANT_IS_DYNAMIC 0 /* Note that we have a different config option, portSET_IMPURE_PTR */

libraries/FreeRTOS/src/variantHooks.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include <Arduino.h>
3030
#include <RP2040USB.h>
3131
#include "tusb.h"
32-
#define USB_TASK_IRQ 31
3332

3433

3534
/* Raspberry PI Pico includes */
@@ -382,19 +381,11 @@ void vApplicationAssertHook() {
382381
#endif
383382

384383

385-
static void __usb_irq() {
386-
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
387-
vTaskNotifyGiveFromISR( __usbTask, &xHigherPriorityTaskWoken );
388-
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
389-
}
390-
391384
static void __usb(void *param)
392385
{
393386
(void) param;
394387

395388
tusb_init();
396-
irq_set_exclusive_handler(USB_TASK_IRQ, __usb_irq);
397-
irq_set_enabled(USB_TASK_IRQ, true);
398389

399390
Serial.begin(115200);
400391

0 commit comments

Comments
 (0)