Doc: improve and add documentations for the guide section of the wiki
Some checks failed
Build Documentation / build-html (push) Has been cancelled

* Add a migration warning to the update release system and the elf
programs documentation pages. This is just to add a papertrail from
where the documentation originate in case of error during the migration
process.
* Improve the building nuttx with app out of source tree
* Add new guide pages
	* Building uclibc++
	* Custom app directories
	* Debugging ELF loadable modules
	* Multiple NSH sessions
	* NSH network link management
	* RAM & ROM disks
	* Reading CAN messages
	* Remove device drivers with NSH
This commit is contained in:
Ludovic Vanasse 2024-12-29 09:25:32 -05:00 committed by Xiang Xiao
parent dc82a296f7
commit c55c2511ad
13 changed files with 1045 additions and 1 deletions

View file

@ -0,0 +1,207 @@
========================================================
Building NuttX with Applications Outside the Source Tree
========================================================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Building+NuttX+with+Applications+Outside+of+the+Source+Tree
Q: Has anyone come up with a tidy way to build NuttX with board-specific pieces outside the source tree?
========================================================================================================
A: Here are four approaches:
============================
1. Make export
--------------
There is a make target called ``make export``. It will build NuttX, then bundle
all of the header files, libraries, startup objects, and other build components
into a ``.zip`` file. You can move that ``.zip`` file into any build environment
you want. You can even build NuttX under a DOS CMD window.
This ``make target`` is documented in the top-level
:doc:`Legacy README </introduction/resources>`. Search for ``Build Targets``
1. Replace the apps/ Directory
------------------------------
You can replace the entire ``apps/`` directory. It is not a critical part of the
OS. The ``apps/`` is simply provided for you to help with your application
development. It should not dictate anything that you do.
To use a different ``apps`` directory, simply execute ``make menuconfig`` in the
top-level ``nuttx/`` directory and redefine ``CONFIG_APPS_DIR`` in your
``.config`` file so that it points to a different, custom application directory.
Note that ``CONFIG_APPS_DIR`` is a `relative` path from the top-level
``nuttx/`` directory.
You can copy any pieces that you like from the old ``apps/`` directory to your
custom ``apps`` directory as necessary. This is documented in
the `NuttX Porting Guide <https://cwiki.apache.org/confluence/display/NUTTX/Porting+Guide>`_
and in the `apps/README.md <https://github.com/apache/nuttx-apps/blob/master/README.md>`_ file.
1. Extend the apps/ Directory
-----------------------------
If you like the random collection of stuff in the ``apps/`` directory but just
want to expand the existing components with your own, external sub-directory,
then there is an easy way to do that too: Create a symbolic link in the
``apps/`` directory that redirects to your application sub-directory (or copy
your code into a sub-directory of ``apps/``).
.. image:: image/custom_app_dir_through_extension.png
Makefile and Make.defs
^^^^^^^^^^^^^^^^^^^^^^
In order to be incorporated into the build, the directory that you link under
the ``apps/`` directory should contain:
1. A ``Makefile`` that supports the ``clean`` and ``distclean`` targets (see
other Makefiles for examples).
2. A tiny ``Make.defs`` make file fragment that simply adds the build
directories to the variable ``CONFIGURED_APPS`` like:
.. code-block:: shell
CONFIGURED_APPS += my_directory1 my_directory2
Automatic Sub-directory Inclusion
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``apps/Makefile`` will always automatically check for the existence of
sub-directories containing a ``Makefile`` and a ``Make.defs`` file. The
``Makefile`` will be used only to support cleaning operations. The
``Make.defs`` file provides the set of relative paths to directories to be
built; these directories must also contain a ``Makefile``. That ``Makefile`` can
build the sources and add the object files to the ``apps/libapps.a`` archive
(see other Makefiles for examples). It should support the ``all``, ``install``,
``context``, and ``depend`` targets.
``apps/Makefile`` does not depend on any hard-coded lists of directories.
Instead, it does a wildcard search to find all appropriate directories. This
means that to install a new application, you simply have to copy the directory
(or link it) into the ``apps/`` directory. If the new directory includes a
``Makefile`` and a ``Make.defs`` file, then it will be automatically discovered
and included in the build at ``make`` time.
Kconfig
^^^^^^^
If the directory that you add also includes a ``Kconfig`` file, then it will be
automatically included in the NuttX configuration system as well.
``apps/Makefile`` uses a tool at ``apps/tools/mkkconfig.sh`` that dynamically
builds the ``apps/Kconfig`` file at pre-configuration time.
.. note::
The native Windows build will use a corresponding tool called
``apps/tools/mkconfig.bat``.
Install script
^^^^^^^^^^^^^^
You could, for example, create a script called ``install.sh`` that installs a
custom application, configuration, and board-specific directory:
1. Copy ``MyBoard`` directory to ``boards/MyBoard``.
2. Add a symbolic link to ``MyApplication`` at ``apps/external``
3. Configure NuttX:
.. code-block:: shell
tools/configure.sh MyBoard:MyConfiguration
Special ``apps/external`` Directory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use of the name ``apps/external`` is suggested because that name is included in
the ``.gitignore`` file and will save you some nuisance when working with GIT.
4. Contain the apps/ Directory
------------------------------
A simple, minimally invasive approach would be to contain the ``apps/`` GIT
clone within your custom application directory. In this case, ``apps/`` would
appear as a directory under your custom application directory instead of your
application directories being inserted as sub-directories of ``apps/``. It may
even be implemented as a sub-module of your custom application directory.
.. image:: image/custom_app_dir_through_containment.png
Kconfig and Makefile
^^^^^^^^^^^^^^^^^^^^
There are only a few minimal requirements of your custom application directory.
It needs to have only its own ``Makefile`` and ``Kconfig`` file. That
``Kconfig`` would need to include the ``apps/Kconfig``. The ``Makefile`` would
similarly need to invoke the ``apps/Makefile`` for all of the relevant build
targets. For example, the ``clean`` target:
.. code-block:: shell
$(MAKE) -c apps clean TOPDIR=$(TOPDIR)
Library Issues
^^^^^^^^^^^^^^
The contained directory will create and install a static library called
``libapps($LIBEXT)`` in the ``nuttx/staging`` directory. Your custom logic must
also appear in the ``nuttx/staging`` directory. Here are two ways that you might
do that:
1. **Merge with ``libapps($LIBEXT)``.**
The custom application directory's ``Makefile`` could create and install the
final ``libapps($LIBEXT)`` in the ``nuttx/staging`` directory.
``<custom-dir>/apps/libapps($LIBEXT)`` could merge its custom object files
with ``<custom-dir>/libapps($LIBEXT)`` and then re-install the library at
``nuttx/staging``.
2. **Use the EXTRA_LIBS Feature.**
The build system supports two special make-related variables called
``EXTRA_LIBS`` and ``EXTRA_LIBPATHS``. These may be defined in your
board-specific ``Make.defs`` file. ``EXTRA_LIBS`` provides the name of your
custom library. If you create ``<custom-dir>/libcustom.a``, then the value
of ``EXTRA_LIBS`` would be ``-lcustom`` and the value of ``EXTRA_LIBPATHS``
would be ``-L <custom-dir>`` (assuming the GNU ld linker).
Relative Effort and Benefits
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The contained ``apps/`` directory approach requires some more effort than the
extended ``apps/`` approach, but has the advantage that there will be no strange
behavior due to issues with ``.gitignore`` and, hence, a cleaner user
experience.
Out-of-tree Builds
^^^^^^^^^^^^^^^^^^
This configuration also has the possibility of supporting out-of-tree builds
using ``fusefs``. Suppose, for example, that you have a project directory with
the contained ``apps/`` directory and, say, three platform build directories.
Using ``fusefs``, you can overlay one of the platform build directories on top
of the project directory. Then all files generated by the build will be written
into the overlaid platform build directory. When the ``fusefs`` is torn down,
the project directory will still be clean, and the build result will still be in
the platform build directory. This can then be repeated for the other two
platform build directories.
In this case, you would probably also want to contain the ``nuttx/`` directory
in the project directory as well so that the entire system is built out-of-tree.
Hooking External Applications into the Configuration System
-----------------------------------------------------------
Suppose you have opted to extend the ``apps/`` directory with your custom
external application directories and would also like to support configuration
variables in your external application. No problem! Thanks to Sebastien Lorquet,
any external application that you install into the ``apps/`` (whether via a
symbolic link or via a directory copy) `will` be included in the NuttX
configuration system.
The top-level ``Kconfig`` file in the ``apps/`` directory is automatically
generated based on the contents of each ``apps/`` sub-directory. If your
installed sub-directory contains ``Kconfig``, ``Makefile``, and ``Make.defs``
files, then it will be incorporated into the NuttX configuration system when the
top-level ``Kconfig`` file is generated.

View file

@ -0,0 +1,84 @@
=================
Building uClibc++
=================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=139629550
and is probably outdated
A version of `uClibc++ <http://cxx.uclibc.org/>`_ has been ported to NuttX and is available in the NuttX
uClibc++ GIT repository at `Bitbucket.org <https://bitbucket.org/nuttx/uclibc/>`_ . This version of uClibc++ was
adapted for NuttX by the RGMP team.
This custom version of uClibc++ resides in the NuttX repository at:
https://bitbucket.org/nuttx/uclibc/
rather than in the main NuttX source tree, due to licensing issues: NuttX is
licensed under the permissive, modified BSD License; uClibc++, on the other
hand, is licensed under the stricter GNU LGPL Version 3 license.
General build instructions are available in the uClibc++ `README.txt <https://bitbucket.org/nuttx/uclibc/src/master/README.txt>`_
file. Those instructions are not repeated here. This page documents specific
issues encountered when building this NuttX version of uClibc++ and how they
are resolved.
Undefined Reference to ``_impure_ptr``
======================================
**Problem**
When building uClibc++, you may encounter an undefined reference to
``_impure_ptr`` similar to:
.. code-block:: none
LD: nuttx
.../arm-none-eabi/lib/armv7e-m\libsupc++.a(vterminate.o): In function
`__gnu_cxx::__verbose_terminate_handler()`:
vterminate.cc:(.text._ZN9__gnu_cxx27__verbose_terminate_handlerEv+0xfc):
undefined reference to `_impure_ptr'
**Solution**
A definitive, elegant solution is not known, but the following workaround has
proven to work:
1. Locate the directory where you can find ``libsupc++``:
.. code-block:: console
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -print-file-name=libsupc++.a
2. Go to that directory and save a copy of ``vterminate.o`` (in case you need
it later):
.. code-block:: console
cd <the-directory-containing-libsupc++.a>
arm-none-eabi-ar.exe -x libsupc++.a vterminate.o
3. Remove ``vterminate.o`` from the library. At build time, the uClibc++
package will provide a usable replacement:
.. code-block:: console
arm-none-eabi-ar.exe -d libsupc++.a vterminate.o
4. At this point, NuttX should link with no problem. If you ever want to
restore the original ``vterminate.o`` to ``libsupc++.a``, you can do so
by running:
.. code-block:: console
arm-none-eabi-ar.exe rcs libsupc++.a vterminate.o
After removing ``vterminate.o`` from the standard library, the
uClibc++-provided ``vterminate.o`` becomes the active implementation and
prevents references to ``_impure_ptr`` from arising during linkage.
.. note::
Always exercise caution when modifying toolchain libraries. This
workaround is known to be effective but it replaces standard library
objects, which may have side effects in other toolchain usage scenarios.

View file

@ -0,0 +1,165 @@
===========================================
Custom Application Directories
===========================================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Custom+Application+Directories
Most people use the generic ``apps/`` directory with NuttX. That is convenient
and well-documented. However, it should always be remembered that NuttX is a
stand-alone, general-purpose OS and has **no dependency** on that "canned"
application directory.
This page shows how to create your own, custom application directory from
scratch.
Creating the Custom Application Directory
=========================================
Below is a simple example of the **minimum** custom application directory. It
contains only three files: ``Makefile``, ``Kconfig``, and ``hello.c``.
Makefile
--------
The custom application directory must include a ``Makefile`` that supports all
of the make targets expected by the NuttX build system **and** must generate an
archive called ``libapps.a`` in the top-level of the custom directory structure.
The minimal required targets for the ``Makefile`` look like this:
.. code-block:: shell
APPDIR = ${shell pwd}
-include $(TOPDIR)/Make.defs
# files
CSRCS = hello.c
COBJS = hello.o
ROOTDEPPATH = --dep-path .
# Build targets
all: libapps.a
.PHONY: dirlinks context preconfig depend clean clean_context distclean
.PRECIOUS: libapps$(LIBEXT)
# Compile C Files
$(COBJS): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
# Add object files to the apps archive
libapps.a: $(COBJS)
$(call ARCHIVE, libapps.a, $(COBJS))
# Create directory links
dirlinks:
# Setup any special pre-build context
context:
# Setup any special pre-configuration context
preconfig:
# Make the dependency file, Make.deps
depend: Makefile $(CSRCS)
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
# Clean the results of the last build
clean:
$(call CLEAN)
# Remove the build context and directory links
clean_context:
# Restore the directory to its original state
distclean: clean clean_context
$(call DELFILE, Make.dep)
# Include dependencies
-include Make.dep
Kconfig
-------
A ``Kconfig`` file must be included, but it need not contain any meaningful
configuration options. This file is where you can add application-specific
configuration settings if desired. The minimal ``Kconfig`` might look like:
.. code-block:: shell
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
hello.c
-------
Your custom application must compile at least one source file to generate the
required ``libapps.a`` archive. One of these source files must include the
``main()`` entry point to the application. That main function (or similarly
named entry point) is called after OS initialization completes.
What this application initialization entry point does, how it interacts with
the rest of your application, and where the rest of you application code is
located is of no concern to the OS. Only this one entry point is needed.
Below is a small "Hello, World!" example, where ``custom_main()`` is the
application entry point:
.. code-block:: c
#include <stdio.h>
int custom_main(int argc, char *argv[])
{
printf("Hello, World!!\n");
return 0;
}
Building with the Custom Application Directory
==============================================
In order to build with the new custom application directory, you need the
following in your NuttX configuration:
.. code-block:: shell
CONFIG_APPS_DIR="../custom-apps"
CONFIG_USER_ENTRYPOINT="custom_main"
.. note::
You can only access the ``../custom-apps/Kconfig`` file if
``CONFIG_APPS_DIR`` is set to ``../custom-apps`` **before** running
``make menuconfig``. If you start with an existing configuration, you may
face a "chicken-and-egg" situation. One workaround is to manually edit
the ``.config`` file before running ``make menuconfig``.
Alternatively, if you use the ``tools/configure.sh`` script, you can specify the
custom-apps directory from the command line:
.. code-block:: shell
tools/configure.sh -a ../custom_apps <board>:<config>
Afterward, just build NuttX as you normally would. When you run the program that
was built with your custom application directory, you should see:
.. code-block:: shell
Hello, World!!

View file

@ -0,0 +1,84 @@
==============================
Debugging ELF Loadable Modules
==============================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Debugging+ELF+Loadable+Modules
Debugging ELF modules loaded in memory can be tricky because the load address
in memory does not match the addresses in the ELF file. This challenge has long
existed for debugging uClinux programs and Linux kernel modules; the same
solution can be used with NuttX ELF files (and probably with NxFLAT modules as
well). Below is a summary of one way to approach this:
1. Get ELF Module Load Address
==============================
Put a change in ``nuttx/binfmt`` so that you print the address where the ELF
text was loaded into memory.
Turning on BINFMT debug (``CONFIG_DEBUG_BINFMT=y``) should give you the same
information, although it may also provide more output than you really want.
Alternatively, you could place a ``printf()`` at the beginning of your ``main()``
function so that your ELF module can print its own load address. For example,
the difference between the address of ``main()`` in your object file and the
address of ``main()`` at run time reveals the actual load address.
2. Make the ELF Module Wait for You
===================================
Insert an infinite loop in the ``main()`` routine of your ELF program. For
example:
.. code-block:: c
volatile bool waitforme;
int main (int arc, char **argv)
{
while (!waitforme);
...
When you start the ELF program, you will see where it was loaded in memory, and
the ELF program will remain stuck in the infinite loop. It will continue to
wait for ``waitforme`` to become true before proceeding.
3. Start the Debugger
=====================
Start the debugger, connect to the GDB server, and halt the program. If your
debugger is well-behaved, it should stop at the infinite loop in ``main()``.
4. Load Offset Symbols
======================
Load symbols using the offset where the ELF module was loaded:
.. code-block:: shell
(gdb) add-symbol-file <myprogram> <load-address>
Here, ``<myprogram>`` is your ELF file containing symbols, and
``<load-address>`` is the address where the program text was actually loaded (as
determined above). Single-step a couple of times and confirm that you are in the
infinite loop.
5. And Debug
============
Set ``waitforme`` to a non-zero value. Execution should exit the infinite loop,
and now you can debug the ELF program loaded into RAM in the usual way.
An Easier Way?
==============
There might be an alternative that allows you to step into the ELF module
without modifying the code to include the ``waitforme`` loop. You could place a
breakpoint on the OS function ``task_start()``. That function runs before your
ELF program starts, so you should be able to single-step from the OS code
directly into your loaded ELF application—no changes to the ELF application
required.
When you step into the application's ``main()``, you have the relocated address
of ``main()`` and can use that address (see step #1) to compute the load offset.

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View file

@ -60,3 +60,13 @@ Guides
updating_release_system_elf.rst
partially_linked_elf.rst
fully_linked_elf.rst
building_nuttx_with_app_out_of_src_tree.rst
building_uclibcpp.rst
custom_app_directories.rst
debugging_elf_loadable_modules.rst
multiple_nsh_sessions.rst
nsh_network_link_management.rst
ram_rom_disks.rst
reading_can_msgs.rst
remove_device_drivers_nsh.rst

View file

@ -0,0 +1,86 @@
=====================
Multiple NSH Sessions
=====================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Multiple+NSH+Sessions
Q:
I would like to run the NuttShell on multiple serial ports, but haven't
figured it out yet; can you point me in the right direction?
A:
Easy. Don't use ``apps/examples/nsh_main.c``. Create your own main function
something like this (with all error handling omitted for simplicity). By the
way, this is all standard POSIX stuff that you can get detailed information
about by just Googling `dup2` or maybe `I/O redirection`:
.. code-block:: c
int my_main(int argc, char **argv)
{
const char *tty = argv[1];
int fd = open(tty, O_RDWR);
(void)dup2(fd, 0);
(void)dup2(fd, 1);
(void)dup2(fd, 2);
close(fd);
...
}
And the rest is just like the original ``nsh_main()`` function (in fact,
perhaps the existing ``nsh_main()`` function could be optionally extended to
accept a console device string?). Then you can start a new NSH session on any
TTY like:
.. code-block:: none
nsh> mynsh /dev/ttyS2 &
This should cause a new NSH session to appear on ``ttyS2``. That session will
persist until you do the following from the new session:
.. code-block:: none
nsh> exit
Then the new session, i.e., ``my_main()`` will exit.
If you were to do something like:
.. code-block:: none
nsh> mynsh /dev/console
then you would get nested NSH sessions on the same console. The first session
would halt and wait for the second session to take control of the console until
it exits. Then the first session will take over console again.
NuTTY
=====
In a previous discussion, there was talk about implementing the moral equivalent
of getty in NuttX (of course, it would be called "nutty"). A simple
implementation of nutty would work like this:
1. It would wait on ``poll()`` on every (configured) serial device.
2. Whenever it is awakened, it would start something like ``my_main()`` above
on the active serial port.
3. NSH has an option to enable logins, but it would be better to remove the
existing login information from NSH and centralize it in nutty.
That way, you could connect to any TTY, hit enter, and you would get an NSH
session. Hmm... it is not clear how nutty would get the TTY back after the
session is closed. That part may require some additional thought.
Other Ideas
===========
There are other ways to get multiple NSH sessions:
- Telnet already supports multiple sessions.
- Implement the existing NSH as an ELF program, then you can get multiple NSH
sessions with ``posix_spawn`` by simply redirecting I/O.
- Using the tiny NxWM window managers, multiple NSH windows are already
supported.

View file

@ -0,0 +1,122 @@
===========================
NSH Network Link Management
===========================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/NSH+Network+Link+Management
In the past, if the network was not connected when NuttX started, two problems
could arise:
1. It could take a very long time for the NSH prompt to appear because of the
sequential initialization (for example, when the network cable is not
connected).
2. After NuttX came up, installing the network cable would not enable the
network; the only way to recover networking was to connect the cable and
reset the board.
Network link management capability has now been added to NSH to address these
problems.
Configuration Options
=====================
A simple feature can be enabled to move network initialization to a separate
thread so that it is no longer performed sequentially. With this feature, the
network bringup occurs asynchronously, and the NSH prompt appears immediately
(although the network may not be available until some time later). That feature
is enabled with the following setting and is the first prerequisite for the full
NSH link management feature:
- ``CONFIG_NSH_NETINIT_THREAD``. Refer to the help text in the Kconfig file for
this option (``apps/nshlib/Kconfig``). Additional information about this
setting is included there.
The logic that implements NSH network management is provided in
``apps/nshlib/nsh_netinit.c``. The behavior of that logic depends on multiple
configuration settings. First, there are some additional prerequisites that
must be satisfied:
- ``CONFIG_NETDEV_PHY_IOCTL``
Enable PHY IOCTL commands in the Ethernet device driver. Special IOCTL
commands must be provided by the Ethernet driver to support certain PHY
operations needed for link management. These operations are not complex and
are implemented for Atmel SAM4/4, SAMA5 families, and for the STMicro STM32.
See ``nuttx/arch/arm/src/sam34/sam_emac.c``,
``nuttx/arch/arm/src/sam34/sam_emaca.c``, ``sam_emacb.c``, and ``sam_gmac.c``,
and ``nuttx/arch/arm/src/stm32/stm32_eth.c``.
- ``CONFIG_ARCH_PHY_INTERRUPT``
This is not a user-selectable option. Rather, it is set when selecting a board
that supports PHY interrupts. In most architectures, the PHY interrupt is not
directly associated with the Ethernet driver. Instead, the PHY interrupt is
provided through some board-specific GPIO, and the board-specific logic must
provide support for that GPIO interrupt. Specifically, the board logic must:
1. Provide the function ``arch_phy_irq()`` as described and prototyped in
``nuttx/include/nuttx/arch.h``.
2. Select ``CONFIG_ARCH_PHY_INTERRUPT`` in the board configuration file to
advertise that ``arch_phy_irq()`` is supported.
Examples can be found at:
- ``nuttx/boards/arm/sama5/sama5d3x-ek/src/sam_ethernet.c``
- ``nuttx/boards/arm/sama5/sama5d3-xplained/src/sam_ethernet.c``
- ``nuttx/boards/arm/sama5/sama5d4-ek/src/sam_ethernet.c``
- Other requirements: UDP support must be enabled (``CONFIG_NET_UDP``), and
signals must not be disabled (``CONFIG_DISABLE_SIGNALS``).
With all these prerequisites in place, NSH network management can be enabled on
the NSH network initialization thread by selecting these additional options:
- ``CONFIG_NSH_NETINIT_MONITOR``
By default, the network initialization thread brings up the network (or
fails while trying) then exits, freeing all resources it used. If this option
is selected, however, the network initialization thread will persist
indefinitely to monitor the network status. Should the network go down (for
example, if the cable is removed), the thread will monitor the link status
and attempt to bring the network back up. In this scenario, the resources
required for network initialization are never released.
If the network monitor is selected, additional options control its behavior:
- ``CONFIG_NSH_NETINIT_SIGNO``
The network monitor logic receives signals when there is a change in link
status. This setting can be used to customize the signal number to avoid
conflicts.
- ``CONFIG_NSH_NETINIT_RETRYMSEC``
When the network is down, the initialization thread will periodically attempt
to bring the network back up. Because this can be time-consuming, the retry
operation is performed only at the interval specified by this value, in
milliseconds.
- ``CONFIG_NSH_NETINIT_THREAD_STACKSIZE``
The stack size for the network initialization thread.
- ``CONFIG_NSH_NETINIT_THREAD_PRIORITY``
The network initialization thread priority.
Overview of the Operation
=========================
Below is a summary of how the NSH management thread operates:
1. During initialization, the thread opens a UDP socket for IOCTL operations
and connects a signal handler.
2. It enters a loop. At the beginning of each loop iteration, the thread
uses an IOCTL command to register (or re-register) with the Ethernet device
to receive a signal whenever the PHY reports a link up or link down
interrupt. Re-registration is necessary because the notification disarms
after each PHY interrupt.
3. The thread reads the link status from both the PHY and the Ethernet device.
If they disagree, the network monitor uses an IOCTL command to bring the
Ethernet driver up or down to match the current state of the network. If the
network is lost, the monitor brings the Ethernet driver down; if the network
is regained, the monitor brings the Ethernet driver back up and re-establishes
the connection.
4. If the PHY and the Ethernet driver agree on the link state, no action is
performed.
5. At the end of the loop, the network monitor waits for a PHY interrupt or a
timeout. When either occurs, control returns to the top of the loop, and the
process repeats.
6. If a PHY interrupt happens, a signal is delivered to the task and handled by
the network monitors signal handler, which posts a semaphore to immediately
re-awaken the network monitor from its wait.

View file

@ -0,0 +1,119 @@
=======================
RAM Disks and ROM Disks
=======================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/RAM+Disks+and+ROM+Disks
NSH mkrd Command
================
The typical way to create a RAM disk is by using the NuttShell (NSH) ``mkrd``
command. The syntax is:
.. code-block:: shell
mkrd [-m <minor>] [-s <sector-size>] <nsectors>
This command creates a RAM disk consisting of ``<nsectors>`` sectors, each of
size ``<sector-size>`` (or 512 bytes if ``<sector-size>`` is not specified). The
RAM disk is then registered as ``/dev/ram<minor>``. If ``<minor>`` is not
specified, ``mkrd`` attempts to register the RAM disk as ``/dev/ram0``.
Internally, the NSH ``mkrd`` command is a simple wrapper around the OS
``boardctl()`` interface, using the ``BOARDIOC_MKRD`` command. “Under the hood,”
this ``boardctl()`` command performs the following:
1. Allocates kernel-space memory with ``kmm_malloc()`` of size ``<nsectors>``
times ``<sector-size>``
2. Zeros the allocated memory, and
3. Calls the OS-internal function ``ramdisk_register()`` to create the RAM disk.
NSH ROMFS /etc Support
======================
A ROM disk is a block device created from a read-only file system image stored
in FLASH or other ROM. There is no NSH command available to create a ROM disk
at runtime. However, it is possible to enable ROM disk support in NSH using the
``CONFIG_NSH_ROMFSETC`` option, as described in the section on NSH start-up
scripts in the `NSH User Guide <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=139629410>`_.
Any application is able to create a ROM disk using the ``boardctl()`` interface
with the ``BOARDIOC_ROMDISK`` command.
Creating RAM Disks in Board Bring-Up Logic
==========================================
RAM disks may be created in board-specific initialization logic that runs in
supervisor mode. That logic might look as follows:
.. code-block:: c
int board_ramdisk(int minor, unsigned int sectsize, unsigned int nsectors)
{
size_t allocsize = (size_t)sectsize * (size_t)nsectors;
FAR uint8_t *buffer;
/* Allocate the memory backing up the ramdisk */
buffer = (FAR uint8_t *)kmm_zalloc(allocsize);
if (buffer == NULL)
{
return -ENOMEM;
}
/* Then register the ramdisk */
ret = ramdisk_register(minor, buffer, nsectors, sectsize,
RDFLAG_WRENABLED | RDFLAG_FUNLINK);
if (ret < 0)
{
kmm_free(buffer);
}
return ret;
}
Alternatively, this could be replaced by a call to the OS internal function
``mkrd()``.
Creating ROM Disks in Board Bring-Up Logic
==========================================
.. note::
Currently, the ``romdisk_register()`` function is only available within the
OS. Certain logic in ``apps/`` directly calls ``romdisk_register()``, which
violates the portable POSIX OS interface. The correct approach for an
application is to create a ROM disk via ``boardctl(BOARDIOC_ROMDISK)`` as
described above. Calling ``romdisk_register()`` directly is not only a
violation of the NuttX portable interface, but also is not allowed in
PROTECTED or KERNEL build modes.
ROM disks, i.e., read-only disks in FLASH, can be created by board bring-up
logic in a way similar to RAM disks, with the following caveats:
- The FLASH region is not allocated; the FLASH address, the sector size, and the
number of sectors must already be known.
- The ``romdisk_register()`` function is used instead of ``ramdisk_register()``.
A simple example could look like:
.. code-block:: c
int board_romdisk(int minor, FAR uint8_t *buffer, unsigned int sectsize,
unsigned int nsectors)
{
/* Register the romdisk */
return romdisk_register(minor, buffer, nsectors, sectsize);
}
Calling ``romdisk_register()`` is equivalent to calling ``ramdisk_register()``
with the final parameter ``flags == 0``.
Most ROM disks use the ROMFS file system, although CROMFS is another option.
Creating ROMFS file system images involves several steps. Tools are available
to simplify the process of building ROMFS images, but that topic is outside the
scope of this Wiki page.

View file

@ -0,0 +1,62 @@
====================
Reading CAN Messages
====================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Reading+CAN+Messages
Twice now, there have been complaints or issues about reading messages from the
CAN driver. The usual concern is that the driver is somehow losing or dropping
CAN messages. In these cases, it is often discovered that the CAN driver is
being used incorrectly and, as is human nature, the driver itself is blamed for
the problem.
When reading from the CAN driver, multiple messages may be returned, depending
on two factors:
1. The size of the returned CAN messages.
2. The size of the buffer provided to receive CAN messages.
It should never be assumed that a single message will be returned; making this
assumption can lead to lost CAN messages under conditions in which the read
buffer can hold more than one small message. The following example shows how to
properly handle the CAN read operation:
.. code-block:: c
#define BUFLEN 128 /* Some arbitrary size for the CAN RX buffer */
FAR struct can_msg_s *msg;
char rxbuffer[BUFLEN];
ssize_t nread;
int nbytes;
int msglen
int i;
/* Read messages into the RX buffer */
nread = read(fd, rxbuffer, BUFLEN);
/* Check for read errors */
...
/* Process each message in the RX buffer */
for (i = 0; i <= nread - CAN_MSGLEN(0); i += msglen)
{
/* Get the next message from the RX buffer */
msg = (FAR struct can_msg_s *)&rxbuffer[i];
nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc);
msglen = CAN_MSGLEN(nbytes);
DEBUGASSERT(i + msglen < BUFLEN);
/* Process the next CAN message */
...
}
By looping over the read buffer and parsing out each CAN message, it is
possible to avoid losing messages that are stored contiguously in the input
buffer.

View file

@ -0,0 +1,101 @@
================================
Removing Device Drivers with NSH
================================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Removing+Device+Drivers+with+NSH
NuttX and Unix-like Operating Systems Compared
==============================================
There are many things that are called device drivers. In this context, the
discussion is limited to **character device drivers**. In NuttX, character
device drivers are represented by device driver nodes in the top-level :doc:`pseudo
filesystem </components/filesystem/pseudofs>`.
Standard Unix-like operating systems also support device driver nodes, which
superficially resemble NuttX device driver nodes: Both look like files and
usually reside under the top-level ``/dev`` directory. Both can be accessed
with standard POSIX file system commands such as ``open()``, ``close()``,
``read()``, ``write()``, and so forth. However, the similarity ends there.
The payload of a standard Unix-like operating system device driver node is a
device major and minor number. These major and minor device numbers are used to
look up the actual device driver interface using internal OS logic and data
structures. A NuttX device node, by contrast, directly holds the device driver
interface with no intervening lookup. This design is less flexible, but it is
more efficient and conserves limited resources in an embedded system.
In standard Unix-like operating systems, the device node can simply be deleted
using the shell command ``rm`` or the programmatic interface ``unlink()``. The
node is removed, and nothing special happens to the underlying device driver
(except that it may no longer be accessible).
In NuttX, if the device node were removed in the same way, the entire device
interface would also be removed, effectively breaking the driver. Internally,
NuttX supports a function called ``unregister_driver()`` that can be invoked
to remove a device driver. Therefore, removing the device driver node must
behave as though ``unregister_driver()`` were called.
The unlink() Method
===================
How is this accomplished in NuttX? It is done via a special device driver
method called ``unlink()``.
NuttX device drivers are implemented via a vtable of function pointers. That
vtable defines the interface between the pseudo-file system and the device
driver. This vtable is the structure ``struct file_operations`` defined in
``[nuttx]/include/nuttx/fs/fs.h``. It provides several interfaces that closely
match the standard POSIX interfaces—``open()``, ``close()``, ``read()``,
``write()``, etc.—and also includes a method called ``unlink()``. This
``unlink()`` method is called by the NuttX VFS when a user removes a device
driver node.
.. note::
Removal of device driver nodes is only permitted if
``CONFIG_DISABLE_PSEUDOFS_OPERATIONS`` is **not** defined. All pseudo-file
system operations may be suppressed to reduce the FLASH footprint in systems
with extremely limited resources.
Removing a Device Node from NSH
===============================
Below is a summary of what happens when a device node is deleted using the NSH
``rm`` command:
1. The user enters the ``rm`` command. The NSH parser recognizes the command
and transfers control to the NSH function ``cmd_rm()``.
2. ``cmd_rm()`` verifies the command, then calls the standard POSIX
``unlink()`` interface. The logic in the VFS ``unlink()`` function in
``[nuttx]/fs/vfs/fs_unlink.c`` is then executed.
3. The VFS ``unlink()`` detects that the target to be removed is a device node
in the top-level pseudo-file system. It calls the device driver's
``unlink()`` method. It also removes the device node from the
pseudo-filesystem. However, the underlying resources required to support
the device driver interface may remain until the device driver frees those
resources.
4. When the device driver's ``unlink()`` method is called, it determines if
the device resources can be freed immediately. If so, it frees those
resources. If, for example, there are still open references to the device
driver, it may defer freeing the resources until the last client has closed
the device driver and there are no open references. In such a case, it may
set a flag indicating that the device driver has been unlinked.
5. If freeing of device driver resources has been deferred, that flag will be
examined later. For instance, when the last client of the device driver
closes its reference to the driver, it checks whether the unlink operation
was deferred. If so, it frees any remaining device driver resources at that
time.
.. warning::
Some character device driver instances do not implement the ``unlink()``
method. If problems arise when attempting to remove character drivers as
described in this Wiki page, a missing ``unlink()`` method is the most
likely cause.

View file

@ -2,6 +2,10 @@
Updating a Release System with ELF Programs
===========================================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Updating+a+Release+System+with+ELF+Programs
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Updating+a+Release+System+with+ELF+Programs