123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- /*
- * Copyright (c) 2013-2014 Wind River Systems, Inc.
- * Copyright (c) 2019 Nordic Semiconductor ASA.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file
- * @brief ARM AArch32 public interrupt handling
- *
- * ARM AArch32-specific kernel interrupt handling interface. Included by
- * arm/arch.h.
- */
- #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_IRQ_H_
- #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_IRQ_H_
- #include <irq.h>
- #include <sw_isr_table.h>
- #include <stdbool.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- #ifdef _ASMLANGUAGE
- GTEXT(z_arm_int_exit);
- GTEXT(arch_irq_enable)
- GTEXT(arch_irq_disable)
- GTEXT(arch_irq_is_enabled)
- #if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
- GTEXT(z_soc_irq_get_active)
- GTEXT(z_soc_irq_eoi)
- #endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
- #else
- #if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
- extern void arch_irq_enable(unsigned int irq);
- extern void arch_irq_disable(unsigned int irq);
- extern int arch_irq_is_enabled(unsigned int irq);
- /* internal routine documented in C file, needed by IRQ_CONNECT() macro */
- extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio,
- uint32_t flags);
- #else
- /*
- * When a custom interrupt controller is specified, map the architecture
- * interrupt control functions to the SoC layer interrupt control functions.
- */
- void z_soc_irq_init(void);
- void z_soc_irq_enable(unsigned int irq);
- void z_soc_irq_disable(unsigned int irq);
- int z_soc_irq_is_enabled(unsigned int irq);
- void z_soc_irq_priority_set(
- unsigned int irq, unsigned int prio, unsigned int flags);
- unsigned int z_soc_irq_get_active(void);
- void z_soc_irq_eoi(unsigned int irq);
- #define arch_irq_enable(irq) z_soc_irq_enable(irq)
- #define arch_irq_disable(irq) z_soc_irq_disable(irq)
- #define arch_irq_is_enabled(irq) z_soc_irq_is_enabled(irq)
- #define z_arm_irq_priority_set(irq, prio, flags) \
- z_soc_irq_priority_set(irq, prio, flags)
- #endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */
- extern void z_arm_int_exit(void);
- extern void z_arm_interrupt_init(void);
- /* macros convert value of it's argument to a string */
- #define DO_TOSTR(s) #s
- #define TOSTR(s) DO_TOSTR(s)
- /* concatenate the values of the arguments into one */
- #define DO_CONCAT(x, y) x ## y
- #define CONCAT(x, y) DO_CONCAT(x, y)
- /* Flags for use with IRQ_CONNECT() */
- /**
- * Set this interrupt up as a zero-latency IRQ. It has a fixed hardware
- * priority level (discarding what was supplied in the interrupt's priority
- * argument), and will run even if irq_lock() is active. Be careful!
- */
- #define IRQ_ZERO_LATENCY BIT(0)
- #ifdef CONFIG_CPU_CORTEX_M
- #define _CHECK_PRIO(priority_p, flags_p) \
- BUILD_ASSERT((flags_p & IRQ_ZERO_LATENCY) || \
- priority_p <= IRQ_PRIO_LOWEST, \
- "Invalid interrupt priority. Values must not exceed IRQ_PRIO_LOWEST");
- #else
- #define _CHECK_PRIO(priority_p, flags_p)
- #endif
- /* All arguments must be computable by the compiler at build time.
- *
- * Z_ISR_DECLARE will populate the .intList section with the interrupt's
- * parameters, which will then be used by gen_irq_tables.py to create
- * the vector table and the software ISR table. This is all done at
- * build-time.
- *
- * We additionally set the priority in the interrupt controller at
- * runtime.
- */
- #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
- { \
- BUILD_ASSERT(IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) || !(flags_p & IRQ_ZERO_LATENCY), \
- "ZLI interrupt registered but feature is disabled"); \
- _CHECK_PRIO(priority_p, flags_p) \
- Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
- z_arm_irq_priority_set(irq_p, priority_p, flags_p); \
- }
- #define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \
- { \
- BUILD_ASSERT(IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) || !(flags_p & IRQ_ZERO_LATENCY), \
- "ZLI interrupt registered but feature is disabled"); \
- _CHECK_PRIO(priority_p, flags_p) \
- Z_ISR_DECLARE(irq_p, ISR_FLAG_DIRECT, isr_p, NULL); \
- z_arm_irq_priority_set(irq_p, priority_p, flags_p); \
- }
- #ifdef CONFIG_PM
- extern void _arch_isr_direct_pm(void);
- #define ARCH_ISR_DIRECT_PM() _arch_isr_direct_pm()
- #else
- #define ARCH_ISR_DIRECT_PM() do { } while (false)
- #endif
- #define ARCH_ISR_DIRECT_HEADER() arch_isr_direct_header()
- #define ARCH_ISR_DIRECT_FOOTER(swap) arch_isr_direct_footer(swap)
- /* arch/arm/core/aarch32/exc_exit.S */
- extern void z_arm_int_exit(void);
- #ifdef CONFIG_TRACING_ISR
- extern void sys_trace_isr_enter(void);
- extern void sys_trace_isr_exit(void);
- #endif
- static inline void arch_isr_direct_header(void)
- {
- #ifdef CONFIG_TRACING_ISR
- sys_trace_isr_enter();
- #endif
- }
- static inline void arch_isr_direct_footer(int maybe_swap)
- {
- #ifdef CONFIG_TRACING_ISR
- sys_trace_isr_exit();
- #endif
- if (maybe_swap != 0) {
- z_arm_int_exit();
- }
- }
- #define ARCH_ISR_DIRECT_DECLARE(name) \
- static inline int name##_body(void); \
- __attribute__ ((interrupt ("IRQ"))) void name(void) \
- { \
- int check_reschedule; \
- ISR_DIRECT_HEADER(); \
- check_reschedule = name##_body(); \
- ISR_DIRECT_FOOTER(check_reschedule); \
- } \
- 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(const void *unused);
- #ifdef CONFIG_GEN_SW_ISR_TABLE
- /* Architecture-specific common entry point for interrupts from the vector
- * table. Most likely implemented in assembly. Looks up the correct handler
- * and parameter from the _sw_isr_table and executes it.
- */
- extern void _isr_wrapper(void);
- #endif
- #if defined(CONFIG_ARM_SECURE_FIRMWARE)
- /* Architecture-specific definition for the target security
- * state of an NVIC IRQ line.
- */
- typedef enum {
- IRQ_TARGET_STATE_SECURE = 0,
- IRQ_TARGET_STATE_NON_SECURE
- } irq_target_state_t;
- #endif /* CONFIG_ARM_SECURE_FIRMWARE */
- #endif /* _ASMLANGUAGE */
- #ifdef __cplusplus
- }
- #endif
- #endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_IRQ_H_ */
|