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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy