1.. _ipc_service: 2 3IPC service 4########### 5 6.. contents:: 7 :local: 8 :depth: 2 9 10The IPC service API provides an interface to exchange data between two domains 11or CPUs. 12 13Overview 14======== 15 16An IPC service communication channel consists of one instance and one or 17several endpoints associated with the instance. 18 19An instance is the external representation of a physical communication channel 20between two domains or CPUs. The actual implementation and internal 21representation of the instance is peculiar to each backend. 22 23An individual instance is not used to send data between domains/CPUs. To send 24and receive the data, the user must create (register) an endpoint in the 25instance. This allows for the connection of the two domains of interest. 26 27It is possible to have zero or multiple endpoints for one single instance, 28possibly with different priorities, and to use each to exchange data. 29Endpoint prioritization and multi-instance ability highly depend on the backend 30used. 31 32The endpoint is an entity the user must use to send and receive data between 33two domains (connected by the instance). An endpoint is always associated to an 34instance. 35 36The creation of the instances is left to the backend, usually at init time. 37The registration of the endpoints is left to the user, usually at run time. 38 39The API does not mandate a way for the backend to create instances but it is 40strongly recommended to use the devicetree to retrieve the configuration 41parameters for an instance. Currently, each backend defines its own 42DT-compatible configuration that is used to configure the interface at boot 43time. 44 45The following usage scenarios are supported: 46 47* Simple data exchange. 48* Data exchange using the no-copy API. 49 50Simple data exchange 51==================== 52 53To send data between domains or CPUs, an endpoint must be registered onto 54an instance. 55 56See the following example: 57 58.. note:: 59 60 Before registering an endpoint, the instance must be opened using the 61 :c:func:`ipc_service_open_instance` function. 62 63 64.. code-block:: c 65 66 #include <zephyr/ipc/ipc_service.h> 67 68 static void bound_cb(void *priv) 69 { 70 /* Endpoint bounded */ 71 } 72 73 static void recv_cb(const void *data, size_t len, void *priv) 74 { 75 /* Data received */ 76 } 77 78 static struct ipc_ept_cfg ept0_cfg = { 79 .name = "ept0", 80 .cb = { 81 .bound = bound_cb, 82 .received = recv_cb, 83 }, 84 }; 85 86 int main(void) 87 { 88 const struct device *inst0; 89 struct ipc_ept ept0; 90 int ret; 91 92 inst0 = DEVICE_DT_GET(DT_NODELABEL(ipc0)); 93 ret = ipc_service_open_instance(inst0); 94 ret = ipc_service_register_endpoint(inst0, &ept0, &ept0_cfg); 95 96 /* Wait for endpoint bound (bound_cb called) */ 97 98 unsigned char message[] = "hello world"; 99 ret = ipc_service_send(&ept0, &message, sizeof(message)); 100 } 101 102Data exchange using the no-copy API 103=================================== 104 105If the backend supports the no-copy API you can use it to directly write and 106read to and from shared memory regions. 107 108See the following example: 109 110.. code-block:: c 111 112 #include <zephyr/ipc/ipc_service.h> 113 #include <stdint.h> 114 #include <string.h> 115 116 static struct ipc_ept ept0; 117 118 static void bound_cb(void *priv) 119 { 120 /* Endpoint bounded */ 121 } 122 123 static void recv_cb_nocopy(const void *data, size_t len, void *priv) 124 { 125 int ret; 126 127 ret = ipc_service_hold_rx_buffer(&ept0, (void *)data); 128 /* Process directly or put the buffer somewhere else and release. */ 129 ret = ipc_service_release_rx_buffer(&ept0, (void *)data); 130 } 131 132 static struct ipc_ept_cfg ept0_cfg = { 133 .name = "ept0", 134 .cb = { 135 .bound = bound_cb, 136 .received = recv_cb, 137 }, 138 }; 139 140 int main(void) 141 { 142 const struct device *inst0; 143 int ret; 144 145 inst0 = DEVICE_DT_GET(DT_NODELABEL(ipc0)); 146 ret = ipc_service_open_instance(inst0); 147 ret = ipc_service_register_endpoint(inst0, &ept0, &ept0_cfg); 148 149 /* Wait for endpoint bound (bound_cb called) */ 150 void *data; 151 unsigned char message[] = "hello world"; 152 uint32_t len = sizeof(message); 153 154 ret = ipc_service_get_tx_buffer(&ept0, &data, &len, K_FOREVER); 155 156 memcpy(data, message, len); 157 158 ret = ipc_service_send_nocopy(&ept0, data, sizeof(message)); 159 } 160 161Backends 162******** 163 164The requirements needed for implementing backends give flexibility to the IPC 165service. These allow for the addition of dedicated backends having only a 166subsets of features for specific use cases. 167 168The backend must support at least the following: 169 170* The init-time creation of instances. 171* The run-time registration of an endpoint in an instance. 172 173Additionally, the backend can also support the following: 174 175* The run-time deregistration of an endpoint from the instance. 176* The run-time closing of an instance. 177* The no-copy API. 178 179Each backend can have its own limitations and features that make the backend 180unique and dedicated to a specific use case. The IPC service API can be used 181with multiple backends simultaneously, combining the pros and cons of each 182backend. 183 184.. toctree:: 185 :maxdepth: 1 186 187 backends/ipc_service_icmsg.rst 188 backends/ipc_service_icbmsg.rst 189 190API Reference 191************* 192 193IPC service API 194=============== 195 196.. doxygengroup:: ipc_service_api 197 198IPC service backend API 199======================= 200 201.. doxygengroup:: ipc_service_backend 202