This is an automated email from the ASF dual-hosted git repository. ccollins pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push: new 585bc6c docs: sysinit and sysdown 585bc6c is described below commit 585bc6cc44f82978fbde7946576033bc9b59f09f Author: Christopher Collins <ccoll...@apache.org> AuthorDate: Fri Aug 7 10:21:20 2020 -0700 docs: sysinit and sysdown This commit removes sysinit from the syscfg+sysinit page and moves it to its own page. It also adds a section for sysdown to the new page. --- docs/os/core_os/mynewt_os.rst | 2 +- docs/os/modules/sysinitconfig/sysinitconfig.rst | 183 +-------------- docs/os/modules/sysinitdown/sysinitdown.rst | 282 ++++++++++++++++++++++++ docs/os/os_user_guide.rst | 1 + 4 files changed, 289 insertions(+), 179 deletions(-) diff --git a/docs/os/core_os/mynewt_os.rst b/docs/os/core_os/mynewt_os.rst index 9338723..2807d43 100644 --- a/docs/os/core_os/mynewt_os.rst +++ b/docs/os/core_os/mynewt_os.rst @@ -80,7 +80,7 @@ task. The main steps are: 3. In your application ``main()`` function, call the ``sysinit()`` function to initialize the system and packages, perform application specific initialization, then wait and dispatch events from the OS - default event queue in an infinite loop. (See :doc:`../modules/sysinitconfig/sysinitconfig` + default event queue in an infinite loop. (See :doc:`../modules/sysinitdown/sysinitdown` for more details.) Initializing application modules and tasks can get somewhat complicated diff --git a/docs/os/modules/sysinitconfig/sysinitconfig.rst b/docs/os/modules/sysinitconfig/sysinitconfig.rst index bda1fb0..cd52e93 100644 --- a/docs/os/modules/sysinitconfig/sysinitconfig.rst +++ b/docs/os/modules/sysinitconfig/sysinitconfig.rst @@ -1,4 +1,4 @@ -Compile-Time Configuration and Initialization +Compile-Time Configuration ----------------------------------------------- .. toctree:: @@ -6,10 +6,10 @@ Compile-Time Configuration and Initialization sysconfig_error -This guide describes how Mynewt manages system configuration and -initialization. It shows you how to tell Mynewt to use default or -customized values to initialize packages that you develop or use to -build a target. This guide: +This guide describes how Mynewt manages system configuration. It shows +you how to tell Mynewt to use default or customized values to +configure packages that you develop or use to build a target. This +guide: - Assumes you have read the :ref:`concepts` section that describes @@ -17,9 +17,6 @@ build a target. This guide: ``syscfg.yml`` files. - Assumes you have read the Mynewt :doc:`../../../newt/newt_operation` and are familiar with how newt determines package dependencies for your target build. -- Covers only the system initialization for hardware independent - packages. It does not cover the Board Support Package (BSP) and other - hardware dependent system initialization. .. contents:: :local: @@ -28,8 +25,6 @@ build a target. This guide: Mynewt defines several configuration parameters in the ``pkg.yml`` and ``syscfg.yml`` files. The newt tool uses this information to: -- Generate a system initialization function that calls all the - package-specific system initialization functions. - Generate a system configuration header file that contains all the package configuration settings and values. - Display the system configuration settings and values in the @@ -512,171 +507,3 @@ when the setting value is non-zero. SYSINIT_PANIC_ASSERT(rc == 0); #endif } - -System Initialization -~~~~~~~~~~~~~~~~~~~~~ - -During system startup, Mynewt creates a default event queue and a main -task to process events from this queue. You can override the -``OS_MAIN_TASK_PRIO`` and ``OS_MAIN_TASK_STACK_SIZE`` setting values -defined by the ``kernel/os`` package to specify different task priority -and stack size values. - -Your application's ``main()`` function executes in the context of the -main task and must perform the following: - -- At the start of ``main()``, call the Mynewt ``sysinit()`` function to - initialize the packages before performing any other processing. -- At the end of ``main()``, wait for and dispatch events from the - default event queue in an infinite loop. - -**Note:** You must include the ``sysinit/sysinit.h`` header file to -access the ``sysinit()`` function. - -Here is an example of a ``main()`` function: - -.. code-block:: cpp - - int - main(int argc, char **argv) - { - /* First, call sysinit() to perform the system and package initialization */ - sysinit(); - - /* ... other application initialization processing ... */ - - /* Last, process events from the default event queue. */ - while (1) { - os_eventq_run(os_eventq_dflt_get()); - } - /* main never returns */ - } - -Specifying Package Initialization Functions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The ``sysinit()`` function calls the ``sysinit_app()`` function to -perform system initialization for the packages in the target. You can, -optionally, specify one or more package initialization functions that -``sysinit_app()`` calls to initialize a package. - -A package initialization function must have the following prototype: - -.. code-block:: cpp - - void init_func_name(void) - -Package initialization functions are called in stages to ensure that -lower priority packages are initialized before higher priority packages. -A stage is an integer value, 0 or higher, that specifies when an -initialization function is called. Mynewt calls the package -initialization functions in increasing stage number order. The call -order for initialization functions with the same stage number depends on -the order the packages are processed, and you cannot rely on a specific -call order for these functions. - -You use the ``pkg.init`` parameter in the ``pkg.yml`` file to specify an -initialization function and the stage number to call the function. You -can specify multiple initialization functions, with a different stage -number for each function, for the parameter values. This feature allows -packages with interdependencies to perform initialization in multiple -stages. - -The ``pkg.init`` parameter has the following syntax in the ``pkg.yml`` -file: - -.. code-block:: yaml - - pkg.init: - pkg_init_func1_name: pkg_init_func1_stage - pkg_init_func2_name: pkg_init_func2_stage - - ... - - pkg_init_funcN_name: pkg_init_funcN_stage - -where ``pkg_init_func#_name`` is the C function name of an -initialization function, and ``pkg_init_func#_stage`` is an integer -value, 0 or higher, that indicates the stage when the -``pkg_init_func#_name`` function is called. - -**Note:** The ``pkg.init_function`` and ``pkg.init_stage`` parameters -introduced in a previous release for specifying a package initialization -function and a stage number are deprecated and have been retained to -support the legacy format. They will not be maintained for future -releases and we recommend that you migrate to use the ``pkg.init`` -parameter. - -Generated sysinit_app() Function -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The newt tool processes the ``pkg.init`` parameters in all the -``pkg.yml`` files for a target, generates the ``sysinit_app()`` function -in the ``<target-path>/generated/src/<target-name>-sysinit_app.c`` file, -and includes the file in the build. Here is an example ``sysinit_app()`` -function: - -.. code-block:: cpp - - /** - * This file was generated by Apache Newt (incubating) version: 1.0.0-dev - */ - - #if !SPLIT_LOADER - - void split_app_init(void); - void os_pkg_init(void); - void imgmgr_module_init(void); - - /* ... */ - - void stats_module_init(void); - - void - sysinit_app(void) - { - - /*** Stage 0 */ - /* 0.0: kernel/os */ - os_pkg_init(); - - /*** Stage 2 */ - /* 2.0: sys/flash_map */ - flash_map_init(); - - /*** Stage 10 */ - /* 10.0: sys/stats/full */ - stats_module_init(); - - /*** Stage 20 */ - /* 20.0: sys/console/full */ - console_pkg_init(); - - /*** Stage 100 */ - /* 100.0: sys/log/full */ - log_init(); - /* 100.1: sys/mfg */ - mfg_init(); - - /* ... */ - - /*** Stage 300 */ - /* 300.0: sys/config */ - config_pkg_init(); - - /*** Stage 500 */ - /* 500.0: sys/id */ - id_init(); - /* 500.1: sys/shell */ - shell_init(); - - /* ... */ - - /* 500.4: mgmt/imgmgr */ - imgmgr_module_init(); - - /*** Stage 501 */ - /* 501.0: mgmt/newtmgr/transport/nmgr_shell */ - nmgr_shell_pkg_init(); - } - #endif diff --git a/docs/os/modules/sysinitdown/sysinitdown.rst b/docs/os/modules/sysinitdown/sysinitdown.rst new file mode 100644 index 0000000..8fd131c --- /dev/null +++ b/docs/os/modules/sysinitdown/sysinitdown.rst @@ -0,0 +1,282 @@ +System Initialization and System Shutdown +----------------------------------------- + +.. toctree:: + :hidden: + +Mynewt allows a package to designate startup and shutdown functions. +These functions are called automatically by the OS using facilities +called *sysinit* and *sysdown*. + +This guide: + +- Assumes you have read the + :ref:`concepts` section that describes + the Mynewt package hierarchy and its use of the ``pkg.yml`` and + ``syscfg.yml`` files. +- Assumes you have read the Mynewt :doc:`../../../newt/newt_operation` and are familiar with how newt + determines package dependencies for your target build. + +.. contents:: + :local: + :depth: 3 + +System Initialization +~~~~~~~~~~~~~~~~~~~~~ + +During system startup, Mynewt creates a default event queue and a main +task to process events from this queue. You can override the +``OS_MAIN_TASK_PRIO`` and ``OS_MAIN_TASK_STACK_SIZE`` setting values +defined by the ``kernel/os`` package to specify different task priority +and stack size values. + +Your application's ``main()`` function executes in the context of the +main task and must perform the following: + +- At the start of ``main()``, call the Mynewt ``sysinit()`` function to + initialize the packages before performing any other processing. +- At the end of ``main()``, wait for and dispatch events from the + default event queue in an infinite loop. + +**Note:** You must include the ``sysinit/sysinit.h`` header file to +access the ``sysinit()`` function. + +Here is an example of a ``main()`` function: + +.. code-block:: cpp + + int + main(int argc, char **argv) + { + /* First, call sysinit() to perform the system and package initialization */ + sysinit(); + + /* ... other application initialization processing ... */ + + /* Last, process events from the default event queue. */ + while (1) { + os_eventq_run(os_eventq_dflt_get()); + } + /* main never returns */ + } + +Specifying Package Initialization Functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``sysinit()`` function calls the ``sysinit_app()`` function to +perform system initialization for the packages in the target. You can, +optionally, specify one or more package initialization functions that +``sysinit_app()`` calls to initialize a package. + +A package initialization function must have the following prototype: + +.. code-block:: cpp + + void init_func_name(void) + +Sysinit functions are not expected to fail. If a sysinit function +encounters an unrecoverable failure, it should invoke one of the +``SYSINIT_PANIC`` macros. By default, these macros trigger a crash, +but the behavior can be overridden by configuring the panic function +with ``sysinit_panic_set()``. + +Package initialization functions are called in stages to ensure that +lower priority packages are initialized before higher priority packages. +A stage is an integer value, 0 or higher, that specifies when an +initialization function is called. Mynewt calls the package +initialization functions in increasing stage number order. When +multiple init functions have the same stage number, they are called in +lexicographic order (by function name). + +You use the ``pkg.init`` parameter in the ``pkg.yml`` file to specify an +initialization function and the stage number to call the function. You +can specify multiple initialization functions with a different stage +number for each function for the parameter values. This feature allows +packages with interdependencies to perform initialization in multiple +stages. + +The ``pkg.init`` parameter has the following syntax in the ``pkg.yml`` +file: + +.. code-block:: yaml + + pkg.init: + pkg_init_func1_name: pkg_init_func1_stage + pkg_init_func2_name: pkg_init_func2_stage + + ... + + pkg_init_funcN_name: pkg_init_funcN_stage + +where ``pkg_init_func#_name`` is the C function name of an +initialization function, and ``pkg_init_func#_stage`` is an integer +value, 0 or higher, that indicates the stage when the +``pkg_init_func#_name`` function is called. + +Generated sysinit_app() Function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The newt tool processes the ``pkg.init`` parameters in all the +``pkg.yml`` files for a target, generates the ``sysinit_app()`` function +in the ``<target-path>/generated/src/<target-name>-sysinit_app.c`` file, +and includes the file in the build. Here is an example ``sysinit_app()`` +function: + +.. code-block:: cpp + + /** + * This file was generated by Apache Newt (incubating) version: 1.0.0-dev + */ + + #if !SPLIT_LOADER + + void split_app_init(void); + void os_pkg_init(void); + void imgmgr_module_init(void); + + /* ... */ + + void stats_module_init(void); + + void + sysinit_app(void) + { + + /*** Stage 0 */ + /* 0.0: kernel/os */ + os_pkg_init(); + + /*** Stage 2 */ + /* 2.0: sys/flash_map */ + flash_map_init(); + + /*** Stage 10 */ + /* 10.0: sys/stats/full */ + stats_module_init(); + + /*** Stage 20 */ + /* 20.0: sys/console/full */ + console_pkg_init(); + + /*** Stage 100 */ + /* 100.0: sys/log/full */ + log_init(); + /* 100.1: sys/mfg */ + mfg_init(); + + /* ... */ + + /*** Stage 300 */ + /* 300.0: sys/config */ + config_pkg_init(); + + /*** Stage 500 */ + /* 500.0: sys/id */ + id_init(); + /* 500.1: sys/shell */ + shell_init(); + + /* ... */ + + /* 500.4: mgmt/imgmgr */ + imgmgr_module_init(); + + /*** Stage 501 */ + /* 501.0: mgmt/newtmgr/transport/nmgr_shell */ + nmgr_shell_pkg_init(); + } + #endif + +System Shutdown +~~~~~~~~~~~~~~~ + +A Mynewt package can specify a sequence of system shutdown ("sysdown") +function calls. As with sysinit, a stage number is associated with +each function. On shutdown, sysdown functions are executed in +ascending order of stage number. In the case of a tie, functions are +executed in lexicographic order (by function name). + +The sysdown procedure is only performed for a controlled +shutdown. It is executed when the system processes a newtmgr +"reset" command, for example. It is not be executed when the system +crashes, browns out, or restarts due to the hardware watchdog. + +Sysdown functions are specified in a ``pkg.yml`` file using the +``pkg.down`` key. They use the following function type: + +.. code-block:: cpp + + int func(int reason) + +The ``reason`` parameter is currently unused and should be ignored. + +Each shutdown callback returns one of the following codes: + +- ``SYSDOWN_COMPLETE`` +- ``SYSDOWN_IN_PROGRESS`` + +If a sysdown function is able to complete its work synchronously, it +should return ``SYSDOWN_COMPLETE``. + +The "in progress" case is a bit more complicated. Sysdown functions +should not block on the current task (e.g., they should not tell the +default task to do something and then wait for the result). Blocking +like this will result in a deadlock since the current task is waiting +for the sysdown function to complete. + +Instead, if a sysdown function needs to do extra work in the current +task, it should do so asynchronously. That is, it should enqueue an +event to the task's event queue, then return ``SYSDOWN_IN_PROGRESS``. +When the sysdown procedure eventually completes, the task should call +``sysdown_release``. + +When all sysdown procedures have completed, Mynewt proceeds to reset +the device. If it takes longer than ``MYNEWT_VAL(SYSDOWN_TIMEOUT_MS)`` +milliseconds (default: 10s) for all shutdown procedures to complete, a +crash is triggered and the device resets. + +As an example, the NimBLE BLE host package configures a sysdown +function that terminates all open connections. Its ``pkg.yml`` +contains the following map: + +.. code-block:: yaml + + pkg.down: + ble_hs_shutdown: 200 + +and ``ble_hs_shutdown`` is defined as follows: + +.. code-block:: cpp + + int + ble_hs_shutdown(int reason) + { + int rc; + + /* Ensure this function only gets called by sysdown. */ + SYSDOWN_ASSERT_ACTIVE(); + + /* Initiate a host stop procedure. */ + rc = ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, + NULL); + switch (rc) { + case 0: + /* Stop initiated. Wait for result to be reported asynchronously. */ + return SYSDOWN_IN_PROGRESS; + + case BLE_HS_EBUSY: + /* Already stopping. Wait for result to be reported asynchronously. */ + return SYSDOWN_IN_PROGRESS; + + case BLE_HS_EALREADY: + /* Already stopped. Shutdown complete. */ + return SYSDOWN_COMPLETE; + + default: + BLE_HS_LOG(ERROR, "ble_hs_shutdown: failed to stop host; rc=%d\n", rc); + return SYSDOWN_COMPLETE; + } + } + +In the cases where this function returns ``SYSDOWN_IN_PROGRESS``, the +host eventually calls ``sysdown_release`` when the procedure completes. diff --git a/docs/os/os_user_guide.rst b/docs/os/os_user_guide.rst index 806683b..fe5a94b 100644 --- a/docs/os/os_user_guide.rst +++ b/docs/os/os_user_guide.rst @@ -16,6 +16,7 @@ OS User Guide Device Management with MCUmgr <modules/mcumgr/mcumgr> Image Manager <modules/imgmgr/imgmgr> Compile-Time Configuration <modules/sysinitconfig/sysinitconfig> + System Initialization and Shutdown <modules/sysinitdown/sysinitdown> File System <modules/fs/fs> Flash Circular Buffer <modules/fcb/fcb> Sensor Framework <modules/sensor_framework/sensor_framework>