Skip to content
Snippets Groups Projects
Commit 79a0d3d5 authored by rahix's avatar rahix
Browse files

feat(interrupts): Dispatch interrupts asynchroneously


Instead of blocking the triggering task when core 1 is still busy
handling the previous interrupt, offload interrupt dispatching into
a separate task.  This is the first step towards making API-calls
interrupt safe.

Next to the async triggering, the synchroneous mechanism is retained for
special cases where async does not work (e.g. because of spin-locks).
Currently, there is only one such case when resetting core 1 (triggering
EPIC_INT_RESET).

Signed-off-by: default avatarRahix <rahix@rahix.de>
parent 7b56f29a
No related branches found
No related tags found
No related merge requests found
......@@ -9,7 +9,7 @@
#include "tmr.h"
static void __core1_init(void);
extern void interrupt_trigger(api_int_id_t id);
extern void interrupt_trigger_sync(api_int_id_t id);
struct core1_info {
/* Location of core1's interrupt vector table */
......@@ -206,8 +206,13 @@ void core1_boot(void)
void core1_trigger_reset(void)
{
/* Signal core 1 that we intend to load a new payload. */
interrupt_trigger(EPIC_INT_RESET);
/*
* Signal core 1 that we intend to load a new payload.
*
* This needs to be synchroneous because otherwise we will deadlock
* (Lifecycle task busy-spins and interrupt can never get dispatched).
*/
interrupt_trigger_sync(EPIC_INT_RESET);
}
void core1_wait_ready(void)
......
......@@ -133,6 +133,16 @@ int main(void)
&dispatcher_task_id) != pdPASS) {
panic("Failed to create %s task!", "API Dispatcher");
}
/* Interrupts */
if (xTaskCreate(
vInterruptsTask,
(const char *)"Interrupt Dispatcher",
configMINIMAL_STACK_SIZE,
NULL,
tskIDLE_PRIORITY + 2,
NULL) != pdPASS) {
panic("Failed to create %s task!", "Interrupt Dispatcher");
}
/* BLE */
if (ble_shall_start()) {
......
#include "modules/mutex.h"
#include "modules/log.h"
#include "epicardium.h"
#include "api/interrupt-sender.h"
#include <assert.h>
......@@ -14,11 +15,28 @@ struct interrupt_priv {
static struct interrupt_priv interrupt_data;
static struct mutex interrupt_mutex;
static TaskHandle_t interrupts_task;
void interrupt_trigger(api_int_id_t id)
{
assert(id < EPIC_INT_NUM);
mutex_lock(&interrupt_mutex);
if (interrupt_data.int_enabled[id]) {
interrupt_data.int_pending[id] = true;
interrupt_data.has_pending = true;
mutex_unlock(&interrupt_mutex);
xTaskNotifyGive(interrupts_task);
} else {
mutex_unlock(&interrupt_mutex);
}
}
void interrupt_trigger_sync(api_int_id_t id)
{
assert(id < EPIC_INT_NUM);
mutex_lock(&interrupt_mutex);
if (!interrupt_data.int_enabled[id])
goto out;
......@@ -97,3 +115,42 @@ int epic_interrupt_disable(api_int_id_t int_id)
return 0;
}
/* }}} */
void vInterruptsTask(void *pvParameters)
{
interrupts_task = xTaskGetCurrentTaskHandle();
while (true) {
mutex_lock(&interrupt_mutex);
if (!interrupt_data.has_pending) {
/* Wait for a wakeup event from interrupt_trigger() */
mutex_unlock(&interrupt_mutex);
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
mutex_lock(&interrupt_mutex);
}
while (!api_interrupt_is_ready()) {
mutex_unlock(&interrupt_mutex);
vTaskDelay(pdMS_TO_TICKS(5));
mutex_lock(&interrupt_mutex);
}
api_int_id_t current_irq = EPIC_INT_NUM;
for (size_t i = 0; i < EPIC_INT_NUM; i++) {
if (interrupt_data.int_pending[i]) {
current_irq = i;
interrupt_data.int_pending[i] = false;
break;
}
}
if (current_irq == EPIC_INT_NUM) {
interrupt_data.has_pending = false;
} else if (interrupt_data.int_enabled[current_irq]) {
api_interrupt_trigger(current_irq);
}
mutex_unlock(&interrupt_mutex);
}
}
......@@ -31,9 +31,11 @@ void return_to_menu(void);
/* ---------- Interrupts --------------------------------------------------- */
void interrupt_init(void);
void interrupt_trigger(api_int_id_t id);
void interrupt_trigger_sync(api_int_id_t id);
void interrupt_trigger_unsafe(api_int_id_t id) __attribute__((deprecated(
"interrupt_trigger_unsafe() is racy and only exists for legacy code."
)));
void vInterruptsTask(void *pvParameters);
/* ---------- Serial ------------------------------------------------------- */
#define SERIAL_READ_BUFFER_SIZE 128
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment