204 lines
7.9 KiB
ReStructuredText
204 lines
7.9 KiB
ReStructuredText
.. _mcumgr_handlers:
|
|
|
|
MCUmgr handlers
|
|
###############
|
|
|
|
Overview
|
|
********
|
|
|
|
MCUmgr functions by having group handlers which identify a group of functions relating to a
|
|
specific management area, which is addressed with a 16-bit identification value,
|
|
:c:enum:`mcumgr_group_t` contains the management groups available in Zephyr with their
|
|
corresponding group ID values. The group ID is included in SMP headers to identify which
|
|
group a command belongs to, there is also an 8-bit command ID which identifies the function of
|
|
that group to execute - see :ref:`mcumgr_smp_protocol_specification` for details on the SMP
|
|
protocol and header. There can only be one registered group per unique ID.
|
|
|
|
Implementation
|
|
**************
|
|
|
|
MCUmgr handlers can be added externally by application code or by module code, they do not have
|
|
to reside in the upstream Zephyr tree to be usable. The first step to creating a handler is to
|
|
create the folder structure for it, the typical Zephyr MCUmgr group layout is as follows:
|
|
|
|
.. code-block:: none
|
|
|
|
<dir>/grp/<grp_name>_mgmt/
|
|
├── CMakeLists.txt
|
|
├── Kconfig
|
|
├── include
|
|
├──── <grp_name>_mgmt.h
|
|
├──── <grp_name>_mgmt_callbacks.h
|
|
├── src
|
|
└──── <grp_name>_mgmt.c
|
|
|
|
Note that the header files in upstream Zephyr MCUmgr handlers reside in the
|
|
``zephyr/include/zephyr/mgmt/mcumgr/grp/<grp_name>_mgmt`` directory to allow the files to be
|
|
globally included by applications.
|
|
|
|
Initial header <grp_name>_mgmt.h
|
|
================================
|
|
|
|
The purpose of the header file is to provide defines which can be used by the MCUmgr handler
|
|
itself and application code, e.g. to reference the command IDs for executing functions. An example
|
|
file would look similar to:
|
|
|
|
.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/include/example_mgmt.h
|
|
:language: c
|
|
:linenos:
|
|
|
|
This provides the defines for 2 command ``test`` and ``other`` and sets up the SMP version 2 error
|
|
responses (which have unique error codes per group as opposed to the legacy SMP version 1 error
|
|
responses that return a :c:enum:`mcumgr_err_t` - there should always be an OK error code with the
|
|
value 0 and an unknown error code with the value 1. The above example then adds an error code of
|
|
``not wanted`` with value 2. In addition, the group ID is set to be
|
|
:c:enumerator:`MGMT_GROUP_ID_PERUSER`, which is the start group ID for user-defined groups, note
|
|
that group IDs need to be unique so other custom groups should use different values, a central index
|
|
header file (as upstream Zephyr has) can be used to distribute group IDs more easily.
|
|
|
|
Initial header <grp_name>_mgmt_callbacks.h
|
|
==========================================
|
|
|
|
The purpose of the header file is to provide defines which can be used by the MCUmgr handler
|
|
itself and application code, e.g. to reference the command IDs for executing functions. An example
|
|
file would look similar to:
|
|
|
|
.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/include/example_mgmt_callbacks.h
|
|
:language: c
|
|
:linenos:
|
|
|
|
This sets up a single event which application (or module) code can register for to receive a
|
|
callback when the function handler is executed, which allows the flow of the handler to be
|
|
changed (i.e. to return an error instead of continuing). The event group ID is set to
|
|
:c:enumerator:`MGMT_EVT_GRP_USER_CUSTOM_START`, which is the start event ID for user-defined groups,
|
|
note that event IDs need to be unique so other custom groups should use different values, a
|
|
central index header file (as upstream Zephyr has) can be used to distribute event IDs more
|
|
easily.
|
|
|
|
Initial source <grp_name>_mgmt.c
|
|
================================
|
|
|
|
The purpose of this source file is to handle the incoming MCUmgr commands, provide responses, and
|
|
register the transport with MCUmgr so that commands will be sent to it. An example file would
|
|
look similar to:
|
|
|
|
.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/src/example_mgmt.c
|
|
:language: c
|
|
:linenos:
|
|
|
|
The above code creates 2 function handlers, ``test`` which supports read requests and takes 2
|
|
required parameters, and ``other`` which supports write requests and takes 1 optional parameter,
|
|
this function handler has an optional notification callback feature that allows other parts of
|
|
the code to listen for the event and take any required actions that are necessary or prevent
|
|
further execution of the function by returning an error, further details on MCUmgr callback
|
|
functionality can be found on :ref:`mcumgr_callbacks`.
|
|
|
|
Note that other code referencing callbacks for custom MCUmgr handlers needs to include both the
|
|
base Zephyr callback include file and the custom handler callback file, only in-tree Zephyr
|
|
handler headers are included when including the upstream Zephyr callback header file.
|
|
|
|
Initial Kconfig
|
|
===============
|
|
|
|
The purpose of the Kconfig file is to provide options which users can enable or change relating
|
|
to the functionality of the handler being implemented. An example file would look similar to:
|
|
|
|
.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/Kconfig
|
|
:language: kconfig
|
|
|
|
Initial CMakeLists.txt
|
|
======================
|
|
|
|
The CMakeLists.txt file is used by the build system to setup files to compile, include
|
|
directories to add and specify options that can be changed. A basic file only need to include the
|
|
source files if the Kconfig options are enabled. An example file would look similar to:
|
|
|
|
.. tabs::
|
|
|
|
.. group-tab:: Zephyr module
|
|
|
|
.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/CMakeLists.txt
|
|
:language: cmake
|
|
|
|
.. group-tab:: Application
|
|
|
|
.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/CMakeLists.txt
|
|
:language: cmake
|
|
:start-after: Include handler files
|
|
|
|
Including from application
|
|
**************************
|
|
|
|
Application-specific MCUmgr handlers can be added by creating/editing application build files.
|
|
Example modifications are shown below.
|
|
|
|
Example CMakeLists.txt
|
|
======================
|
|
|
|
The application ``CMakeLists.txt`` file can load the CMake file for the example MCUmgr handler by
|
|
adding the following:
|
|
|
|
.. code-block:: cmake
|
|
|
|
add_subdirectory(mcumgr/grp/<grp_name>)
|
|
|
|
Example Kconfig
|
|
===============
|
|
|
|
The application Kconfig file can include the Kconfig file for the example MCUmgr handler by adding
|
|
the following to the ``Kconfig`` file in the application directory (or creating it if it does not
|
|
exist):
|
|
|
|
.. code-block:: kconfig
|
|
|
|
rsource "mcumgr/grp/<grp_name>/Kconfig"
|
|
|
|
# Include Zephyr's Kconfig
|
|
source "Kconfig.zephyr"
|
|
|
|
Including from Zephyr Module
|
|
****************************
|
|
|
|
Zephyr :ref:`modules` can be used to add custom MCUmgr handlers to multiple different applications
|
|
without needing to duplicate the code in each application's source tree, see :ref:`module-yml` for
|
|
details on how to set up the module files. Example files are shown below.
|
|
|
|
Example zephyr/module.yml
|
|
=========================
|
|
|
|
This is an example file which can be used to load the Kconfig and CMake files from the root of the
|
|
module directory, and would be placed at ``zephyr/module.yml``:
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
kconfig: Kconfig
|
|
cmake: .
|
|
|
|
Example CMakeLists.txt
|
|
======================
|
|
|
|
This is an example CMakeLists.txt file which loads the CMake file for the example MCUmgr handler,
|
|
and would be placed at ``CMakeLists.txt``:
|
|
|
|
.. code-block:: cmake
|
|
|
|
add_subdirectory(mcumgr/grp/<grp_name>)
|
|
|
|
Example Kconfig
|
|
===============
|
|
|
|
This is an example Kconfig file which loads the Kconfig file for the example MCUmgr handler, and
|
|
would be placed at ``Kconfig``:
|
|
|
|
.. code-block:: kconfig
|
|
|
|
rsource "mcumgr/grp/<grp_name>/Kconfig"
|
|
|
|
Demonstration handler
|
|
*********************
|
|
|
|
There is a demonstration project which includes configuration for both application and zephyr
|
|
module-MCUmgr handlers which can be used as a basis for created your own in
|
|
:zephyr_file:`tests/subsys/mgmt/mcumgr/handler_demo/`.
|