| <!-- |
| 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>Nested Interrupts — NuttX latest documentation</title> |
| <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> |
| <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" /> |
| <link rel="stylesheet" href="../_static/copybutton.css" type="text/css" /> |
| <link rel="stylesheet" href="../_static/tabs.css" type="text/css" /> |
| <link rel="stylesheet" href="../_static/custom.css" type="text/css" /> |
| <link rel="shortcut icon" href="../_static/favicon.ico"/> |
| <!--[if lt IE 9]> |
| <script src="../_static/js/html5shiv.min.js"></script> |
| <![endif]--> |
| |
| <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="Analyzing Cortex-M Hardfaults" href="cortexmhardfaults.html" /> |
| <link rel="prev" title="High Performance, Zero Latency Interrupts" href="zerolatencyinterrupts.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="../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="zerolatencyinterrupts.html">High Performance, Zero Latency Interrupts</a></li> |
| <li class="toctree-l2 current"><a class="current reference internal" href="#">Nested Interrupts</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#are-nested-interrupts-needed">Are Nested Interrupts Needed?</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#layered-interrupt-handling-architecture">Layered Interrupt Handling Architecture</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#how-to-implement-nested-interrupts-in-the-layered-interrupt-handling-architecture">How to Implement Nested Interrupts in the Layered Interrupt Handling Architecture</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#svcall-vs-pendsv">SVCall vs PendSV</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#what-could-go-wrong">What Could Go Wrong?</a></li> |
| </ul> |
| </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="gdbwithpython.html">GDB with Python</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</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">Nested Interrupts</li> |
| <li class="wy-breadcrumbs-aside"> |
| <a href="../_sources/guides/nestedinterrupts.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="nested-interrupts"> |
| <h1>Nested Interrupts<a class="headerlink" href="#nested-interrupts" title="Permalink to this heading"></a></h1> |
| <section id="are-nested-interrupts-needed"> |
| <h2>Are Nested Interrupts Needed?<a class="headerlink" href="#are-nested-interrupts-needed" title="Permalink to this heading"></a></h2> |
| <p>Most NuttX architectures do not support nested interrupts: Interrupts |
| are disabled when the interrupt is entered and restored when the |
| interrupt returns. Being able to handle nested interrupt is critical in |
| simple architectures where a lot of interrupt level processing is |
| performed: In this case, you can prioritize interrupts and assure that |
| the highest priority interrupt processing is not delayed by lower level |
| interrupt processing.</p> |
| <p>In an RTOS model, however, all interrupt processing should be as brief |
| as possible; any extended processing should be deferred to a user task |
| and not performed in the interrupt handler. However, you may find a need |
| to have nested interrupt handling in NuttX too. The lack of support of |
| nested interrupts is not inherently an issue with NuttX and need not be |
| the case; it should be a simple matter to modify the interrupt handling |
| so that interrupts are nested.</p> |
| </section> |
| <section id="layered-interrupt-handling-architecture"> |
| <h2>Layered Interrupt Handling Architecture<a class="headerlink" href="#layered-interrupt-handling-architecture" title="Permalink to this heading"></a></h2> |
| <p>Interrupt handling occurs in several files. In most implementations, |
| there are several layers of interrupt handling logic:</p> |
| <ol class="arabic simple"> |
| <li><p>Some low-level logic, usually in assembly language, that catches the |
| interrupt and determines the IRQ number. Consider |
| <code class="docutils literal notranslate"><span class="pre">arch/arm/src/armv7-m/up_exception.S</span></code> as an example for the |
| Cortex-M family.</p></li> |
| <li><p>That low-level logic than calls some MCU-specific, intermediate level |
| function usually called <code class="docutils literal notranslate"><span class="pre">up_doirq()</span></code>. An example is |
| <code class="docutils literal notranslate"><span class="pre">arch/arm/src/armv7-m/up_doirq.c</span></code>.</p></li> |
| <li><p>That MCU-specific function then calls the NuttX common interrupt |
| dispatching logic <code class="docutils literal notranslate"><span class="pre">irq_dispatch()</span></code> that can be found at |
| <code class="docutils literal notranslate"><span class="pre">sched/irq_dispatch.c</span></code>.</p></li> |
| </ol> |
| </section> |
| <section id="how-to-implement-nested-interrupts-in-the-layered-interrupt-handling-architecture"> |
| <h2>How to Implement Nested Interrupts in the Layered Interrupt Handling Architecture<a class="headerlink" href="#how-to-implement-nested-interrupts-in-the-layered-interrupt-handling-architecture" title="Permalink to this heading"></a></h2> |
| <p>The logic in these first two levels that would have to change to support |
| nested interrupt handling. Here is one technical approach to do that:</p> |
| <ol class="arabic simple"> |
| <li><p>Add a global variable, say <code class="docutils literal notranslate"><span class="pre">g_nestlevel</span></code>, that counts the interrupt |
| nesting level. It would have an initial value of zero; it would be |
| incremented on each interrupt entry and decremented on interrupt exit |
| (making sure that interrupts are disabled in each case because |
| incrementing and decrementing are not usually atomic operations).</p></li> |
| <li><p>At the lowest level, there is usually some assembly language logic |
| that will switch from the user’s stack to a special interrupt level |
| stack. This behavior is controlled <code class="docutils literal notranslate"><span class="pre">CONFIG_ARCH_INTERRUPTSTACK</span></code>. |
| The logic here would have to change in the following way: If |
| <code class="docutils literal notranslate"><span class="pre">g_nestlevel</span></code> is zero then behave as normal, switching from the |
| user to the interrupt stack; if <code class="docutils literal notranslate"><span class="pre">g_nestlevel</span></code> is greater than zero, |
| then do not switch stacks. In this latter case, we are already using |
| the interrupt stack.</p></li> |
| <li><p>In the middle-level, MCU-specific is where the <code class="docutils literal notranslate"><span class="pre">g_nestlevel</span></code> would |
| be increment. And here some additional decision must be made based on |
| the state of <code class="docutils literal notranslate"><span class="pre">g_nestlevel</span></code>. If <code class="docutils literal notranslate"><span class="pre">g_nestlevel</span></code> is zero, then we |
| have interrupted user code and we need to handle the context |
| information specially and handle interrupt level context switches. If |
| <code class="docutils literal notranslate"><span class="pre">g_nestlevel</span></code> is greater than zero, then the interrupt handler was |
| interrupt by an interrupt. In this case, the interrupt handling must |
| always return to the interrupt handler. No context switch can occur |
| here. No context switch can occur until the outermost, nested |
| interrupt handler returns to the user task.</p></li> |
| <li><p>You would also need to support some kind of critical section within |
| interrupt handlers to prevent nested interrupts. For example, within |
| the logic of functions like <code class="docutils literal notranslate"><span class="pre">up_block_task()</span></code>. Such logic must be |
| atomic in any case.</p></li> |
| </ol> |
| <p><strong>NOTE 1</strong>: The ARMv7-M could also be configured to use separate MSP and |
| PSP stacks with the interupt processing using the MSP stack and the |
| tasks all using the PSP stacks. This is not compatible with certain |
| parts of the existing design and would be more effort, but could result |
| in a better solution.</p> |
| <p><strong>NOTE 2</strong>: SMP has this same issue as 2 but it is addressed |
| differently: With SMP there is an array of stacks indexed by the CPU |
| number so that all CPUs get to have an interrupt stack. See for |
| example, |
| <a class="reference external" href="https://bitbucket.org/nuttx/nuttx/src/ca4ef377fb789ddc3e70979b28acb6730ff6a98c/arch/arm/src/lc823450/chip.h">LC823450</a> |
| or |
| <a class="reference external" href="https://bitbucket.org/nuttx/nuttx/src/ca4ef377fb789ddc3e70979b28acb6730ff6a98c/arch/arm/src/imx6/chip.h">i.MX6</a> |
| SMP logic.</p> |
| <p>A generic <code class="docutils literal notranslate"><span class="pre">up_doirq()</span></code> might look like the following. It can be very |
| simple because interrupts are disabled:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">uint32_t</span><span class="w"> </span><span class="o">*</span><span class="nf">up_doirq</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">irq</span><span class="p">,</span><span class="w"> </span><span class="kt">uint32_t</span><span class="w"> </span><span class="o">*</span><span class="n">regs</span><span class="p">)</span> |
| <span class="p">{</span> |
| <span class="w"> </span><span class="cm">/* Current regs non-zero indicates that we are processing an interrupt;</span> |
| <span class="cm"> * current_regs is also used to manage interrupt level context switches.</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="n">current_regs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">regs</span><span class="p">;</span> |
| |
| <span class="w"> </span><span class="cm">/* Deliver the IRQ */</span> |
| |
| <span class="w"> </span><span class="n">irq_dispatch</span><span class="p">(</span><span class="n">irq</span><span class="p">,</span><span class="w"> </span><span class="n">regs</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="cm">/* If a context switch occurred while processing the interrupt then</span> |
| <span class="cm"> * current_regs may have change value. If we return any value different</span> |
| <span class="cm"> * from the input regs, then the lower level will know that a context</span> |
| <span class="cm"> * switch occurred during interrupt processing.</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="n">regs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">uint32_t</span><span class="o">*</span><span class="p">)</span><span class="n">current_regs</span><span class="p">;</span> |
| <span class="w"> </span><span class="n">current_regs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span> |
| <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">regs</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| <p>What has to change to support nested interrupts is:</p> |
| <ol class="arabic simple"> |
| <li><p>If we are nested, then we must retain the original value of |
| <code class="docutils literal notranslate"><span class="pre">current_regs</span></code>. This will be need when the outermost interrupt |
| handler returns in order to handle interrupt level context switches.</p></li> |
| <li><p>If we are nested, then we need to always return the same value of |
| <code class="docutils literal notranslate"><span class="pre">regs</span></code> that was received.</p></li> |
| </ol> |
| <p>So the modified version of <code class="docutils literal notranslate"><span class="pre">up_doirq()</span></code> would be as follows. Here we |
| assume that interrupts are enabled.</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">uint32_t</span><span class="w"> </span><span class="o">*</span><span class="nf">up_doirq</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">irq</span><span class="p">,</span><span class="w"> </span><span class="kt">uint32_t</span><span class="w"> </span><span class="o">*</span><span class="n">regs</span><span class="p">)</span> |
| <span class="p">{</span> |
| <span class="w"> </span><span class="n">irqstate_t</span><span class="w"> </span><span class="n">flags</span><span class="p">;</span> |
| |
| <span class="w"> </span><span class="cm">/* Current regs non-zero indicates that we are processing an interrupt;</span> |
| <span class="cm"> * regs holds the state of the interrupted logic; current_regs holds the</span> |
| <span class="cm"> * state of the interrupted user task. current_regs should, therefor,</span> |
| <span class="cm"> * only be modified for outermost interrupt handler (when g_nestlevel == 0)</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="n">flags</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">irqsave</span><span class="p">();</span> |
| <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">g_nestlevel</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">current_regs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">regs</span><span class="p">;</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="n">g_nestlevel</span><span class="o">++</span> |
| <span class="w"> </span><span class="n">irqrestore</span><span class="p">(</span><span class="n">flags</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="cm">/* Deliver the IRQ */</span> |
| |
| <span class="w"> </span><span class="n">irq_dispatch</span><span class="p">(</span><span class="n">irq</span><span class="p">,</span><span class="w"> </span><span class="n">regs</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="cm">/* Context switches are indicated by the returned value of this function.</span> |
| <span class="cm"> * If a context switch occurred while processing the interrupt then</span> |
| <span class="cm"> * current_regs may have change value. If we return any value different</span> |
| <span class="cm"> * from the input regs, then the lower level will know that a context</span> |
| <span class="cm"> * switch occurred during interrupt processing. Context switching should</span> |
| <span class="cm"> * only be performed when the outermost interrupt handler returns.</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="n">flags</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">irqsave</span><span class="p">();</span> |
| <span class="w"> </span><span class="n">g_nestlevel</span><span class="o">--</span><span class="p">;</span> |
| <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">g_nestlevel</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">regs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">uint32_t</span><span class="o">*</span><span class="p">)</span><span class="n">current_regs</span><span class="p">;</span> |
| <span class="w"> </span><span class="n">current_regs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="cm">/* Note that interrupts are left disabled. This needed if context switch</span> |
| <span class="cm"> * will be performed. But, any case, the correct interrupt state should</span> |
| <span class="cm"> * be restored when returning from the interrupt.</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">regs</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| <p><strong>NOTE:</strong> An alternative, cleaner design might also be possible. If one |
| were to defer all context switching to a <em>PendSV</em> handler, then the |
| interrupts could vector to the <code class="docutils literal notranslate"><span class="pre">do_irq()</span></code> logic and then all |
| interrupts would be naturally nestable.</p> |
| </section> |
| <section id="svcall-vs-pendsv"> |
| <h2>SVCall vs PendSV<a class="headerlink" href="#svcall-vs-pendsv" title="Permalink to this heading"></a></h2> |
| <p>An issue that may be related to nested interrupt handling is the use of |
| the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exceptions in NuttX. The <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exception is used as |
| a classic software interrupt in NuttX for performing context switches, |
| user- to kernel-mode changes (and vice versa), and also for system calls |
| when NuttX is built as a kernel.</p> |
| <p><code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exceptions are never performed from interrupt level, handler |
| mode processing; only from thread mode logic. The <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exception |
| is used as follows to perform the system call:</p> |
| <ul class="simple"> |
| <li><p>All interrupts are disabled: There are a few steps the must be |
| performed in a critical section. Those setups and the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> must |
| work as a single, uninterrupted atomic action.</p></li> |
| <li><p>A special register setup is put in place: Parameters are passed to the |
| <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> in registers just as with a normal function call.</p></li> |
| <li><p>The Cortex SVC instruction is executed. This causes the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> |
| exception which is dispatched to the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exception handler. |
| This exception must occur while the input register setup is in place; |
| it cannot be deferred and perform at some later time. The <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> |
| exception handler decodes the registers and performs the requested |
| operation. If no context switch occurs, the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> will return to |
| the caller immediately.</p></li> |
| <li><p>Upon return interrupts will be re-enabled.</p></li> |
| </ul> |
| <p>So what does this have to do with nested interrupt handling? Since |
| interrupts are disabled throughout the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> sequence, nothing |
| really. However, there are some concerns because if the <code class="docutils literal notranslate"><span class="pre">BASEPRI</span></code> is |
| used to disable interrupts then the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exception must have the |
| highest priority: The <code class="docutils literal notranslate"><span class="pre">BASEPRI</span></code> register is set to disable all |
| interrupt except for the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code>.</p> |
| <p>The motivation for supporting nested interrupts is, presumably, to make |
| sure that certain high priority interrupts are not delayed by lower |
| processing interrupt handling. Since the <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exception has |
| highest priority, it will delay all other interrupts (but, of course, |
| disabling interrupt also delays all other interrupts).</p> |
| <p>The PendSV exception is another mechanism offered by the Cortex |
| architecture. It has been suggested that some of these issues with the |
| <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> exception could be avoided by using the PendSV interrupt. The |
| architecture that would use the PendSV exception instead of the |
| <code class="docutils literal notranslate"><span class="pre">SVCall</span></code> interrupt is not clear in my mind. But I will keep this note |
| here for future reference if this were to become as issue.</p> |
| </section> |
| <section id="what-could-go-wrong"> |
| <h2>What Could Go Wrong?<a class="headerlink" href="#what-could-go-wrong" title="Permalink to this heading"></a></h2> |
| <p>Whenever you deal with logic at software hardware interface, lots of |
| things can go wrong. But, aside from that general risk, the only |
| specific NuttX risk issue is that you may uncover some subtle interrupt |
| level logic that assumes that interrupts are already disabled. In those |
| cases, additional critical sections may be needed inside of the |
| interrupt level processing. The likelihood of such a thing is probably |
| pretty low, but cannot be fully discounted.</p> |
| </section> |
| </section> |
| |
| |
| </div> |
| </div> |
| <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer"> |
| <a href="zerolatencyinterrupts.html" class="btn btn-neutral float-left" title="High Performance, Zero Latency Interrupts" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> |
| <a href="cortexmhardfaults.html" class="btn btn-neutral float-right" title="Analyzing Cortex-M Hardfaults" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> |
| </div> |
| |
| <hr/> |
| |
| <div role="contentinfo"> |
| <p>© Copyright 2020, The Apache Software Foundation.</p> |
| </div> |
| |
| |
| |
| </footer> |
| </div> |
| </div> |
| </section> |
| </div> |
| <script> |
| jQuery(function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }); |
| </script> |
| |
| </body> |
| </html> |