diff --git a/epicardium/api/caller.c b/epicardium/api/caller.c index 8e61b674b4179832223f1c85adafca137c2ea113..54d9c4aea555950816bf7ab3f52898c6ca73572c 100644 --- a/epicardium/api/caller.c +++ b/epicardium/api/caller.c @@ -5,8 +5,17 @@ #define MXC_ASSERT_ENABLE #include "mxc_assert.h" +static uint32_t irq_save = 0; + void *_api_call_start(api_id_t id, uintptr_t size) { + /* + * Disable all maskable interrupts here, to be turned on again at the + * end of _api_call_transact(). + */ + irq_save = __get_PRIMASK(); + __set_PRIMASK(1); + while (SEMA_GetSema(_API_SEMAPHORE) == E_BUSY) { } @@ -51,6 +60,12 @@ void *_api_call_transact(void *buffer) API_CALL_MEM->call_flag = _API_FLAG_IDLE; SEMA_FreeSema(_API_SEMAPHORE); + /* + * Re-enable interrupts (if previously enabled) after completing the API + * call. + */ + __set_PRIMASK(irq_save); + return API_CALL_MEM->buffer; } diff --git a/epicardium/api/control.c b/epicardium/api/control.c index 102c07e27d325004e4ae584c7cd327ecb67503ce..27b88c2c9a18dd358632f39f504f1f4aa0efa0ad 100644 --- a/epicardium/api/control.c +++ b/epicardium/api/control.c @@ -214,24 +214,32 @@ void core1_trigger_reset(void) interrupt_trigger_sync(EPIC_INT_RESET); } +bool core1_is_ready(void) +{ + bool ready; + + while (SEMA_GetSema(_CONTROL_SEMAPHORE) == E_BUSY) { + } + + /* + * core 1 will set the ready flag once it is spinning in the + * above loop, waiting for a new IVT. + */ + ready = core1_info.ready; + + SEMA_FreeSema(_CONTROL_SEMAPHORE); + + return ready; +} + void core1_wait_ready(void) { /* Wait for the core to accept */ while (1) { - while (SEMA_GetSema(_CONTROL_SEMAPHORE) == E_BUSY) { - } - - /* - * core 1 will set the ready flag once it is spinning in the - * above loop, waiting for a new IVT. - */ - if (core1_info.ready) { - SEMA_FreeSema(_CONTROL_SEMAPHORE); + if (core1_is_ready()) { break; } - SEMA_FreeSema(_CONTROL_SEMAPHORE); - for (int i = 0; i < 10000; i++) { } } diff --git a/epicardium/api/dispatcher.h b/epicardium/api/dispatcher.h index 4b79095ea530aa8b06cd1bf71d5d5b91972eb049..727fe5acd339e1ce2e882b6bf4a73b433daf09c3 100644 --- a/epicardium/api/dispatcher.h +++ b/epicardium/api/dispatcher.h @@ -39,6 +39,9 @@ void core1_boot(void); /* Reset core 1 into a state where it can accept a new payload */ void core1_trigger_reset(void); +/* Check if core 1 is ready for a new payload */ +bool core1_is_ready(void); + /* Wait for core 1 to respond that it is ready for a new payload */ void core1_wait_ready(void); diff --git a/epicardium/user_core/lifecycle.c b/epicardium/user_core/lifecycle.c index efe1f532a3eb36d2fcd626aaa978634b221d14b2..89d4dce4973ed9df3a11a0ba89dcad7d9878dcb8 100644 --- a/epicardium/user_core/lifecycle.c +++ b/epicardium/user_core/lifecycle.c @@ -119,8 +119,18 @@ static int do_load(struct load_info *info) /* * Wait for the core to become ready to accept a new payload. + * + * If it is not yet ready, hand back control of the API mutex to the + * dispatcher so it can finish dispatching a current API call. This is + * necessary for payloads which have interrupts disabled during an API + * call. */ - core1_wait_ready(); + while (!core1_is_ready()) { + mutex_unlock(&api_mutex); + /* Sleep so the dispatcher task can take the lock. */ + vTaskDelay(8); + mutex_lock(&api_mutex); + } /* * Reinitialize Hardware & Drivers