From e52976fa14d26d56beb27f8174260bcc39a89dd9 Mon Sep 17 00:00:00 2001 From: Aryan Kashem <130705280+Akashem06@users.noreply.github.com> Date: Tue, 31 Dec 2024 14:25:27 -0500 Subject: [PATCH] X86 interrupts (#16) * started working on nvic * finish interrupt_nvic_enable * exti enable and small fixes * finish exti functions * Finish NVIC and fix EXTI * Remove .idea * Comment NVIC related * small fix * lint and format * Formatting --------- Co-authored-by: M. Wasif Kamran Co-authored-by: d3kanesa --- libraries/ms-common/src/x86/interrupts.c | 84 +++++++++++++++++++++--- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/libraries/ms-common/src/x86/interrupts.c b/libraries/ms-common/src/x86/interrupts.c index c0140c9..93c35bb 100644 --- a/libraries/ms-common/src/x86/interrupts.c +++ b/libraries/ms-common/src/x86/interrupts.c @@ -39,7 +39,9 @@ typedef enum { typedef struct { bool enabled; /**< Interrupt Channel enabled state */ bool masked; /**< Interrupt Channel masked state */ + bool pending; /**< Interrupt Channel pending state */ x86InterruptHandler handler; /**< Interrupt Channel interrupt handler */ + InterruptPriority priority; /**< Interrupt Channel interrupt priority */ } X86Interrupt; /** @brief Mock NVIC table that stores all function pointers */ @@ -59,8 +61,11 @@ static void s_nvic_handler(int signum, siginfo_t *info, void *context) { int interrupt_id = info->si_value.sival_int; if (interrupt_id >= 0 && (uint32_t)interrupt_id < NUM_STM32L433X_INTERRUPT_CHANNELS) { - if ((s_nvic_handlers[interrupt_id].handler != NULL) && !s_nvic_handlers[interrupt_id].masked && s_nvic_handlers[interrupt_id].enabled) { + if ((s_nvic_handlers[interrupt_id].handler != NULL) && !s_nvic_handlers[interrupt_id].masked && s_nvic_handlers[interrupt_id].enabled && s_nvic_handlers[interrupt_id].pending) { s_nvic_handlers[interrupt_id].handler(interrupt_id); + + /* Turn off pending after handler function has run */ + s_nvic_handlers[interrupt_id].pending = false; } } } @@ -69,8 +74,9 @@ static void s_exti_handler(int signum, siginfo_t *info, void *context) { int interrupt_id = info->si_value.sival_int; if (interrupt_id >= 0 && (uint32_t)interrupt_id < NUM_STM32L433X_EXTI_LINES) { - if ((s_exti_interrupts[interrupt_id].handler != NULL) && !s_exti_interrupts[interrupt_id].masked && s_exti_interrupts[interrupt_id].enabled) { + if ((s_exti_interrupts[interrupt_id].handler != NULL) && !s_exti_interrupts[interrupt_id].masked && s_exti_interrupts[interrupt_id].enabled && s_exti_interrupts[interrupt_id].pending) { s_exti_interrupts[interrupt_id].handler(interrupt_id); + s_exti_interrupts[interrupt_id].pending = false; } } } @@ -150,26 +156,44 @@ void interrupt_init(void) { for (uint8_t i = 0U; i < NUM_STM32L433X_INTERRUPT_CHANNELS; i++) { s_nvic_handlers[i].enabled = false; s_nvic_handlers[i].masked = true; + s_nvic_handlers[i].pending = false; s_nvic_handlers[i].handler = s_default_handler; } for (uint8_t i = 0U; i < NUM_STM32L433X_EXTI_LINES; i++) { s_exti_interrupts[i].enabled = false; s_exti_interrupts[i].masked = true; + s_exti_interrupts[i].pending = false; s_exti_interrupts[i].handler = s_default_handler; } } StatusCode interrupt_nvic_enable(uint8_t irq_channel, InterruptPriority priority) { - /* This function is for future expansion, in the situation we want to simulate NVIC interrupts */ - return STATUS_CODE_UNIMPLEMENTED; + /* Validate priority and irq_channel */ + if ((priority >= NUM_INTERRUPT_PRIORITIES && priority < configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY) || irq_channel >= NUM_STM32L433X_INTERRUPT_CHANNELS) { + return STATUS_CODE_INVALID_ARGS; + } + + /* Check if channel is already enabled */ + if (s_nvic_handlers[irq_channel].enabled) { + return STATUS_CODE_RESOURCE_EXHAUSTED; + } + + /* Enable the interrupt, unmask, and set priority */ + s_nvic_handlers[irq_channel].enabled = true; + s_nvic_handlers[irq_channel].masked = false; + s_nvic_handlers[irq_channel].priority = priority; + + return STATUS_CODE_OK; } StatusCode interrupt_nvic_register_handler(uint8_t irq_channel, x86InterruptHandler handler, const InterruptSettings *settings) { + /* Validate settings and channel */ if (settings == NULL || settings->class >= NUM_INTERRUPT_CLASSES || settings->edge >= NUM_INTERRUPT_EDGES || irq_channel > NUM_STM32L433X_INTERRUPT_CHANNELS) { return STATUS_CODE_INVALID_ARGS; } + /* If handler is not provided, use the default handler defined earlier */ if (handler == NULL) { s_nvic_handlers[irq_channel].handler = s_default_handler; } else { @@ -180,8 +204,21 @@ StatusCode interrupt_nvic_register_handler(uint8_t irq_channel, x86InterruptHand } StatusCode interrupt_nvic_trigger(uint8_t irq_channel) { - /* This function is for future expansion, in the situation we want to simulate NVIC interrupts */ - return STATUS_CODE_UNIMPLEMENTED; + /* Validate channel */ + + if (irq_channel >= NUM_STM32L433X_INTERRUPT_CHANNELS) { + return STATUS_CODE_INVALID_ARGS; + } + + s_nvic_handlers[irq_channel].pending = true; + + /* Add the interrupt to the signal queue + https://man7.org/linux/man-pages/man3/sigqueue.3.html */ + siginfo_t value_store; + value_store.si_value.sival_int = irq_channel; + sigqueue(s_pid, SIGRTMIN + (int)s_nvic_handlers[irq_channel].priority, value_store.si_value); + + return STATUS_CODE_OK; } StatusCode interrupt_exti_enable(GpioAddress *address, const InterruptSettings *settings) { @@ -195,6 +232,7 @@ StatusCode interrupt_exti_enable(GpioAddress *address, const InterruptSettings * s_exti_interrupts[address->pin].enabled = true; s_exti_interrupts[address->pin].masked = false; + s_exti_interrupts[address->pin].priority = settings->priority; return STATUS_CODE_OK; } @@ -214,17 +252,43 @@ StatusCode interrupt_exti_register_handler(uint8_t line, x86InterruptHandler han } StatusCode interrupt_exti_trigger(uint8_t line) { - return STATUS_CODE_UNIMPLEMENTED; + if (line > NUM_STM32L433X_EXTI_LINES) { + return STATUS_CODE_INVALID_ARGS; + } + + s_exti_interrupts[line].pending = true; + + siginfo_t value_store; + value_store.si_value.sival_int = line; + sigqueue(s_pid, SIGRTMIN + (int)s_exti_interrupts[line].priority, value_store.si_value); + + return STATUS_CODE_OK; } StatusCode interrupt_exti_get_pending(uint8_t line, uint8_t *pending_bit) { - return STATUS_CODE_UNIMPLEMENTED; + if (line > NUM_STM32L433X_EXTI_LINES) { + return STATUS_CODE_INVALID_ARGS; + } + + *pending_bit = (uint8_t)s_exti_interrupts[line].pending; + return STATUS_CODE_OK; } StatusCode interrupt_exti_clear_pending(uint8_t line) { - return STATUS_CODE_UNIMPLEMENTED; + if (line > NUM_STM32L433X_EXTI_LINES) { + return STATUS_CODE_INVALID_ARGS; + } + + s_exti_interrupts[line].pending = false; + return STATUS_CODE_OK; } StatusCode interrupt_exti_set_mask(uint8_t line, bool masked) { - return STATUS_CODE_UNIMPLEMENTED; + if (line > NUM_STM32L433X_EXTI_LINES) { + return STATUS_CODE_INVALID_ARGS; + } + + s_exti_interrupts[line].masked = masked; + + return STATUS_CODE_OK; }