blob: 706fc025056877c9d38153cc81ad90cd48c09953 [file] [log] [blame]
<!--
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>The NuttX Simulation &mdash; 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="API Reference" href="../reference/index.html" />
<link rel="prev" title="Bottom-Half Interrupt Handlers" href="bottomhalf_interrupt.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 current"><a class="reference internal" href="index.html">Implementation Details</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="processes_vs_tasks.html">Linux Processes vs NuttX Tasks</a></li>
<li class="toctree-l2"><a class="reference internal" href="critical_sections.html">Critical Sections</a></li>
<li class="toctree-l2"><a class="reference internal" href="interrupt_controls.html">Per-Thread Interrupt Controls</a></li>
<li class="toctree-l2"><a class="reference internal" href="preemption_latency.html">Effects of Disabling Interrupts or Pre-Emption on Response Latency</a></li>
<li class="toctree-l2"><a class="reference internal" href="bottomhalf_interrupt.html">Bottom-Half Interrupt Handlers</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">The NuttX Simulation</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#how-the-simulator-is-built">How the Simulator is Built</a></li>
<li class="toctree-l3"><a class="reference internal" href="#the-nuttx-rel-blob">The nuttx.rel Blob</a></li>
<li class="toctree-l3"><a class="reference internal" href="#the-hostobj-blob">The $(HOSTOBJ) Blob</a></li>
<li class="toctree-l3"><a class="reference internal" href="#accessing-host-devices-using-fifos">Accessing Host Devices Using FIFOs?</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#general-concepts">General Concepts</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#toward-a-general-design">Toward a General Design</a></li>
<li class="toctree-l3"><a class="reference internal" href="#what-is-wrong-with-that">What is Wrong With That?</a></li>
<li class="toctree-l3"><a class="reference internal" href="#simulated-interrupts">Simulated Interrupts</a></li>
<li class="toctree-l3"><a class="reference internal" href="#supported-devices">Supported Devices</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#serial-console">Serial Console</a></li>
<li class="toctree-l4"><a class="reference internal" href="#host-file-system-access">Host File System Access</a></li>
<li class="toctree-l4"><a class="reference internal" href="#networking">Networking</a></li>
<li class="toctree-l4"><a class="reference internal" href="#usb">USB</a></li>
<li class="toctree-l4"><a class="reference internal" href="#lcd">LCD</a></li>
<li class="toctree-l4"><a class="reference internal" href="#smp">SMP</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</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"><a class="reference internal" href="../guides/index.html">Guides</a></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">Implementation Details</a></li>
<li class="breadcrumb-item active">The NuttX Simulation</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/implementation/simulation.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="the-nuttx-simulation">
<h1>The NuttX Simulation<a class="headerlink" href="#the-nuttx-simulation" title="Permalink to this heading"></a></h1>
<p>The NuttX simulation is a port of NuttX to run as a process under Linux or Cygwin and probably other POSIX contexts as well.</p>
<p>Reference: The <code class="docutils literal notranslate"><span class="pre">sim</span></code> configuration file <a class="reference internal" href="../platforms/sim/sim/index.html"><span class="doc">SIM</span></a>.</p>
<section id="how-the-simulator-is-built">
<h2>How the Simulator is Built<a class="headerlink" href="#how-the-simulator-is-built" title="Permalink to this heading"></a></h2>
<p>The simulator isn’t a virtual machine or anything like that. It is just a single thread that implements a non-preemptive version of NuttX using <code class="docutils literal notranslate"><span class="pre">setjmp</span></code>/<code class="docutils literal notranslate"><span class="pre">longjmp</span></code> to do the context switches.</p>
<figure class="align-center">
<img alt="../_images/simulation.png" src="../_images/simulation.png" />
</figure>
</section>
<section id="the-nuttx-rel-blob">
<h2>The nuttx.rel Blob<a class="headerlink" href="#the-nuttx-rel-blob" title="Permalink to this heading"></a></h2>
<p>The first thing that you have to understand is how the simulation is built.
Look at <code class="docutils literal notranslate"><span class="pre">arch/sim/src/Makefile</span></code>. This target builds the NuttX executable (simplified for clarity):</p>
<blockquote>
<div><div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">nuttx$(EXEEXT): nuttx.rel $(HOSTOBJS)</span>
<span class="gp"> $</span><span class="o">(</span>CC<span class="o">)</span><span class="w"> </span><span class="k">$(</span>CCLINKFLAGS<span class="k">)</span><span class="w"> </span><span class="k">$(</span>LIBPATHS<span class="k">)</span><span class="w"> </span>-o<span class="w"> </span><span class="k">$(</span>TOPDIR<span class="k">)</span>/<span class="nv">$@</span><span class="w"> </span>nuttx.rel<span class="w"> </span><span class="k">$(</span>HOSTOBJS<span class="k">)</span><span class="w"> </span><span class="k">$(</span>DRVLIB<span class="k">)</span><span class="w"> </span><span class="k">$(</span>STDLIBS<span class="k">)</span>
</pre></div>
</div>
</div></blockquote>
<p>The secret is <code class="docutils literal notranslate"><span class="pre">nuttx.rel</span></code>. That is a blob that contains the entire Nuttx simulation.
It is built like this:</p>
<blockquote>
<div><div class="highlight-console notranslate"><div class="highlight"><pre><span></span>
</pre></div>
</div>
<dl class="simple">
<dt>nuttx.rel<span class="classifier">libarch$(LIBEXT) board/libboard$(LIBEXT) $(HOSTOS)-names.dat $(LINKOBJS)</span></dt><dd><p>$(LD) -r $(LDLINKFLAGS) $(RELPATHS) $(EXTRA_LIBPATHS) -o $&#64; $(REQUIREDOBJS) –start-group $(RELLIBS) $(EXTRA_LIBS) –end-group
$(OBJCOPY) –redefine-syms=$(HOSTOS)-names.dat $&#64;</p>
</dd>
</dl>
</div></blockquote>
<p>The first <code class="docutils literal notranslate"><span class="pre">$(LD)</span></code> builds a partially linked, relocatable object (hence, the extension <code class="docutils literal notranslate"><span class="pre">.rel</span></code>). This contains all of the NuttX objects. So <code class="docutils literal notranslate"><span class="pre">nuttx.rel</span></code> is the entire “fish bowl” that the NuttX simulation lives.</p>
<p>The second <code class="docutils literal notranslate"><span class="pre">$(OBJCOPY)</span></code> line is the thing the irrevocable severs the NuttX “fish bowl” from the host environment. It renames most of the symbols in <code class="docutils literal notranslate"><span class="pre">nuttx.rel</span></code> so that they do not collide with the symbols use by the host system. Look in <code class="docutils literal notranslate"><span class="pre">arch/sim/src/nuttx-names.dat</span></code>. So <code class="docutils literal notranslate"><span class="pre">open()</span></code> becomes <code class="docutils literal notranslate"><span class="pre">NXopen()</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code> becomes <code class="docutils literal notranslate"><span class="pre">NXclose()</span></code>, read becomes <code class="docutils literal notranslate"><span class="pre">NXread()</span></code>, etc.</p>
</section>
<section id="the-hostobj-blob">
<h2>The $(HOSTOBJ) Blob<a class="headerlink" href="#the-hostobj-blob" title="Permalink to this heading"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">$(HOSTOBJS)</span></code> contains the final host interface. This is the host PC blob and in this one, there is no re-naming: <code class="docutils literal notranslate"><span class="pre">open()</span></code> goes to the real system <code class="docutils literal notranslate"><span class="pre">open()</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code> goes to the real system <code class="docutils literal notranslate"><span class="pre">close()</span></code>, etc. When these two blobs are linked together in the final <code class="docutils literal notranslate"><span class="pre">$(CC</span></code>, you have the simulation.</p>
</section>
<section id="accessing-host-devices-using-fifos">
<h2>Accessing Host Devices Using FIFOs?<a class="headerlink" href="#accessing-host-devices-using-fifos" title="Permalink to this heading"></a></h2>
<section id="general-concepts">
<h3>General Concepts<a class="headerlink" href="#general-concepts" title="Permalink to this heading"></a></h3>
<p>When you write the code in the simulation, it runs in the NuttX blob and can only interface with NuttX interfaces. It cannot interact directly with the host system. It cannot <code class="docutils literal notranslate"><span class="pre">open()</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code>, <code class="docutils literal notranslate"><span class="pre">read()</span></code>, or access a host device driver in any way (because it cannot get to the host system namespace).</p>
<p>To further complicate things, nothing in the simulation can call into a host interface that blocks. Why? Because this is not a NuttX blocking call, this is a host system blocking call. It just not block that one NuttX thread; it blocks the entire simulation!</p>
<p>But you can add special, low level interface between the NuttX and the Host blobs so that they can communicate. The Host blob could access the host device in some and provide some authentic NuttX driver interface to the simulation in some fashion.</p>
<p>If you want to access a host device driver, then the code that does that has to reside in the Host blob (i.e., it is in <code class="docutils literal notranslate"><span class="pre">$(HOSTOS</span></code>)). Only there can it interact with the host OS. And there, you can do things like create a host pthread to service a device interface. That pthread can wait for I/O without blocking the whole simulation on the main thread (that is how the simulated console I/O works, for example).</p>
</section>
</section>
<section id="toward-a-general-design">
<h2>Toward a General Design<a class="headerlink" href="#toward-a-general-design" title="Permalink to this heading"></a></h2>
<p>There is no design in place for accessing Host devices from the simulation. Here are some directions that I would investigate, however.</p>
<p>Perhaps you could create a NuttX FIFO in the NuttX blob. It would reside at, say, <code class="docutils literal notranslate"><span class="pre">/dev/mydevice</span></code> in the NuttX VFS. Perhaps this FIFO could be used in the NuttX world as your character device? Perhaps it could read and write from FIFOs to intermediate the interaction with the host PC device?</p>
<p>On the NuttX side the target logic would call <code class="docutils literal notranslate"><span class="pre">open()</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code>, <code class="docutils literal notranslate"><span class="pre">read()</span></code>, … to access the FIFO. These are, of course, really <code class="docutils literal notranslate"><span class="pre">NXopen()</span></code>, <code class="docutils literal notranslate"><span class="pre">NXclose()</span></code>, <code class="docutils literal notranslate"><span class="pre">NXread()</span></code>, …</p>
<p>On the Host PC side it would call <code class="docutils literal notranslate"><span class="pre">open()</span></code>, <code class="docutils literal notranslate"><span class="pre">close()</span></code>, <code class="docutils literal notranslate"><span class="pre">read()</span></code>, .. to access the host device driver. These are real host device accesses. But some code in the host blob should also be able to call <code class="docutils literal notranslate"><span class="pre">NXopen()</span></code>, <code class="docutils literal notranslate"><span class="pre">NXclose()</span></code>, <code class="docutils literal notranslate"><span class="pre">NXwrite()</span></code>, etc. to access the NuttX FIFO. So there might be a pthread in the host blob that does something like this:</p>
<ol class="arabic simple">
<li><p>Open a real PC device O_RDONLY using open()</p></li>
<li><p>Open a FIFO in using NXopen()</p></li>
<li><p>Read from the device using read(). This blocks, but only the host pthread that is intermediating the I/O.</p></li>
<li><p>When read data is obtained, call NXwrite() to write the data to the NuttX FIFO</p></li>
<li><p>etc.</p></li>
</ol>
<p>In this way, the pthread in the host blob would be conduit that maps the host device to a NuttX FIFO. Within the NuttX blob, simulation logic should be able to open, close, read, etc. the FIFO just as though it were the real device.</p>
<blockquote>
<div><p>NuttX Target Code &lt;—&gt;NuttX FIFO&lt;—&gt;Host Interface&lt;—-&gt;Host Driver</p>
</div></blockquote>
</section>
<section id="what-is-wrong-with-that">
<h2>What is Wrong With That?<a class="headerlink" href="#what-is-wrong-with-that" title="Permalink to this heading"></a></h2>
<p>There is a one big problem: if logic in the Host blob calls <code class="docutils literal notranslate"><span class="pre">NXwrite()</span></code>, that could potentially cause a NuttX context switch. Remember that a context switch is really a <code class="docutils literal notranslate"><span class="pre">setjmp()</span></code> that saves the current context followed by a <code class="docutils literal notranslate"><span class="pre">longjmp()</span></code> that switches to the new context. All of this must happen on the main thread of the simulation.</p>
<p>But if <code class="docutils literal notranslate"><span class="pre">NXwrite()</span></code> causes a context switch, then the switch would occur on the pthread of the Host device handler! That would be very bad. The Host driver could not return until all of the NuttX tasks finally terminate. That would need to be avoided.</p>
<p>The NuttX serial console interface faces all of these same problems: It simulates a NuttX device, <code class="docutils literal notranslate"><span class="pre">/dev/console</span></code> using the Host <code class="docutils literal notranslate"><span class="pre">stdin</span></code> and <code class="docutils literal notranslate"><span class="pre">stdout</span></code>. How does it avoid this problem? Not in a very pretty way. It puts the received data in a FIFO; When all of the NuttX tasks become IDLE the simulations IDLE thread runs, it empties the queued data to the console which can then cause a context switch. But now this is okay because the IDLE thread is correctly running on the main thread of the simulation.</p>
<p>Pretty kludgey. This just begs for a better solution. If only the simulation supported interrupts…</p>
</section>
<section id="simulated-interrupts">
<h2>Simulated Interrupts<a class="headerlink" href="#simulated-interrupts" title="Permalink to this heading"></a></h2>
<p>The current NuttX host simulation has no interrupts and, hence, is non-preemptible. Also, without simulated interrupts, there can be no high-fidelity simulated device drivers or precise timer interrupt.</p>
<p>Currently, all timing and serial input is simulated in the IDLE loop: When nothing is going on in the simulation, the IDLE loop runs and fakes timer and UART events.</p>
<p>I have been thinking about how to implement simulated interrupts in the simulation. I think a solution would work like this.</p>
<blockquote>
<div><ul>
<li><p>In the earliest initialization, simulator could start a host simulation interrupt thread and setup a signal handler to catch signals on the main thread. One signal, say <code class="docutils literal notranslate"><span class="pre">SIGUSER</span></code> could indicate a context switch. This would be a type <code class="docutils literal notranslate"><span class="pre">SA_SIGINFO</span></code> and the context switch information would be provided in the <code class="docutils literal notranslate"><span class="pre">sival_t</span></code> field of the <code class="docutils literal notranslate"><span class="pre">siginfo</span></code>.</p></li>
<li><p>Interrupt logic could be implemented on a host pthread. The host pthread, like a hardware interrupt, executes asynchronously outside of the operating system. The interrupt thread could wait for a host signal or a host message and, upon receipt, perform simulated interrupt logic.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">up_interrupt_context()</span></code> would need to be implemented; it is only a stub now. I think this could be done with a simple global boolean like:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span>
</pre></div>
</div>
<p>bool g_in_interrupt;
xcpt_reg_t g_context_regs;</p>
</li>
</ul>
</div></blockquote>
<p>Simulated interrupt handling logic would set <code class="docutils literal notranslate"><span class="pre">g_in_interrupt</span></code> on entry and clear it on exit (perhaps it would be better to have a counter and increment it interrupt entry and decrement it on exit?). The interrupt handler would also need to clear <code class="docutils literal notranslate"><span class="pre">g_context_regs</span></code> on entry. <code class="docutils literal notranslate"><span class="pre">up_interrupt_contest()</span></code> would then just report the state of the boolean.</p>
<blockquote>
<div><ul class="simple">
<li><p>All context switching functions would also need to check this boolean (<code class="docutils literal notranslate"><span class="pre">up_block_task()</span></code>, <code class="docutils literal notranslate"><span class="pre">up_unblock_task()</span></code>, <code class="docutils literal notranslate"><span class="pre">up_reprioritize_rtr()</span></code>, <code class="docutils literal notranslate"><span class="pre">up_releasepending()</span></code> and perhaps others). It set, they should not perform the context switch. Instead, they should set <code class="docutils literal notranslate"><span class="pre">g_context_regs</span></code> to the context switch register array.</p></li>
</ul>
<blockquote>
<div><ul class="simple">
<li><p>Before <em>returning</em> and before clearing <code class="docutils literal notranslate"><span class="pre">g_in_interrupt</span></code>, the host simulated interrupt logic would check <code class="docutils literal notranslate"><span class="pre">g_context_regs</span></code>. If non-NULL, then a context switch is required on <em>return</em> from the simulated interrupt. In this case, the simulation thread would signal the main thread with the <code class="docutils literal notranslate"><span class="pre">SIGUSER</span></code> signal.</p></li>
<li><p>The <code class="docutils literal notranslate"><span class="pre">SIGUSER</span></code> signal handler would perform the context with logic something like the following:</p></li>
</ul>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span><span class="w"> </span><span class="nc">tcb_s</span><span class="w"> </span><span class="o">*</span><span class="n">rtcb</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sched_self</span><span class="p">();</span><span class="w"> </span><span class="cm">/* Get the TCB of the currently executing thread */</span>
<span class="n">xcpt_reg_t</span><span class="w"> </span><span class="o">*</span><span class="n">regs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">siginfo</span><span class="o">-&gt;</span><span class="n">si_value</span><span class="p">.</span><span class="n">sival_ptr</span><span class="p">;</span><span class="w"> </span><span class="cm">/* The new register state to be instantiated */</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">up_setjump</span><span class="p">(</span><span class="n">rtcb</span><span class="o">-&gt;</span><span class="n">xcp</span><span class="p">.</span><span class="n">regs</span><span class="p">)</span><span class="w"> </span><span class="cm">/* Save the current context */</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">up_longjmp</span><span class="p">(</span><span class="n">regs</span><span class="p">);</span><span class="w"> </span><span class="cm">/* Instantiate the new context */</span>
<span class="w"> </span><span class="p">}</span>
</pre></div>
</div>
</div></blockquote>
</div></blockquote>
<p>When we switch back to this thread, or course, it will appear as another return from <code class="docutils literal notranslate"><span class="pre">up_setjmp()</span></code>, but this time with a non-zero return value.</p>
<p>The threading is a little mind-bending. The signal handler needs to run in the context on the main thread. The main thread is actually using the allocation NuttX stack and is executed the NuttX code. When the signal handler executes, it should execute on a stack frame added to the stack of the currently executing NuttX task.</p>
<p>When <code class="docutils literal notranslate"><span class="pre">up_longjmp()</span></code> is executing, operation will continue under the main thread, but the context including the stack are different for the new NuttX thread. When the context finally switches back to this thread, it will appear as an appear return from <code class="docutils literal notranslate"><span class="pre">up_setjmp()</span></code> with a non-zero return value. In that case, the signal handler will just return and the normal execution of the pre-empted NuttX task will resume.</p>
<p><strong>Issues</strong>. My only real technical questions involve signal masking. When the <code class="docutils literal notranslate"><span class="pre">SIGUSER</span></code> signal handler executes, the <code class="docutils literal notranslate"><span class="pre">SIGUSER</span></code> interrupt will be masked. That would prevent any further context switches until the signal handler returns. Can we simply <em>unmask</em> <code class="docutils literal notranslate"><span class="pre">SIGUSER</span></code> signal to get more context switches? I would need to experiment to know for sure.</p>
</section>
<section id="supported-devices">
<h2>Supported Devices<a class="headerlink" href="#supported-devices" title="Permalink to this heading"></a></h2>
<section id="serial-console">
<h3>Serial Console<a class="headerlink" href="#serial-console" title="Permalink to this heading"></a></h3>
<p>The simulation’s serial console is provided by wrapping host <em>stdin</em> and <em>stdout</em> so that it appears to be <code class="docutils literal notranslate"><span class="pre">/dev/console</span></code>. Serial data from the host <em>stdin</em> is sampled in the IDLE loop. If serial data is available, the IDLE loop will <em>post</em> simulated UART activity. The fidelity of this simulation could be improved with simulated interrupts when UART data is avaiable.</p>
</section>
<section id="host-file-system-access">
<h3>Host File System Access<a class="headerlink" href="#host-file-system-access" title="Permalink to this heading"></a></h3>
<p>Host file system access is supported via the <em>nxfuse</em> user-space file system that you can find in the NuttX <a class="reference external" href="https://bitbucket.org/nuttx/tools/src/master/nxfuse/">https://bitbucket.org/nuttx/tools/src/master/nxfuse/</a> repository. Instructions for using the <em>nxfuse</em> file system can be found in a <a class="reference external" href="https://bitbucket.org/nuttx/tools/src/master/nxfuse/README.txt">https://bitbucket.org/nuttx/tools/src/master/nxfuse/README.txt</a> in that repository directory.</p>
</section>
<section id="networking">
<h3>Networking<a class="headerlink" href="#networking" title="Permalink to this heading"></a></h3>
<p>Networking is supported for the simulation using TUN/TAP interface under Linux or using WPCap under Windows. A README file providing instruction for setting up the TUN/TAP interface under Linux is provided in the <a class="reference internal" href="../platforms/sim/sim/index.html"><span class="doc">SIM</span></a>. The network is again handled by the IDLE loop in the simulator and could benefit from simulated interrupts.</p>
</section>
<section id="usb">
<h3>USB<a class="headerlink" href="#usb" title="Permalink to this heading"></a></h3>
<p>At one time, there was an effort underway on GitHub to port <code class="docutils literal notranslate"><span class="pre">libusb</span></code> into NuttX in order to support USB devices in the simulation. That effort was never completed although is it still a very good idea.</p>
</section>
<section id="lcd">
<h3>LCD<a class="headerlink" href="#lcd" title="Permalink to this heading"></a></h3>
<p>X11 framebuffers can be used to simulate NuttX graphics framebuffer devices. These are, again, managed in the IDLE loop.</p>
</section>
<section id="smp">
<h3>SMP<a class="headerlink" href="#smp" title="Permalink to this heading"></a></h3>
<p>There is a simulator configuration has basic support for SMP testing. The simulation supports the emulation of multiple CPUs by creating multiple pthreads, each run a copy of the simulation in the same process address space.</p>
<p>At present, the SMP simulation is not fully functional: It does operate on the simulated CPU threads for a few context switches then fails during a setjmp() operation. I suspect that this is not an issue with the NuttX SMP logic but more likely some chaos in the pthread controls. I have seen similar such strange behavior other times that I have tried to use setjmp/longmp from a signal handler! Like when I tried to implement simulated interrupts using signals.</p>
<p>Apparently, if longjmp is invoked from the context of a signal handler, the result is undefined: <a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1318.htm">http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1318.htm</a></p>
<p>You can enable SMP for ostest configuration by enabling:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Add:<span class="w"> </span><span class="nv">CONFIG_SPINLOCK</span><span class="o">=</span>y
Add:<span class="w"> </span><span class="nv">CONFIG_SMP</span><span class="o">=</span>y
Add:<span class="w"> </span><span class="nv">CONFIG_SMP_NCPUS</span><span class="o">=</span><span class="m">2</span>
Add:<span class="w"> </span><span class="nv">CONFIG_SMP_IDLETHREAD_STACKSIZE</span><span class="o">=</span><span class="m">2048</span>
</pre></div>
</div>
<p>You also must enable near-realtime-performance otherwise even long timeouts will expire before a CPU thread even has a chance to execute.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Remove:<span class="w"> </span><span class="c1"># CONFIG_SIM_WALLTIME is not set</span>
Add:<span class="w"> </span><span class="nv">CONFIG_SIM_WALLTIME</span><span class="o">=</span>y
</pre></div>
</div>
<p>And you can enable some additional debug output with:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Remove:<span class="w"> </span><span class="c1"># CONFIG_DEBUG_SCHED is not set</span>
Add:<span class="w"> </span><span class="nv">CONFIG_DEBUG_SCHED</span><span class="o">=</span>y
Remove:<span class="w"> </span><span class="c1"># CONFIG_SCHED_INSTRUMENTATION is not set</span>
Add:<span class="w"> </span><span class="nv">CONFIG_SCHED_INSTRUMENTATION</span><span class="o">=</span>y
</pre></div>
</div>
<p>The SMP configuration will run with:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">CONFIG_SMP_NCPUS</span><span class="o">=</span><span class="m">1</span>
</pre></div>
</div>
<p>In this case there is, of course, no multi-CPU processing, but this does verify the correctness of some the basic SMP logic in a simpler environment.</p>
<p>The NSH configuration can also be forced to run SMP, but suffers from the same quirky behavior. It can be made reliable if you modify <code class="docutils literal notranslate"><span class="pre">arch/sim/src/up_idle.c</span></code> so that the IDLE loop only runs for CPU0. Otherwise, often <code class="docutils literal notranslate"><span class="pre">simuart_post()</span></code> will be called from CPU1 and it will try to restart NSH on CPU0 and, again, the same quirkiness occurs.</p>
<p>But for example, this command:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>nsh&gt;<span class="w"> </span>sleep<span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="p">&amp;</span>
</pre></div>
</div>
<p>will execute the sleep command on CPU1 which has worked every time that I have tried it (which is not too many times).</p>
</section>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="bottomhalf_interrupt.html" class="btn btn-neutral float-left" title="Bottom-Half Interrupt Handlers" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="../reference/index.html" class="btn btn-neutral float-right" title="API Reference" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, The Apache Software Foundation.</p>
</div>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>