diff options
| -rw-r--r-- | ports/rp2/mpnetworkport.c | 4 | ||||
| -rw-r--r-- | ports/rp2/mpthreadport.c | 3 | ||||
| -rw-r--r-- | ports/rp2/pendsv.c | 30 | ||||
| -rw-r--r-- | ports/rp2/pendsv.h | 3 |
4 files changed, 26 insertions, 14 deletions
diff --git a/ports/rp2/mpnetworkport.c b/ports/rp2/mpnetworkport.c index 7a6df7f6e..e1e156782 100644 --- a/ports/rp2/mpnetworkport.c +++ b/ports/rp2/mpnetworkport.c @@ -42,7 +42,6 @@ static soft_timer_entry_t mp_network_soft_timer; #if MICROPY_PY_NETWORK_CYW43 #include "lib/cyw43-driver/src/cyw43.h" #include "lib/cyw43-driver/src/cyw43_stats.h" -#include "hardware/irq.h" #if !defined(__riscv) #if PICO_RP2040 @@ -97,9 +96,6 @@ 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); - #if !defined(__riscv) - NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV); - #endif } // This hook will run on whichever CPU serviced the PendSV interrupt diff --git a/ports/rp2/mpthreadport.c b/ports/rp2/mpthreadport.c index 8fd5e5d79..043a878c8 100644 --- a/ports/rp2/mpthreadport.c +++ b/ports/rp2/mpthreadport.c @@ -106,6 +106,9 @@ static void core1_entry_wrapper(void) { // Allow MICROPY_BEGIN_ATOMIC_SECTION to be invoked from core0. multicore_lockout_victim_init(); + // Set PendSV interrupt priority correctly for CPU1 + pendsv_init(); + if (core1_entry) { core1_entry(core1_arg); } diff --git a/ports/rp2/pendsv.c b/ports/rp2/pendsv.c index 0bf64d0ae..05b521fde 100644 --- a/ports/rp2/pendsv.c +++ b/ports/rp2/pendsv.c @@ -28,6 +28,7 @@ #include "py/mpconfig.h" #include "py/mpthread.h" #include "pendsv.h" +#include "hardware/irq.h" #if PICO_RP2040 #include "RP2040.h" @@ -45,6 +46,9 @@ static pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; static inline void pendsv_resume_run_dispatch(void); +// PendSV IRQ priority, to run system-level tasks that preempt the main thread. +#define IRQ_PRI_PENDSV PICO_LOWEST_IRQ_PRIORITY + void PendSV_Handler(void); #if MICROPY_PY_THREAD @@ -53,8 +57,14 @@ void PendSV_Handler(void); // loop of mp_wfe_or_timeout(), where we don't want the CPU event bit to be set. static mp_thread_recursive_mutex_t pendsv_mutex; +// Called from CPU0 during boot, but may be called later when CPU1 wakes up void pendsv_init(void) { - mp_thread_recursive_mutex_init(&pendsv_mutex); + if (get_core_num() == 0) { + mp_thread_recursive_mutex_init(&pendsv_mutex); + } + #if !defined(__riscv) + NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV); + #endif } void pendsv_suspend(void) { @@ -117,11 +127,13 @@ static inline void pendsv_resume_run_dispatch(void) { void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { pendsv_dispatch_table[slot] = f; + // There is a race here where other core calls pendsv_suspend() before ISR + // can execute so this check fails, but dispatch will happen later when + // other core calls pendsv_resume(). if (pendsv_suspend_count() == 0) { #if PICO_ARM - // There is a race here where other core calls pendsv_suspend() before - // ISR can execute, but dispatch will happen later when other core - // calls pendsv_resume(). + // Note this register is part of each CPU core, so setting it on CPUx + // will set the IRQ and run PendSV_Handler on CPUx only. SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; #elif PICO_RISCV struct timespec ts; @@ -136,15 +148,19 @@ void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { } // PendSV interrupt handler to perform background processing. +// +// Handler can execute on either CPU if MICROPY_PY_THREAD is set (no code on +// CPU1 calls pendsv_schedule_dispatch(), but CPU1 can call pendsv_resume() +// which will trigger it). void PendSV_Handler(void) { #if MICROPY_PY_THREAD if (!mp_thread_recursive_mutex_lock(&pendsv_mutex, 0)) { - // Failure here means core 1 holds pendsv_mutex. ISR will - // run again after core 1 calls pendsv_resume(). + // Failure here means other core holds pendsv_mutex. ISR will + // run again after that core calls pendsv_resume(). return; } - // Core 0 should not already have locked pendsv_mutex + // This core should not already have locked pendsv_mutex assert(pendsv_mutex.mutex.enter_count == 1); #else assert(pendsv_suspend_count() == 0); diff --git a/ports/rp2/pendsv.h b/ports/rp2/pendsv.h index 6abe950df..de89f0473 100644 --- a/ports/rp2/pendsv.h +++ b/ports/rp2/pendsv.h @@ -42,9 +42,6 @@ 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_init(void); |
