From e444825ee37162ebdedbde233afea8ac9785cdff Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Thu, 25 Feb 2016 13:21:02 -0800 Subject: [PATCH] irq: formalize external zephyr interrupt API The app-facing interface for configuring interrupts was never formally defined, instead it was defined separately for each arch in their respective arch-specific header files. Occasionally these would go out of sync. Now there is a single irq.h header which defines this interface. To avoid runtime overhead, these map to _arch_* implementations of each that must be defined in headers pulled in by arch/cpu.h. Change-Id: I69afbeff31fd07f981b5b291f3c427296b00a4ef Signed-off-by: Andrew Boie --- arch/arc/core/irq_manage.c | 8 +- arch/arm/core/irq_manage.c | 7 +- arch/x86/core/intconnect.c | 3 +- include/arch/arc/arch.h | 3 +- include/arch/arc/v2/irq.h | 17 +-- include/arch/arm/cortex_m/asm_inline_gcc.h | 5 +- include/arch/arm/cortex_m/irq.h | 15 +-- include/arch/x86/arch.h | 14 ++- include/irq.h | 126 +++++++++++++++++++++ 9 files changed, 166 insertions(+), 32 deletions(-) create mode 100644 include/irq.h diff --git a/arch/arc/core/irq_manage.c b/arch/arc/core/irq_manage.c index 87618f23fa2..46f6de3f94d 100644 --- a/arch/arc/core/irq_manage.c +++ b/arch/arc/core/irq_manage.c @@ -36,7 +36,7 @@ #include #include #include - +#include /* * @brief Enable an interrupt line @@ -48,7 +48,7 @@ * @return N/A */ -void irq_enable(unsigned int irq) +void _arch_irq_enable(unsigned int irq) { int key = irq_lock(); @@ -65,7 +65,7 @@ void irq_enable(unsigned int irq) * @return N/A */ -void irq_disable(unsigned int irq) +void _arch_irq_disable(unsigned int irq) { int key = irq_lock(); @@ -158,7 +158,7 @@ void _irq_handler_set( * @return the interrupt line number */ -int irq_connect_dynamic( +int _arch_irq_connect_dynamic( unsigned int irq, unsigned int prio, void (*isr)(void *arg), diff --git a/arch/arm/core/irq_manage.c b/arch/arm/core/irq_manage.c index ea19751e744..2d34ba58d2a 100644 --- a/arch/arm/core/irq_manage.c +++ b/arch/arm/core/irq_manage.c @@ -30,6 +30,7 @@ #include #include #include +#include extern void __reserved(void); @@ -44,7 +45,7 @@ extern void __reserved(void); * * @return N/A */ -void irq_enable(unsigned int irq) +void _arch_irq_enable(unsigned int irq) { /* before enabling interrupts, ensure that interrupt is cleared */ _NvicIrqUnpend(irq); @@ -60,7 +61,7 @@ void irq_enable(unsigned int irq) * * @return N/A */ -void irq_disable(unsigned int irq) +void _arch_irq_disable(unsigned int irq) { _NvicIrqDisable(irq); } @@ -160,7 +161,7 @@ void _irq_handler_set(unsigned int irq, * * @return the interrupt line number */ -int irq_connect_dynamic(unsigned int irq, +int _arch_irq_connect_dynamic(unsigned int irq, unsigned int prio, void (*isr)(void *arg), void *arg, diff --git a/arch/x86/core/intconnect.c b/arch/x86/core/intconnect.c index 0707dad589b..25932663a96 100644 --- a/arch/x86/core/intconnect.c +++ b/arch/x86/core/intconnect.c @@ -41,6 +41,7 @@ #include #include #include +#include extern void _SpuriousIntHandler(void *); extern void _SpuriousIntNoErrCodeHandler(void *); @@ -262,7 +263,7 @@ extern void *_DynIntStubsBegin; * vectors remaining in the specified level. */ -int irq_connect_dynamic(unsigned int irq, unsigned int priority, +int _arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, void (*routine)(void *parameter), void *parameter, uint32_t flags) { diff --git a/include/arch/arc/arch.h b/include/arch/arc/arch.h index 017cb73c46a..b6fd1bc625d 100644 --- a/include/arch/arc/arch.h +++ b/include/arch/arc/arch.h @@ -55,6 +55,7 @@ extern "C" { #endif #ifndef _ASMLANGUAGE +#include /* internal routine documented in C file, needed by IRQ_CONNECT() macro */ extern void _irq_priority_set(unsigned int irq, unsigned int prio); @@ -88,7 +89,7 @@ extern void _irq_priority_set(unsigned int irq, unsigned int prio); * * @return The vector assigned to this interrupt */ -#define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ +#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ ({ \ enum { IRQ = irq_p }; \ static struct _IsrTableEntry _CONCAT(_isr_irq, irq_p) \ diff --git a/include/arch/arc/v2/irq.h b/include/arch/arc/v2/irq.h index 3429f8cbf1e..ae31f7abfa2 100644 --- a/include/arch/arc/v2/irq.h +++ b/include/arch/arc/v2/irq.h @@ -26,6 +26,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -33,18 +34,18 @@ extern "C" { #ifdef _ASMLANGUAGE GTEXT(_irq_exit); -GTEXT(irq_connect) -GTEXT(irq_enable) -GTEXT(irq_disable) +GTEXT(_arch_irq_connect) +GTEXT(_arch_irq_enable) +GTEXT(_arch_irq_disable) #else -extern int irq_connect_dynamic(unsigned int irq, +extern int _arch_irq_connect_dynamic(unsigned int irq, unsigned int prio, void (*isr)(void *arg), void *arg, uint32_t flags); -extern void irq_enable(unsigned int irq); -extern void irq_disable(unsigned int irq); +extern void _arch_irq_enable(unsigned int irq); +extern void _arch_irq_disable(unsigned int irq); extern void _irq_exit(void); @@ -80,7 +81,7 @@ extern void _irq_exit(void); * "interrupt disable state" prior to the call. */ -static ALWAYS_INLINE unsigned int irq_lock(void) +static ALWAYS_INLINE unsigned int _arch_irq_lock(void) { unsigned int key; @@ -101,7 +102,7 @@ static ALWAYS_INLINE unsigned int irq_lock(void) * @return N/A */ -static ALWAYS_INLINE void irq_unlock(unsigned int key) +static ALWAYS_INLINE void _arch_irq_unlock(unsigned int key) { __asm__ volatile("seti %0" : : "ir"(key)); } diff --git a/include/arch/arm/cortex_m/asm_inline_gcc.h b/include/arch/arm/cortex_m/asm_inline_gcc.h index 04222575142..85a4a1c9101 100644 --- a/include/arch/arm/cortex_m/asm_inline_gcc.h +++ b/include/arch/arm/cortex_m/asm_inline_gcc.h @@ -41,6 +41,7 @@ extern "C" { #else /* !_ASMLANGUAGE */ #include #include +#include /** * @@ -136,7 +137,7 @@ static ALWAYS_INLINE unsigned int find_lsb_set(uint32_t op) * the two highest priorities from interrupting the CPU. */ -static ALWAYS_INLINE unsigned int irq_lock(void) +static ALWAYS_INLINE unsigned int _arch_irq_lock(void) { unsigned int key; @@ -167,7 +168,7 @@ static ALWAYS_INLINE unsigned int irq_lock(void) * @return N/A */ -static ALWAYS_INLINE void irq_unlock(unsigned int key) +static ALWAYS_INLINE void _arch_irq_unlock(unsigned int key) { __asm__ volatile("msr BASEPRI, %0;\n\t" : : "r"(key)); } diff --git a/include/arch/arm/cortex_m/irq.h b/include/arch/arm/cortex_m/irq.h index 9ac9cee72ee..dcbb7341fd2 100644 --- a/include/arch/arm/cortex_m/irq.h +++ b/include/arch/arm/cortex_m/irq.h @@ -24,6 +24,7 @@ #ifndef _ARCH_ARM_CORTEXM_IRQ_H_ #define _ARCH_ARM_CORTEXM_IRQ_H_ +#include #include #include @@ -33,18 +34,18 @@ extern "C" { #ifdef _ASMLANGUAGE GTEXT(_IntExit); -GTEXT(irq_connect_dynamic) -GTEXT(irq_enable) -GTEXT(irq_disable) +GTEXT(_arch_irq_connect_dynamic) +GTEXT(_arch_irq_enable) +GTEXT(_arch_irq_disable) #else -extern int irq_connect_dynamic(unsigned int irq, +extern int _arch_irq_connect_dynamic(unsigned int irq, unsigned int prio, void (*isr)(void *arg), void *arg, uint32_t flags); -extern void irq_enable(unsigned int irq); -extern void irq_disable(unsigned int irq); +extern void _arch_irq_enable(unsigned int irq); +extern void _arch_irq_disable(unsigned int irq); extern void _IntExit(void); @@ -101,7 +102,7 @@ extern void _irq_priority_set(unsigned int irq, unsigned int prio, * * @return The vector assigned to this interrupt */ -#define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ +#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ ({ \ enum { IRQ = irq_p }; \ static struct _IsrTableEntry _CONCAT(_isr_irq, irq_p) \ diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h index 7cb0fd94df4..19e5773640a 100644 --- a/include/arch/x86/arch.h +++ b/include/arch/x86/arch.h @@ -24,6 +24,8 @@ #ifndef _ARCH_IFACE_H #define _ARCH_IFACE_H +#include + #ifndef _ASMLANGUAGE #include #include @@ -250,7 +252,7 @@ typedef struct s_isrList { * * @return The vector assigned to this interrupt */ -#define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ +#define _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ ({ \ __asm__ __volatile__( \ "jmp 2f\n\t" \ @@ -404,7 +406,7 @@ void _int_latency_stop(void); * */ -static inline __attribute__((always_inline)) unsigned int irq_lock(void) +static inline __attribute__((always_inline)) unsigned int _arch_irq_lock(void) { unsigned int key = _do_irq_lock(); @@ -428,7 +430,7 @@ static inline __attribute__((always_inline)) unsigned int irq_lock(void) * */ -static inline __attribute__((always_inline)) void irq_unlock(unsigned int key) +static inline __attribute__((always_inline)) void _arch_irq_unlock(unsigned int key) { if (!(key & 0x200)) { return; @@ -460,7 +462,7 @@ typedef void (*NANO_EOI_GET_FUNC) (void *); #endif /* CONFIG_SSE */ #endif /* CONFIG_FP_SHARING */ -extern int irq_connect_dynamic(unsigned int irq, +extern int _arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, void (*routine)(void *parameter), void *parameter, @@ -470,12 +472,12 @@ extern int irq_connect_dynamic(unsigned int irq, * @brief Enable a specific IRQ * @param irq IRQ */ -extern void irq_enable(unsigned int irq); +extern void _arch_irq_enable(unsigned int irq); /** * @brief Disable a specific IRQ * @param irq IRQ */ -extern void irq_disable(unsigned int irq); +extern void _arch_irq_disable(unsigned int irq); #ifdef CONFIG_FP_SHARING /** diff --git a/include/irq.h b/include/irq.h new file mode 100644 index 00000000000..62e00855313 --- /dev/null +++ b/include/irq.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015 Intel corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * @brief Public interface for configuring interrupts + */ +#ifndef _IRQ_H_ +#define _IRQ_H_ + +/* Pull in the arch-specific implementations */ +#include + +/** + * Configure a static interrupt. + * + * All arguments must be computable by the compiler at build time; if this + * can't be done use irq_connect_dynamic() instead. + * + * @param irq_p IRQ line number + * @param priority_p Interrupt priority + * @param isr_p Interrupt service routine + * @param isr_param_p ISR parameter + * @param flags_p Arch-specific IRQ configuration flags + * + * @return The vector assigned to this interrupt + */ +#define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ + _ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) + +/** + * Configure a dynamic interrupt. + * + * @param irq_p IRQ line number + * @param priority_p Interrupt priority + * @param isr_p Interrupt service routine + * @param isr_param_p ISR parameter + * @param flags_p Arch-specific IRQ configuration flags + * + * @return The vector assigned to this interrupt + */ +#define irq_connect_dynamic(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ + _arch_irq_connect_dynamic(irq_p, priority_p, isr_p, isr_param_p, \ + flags_p) + + +/** + * @brief Disable all interrupts on the CPU (inline) + * + * This routine disables interrupts. It can be called from either interrupt, + * task or fiber level. This routine returns an architecture-dependent + * lock-out key representing the "interrupt disable state" prior to the call; + * this key can be passed to irq_unlock() to re-enable interrupts. + * + * The lock-out key should only be used as the argument to the irq_unlock() + * API. It should never be used to manually re-enable interrupts or to inspect + * or manipulate the contents of the source register. + * + * This function can be called recursively: it will return a key to return the + * state of interrupt locking to the previous level. + * + * WARNINGS + * Invoking a kernel routine with interrupts locked may result in + * interrupts being re-enabled for an unspecified period of time. If the + * called routine blocks, interrupts will be re-enabled while another + * thread executes, or while the system is idle. + * + * The "interrupt disable state" is an attribute of a thread. Thus, if a + * fiber or task disables interrupts and subsequently invokes a kernel + * routine that causes the calling thread to block, the interrupt + * disable state will be restored when the thread is later rescheduled + * for execution. + * + * @return An architecture-dependent unsigned int lock-out key representing the + * "interrupt disable state" prior to the call. + * + */ +#define irq_lock() _arch_irq_lock() + +/** + * + * @brief Enable all interrupts on the CPU (inline) + * + * This routine re-enables interrupts on the CPU. The @a key parameter + * is an architecture-dependent lock-out key that is returned by a previous + * invocation of irq_lock(). + * + * This routine can be called from either interrupt, task or fiber level + * + * @param key architecture-dependent lock-out key + * + * @return N/A + */ +#define irq_unlock(key) _arch_irq_unlock(key) + +/** + * @brief Enable a specific IRQ + * + * @param irq IRQ line + * @return N/A + */ +#define irq_enable(irq) _arch_irq_enable(irq) + +/** + * @brief Disable a specific IRQ + * + * @param irq IRQ line + * @return N/A + */ +#define irq_disable(irq) _arch_irq_disable(irq) + + +#endif /* _IRQ_H_ */