Skip to content

Commit 28df449

Browse files
doki-nordiccarlescufi
authored andcommitted
ipc: add dynamically allocated buffers to icmsg
The icmsg and icmsg_me backends has limitations in context of concurrent access to single instance. Some limitations are: * sending by more thread at the same time may cause -EBUSY * allocating TX buffer will cause errors in other threads that want to allocate before first thread sent the message, * during no-copy receive, when RX buffer is on hold receiving is totally blocked. This backend resolves those limitations by adding dynamically allocated buffers on shared memory next to ICmsg circular buffer. The data is passed using those buffers, so concurrency is not a problem. The ICmsg is used only to pass short 2-byte messages containing references to those buffers. The backend also supports multiple endpoint. The ipc/icmsg_me sample was modified to support this backend. Signed-off-by: Dominik Kilian <[email protected]>
1 parent a3ff19a commit 28df449

File tree

8 files changed

+1452
-0
lines changed

8 files changed

+1452
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
.. _ipc_service_backend_icbmsg:
2+
3+
ICMsg with dynamically allocated buffers backend
4+
################################################
5+
6+
This backend is built on top of the :ref:`ipc_service_backend_icmsg`.
7+
Data transferred over this backend travels in dynamically allocated buffers on shared memory.
8+
The ICMsg just sends references to the buffers.
9+
It also supports multiple endpoints.
10+
11+
This architecture allows for overcoming some common problems with other backends (mostly related to multithread access and zero-copy).
12+
This backend provides an alternative with no significant limitations.
13+
14+
Overview
15+
========
16+
17+
The shared memory is divided into two parts.
18+
One is reserved for the ICMsg and the other contains equal-sized blocks.
19+
The number of blocks is configured in the devicetree.
20+
21+
The data sending process is following:
22+
23+
* The sender allocates one or more blocks.
24+
If there are not enough sequential blocks, it waits using the timeout provided in the parameter that also includes K_FOREVER and K_NO_WAIT.
25+
* The allocated blocks are filled with data.
26+
For the zero-copy case, this is done by the caller, otherwise, it is copied automatically.
27+
During this time other threads are not blocked in any way as long as there are enough free blocks for them.
28+
They can allocate, send data and receive data.
29+
* A message containing the block index is sent over ICMsg to the receiver.
30+
The size of the ICMsg queue is large enough to hold messages for all blocks, so it will never overflow.
31+
* The receiver can hold the data as long as desired.
32+
Again, other threads are not blocked as long as there are enough free blocks for them.
33+
* When data is no longer needed, the backend sends a release message over ICMsg.
34+
* When the backend receives this message, it deallocates all blocks.
35+
It is done internally by the backend and it is invisible to the caller.
36+
37+
Configuration
38+
=============
39+
40+
The backend is configured using Kconfig and devicetree.
41+
When configuring the backend, do the following:
42+
43+
* Define two memory regions and assign them to ``tx-region`` and ``rx-region`` of an instance.
44+
Ensure that the memory regions used for data exchange are unique (not overlapping any other region) and accessible by both domains (or CPUs).
45+
* Define the number of allocable blocks for each region with ``tx-blocks`` and ``rx-blocks``.
46+
* Define MBOX devices for sending a signal that informs the other domain (or CPU) of the written data.
47+
Ensure that the other domain (or CPU) can receive the signal.
48+
49+
See the following configuration example for one of the instances:
50+
51+
.. code-block:: devicetree
52+
53+
reserved-memory {
54+
tx: memory@20070000 {
55+
reg = <0x20070000 0x0800>;
56+
};
57+
58+
rx: memory@20078000 {
59+
reg = <0x20078000 0x0800>;
60+
};
61+
};
62+
63+
ipc {
64+
ipc0: ipc0 {
65+
compatible = "zephyr,ipc-icbmsg";
66+
tx-region = <&tx>;
67+
rx-region = <&rx>;
68+
tx-blocks = <16>;
69+
rx-blocks = <32>;
70+
mboxes = <&mbox 0>, <&mbox 1>;
71+
mbox-names = "tx", "rx";
72+
status = "okay";
73+
};
74+
};
75+
76+
77+
You must provide a similar configuration for the other side of the communication (domain or CPU).
78+
Swap the MBOX channels, memory regions (``tx-region`` and ``rx-region``), and block count (``tx-blocks`` and ``rx-blocks``).
79+
80+
Samples
81+
=======
82+
83+
* :ref:`ipc_multi_endpoint_sample`

doc/services/ipc/ipc_service/ipc_service.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ backend.
185185
:maxdepth: 1
186186

187187
backends/ipc_service_icmsg.rst
188+
backends/ipc_service_icbmsg.rst
188189

189190
API Reference
190191
*************
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#
2+
# Copyright (c) 2023 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
description: Inter-core messaging backend with dynamically allocated buffers
8+
9+
compatible: "zephyr,ipc-icbmsg"
10+
11+
include: zephyr,ipc-icmsg.yaml
12+
13+
properties:
14+
tx-blocks:
15+
description: number of allocable TX blocks
16+
required: true
17+
type: int
18+
19+
rx-blocks:
20+
description: number of allocable RX blocks
21+
required: true
22+
type: int

include/zephyr/ipc/pbuf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ struct pbuf {
116116
.dcache_alignment = (dcache_align), \
117117
}
118118

119+
/**
120+
* @brief Macro calculates memory overhead taken by the header in shared memory.
121+
*
122+
* It contains the read index, write index and padding.
123+
*
124+
* @param dcache_align Data cache alignment.
125+
*/
126+
#define PBUF_HEADER_OVERHEAD(dcache_align) \
127+
(MAX(dcache_align, _PBUF_IDX_SIZE) + _PBUF_IDX_SIZE)
128+
119129
/**
120130
* @brief Statically define and initialize pbuf.
121131
*

subsys/ipc/ipc_service/backends/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICMSG ipc_icmsg.c)
44
zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_INITIATOR ipc_icmsg_me_initiator.c)
55
zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICMSG_ME_FOLLOWER ipc_icmsg_me_follower.c)
6+
zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_ICBMSG ipc_icbmsg.c)
67
zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_RPMSG ipc_rpmsg_static_vrings.c)

subsys/ipc/ipc_service/backends/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ config IPC_SERVICE_BACKEND_ICMSG_ME_FOLLOWER
4949
role.
5050

5151
rsource "Kconfig.icmsg_me"
52+
rsource "Kconfig.icbmsg"
5253
rsource "Kconfig.rpmsg"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright (c) 2023 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
menuconfig IPC_SERVICE_BACKEND_ICBMSG
5+
bool "ICMSG backend with dynamically allocated buffers"
6+
default y
7+
depends on MBOX
8+
depends on DT_HAS_ZEPHYR_IPC_ICBMSG_ENABLED
9+
select IPC_SERVICE_ICMSG
10+
help
11+
Choosing this backend results in multi endpoint implementation based
12+
on dynamically allocated buffers. References to them are send over
13+
ICMsg circular buffer.
14+
15+
if IPC_SERVICE_BACKEND_ICBMSG
16+
17+
config IPC_SERVICE_BACKEND_ICBMSG_NUM_EP
18+
int "Endpoints count"
19+
range 1 254
20+
default 4
21+
help
22+
Number of endpoints supported by the ICBMsg IPC service
23+
backend. The number of endpoints are applied to all the instances,
24+
so this value should be maximum number among all the instances.
25+
26+
module = IPC_SERVICE_BACKEND_ICBMSG
27+
module-str = ICMSG backend with separate buffers
28+
module-help = Sets log level for ICMsg backend with buffers
29+
source "subsys/logging/Kconfig.template.log_config"
30+
31+
endif # IPC_SERVICE_BACKEND_ICBMSG

0 commit comments

Comments
 (0)