| <!-- |
| Documentation/_templates/layout.html |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. The |
| ASF licenses this file to you 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. |
| --> |
| |
| |
| |
| <!DOCTYPE html> |
| <html class="writer-html5" lang="en"> |
| <head> |
| <meta charset="utf-8" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" /> |
| |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>High Performance: Zero Latency Interrupts, Maskable nested interrupts — NuttX latest documentation</title> |
| <link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> |
| <link rel="stylesheet" type="text/css" href="../_static/css/theme.css" /> |
| <link rel="stylesheet" type="text/css" href="../_static/copybutton.css" /> |
| <link rel="stylesheet" type="text/css" href="../_static/custom.css" /> |
| |
| |
| <link rel="shortcut icon" href="../_static/favicon.ico"/> |
| <script src="../_static/jquery.js"></script> |
| <script src="../_static/_sphinx_javascript_frameworks_compat.js"></script> |
| <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script> |
| <script src="../_static/doctools.js"></script> |
| <script src="../_static/sphinx_highlight.js"></script> |
| <script src="../_static/clipboard.min.js"></script> |
| <script src="../_static/copybutton.js"></script> |
| <script src="../_static/js/theme.js"></script> |
| <link rel="index" title="Index" href="../genindex.html" /> |
| <link rel="search" title="Search" href="../search.html" /> |
| <link rel="next" title="The Kernel Address Sanitizer (KASAN)" href="kasan.html" /> |
| <link rel="prev" title="Running CI Test Locally" href="citests.html" /> |
| </head> |
| |
| <body class="wy-body-for-nav"> |
| <div class="wy-grid-for-nav"> |
| <nav data-toggle="wy-nav-shift" class="wy-nav-side"> |
| <div class="wy-side-scroll"> |
| <div class="wy-side-nav-search" > |
| |
| <a href="../index.html" class="icon icon-home"> NuttX |
| |
| |
| |
| </a> |
| |
| <!-- this version selector is quite ugly, should be probably replaced by something |
| more modern --> |
| |
| <div class="version-selector"> |
| <select onchange="javascript:location.href = this.value;"> |
| |
| <option value="../../latest" selected="selected">latest</option> |
| |
| <option value="../../10.0.0" >10.0.0</option> |
| |
| <option value="../../10.0.1" >10.0.1</option> |
| |
| <option value="../../10.1.0" >10.1.0</option> |
| |
| <option value="../../10.2.0" >10.2.0</option> |
| |
| <option value="../../10.3.0" >10.3.0</option> |
| |
| <option value="../../11.0.0" >11.0.0</option> |
| |
| <option value="../../12.0.0" >12.0.0</option> |
| |
| <option value="../../12.1.0" >12.1.0</option> |
| |
| <option value="../../12.2.0" >12.2.0</option> |
| |
| <option value="../../12.2.1" >12.2.1</option> |
| |
| <option value="../../12.3.0" >12.3.0</option> |
| |
| <option value="../../12.4.0" >12.4.0</option> |
| |
| <option value="../../12.5.0" >12.5.0</option> |
| |
| <option value="../../12.5.1" >12.5.1</option> |
| |
| <option value="../../12.6.0" >12.6.0</option> |
| |
| <option value="../../12.7.0" >12.7.0</option> |
| |
| <option value="../../12.8.0" >12.8.0</option> |
| |
| <option value="../../12.9.0" >12.9.0</option> |
| |
| <option value="../../12.10.0" >12.10.0</option> |
| |
| <option value="../../12.11.0" >12.11.0</option> |
| |
| </select> |
| </div> |
| |
| |
| <div role="search"> |
| <form id="rtd-search-form" class="wy-form" action="../search.html" method="get"> |
| <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" /> |
| <input type="hidden" name="check_keywords" value="yes" /> |
| <input type="hidden" name="area" value="default" /> |
| </form> |
| </div> |
| |
| </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu"> |
| <p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p> |
| <ul class="current"> |
| <li class="toctree-l1"><a class="reference internal" href="../index.html">Home</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../introduction/index.html">Introduction</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../quickstart/index.html">Getting Started</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../contributing/index.html">Contributing</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../platforms/index.html">Supported Platforms</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../components/index.html">OS Components</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../applications/index.html">Applications</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../implementation/index.html">Implementation Details</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../reference/index.html">API Reference</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li> |
| <li class="toctree-l1 current"><a class="reference internal" href="index.html">Guides</a><ul class="current"> |
| <li class="toctree-l2"><a class="reference internal" href="nfs.html">NFS Client How-To</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="usbtrace.html">USB Device Trace</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="simulator.html">Simulator</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="qemugdb.html">How to debug NuttX using QEMU and GDB</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="rndis.html">How to use RNDIS</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="drivers.html">Drivers</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="tasktrace.html">Task Trace</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="cpp_cmake.html">C++ Example using CMake</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="pysimcoder.html">pysimCoder integration with NuttX</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="customboards.html">Custom Boards How-To</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="customapps.html">Custom Apps How-to</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="citests.html">Running CI Test Locally</a></li> |
| <li class="toctree-l2 current"><a class="current reference internal" href="#">High Performance: Zero Latency Interrupts, Maskable nested interrupts</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#generic-interrupt-handling">Generic Interrupt Handling</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#bypassing-the-generic-interrupt-handling">Bypassing the Generic Interrupt Handling</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#getting-back-into-the-game">Getting Back into the Game</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#maskable-nested-interrupts">Maskable Nested Interrupts</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#nested-interrupt-handling">Nested Interrupt Handling</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#cortex-m3-4-implementation">Cortex-M3/4 Implementation</a><ul> |
| <li class="toctree-l4"><a class="reference internal" href="#configuration-options">Configuration Options</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#disabling-the-high-priority-interrupt">Disabling the High Priority Interrupt</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#dependencies">Dependencies</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#configuring-high-priority-interrupts">Configuring High Priority Interrupts</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#example-code">Example Code</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="kasan.html">The Kernel Address Sanitizer (KASAN)</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="nestedinterrupts.html">Nested Interrupts</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="cortexmhardfaults.html">Analyzing Cortex-M Hardfaults</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="coredump.html">Core Dump</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="coresight.html">Coresight - HW Assisted Tracing on ARM</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="gdbserver.html">gdbserver</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="gdbwithpython.html">GDB with Python</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="ofloader.html">Open Flash Loader</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="testingtcpip.html">Testing TCP/IP Network Stacks</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="automounter.html">Auto-Mounter</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="stm32nullpointer.html">STM32 Null Pointer Detection</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="stm32ccm.html">STM32 CCM Allocator</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="stackrecord.html">Run time stack statistics</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="etcromfs.html">etc romfs</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="thread_local_storage.html">Thread Local Storage</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../logos/index.html">NuttX Logos</a></li> |
| </ul> |
| |
| </div> |
| </div> |
| </nav> |
| |
| <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" > |
| <i data-toggle="wy-nav-top" class="fa fa-bars"></i> |
| <a href="../index.html">NuttX</a> |
| </nav> |
| |
| <div class="wy-nav-content"> |
| <div class="rst-content"> |
| <div role="navigation" aria-label="Page navigation"> |
| <ul class="wy-breadcrumbs"> |
| <li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li> |
| <li class="breadcrumb-item"><a href="index.html">Guides</a></li> |
| <li class="breadcrumb-item active">High Performance: Zero Latency Interrupts, Maskable nested interrupts</li> |
| <li class="wy-breadcrumbs-aside"> |
| <a href="../_sources/guides/zerolatencyinterrupts.rst.txt" rel="nofollow"> View page source</a> |
| </li> |
| </ul> |
| <hr/> |
| </div> |
| <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> |
| <div itemprop="articleBody"> |
| |
| <section id="high-performance-zero-latency-interrupts-maskable-nested-interrupts"> |
| <h1>High Performance: Zero Latency Interrupts, Maskable nested interrupts<a class="headerlink" href="#high-performance-zero-latency-interrupts-maskable-nested-interrupts" title="Permalink to this heading"></a></h1> |
| <section id="generic-interrupt-handling"> |
| <h2>Generic Interrupt Handling<a class="headerlink" href="#generic-interrupt-handling" title="Permalink to this heading"></a></h2> |
| <p>NuttX includes a generic interrupt handling subsystem that makes it |
| convenient to deal with interrupts using only IRQ numbers. In order to |
| integrate with this generic interrupt handling system, the platform |
| specific code is expected to collect all thread state into a container, |
| <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">xcptcontext</span></code>. This container represents the full state of the |
| thread and can be saved, restored, and exchanged as a <em>unit of thread</em>.</p> |
| <p>While this state saving has many useful benefits, it does require |
| processing time. It was reported to me that this state saving required |
| about two microseconds on an STM32F4Discovery board. That added |
| interrupt latency might be an issue in some circumstances.</p> |
| <p>In addition, critical sections that are required in various places |
| 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 <em>jitter</em>). Like the added latency discussed above, that |
| jitter might be an issue in some circumstances.</p> |
| <p><strong>Terminology:</strong> The concepts discussed in this guide are not unique to |
| NuttX. Other RTOSes have similar concepts but will use different |
| terminology. The <a class="reference external" href="https://www.embedded.com/design/operating-systems/4461604/Interrupts-in-the-Nucleus-SE-RTOS">Nucleus</a> |
| RTOS, for example, uses the terms <em>Native</em> and <em>Managed</em> interrupts.</p> |
| </section> |
| <section id="bypassing-the-generic-interrupt-handling"> |
| <h2>Bypassing the Generic Interrupt Handling<a class="headerlink" href="#bypassing-the-generic-interrupt-handling" title="Permalink to this heading"></a></h2> |
| <p>Most modern MCUs (such as the ARM Cortex-M family) receive and dispatch |
| interrupts through a <em>vector table</em>. The vector table is a table in |
| memory. Each entry in the table holds the address of an interrupt |
| handler corresponding to different interrupts. When the interrupt |
| occurs, the hardware fetches the corresponding interrupt handler address |
| and gives control to the interrupt handler.</p> |
| <p>In the implementation of the generic interrupt handler, these vectored |
| interrupts are not used as intended by the hardware designer. Rather, |
| they are used to obtain an IRQ number and then to transfer control to |
| the common, generic interrupt handling logic.</p> |
| <p>One way to achieve higher performance interrupts and still retain the |
| benefits of the generic interrupt handling logic is to simply replace an |
| interrupt handler address in the vector table with a different interrupt |
| handler; one that does not vector to the generic interrupt handling |
| logic logic, but rather to your custom code.</p> |
| <p>Often, the vector table is in ROM. So you can hard-code a special |
| interrupt vector by modifying the ROM vector table so that the specific |
| entry points to your custom interrupt handler. Or, if the architecture |
| permits, you can use a vector table in RAM. Then you can freely attach |
| and detach custom vector handlers by writing directly to the vector |
| table. The ARM Cortex-M port provides interfaces to support this mode |
| when the <code class="docutils literal notranslate"><span class="pre">CONFIG_ARCH_RAMVECTORS</span></code> option is enabled.</p> |
| <p>So what is the downside? There are two:</p> |
| <ul class="simple"> |
| <li><p>Your custom interrupt handler will not have collected its state into |
| the <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">xcptcontext</span></code> container. Therefore, it cannot communicate |
| with operating system. Your custom interrupt handler has been taken |
| “out of the game” and can no longer work with the system.</p></li> |
| <li><p>If your custom interrupt is truly going to be <em>high performance</em> then |
| you will also have to support nested interrupts! The custom interrupt |
| must have a high priority and must be able interrupt the generic |
| interrupt handling logic. Otherwise, it will be occasionally delayed |
| when there is a collision between your custom interrupt and other, |
| lower priority interrupts.</p></li> |
| </ul> |
| </section> |
| <section id="getting-back-into-the-game"> |
| <h2>Getting Back into the Game<a class="headerlink" href="#getting-back-into-the-game" title="Permalink to this heading"></a></h2> |
| <p>As mentioned, the custom interrupt handler cannot use most of the |
| services of the OS since it has not created a <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">xcptcontext</span></code> |
| 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 |
| semaphore, signal a thread, or send a message.</p> |
| <p>The ARM Cortex-M family supports a special way to do this using the |
| <em>PendSV</em> interrupt:</p> |
| <ul class="simple"> |
| <li><p>The custom logic would connect with the <em>PendSV</em> interrupt using the |
| standard <code class="docutils literal notranslate"><span class="pre">irq_attach()</span></code> interface.</p></li> |
| <li><p>In the custom interrupt handler, it would schedule the <em>PendSV</em> |
| interrupt when it needs to communicate with the OS.</p></li> |
| <li><p>The <em>PendSV</em> interrupt is dispatched through the generic interrupt |
| system so when the attached <em>PendSV</em> interrupt is handled, it will be |
| in a context where it can perform any necessary OS interactions.</p></li> |
| </ul> |
| <p>With the ARMv7_M architecture, the <em>PendSV</em> interrupt can be generated |
| with:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">up_trigger_irq</span><span class="p">(</span><span class="n">NVIC_IRQ_PENDSV</span><span class="p">);</span> |
| </pre></div> |
| </div> |
| <p>On other architectures, it may be possible to do something like a |
| software interrupt from the custom interrupt handler to accomplish the |
| same thing.</p> |
| <p>The custom logic would be needed to communicate the events of interest |
| between the high priority interrupt handler and <em>PendSV</em> interrupt |
| handler. A detailed discussion of that custom logic is beyond the |
| scope of this Wiki page.</p> |
| <p>The following table shows the priority levels of the Cortex-M family:</p> |
| <div class="highlight-none notranslate"><div class="highlight"><pre><span></span>IRQ type Priority |
| Dataabort 0x00 |
| High prio IRQ1 0x20 (Zero-latency interrupt) |
| High prio IRQ2 0x30 (Can't call OS API in ISR) |
| SVC 0x70 |
| Disable IRQ 0x80 |
| (critical-section) |
| Low prio IRQ 0xB0 |
| PendSV 0xE0 |
| </pre></div> |
| </div> |
| <p>As you can see, the priority levels of the zero-latency interrupts can |
| beyond the critical section and SVC. |
| But High prio IRQ can’t call OS API.</p> |
| </section> |
| <section id="maskable-nested-interrupts"> |
| <h2>Maskable Nested Interrupts<a class="headerlink" href="#maskable-nested-interrupts" title="Permalink to this heading"></a></h2> |
| <p>The ARM Cortex-M family supports a feature called <em>BASEPRI</em> that can be |
| used to disable interrupts at a priority level below a certain level. |
| This feature can be used to support maskable nested interrupts.</p> |
| <p>Maskable nested interrupts differ from zero-latency interrupts in |
| that they obey the interrupt masking mechanisms of the system. |
| For example, setting the BASEPRI register to a specific threshold will |
| block all interrupts of a lower or equal priority. |
| However, high-priority interrupts (such as Non-Maskable Interrupts |
| or zero-latency interrupts) are unaffected by these masks.</p> |
| <p>This is useful when you have a high-priority interrupt that needs to |
| be able to interrupt the system, but you also have lower-priority |
| interrupts that you want to be able to mask.</p> |
| <p>The following table shows the priority levels of the Cortex-M family:</p> |
| <div class="highlight-none notranslate"><div class="highlight"><pre><span></span>IRQ type Priority |
| Dataabort 0x00 |
| SVC 0x70 |
| Disable IRQ 0x80 |
| (critical-section) |
| High prio IRQ1 0x90 (Maskable nested interrupt) |
| High prio IRQ2 0xA0 (Can call OS API in ISR) |
| Low prio IRQ 0xB0 |
| PendSV 0xE0 |
| </pre></div> |
| </div> |
| <p>As you can see, the priority levels of the maskable nested interrupts |
| are between the critical section and the low-priority interrupts. |
| And High prio IRQ can call OS API in ISR.</p> |
| </section> |
| <section id="nested-interrupt-handling"> |
| <h2>Nested Interrupt Handling<a class="headerlink" href="#nested-interrupt-handling" title="Permalink to this heading"></a></h2> |
| <p>Some general notes about nested interrupt handling are provided in |
| <a class="reference internal" href="nestedinterrupts.html"><span class="doc">Nested Interrupts</span></a>. In this case, handling the nested custom |
| interrupt is simpler because the generic interrupt handler is not |
| re-entered. Rather, the generic interrupt handler must simply be made to |
| co-exist with the custom interrupt interrupt handler.</p> |
| <p>Modifications may be required to the generic interrupt handling logic |
| to accomplish. A few points need to be made here:</p> |
| <ul class="simple"> |
| <li><p>The MCU should support interrupt prioritization so that the custom |
| interrupt can be scheduled with a higher priority.</p></li> |
| <li><p>The generic interrupt handlers currently disable interrupts during |
| interrupts. Instead, they must be able to keep the custom interrupt |
| enabled throughout interrupt process but still prevent re-entrancy by |
| other standard interrupts (This can be done by setting an interrupt |
| base priority level in the Cortex-M family).</p></li> |
| <li><p>The custom interrupt handler can now interrupt the generic interrupt |
| handler at any place. Is the logic safe in all cases to be |
| interrupted? Sometimes interrupt handlers place the MCU in momentarily |
| perverse states while registers are being manipulated. Make sure that |
| it is safe to take interrupts at any time (or else keep the interrupts |
| disabled in the critical times).</p></li> |
| <li><p>Will the custom interrupt handler have all of the resources it needs |
| in place when it occurs? Will it have a valid stack pointer? (In the |
| Cortex-M implementation, for example, the MSP may not be valid when |
| the custom interrupt handler is entered).</p></li> |
| </ul> |
| <p>Some of these issues are complex and so you should expect some |
| complexity in getting the nested interrupt handler to work.</p> |
| </section> |
| <section id="cortex-m3-4-implementation"> |
| <h2>Cortex-M3/4 Implementation<a class="headerlink" href="#cortex-m3-4-implementation" title="Permalink to this heading"></a></h2> |
| <p>Such high priority, nested interrupt handler has been implemented for |
| the Cortex-M3/4 families.</p> |
| <p>The following paragraphs will summarize that implementation.</p> |
| <section id="configuration-options"> |
| <h3>Configuration Options<a class="headerlink" href="#configuration-options" title="Permalink to this heading"></a></h3> |
| <p><code class="docutils literal notranslate"><span class="pre">CONFIG_ARCH_HIPRI_INTERRUPT</span></code></p> |
| <p>If <code class="docutils literal notranslate"><span class="pre">CONFIG_ARMV7M_USEBASEPRI</span></code> is selected, then interrupts will be |
| disabled by setting the <em>BASEPRI</em> register to |
| <code class="docutils literal notranslate"><span class="pre">NVIC_SYSH_DISABLE_PRIORITY</span></code> so that most interrupts will not have |
| execution priority. <em>SVCall</em> must have execution priority in all |
| cases.</p> |
| <p>In the normal cases, interrupts are not nest-able and all interrupts |
| run at an execution priority between <code class="docutils literal notranslate"><span class="pre">NVIC_SYSH_PRIORITY_MIN</span></code> and |
| <code class="docutils literal notranslate"><span class="pre">NVIC_SYSH_PRIORITY_MAX</span></code> (with <code class="docutils literal notranslate"><span class="pre">NVIC_SYSH_PRIORITY_MAX</span></code> reserved |
| for <em>SVCall</em>).</p> |
| <p>If, in addition, <code class="docutils literal notranslate"><span class="pre">CONFIG_ARCH_HIPRI_INTERRUPT</span></code> is defined, then |
| special high priority interrupts are supported. These are not “nested” |
| in the normal sense of the word. These high priority interrupts can |
| interrupt normal processing but execute outside of OS (although they |
| can “get back into the game” via a <em>PendSV</em> interrupt).</p> |
| </section> |
| <section id="disabling-the-high-priority-interrupt"> |
| <h3>Disabling the High Priority Interrupt<a class="headerlink" href="#disabling-the-high-priority-interrupt" title="Permalink to this heading"></a></h3> |
| <p>In the normal course of things, interrupts must occasionally be |
| disabled using the <code class="docutils literal notranslate"><span class="pre">up_irq_save()</span></code> inline function to prevent |
| contention in use of resources that may be shared between interrupt |
| level and non-interrupt level logic. Now the question arises, if we |
| are using the <em>BASEPRI</em> to disable interrupts and have high priority |
| interrupts enabled (<code class="docutils literal notranslate"><span class="pre">CONFIG_ARCH_HIPRI_INTERRUPT=y</span></code>), do we disable |
| all interrupts except <em>SVCall</em> (we cannot disable <em>SVCall</em> |
| interrupts)? Or do we only disable the “normal” interrupts?</p> |
| <p>If we are using the <em>BASEPRI</em> register to disable interrupts, then the |
| answer is that we must disable <em>ONLY</em> the normal interrupts. That is |
| because we cannot disable <em>SVCall</em> interrupts and we cannot permit |
| <em>SVCall</em> interrupts running at a higher priority than the high |
| priority interrupts. Otherwise, they will introduce jitter in the high |
| priority interrupt response time.</p> |
| <p>Hence, if you need to disable the high priority interrupt, you will |
| have to disable the interrupt either at the peripheral that generates |
| the interrupt or at the interrupt controller, the <em>NVIC</em>. Disabling |
| global interrupts via the <em>BASEPRI</em> register cannot affect high |
| priority interrupts.</p> |
| </section> |
| <section id="dependencies"> |
| <h3>Dependencies<a class="headerlink" href="#dependencies" title="Permalink to this heading"></a></h3> |
| <ul class="simple"> |
| <li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_ARCH_HAVE_IRQPRIO</span></code>. Support for prioritized interrupt |
| support must be enabled.</p></li> |
| <li><p>Floating Point Registers. If used with a Cortex-M4 that supports |
| hardware floating point, you cannot use hardware floating point in the |
| high priority interrupt handler UNLESS you use the common vector logic |
| that supports saving of floating point registers on all interrupts.</p></li> |
| </ul> |
| </section> |
| <section id="configuring-high-priority-interrupts"> |
| <h3>Configuring High Priority Interrupts<a class="headerlink" href="#configuring-high-priority-interrupts" title="Permalink to this heading"></a></h3> |
| <p>How do you specify a high priority interrupt? You need to do two |
| things:</p> |
| <p>First, You need to change the address in the vector table so that the |
| high priority interrupt vectors to your special C interrupt handler. |
| There are two ways to do this:</p> |
| <ul class="simple"> |
| <li><p>If you select <code class="docutils literal notranslate"><span class="pre">CONFIG_ARCH_RAMVECTORS</span></code>, then vectors will be kept in |
| RAM and the system will support the interface: <code class="docutils literal notranslate"><span class="pre">int</span> |
| <span class="pre">up_ramvec_attach(int</span> <span class="pre">irq,</span> <span class="pre">up_vector_t</span> <span class="pre">vector)</span></code>. That interface can be |
| used to attach your C interrupt handler to the vector at run time.</p></li> |
| <li><p>Alternatively, you could keep your vectors in FLASH but in order to |
| this, you would have to develop your own custom vector table.</p></li> |
| </ul> |
| <p>Second, you need to set the priority of your interrupt to <em>NVIC</em> to |
| <code class="docutils literal notranslate"><span class="pre">NVIC_SYSH_HIGH_PRIORITY</span></code> using the standard interface: |
| <code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">up_prioritize_irq(int</span> <span class="pre">irq,</span> <span class="pre">int</span> <span class="pre">priority);</span></code></p> |
| </section> |
| <section id="example-code"> |
| <h3>Example Code<a class="headerlink" href="#example-code" title="Permalink to this heading"></a></h3> |
| <p>You can find an example that tests the high priority, nested interrupts in the NuttX source:</p> |
| <ul class="simple"> |
| <li><p><a class="reference internal" href="../platforms/arm/stm32f1/boards/viewtool-stm32f107/index.html"><span class="doc">ViewTool STM32F103/F107</span></a> Description of |
| the configuration</p></li> |
| <li><p><code class="docutils literal notranslate"><span class="pre">nuttx/boards/arm/stm32/viewtool-stm32f107/highpri</span></code> Test configuration</p></li> |
| <li><p><code class="docutils literal notranslate"><span class="pre">nuttx/boards/arm/stm32/viewtool-stm32f107/src/stm32_highpri</span></code> Test |
| driver.</p></li> |
| </ul> |
| </section> |
| </section> |
| </section> |
| |
| |
| </div> |
| </div> |
| <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer"> |
| <a href="citests.html" class="btn btn-neutral float-left" title="Running CI Test Locally" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> |
| <a href="kasan.html" class="btn btn-neutral float-right" title="The Kernel Address Sanitizer (KASAN)" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> |
| </div> |
| |
| <hr/> |
| |
| <div role="contentinfo"> |
| <p>© Copyright 2023, The Apache Software Foundation.</p> |
| </div> |
| |
| |
| |
| </footer> |
| </div> |
| </div> |
| </section> |
| </div> |
| <script> |
| jQuery(function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }); |
| </script> |
| |
| </body> |
| </html> |