8000 rp2: Refactor soft timer to use hardware timer alarm. · micropython/micropython@74fb42a · GitHub
[go: up one dir, main page]

Skip to content

Commit 74fb42a

Browse files
projectgusdpgeorge
authored andcommitted
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>
1 parent 2926001 commit 74fb42a

File tree

6 files changed

+29
-13
lines changed

6 files changed

+29
-13
lines changed

ports/rp2/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ int main(int argc, char **argv) {
7676
// This is a tickless port, interrupts should always trigger SEV.
7777
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
7878

79+
soft_timer_init();
80+
7981
#if MICROPY_HW_ENABLE_UART_REPL
8082
bi_decl(bi_program_feature("UART REPL"))
8183
setup_default_uart();

ports/rp2/mpconfigport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@
154154
#define MICROPY_SSL_MBEDTLS (1)
155155
#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP)
156156

157+
// Hardware timer alarm index. Available range 0-3.
158+
// Number 3 is currently used by pico-sdk (PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM)
159+
#define MICROPY_HW_SOFT_TIMER_ALARM_NUM (2)
160+
157161
// fatfs configuration
158162
#define MICROPY_FATFS_ENABLE_LFN (1)
159163
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */

ports/rp2/mphalport.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "pendsv.h"
3636
#include "tusb.h"
3737
#include "uart.h"
38+
#include "hardware/irq.h"
3839
#include "hardware/rtc.h"
3940
#include "pico/unique_id.h"
4041

@@ -46,8 +47,6 @@
4647
// microseconds since the Epoch.
4748
static uint64_t time_us_64_offset_from_epoch;
4849

49-
static alarm_id_t soft_timer_alarm_id = 0;
50-
5150
#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_USB_CDC
5251

5352
#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
273272
panic_unsupported();
274273
}
275274

276-
static int64_t soft_timer_callback(alarm_id_t id, void *user_data) {
277-
soft_timer_alarm_id = 0;
278-
pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
279-
return 0; // don't reschedule this alarm
280-
}
281-
282275
uint32_t soft_timer_get_ms(void) {
283276
return mp_hal_ticks_ms();
284277
}
285278

286279
void soft_timer_schedule_at_ms(uint32_t ticks_ms) {
287-
if (soft_timer_alarm_id != 0) {
288-
cancel_alarm(soft_timer_alarm_id);
289-
}
290280
int32_t ms = soft_timer_ticks_diff(ticks_ms, mp_hal_ticks_ms());
291281
ms = MAX(0, ms);
292-
soft_timer_alarm_id = add_alarm_in_ms(ms, soft_timer_callback, NULL, true);
282+
if (hardware_alarm_set_target(MICROPY_HW_SOFT_TIMER_ALARM_NUM, delayed_by_ms(get_absolute_time(), ms))) {
283+
// "missed" hardware alarm target
284+
hardware_alarm_force_irq(MICROPY_HW_SOFT_TIMER_ALARM_NUM);
285+
}
286+
}
287+
288+
static void soft_timer_hardware_callback(unsigned int alarm_num) {
289+
// The timer alarm ISR needs to call here and trigger PendSV dispatch via
290+
// a second ISR, as PendSV may be currently suspended by the other CPU.
291+
pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
292+
}
293+
294+
void soft_timer_init(void) {
295+
hardware_alarm_claim(MICROPY_HW_SOFT_TIMER_ALARM_NUM);
296+
hardware_alarm_set_callback(MICROPY_HW_SOFT_TIMER_ALARM_NUM, soft_timer_hardware_callback);
293297
}

ports/rp2/mpnetworkport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static void gpio_irq_handler(void) {
6666
void cyw43_irq_init(void) {
6767
gpio_add_raw_irq_handler_with_order_priority(CYW43_PIN_WL_HOST_WAKE, gpio_irq_handler, CYW43_SHARED_IRQ_HANDLER_PRIORITY);
6868
irq_set_enabled(IO_IRQ_BANK0, true);
69-
NVIC_SetPriority(PendSV_IRQn, PICO_LOWEST_IRQ_PRIORITY);
69+
NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV);
7070
}
7171

7272
void cyw43_post_poll_hook(void) {

ports/rp2/pendsv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ enum {
4242

4343
#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX
4444

45+
// PendSV IRQ priority, to run system-level tasks that preempt the main thread.
46+
#define IRQ_PRI_PENDSV PICO_LOWEST_IRQ_PRIORITY
47+
4548
typedef void (*pendsv_dispatch_t)(void);
4649

4750
void pendsv_suspend(void);

shared/runtime/softtimer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ static inline void soft_timer_reinsert(soft_timer_entry_t *entry, uint32_t initi
8181
// pend-SV IRQ level, or equivalent.
8282
uint32_t soft_timer_get_ms(void);
8383
void soft_timer_schedule_at_ms(uint32_t ticks_ms);
84+
85+
// Optional port-specific initialisation function (provided and called by the port if needed).
86+
void soft_timer_init(void);
8487
#endif
8588

8689
#endif // MICROPY_INCLUDED_SHARED_RUNTIME_SOFTTIMER_H

0 commit comments

Comments
 (0)
0