diff --git a/epicardium/api/interrupt-receiver.c b/epicardium/api/interrupt-receiver.c index 95c5038d12ee10bdc53a087ea121a568bb44d86a..c212a402d0a564375bddc193fd7ccf7c50507a81 100644 --- a/epicardium/api/interrupt-receiver.c +++ b/epicardium/api/interrupt-receiver.c @@ -3,33 +3,12 @@ #include "api/common.h" #include "epicardium.h" -void api_interrupt_handler_ctrl_c(api_int_id_t id) - __attribute__((weak, alias("api_interrupt_handler_default"))); -void api_interrupt_handler_bhi160(api_int_id_t id) - __attribute__((weak, alias("api_interrupt_handler_default"))); +void __dispatch_isr(api_int_id_t); /* Timer Interrupt used for control char notification */ void TMR5_IRQHandler(void) { TMR_IntClear(MXC_TMR5); - - switch (API_CALL_MEM->int_id) { - case API_INT_CTRL_C: - api_interrupt_handler_ctrl_c(API_CALL_MEM->int_id); - break; - case API_INT_BHI160: - api_interrupt_handler_bhi160(API_CALL_MEM->int_id); - break; - } - + __dispatch_isr(API_CALL_MEM->int_id); API_CALL_MEM->int_id = 0; } - -__attribute__((weak)) void api_interrupt_handler_catch_all(api_int_id_t id) -{ -} - -void api_interrupt_handler_default(api_int_id_t id) -{ - api_interrupt_handler_catch_all(id); -} diff --git a/epicardium/api/interrupt-sender.c b/epicardium/api/interrupt-sender.c index fb0c65a7c189fbdfa329e8a6a8acdfb67db97c64..cabd3bcb2b96f6f79c65a0a9722bd05860cf860e 100644 --- a/epicardium/api/interrupt-sender.c +++ b/epicardium/api/interrupt-sender.c @@ -2,15 +2,15 @@ #include "api/common.h" #include "tmr_utils.h" -static bool enabled[API_INT_MAX + 1]; +static bool int_enabled[EPIC_INT_NUM]; int api_interrupt_trigger(api_int_id_t id) { - if (id > API_INT_MAX) { + if (id >= EPIC_INT_NUM) { return -EINVAL; } - if (enabled[id]) { + if (int_enabled[id]) { while (API_CALL_MEM->int_id) ; API_CALL_MEM->int_id = id; @@ -21,30 +21,29 @@ int api_interrupt_trigger(api_int_id_t id) void api_interrupt_init(void) { - int i; API_CALL_MEM->int_id = 0; - for (i = 0; i <= API_INT_MAX; i++) { - enabled[i] = false; + for (int i = 0; i < EPIC_INT_NUM; i++) { + int_enabled[i] = false; } } int epic_interrupt_enable(api_int_id_t int_id) { - if (int_id > API_INT_MAX) { + if (int_id >= EPIC_INT_NUM) { return -EINVAL; } - enabled[int_id] = true; + int_enabled[int_id] = true; return 0; } int epic_interrupt_disable(api_int_id_t int_id) { - if (int_id > API_INT_MAX) { + if (int_id >= EPIC_INT_NUM) { return -EINVAL; } - enabled[int_id] = false; + int_enabled[int_id] = false; return 0; } diff --git a/epicardium/api/interrupt-sender.h b/epicardium/api/interrupt-sender.h index 4f690167ceff8622418b4983da17b29085a446f4..419993c72388d15a234d4887a4a71d0a00ccd6d7 100644 --- a/epicardium/api/interrupt-sender.h +++ b/epicardium/api/interrupt-sender.h @@ -1,4 +1,5 @@ #pragma once #include "api/common.h" + void api_interrupt_init(void); int api_interrupt_trigger(api_int_id_t id); diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index c32120e87399e7ca455d2b00ad0b20579df5d1f2..485cb2e1b19bc47af0ee31192cd43cb9470d2fb8 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -11,18 +11,22 @@ typedef unsigned int size_t; #endif /* __SPHINX_DOC */ -/* clang-format off */ -#define API_INT_CTRL_C 1 -#define API_INT_BHI160 2 -#define API_INT_MAX API_INT_BHI160 - /* * These definitions are required for the code-generator. Please don't touch! */ #ifndef API #define API(id, def) def #endif +#ifndef API_ISR +#define API_ISR(id, isr) void isr(void); +#endif +/* + * IDs for all defined API calls. These IDs should not be needed in application + * code on any side. + */ + +/* clang-format off */ #define API_UART_WRITE 0x1 #define API_UART_READ 0x2 #define API_LEDS_SET 0x3 @@ -31,9 +35,53 @@ typedef unsigned int size_t; #define API_STREAM_READ 0x6 #define API_INTERRUPT_ENABLE 0x7 #define API_INTERRUPT_DISABLE 0x8 +/* clang-format on */ + +typedef uint32_t api_int_id_t; + +/** + * Interrupts + * ========== + * Next to API calls, Epicardium API also has an interrupt mechanism to serve + * the other direction. These interrupts can be enabled/disabled + * (masked/unmasked) using :c:func:`epic_interrupt_enable` and + * :c:func:`epic_interrupt_disable`. + */ + +/** + * Enable/unmask an API interrupt. + * + * :param int_id: The interrupt to be enabled + */ +API(API_INTERRUPT_ENABLE, int epic_interrupt_enable(api_int_id_t int_id)); + +/** + * Disable/mask an API interrupt. + * + * :param int_id: The interrupt to be disabled + */ +API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id)); + +/** + * The following interrupts are defined: + */ +/* clang-format off */ +/** Reset Handler? **TODO** */ +#define EPIC_INT_RESET 0 +/** ``^C`` interrupt. See :c:func:`epic_isr_ctrl_c` for details. */ +#define EPIC_INT_CTRL_C 1 +/* Debug interrupt, please ignore */ +#define EPIC_INT_BHI160_TEST 2 +API_ISR(EPIC_INT_BHI160_TEST, epic_isr_bhi160_test); + +/* Number of defined interrupts. */ +#define EPIC_INT_NUM 3 /* clang-format on */ +API_ISR(EPIC_INT_RESET, epic_isr_reset); + + /** * UART/Serial Interface * ===================== @@ -60,6 +108,21 @@ API(API_UART_WRITE, void epic_uart_write_str(const char *str, intptr_t length)); */ API(API_UART_READ, char epic_uart_read_chr(void)); +/** + * **Interrupt Service Routine** + * + * A user-defineable ISR which is triggered when a ``^C`` (``0x04``) is received + * on any serial input device. This function is weakly aliased to + * :c:func:`epic_isr_default` by default. + * + * To enable this interrupt, you need to enable :c:data:`EPIC_INT_CTRL_C`: + * + * .. code-block:: cpp + * + * epic_interrupt_enable(EPIC_INT_CTRL_C); + */ +API_ISR(EPIC_INT_CTRL_C, epic_isr_ctrl_c); + /** * LEDs * ==== @@ -156,23 +219,4 @@ API(API_VIBRA_SET, void epic_vibra_set(int status)); */ API(API_VIBRA_VIBRATE, void epic_vibra_vibrate(int millis)); -/** - * API interrupt type - */ -typedef uint32_t api_int_id_t; - -/** - * Enable/unmask an API interrupt - * - * :param int_id: The interrupt to be enabled - */ -API(API_INTERRUPT_ENABLE, int epic_interrupt_enable(api_int_id_t int_id)); - -/** - * Disable/mask an API interrupt - * - * :param int_id: The interrupt to be disabled - */ -API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id)); - #endif /* _EPICARDIUM_H */ diff --git a/epicardium/modules/serial.c b/epicardium/modules/serial.c index bb9c325ce3933287307093d3e4caefc28ef3a0e8..bf341fe79f1d36242481c150e6dd56dfcae119c6 100644 --- a/epicardium/modules/serial.c +++ b/epicardium/modules/serial.c @@ -57,12 +57,12 @@ static void enqueue_char(char chr) { if (chr == 0x3) { /* Control-C */ - api_interrupt_trigger(API_INT_CTRL_C); + api_interrupt_trigger(EPIC_INT_CTRL_C); } if (chr == 0x0e) { /* Control-N */ - api_interrupt_trigger(API_INT_BHI160); + api_interrupt_trigger(EPIC_INT_BHI160_TEST); } if (xQueueSend(read_queue, &chr, 100) == errQUEUE_FULL) { diff --git a/pycardium/modules/interrupt.c b/pycardium/modules/interrupt.c index b45680c723a8150fd440665065ff8170f8e3e6bc..510efa313f2299b36cf4b99214103094d348e224 100644 --- a/pycardium/modules/interrupt.c +++ b/pycardium/modules/interrupt.c @@ -6,15 +6,15 @@ #include "mphalport.h" // TODO: these should be intialized as mp_const_none -mp_obj_t callbacks[API_INT_MAX + 1] = { +mp_obj_t callbacks[EPIC_INT_NUM] = { 0, }; -void api_interrupt_handler_catch_all(api_int_id_t id) +void epic_isr_default_handler(api_int_id_t id) { // TODO: check if id is out of rante // TOOD: check against mp_const_none - if (id <= API_INT_MAX) { + if (id < EPIC_INT_NUM) { if (callbacks[id]) { mp_sched_schedule( callbacks[id], MP_OBJ_NEW_SMALL_INT(id) @@ -32,7 +32,7 @@ STATIC mp_obj_t mp_interrupt_set_callback(mp_obj_t id_in, mp_obj_t callback_obj) } // TODO: throw error if id is out of range - if (id <= API_INT_MAX) { + if (id < EPIC_INT_NUM) { callbacks[id] = callback_obj; } diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c index 4ca84e13027f55c434ece35cf741447284498450..95d4bffa90089570d4e26ab5f098345b646c8dab 100644 --- a/pycardium/mphalport.c +++ b/pycardium/mphalport.c @@ -62,7 +62,7 @@ long _write(int fd, const char *buf, size_t cnt) return cnt; } -void api_interrupt_handler_ctrl_c(void) +void epic_isr_ctrl_c(void) { /* Taken from lib/micropython/micropython/lib/utils/interrupt_char.c */ MP_STATE_VM(mp_pending_exception) = @@ -83,9 +83,9 @@ void mp_hal_set_interrupt_char(char c) } if (c == 0x03) { - epic_interrupt_enable(API_INT_CTRL_C); + epic_interrupt_enable(EPIC_INT_CTRL_C); } else { - epic_interrupt_disable(API_INT_CTRL_C); + epic_interrupt_disable(EPIC_INT_CTRL_C); } }