Skip to content

Commit

Permalink
sm_ipt: Add Shared Memory Inter-Processor Transport
Browse files Browse the repository at this point in the history
SM_IPT is OS independent shared memory
communication protocol, which works on shared memory
and provides os-porting header templates.

Signed-off-by: Dominik Chat <dominik.chat@nordicsemi.no>

Co-authored-by: Dominik Kilian <Dominik.Kilian@nordicsemi.no>
  • Loading branch information
dchat-nordic and doki-nordic committed Aug 23, 2021
1 parent 59179ff commit 0f500c5
Show file tree
Hide file tree
Showing 15 changed files with 1,158 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2019 - 2020 Nordic Semiconductor
# Copyright (c) 2019 - 2021 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
Expand All @@ -19,3 +19,4 @@ add_subdirectory_ifdef(CONFIG_BT softdevice_controller)
add_subdirectory_ifdef(CONFIG_NET_L2_OPENTHREAD openthread)
add_subdirectory_ifdef(CONFIG_NRF_RPC nrf_rpc)
add_subdirectory_ifdef(CONFIG_ZIGBEE zboss)
add_subdirectory_ifdef(CONFIG_SM_IPT sm_ipt)
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ doc/* @b-gent
/zboss/ @tomchy
/zephyr/ @carlescufi
/nrf_rpc/ @doki-nordic @KAGA164
/sm_ipt/ @doki-nordic
3 changes: 2 additions & 1 deletion Kconfig.nrfxlib
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2019 - 2020 Nordic Semiconductor
# Copyright (c) 2019 - 2021 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
Expand All @@ -13,6 +13,7 @@ rsource "crypto/Kconfig"
rsource "nrf_security/Kconfig"
rsource "softdevice_controller/Kconfig"
rsource "nrf_rpc/Kconfig"
rsource "sm_ipt/Kconfig"
rsource "zboss/Kconfig"
rsource "openthread/Kconfig"
rsource "nrf_802154/zephyr/Kconfig.nrfxlib"
Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ Refer to their respective documentation for more information.
nrf_rpc/README
softdevice_controller/README
zboss/README
sm_ipt/README
11 changes: 11 additions & 0 deletions sm_ipt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# Copyright (c) 2021 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

zephyr_include_directories(include)

zephyr_library()

zephyr_library_sources(sm_ipt.c)
42 changes: 42 additions & 0 deletions sm_ipt/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#
# Copyright (c) 2021 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

menuconfig SM_IPT
bool "Shared memory Inter-Processor Transport"
help
Enable Shared memory Inter-Processor Transport library

if SM_IPT

choice
prompt "Shared memory blocks"
default SM_IPT_NUM_BLOCKS_32

config SM_IPT_NUM_BLOCKS_32
bool "32"
help
Selects 32 shared memory blocks per single input or output channel.

config SM_IPT_NUM_BLOCKS_64
bool "64"
help
Selects 64 shared memory blocks per single input or output channel.
This will increase allocatable memory granularity, but it will have
some impact on performance and code size.

endchoice

config SM_IPT_PRIMARY
bool "Primary role"
help
One side must have primary role (this option selected) and the other
side must have secondary role. Shared memory layout depends on this configuration.

module = SM_IPT
module-str = SM IPT
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"

endif # SM_IPT
16 changes: 16 additions & 0 deletions sm_ipt/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.. _sm_ipt:

Shared Memory Inter-Processor Transport library (SM IPT)
########################################################

SM IPT is a inter-processor transport library for |NCS| enabling inter-processor communication on Nordic Semiconductor SoCs.
The library is RTOS-agnostic and provides porting templates.

It is designed to be used with as a transport layer, or standalone.

.. toctree::
:maxdepth: 2
:caption: Subpages:

doc/usage
doc/api
17 changes: 17 additions & 0 deletions sm_ipt/doc/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.. _sm_ipt_api:

API documentation
#################

.. contents::
:local:
:depth: 2

.. _sm_ipt_api_documentation:

SM IPT
------

.. doxygengroup:: sm_ipt
:project: nrfxlib
:members:
3 changes: 3 additions & 0 deletions sm_ipt/doc/img/architecture.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
213 changes: 213 additions & 0 deletions sm_ipt/doc/usage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
.. _sm_ipt_usage:

Usage and implementation
########################

.. contents::
:local:
:depth: 2

The following picture gives an overview of the SM IPT architecture:

.. figure:: img/architecture.drawio.svg
:alt: SM IPT architecture layers
:align: center

SM IPT architecture layers

Usage
=====

.. note::
Following examples are purely conceptual and simplified to demonstrate the library functions.
They should be rewritten to suit particular need and use OS modules like FIFO.

Initialization
--------------

The initialization function initializes the context data and retrieves the shared memory parameters from the :c:func:`sm_ipt_os_init` function.

.. code-block:: c
struct sm_ipt_ctx sm_ipt_ctx;
void sm_ipt_receive_handler(const uint8_t *packet, size_t len)
{
/* Process data */
some_data_processing_function();
}
int initialize(void)
{
return sm_ipt_init(&sm_ipt_ctx, sm_ipt_receive_handler);
}
The above code uses the :c:func:`sm_ipt_init` function to initialize the :c:struct:`sm_ipt_ctx` SM IPT context data structure and to assign the receive handler.

Data send full-copy
-------------------

The data is prepared beforehand, copied into the allocated buffer and sent to another core.

.. code-block:: c
int send(const void *data, size_t len)
{
uint8_t *buffer;
sm_ipt_alloc_tx_buf(&sm_ipt_ctx, &buffer, len);
memcpy(buffer, data, len);
return sm_ipt_send(&sm_ipt_ctx, buffer, len);
}
The above code uses the :c:func:`sm_ipt_alloc_tx_buf` function to allocate the transmit buffer in the shared memory.
The data is copied into the said buffer and sent to another core through the :c:func:`sm_ipt_send` function.

Data send no-copy
-----------------

It is possible to operate directly on the transmit buffer to avoid copying from the local buffer.

.. code-block:: c
int send_nocopy(size_t len)
{
uint8_t *buffer;
size_t i;
sm_ipt_alloc_tx_buf(&sm_ipt_ctx, &buffer, len);
/* Use buffer as any other allocated buffer */
some_data_preparation_function(buffer);
return sm_ipt_send(&sm_ipt_ctx, buffer, len);
}
The above code uses the :c:func:`sm_ipt_alloc_tx_buf` function to allocate the transmit buffer in the shared memory.
The buffer is prepared by the :c:func:`some_data_preparation_function` and sent to another core through the :c:func:`sm_ipt_send` function.

Data send abort
---------------

It is possible to free the transmit buffer instead of sending it.

.. code-block:: c
int send_if(size_t len)
{
uint8_t *buffer;
bool preparation_success;
sm_ipt_alloc_tx_buf(&sm_ipt_ctx, &buffer, len);
/* Prepare some data */
preparation_success = some_data_preparation_function(buffer);
if (preparation_success) {
return sm_ipt_send(&sm_ipt_ctx, buffer, len);
} else {
sm_ipt_free_tx_buf(&sm_ipt_ctx, buffer);
return ERROR_ABORT;
}
}
The above code uses the :c:func:`sm_ipt_alloc_tx_buf` function to allocate the transmit buffer in the shared memory.
The buffer is sent only if ``preparation_success`` is true.
If ``preparation_success`` is false the buffer is free using the :c:func:`sm_ipt_free_tx_buf` and the send operation is aborted.

Data receive full-copy
----------------------

When data is received, it can be processed using the full-copy mechanism.
The buffer must be copied to the local memory.
The shared memory rx buffer must be freed and data processing takes place on the local copy of the buffer.

.. code-block:: c
void sm_ipt_receive_handler(const uint8_t *packet, size_t len)
{
/* Write content of the buffer to some pipe */
write_bytes_to_pipe(packet, len);
/* Free receive buffer */
sm_ipt_free_rx_buf(&sm_ipt_ctx, packet);
/* Signal message received */
data_received = true;
}
The above code uses the :c:func:`write_bytes_to_pipe` function to copy the shared memory buffer into the local pipe.
The shared memory buffer is freed using the :c:func:`sm_ipt_free_rx_buf` function.
The data is processed locally using a copy of the shared memory buffer.

Data receive no-copy
--------------------

When the data is received, it can be processed using the no-copy mechanism.
The pointer to the shared memory buffer must be saved for later use.
The shared memory rx buffer must be freed and data processing takes place on the shared memory buffer.

.. note::
This approach increases the risk of out-of-memory errors if the buffer is not freed right after receiving data.

.. code-block:: c
void sm_ipt_receive_handler(const uint8_t *packet, size_t len)
{
/* Put the buffer pointer to some FIFO */
put_buffer_ptr_to_fifo(packet, len);
}
void data_processing_thread(void)
{
uint8_t *packet;
size_t len;
/* Wait for incoming data */
get_buffer_ptr_from_fifo(&packet, &len);
/*Process data */
some_data_processing_function(packet, len);
/* Free receive buffer */
sm_ipt_free_rx_buf(&sm_ipt_ctx, packet);
}
The above code puts the pointer to the shared memory buffer to the local fifo using :c:func:`put_buffer_ptr_to_fifo` function.
Next data is processed using the original buffer in the shared memory.
The shared memory buffer is freed using the :c:func:`sm_ipt_free_rx_buf` function.


Lower layers
============

The lower layers of SM IPT are OS-dependent.
They are responsible for memory management, synchronization and logging support.

.. note::
Details about the implementation of the lower layers are not required when using the SM IPT API.
However, this knowledge is needed to port to a different operating system.

Operating system abstraction
----------------------------

The operating system abstraction provides the SM IPT functionalities that depend on the operating system.
It manages the shared memory, thread synchronization, and atomic support.

The template header describing the OS abstraction is :file:`template/sm_ipt_os_tmpl.h`.


Logging
-------

SM IPT logs some of its activities.
This allows for tracking, diagnosis, and debugging.
It provides four levels for logging: errors, warnings, information, and debug.

Error logs indicate serious errors, so they should be enabled if possible.
Debug logs should be enabled only for debugging purpose.

The template header describing the logger is :file:`template/sm_ipt_log_tmpl.h`.
Loading

0 comments on commit 0f500c5

Please sign in to comment.