|
| 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` |
0 commit comments