| =========================== |
| NSH "Built-In" Applications |
| =========================== |
| |
| **Overview.** In addition to these commands that are a part of NSH, |
| external programs can also be executed as NSH commands. These external |
| programs are called "Built-In" Applications for historic reasons. That |
| terminology is somewhat confusing because the actual NSH commands as |
| described above are truly "built-into" NSH whereas these applications |
| are really external to NuttX. |
| |
| These applications are built-into NSH in the sense that they can be |
| executed by simply typing the name of the application at the NSH prompt. |
| Built-in application support is enabled with these configuration option: |
| |
| - ``CONFIG_BUILTIN``: Enable NuttX support for builtin applications. |
| - ``CONFIG_NSH_BUILTIN_APPS``: Enable NSH support for builtin |
| applications. |
| |
| When these configuration options are set, you will also be able to see |
| the built-in applications if you enter "nsh> help". They will appear at |
| the bottom of the list of NSH commands under:: |
| |
| Builtin Apps: |
| |
| Note that no detailed help information beyond the name of the built-in |
| application is provided. |
| |
| Built-In Applications |
| ===================== |
| |
| **Overview.** The underlying logic that supports the NSH built-in |
| applications is called "Built-In Applications". The builtin application |
| logic can be found at ``apps/builtin``. This logic simply does the |
| following: |
| |
| #. It supports registration mechanism so that builtin applications can |
| dynamically register themselves at build time, and |
| |
| #. Utility functions to look up, list, and execute the builtin |
| applications. |
| |
| **Built-In Application Utility Functions**. The utility functions |
| exported by the builtin application logic are prototyped in |
| ``nuttx/include/nuttx/lib/builtin.h`` and ``apps/include/builtin.h``. |
| These utility functions include: |
| |
| - ``int builtin_isavail(FAR const char *appname);`` Checks for |
| availability of application registered as ``appname`` during build |
| time. |
| |
| - ``const char *builtin_getname(int index);`` Returns a pointer to a |
| name of built-in application pointed by the ``index``. This is the |
| utility function that is used by NSH in order to list the available |
| built-in applications when "``nsh> help``" is entered. |
| |
| - ``int exec_builtin(FAR const char *appname, FAR const char **argv);`` |
| Executes built-in builtin application registered during compile time. |
| This is the utility function used by NSH to execute the built-in |
| application. |
| |
| **Autogenerated Header Files**. Application entry points with their |
| requirements are gathered together in two files when NuttX is first |
| built: |
| |
| #. ``apps/builtin/builtin_proto.h``: Prototypes of application task |
| entry points. |
| |
| #. ``apps/builtin/builtin_list.h``: Application specific information and |
| start-up requirements |
| |
| **Registration of Built-In Applications**. The NuttX build occurs in |
| several phases as different build targets are executed: (1) *context* |
| when the configuration is established, (2) *depend* when target |
| dependencies are generated, and (3) *default* (``all``) when the normal |
| compilation and link operations are performed. Built-in application |
| information is collected during the make *context* build phase. |
| |
| An example application that can be "built-in" is be found in the |
| ``apps/examples/hello directory``. Let's walk through this specific |
| cause to illustrate the general way that built-in applications are |
| created and how they register themselves so that they can be used from |
| NSH. |
| |
| ``apps/examples/hello``. The main routine for apps/examples/hello can be |
| found in ``apps/examples/hello/main.c``. The main routine is: |
| |
| .. code-block:: c |
| |
| int hello_main(int argc, char *argv[]) |
| { |
| printf("Hello, World!!\n"); |
| return 0; |
| } |
| |
| This is the built in function that will be registered during the |
| *context* build phase of the NuttX build. That registration is performed |
| by logic in ``apps/examples/hello/Makefile``. But the build system gets |
| to that logic through a rather tortuous path: |
| |
| #. The top-level context make target is in ``nuttx/Makefile``. All build |
| targets depend upon the *context* build target. For the ``apps/`` |
| directory, this build target will execute the *context* target in the |
| ``apps/Makefile``. |
| |
| #. The ``apps/Makefile`` will, in turn, execute the *context* targets in |
| all of the configured sub-directories. In our case will include the |
| ``Makefile`` in ``apps/examples``. |
| |
| #. And finally, the ``apps/examples/Makefile`` will execute the |
| *context* target in all configured ``example``\ sub-directories, |
| getting us finally to ``apps/examples/Makefile`` which is covered |
| below. |
| |
| **NOTE**: Since this context build phase can only be executed one time, |
| any subsequent configuration changes that you make will, then, not be |
| reflected in the build sequence. That is a common area of confusion. |
| Before you can instantiate the new configuration, you have to first get |
| rid of the old configuration. The most drastic way to this is:: |
| |
| make distclean |
| |
| But then you will have to re-configuration NuttX from scratch. But if |
| you only want to re-build the configuration in the ``apps/`` |
| sub-directory, then there is a less labor-intensive way to do that. The |
| following NuttX make command will remove the configuration only from the |
| ``apps/`` directory and will let you continue without re-configuring |
| everything:: |
| |
| make apps_distclean |
| |
| Logic for the ``context`` target in ``apps/examples/hello/Makefile`` |
| registers the ``hello_main()`` application in the ``builtin``'s |
| ``builtin_proto.h``\ and ``builtin_list.h`` files. That logic that does |
| that in ``apps/examples/hello/Makefile`` is abstracted below: |
| |
| #. First, the ``Makefile`` includes ``apps/Make.defs``:: |
| |
| include $(APPDIR)/Make.defs |
| |
| This defines a macro called ``REGISTER`` that adds data to the |
| *builtin* header files:: |
| |
| define REGISTER |
| @echo "Register: $1" |
| @echo "{ \"$1\", $2, $3, $4 }," >> "$(APPDIR)/builtin/builtin_list.h" |
| @echo "EXTERN int $4(int argc, char *argv[]);" >> "$(APPDIR)/builtin/builtin_proto.h" |
| endef |
| |
| When this macro runs, you will see the output in the build |
| "``Register: hello``", that is a sure sign that the registration was |
| successful. |
| |
| #. The make file then defines the application name (``hello``), the task |
| priority (default), and the stack size that will be allocated in the |
| task runs (2K):: |
| |
| APPNAME = hello |
| PRIORITY = SCHED_PRIORITY_DEFAULT |
| STACKSIZE = 2048 |
| |
| #. And finally, the ``Makefile`` invokes the ``REGISTER`` macro to added |
| the ``hello_main()`` builtin application. Then, when the system build |
| completes, the ``hello`` command can be executed from the NSH command |
| line. When the ``hello`` command is executed, it will start the task |
| with entry point ``hello_main()`` with the default priority and with |
| a stack size of 2K:: |
| |
| context: |
| $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) |
| |
| **Other Uses of Built-In Application.** The primary purpose of builtin |
| applications is to support command line execution of applications from |
| NSH. However, there is one other use of builtin applications that should |
| be mentioned. |
| |
| #. **binfs**. *binfs* is a tiny file system located at |
| ``apps/builtin/binfs.c``. This provides an alternative what of |
| visualizing installed builtin applications. Without *binfs*, you can |
| see the installed builtin applications using the NSH help command. |
| *binfs* will create a tiny pseudo-file system mounted at ``/bin``. |
| Using *binfs*, you can see the available builtin applications by |
| listing the contents of ``/bin`` directory. This gives some |
| superficial Unix-like compatibility, but does not really add any new |
| functionality. |
| |
| Synchronous Built-In Applications |
| ================================= |
| |
| By default, built-in commands started from the NSH command line will run |
| asynchronously with NSH. If you want to force NSH to execute commands |
| then wait for the command to execute, you can enable that feature by |
| adding the following to the NuttX configuration file:: |
| |
| CONFIG_SCHED_WAITPID=y |
| |
| This configuration option enables support for the standard ``waitpid()`` |
| RTOS interface. When that interface is enabled, NSH will use it to wait, |
| sleeping until the built-in application executes to completion. |
| |
| Of course, even with ``CONFIG_SCHED_WAITPID=y`` defined, specific |
| applications can still be forced to run asynchronously by adding the |
| ampersand (&) after the NSH command. |