You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pr...@apache.org on 2020/09/04 23:02:42 UTC

[incubator-nuttx] 01/10: add sim and drivers guides, contributing workflow

This is an automated email from the ASF dual-hosted git repository.

protobits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 56b89a89f20fb78490c945e4c9f582db8863ff17
Author: Adam Feuer <ad...@adamfeuer.com>
AuthorDate: Sun Aug 30 17:48:30 2020 -0700

    add sim and drivers guides, contributing workflow
---
 Documentation/contributing/coding_style.rst   |   3 +
 Documentation/contributing/index.rst          |   1 +
 Documentation/contributing/making-changes.rst | 256 ++++++++++++++++++++++++++
 Documentation/guides/drivers.rst              | 211 +++++++++++++++++++++
 Documentation/guides/index.rst                |   2 +
 Documentation/guides/simulator.rst            | 145 +++++++++++++++
 6 files changed, 618 insertions(+)

diff --git a/Documentation/contributing/coding_style.rst b/Documentation/contributing/coding_style.rst
index 5f0aeda..d83910d 100644
--- a/Documentation/contributing/coding_style.rst
+++ b/Documentation/contributing/coding_style.rst
@@ -1,4 +1,7 @@
 =================
+.. include:: /substitutions.rst
+.. _coding-standard:
+
 C Coding Standard
 =================
 
diff --git a/Documentation/contributing/index.rst b/Documentation/contributing/index.rst
index a69411b..b2428f0 100644
--- a/Documentation/contributing/index.rst
+++ b/Documentation/contributing/index.rst
@@ -8,6 +8,7 @@ and documentation (the one you are reading now):
    :maxdepth: 2
 
    workflow.rst
+   making-changes.rst
    coding_style.rst
    documentation.rst
 
diff --git a/Documentation/contributing/making-changes.rst b/Documentation/contributing/making-changes.rst
new file mode 100644
index 0000000..0c9c871
--- /dev/null
+++ b/Documentation/contributing/making-changes.rst
@@ -0,0 +1,256 @@
+.. include:: /substitutions.rst
+.. _making-changes:
+
+Making Changes
+==============
+
+If you want to make changes to NuttX, for your own personal use, or to submit them back to project to improve NuttX,
+that's easy. For the purposes of this guide, you'll need a `GitHub <https://www.github.com>`_ account, since
+the Apache NuttX team uses GitHub. (You could also use git locally, or save your changes to other sites like
+`GitLab <https://about.gitlab.com/>`_ or `BitBucket <https://bitbucket.org>`_, but that's beyond the scope of this
+guide).
+
+Here's how to do it:
+
+#. Set your git user name and email
+
+    .. code-block:: bash
+
+       $ cd nuttx/
+       $ git config --global user.name "Your Name"
+       $ git config --global user.email "yourname@somedomaincom"
+
+#. Sign in to GitHub
+
+   If you don't have a `GitHub <https://www.github.com>`_ account, it's free to
+   sign up.
+   |br|
+   |br|
+
+
+#. Fork the Project
+
+   Visit both these links and hit the Fork button in the upper right of the page:
+
+   * `NuttX <https://github.com/apache/incubator-nuttx/>`_
+   * `NuttX Apps <https://github.com/apache/incubator-nuttx-apps/>`_
+
+
+#. Change the Git Remotes
+
+   The git repositories in your project are currently connected to the official NuttX repositories, but you don't
+   have permission to push software there. But you can push them to your forks, and from there create Pull Requests
+   if you want to send them to the NuttX project.
+
+   First, remove the current remote, ``origin`` (we'll add it back later):
+
+    .. code-block:: bash
+
+       $ cd nuttx/
+       $ # display the remote
+       $ git remote -v
+
+   You should see something like this:
+
+    .. code-block:: bash
+
+       origin	https://github.com/apache/incubator-nuttx.git
+
+   Now, on the GitHub web page for your forked ``incubator-nuttx`` project, copy the clone url – get it by hitting the
+   green ``Clone or Download`` button in the upper right. Then do this:
+
+    .. code-block:: bash
+
+       $ git remote rm origin
+       $ git remote add origin <your forked incubator-nuttx project clone url>
+       $ git remote add upstream https://github.com/apache/incubator-nuttx.git
+
+   Do the same for your forked ``incubator-nuttx-apps`` project:
+
+    .. code-block:: bash
+
+       $ cd ../apps
+       $ git remote rm origin
+       $ git remote add origin <your forked incubator-nuttx-apps project clone url>
+       $ git remote add upstream https://github.com/apache/incubator-nuttx-apps.git
+
+
+#. Create a Local Git Branch
+
+   Now you can create local git branches and push them to GitHub:
+
+    .. code-block:: bash
+
+       $ git checkout -b test/my-new-branch
+       $ git push
+
+
+Git Workflow With an Upstream Repository
+----------------------------------------
+
+The main NuttX git repository is called an "upstream" repository - this is because it's the main source of truth, and
+its changes flow downstream to people who've forked that repository, like us.
+
+Working with an upstream repo is a bit more complex, but it's worth it since you can submit fixes and features
+to the main NuttX repos. One of the things you need to do regularly is keep your local repo in sync
+with the upstream. I work with a local branch, make changes, pull new software from the upstream and merge it in,
+maybe doing that several times. Then when everything works, I get my branch ready to do a Pull Request. Here's how:
+
+#. Fetch upstream changes and merge into my local master:
+
+    .. code-block:: bash
+
+       $ git checkout master
+       $ git fetch upstream
+       $ git merge upstream/master
+       $ git push
+
+#. Merge my local master with my local branch:
+
+    .. code-block:: bash
+
+       $ git checkout my-local-branch
+       $ git merge master
+       $ git push
+
+#. Make changes and push them to my fork
+
+    .. code-block:: bash
+
+       $ vim my-file.c
+       $ git add my-file.c
+       $ git commit my-file.c
+       $ git push
+
+#. Repeat 1-3 as necessary
+
+#. Run the ``tools/checkpatch.sh`` script on your files
+
+   When your code runs, then you're almost ready to submit it. But first you need to check the code to ensure
+   that it conforms to the NuttX :ref:`contributing/coding_style:C Coding Standard`.
+   The ``tools/checkpatch.sh`` script will do that. Here's the usage info:
+
+    .. code-block:: bash
+
+       $ ./tools/checkpatch.sh -h
+       USAGE: ./tools/checkpatch.sh [options] [list|-]
+
+       Options:
+       -h
+       -c spell check with codespell(install with: pip install codespell
+       -r range check only (used with -p and -g)
+       -p <patch list> (default)
+       -g <commit list>
+       -f <file list>
+       -  read standard input mainly used by git pre-commit hook as below:
+          git diff --cached | ./tools/checkpatch.sh -
+
+   Run it against your files and correct all the errors in the code you added, so that
+   ``tools/checkpatch.sh`` reports no errors. Then commit the result.
+   For example:
+
+    .. code-block:: bash
+
+       $ ./tools/checkpatch.sh -f my-file.c
+       arch/arm/src/sama5/hardware/my-file.c:876:82: warning: Long line found
+       $ # fix errors
+       $ vim my-file.c
+       $ # run again
+       $ ./tools/checkpatch.sh -f my-file.c
+
+   If you have made a lot of changes, you can also use this bash commandline to see the errors for all the changed C
+   files in your branch (assumes you are currently on the branch that has the changed files):
+
+    .. code-block:: bash
+
+       $ git diff --name-only master | egrep "\.c|\.h" | xargs echo | xargs ./tools/checkpatch.sh -f | less
+
+   Note that there are some bugs in the ``nxstyle`` program that ``checkpatch.sh`` uses, so
+   it may report a few errors that are not actually errors. The committers will help you
+   find these. (Or view the
+   `nxstyle Issues <https://github.com/apache/incubator-nuttx/issues?q=is%3Aissue+is%3Aopen+nxstyle>`_.)
+   |br|
+   |br|
+
+#. Commit the fixed files
+
+    .. code-block:: bash
+
+       $ git add my-file.c
+       $ git commit my-file.c
+       $ git push
+
+
+Submitting Your Changes to NuttX
+--------------------------------
+
+  Pull requests let you tell others about changes you've pushed to a branch in a repository on GitHub. Once a pull
+  request is opened, you can discuss and review the potential changes with collaborators and add follow-up commits
+  before your changes are merged into the base branch.
+
+  (from GitHub's `About pull requests <https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests>`_ page)
+
+Before you do a Pull Request, the NuttX team will usually want all the changes you made in your branch "squashed" into
+a single commit, so that when they review your changes, there's a clean view of the history. If there are changes
+after Pull Request review feedback, they can be separate commits. Here's the easiest way I found to do that initial
+squash before submitting the Pull Request:
+
+#. Check out my branch
+
+    .. code-block:: bash
+
+       $ git checkout my-branch
+
+#. Rename it to ``my-branch-old`` to save it, because we're going to create new clean branch to push:
+
+    .. code-block:: bash
+
+       $ git branch -m my-branch-old
+
+#. Create a new clean branch with the same name you were using before the last step:
+
+    .. code-block:: bash
+
+       $ git checkout master
+       $ git checkout -b my-branch
+
+#. Merge your saved old branch into the new one, telling git to "squash" all your commits into one (note this will
+   not commit the result; the changed files will be in your staging area, ready to be committed):
+
+    .. code-block:: bash
+
+       $ git merge --squash my-branch-old
+
+#. Commit the result
+
+    .. code-block:: bash
+
+       $ git commit
+
+#. Force-push your new clean branch to the remote— this will overwrite all your previous changes in that branch:
+
+    .. code-block:: bash
+
+       $ git push -f --set-upstream origin my-branch
+
+#. Create a GitHub Pull Request
+
+   A Pull Request is how you ask your upstream to review and merge your changes.
+
+   Here's `GitHub's instructions for creating a Pull Request <https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request>`_.
+
+   |br|
+
+#. Get Pull Request feedback and implement changes
+
+   Get suggestions for improvements from reviewers, make changes, and push them to the branch. Once the reviewers are
+   happy, they may suggest squashing and merging again to make a single commit. In this case you would repeat steps
+   1 through 6.
+
+Git Resources
+-------------
+
+* `Git Cheat Sheet (by GitHub) <https://github.github.com/training-kit/downloads/github-git-cheat-sheet.pdf>`_
+* `Git Book (online) <https://git-scm.com/book/en/v2>`_
+* `NuttX Code Contribution Workflow <https://cwiki.apache.org/confluence/display/NUTTX/Code+Contribution+Workflow>`_ –
+  All the details are here if you need them!
diff --git a/Documentation/guides/drivers.rst b/Documentation/guides/drivers.rst
new file mode 100644
index 0000000..86586cb
--- /dev/null
+++ b/Documentation/guides/drivers.rst
@@ -0,0 +1,211 @@
+.. include:: /substitutions.rst
+.. _drivers:
+
+Drivers
+=======
+
+Some NuttX boards don't have full support for all the on-chip peripherals. If you need support for this hardware,
+you will either need to port a driver from another chip, or write one yourself. This section discusses how to do that.
+
+Porting a Driver
+----------------
+
+Often support for on-chip peripherals exists in a closely related chip, or even a different family or from a different
+manufacturer. Many chips are made up of different Intellectual Property (IP) blocks that are licensed from vendors like
+Cadence, Synopsys, and others. The IP blocks may be similar enough to use another chip's driver with little
+modification.
+
+* Find a similar driver in NuttX source code:
+
+  * Look at register names listed in the datasheet for the peripheral.
+  * Search the NuttX codebase for the register names (try several different ones).
+  * Note that you'll have to compare the datasheet to the header and code files to see if there are differences; there
+    will usually be some differences between architectures, and they can be significant.
+
+* Find a similar driver in U-Boot source code:
+
+  * Only for inspiration, you can't copy code because of license incompatibility.
+  * But you can debug to see how the driver works.
+  * `U-Boot <https://www.denx.de/wiki/U-Boot>`_ drivers are often easier to understand than BSD Unix drivers because
+    U-Boot is simpler.
+
+* Find a similar driver in Zephyr or BSD Unix (OpenBSD, FreeBSD, NetBSD):
+
+  * If you find one, you can borrow code directly (Apache 2.0 and BSD licenses are compatible).
+
+* Understanding how the driver works
+
+  Here are a couple of techniques that helped me.
+
+    * printf debugging
+
+      * Sprinkle ``custinfo()`` logging statements through your code to see execution paths and look at variables
+        while the code is running. The reason to use ``custinfo()`` as opposed to the other logging shortcuts
+        (``mcinfo()``, etc.) is that you can turn on and off other other logging and still see your custom debug
+        logging. Sometimes it's useful to quiet the flood of logging that comes from a particular debug logging
+        shortcut.
+      * Note that printing info to the console will affect timing.
+      * Keep a file with just your debug settings in it, like this (``debugsettings``):
+
+        .. code-block:: c
+
+           CONFIG_DEBUG_CUSTOM_INFO=y
+           (etc..)
+
+      * Add the settings to the end of your ``.config`` file after running ``make menuconfig`` (that will reorder
+        the file, making it harder to see and change the debug settings if you need to).
+
+        .. code-block:: bash
+
+           $ cat .config debugsettings > .config1 ; mv .config1 .config
+
+      * If you are using interrupts and threads (many things in NuttX run in different threads as a response to interrupts),
+        you can use printf debugging to see overlapping execution.
+
+        * Interrupts - here's how to inspect the C stack frame to see what execution environment is currently running:
+
+          .. code-block:: c
+
+            uint32_t frame = 0;  /* MUST be the very first thing in the function */
+            uint32_t p_frame;
+            frame++;             /* make sure that frame doesn't get optimized out */
+            p_frame = (uint32_t)(&frame);
+            custinfo("p_frame: %08x\n", p_frame);
+
+        * Threads - here's how to get the thread identifier to see which thread is currently executing:
+
+          .. code-block:: c
+
+            pthread_t thread_id = pthread_self();
+            custinfo("pthread_id: %08x\n", thread_id);
+
+      * stack frame printf
+      * thread printf
+
+    * `GDB — the Gnu Debugger <https://www.gnu.org/software/gdb/>`_
+
+      GDB is a great tool. In this guide we've already used it to load our program and run it. But it can do a lot
+      more. You can single-step through code, examine variables and memory, set breakpoints, and more. I generally use
+      it from the commandline, but have also used it from an IDE like JetBrains' Clion, where it's easier to see the
+      code context.
+
+      One add-on that I found to be essential is the ability to examine blocks of memory, like buffers that NuttX uses
+      for reading and writing to storage media or network adapters. This `Stack Overflow question on using GDB to
+      examine memory <https://stackoverflow.com/a/54784260/431222>`_ includes a GDB command that is very handy. Add
+      this to your ``.gdbinit`` file, and then use the ``xxd`` command to dump memory in an easy-to-read format:
+
+      .. code-block::
+
+         define xxd
+           if $argc < 2
+             set $size = sizeof(*$arg0)
+           else
+             set $size = $arg1
+           end
+           dump binary memory dump.bin $arg0 ((void *)$arg0)+$size
+           eval "shell xxd -o %d dump.bin; rm dump.bin", ((void *)$arg0)
+         end
+         document xxd
+           Dump memory with xxd command (keep the address as offset)
+
+           xxd addr [size]
+             addr -- expression resolvable as an address
+             size -- size (in byte) of memory to dump
+                     sizeof(*addr) is used by default end
+
+      Here's a short GDB session that shows what this looks like in practice. Note that the memory location being
+      examined (``0x200aa9eo`` here) is a buffer being passed to ``mmcsd_readsingle``:
+
+      .. code-block::
+
+        Program received signal SIGTRAP, Trace/breakpoint trap.
+        0x200166e8 in up_idle () at common/arm_idle.c:78
+        78	}
+        (gdb) b mmcsd_readsingle
+        Breakpoint 1 at 0x2006ea70: file mmcsd/mmcsd_sdio.c, line 1371.
+        (gdb) c
+        Continuing.
+
+        Breakpoint 1, mmcsd_readsingle (priv=0x200aa8c0, buffer=0x200aa9e0 "WRTEST  TXT \030", startblock=2432) at mmcsd/mmcsd_sdio.c:1371
+        1371	  finfo("startblock=%d\n", startblock);
+        (gdb) xxd 0x200aa9e0 200
+        200aa9e0: 5752 5445 5354 2020 5458 5420 1800 0000  WRTEST  TXT ....
+        200aa9f0: 0000 0000 0000 0000 0000 5500 1100 0000  ..........U.....
+        200aaa00: 5752 5445 5354 3520 5458 5420 1800 0000  WRTEST5 TXT ....
+        200aaa10: 0000 0000 0000 0000 0000 5800 1500 0000  ..........X.....
+        200aaa20: e552 5445 5854 3620 5458 5420 1800 0000  .RTEXT6 TXT ....
+        200aaa30: 0000 0000 0000 0000 0000 5600 1200 0000  ..........V.....
+        200aaa40: 5752 5445 5354 3620 5458 5420 1800 0000  WRTEST6 TXT ....
+        200aaa50: 0000 0000 0000 0000 0000 5600 1200 0000  ..........V.....
+        200aaa60: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+        200aaa70: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+        200aaa80: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+        200aaa90: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+        200aaaa0: 0000 0000 0000 0000                      ........
+
+
+NuttX Drivers as a Reference
+----------------------------
+
+If you're not porting a NuttX driver from another architecture, it still helps to look at other similar NuttX
+drivers, if there are any. For instance, when implementing an Ethernet driver, look at other NuttX Ethernet drivers;
+for an SD Card driver, look at other NuttX Ethernet drivers. Even if the chip-specific code won't be the same, the
+structure to interface with NuttX can be used.
+
+Using Chip Datasheets
+---------------------
+
+To port or write a driver, you'll have to be familiar with the information in the chip datasheet. Definitely find
+the datasheet for your chip, and read the sections relevant to the peripheral you're working with. Doing so ahead
+of time will save a lot of time later.
+
+Another thing that's often helpful is to refer to sample code provided by the manufacturer, or driver code from
+another operating system (like U-Boot, Zephyr, or FreeBSD) while referring to the datasheet — seeing how working
+code implements the necessary algorithms often helps one understand how the driver needs to work.
+
+* How to use a datasheet
+
+  Key pieces of information in System-on-a-Chip (SoC) datasheets are usually:
+
+  * Chip Architecture Diagram — shows how the subsections of the chip (CPU, system bus, peripherals, I/O, etc.) connect
+    to each other.
+  * Memory Map — showing the location of peripheral registers in memory. This info usually goes into a header file.
+  * DMA Engine — if Direct Memory Access (DMA) is used, this may have info on how to use it.
+  * Peripheral — the datasheet usually has a section on how the peripheral works. Key parts of this include:
+
+    * Registers List — name and offset from the base memory address of the peripheral. This needs to go into a header
+      file.
+    * Register Map — what is the size of each register, and what do the bits mean? You will need to create ``#defines``
+      in a header file that your code will use to operate on the registers. Refer to other driver header files for
+      examples.
+
+`Logic analyzers <https://en.wikipedia.org/wiki/Logic_analyzer>`_
+-----------------------------------------------------------------
+
+For drivers that involve input and output (I/O), especially that involve complex protocols like SD Cards, SPI, I2C,
+etc., actually seeing the waveform that goes in and out the chip's pins is extremely helpful. Logic analyzers can
+capture that information and display it graphically, allowing you to see if the driver is doing the right thing
+on the wire.
+
+DMA Debugging
+-------------
+
+* Dump registers before, during, and after transfer. Some NuttX drivers (``sam_sdmmc.c`` or ``imxrt_sdmmc.c`` for
+  example) have built-in code for debugging register states, and can sample registers before, during, and
+  immediately after a DMA transfer, as well as code that can dump the peripheral registers in a nicely-formatted
+  way onto the console device (which can be a serial console, a network console, or memory). Consider using something
+  like this to see what's happening inside the chip if you're trying to debug DMA transfer code.
+* Compare register settings to expected settings determined from the datasheet or from dumping registers from working
+  code in another operating system (U-Boot, Zephyr, FreeBSD, etc.).
+* Use the ``xxd`` GDB tool mentioned above to dump NuttX memory buffers before, during, and after a transfer to see if
+  data is being transferred correctly, if there are over- or under-runs, or to diagnose data being stored in incorrect
+  locations.
+* printf debugging register states can also help here.
+* Remember that logging can change the timing of any algorithms you might be using, so things may start or stop
+  working when logging is added or removed. Definitely test with logging disabled.
+
+
+
+
+
+
diff --git a/Documentation/guides/index.rst b/Documentation/guides/index.rst
index c592db1..74f7873 100644
--- a/Documentation/guides/index.rst
+++ b/Documentation/guides/index.rst
@@ -7,3 +7,5 @@ Guides
 .. toctree::
   nfs.rst
   usbtrace.rst
+  simulator.rst
+  drivers.rst
diff --git a/Documentation/guides/simulator.rst b/Documentation/guides/simulator.rst
new file mode 100644
index 0000000..4340492
--- /dev/null
+++ b/Documentation/guides/simulator.rst
@@ -0,0 +1,145 @@
+.. include:: /substitutions.rst
+.. _simulator:
+
+Simulator
+=========
+
+Apache NuttX has a simulator that can run as a regular program on Linux, Mac, and Windows computers.
+It's useful for debugging operating system features that aren't associated with particular
+device drivers— for instance the TCP/IP stack itself, a web interface or API for your
+application, or other communication protocols. It's also handy for trying out Apache NuttX without
+having a piece of embedded hardware.
+
+This guide assumes you're on Linux. It works on Windows and Mac too— if you know how,
+submit a PR the NuttX Companion to update this guide!
+
+Compiling
+---------
+
+#. Configure the Simulator
+
+   There are a lot of simulator configurations available that set you up to test various
+   operating system features.
+
+   Here we'll use the ``sim:tcpblaster`` configuration because it comes with networking
+   that is ready to use.
+
+    .. code-block:: bash
+
+       $ cd nuttx
+       $ ./tools/configure.sh sim:tcpblaster
+
+#. Compile
+
+    .. code-block:: bash
+
+       $ make clean; make
+
+Running
+-------
+
+#. Give the Simulator Privileges
+
+   On recent Linux distributions, you need to give the ``nuttx`` program the capabilities
+   (similar to permissions) to access the network:
+
+    .. code-block:: bash
+
+       $ sudo setcap cap_net_admin+ep ./nuttx
+
+#. Run the simulator:
+
+    .. code-block:: bash
+
+       $ ./nuttx
+
+#. Bring Up the Network Interfaces
+
+   On Apache NuttX:
+
+    .. code-block:: bash
+
+       nsh> ifup eth0
+
+   On Linux, first you need to find your main network interface— this will usually either
+   be an ethernet or wireless network adapter. Do this:
+
+    .. code-block:: bash
+
+       $ ifconfig
+       lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
+               inet 127.0.0.1  netmask 255.0.0.0
+               inet6 ::1  prefixlen 128  scopeid 0x10<host>
+               loop  txqueuelen 1000  (Local Loopback)
+               RX packets 5846  bytes 614351 (614.3 KB)
+               RX errors 0  dropped 0  overruns 0  frame 0
+               TX packets 5846  bytes 614351 (614.3 KB)
+               TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
+
+       wlp0s20f3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
+               inet 192.168.1.209  netmask 255.255.255.0  broadcast 192.168.1.255
+               inet6 fe80::1161:c26b:af05:d784  prefixlen 64  scopeid 0x20<link>
+               ether 24:41:8c:a8:30:d1  txqueuelen 1000  (Ethernet)
+               RX packets 219369  bytes 176416490 (176.4 MB)
+               RX errors 0  dropped 0  overruns 0  frame 0
+               TX packets 108399  bytes 27213617 (27.2 MB)
+               TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
+
+   ``lo0`` is the Loopback Interface, so ``wlp0s20f3`` is the wireless interface. Note
+   that it has an IP address on the local net. There may be other interfaces listed, you'll
+   need to pick the one that's right for your system.
+
+   Then, on Linux do this to set up the tap network interface and route that will let
+   the Apache Nuttx simulator access the network:
+
+    .. code-block:: bash
+
+       $ sudo ./tools/simhostroute.sh wlp0s20f3 on
+       $ ping -c 1 10.0.1.2  # nuttx system
+       PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
+       64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=7.52 ms
+
+       --- 10.0.1.2 ping statistics ---
+       1 packets transmitted, 1 received, 0% packet loss, time 0ms
+       rtt min/avg/max/mdev = 7.529/7.529/7.529/0.000 m
+
+#. Test that Apache NuttX can access the Internet
+
+   First let's ping the network interface of our Linux host to prove we can see the
+   gateway to the Internet:
+
+    .. code-block:: bash
+
+       nsh> ping -c 1 10.0.1.1
+       nsh> ping -c 1 10.0.1.1
+       PING 10.0.1.1 56 bytes of data
+       56 bytes from 10.0.1.1: icmp_seq=0 time=0 ms
+       1 packets transmitted, 1 received, 0% packet loss, time 1010 ms
+
+    Now let's ping one of Google's DNS servers to prove we can access the rest of the
+    Internet:
+
+    .. code-block:: bash
+
+       nsh> ping -c 1 8.8.8.8
+       PING 8.8.8.8 56 bytes of data
+       56 bytes from 8.8.8.8: icmp_seq=0 time=10 ms
+       1 packets transmitted, 1 received, 0% packet loss, time 1010 ms
+
+   Success!
+
+Stopping
+--------
+
+The only really effective way to stop the simulator is kill it from another terminal:
+
+    .. code-block:: bash
+
+       $ pkill nuttx
+
+
+
+Debugging
+---------
+
+You can debug the simulator like any regular Linux program.