rp2: Fix wakeup from WFE on core1.

If core1 executes `mp_wfe_or_timeout()` then it needs to receive an
interrupt or a SEV to resume execution, but the soft timer interrupt only
fires on core 0.  This fix adds a SEV to the soft timer interrupt handler.

This issue was masked by the issue fixed in the previous commit, as WFE
previously wasn't suspending properly.

Verified via the existing thread_sleep2 test.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
Angus Gratton 2024-07-03 15:52:31 +10:00 committed by Damien George
parent eced9d86a7
commit 9db16cfe31
3 changed files with 12 additions and 1 deletions

View File

@ -228,6 +228,13 @@ static void soft_timer_hardware_callback(unsigned int alarm_num) {
// The timer alarm ISR needs to call here and trigger PendSV dispatch via // 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. // a second ISR, as PendSV may be currently suspended by the other CPU.
pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
// This ISR only runs on core0, but if core1 is running Python code then it
// may be blocked in WFE so wake it up as well. Unfortunately this also sets
// the event flag on core0, so a subsequent WFE on this core will not suspend
if (core1_entry != NULL) {
__sev();
}
} }
void soft_timer_init(void) { void soft_timer_init(void) {

View File

@ -39,7 +39,7 @@ extern uint8_t __StackTop, __StackBottom;
void *core_state[2]; void *core_state[2];
// This will be non-NULL while Python code is executing. // This will be non-NULL while Python code is executing.
static void *(*core1_entry)(void *) = NULL; core_entry_func_t core1_entry = NULL;
static void *core1_arg = NULL; static void *core1_arg = NULL;
static uint32_t *core1_stack = NULL; static uint32_t *core1_stack = NULL;

View File

@ -32,6 +32,10 @@ typedef struct mutex mp_thread_mutex_t;
extern void *core_state[2]; extern void *core_state[2];
typedef void *(*core_entry_func_t)(void *);
extern core_entry_func_t core1_entry;
void mp_thread_init(void); void mp_thread_init(void);
void mp_thread_deinit(void); void mp_thread_deinit(void);
void mp_thread_gc_others(void); void mp_thread_gc_others(void);