Skip to content

Commit 678f47e

Browse files
committed
extmod/freertos: Implement core threading backend (Phases 3-8).
Phase 3 - HAL functions: - mp_freertos_delay_ms/us with scheduler state awareness - mp_freertos_ticks_ms/us using FreeRTOS tick count Phase 4 - Thread state management: - mp_thread_get_state/set_state using FreeRTOS TLS - mp_thread_get_id returning task handle Phase 5 - Mutex implementation: - Binary semaphore for basic mutex - Recursive mutex for GIL support - Pre-scheduler safety (return success when scheduler not running) Phase 6 - Thread lifecycle: - mp_thread_init/deinit for main thread adoption - mp_thread_create with GC-first allocation strategy - Lazy reaper mechanism for finished thread cleanup - Entry wrapper handling TLS setup and exit protocol Phase 7 - GC integration: - mp_thread_gc_others scanning all thread stacks Phase 8 - GIL integration: - mp_thread_gil_exit with yield for fairness Signed-off-by: Andrew Leech <[email protected]>
1 parent 10fde15 commit 678f47e

File tree

3 files changed

+433
-2
lines changed

3 files changed

+433
-2
lines changed

extmod/freertos/mp_freertos_hal.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,59 @@
3333

3434
#include "extmod/freertos/mp_freertos_hal.h"
3535

36-
// Implementation will be added in Phase 3
36+
// FreeRTOS-aware millisecond delay.
37+
// Yields to the scheduler if running, otherwise busy-waits.
38+
void mp_freertos_delay_ms(mp_uint_t ms) {
39+
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
40+
if (ms > 0) {
41+
vTaskDelay(pdMS_TO_TICKS(ms));
42+
} else {
43+
taskYIELD();
44+
}
45+
} else {
46+
// Scheduler not running, use busy-wait fallback.
47+
// This path is used during early init before vTaskStartScheduler().
48+
// Port should provide mp_hal_delay_us() for accurate timing.
49+
#if defined(mp_hal_delay_us)
50+
mp_hal_delay_us(ms * 1000);
51+
#else
52+
// Crude busy-wait; actual delay depends on CPU speed.
53+
volatile uint32_t count = ms * 1000;
54+
while (count--) {
55+
__asm volatile ("nop");
56+
}
57+
#endif
58+
}
59+
}
60+
61+
// Microsecond delay.
62+
// This is a busy-wait implementation. Ports requiring precise microsecond
63+
// timing should override with a hardware timer implementation.
64+
void mp_freertos_delay_us(mp_uint_t us) {
65+
// Simple busy-wait loop. Accuracy depends on CPU speed.
66+
// Each iteration is roughly 4-10 cycles depending on architecture.
67+
// For 100MHz CPU: 1us ≈ 100 cycles ≈ 10-25 iterations.
68+
// This is intentionally imprecise; ports needing accuracy should
69+
// provide their own mp_hal_delay_us() using DWT or hardware timer.
70+
volatile uint32_t count = us * 10; // Approximate for ~100MHz
71+
while (count--) {
72+
__asm volatile ("nop");
73+
}
74+
}
75+
76+
// Get milliseconds since boot using FreeRTOS tick count.
77+
// Resolution is limited to tick rate (typically 1ms for 1kHz tick).
78+
mp_uint_t mp_freertos_ticks_ms(void) {
79+
return xTaskGetTickCount() * portTICK_PERIOD_MS;
80+
}
81+
82+
// Get microseconds since boot.
83+
// This uses the tick count scaled to microseconds. Resolution is poor
84+
// (typically 1ms). Ports needing microsecond precision should override
85+
// with a hardware timer implementation (DWT, SysTick, or dedicated timer).
86+
mp_uint_t mp_freertos_ticks_us(void) {
87+
// Scale tick count to microseconds. Limited by tick resolution.
88+
return xTaskGetTickCount() * (portTICK_PERIOD_MS * 1000);
89+
}
3790

3891
#endif // MICROPY_PY_THREAD

0 commit comments

Comments
 (0)