Skip to content

Commit

Permalink
Stop random crashes while writing to flash (#730)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
earlephilhower authored Jul 30, 2022
1 parent bb029cc commit 005cba3
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 10 deletions.
23 changes: 23 additions & 0 deletions cores/rp2040/RP2040Support.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@

extern "C" volatile bool __otherCoreIdled;

// Halt the FreeRTOS PendSV task switching magic
extern "C" int __holdUpPendSV;

// FreeRTOS weak functions, to be overridden when we really are running FreeRTOS
extern "C" {
extern void vTaskSuspendAll() __attribute__((weak));
extern int32_t xTaskResumeAll() __attribute__((weak));
typedef struct tskTaskControlBlock * TaskHandle_t;
extern void vTaskPreemptionDisable(TaskHandle_t p) __attribute__((weak));
extern void vTaskPreemptionEnable(TaskHandle_t p) __attribute__((weak));
}

class _MFIFO {
public:
_MFIFO() { /* noop */ };
Expand Down Expand Up @@ -86,6 +98,11 @@ class _MFIFO {
if (!_multicore) {
return;
}
__holdUpPendSV = 1;
if (__isFreeRTOS) {
vTaskPreemptionDisable(nullptr);
vTaskSuspendAll();
}
mutex_enter_blocking(&_idleMutex);
__otherCoreIdled = false;
multicore_fifo_push_blocking(_GOTOSLEEP);
Expand All @@ -98,6 +115,12 @@ class _MFIFO {
}
mutex_exit(&_idleMutex);
__otherCoreIdled = false;
if (__isFreeRTOS) {
xTaskResumeAll();
vTaskPreemptionEnable(nullptr);
}
__holdUpPendSV = 0;

// Other core will exit busy-loop and return to operation
// once __otherCoreIdled == false.
}
Expand Down
1 change: 1 addition & 0 deletions cores/rp2040/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
RP2040 rp2040;
extern "C" {
volatile bool __otherCoreIdled = false;
int __holdUpPendSV = 0;
};

mutex_t _pioMutex;
Expand Down
2 changes: 1 addition & 1 deletion libraries/FreeRTOS/lib/FreeRTOS-Kernel
1 change: 1 addition & 0 deletions libraries/FreeRTOS/src/FreeRTOSConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSTACK_DEPTH_TYPE uint32_t
#define configUSE_TASK_PREEMPTION_DISABLE 1

#define configUSE_NEWLIB_REENTRANT 1
#define configNEWLIB_REENTRANT_IS_DYNAMIC 0 /* Note that we have a different config option, portSET_IMPURE_PTR */
Expand Down
9 changes: 0 additions & 9 deletions libraries/FreeRTOS/src/variantHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <Arduino.h>
#include <RP2040USB.h>
#include "tusb.h"
#define USB_TASK_IRQ 31


/* Raspberry PI Pico includes */
Expand Down Expand Up @@ -382,19 +381,11 @@ void vApplicationAssertHook() {
#endif


static void __usb_irq() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
vTaskNotifyGiveFromISR( __usbTask, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

static void __usb(void *param)
{
(void) param;

tusb_init();
irq_set_exclusive_handler(USB_TASK_IRQ, __usb_irq);
irq_set_enabled(USB_TASK_IRQ, true);

Serial.begin(115200);

Expand Down

0 comments on commit 005cba3

Please sign in to comment.