From 63bee9468731da75091b8cd5a9cd39018370a57e Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sun, 1 Sep 2024 09:50:09 -0700 Subject: [PATCH 1/3] WIP - Add FreeRTOS support for RP2350 Pull in Raspberry Pi's custom RP2350 ARM and RISC-V ports for FreeRTOS. Basic tests run, but stress mutex test is failing in unique and interesting ways. --- libraries/FreeRTOS/lib/FreeRTOS-Kernel | 2 +- libraries/FreeRTOS/src/FreeRTOS.h | 4 ---- libraries/FreeRTOS/src/FreeRTOSConfig.h | 9 +++++++++ libraries/FreeRTOS/src/mpu_syscall_numbers.h | 1 + libraries/FreeRTOS/src/mpu_wrappers_v2_asm.c | 3 +++ libraries/FreeRTOS/src/port.c | 4 ++++ libraries/FreeRTOS/src/portasm.c | 3 +++ libraries/FreeRTOS/src/portmacro.h | 4 ++++ libraries/FreeRTOS/src/rp2040_config.h | 4 ++++ tests/common.sh | 1 - 10 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 libraries/FreeRTOS/src/mpu_syscall_numbers.h create mode 100644 libraries/FreeRTOS/src/mpu_wrappers_v2_asm.c create mode 100644 libraries/FreeRTOS/src/portasm.c diff --git a/libraries/FreeRTOS/lib/FreeRTOS-Kernel b/libraries/FreeRTOS/lib/FreeRTOS-Kernel index 6a303231e..2e588af95 160000 --- a/libraries/FreeRTOS/lib/FreeRTOS-Kernel +++ b/libraries/FreeRTOS/lib/FreeRTOS-Kernel @@ -1 +1 @@ -Subproject commit 6a303231eceaec08a26a7e534800ba4010cec58d +Subproject commit 2e588af95bad29aef577373512883370c9408c1c diff --git a/libraries/FreeRTOS/src/FreeRTOS.h b/libraries/FreeRTOS/src/FreeRTOS.h index 5827e5d21..1db1c270b 100644 --- a/libraries/FreeRTOS/src/FreeRTOS.h +++ b/libraries/FreeRTOS/src/FreeRTOS.h @@ -1,5 +1 @@ -#ifdef PICO_RP2350 -#error Sorry, FreeRTOS is not yet supported on the RP2350 in this core. -#else #include "../lib/FreeRTOS-Kernel/include/FreeRTOS.h" -#endif diff --git a/libraries/FreeRTOS/src/FreeRTOSConfig.h b/libraries/FreeRTOS/src/FreeRTOSConfig.h index 287942059..10e96c663 100644 --- a/libraries/FreeRTOS/src/FreeRTOSConfig.h +++ b/libraries/FreeRTOS/src/FreeRTOSConfig.h @@ -82,6 +82,10 @@ extern unsigned long ulMainGetRunTimeCounterValue(void); #define configPRIO_BITS 3 /* 8 priority levels */ #endif +#define configENABLE_MPU 0 +#define configENABLE_TRUSTZONE 0 +#define configRUN_FREERTOS_SECURE_ONLY 1 +#define configENABLE_FPU 1 /* The lowest interrupt priority that can be used in a call to a "set priority" function. */ #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x7 @@ -95,9 +99,14 @@ extern unsigned long ulMainGetRunTimeCounterValue(void); /* Interrupt priorities used by the kernel port layer itself. These are generic to all Cortex-M ports, and do not rely on any particular library functions. */ #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#ifdef PICO_RP2350 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16 +#else /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +#endif #ifdef __cplusplus extern "C" { diff --git a/libraries/FreeRTOS/src/mpu_syscall_numbers.h b/libraries/FreeRTOS/src/mpu_syscall_numbers.h new file mode 100644 index 000000000..fb175c2f2 --- /dev/null +++ b/libraries/FreeRTOS/src/mpu_syscall_numbers.h @@ -0,0 +1 @@ +#include "../lib/FreeRTOS-Kernel/include/mpu_syscall_numbers.h" diff --git a/libraries/FreeRTOS/src/mpu_wrappers_v2_asm.c b/libraries/FreeRTOS/src/mpu_wrappers_v2_asm.c new file mode 100644 index 000000000..97b24aead --- /dev/null +++ b/libraries/FreeRTOS/src/mpu_wrappers_v2_asm.c @@ -0,0 +1,3 @@ +#ifdef PICO_RP2350 +#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure/mpu_wrappers_v2_asm.c" +#endif diff --git a/libraries/FreeRTOS/src/port.c b/libraries/FreeRTOS/src/port.c index 2327f4627..944a548b7 100644 --- a/libraries/FreeRTOS/src/port.c +++ b/libraries/FreeRTOS/src/port.c @@ -1 +1,5 @@ +#ifdef PICO_RP2040 #include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/port.c" +#else +#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure/port.c" +#endif diff --git a/libraries/FreeRTOS/src/portasm.c b/libraries/FreeRTOS/src/portasm.c new file mode 100644 index 000000000..8f36df1f4 --- /dev/null +++ b/libraries/FreeRTOS/src/portasm.c @@ -0,0 +1,3 @@ +#ifdef PICO_RP2350 +#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure/portasm.c" +#endif diff --git a/libraries/FreeRTOS/src/portmacro.h b/libraries/FreeRTOS/src/portmacro.h index e769db5b0..3e549b080 100644 --- a/libraries/FreeRTOS/src/portmacro.h +++ b/libraries/FreeRTOS/src/portmacro.h @@ -1 +1,5 @@ +#ifdef PICO_RP2350 +#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure/portmacro.h" +#else #include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/portmacro.h" +#endif diff --git a/libraries/FreeRTOS/src/rp2040_config.h b/libraries/FreeRTOS/src/rp2040_config.h index a57b4421f..a99652775 100644 --- a/libraries/FreeRTOS/src/rp2040_config.h +++ b/libraries/FreeRTOS/src/rp2040_config.h @@ -1 +1,5 @@ +#ifdef PICO_RP2350 +#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2350_ARM_NTZ/non_secure//rp2040_config.h" +#else #include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/rp2040_config.h" +#endif diff --git a/tests/common.sh b/tests/common.sh index 7dd2044e3..e8f99ac81 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -8,7 +8,6 @@ function skip_ino() local skiplistrp2350="" if [ "$PICO_BOARD" == "rp2350" ]; then read -d '' skiplistrp2350 << EOL || true -/FreeRTOS/ /BTstackLib/ /JoystickBT/ /KeyboardBT/ From 64adae9bfad8b8962a0533863741ed4f7fe34979 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sun, 15 Sep 2024 15:59:23 -0700 Subject: [PATCH 2/3] Add simplified switching test catching task swap problem --- .../FreeRTOS/tests/switching/switching.ino | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 libraries/FreeRTOS/tests/switching/switching.ino diff --git a/libraries/FreeRTOS/tests/switching/switching.ino b/libraries/FreeRTOS/tests/switching/switching.ino new file mode 100644 index 000000000..44aa5a142 --- /dev/null +++ b/libraries/FreeRTOS/tests/switching/switching.ino @@ -0,0 +1,57 @@ +// Released to the public domain +#include +#include +#include +#define STACK_SIZE 512 +#define CORE_0 (1 << 0) +#define CORE_1 (1 << 1) + +std::map eTaskStateName { {eReady, "Ready"}, { eRunning, "Running" }, {eBlocked, "Blocked"}, {eSuspended, "Suspended"}, {eDeleted, "Deleted"} }; +void ps() { + int tasks = uxTaskGetNumberOfTasks(); + TaskStatus_t *pxTaskStatusArray = new TaskStatus_t[tasks]; + unsigned long runtime; + tasks = uxTaskGetSystemState( pxTaskStatusArray, tasks, &runtime ); + Serial.printf("# Tasks: %d\n", tasks); + Serial.printf("%-3s %-16s %-10s %s %s\n", "ID", "NAME", "STATE", "PRIO", "CYCLES"); + for (int i = 0; i < tasks; i++) { + Serial.printf("%2d: %-16s %-10s %4d %lu\n", i, pxTaskStatusArray[i].pcTaskName, eTaskStateName[pxTaskStatusArray[i].eCurrentState], (int)pxTaskStatusArray[i].uxCurrentPriority, pxTaskStatusArray[i].ulRunTimeCounter); + } + delete[] pxTaskStatusArray; +} + +static TaskHandle_t l[16]; + +void loop() { + ps(); + delay(1000); +} + +#define LOOP(z) \ +void loop##z(void *params) {\ + (void) params;\ + while (true) {\ + srand(z);\ + int sum = 0;\ + for (int i = 0; i < 500000; i++) sum+= rand();\ + Serial.printf("L%d: %08x\n", z, sum);\ + delay(1000 + z * 10);\ + }\ +} + +LOOP(0); +LOOP(1); +LOOP(2); +LOOP(3); + + +void setup() { + xTaskCreate(loop0, "loop0", STACK_SIZE, NULL, 1, &l[0]); + vTaskCoreAffinitySet(l[0], CORE_0); +// xTaskCreate(loop1, "loop1", STACK_SIZE, NULL, 1, &l[1]); +// vTaskCoreAffinitySet(l[1], CORE_0); +// xTaskCreate(loop2, "loop2", STACK_SIZE, NULL, 1, &l[2]); +// vTaskCoreAffinitySet(l[2], CORE_0); +// xTaskCreate(loop3, "loop3", STACK_SIZE, NULL, 1, &l[3]); +// vTaskCoreAffinitySet(l[3], CORE_1); +} From f9ba639603567d6768c7eb7c1d8b77a111f33586 Mon Sep 17 00:00:00 2001 From: fietser28 Date: Tue, 17 Sep 2024 01:41:51 +0200 Subject: [PATCH 3/3] Freertosrp2350: use FreeRTOS macros in noInterrupts/interrupts when applicable. (#2456) * Use FreeRTOS macros in noInterrupts/interrupts when applicable. * Fixed calling taskEXIT_CRITICAL and taskENTER_CRITICAL --- cores/rp2040/_freertos.h | 3 +++ cores/rp2040/wiring_private.cpp | 31 ++++++++++++++++--------- libraries/FreeRTOS/src/variantHooks.cpp | 8 +++++++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/cores/rp2040/_freertos.h b/cores/rp2040/_freertos.h index 74e1133bf..0c626f1ba 100644 --- a/cores/rp2040/_freertos.h +++ b/cores/rp2040/_freertos.h @@ -54,5 +54,8 @@ extern "C" { extern void __freertos_idle_other_core() __attribute__((weak)); extern void __freertos_resume_other_core() __attribute__((weak)); + + extern void __freertos_task_exit_critical() __attribute__((weak)); + extern void __freertos_task_enter_critical() __attribute__((weak)); } extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive = false); diff --git a/cores/rp2040/wiring_private.cpp b/cores/rp2040/wiring_private.cpp index b84d0d1ea..a91b4f9dd 100644 --- a/cores/rp2040/wiring_private.cpp +++ b/cores/rp2040/wiring_private.cpp @@ -23,6 +23,8 @@ #include #include #include +#include "_freertos.h" + // Support nested IRQ disable/re-enable #ifndef maxIRQs @@ -32,22 +34,29 @@ static uint32_t _irqStackTop[2] = { 0, 0 }; static uint32_t _irqStack[2][maxIRQs]; extern "C" void interrupts() { - auto core = get_core_num(); - if (!_irqStackTop[core]) { - // ERROR - return; + if (__freeRTOSinitted) { + __freertos_task_exit_critical(); + } else { + auto core = get_core_num(); + if (!_irqStackTop[core]) { + // ERROR + return; + } + restore_interrupts(_irqStack[core][--_irqStackTop[core]]); } - restore_interrupts(_irqStack[core][--_irqStackTop[core]]); } extern "C" void noInterrupts() { - auto core = get_core_num(); - if (_irqStackTop[core] == maxIRQs) { - // ERROR - panic("IRQ stack overflow"); + if (__freeRTOSinitted) { + __freertos_task_enter_critical(); + } else { + auto core = get_core_num(); + if (_irqStackTop[core] == maxIRQs) { + // ERROR + panic("IRQ stack overflow"); + } + _irqStack[core][_irqStackTop[core]++] = save_and_disable_interrupts(); } - - _irqStack[core][_irqStackTop[core]++] = save_and_disable_interrupts(); } // Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and diff --git a/libraries/FreeRTOS/src/variantHooks.cpp b/libraries/FreeRTOS/src/variantHooks.cpp index f4d2487cc..bc0846f05 100644 --- a/libraries/FreeRTOS/src/variantHooks.cpp +++ b/libraries/FreeRTOS/src/variantHooks.cpp @@ -91,6 +91,14 @@ extern "C" { bool __freertos_check_if_in_isr() { return portCHECK_IF_IN_ISR(); } + + void __freertos_task_exit_critical() { + taskEXIT_CRITICAL(); + } + + void __freertos_task_enter_critical() { + taskENTER_CRITICAL(); + } }