summaryrefslogtreecommitdiff
path: root/include/irq.h
diff options
context:
space:
mode:
authorAndrew Boie <andrew.p.boie@intel.com>2017-01-18 13:06:59 -0800
committerAndrew Boie <andrew.p.boie@intel.com>2017-02-02 17:46:33 +0000
commit4fc96066b025f9e4ffcd1b244d460c7338d3099b (patch)
treee0000cd7f6733878ee25a55f7e2f0721c11e085f /include/irq.h
parentd4dddf7f522b5773215f4503d23ff5e66a31c082 (diff)
irq: introduce 'direct' interrupt API definition
These interrupts are for ISRs that need the lowest possible latency. They do not take parameters and are installed directly in the interrupt vector table. Issue: ZEP-1038 Change-Id: I7583e9191dd32d9253ad933181d2103a6e191dea Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
Diffstat (limited to 'include/irq.h')
-rw-r--r--include/irq.h110
1 files changed, 110 insertions, 0 deletions
diff --git a/include/irq.h b/include/irq.h
index b1a948e7d..661babf06 100644
--- a/include/irq.h
+++ b/include/irq.h
@@ -50,6 +50,116 @@ extern "C" {
_ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p)
/**
+ * @brief Initialize a 'direct' interrupt handler.
+ *
+ * This routine initializes an interrupt handler for an IRQ. The IRQ must be
+ * subsequently enabled via irq_enable() before the interrupt handler begins
+ * servicing interrupts.
+ *
+ * These ISRs are designed for performance-critical interrupt handling and do
+ * not go through common interrupt handling code. They must be implemented in
+ * such a way that it is safe to put them directly in the vector table. For
+ * ISRs written in C, The ISR_DIRECT_DECLARE() macro will do this
+ * automatically. For ISRs wriiten in assembly it is entirely up to the
+ * developer to ensure that the right steps are taken.
+ *
+ * This type of interrupt currently has a few limitations compared to normal
+ * Zephyr interrupts:
+ * - No parameters are passed to the ISR.
+ * - No stack switch is done, the ISR will run on the interrupted context's
+ * stack, unless the architecture automatically does the stack switch in HW.
+ * - Interrupt locking state is unchanged from how the HW sets it when the ISR
+ * runs. On arches that enter ISRs with interrupts locked, they will remain
+ * locked.
+ * - Scheduling decisions are now optional, controlled by the return value of
+ * ISRs implemented with the ISR_DIRECT_DECLARE() macro
+ * - The call into the OS to exit power management idle state is now optional.
+ * Normal interrupts always do this before the ISR is run, but when it runs
+ * is now controlled by the placement of a ISR_DIRECT_PM() macro, or omitted
+ * entirely.
+ *
+ * @warning
+ * Although this routine is invoked at run-time, all of its arguments must be
+ * computable by the compiler at build time.
+ *
+ * @param irq_p IRQ line number.
+ * @param priority_p Interrupt priority.
+ * @param isr_p Address of interrupt service routine.
+ * @param flags_p Architecture-specific IRQ configuration flags.
+ *
+ * @return Interrupt vector assigned to this interrupt.
+ */
+#define IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \
+ _ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p)
+
+/**
+ * @brief Common tasks before executing the body of an ISR
+ *
+ * This macro must be at the beginning of all direct interrupts and performs
+ * minimal architecture-specific tasks before the ISR itself can run. It takes
+ * no arguments and has no return value.
+ */
+#define ISR_DIRECT_HEADER() _ARCH_ISR_DIRECT_HEADER()
+
+/**
+ * @brief Common tasks before exiting the body of an ISR
+ *
+ * This macro must be at the end of all direct interrupts and performs
+ * minimal architecture-specific tasks like EOI. It has no return value.
+ *
+ * In a normal interrupt, a check is done at end of interrupt to invoke
+ * _Swap() logic if the current thread is preemptible and there is another
+ * thread ready to run in the kernel's ready queue cache. This is now optional
+ * and controlled by the check_reschedule argument. If unsure, set to nonzero.
+ * On systems that do stack switching and nested interrupt tracking in software,
+ * _Swap() should only be called if this was a non-nested interrupt.
+ *
+ * @param check_reschedule If nonzero, additionally invoke scheduling logic
+ */
+#define ISR_DIRECT_FOOTER(check_reschedule) \
+ _ARCH_ISR_DIRECT_FOOTER(check_reschedule)
+
+/**
+ * @brief Perform power management idle exit logic
+ *
+ * This macro may optionally be invoked somewhere in between IRQ_DIRECT_HEADER()
+ * and IRQ_DIRECT_FOOTER() invocations. It performs tasks necessary to
+ * exit power management idle state. It takes no parameters and returns no
+ * arguments. It may be omitted, but be careful!
+ */
+#define ISR_DIRECT_PM() _ARCH_ISR_DIRECT_PM()
+
+/**
+ * @brief Helper macro to declare a direct interrupt service routine.
+ *
+ * This will declare the function in a proper way and automatically include
+ * the ISR_DIRECT_FOOTER() and ISR_DIRECT_HEADER() macros. The function should
+ * return nonzero status if a scheduling decision should potentially be made.
+ * See ISR_DIRECT_FOOTER() for more details on the scheduling decision.
+ *
+ * For architectures that support 'regular' and 'fast' interrupt types, where
+ * these interrupt types require different assembly language handling of
+ * registers by the ISR, this will always generate code for the 'fast'
+ * interrupt type.
+ *
+ * Example usage:
+ *
+ * ISR_DIRECT_DECLARE(my_isr)
+ * {
+ * bool done = do_stuff();
+ * ISR_DIRECT_PM(); <-- done after do_stuff() due to latency concerns
+ * if (!done) {
+ * return 0; <-- Don't bother checking if we have to _Swap()
+ * }
+ * k_sem_give(some_sem);
+ * return 1;
+ * }
+ *
+ * @param name symbol name of the ISR
+ */
+#define ISR_DIRECT_DECLARE(name) _ARCH_ISR_DIRECT_DECLARE(name)
+
+/**
* @brief Lock interrupts.
*
* This routine disables all interrupts on the CPU. It returns an unsigned