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>
  • Loading branch information
dchat-nordic committed Aug 9, 2021
1 parent 59179ff commit 8e04175
Show file tree
Hide file tree
Showing 15 changed files with 1,104 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_ifdef(CONFIG_SM_IPT 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 shared memory blocks per channel"
help
Selects 32 shared memory blocks per single input or output channel.

config SM_IPT_NUM_BLOCKS_64
bool "64 shared memory blocks per channel"
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 API documentation
----------------------

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

Usage and Implementation
########################

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

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

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

SM IPT architecture layers

Usage
=====

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


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

The initialization function initializes context data and retrieves shared memory parameters from ``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_funtion();
}
int initialize(void)
{
return sm_ipt_init(&sm_ipt_ctx, sm_ipt_receive_handler);
}
The above code uses the ``sm_ipt_init`` function to initialize ``struct sm_ipt_ctx`` SM IPT context data structure and assign the receive handler.

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

The data is prepared beforehand, copied into allocated buffer and send 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 ``sm_ipt_alloc_tx_buf`` function to allocate transmit buffer in shared memory. Data is copied into said buffer and sent to another core via ``sm_ipt_send`` function.

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

The data is prepared after buffer allocation send to another core when data preparation (and usage) is finished.

.. 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_funtion(buffer);
return sm_ipt_send(&sm_ipt_ctx, buffer, len);
}
The above code uses the ``sm_ipt_alloc_tx_buf`` function to allocate transmit buffer in shared memory. Buffer is prepared by ``some_data_preparation_funtion`` and sent to another core via ``sm_ipt_send`` function.

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

There is possibility to free transmit buffer instead of sending it if the need arises.

.. code-block:: c
int send_if(size_t len, bool send_choice)
{
uint8_t *buffer;
size_t i;
sm_ipt_alloc_tx_buf(&sm_ipt_ctx, &buffer, len);
if (send_choice){
/* Prepare some data */
some_data_preparation_funtion(buffer);
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 ``sm_ipt_alloc_tx_buf`` function to allocate transmit buffer in shared memory. Buffer is send only if send_choice is true. If send_choice is false the buffer is free using ``sm_ipt_free_tx_buf`` and send operation is aborted.


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

When data is received it can be processed using full-copy mechanism. Buffer has to be copied to local memory. Shared memory rx buffer has to be freed and data processing is done on local copy of buffer.

.. code-block:: c
volatile uint8_t receive_buffer[MAX_PACKET_SIZE];
volatile bool data_received;
void sm_ipt_receive_handler(const uint8_t *packet, size_t len)
{
/* Copy whole message */
memcpy(receive_buffer, packet, len);
/* Free receive buffer */
sm_ipt_free_rx_buf(&sm_ipt_ctx, packet);
/* Signal message received */
data_received = true;
}
void data_processing_thread(void)
{
/* Wait for incoming data */
while(!data_received);
/*Process data */
some_data_processing_funtion(receive_buffer);
}
The above code uses the ``memcpy`` function to copy shared memory buffer into local buffer. Next shared memory buffer is freed using ``sm_ipt_free_rx_buf``. Lastly the data is processed locally using a copy of buffer.


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

When data is received it can be processed using no-copy mechanism. The pointer to shared memory buffer has to be saved in order to use it later. Shared memory rx buffer has to be freed and data processing is done on shared memory buffer.

.. note::
This approach increases risk of out of memory errors due to not freeing buffer right after receiving data.

.. code-block:: c
volatile void *receive_buffer;
volatile bool data_received;
void sm_ipt_receive_handler(const uint8_t *packet, size_t len)
{
/* Save buffer pointer */
receive_buffer = (void *) packet;
/* Signal message received */
data_received = true;
}
void data_processing_thread(void)
{
/* Wait for incoming data */
while(!data_received);
/*Process data */
some_data_processing_funtion(receive_buffer);
/* Free receive buffer */
sm_ipt_free_rx_buf(&sm_ipt_ctx, packet);
}
The above code copies pointer to shared memory buffer. Next data is processed using original buffer in share memory. Lastly shared memory buffer is freed using ``sm_ipt_free_rx_buf``.


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

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

.. note::
Detailed knowledge about how the lower layers are implemented is not required when using the SM IPT API.
However, this knowledge is required to port to a different operating system.

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

The operating system abstraction provides functionality for SM IPT that depends 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 to track specific problems.

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

0 comments on commit 8e04175

Please sign in to comment.