kopia lustrzana https://github.com/micropython/micropython
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>pull/13329/head
rodzic
20c866de07
commit
fccab87fc7
|
@ -263,6 +263,7 @@ typedef intptr_t mp_off_t;
|
|||
#define BINARY_INFO_ID_MP_FROZEN 0x4a99d719
|
||||
#define MICROPY_FROZEN_LIST_ITEM(name, file) bi_decl(bi_string(BINARY_INFO_TAG_MICROPYTHON, BINARY_INFO_ID_MP_FROZEN, name))
|
||||
|
||||
|
||||
extern uint32_t rosc_random_u32(void);
|
||||
extern void lwip_lock_acquire(void);
|
||||
extern void lwip_lock_release(void);
|
||||
|
|
|
@ -198,17 +198,31 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
|
|||
return did_write ? ret : 0;
|
||||
}
|
||||
|
||||
void mp_hal_delay_us(mp_uint_t us) {
|
||||
// Avoid calling sleep_us() and invoking the alarm pool by splitting long
|
||||
// sleeps into an optional longer sleep and a shorter busy-wait
|
||||
uint64_t end = time_us_64() + us;
|
||||
if (us > 1000) {
|
||||
mp_hal_delay_ms(us / 1000);
|
||||
}
|
||||
while (time_us_64() < end) {
|
||||
// Tight loop busy-wait for accurate timing
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_delay_ms(mp_uint_t ms) {
|
||||
absolute_time_t t = make_timeout_time_ms(ms);
|
||||
mp_uint_t start = mp_hal_ticks_ms();
|
||||
mp_uint_t elapsed = 0;
|
||||
do {
|
||||
mp_event_handle_nowait();
|
||||
} while (!best_effort_wfe_or_timeout(t));
|
||||
mp_event_wait_ms(ms - elapsed);
|
||||
elapsed = mp_hal_ticks_ms() - start;
|
||||
} while (elapsed < ms);
|
||||
}
|
||||
|
||||
void mp_hal_time_ns_set_from_rtc(void) {
|
||||
// Delay at least one RTC clock cycle so it's registers have updated with the most
|
||||
// recent time settings.
|
||||
sleep_us(23);
|
||||
// Outstanding RTC register writes need at least two RTC clock cycles to
|
||||
// update. (See RP2040 datasheet section 4.8.4 "Reference clock").
|
||||
mp_hal_delay_us(44);
|
||||
|
||||
// Sample RTC and time_us_64() as close together as possible, so the offset
|
||||
// calculated for the latter can be as accurate as possible.
|
||||
|
@ -295,3 +309,17 @@ void soft_timer_init(void) {
|
|||
hardware_alarm_claim(MICROPY_HW_SOFT_TIMER_ALARM_NUM);
|
||||
hardware_alarm_set_callback(MICROPY_HW_SOFT_TIMER_ALARM_NUM, soft_timer_hardware_callback);
|
||||
}
|
||||
|
||||
void mp_wfe_or_timeout(uint32_t timeout_ms) {
|
||||
soft_timer_entry_t timer;
|
||||
|
||||
// Note the timer doesn't have an associated callback, it just exists to create a
|
||||
// hardware interrupt to wake the CPU
|
||||
soft_timer_static_init(&timer, SOFT_TIMER_MODE_ONE_SHOT, 0, NULL);
|
||||
soft_timer_insert(&timer, timeout_ms);
|
||||
|
||||
__wfe();
|
||||
|
||||
// Clean up the timer node if it's not already
|
||||
soft_timer_remove(&timer);
|
||||
}
|
||||
|
|
|
@ -57,23 +57,22 @@
|
|||
if ((TIMEOUT_MS) < 0) { \
|
||||
__wfe(); \
|
||||
} else { \
|
||||
best_effort_wfe_or_timeout(make_timeout_time_ms(TIMEOUT_MS)); \
|
||||
mp_wfe_or_timeout(TIMEOUT_MS); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
extern int mp_interrupt_char;
|
||||
extern ringbuf_t stdin_ringbuf;
|
||||
|
||||
// Port-specific function to create a wakeup interrupt after timeout_ms and enter WFE
|
||||
void mp_wfe_or_timeout(uint32_t timeout_ms);
|
||||
|
||||
uint32_t mp_thread_begin_atomic_section(void);
|
||||
void mp_thread_end_atomic_section(uint32_t);
|
||||
|
||||
void mp_hal_set_interrupt_char(int c);
|
||||
void mp_hal_time_ns_set_from_rtc(void);
|
||||
|
||||
static inline void mp_hal_delay_us(mp_uint_t us) {
|
||||
sleep_us(us);
|
||||
}
|
||||
|
||||
static inline void mp_hal_delay_us_fast(mp_uint_t us) {
|
||||
busy_wait_us(us);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ void soft_timer_handler(void) {
|
|||
heap = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap->pairheap);
|
||||
if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) {
|
||||
mp_sched_schedule(entry->py_callback, MP_OBJ_FROM_PTR(entry));
|
||||
} else {
|
||||
} else if (entry->c_callback) {
|
||||
entry->c_callback(entry);
|
||||
}
|
||||
if (entry->mode == SOFT_TIMER_MODE_PERIODIC) {
|
||||
|
|
Ładowanie…
Reference in New Issue