mirror of
https://github.com/W3SLAV/micropython.git
synced 2025-06-19 20:15:33 -04:00
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.
|
// This is a tickless port, interrupts should always trigger SEV.
|
||||||
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
|
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
|
||||||
|
|
||||||
|
soft_timer_init();
|
||||||
|
|
||||||
#if MICROPY_HW_ENABLE_UART_REPL
|
#if MICROPY_HW_ENABLE_UART_REPL
|
||||||
bi_decl(bi_program_feature("UART REPL"))
|
bi_decl(bi_program_feature("UART REPL"))
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
@ -154,6 +154,10 @@
|
|||||||
#define MICROPY_SSL_MBEDTLS (1)
|
#define MICROPY_SSL_MBEDTLS (1)
|
||||||
#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP)
|
#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
|
// fatfs configuration
|
||||||
#define MICROPY_FATFS_ENABLE_LFN (1)
|
#define MICROPY_FATFS_ENABLE_LFN (1)
|
||||||
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
|
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "pendsv.h"
|
#include "pendsv.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
#include "hardware/irq.h"
|
||||||
#include "hardware/rtc.h"
|
#include "hardware/rtc.h"
|
||||||
#include "pico/unique_id.h"
|
#include "pico/unique_id.h"
|
||||||
|
|
||||||
@ -46,8 +47,6 @@
|
|||||||
// microseconds since the Epoch.
|
// microseconds since the Epoch.
|
||||||
static uint64_t time_us_64_offset_from_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
|
#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_USB_CDC
|
||||||
|
|
||||||
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
|
#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();
|
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) {
|
uint32_t soft_timer_get_ms(void) {
|
||||||
return mp_hal_ticks_ms();
|
return mp_hal_ticks_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
void soft_timer_schedule_at_ms(uint32_t 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());
|
int32_t ms = soft_timer_ticks_diff(ticks_ms, mp_hal_ticks_ms());
|
||||||
ms = MAX(0, 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) {
|
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);
|
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);
|
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) {
|
void cyw43_post_poll_hook(void) {
|
||||||
|
@ -42,6 +42,9 @@ enum {
|
|||||||
|
|
||||||
#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX
|
#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);
|
typedef void (*pendsv_dispatch_t)(void);
|
||||||
|
|
||||||
void pendsv_suspend(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.
|
// pend-SV IRQ level, or equivalent.
|
||||||
uint32_t soft_timer_get_ms(void);
|
uint32_t soft_timer_get_ms(void);
|
||||||
void soft_timer_schedule_at_ms(uint32_t ticks_ms);
|
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
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_SHARED_RUNTIME_SOFTTIMER_H
|
#endif // MICROPY_INCLUDED_SHARED_RUNTIME_SOFTTIMER_H
|
||||||
|
Loading…
Reference in New Issue
Block a user