1 /* 2 * Copyright (c) 2022 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_INCLUDE_IPC_ICMSG_H_ 8 #define ZEPHYR_INCLUDE_IPC_ICMSG_H_ 9 10 #include <stddef.h> 11 #include <stdint.h> 12 #include <zephyr/kernel.h> 13 #include <zephyr/drivers/mbox.h> 14 #include <zephyr/ipc/ipc_service.h> 15 #include <zephyr/sys/atomic.h> 16 #include <zephyr/sys/spsc_pbuf.h> 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 /** 23 * @brief Icmsg IPC library API 24 * @defgroup ipc_icmsg_api Icmsg IPC library API 25 * @ingroup ipc 26 * @{ 27 */ 28 29 enum icmsg_state { 30 ICMSG_STATE_OFF, 31 ICMSG_STATE_BUSY, 32 ICMSG_STATE_READY, 33 }; 34 35 struct icmsg_config_t { 36 uintptr_t tx_shm_addr; 37 uintptr_t rx_shm_addr; 38 size_t tx_shm_size; 39 size_t rx_shm_size; 40 struct mbox_channel mbox_tx; 41 struct mbox_channel mbox_rx; 42 }; 43 44 struct icmsg_data_t { 45 /* Tx/Rx buffers. */ 46 struct spsc_pbuf *tx_ib; 47 struct spsc_pbuf *rx_ib; 48 atomic_t tx_buffer_state; 49 #ifdef CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC 50 struct k_mutex tx_lock; 51 #endif 52 53 /* Callbacks for an endpoint. */ 54 const struct ipc_service_cb *cb; 55 void *ctx; 56 57 /* General */ 58 const struct icmsg_config_t *cfg; 59 struct k_work_delayable notify_work; 60 struct k_work mbox_work; 61 atomic_t state; 62 /* No-copy */ 63 #ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX 64 atomic_t rx_buffer_state; 65 const void *rx_buffer; 66 uint16_t rx_len; 67 #endif 68 }; 69 70 /** @brief Open an icmsg instance 71 * 72 * Open an icmsg instance to be able to send and receive messages to a remote 73 * instance. 74 * This function is blocking until the handshake with the remote instance is 75 * completed. 76 * This function is intended to be called late in the initialization process, 77 * possibly from a thread which can be safely blocked while handshake with the 78 * remote instance is being pefromed. 79 * 80 * @param[in] conf Structure containing configuration parameters for the icmsg 81 * instance. 82 * @param[inout] dev_data Structure containing run-time data used by the icmsg 83 * instance. 84 * @param[in] cb Structure containing callback functions to be called on 85 * events generated by this icmsg instance. The pointed memory 86 * must be preserved while the icmsg instance is active. 87 * @param[in] ctx Pointer to context passed as an argument to callbacks. 88 * 89 * 90 * @retval 0 on success. 91 * @retval -EALREADY when the instance is already opened. 92 * @retval other errno codes from dependent modules. 93 */ 94 int icmsg_open(const struct icmsg_config_t *conf, 95 struct icmsg_data_t *dev_data, 96 const struct ipc_service_cb *cb, void *ctx); 97 98 /** @brief Close an icmsg instance 99 * 100 * Closing an icmsg instance results in releasing all resources used by given 101 * instance including the shared memory regions and mbox devices. 102 * 103 * @param[in] conf Structure containing configuration parameters for the icmsg 104 * instance being closed. Its content must be the same as used 105 * for creating this instance with @ref icmsg_open. 106 * @param[inout] dev_data Structure containing run-time data used by the icmsg 107 * instance. 108 * 109 * @retval 0 on success. 110 * @retval other errno codes from dependent modules. 111 */ 112 int icmsg_close(const struct icmsg_config_t *conf, 113 struct icmsg_data_t *dev_data); 114 115 /** @brief Send a message to the remote icmsg instance. 116 * 117 * @param[in] conf Structure containing configuration parameters for the icmsg 118 * instance. 119 * @param[inout] dev_data Structure containing run-time data used by the icmsg 120 * instance. 121 * @param[in] msg Pointer to a buffer containing data to send. 122 * @param[in] len Size of data in the @p msg buffer. 123 * 124 * 125 * @retval 0 on success. 126 * @retval -EBUSY when the instance has not finished handshake with the remote 127 * instance. 128 * @retval -ENODATA when the requested data to send is empty. 129 * @retval -EBADMSG when the requested data to send is too big. 130 * @retval -ENOBUFS when there are no TX buffers available. 131 * @retval other errno codes from dependent modules. 132 */ 133 int icmsg_send(const struct icmsg_config_t *conf, 134 struct icmsg_data_t *dev_data, 135 const void *msg, size_t len); 136 137 /** @brief Get an empty TX buffer to be sent using @ref icmsg_send_nocopy 138 * 139 * This function can be called to get an empty TX buffer so that the 140 * application can directly put its data into the sending buffer avoiding copy 141 * performed by the icmsg library. 142 * 143 * It is the application responsibility to correctly fill the allocated TX 144 * buffer with data and passing correct parameters to @ref 145 * icmsg_send_nocopy function to perform data no-copy-send mechanism. 146 * 147 * The size parameter can be used to request a buffer with a certain size: 148 * - if the size can be accommodated the function returns no errors and the 149 * buffer is allocated 150 * - if the requested size is too big, the function returns -ENOMEM and the 151 * the buffer is not allocated. 152 * - if the requested size is '0' the buffer is allocated with the maximum 153 * allowed size. 154 * 155 * In all the cases on return the size parameter contains the maximum size for 156 * the returned buffer. 157 * 158 * When the function returns no errors, the buffer is intended as allocated 159 * and it is released under one of two conditions: (1) when sending the buffer 160 * using @ref icmsg_send_nocopy (and in this case the buffer is automatically 161 * released by the backend), (2) when using @ref icmsg_drop_tx_buffer on a 162 * buffer not sent. 163 * 164 * @param[in] conf Structure containing configuration parameters for the icmsg 165 * instance. 166 * @param[inout] dev_data Structure containing run-time data used by the icmsg 167 * instance. 168 * @param[out] data Pointer to the empty TX buffer. 169 * @param[inout] size Pointer to store the requested TX buffer size. If the 170 * function returns -ENOMEM, this parameter returns the 171 * maximum allowed size. 172 * 173 * @retval -ENOBUFS when there are no TX buffers available. 174 * @retval -EALREADY when a buffer was already claimed and not yet released. 175 * @retval -ENOMEM when the requested size is too big (and the size parameter 176 * contains the maximum allowed size). 177 * 178 * @retval 0 on success. 179 */ 180 int icmsg_get_tx_buffer(const struct icmsg_config_t *conf, 181 struct icmsg_data_t *dev_data, 182 void **data, size_t *size); 183 184 /** @brief Drop and release a TX buffer 185 * 186 * Drop and release a TX buffer. It is possible to drop only TX buffers 187 * obtained by using @ref icmsg_get_tx_buffer. 188 * 189 * @param[in] conf Structure containing configuration parameters for the icmsg 190 * instance. 191 * @param[inout] dev_data Structure containing run-time data used by the icmsg 192 * instance. 193 * @param[in] data Pointer to the TX buffer. 194 * 195 * @retval -EALREADY when the buffer was already dropped. 196 * @retval -ENXIO when the buffer was not obtained using @ref 197 * ipc_service_get_tx_buffer 198 * 199 * @retval 0 on success. 200 */ 201 int icmsg_drop_tx_buffer(const struct icmsg_config_t *conf, 202 struct icmsg_data_t *dev_data, 203 const void *data); 204 205 /** @brief Send a message from a buffer obtained by @ref icmsg_get_tx_buffer 206 * to the remote icmsg instance. 207 * 208 * This is equivalent to @ref icmsg_send but in this case the TX buffer must 209 * have been obtained by using @ref icmsg_get_tx_buffer. 210 * 211 * The API user has to take the responsibility for getting the TX buffer using 212 * @ref icmsg_get_tx_buffer and filling the TX buffer with the data. 213 * 214 * After the @ref icmsg_send_nocopy function is issued the TX buffer is no 215 * more owned by the sending task and must not be touched anymore unless the 216 * function fails and returns an error. 217 * 218 * If this function returns an error, @ref icmsg_drop_tx_buffer can be used 219 * to drop the TX buffer. 220 * 221 * @param[in] conf Structure containing configuration parameters for the icmsg 222 * instance. 223 * @param[inout] dev_data Structure containing run-time data used by the icmsg 224 * instance. 225 * @param[in] msg Pointer to a buffer containing data to send. 226 * @param[in] len Size of data in the @p msg buffer. 227 * 228 * 229 * @return Size of sent data on success. 230 * @retval -EBUSY when the instance has not finished handshake with the remote 231 * instance. 232 * @retval -ENODATA when the requested data to send is empty. 233 * @retval -EBADMSG when the requested data to send is too big. 234 * @retval -ENXIO when the buffer was not obtained using @ref 235 * ipc_service_get_tx_buffer 236 * @retval other errno codes from dependent modules. 237 */ 238 int icmsg_send_nocopy(const struct icmsg_config_t *conf, 239 struct icmsg_data_t *dev_data, 240 const void *msg, size_t len); 241 242 #ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX 243 /** @brief Hold RX buffer to be used outside of the received callback. 244 * 245 * @param[in] conf Structure containing configuration parameters for the icmsg 246 * instance. 247 * @param[inout] dev_data Structure containing run-time data used by the icmsg 248 * instance. 249 * @param[in] data Pointer to the buffer to be held. 250 * 251 * @retval 0 on success. 252 * @retval -EBUSY when the instance has not finished handshake with the remote 253 * instance. 254 * @retval -EINVAL when the @p data argument does not point to a valid RX 255 * buffer. 256 * @retval -EALREADY when the buffer is already held. 257 */ 258 int icmsg_hold_rx_buffer(const struct icmsg_config_t *conf, 259 struct icmsg_data_t *dev_data, 260 const void *data); 261 262 /** @brief Release RX buffer for future use. 263 * 264 * @param[in] conf Structure containing configuration parameters for the icmsg 265 * instance. 266 * @param[inout] dev_data Structure containing run-time data used by the icmsg 267 * instance. 268 * @param[in] data Pointer to the buffer to be released. 269 * 270 * @retval 0 on success. 271 * @retval -EBUSY when the instance has not finished handshake with the remote 272 * instance. 273 * @retval -EINVAL when the @p data argument does not point to a valid RX 274 * buffer. 275 * @retval -EALREADY when the buffer is not held. 276 */ 277 int icmsg_release_rx_buffer(const struct icmsg_config_t *conf, 278 struct icmsg_data_t *dev_data, 279 const void *data); 280 #endif 281 282 /** 283 * @} 284 */ 285 286 #ifdef __cplusplus 287 } 288 #endif 289 290 #endif /* ZEPHYR_INCLUDE_IPC_ICMSG_H_ */ 291