rp2: Refactor soft timer to use hardware timer alarm.
Progress towards removing pico-sdk alarm pool, due to a known issue. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
parent
2926001b60
commit
74fb42aa82
@ -76,6 +76,8 @@ int main(int argc, char **argv) {
|
||||
// This is a tickless port, interrupts should always trigger SEV.
|
||||
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
|
||||
|
||||
soft_timer_init();
|
||||
|
||||
#if MICROPY_HW_ENABLE_UART_REPL
|
||||
bi_decl(bi_program_feature("UART REPL"))
|
||||
setup_default_uart();
|
||||
|
@ -154,6 +154,10 @@
|
||||
#define MICROPY_SSL_MBEDTLS (1)
|
||||
#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP)
|
||||
|
||||
// Hardware timer alarm index. Available range 0-3.
|
||||
// Number 3 is currently used by pico-sdk (PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM)
|
||||
#define MICROPY_HW_SOFT_TIMER_ALARM_NUM (2)
|
||||
|
||||
// fatfs configuration
|
||||
#define MICROPY_FATFS_ENABLE_LFN (1)
|
||||
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "pendsv.h"
|
||||
#include "tusb.h"
|
||||
#include "uart.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "hardware/rtc.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
@ -46,8 +47,6 @@
|
||||
// microseconds since the Epoch.
|
||||
static uint64_t time_us_64_offset_from_epoch;
|
||||
|
||||
static alarm_id_t soft_timer_alarm_id = 0;
|
||||
|
||||
#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_USB_CDC
|
||||
|
||||
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
|
||||
@ -273,21 +272,26 @@ uint32_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
|
||||
panic_unsupported();
|
||||
}
|
||||
|
||||
static int64_t soft_timer_callback(alarm_id_t id, void *user_data) {
|
||||
soft_timer_alarm_id = 0;
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
|
||||
return 0; // don't reschedule this alarm
|
||||
}
|
||||
|
||||
uint32_t soft_timer_get_ms(void) {
|
||||
return mp_hal_ticks_ms();
|
||||
}
|
||||
|
||||
void soft_timer_schedule_at_ms(uint32_t ticks_ms) {
|
||||
if (soft_timer_alarm_id != 0) {
|
||||
cancel_alarm(soft_timer_alarm_id);
|
||||
}
|
||||
int32_t ms = soft_timer_ticks_diff(ticks_ms, mp_hal_ticks_ms());
|
||||
ms = MAX(0, ms);
|
||||
soft_timer_alarm_id = add_alarm_in_ms(ms, soft_timer_callback, NULL, true);
|
||||
if (hardware_alarm_set_target(MICROPY_HW_SOFT_TIMER_ALARM_NUM, delayed_by_ms(get_absolute_time(), ms))) {
|
||||
// "missed" hardware alarm target
|
||||
hardware_alarm_force_irq(MICROPY_HW_SOFT_TIMER_ALARM_NUM);
|
||||
}
|
||||
}
|
||||
|
||||
static void soft_timer_hardware_callback(unsigned int alarm_num) {
|
||||
// The timer alarm ISR needs to call here and trigger PendSV dispatch via
|
||||
// a second ISR, as PendSV may be currently suspended by the other CPU.
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ static void gpio_irq_handler(void) {
|
||||
void cyw43_irq_init(void) {
|
||||
gpio_add_raw_irq_handler_with_order_priority(CYW43_PIN_WL_HOST_WAKE, gpio_irq_handler, CYW43_SHARED_IRQ_HANDLER_PRIORITY);
|
||||
irq_set_enabled(IO_IRQ_BANK0, true);
|
||||
NVIC_SetPriority(PendSV_IRQn, PICO_LOWEST_IRQ_PRIORITY);
|
||||
NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV);
|
||||
}
|
||||
|
||||
void cyw43_post_poll_hook(void) {
|
||||
|
@ -42,6 +42,9 @@ enum {
|
||||
|
||||
#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX
|
||||
|
||||
// PendSV IRQ priority, to run system-level tasks that preempt the main thread.
|
||||
#define IRQ_PRI_PENDSV PICO_LOWEST_IRQ_PRIORITY
|
||||
|
||||
typedef void (*pendsv_dispatch_t)(void);
|
||||
|
||||
void pendsv_suspend(void);
|
||||
|
@ -81,6 +81,9 @@ static inline void soft_timer_reinsert(soft_timer_entry_t *entry, uint32_t initi
|
||||
// pend-SV IRQ level, or equivalent.
|
||||
uint32_t soft_timer_get_ms(void);
|
||||
void soft_timer_schedule_at_ms(uint32_t ticks_ms);
|
||||
|
||||
// Optional port-specific initialisation function (provided and called by the port if needed).
|
||||
void soft_timer_init(void);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_RUNTIME_SOFTTIMER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user