diff --git a/Documentation/guides/building_nuttx_with_app_out_of_src_tree.rst b/Documentation/guides/building_nuttx_with_app_out_of_src_tree.rst new file mode 100644 index 0000000000..a31d5b77f4 --- /dev/null +++ b/Documentation/guides/building_nuttx_with_app_out_of_src_tree.rst @@ -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 `. 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 `_ +and in the `apps/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. + ``/apps/libapps($LIBEXT)`` could merge its custom object files + with ``/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 ``/libcustom.a``, then the value + of ``EXTRA_LIBS`` would be ``-lcustom`` and the value of ``EXTRA_LIBPATHS`` + would be ``-L `` (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. diff --git a/Documentation/guides/building_uclibcpp.rst b/Documentation/guides/building_uclibcpp.rst new file mode 100644 index 0000000000..53fbad5de6 --- /dev/null +++ b/Documentation/guides/building_uclibcpp.rst @@ -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++ `_ has been ported to NuttX and is available in the NuttX +uClibc++ GIT repository at `Bitbucket.org `_ . 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 `_ +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 + 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. diff --git a/Documentation/guides/custom_app_directories.rst b/Documentation/guides/custom_app_directories.rst new file mode 100644 index 0000000000..eb3b473ccc --- /dev/null +++ b/Documentation/guides/custom_app_directories.rst @@ -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 + + 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 : + +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!! diff --git a/Documentation/guides/debugging_elf_loadable_modules.rst b/Documentation/guides/debugging_elf_loadable_modules.rst new file mode 100644 index 0000000000..941048c988 --- /dev/null +++ b/Documentation/guides/debugging_elf_loadable_modules.rst @@ -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 + +Here, ```` is your ELF file containing symbols, and +```` 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. diff --git a/Documentation/guides/image/custom_app_dir_through_containment.png b/Documentation/guides/image/custom_app_dir_through_containment.png new file mode 100644 index 0000000000..e7152ecbf6 Binary files /dev/null and b/Documentation/guides/image/custom_app_dir_through_containment.png differ diff --git a/Documentation/guides/image/custom_app_dir_through_extension.png b/Documentation/guides/image/custom_app_dir_through_extension.png new file mode 100644 index 0000000000..f20d5f6969 Binary files /dev/null and b/Documentation/guides/image/custom_app_dir_through_extension.png differ diff --git a/Documentation/guides/index.rst b/Documentation/guides/index.rst index b20ba5b022..04910b978d 100644 --- a/Documentation/guides/index.rst +++ b/Documentation/guides/index.rst @@ -59,4 +59,14 @@ Guides port.rst updating_release_system_elf.rst partially_linked_elf.rst - fully_linked_elf.rst \ No newline at end of file + 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 + diff --git a/Documentation/guides/multiple_nsh_sessions.rst b/Documentation/guides/multiple_nsh_sessions.rst new file mode 100644 index 0000000000..ca0fbd366c --- /dev/null +++ b/Documentation/guides/multiple_nsh_sessions.rst @@ -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. diff --git a/Documentation/guides/nsh_network_link_management.rst b/Documentation/guides/nsh_network_link_management.rst new file mode 100644 index 0000000000..3100f7ba7d --- /dev/null +++ b/Documentation/guides/nsh_network_link_management.rst @@ -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 monitor’s signal handler, which posts a semaphore to immediately + re-awaken the network monitor from its wait. diff --git a/Documentation/guides/ram_rom_disks.rst b/Documentation/guides/ram_rom_disks.rst new file mode 100644 index 0000000000..1507307ddf --- /dev/null +++ b/Documentation/guides/ram_rom_disks.rst @@ -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 ] [-s ] + +This command creates a RAM disk consisting of ```` sectors, each of +size ```` (or 512 bytes if ```` is not specified). The +RAM disk is then registered as ``/dev/ram``. If ```` 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 ```` + times ```` +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 `_. + +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. \ No newline at end of file diff --git a/Documentation/guides/reading_can_msgs.rst b/Documentation/guides/reading_can_msgs.rst new file mode 100644 index 0000000000..2e956a98ae --- /dev/null +++ b/Documentation/guides/reading_can_msgs.rst @@ -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. diff --git a/Documentation/guides/remove_device_drivers_nsh.rst b/Documentation/guides/remove_device_drivers_nsh.rst new file mode 100644 index 0000000000..96505d55f9 --- /dev/null +++ b/Documentation/guides/remove_device_drivers_nsh.rst @@ -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 `. + +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. diff --git a/Documentation/guides/updating_release_system_elf.rst b/Documentation/guides/updating_release_system_elf.rst index 7b83e909d5..9969a54fc1 100644 --- a/Documentation/guides/updating_release_system_elf.rst +++ b/Documentation/guides/updating_release_system_elf.rst @@ -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