1.. _ipc_service_backend_icbmsg: 2 3ICMsg with dynamically allocated buffers backend 4################################################ 5 6This backend is built on top of the :ref:`ipc_service_backend_icmsg`. 7Data transferred over this backend travels in dynamically allocated buffers on shared memory. 8The ICMsg just sends references to the buffers. 9It also supports multiple endpoints. 10 11This architecture allows for overcoming some common problems with other backends (mostly related to multithread access and zero-copy). 12This backend provides an alternative with no significant limitations. 13 14Overview 15======== 16 17The shared memory is divided into two parts. 18One is reserved for the ICMsg and the other contains equal-sized blocks. 19The number of blocks is configured in the devicetree. 20 21The 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 37Configuration 38============= 39 40The backend is configured using Kconfig and devicetree. 41When configuring the backend, do the following: 42 43* If at least one of the cores uses data cache on shared memory, set the ``dcache-alignment`` value. 44 This must be the largest value of the invalidation or the write-back size for both sides of the communication. 45 You can skip it if none of the communication sides is using data cache on shared memory. 46* Define two memory regions and assign them to ``tx-region`` and ``rx-region`` of an instance. 47 Ensure that the memory regions used for data exchange are unique (not overlapping any other region) and accessible by both domains (or CPUs). 48* Define the number of allocable blocks for each region with ``tx-blocks`` and ``rx-blocks``. 49* Define MBOX devices for sending a signal that informs the other domain (or CPU) of the written data. 50 Ensure that the other domain (or CPU) can receive the signal. 51 52.. caution:: 53 54 Make sure that you set correct value of the ``dcache-alignment``. 55 At first, wrong value may not show any signs, which may give a false impression that everything works. 56 Unstable behavior will appear sooner or later. 57 58See the following configuration example for one of the instances: 59 60.. code-block:: devicetree 61 62 reserved-memory { 63 tx: memory@20070000 { 64 reg = <0x20070000 0x0800>; 65 }; 66 67 rx: memory@20078000 { 68 reg = <0x20078000 0x0800>; 69 }; 70 }; 71 72 ipc { 73 ipc0: ipc0 { 74 compatible = "zephyr,ipc-icbmsg"; 75 dcache-alignment = <32>; 76 tx-region = <&tx>; 77 rx-region = <&rx>; 78 tx-blocks = <16>; 79 rx-blocks = <32>; 80 mboxes = <&mbox 0>, <&mbox 1>; 81 mbox-names = "tx", "rx"; 82 status = "okay"; 83 }; 84 }; 85 86 87You must provide a similar configuration for the other side of the communication (domain or CPU). 88Swap the MBOX channels, memory regions (``tx-region`` and ``rx-region``), and block count (``tx-blocks`` and ``rx-blocks``). 89 90Samples 91======= 92 93* :zephyr:code-sample:`ipc_multi_endpoint` 94 95Detailed Protocol Specification 96=============================== 97 98The ICBMsg protocol transfers messages using dynamically allocated blocks of shared memory. 99Internally, it uses ICMsg for control messages. 100 101Shared Memory Organization 102-------------------------- 103 104The ICBMsg uses two shared memory regions, ``rx-region`` for message receiving, and ``tx-region`` for message transmission. 105The regions do not need to be next to each other, placed in any specific order, or be of the same size. 106Those regions are interchanged on each core. 107 108Each shared memory region is divided into following two parts: 109 110* **ICMsg area** - An area reserved by ICMsg instance and used to transfer the control messages. 111* **Blocks area** - An area containing allocatable blocks carrying the content of the messages. 112 This area is divided into even-sized blocks aligned to cache boundaries. 113 114The location of each area is calculated to fulfill cache boundary requirements and allow optimal region usage. 115It is calculated using the following algorithm: 116 117Inputs: 118 119* ``region_begin``, ``region_end`` - Boundaries of the region. 120* ``local_blocks`` - Number of blocks in this region. 121* ``remote_blocks`` - Number of blocks in the opposite region. 122* ``alignment`` - Memory cache alignment. 123 124The algorithm: 125 126#. Align region boundaries to cache: 127 128 * ``region_begin_aligned = ROUND_UP(region_begin, alignment)`` 129 * ``region_end_aligned = ROUND_DOWN(region_end, alignment)`` 130 * ``region_size_aligned = region_end_aligned - region_begin_aligned`` 131 132#. Calculate the minimum size required for ICMsg area ``icmsg_min_size``, which is a sum of: 133 134 * ICMsg header size (refer to the ICMsg specification) 135 * ICMsg message size for 4 bytes of content (refer to the ICMsg specification) multiplied by ``local_blocks + remote_blocks + 2`` 136 137#. Calculate available size for block area. Note that the actual size may be smaller because of block alignment: 138 139 ``blocks_area_available_size = region_size_aligned - icmsg_min_size`` 140 141#. Calculate single block size: 142 143 ``block_size = ROUND_DOWN(blocks_area_available_size / local_blocks, alignment)`` 144 145#. Calculate actual block area size: 146 147 ``blocks_area_size = block_size * local_blocks`` 148 149#. Calculate block area start address: 150 151 ``blocks_area_begin = region_end_aligned - blocks_area_size`` 152 153The result: 154 155* ``region_begin_aligned`` - The start of ICMsg area. 156* ``blocks_area_begin`` - End of ICMsg area and the start of block area. 157* ``block_size`` - Single block size. 158* ``region_end_aligned`` - End of blocks area. 159 160.. image:: icbmsg_memory.svg 161 :align: center 162 163| 164 165Message Transfer 166---------------- 167 168The ICBMsg uses following two types of messages: 169 170* **Binding message** - Message exchanged during endpoint binding process (described below). 171* **Data message** - Message carrying actual data from a user. 172 173They serve different purposes, but their lifetime and flow are the same. 174The following steps describe it: 175 176#. The sender wants to send a message that contains ``K`` bytes. 177#. The sender reserves blocks from his ``tx-region`` blocks area that can hold at least ``K + 4`` bytes. 178 The additional ``+ 4`` bytes are reserved for the header, which contains the exact size of the message. 179 The blocks must be continuous (one after another). 180 The sender is responsible for block allocation management. 181 It is up to the implementation to decide what to do if no blocks are available. 182#. The sender fills the header with a 32-bit integer value, ``K`` (little-endian). 183#. The sender fills the remaining part of the blocks with his data. 184 Unused space is ignored. 185#. The sender sends an ``MSG_DATA`` or ``MSG_BOUND`` control message over ICMsg that contains starting block number (where the header is located). 186 Details about the control message are in the next section. 187#. The control message travels to the receiver. 188#. The receiver reads message size and data from his ``rx-region`` starting from the block number received in the control message. 189#. The receiver processes the message. 190#. The receiver sends ``MSG_RELEASE_DATA`` or ``MSG_RELEASE_BOUND`` control message over ICMsg containing the starting block number 191 (the same as inside received control message). 192#. The control message travels back to the sender. 193#. The sender releases the blocks starting from the block number provided in the control message. 194 The number of blocks to release can be calculated using a size from the header. 195 196.. image:: icbmsg_message.svg 197 :align: center 198 199| 200 201Control Messages 202---------------- 203 204The control messages are transmitted over ICMsg. 205Each control message contains three bytes. 206The first byte tells what kind of message it is. 207 208The allocated size for ICMsg ensures that the maximum possible number of control messages will fit into its ring buffer, 209so sending over the ICMsg will never fail because of buffer overflow. 210 211MSG_DATA 212^^^^^^^^ 213 214.. list-table:: 215 :header-rows: 1 216 217 * - byte 0 218 - byte 1 219 - byte 2 220 * - MSG_DATA 221 - endpoint address 222 - block number 223 * - 0x00 224 - 0x00 ÷ 0xFD 225 - 0x00 ÷ N-1 226 227The ``MSG_DATA`` control message indicates that a new data message was sent. 228The data message starts with a header inside ``block number``. 229The data message was sent over the endpoint specified in ``endpoint address``. 230The endpoint binding procedure must be finished before sending this control message. 231 232MSG_RELEASE_DATA 233^^^^^^^^^^^^^^^^ 234 235.. list-table:: 236 :header-rows: 1 237 238 * - byte 0 239 - byte 1 240 - byte 2 241 * - MSG_RELEASE_DATA 242 - unused 243 - block number 244 * - 0x01 245 - 246 - 0x00 ÷ N-1 247 248The ``MSG_RELEASE_DATA`` control message is sent in response to ``MSG_DATA``. 249It informs us that the data message starting with ``block number`` was received and is no longer needed. 250When this control message is received, the blocks containing the message must be released. 251 252MSG_BOUND 253^^^^^^^^^ 254 255.. list-table:: 256 :header-rows: 1 257 258 * - byte 0 259 - byte 1 260 - byte 2 261 * - MSG_BOUND 262 - endpoint address 263 - block number 264 * - 0x02 265 - 0x00 ÷ 0xFD 266 - 0x00 ÷ N-1 267 268The ``MSG_BOUND`` control message is similar to the ``MSG_DATA`` except the blocks carry binding information. 269See the next section for details on the binding procedure. 270 271MSG_RELEASE_BOUND 272^^^^^^^^^^^^^^^^^ 273 274.. list-table:: 275 :header-rows: 1 276 277 * - byte 0 278 - byte 1 279 - byte 2 280 * - MSG_RELEASE_BOUND 281 - endpoint address 282 - block number 283 * - 0x03 284 - 0x00 ÷ 0xFD 285 - 0x00 ÷ N-1 286 287The ``MSG_RELEASE_BOUND`` control message is sent in response to ``MSG_BOUND``. 288It is similar to the ``MSG_RELEASE_DATA`` except the ``endpoint address`` is required. 289See the next section for details on the binding procedure. 290 291Initialization 292-------------- 293 294The ICBMsg initialization calls ICMsg to initialize. 295When it is done, no further initialization is required. 296Blocks can be left uninitialized. 297 298After ICBMsg initialization, you are ready for the endpoint binding procedure. 299 300Endpoint Binding 301----------------- 302 303So far, the protocol is symmetrical. 304Each side of the connection was the same. 305The binding process is not symmetrical. 306There are following two roles: 307 308* **Initiator** - It assigns endpoint addresses and sends binding messages. 309* **Follower** - It waits for a binding message. 310 311The roles are determined based on the addresses of the ``rx-region`` and ``tx-region``. 312 313* If ``address of rx-region < address of tx-region``, then it is initiator. 314* If ``address of rx-region > address of tx-region``, then it is follower. 315 316The binding process needs an endpoint name and is responsible for following two things: 317 318* To establish a common endpoint address, 319* To make sure that two sides are ready to exchange messages over that endpoint. 320 321After ICMsg is initialized, both sides can start the endpoint binding. 322There are no restrictions on the order in which the sides start the endpoint binding. 323 324Initiator Binding Procedure 325^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 326 327The initiator sends a binding message. 328It contains a single null-terminated string with an endpoint name. 329As usual, it is preceded by a message header containing the message size (including null-terminator). 330 331Example of the binding message for ``example`` endpoint name: 332 333.. list-table:: 334 :header-rows: 1 335 336 * - Header 337 - Endpoint name 338 - Null-terminator 339 * - bytes 0-3 340 - bytes 4-10 341 - byte 11 342 * - 0x00000008 343 - ``example`` 344 - 0x00 345 346The binding message is sent using the ``MSG_BOUND`` control message and released with the ``MSG_RELEASE_BOUND`` control message. 347 348The endpoint binding procedure from the initiator's point of view is the following: 349 350#. The initiator assigns an endpoint address to this endpoint. 351#. The initiator sends a binding message containing the endpoint name and address. 352#. The initiator waits for any message from the follower using this endpoint address. 353 Usually, it will be ``MSG_RELEASE_BOUND``, but ``MSG_DATA`` is also allowed. 354#. The initiator is bound to an endpoint, and it can send data messages using this endpoint. 355 356Follower Binding Procedure 357^^^^^^^^^^^^^^^^^^^^^^^^^^ 358 359If the follower receives a binding message before it starts the binding procedure on that endpoint, it should store the message for later. 360It should not send the ``MSG_RELEASE_BOUND`` yet. 361 362The endpoint binding procedure from the follower's point of view is the following: 363 364#. The follower waits for a binding message containing its endpoint name. 365 The message may be a newly received message or a message stored before the binding procedure started. 366#. The follower stores the endpoint address assigned to this endpoint by the initiator. 367#. The follower sends the ``MSG_RELEASE_BOUND`` control message. 368#. The follower is bound to an endpoint, and it can send data messages using this endpoint. 369 370Example sequence diagrams 371------------------------- 372 373The following diagram shows a few examples of how the messages flow between two ends. 374There is a binding of two endpoints and one fully processed data message exchange. 375 376.. image:: icbmsg_flows.svg 377 :align: center 378 379| 380 381Protocol Versioning 382------------------- 383 384The protocol allows improvements in future versions. 385The newer implementations should be able to work with older ones in backward compatible mode. 386To allow it, the current protocol version has the following restrictions: 387 388* If the receiver receives a longer control message, it should use only the first three bytes and ignore the remaining. 389* If the receiver receives a control message starting with a byte that does not match any of the messages described here, it should ignore it. 390* If the receiver receives a binding message with additional bytes at the end, it should ignore the additional bytes. 391