diff --git a/ports/arm/atomport-private.h b/ports/arm/atomport-private.h index 42c19fc..35f1a80 100644 --- a/ports/arm/atomport-private.h +++ b/ports/arm/atomport-private.h @@ -30,9 +30,12 @@ #ifndef __ATOM_PORT_PRIVATE_H #define __ATOM_PORT_PRIVATE_H +/* ISR handler prototype used for registration of interuppt handlers */ +typedef void (*ISR_FUNC)(void); /* Function prototypes */ extern void archIRQHandler (void); +extern int archISRInstall (int int_vector, ISR_FUNC isr_func); /* Platform-specific interrupt dispatcher called on receipt of IRQ */ extern void __interrupt_dispatcher (void); diff --git a/ports/arm/platforms/dm36x/atomport-private.c b/ports/arm/platforms/dm36x/atomport-private.c index a7b2064..40371df 100644 --- a/ports/arm/platforms/dm36x/atomport-private.c +++ b/ports/arm/platforms/dm36x/atomport-private.c @@ -45,6 +45,20 @@ extern int main(void); #define TIMER0_REG(offset) *(volatile uint32_t *)(DM36X_TIMER0_BASE + offset) #define INTC_REG(offset) *(volatile uint32_t *)(DM36X_INTC_BASE + offset) +/** + * Table of registered ISR handlers: pre-initialised + * with all disabled except the Atomthreads timer tick ISR. + */ +static ISR_FUNC isr_handlers[DM36X_INTC_MAX_VEC + 1] = +{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + atomTimerTick, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + /** * \b _mainCRTStartup @@ -136,14 +150,49 @@ low_level_init (void) } +/** + * \b archISRInstall + * + * Register an interrupt handler to be called if a particular + * interrupt vector occurs. + * + * Note that all registered ISRs are called within atomIntEnter() + * and atomIntExit() calls, which means they can use OS services + * that do not block (e.g. atomSemPut()). + * + * @param[in] int_vector Interrupt vector to install handler for + * @param[in] isr_func Handler to call when specified int occurs + * + * @retval ATOM_OK Success + * @retval ATOM_ERROR Error + */ +int archISRInstall (int int_vector, ISR_FUNC isr_func) +{ + int status; + + /* Check vector is valid */ + if ((int_vector < 0) || (int_vector > DM36X_INTC_MAX_VEC)) + { + /* Invalid vector number */ + status = ATOM_ERROR; + } + else + { + /* Valid vector, install it in the ISR table */ + isr_handlers[int_vector] = isr_func; + status = ATOM_OK; + } + + return (status); +} + + /** * \b __interrupt_dispatcher * * Interrupt dispatcher: determines the source of the IRQ and calls * the appropriate ISR. * - * Currently only the OS system tick ISR is implemented. - * * Note that any ISRs which call Atomthreads OS routines that can * cause rescheduling of threads must be surrounded by calls to * atomIntEnter() and atomIntExit(). @@ -163,14 +212,14 @@ __interrupt_dispatcher (void) { /* Spurious interrupt */ uart_write_halt ("Spurious IRQ\n"); - } - else - { + } + else + { /* Translate from vector address to vector number */ vector = (INTC_REG(DM36X_INTC_IRQENTRY) / 4) - 1; - /* TIMER0:12 tick interrupt (call Atomthreads timer tick ISR) */ - if (vector == DM36X_INTC_VEC_TINT0) + /* Check vector number is valid */ + if ((vector > 0) && (vector <= DM36X_INTC_MAX_VEC) && (isr_handlers[vector] != NULL)) { /* Ack the interrupt immediately, could get scheduled out below */ INTC_REG(((vector >= 32) ? DM36X_INTC_IRQ1 : DM36X_INTC_IRQ0)) = (1 << ((vector >= 32) ? (vector - 32) : vector)); @@ -181,8 +230,8 @@ __interrupt_dispatcher (void) */ atomIntEnter(); - /* Call the OS system tick handler */ - atomTimerTick(); + /* Call the registered ISR */ + isr_handlers[vector](); /* Call the interrupt exit routine */ atomIntExit(TRUE); @@ -193,7 +242,7 @@ __interrupt_dispatcher (void) uart_write_halt ("Unexpected IRQ vector\n"); } - } + } } diff --git a/ports/arm/platforms/dm36x/dm36x-io.h b/ports/arm/platforms/dm36x/dm36x-io.h index b6fe164..c4e5cfb 100644 --- a/ports/arm/platforms/dm36x/dm36x-io.h +++ b/ports/arm/platforms/dm36x/dm36x-io.h @@ -230,7 +230,17 @@ #define DM36X_INTC_PRI6 0x48 #define DM36X_INTC_PRI7 0x4C /** Interrupt controller vector offsets */ -#define DM36X_INTC_VEC_TINT0 32 +#define DM36X_INTC_VEC_VPSSINT0 0 +#define DM36X_INTC_VEC_VPSSINT1 1 +#define DM36X_INTC_VEC_VPSSINT2 2 +#define DM36X_INTC_VEC_VPSSINT3 3 +#define DM36X_INTC_VEC_VPSSINT4 4 +#define DM36X_INTC_VEC_VPSSINT5 5 +#define DM36X_INTC_VEC_VPSSINT6 6 +#define DM36X_INTC_VEC_VPSSINT7 7 +#define DM36X_INTC_VEC_VPSSINT8 8 +#define DM36X_INTC_VEC_TINT0 32 +#define DM36X_INTC_MAX_VEC 63 /** UART registers */