From a07cb30d18b8c86807a90c8d028a59091e78b22d Mon Sep 17 00:00:00 2001 From: Ioannis Glaropoulos Date: Thu, 19 Dec 2019 11:57:43 +0100 Subject: [PATCH] arch: arm: cortex-m: implement support for dynamic direct interrupts This commits implements the support for dynamic direct interrupts for the ARM Cortex-M architecture, and exposes the support to the user as an ARM-only API. Signed-off-by: Ioannis Glaropoulos --- arch/arm/core/aarch32/irq_manage.c | 29 +++++++++++++++ include/arch/arm/aarch32/irq.h | 58 ++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/arch/arm/core/aarch32/irq_manage.c b/arch/arm/core/aarch32/irq_manage.c index b40de5aa55e..13d59d8457d 100644 --- a/arch/arm/core/aarch32/irq_manage.c +++ b/arch/arm/core/aarch32/irq_manage.c @@ -262,4 +262,33 @@ int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, z_arm_irq_priority_set(irq, priority, flags); return irq; } + +#ifdef CONFIG_DYNAMIC_DIRECT_INTERRUPTS +static inline void z_arm_irq_dynamic_direct_isr_dispatch(void) +{ + u32_t irq = __get_IPSR() - 16; + + if (irq < IRQ_TABLE_SIZE) { + struct _isr_table_entry *isr_entry = &_sw_isr_table[irq]; + + isr_entry->isr(isr_entry->arg); + } +} + +ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_reschedule) +{ + z_arm_irq_dynamic_direct_isr_dispatch(); + + return 1; +} + +ISR_DIRECT_DECLARE(z_arm_irq_direct_dynamic_dispatch_no_reschedule) +{ + z_arm_irq_dynamic_direct_isr_dispatch(); + + return 0; +} + +#endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ + #endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/include/arch/arm/aarch32/irq.h b/include/arch/arm/aarch32/irq.h index dd4f78d897b..e59af4e3ec3 100644 --- a/include/arch/arm/aarch32/irq.h +++ b/include/arch/arm/aarch32/irq.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2019 Nordic Semiconductor ASA. * * SPDX-License-Identifier: Apache-2.0 */ @@ -136,6 +137,63 @@ static inline void arch_isr_direct_footer(int maybe_swap) } \ static inline int name##_body(void) +#if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) + +extern void z_arm_irq_direct_dynamic_dispatch_reschedule(void); +extern void z_arm_irq_direct_dynamic_dispatch_no_reschedule(void); + +/** + * @brief Macro to register an ISR Dispatcher (with or without re-scheduling + * request) for dynamic direct interrupts. + * + * This macro registers the ISR dispatcher function for dynamic direct + * interrupts for a particular IRQ line, allowing the use of dynamic + * direct ISRs in the kernel for that interrupt source. + * The dispatcher function is invoked when the hardware + * interrupt occurs and then triggers the (software) Interrupt Service Routine + * (ISR) that is registered dynamically (i.e. at run-time) into the software + * ISR table stored in SRAM. The ISR must be connected with + * irq_connect_dynamic() and enabled via irq_enable() before the dynamic direct + * interrupt can be serviced. This ISR dispatcher must be configured by the + * user to trigger thread re-secheduling upon return, using the @param resch + * parameter. + * + * These ISRs are designed for performance-critical interrupt handling and do + * not go through all of the common interrupt handling code. + * + * With respect to their declaration, dynamic 'direct' interrupts are regular + * Zephyr interrupts; their signature must match void isr(void* parameter), as, + * unlike regular direct interrupts, they are not placed directly into the + * ROM hardware vector table but instead they are installed in the software + * ISR table. + * + * The major differences with regular Zephyr interrupts are the following: + * - Similar to direct interrupts, the call into the OS to exit power + * management idle state is optional. Normal interrupts always do this + * before the ISR is run, but with dynamic direct ones when and if it runs + * is controlled by the placement of + * a ISR_DIRECT_PM() macro, or omitted entirely. + * - Similar to direct interrupts, scheduling decisions are optional. Unlike + * direct interrupts, the decisions must be made at build time. + * They are controlled by @param resch to this macro. + * + * @param irq_p IRQ line number. + * @param priority_p Interrupt priority. + * @param flags_p Architecture-specific IRQ configuration flags. + * @param resch Set flag to 'reschedule' to request thread + * re-scheduling upon ISR function. Set flag + * 'no_reschedule' to skip thread re-scheduling + * + * Note: the function is an ARM Cortex-M only API. + * + * @return Interrupt vector assigned to this interrupt. + */ +#define ARM_IRQ_DIRECT_DYNAMIC_CONNECT(irq_p, priority_p, flags_p, resch) \ + IRQ_DIRECT_CONNECT(irq_p, priority_p, \ + CONCAT(z_arm_irq_direct_dynamic_dispatch_, resch), flags_p) + +#endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ + /* Spurious interrupt handler. Throws an error if called */ extern void z_irq_spurious(void *unused);