Skip to content

Commit 0e85745

Browse files
WIP - Make FreeRTOS a first-class citizen
With the expanded performance and memory of the Pico 2, having a full operating system with threads could really improve developer life and get the best possible algorithm performance. Start by moving FreeRTOS checks from a global bool set by weak function linkage checks to a compiler definition. This can allow the build process to differ between bare metal and FreeRTOS builds (i.e. async_context implementations) and save a few bytes of program space.
1 parent b886471 commit 0e85745

File tree

22 files changed

+793
-212
lines changed

22 files changed

+793
-212
lines changed

boards.txt

Lines changed: 529 additions & 0 deletions
Large diffs are not rendered by default.

cores/rp2040/Arduino.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,6 @@ void analogWriteResolution(int res);
109109
} // extern "C"
110110
#endif
111111

112-
// FreeRTOS potential calls
113-
extern bool __isFreeRTOS;
114-
115112
// Ancient AVR defines
116113
#define HAVE_HWSERIAL0
117114
#define HAVE_HWSERIAL1

cores/rp2040/Bootsel.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ static bool __no_inline_not_in_flash_func(get_bootsel_button)() {
2626

2727
// Must disable interrupts, as interrupt handlers may be in flash, and we
2828
// are about to temporarily disable flash access!
29-
if (!__isFreeRTOS) {
30-
noInterrupts();
31-
}
29+
#ifndef __FREERTOS
30+
noInterrupts();
31+
#endif
3232
rp2040.idleOtherCore();
3333

3434
// Set chip select to Hi-Z
@@ -55,9 +55,9 @@ static bool __no_inline_not_in_flash_func(get_bootsel_button)() {
5555
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
5656

5757
rp2040.resumeOtherCore();
58-
if (!__isFreeRTOS) {
59-
interrupts();
60-
}
58+
#ifndef __FREERTOS
59+
interrupts();
60+
#endif
6161

6262
return button_state;
6363
}

cores/rp2040/CoreMutex.cpp

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,45 +28,45 @@ CoreMutex::CoreMutex(mutex_t *mutex, uint8_t option) {
2828
_mutex = mutex;
2929
_acquired = false;
3030
_option = option;
31+
#ifdef __FREERTOS
3132
_pxHigherPriorityTaskWoken = 0; // pdFALSE
32-
if (__isFreeRTOS) {
33-
auto m = __get_freertos_mutex_for_ptr(mutex);
33+
auto m = __get_freertos_mutex_for_ptr(mutex);
3434

35-
if (__freertos_check_if_in_isr()) {
36-
if (!__freertos_mutex_take_from_isr(m, &_pxHigherPriorityTaskWoken)) {
37-
return;
38-
}
39-
// At this point we have the mutex in ISR
40-
} else {
41-
// Grab the mutex normally, possibly waking other tasks to get it
42-
__freertos_mutex_take(m);
35+
if (__freertos_check_if_in_isr()) {
36+
if (!__freertos_mutex_take_from_isr(m, &_pxHigherPriorityTaskWoken)) {
37+
return;
4338
}
39+
// At this point we have the mutex in ISR
4440
} else {
45-
uint32_t owner;
46-
if (!mutex_try_enter(_mutex, &owner)) {
47-
if (owner == get_core_num()) { // Deadlock!
48-
if (_option & DebugEnable) {
49-
DEBUGCORE("CoreMutex - Deadlock detected!\n");
50-
}
51-
return;
41+
// Grab the mutex normally, possibly waking other tasks to get it
42+
__freertos_mutex_take(m);
43+
}
44+
#else
45+
uint32_t owner;
46+
if (!mutex_try_enter(_mutex, &owner)) {
47+
if (owner == get_core_num()) { // Deadlock!
48+
if (_option & DebugEnable) {
49+
DEBUGCORE("CoreMutex - Deadlock detected!\n");
5250
}
53-
mutex_enter_blocking(_mutex);
51+
return;
5452
}
53+
mutex_enter_blocking(_mutex);
5554
}
55+
#endif
5656
_acquired = true;
5757
}
5858

5959
CoreMutex::~CoreMutex() {
6060
if (_acquired) {
61-
if (__isFreeRTOS) {
62-
auto m = __get_freertos_mutex_for_ptr(_mutex);
63-
if (__freertos_check_if_in_isr()) {
64-
__freertos_mutex_give_from_isr(m, &_pxHigherPriorityTaskWoken);
65-
} else {
66-
__freertos_mutex_give(m);
67-
}
61+
#ifdef __FREERTOS
62+
auto m = __get_freertos_mutex_for_ptr(_mutex);
63+
if (__freertos_check_if_in_isr()) {
64+
__freertos_mutex_give_from_isr(m, &_pxHigherPriorityTaskWoken);
6865
} else {
69-
mutex_exit(_mutex);
66+
__freertos_mutex_give(m);
7067
}
68+
#else
69+
mutex_exit(_mutex);
70+
#endif
7171
}
7272
}

cores/rp2040/CoreMutex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,7 @@ class CoreMutex {
4343
mutex_t *_mutex;
4444
bool _acquired;
4545
uint8_t _option;
46+
#ifdef __FREERTOS
4647
BaseType_t _pxHigherPriorityTaskWoken;
48+
#endif
4749
};

cores/rp2040/RP2040Support.h

Lines changed: 62 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,18 @@ class _MFIFO {
7272
}
7373

7474
void registerCore() {
75-
if (!__isFreeRTOS) {
76-
multicore_fifo_clear_irq();
75+
#ifndef __FREERTOS
76+
multicore_fifo_clear_irq();
7777
#ifdef PICO_RP2350
78-
irq_set_exclusive_handler(SIO_IRQ_FIFO, _irq);
79-
irq_set_enabled(SIO_IRQ_FIFO, true);
78+
irq_set_exclusive_handler(SIO_IRQ_FIFO, _irq);
79+
irq_set_enabled(SIO_IRQ_FIFO, true);
8080
#else
81-
irq_set_exclusive_handler(SIO_IRQ_PROC0 + get_core_num(), _irq);
82-
irq_set_enabled(SIO_IRQ_PROC0 + get_core_num(), true);
81+
irq_set_exclusive_handler(SIO_IRQ_PROC0 + get_core_num(), _irq);
82+
irq_set_enabled(SIO_IRQ_PROC0 + get_core_num(), true);
8383
#endif
84-
}
84+
#else
8585
// FreeRTOS port.c will handle the IRQ hooking
86+
#endif
8687
}
8788

8889
void push(uint32_t val) {
@@ -113,14 +114,14 @@ class _MFIFO {
113114
if (!_multicore) {
114115
return;
115116
}
116-
if (__isFreeRTOS) {
117-
__freertos_idle_other_core();
118-
} else {
119-
mutex_enter_blocking(&_idleMutex);
120-
__otherCoreIdled = false;
121-
multicore_fifo_push_blocking(_GOTOSLEEP);
122-
while (!__otherCoreIdled) { /* noop */ }
123-
}
117+
#ifdef __FREERTOS
118+
__freertos_idle_other_core();
119+
#else
120+
mutex_enter_blocking(&_idleMutex);
121+
__otherCoreIdled = false;
122+
multicore_fifo_push_blocking(_GOTOSLEEP);
123+
while (!__otherCoreIdled) { /* noop */ }
124+
#endif
124125
}
125126

126127
void resumeOtherCore() {
@@ -129,9 +130,9 @@ class _MFIFO {
129130
}
130131
mutex_exit(&_idleMutex);
131132
__otherCoreIdled = false;
132-
if (__isFreeRTOS) {
133-
__freertos_resume_other_core();
134-
}
133+
#ifdef __FREERTOS
134+
__freertos_resume_other_core();
135+
#endif
135136

136137
// Other core will exit busy-loop and return to operation
137138
// once __otherCoreIdled == false.
@@ -151,18 +152,18 @@ class _MFIFO {
151152

152153
private:
153154
static void __no_inline_not_in_flash_func(_irq)() {
154-
if (!__isFreeRTOS) {
155-
multicore_fifo_clear_irq();
156-
noInterrupts(); // We need total control, can't run anything
157-
while (multicore_fifo_rvalid()) {
158-
if (_GOTOSLEEP == multicore_fifo_pop_blocking()) {
159-
__otherCoreIdled = true;
160-
while (__otherCoreIdled) { /* noop */ }
161-
break;
162-
}
155+
#ifndef __FREERTOS
156+
multicore_fifo_clear_irq();
157+
noInterrupts(); // We need total control, can't run anything
158+
while (multicore_fifo_rvalid()) {
159+
if (_GOTOSLEEP == multicore_fifo_pop_blocking()) {
160+
__otherCoreIdled = true;
161+
while (__otherCoreIdled) { /* noop */ }
162+
break;
163163
}
164-
interrupts();
165164
}
165+
interrupts();
166+
#endif
166167
}
167168

168169
bool _multicore = false;
@@ -192,23 +193,19 @@ class RP2040 {
192193

193194
void begin(int cpuid) {
194195
_epoch[cpuid] = 0;
195-
#if !defined(__riscv) && !defined(__PROFILE)
196-
if (!__isFreeRTOS) {
197-
// Enable SYSTICK exception
198-
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
199-
systick_hw->csr = 0x7;
200-
systick_hw->rvr = 0x00FFFFFF;
201-
} else {
202-
#endif
203-
// Only start 1 instance of the PIO SM
204-
if (cpuid == 0) {
205-
int off = 0;
206-
_ccountPgm = new PIOProgram(&ccount_program);
207-
_ccountPgm->prepare(&_pio, &_sm, &off);
208-
ccount_program_init(_pio, _sm, off);
209-
pio_sm_set_enabled(_pio, _sm, true);
210-
}
211-
#if !defined(__riscv) && !defined(__PROFILE)
196+
#if !defined(__riscv) && !defined(__PROFILE) && !defined(__FREERTOS)
197+
// Enable SYSTICK exception
198+
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
199+
systick_hw->csr = 0x7;
200+
systick_hw->rvr = 0x00FFFFFF;
201+
#else
202+
// Only start 1 instance of the PIO SM
203+
if (cpuid == 0) {
204+
int off = 0;
205+
_ccountPgm = new PIOProgram(&ccount_program);
206+
_ccountPgm->prepare(&_pio, &_sm, &off);
207+
ccount_program_init(_pio, _sm, off);
208+
pio_sm_set_enabled(_pio, _sm, true);
212209
}
213210
#endif
214211
}
@@ -255,21 +252,17 @@ class RP2040 {
255252
@returns CPU clock cycles since power up
256253
*/
257254
inline uint32_t getCycleCount() {
258-
#if !defined(__riscv) && !defined(__PROFILE)
255+
#if !defined(__riscv) && !defined(__PROFILE) && !defined(__FREERTOS)
259256
// Get CPU cycle count. Needs to do magic to extend 24b HW to something longer
260-
if (!__isFreeRTOS) {
261-
uint32_t epoch;
262-
uint32_t ctr;
263-
do {
264-
epoch = (uint32_t)_epoch[sio_hw->cpuid];
265-
ctr = systick_hw->cvr;
266-
} while (epoch != (uint32_t)_epoch[sio_hw->cpuid]);
267-
return epoch + (1 << 24) - ctr; /* CTR counts down from 1<<24-1 */
268-
} else {
269-
#endif
270-
return ccount_read(_pio, _sm);
271-
#if !defined(__riscv) && !defined(__PROFILE)
272-
}
257+
uint32_t epoch;
258+
uint32_t ctr;
259+
do {
260+
epoch = (uint32_t)_epoch[sio_hw->cpuid];
261+
ctr = systick_hw->cvr;
262+
} while (epoch != (uint32_t)_epoch[sio_hw->cpuid]);
263+
return epoch + (1 << 24) - ctr; /* CTR counts down from 1<<24-1 */
264+
#else
265+
return ccount_read(_pio, _sm);
273266
#endif
274267
}
275268
/**
@@ -278,20 +271,16 @@ class RP2040 {
278271
@returns CPU clock cycles since power up
279272
*/
280273
inline uint64_t getCycleCount64() {
281-
#if !defined(__riscv) && !defined(__PROFILE)
282-
if (!__isFreeRTOS) {
283-
uint64_t epoch;
284-
uint64_t ctr;
285-
do {
286-
epoch = _epoch[sio_hw->cpuid];
287-
ctr = systick_hw->cvr;
288-
} while (epoch != _epoch[sio_hw->cpuid]);
289-
return epoch + (1LL << 24) - ctr;
290-
} else {
291-
#endif
292-
return ccount_read(_pio, _sm);
293-
#if !defined(__riscv) && !defined(__PROFILE)
294-
}
274+
#if !defined(__riscv) && !defined(__PROFILE) && !defined(__FREERTOS)
275+
uint64_t epoch;
276+
uint64_t ctr;
277+
do {
278+
epoch = _epoch[sio_hw->cpuid];
279+
ctr = systick_hw->cvr;
280+
} while (epoch != _epoch[sio_hw->cpuid]);
281+
return epoch + (1LL << 24) - ctr;
282+
#else
283+
return ccount_read(_pio, _sm);
295284
#endif
296285
}
297286

cores/rp2040/SerialUSB.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ static int _bps = 115200;
181181
static bool _rebooting = false;
182182
static void CheckSerialReset() {
183183
if (!_rebooting && (_bps == 1200) && (!_dtr)) {
184-
if (__isFreeRTOS) {
185-
__freertos_idle_other_core();
186-
}
184+
#ifdef __FREERTOS
185+
__freertos_idle_other_core();
186+
#endif
187187
_rebooting = true;
188188
// Disable NVIC IRQ, so that we don't get bothered anymore
189189
irq_set_enabled(USBCTRL_IRQ, false);

cores/rp2040/_freertos.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1919
*/
2020

21+
#ifdef __FREERTOS
22+
2123
#include "_freertos.h"
2224
#include <pico/mutex.h>
2325
#include <stdlib.h>
@@ -60,3 +62,5 @@ SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive) {
6062
}
6163
return nullptr; // Need to make space for more mutex maps!
6264
}
65+
66+
#endif

cores/rp2040/_freertos.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1919
*/
2020

21+
#ifdef __FREERTOS
22+
2123
#pragma once
2224
#include <pico/mutex.h>
2325

2426
// Cannot include refs to FreeRTOS's actual semaphore calls because they
2527
// are implemented as macros, so we have a wrapper in our variant hook
2628
// to handle it.
2729

28-
extern bool __isFreeRTOS;
29-
3030
// FreeRTOS has been set up
3131
extern volatile bool __freeRTOSinitted;
3232

@@ -63,3 +63,5 @@ extern void __freertos_task_enter_critical() __attribute__((weak));
6363
}
6464
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive = false);
6565
#endif // __cplusplus
66+
67+
#endif // __FREERTOS

0 commit comments

Comments
 (0)