8000 rp2: Refactor to not use pico-sdk alarm pool functions for sleeping. · micropython/micropython@35245a7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 35245a7

Browse files
committed
rp2: Refactor to not use pico-sdk alarm pool functions for sleeping.
The best_effort_wfe_or_timeout() and sleep_us() pico-sdk functions use the pico-sdk alarm pool internally, and that has a bug. Some usages inside pico-sdk (notably multicore_lockout_start_blocking()) will still end up calling best_effort_wfe_or_timeout(), although usually with "end_of_time" as the timeout value so it should avoid any alarm pool race conditions. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent b9d8f65 commit 35245a7

File 8000 tree

4 files changed

+38
-9
lines changed

4 files changed

+38
-9
lines changed

ports/rp2/mpconfigport.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
261261
if ((TIMEOUT_MS) < 0) { \
262262
__wfe(); \
263263
} else { \
264-
best_effort_wfe_or_timeout(make_timeout_time_ms(TIMEOUT_MS)); \
264+
void mp_wfe_or_timeout(uint32_t timeout_ms); \
265+
mp_wfe_or_timeout(TIMEOUT_MS); \
265266
} \
266267
} while (0)
267268

ports/rp2/mphalport.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,17 +198,32 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
198198
return did_write ? ret : 0;
199199
}
200200

201+
void mp_hal_delay_us(mp_uint_t us) {
202+
// Until soft timer supports microseconds, avoid calling sleep_us() and
203+
// invoking the alarm pool by splitting long sleeps into an optional longer
204+
// sleep and a shorter busy-wait
205+
uint64_t end = time_us_64() + us;
206+
if (us > 1000) {
207+
mp_hal_delay_ms(us / 1000);
208+
}
209+
while (time_us_64() < end) {
210+
mp_event_handle_nowait();
211+
}
212+
}
213+
201214
void mp_hal_delay_ms(mp_uint_t ms) {
202-
absolute_time_t t = make_timeout_time_ms(ms);
215+
mp_uint_t start = mp_hal_ticks_ms();
216+
mp_uint_t elapsed = 0;
203217
do {
204-
mp_event_handle_nowait();
205-
} while (!best_effort_wfe_or_timeout(t));
218+
mp_event_wait_ms(ms - elapsed);
219+
elapsed = mp_hal_ticks_ms() - start;
220+
} while (elapsed < ms);
206221
}
207222

208223
void mp_hal_time_ns_set_from_rtc(void) {
209224
// Delay at least one RTC clock cycle so it's registers have updated with the most
210225
// recent time settings.
211-
sleep_us(23);
226+
mp_hal_delay_us(23);
212227

213228
// Sample RTC and time_us_64() as close together as possible, so the offset
214229
// calculated for the latter can be as accurate as possible.
@@ -292,3 +307,18 @@ void soft_timer_init(void) {
292307
// need to trigger PendSV the timer IRQ.
293308
NVIC_SetPriority(TIMER_IRQ_0_IRQn + MICROPY_HW_SOFT_TIMER_ALARM_NUM, PICO_LOWEST_IRQ_PRIORITY);
294309
}
310+
311+
void mp_wfe_or_timeout(uint32_t timeout_ms) {
312+
soft_timer_entry_t timer;
313+
314+
soft_timer_static_init(&timer, SOFT_TIMER_MODE_ONE_SHOT, 0, NULL);
315+
316+
// Note the timer doesn't have an associated callback, it just exists to create a
317+
// hardware interrupt to wake the CPU
318+
soft_timer_insert(&timer, timeout_ms);
319+
320+
__wfe();
321+
322+
// Clean up the timer node if it's not already
323+
soft_timer_remove(&timer);
324+
}

ports/rp2/mphalport.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ void mp_thread_end_atomic_section(uint32_t);
5252
void mp_hal_set_interrupt_char(int c);
5353
void mp_hal_time_ns_set_from_rtc(void);
5454

55-
static inline void mp_hal_delay_us(mp_uint_t us) {
56-
sleep_us(us);
57-
}
55+
void mp_hal_delay_us(mp_uint_t us);
5856

5957
static inline void mp_hal_delay_us_fast(mp_uint_t us) {
6058
busy_wait_us(us);

shared/runtime/softtimer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void soft_timer_handler(void) {
8989
heap = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap->pairheap);
9090
if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) {
9191
mp_sched_schedule(entry->py_callback, MP_OBJ_FROM_PTR(entry));
92-
} else {
92+
} else if (entry->c_callback) {
9393
entry->c_callback(entry);
9494
}
9595
if (entry->mode == SOFT_TIMER_MODE_PERIODIC) {

0 commit comments

Comments
 (0)
0