1d1bdd85a3
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
204 lines
8.4 KiB
ReStructuredText
204 lines
8.4 KiB
ReStructuredText
***************************
|
|
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.
|