Skip to content

Commit

Permalink
X86 interrupts (#16)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: d3kanesa <[email protected]>
  • Loading branch information
3 people authored Dec 31, 2024
1 parent c2be979 commit e52976f
Showing 1 changed file with 74 additions and 10 deletions.
84 changes: 74 additions & 10 deletions libraries/ms-common/src/x86/interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
}
}
}
Expand All @@ -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;
}
}
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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;
}

0 comments on commit e52976f

Please sign in to comment.