doc: kernel: Clarify relationship between direct and ZLI interrupts
The documentation did not state clearly that any zero-latency IRQ must also be declared as a direct ISR. This is critical because failure to do so may cause race conditions between the ZLI and regular ISRs when executing the preable/postamble code in regular interrupts. Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
c3b3aab77e
commit
3b8e1fa8df
3 changed files with 44 additions and 10 deletions
|
@ -162,6 +162,8 @@ The IRQ must be subsequently **enabled** to permit the ISR to execute.
|
|||
Disabling an IRQ prevents *all* threads in the system from being preempted
|
||||
by the associated ISR, not just the thread that disabled the IRQ.
|
||||
|
||||
.. _zlis:
|
||||
|
||||
Zero Latency Interrupts
|
||||
-----------------------
|
||||
|
||||
|
@ -173,10 +175,14 @@ The kernel addresses such use-cases by allowing interrupts with critical
|
|||
latency constraints to execute at a priority level that cannot be blocked
|
||||
by interrupt locking. These interrupts are defined as
|
||||
*zero-latency interrupts*. The support for zero-latency interrupts requires
|
||||
:kconfig:option:`CONFIG_ZERO_LATENCY_IRQS` to be enabled. In addition to that, the
|
||||
flag :c:macro:`IRQ_ZERO_LATENCY` must be passed to :c:macro:`IRQ_CONNECT` or
|
||||
:c:macro:`IRQ_DIRECT_CONNECT` macros to configure the particular interrupt
|
||||
with zero latency.
|
||||
:kconfig:option:`CONFIG_ZERO_LATENCY_IRQS` to be enabled. Any interrupts
|
||||
configured as zero-latency must also be declared as :ref:`direct ISRs
|
||||
<direct_isrs>` (and must not use the :c:macro:`ISR_DIRECT_PM` in them), since
|
||||
regular ISRs interact with the kernel. In addition to that, the flag
|
||||
:c:macro:`IRQ_ZERO_LATENCY` must be passed to the :c:macro:`IRQ_DIRECT_CONNECT`
|
||||
macro to configure the particular interrupt with
|
||||
zero latency. Declaring a zero-latency interrupt ISR to be both direct and
|
||||
dynamic is possible on some architectures, see :ref:`direct_isrs`.
|
||||
|
||||
Zero-latency interrupts are expected to be used to manage hardware events
|
||||
directly, and not to interoperate with the kernel code at all. They should
|
||||
|
@ -306,6 +312,8 @@ Dynamic interrupts require the :kconfig:option:`CONFIG_DYNAMIC_INTERRUPTS` optio
|
|||
be enabled. Removing or re-configuring a dynamic interrupt is currently
|
||||
unsupported.
|
||||
|
||||
.. _direct_isrs:
|
||||
|
||||
Defining a 'direct' ISR
|
||||
=======================
|
||||
|
||||
|
@ -322,7 +330,10 @@ for some low-latency use-cases. Specifically:
|
|||
need to switch to the interrupt stack in code
|
||||
|
||||
* After the interrupt is serviced, the OS then performs some logic to
|
||||
potentially make a scheduling decision.
|
||||
potentially make a scheduling decision
|
||||
|
||||
* :ref:`zlis` must always be declared as direct ISRs, since regular
|
||||
ISRs interact with the kernel
|
||||
|
||||
Zephyr supports so-called 'direct' interrupts, which are installed via
|
||||
:c:macro:`IRQ_DIRECT_CONNECT` and whose handlers are declared using
|
||||
|
@ -341,8 +352,12 @@ The following code demonstrates a direct ISR:
|
|||
ISR_DIRECT_DECLARE(my_isr)
|
||||
{
|
||||
do_stuff();
|
||||
ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency */
|
||||
return 1; /* We should check if scheduling decision should be made */
|
||||
/* PM done after servicing interrupt for best latency. This cannot be
|
||||
used for zero-latency IRQs because it accesses kernel data. */
|
||||
ISR_DIRECT_PM();
|
||||
/* Ask the kernel to check if scheduling decision should be made. If the
|
||||
ISR is for a zero-latency IRQ then the return value must always be 0. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void my_isr_installer(void)
|
||||
|
@ -354,9 +369,10 @@ The following code demonstrates a direct ISR:
|
|||
}
|
||||
|
||||
Installation of dynamic direct interrupts is supported on an
|
||||
architecture-specific basis. (The feature is currently implemented in
|
||||
ARM Cortex-M architecture variant. Dynamic direct interrupts feature is
|
||||
exposed to the user via an ARM-only API.)
|
||||
architecture-specific basis. The feature is currently implemented in the Arm
|
||||
Cortex-M architecture variant via the macro
|
||||
:c:macro:`ARM_IRQ_DIRECT_DYNAMIC_CONNECT`, which can be used to declare a direct
|
||||
and dynamic interrupt.
|
||||
|
||||
Sharing an interrupt line
|
||||
=========================
|
||||
|
|
|
@ -231,12 +231,18 @@ extern void z_arm_irq_direct_dynamic_dispatch_no_reschedule(void);
|
|||
* direct interrupts, the decisions must be made at build time.
|
||||
* They are controlled by @param resch to this macro.
|
||||
*
|
||||
* @warning
|
||||
* Just like with regular direct ISRs, any ISRs that serve IRQs configured with
|
||||
* the IRQ_ZERO_LATENCY flag must not use the ISR_DIRECT_PM() macro and must
|
||||
* return 0 (i.e. resch must be no_reschedule).
|
||||
*
|
||||
* @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
|
||||
* Must be 'no_reschedule' for zero-latency interrupts
|
||||
*
|
||||
* Note: the function is an ARM Cortex-M only API.
|
||||
*
|
||||
|
|
|
@ -128,6 +128,10 @@ irq_disconnect_dynamic(unsigned int irq, unsigned int priority,
|
|||
* Although this routine is invoked at run-time, all of its arguments must be
|
||||
* computable by the compiler at build time.
|
||||
*
|
||||
* @note
|
||||
* All IRQs configured with the IRQ_ZERO_LATENCY flag must be declared as
|
||||
* direct.
|
||||
*
|
||||
* @param irq_p IRQ line number.
|
||||
* @param priority_p Interrupt priority.
|
||||
* @param isr_p Address of interrupt service routine.
|
||||
|
@ -170,6 +174,10 @@ irq_disconnect_dynamic(unsigned int irq, unsigned int priority,
|
|||
* 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!
|
||||
*
|
||||
* @warning
|
||||
* This macro must not be used at all with IRQs configured with the
|
||||
* IRQ_ZERO_LATENCY flag.
|
||||
*/
|
||||
#define ISR_DIRECT_PM() ARCH_ISR_DIRECT_PM()
|
||||
|
||||
|
@ -186,6 +194,10 @@ irq_disconnect_dynamic(unsigned int irq, unsigned int priority,
|
|||
* registers by the ISR, this will always generate code for the 'fast'
|
||||
* interrupt type.
|
||||
*
|
||||
* @warning
|
||||
* Any ISRs that serve IRQs configured with the IRQ_ZERO_LATENCY flag must
|
||||
* always return 0 in this macro.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ISR_DIRECT_DECLARE(my_isr)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue