Documentation: Improve "High Performance, Zero Latency Interrupts"
* Documentation/guides/zerolatencyinterrupts.rst: Add paragraph that defines jitter. Fix a few minor typos. Fix incorrect reStructuredText formatting for bulletpoints (they were being rendered like 2nd level bulletpoints). * Documentation/guides/index.rst: Add zerolatencyinterrupts.rst to the TOC, which I forgot to do in PR # 9302.
This commit is contained in:
parent
ab02bdc626
commit
33bf661413
@ -16,3 +16,4 @@ Guides
|
|||||||
pysimcoder.rst
|
pysimcoder.rst
|
||||||
customboards.rst
|
customboards.rst
|
||||||
customapps.rst
|
customapps.rst
|
||||||
|
zerolatencyinterrupts.rst
|
||||||
|
@ -8,19 +8,27 @@ Generic Interrupt Handling
|
|||||||
NuttX includes a generic interrupt handling subsystem that makes it
|
NuttX includes a generic interrupt handling subsystem that makes it
|
||||||
convenient to deal with interrupts using only IRQ numbers. In order to
|
convenient to deal with interrupts using only IRQ numbers. In order to
|
||||||
integrate with this generic interrupt handling system, the platform
|
integrate with this generic interrupt handling system, the platform
|
||||||
specific code is expected to collect all thread state into an container,
|
specific code is expected to collect all thread state into a container,
|
||||||
``struct xcptcontext``. This container represents the full state of the
|
``struct xcptcontext``. This container represents the full state of the
|
||||||
thread and can be saved, restored, and exchanged as a *unit of thread*.
|
thread and can be saved, restored, and exchanged as a *unit of thread*.
|
||||||
|
|
||||||
While this state saving has many useful benefits, it does require
|
While this state saving has many useful benefits, it does require
|
||||||
processing time. It was reported to me that this state saving required
|
processing time. It was reported to me that this state saving required
|
||||||
about two microseconds on an STM32F4Discovery board. That added
|
about two microseconds on an STM32F4Discovery board. That added
|
||||||
interrupt latency might be an issue in some circumstance.
|
interrupt latency might be an issue in some circumstances.
|
||||||
|
|
||||||
**Terminology:** The concepts discussed in this Wiki are not unique to
|
In addition, critical sections that are required in various places
|
||||||
NuttX. Other RTOS have similar concepts but will use different
|
throughout the RTOS can pause interrupt handling momentarily. This
|
||||||
|
increases the latency for those interrupts which become pending during a
|
||||||
|
critical section. As this is likely to occur for some instances of an
|
||||||
|
interrupt and not others, the interrupt latency varies from time to time
|
||||||
|
(experiences *jitter*). Like the added latency discussed above, that
|
||||||
|
jitter might be an issue in some circumstances.
|
||||||
|
|
||||||
|
**Terminology:** The concepts discussed in this guide are not unique to
|
||||||
|
NuttX. Other RTOSes have similar concepts but will use different
|
||||||
terminology. The `Nucleus <https://www.embedded.com/design/operating-systems/4461604/Interrupts-in-the-Nucleus-SE-RTOS>`_
|
terminology. The `Nucleus <https://www.embedded.com/design/operating-systems/4461604/Interrupts-in-the-Nucleus-SE-RTOS>`_
|
||||||
RTOS, for example use the terms *Native* and *Managed* interrupts.
|
RTOS, for example, uses the terms *Native* and *Managed* interrupts.
|
||||||
|
|
||||||
Bypassing the Generic Interrupt Handling
|
Bypassing the Generic Interrupt Handling
|
||||||
========================================
|
========================================
|
||||||
@ -53,24 +61,23 @@ when the ``CONFIG_ARCH_RAMVECTORS`` option is enabled.
|
|||||||
|
|
||||||
So what is the downside? There are two:
|
So what is the downside? There are two:
|
||||||
|
|
||||||
- Your custom interrupt handler will not have collected its state
|
* Your custom interrupt handler will not have collected its state into
|
||||||
into the ``struct xcptcontext`` container. Therefore, it cannot
|
the ``struct xcptcontext`` container. Therefore, it cannot communicate
|
||||||
communicate with operating system. Your custom interrupt handler
|
with operating system. Your custom interrupt handler has been taken
|
||||||
has been taken "out of the game" and can no longer work with the
|
"out of the game" and can no longer work with the system.
|
||||||
system.
|
|
||||||
|
|
||||||
- If your custom interrupt is truly going to be *high performance*
|
* If your custom interrupt is truly going to be *high performance* then
|
||||||
then you will also have to support nested interrupts! The custom
|
you will also have to support nested interrupts! The custom interrupt
|
||||||
interrupt must have a high priority and must be able interrupt the
|
must have a high priority and must be able interrupt the generic
|
||||||
generic interrupt handling logic. Otherwise, it will be
|
interrupt handling logic. Otherwise, it will be occasionally delayed
|
||||||
occasionally delayed when there is a collision between your custom
|
when there is a collision between your custom interrupt and other,
|
||||||
interrupt and other, lower priority interrupts.
|
lower priority interrupts.
|
||||||
|
|
||||||
Getting Back into the Game
|
Getting Back into the Game
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
As mentioned, the custom interrupt handler can not use most of the
|
As mentioned, the custom interrupt handler cannot use most of the
|
||||||
service of the OS since it has not created a ``struct xcptcontext``
|
services of the OS since it has not created a ``struct xcptcontext``
|
||||||
container. So it needs a mechanism to "get back into the game" when it
|
container. So it needs a mechanism to "get back into the game" when it
|
||||||
needs to interact with the operating system to, for example, post a
|
needs to interact with the operating system to, for example, post a
|
||||||
semaphore, signal a thread, or send a message.
|
semaphore, signal a thread, or send a message.
|
||||||
@ -78,16 +85,15 @@ semaphore, signal a thread, or send a message.
|
|||||||
The ARM Cortex-M family supports a special way to do this using the
|
The ARM Cortex-M family supports a special way to do this using the
|
||||||
*PendSV* interrupt:
|
*PendSV* interrupt:
|
||||||
|
|
||||||
- The custom logic would connect with the *PendSV* interrupt using
|
* The custom logic would connect with the *PendSV* interrupt using the
|
||||||
the standard ``irq_attach()`` interface.
|
standard ``irq_attach()`` interface.
|
||||||
|
|
||||||
- In the custom interrupt handler, it would schedule the *PendSV*
|
* In the custom interrupt handler, it would schedule the *PendSV*
|
||||||
interrupt when it needs to communicate with the OS.
|
interrupt when it needs to communicate with the OS.
|
||||||
|
|
||||||
- The *PendSV* interrupt is dispatched through generic interrupt
|
* The *PendSV* interrupt is dispatched through the generic interrupt
|
||||||
system so when the attached *PendSV* interrupt is handled, it
|
system so when the attached *PendSV* interrupt is handled, it will be
|
||||||
will be in a context where it can perform any necessary OS
|
in a context where it can perform any necessary OS interactions.
|
||||||
interactions.
|
|
||||||
|
|
||||||
With the ARMv7_M architecture, the *PendSV* interrupt can be generated
|
With the ARMv7_M architecture, the *PendSV* interrupt can be generated
|
||||||
with:
|
with:
|
||||||
@ -118,27 +124,26 @@ interrupt interrupt handler.
|
|||||||
Modifications may be required to the generic interrupt handling logic
|
Modifications may be required to the generic interrupt handling logic
|
||||||
to accomplish. A few points need to be made here:
|
to accomplish. A few points need to be made here:
|
||||||
|
|
||||||
- The MCU should support interrupt prioritization so that the custom
|
* The MCU should support interrupt prioritization so that the custom
|
||||||
interrupt can be scheduled with a higher priority.
|
interrupt can be scheduled with a higher priority.
|
||||||
|
|
||||||
- The generic interrupt handlers currently disable interrupts during
|
* The generic interrupt handlers currently disable interrupts during
|
||||||
interrupts. Instead, they must be able to keep the custom
|
interrupts. Instead, they must be able to keep the custom interrupt
|
||||||
interrupt enabled throughout interrupt process but still prevent
|
enabled throughout interrupt process but still prevent re-entrancy by
|
||||||
re-entrancy by other standard interrupts (This can be done by
|
other standard interrupts (This can be done by setting an interrupt
|
||||||
setting an interrupt base priority level in the Cortex-M family).
|
base priority level in the Cortex-M family).
|
||||||
|
|
||||||
- The custom interrupt handler can now interrupt the generic
|
* The custom interrupt handler can now interrupt the generic interrupt
|
||||||
interrupt handler at any place. Is the logic safe in all cases to
|
handler at any place. Is the logic safe in all cases to be
|
||||||
be interrupted? Sometimes interrupt handlers place the MCU in
|
interrupted? Sometimes interrupt handlers place the MCU in momentarily
|
||||||
momentarily perverse states while registers are being
|
perverse states while registers are being manipulated. Make sure that
|
||||||
manipulated. Make sure that it is safe to take interrupts at any
|
it is safe to take interrupts at any time (or else keep the interrupts
|
||||||
time (or else keep the interrupts disabled in the critical
|
disabled in the critical times).
|
||||||
times).
|
|
||||||
|
|
||||||
- Will the custom interrupt handler have all of the resources it
|
* Will the custom interrupt handler have all of the resources it needs
|
||||||
needs in place when it occurs? Will it have a valid stack
|
in place when it occurs? Will it have a valid stack pointer? (In the
|
||||||
pointer? (In the Cortex-M implementation, for example, the MSP
|
Cortex-M implementation, for example, the MSP may not be valid when
|
||||||
may not be valid when the custom interrupt handler is entered).
|
the custom interrupt handler is entered).
|
||||||
|
|
||||||
Some of these issues are complex and so you should expect some
|
Some of these issues are complex and so you should expect some
|
||||||
complexity in getting the nested interrupt handler to work.
|
complexity in getting the nested interrupt handler to work.
|
||||||
@ -201,14 +206,13 @@ priority interrupts.
|
|||||||
Dependencies
|
Dependencies
|
||||||
------------
|
------------
|
||||||
|
|
||||||
- ``CONFIG_ARCH_HAVE_IRQPRIO``. Support for prioritized interrupt
|
* ``CONFIG_ARCH_HAVE_IRQPRIO``. Support for prioritized interrupt
|
||||||
support must be enabled.
|
support must be enabled.
|
||||||
|
|
||||||
- Floating Point Registers. If used with a Cortex-M4 that supports
|
* Floating Point Registers. If used with a Cortex-M4 that supports
|
||||||
hardware floating point, you cannot use hardware floating point
|
hardware floating point, you cannot use hardware floating point in the
|
||||||
in the high priority interrupt handler UNLESS you use the common
|
high priority interrupt handler UNLESS you use the common vector logic
|
||||||
vector logic that supports saving of floating point registers on
|
that supports saving of floating point registers on all interrupts.
|
||||||
all interrupts.
|
|
||||||
|
|
||||||
Configuring High Priority Interrupts
|
Configuring High Priority Interrupts
|
||||||
------------------------------------
|
------------------------------------
|
||||||
@ -220,14 +224,13 @@ First, You need to change the address in the vector table so that the
|
|||||||
high priority interrupt vectors to your special C interrupt handler.
|
high priority interrupt vectors to your special C interrupt handler.
|
||||||
There are two ways to do this:
|
There are two ways to do this:
|
||||||
|
|
||||||
- If you select ``CONFIG_ARCH_RAMVECTORS``, then vectors will be
|
* If you select ``CONFIG_ARCH_RAMVECTORS``, then vectors will be kept in
|
||||||
kept in RAM and the system will support the interface: ``int
|
RAM and the system will support the interface: ``int
|
||||||
up_ramvec_attach(int irq, up_vector_t vector)``. That interface
|
up_ramvec_attach(int irq, up_vector_t vector)``. That interface can be
|
||||||
can be used to attach your C interrupt handler to the vector at
|
used to attach your C interrupt handler to the vector at run time.
|
||||||
run time.
|
|
||||||
|
|
||||||
- Alternatively, you could keep your vectors in FLASH but in order
|
* Alternatively, you could keep your vectors in FLASH but in order to
|
||||||
to this, you would have to develop your own custom vector table.
|
this, you would have to develop your own custom vector table.
|
||||||
|
|
||||||
Second, you need to set the priority of your interrupt to *NVIC* to
|
Second, you need to set the priority of your interrupt to *NVIC* to
|
||||||
``NVIC_SYSH_HIGH_PRIORITY`` using the standard interface:
|
``NVIC_SYSH_HIGH_PRIORITY`` using the standard interface:
|
||||||
@ -238,12 +241,11 @@ Example Code
|
|||||||
|
|
||||||
You can find an example that tests the high priority, nested interrupts in the NuttX source:
|
You can find an example that tests the high priority, nested interrupts in the NuttX source:
|
||||||
|
|
||||||
- nuttx/boards/arm/stm32/viewtool-stm32f107/README.txt. Description
|
* nuttx/boards/arm/stm32/viewtool-stm32f107/README.txt. Description of
|
||||||
of the configuration
|
the configuration
|
||||||
|
|
||||||
- nuttx/boards/arm/stm32/viewtool-stm32f107/highpri. Test
|
* nuttx/boards/arm/stm32/viewtool-stm32f107/highpri. Test configuration
|
||||||
configuration
|
|
||||||
|
|
||||||
- nuttx/boards/arm/stm32/viewtool-stm32f107/src/stm32_highpri. Test
|
* nuttx/boards/arm/stm32/viewtool-stm32f107/src/stm32_highpri. Test
|
||||||
driver.
|
driver.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user