diff --git a/include/ipc/ipc_rpmsg.h b/include/ipc/ipc_rpmsg.h new file mode 100644 index 00000000000..c3f742d85ce --- /dev/null +++ b/include/ipc/ipc_rpmsg.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_IPC_SERVICE_IPC_RPMSG_H_ +#define ZEPHYR_INCLUDE_IPC_SERVICE_IPC_RPMSG_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief IPC service RPMsg API + * @defgroup ipc_service_rpmsg_api IPC service RPMsg API + * @{ + */ + +/** Number of endpoints. */ +#define NUM_ENDPOINTS CONFIG_IPC_SERVICE_NUM_ENDPOINTS_PER_INSTANCE + +/** + * @typedef rpmsg_ept_bound_cb + * @brief Define the bound callback. + * + * This callback is defined at instance level and it is called when an endpoint + * of the instance is bound. + * + * @param ept Endpoint of the instance just bound. + */ +typedef void (*rpmsg_ept_bound_cb)(struct ipc_ept *ept); + +/** @brief Endpoint structure. + * + * Used to define an endpoint to be encapsulated in an RPMsg instance. + */ +struct ipc_ept { + /** RPMsg endpoint. */ + struct rpmsg_endpoint ep; + + /** Name of the endpoint. */ + const char *name; + + /** Bound flag. */ + volatile bool bound; + + /** Callbacks. */ + const struct ipc_service_cb *cb; + + /** Private data to be passed to the endpoint callbacks. */ + void *priv; +}; + +/** @brief RPMsg instance structure. + * + * Struct representation of an RPMsg instance. + */ +struct ipc_rpmsg_instance { + /** Endpoints in the instance. */ + struct ipc_ept endpoint[NUM_ENDPOINTS]; + + /** RPMsg virtIO device. */ + struct rpmsg_virtio_device rvdev; + + /** SHM pool. */ + struct rpmsg_virtio_shm_pool shm_pool; + + /** EPT (instance) bound callback. */ + rpmsg_ept_bound_cb bound_cb; + + /** EPT (instance) callback. */ + rpmsg_ept_cb cb; +}; + +/** @brief Init an RPMsg instance. + * + * Init an RPMsg instance. + * + * @param instance Pointer to the RPMsg instance struct. + * @param role Master / Remote role. + * @param shm_io SHM IO region pointer. + * @param vdev VirtIO device pointer. + * @param shb Shared memory region pointer. + * @param size Size of the shared memory region. + * @param ns_bind_cb callback handler for name service announcement without + * local endpoints waiting to bind. If NULL the + * implementation falls back to the internal implementation. + * + * @retval -EINVAL When some parameter is missing. + * @retval 0 If successful. + * @retval Other errno codes depending on the OpenAMP implementation. + */ +int ipc_rpmsg_init(struct ipc_rpmsg_instance *instance, + unsigned int role, + struct metal_io_region *shm_io, + struct virtio_device *vdev, + void *shb, size_t size, + rpmsg_ns_bind_cb ns_bind_cb); + +/** @brief Register an endpoint. + * + * Register an endpoint to a provided RPMsg instance. + * + * @param instance Pointer to the RPMsg instance struct. + * @param role Master / Remote role. + * @param ept Endpoint to register. + * + * @retval -EINVAL When some parameter is missing. + * @retval 0 If successful. + * @retval Other errno codes depending on the OpenAMP implementation. + */ +int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role, + struct ipc_ept *ept); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_IPC_SERVICE_IPC_RPMSG_H_ */ diff --git a/include/ipc/ipc_static_vrings.h b/include/ipc/ipc_static_vrings.h new file mode 100644 index 00000000000..6a635eedb97 --- /dev/null +++ b/include/ipc/ipc_static_vrings.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_IPC_SERVICE_IPC_STATIC_VRINGS_H_ +#define ZEPHYR_INCLUDE_IPC_SERVICE_IPC_STATIC_VRINGS_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief IPC service static VRINGs API + * @defgroup ipc_service_static_vrings_api IPC service static VRINGs API + * @{ + */ + +/** Number of used VRING buffers. */ +#define VRING_COUNT (2) + +/** + * @typedef ipc_notify_cb + * @brief Define the notify callback. + * + * This callback is defined at instance level and it is called on virtqueue notify. + * + * @param vq Virtqueue. + * @param priv Priv data. + */ +typedef void (*ipc_notify_cb)(struct virtqueue *vq, void *priv); + +/** @brief Static VRINGs structure. + * + * Struct used to represent and carry information about static allocation of VRINGs. + */ +struct ipc_static_vrings { + /** virtIO device. */ + struct virtio_device vdev; + + /** SHM physmap. */ + metal_phys_addr_t shm_physmap[1]; + + /** SHM device. */ + struct metal_device shm_device; + + /** SHM and addresses. */ + uintptr_t status_reg_addr; + + /** TX VRING address. */ + uintptr_t tx_addr; + + /** RX VRING address. */ + uintptr_t rx_addr; + + /** VRING size. */ + size_t vring_size; + + /** Shared memory region address. */ + uintptr_t shm_addr; + + /** Share memory region size. */ + size_t shm_size; + + /** SHM IO region. */ + struct metal_io_region *shm_io; + + /** VRINGs */ + struct virtio_vring_info rvrings[VRING_COUNT]; + + /** Virtqueues. */ + struct virtqueue *vq[VRING_COUNT]; + + /** Private data to be passed to the notify callback. */ + void *priv; + + /** Notify callback. */ + ipc_notify_cb notify_cb; +}; + +/** @brief Init the static VRINGs. + * + * Init VRINGs and Virtqueues of an OpenAMP / RPMsg instance. + * + * @param vr Pointer to the VRINGs instance struct. + * @param role Master / Remote role. + * + * @retval -EINVAL When some parameter is missing. + * @retval -ENOMEM When memory is not enough for VQs allocation. + * @retval 0 If successful. + * @retval Other errno codes depending on the OpenAMP implementation. + */ +int ipc_static_vrings_init(struct ipc_static_vrings *vr, unsigned int role); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_IPC_SERVICE_IPC_STATIC_VRINGS_H_ */ diff --git a/include/ipc/rpmsg_multi_instance.h b/include/ipc/rpmsg_multi_instance.h deleted file mode 100644 index 5749c39d380..00000000000 --- a/include/ipc/rpmsg_multi_instance.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INSTANCE_H_ -#define ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INSTANCE_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief RPMsg multiple instance API - * @defgroup rpmsg_multiple_instance_api RPMsg multiple instance APIs - * @{ - */ - -#define VDEV_START_ADDR CONFIG_RPMSG_MULTI_INSTANCE_SHM_BASE_ADDRESS -#define VDEV_SIZE CONFIG_RPMSG_MULTI_INSTANCE_SHM_SIZE - -#define SHM_START_ADDR VDEV_START_ADDR -#define SHM_SIZE VDEV_SIZE - -#define VRING_ALIGNMENT (4) /**< Alignment of vring buffer. */ -#define VDEV_STATUS_SIZE (0x4) /**< Size of status region. */ - -/** @brief Event callback structure. - * - * It is registered during endpoint registration. - * This structure is packed into the endpoint configuration. - */ -struct rpmsg_mi_cb { - /** @brief Bind was successful. - * - * @param priv Private user data. - */ - void (*bound)(void *priv); - - /** @brief New packet arrived. - * - * @param data Pointer to data buffer. - * @param len Length of @a data. - * @param priv Private user data. - */ - void (*received)(const void *data, size_t len, void *priv); -}; - -/** @brief Endpoint instance. */ -struct rpmsg_mi_ept { - - /** Name of endpoint. */ - const char *name; - - /** RPMsg endpoint. */ - struct rpmsg_endpoint ep; - - /** Event callback structure. */ - struct rpmsg_mi_cb *cb; - - /** Private user data. */ - void *priv; - - /** Endpoint was bound. */ - volatile bool bound; - - /** Linked list node. */ - sys_snode_t node; -}; - -/** @brief Endpoint configuration. */ -struct rpmsg_mi_ept_cfg { - - /** Name of endpoint. */ - const char *name; - - /** Event callback structure. */ - struct rpmsg_mi_cb *cb; - - /** Private user data. */ - void *priv; -}; - -/** @brief Struct describing the context of the RPMsg instance. */ -struct rpmsg_mi_ctx { - const char *name; - struct k_work_q ipm_work_q; - struct k_work ipm_work; - - const struct device *ipm_tx_handle; - const struct device *ipm_rx_handle; - - unsigned int ipm_tx_id; - - uintptr_t shm_status_reg_addr; - struct metal_io_region *shm_io; - struct metal_device shm_device; - metal_phys_addr_t shm_physmap[1]; - - struct rpmsg_virtio_device rvdev; - struct rpmsg_virtio_shm_pool shpool; - struct rpmsg_device *rdev; - - struct virtqueue *vq[2]; - struct virtio_vring_info rvrings[2]; - struct virtio_device vdev; - - uintptr_t vring_tx_addr; - uintptr_t vring_rx_addr; - - sys_slist_t endpoints; -}; - -struct rpmsg_mi_ctx_shm_cfg { - /** Physical address shared memory region. */ - uintptr_t addr; - - /** Size shared memory region. */ - size_t size; - - /** Internal counter. */ - unsigned int instance; -}; - -/** @brief Configuration of the RPMsg instance. */ -struct rpmsg_mi_ctx_cfg { - - /** Name of instance. */ - const char *name; - - /** Stack area for k_work_q. */ - k_thread_stack_t *ipm_stack_area; - - /** Size of stack area. */ - size_t ipm_stack_size; - - /** Priority of work_q. */ - int ipm_work_q_prio; - - /** Name of work_q thread. */ - const char *ipm_thread_name; - - /** Name of the TX IPM channel. */ - const char *ipm_tx_name; - - /** Name of the RX IPM channel. */ - const char *ipm_rx_name; - - /** IPM message identifier. */ - unsigned int ipm_tx_id; - - /** SHM struct. */ - struct rpmsg_mi_ctx_shm_cfg *shm; -}; - -/** @brief Initialization of RPMsg instance. - * - * Each instance has an automatically allocated area of shared memory. - * - * @param ctx Pointer to the RPMsg instance. - * @param cfg Pointer to the configuration structure. - * @retval 0 if the operation was successful. - * -EINVAL when the incorrect parameters have been passed. - * -EIO when the configuration is not correct. - * -ENODEV failed to get TX or RX IPM handle. - * -ENOMEM when there is not enough memory to register virqueue. - * < 0 on other negative errno code, reported by rpmsg. - */ -int rpmsg_mi_ctx_init(struct rpmsg_mi_ctx *ctx, const struct rpmsg_mi_ctx_cfg *cfg); - -/** @brief Register IPC endpoint. - * - * Registers IPC endpoint to enable communication with a remote device. - * - * @param ctx Pointer to the RPMsg instance. - * @param ept Pointer to endpoint object. - * @param cfg Pointer to the endpoint configuration. - * - * @retval -EINVAL One of the parameters is incorrect. - * @retval other errno code reported by rpmsg. - */ -int rpmsg_mi_ept_register(struct rpmsg_mi_ctx *ctx, - struct rpmsg_mi_ept *ept, - struct rpmsg_mi_ept_cfg *cfg); - -/** @brief Send data using given IPC endpoint. - * - * Note: It is not possible to send a message of zero length. - * - * @param ept Endpoint object. - * @param data Pointer to the buffer to send through RPMsg. - * @param len Number of bytes to send. - * - * @retval Number of bytes it has sent or negative error value on failure. - */ -int rpmsg_mi_send(struct rpmsg_mi_ept *ept, const void *data, size_t len); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INNSTANCE_H_ */ diff --git a/samples/subsys/ipc/ipc_service/boards/bl5340_dvk_cpuapp.conf b/samples/subsys/ipc/ipc_service/boards/bl5340_dvk_cpuapp.conf index 80828ae708d..3a3bad9f085 100644 --- a/samples/subsys/ipc/ipc_service/boards/bl5340_dvk_cpuapp.conf +++ b/samples/subsys/ipc/ipc_service/boards/bl5340_dvk_cpuapp.conf @@ -18,7 +18,7 @@ CONFIG_IPM_MSG_CH_2_RX=y CONFIG_IPM_MSG_CH_1_TX=y CONFIG_IPM_MSG_CH_3_TX=y -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_3" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_2" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_TX_NAME="IPM_1" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_RX_NAME="IPM_0" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_TX_NAME="IPM_3" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_RX_NAME="IPM_2" diff --git a/samples/subsys/ipc/ipc_service/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/subsys/ipc/ipc_service/boards/nrf5340dk_nrf5340_cpuapp.conf index 80828ae708d..3a3bad9f085 100644 --- a/samples/subsys/ipc/ipc_service/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/samples/subsys/ipc/ipc_service/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -18,7 +18,7 @@ CONFIG_IPM_MSG_CH_2_RX=y CONFIG_IPM_MSG_CH_1_TX=y CONFIG_IPM_MSG_CH_3_TX=y -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_3" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_2" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_TX_NAME="IPM_1" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_RX_NAME="IPM_0" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_TX_NAME="IPM_3" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_RX_NAME="IPM_2" diff --git a/samples/subsys/ipc/ipc_service/prj.conf b/samples/subsys/ipc/ipc_service/prj.conf index 3fe55e55a8b..6c230287c3b 100644 --- a/samples/subsys/ipc/ipc_service/prj.conf +++ b/samples/subsys/ipc/ipc_service/prj.conf @@ -6,14 +6,14 @@ CONFIG_HEAP_MEM_POOL_SIZE=4096 # Configuration IPC Service CONFIG_IPC_SERVICE=y -CONFIG_IPC_SERVICE_BACKEND_RPMSG_MULTI_INSTANCE=y +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_MASTER=y +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI=y # Configuration backend for IPC Service CONFIG_OPENAMP=y CONFIG_OPENAMP_SLAVE=n -CONFIG_RPMSG_MULTI_INSTANCE_MASTER=y -CONFIG_RPMSG_MULTI_INSTANCES_NO=2 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_NUM_INSTANCES=2 CONFIG_LOG=y CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/ipc_service/remote/boards/bl5340_dvk_cpunet.conf b/samples/subsys/ipc/ipc_service/remote/boards/bl5340_dvk_cpunet.conf index 6330edea978..7b89adb4690 100644 --- a/samples/subsys/ipc/ipc_service/remote/boards/bl5340_dvk_cpunet.conf +++ b/samples/subsys/ipc/ipc_service/remote/boards/bl5340_dvk_cpunet.conf @@ -16,7 +16,7 @@ CONFIG_IPM_MSG_CH_3_RX=y CONFIG_IPM_MSG_CH_0_TX=y CONFIG_IPM_MSG_CH_2_TX=y -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_2" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_3" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_TX_NAME="IPM_0" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_RX_NAME="IPM_1" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_TX_NAME="IPM_2" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_RX_NAME="IPM_3" diff --git a/samples/subsys/ipc/ipc_service/remote/boards/nrf5340dk_nrf5340_cpunet.conf b/samples/subsys/ipc/ipc_service/remote/boards/nrf5340dk_nrf5340_cpunet.conf index 6330edea978..7b89adb4690 100644 --- a/samples/subsys/ipc/ipc_service/remote/boards/nrf5340dk_nrf5340_cpunet.conf +++ b/samples/subsys/ipc/ipc_service/remote/boards/nrf5340dk_nrf5340_cpunet.conf @@ -16,7 +16,7 @@ CONFIG_IPM_MSG_CH_3_RX=y CONFIG_IPM_MSG_CH_0_TX=y CONFIG_IPM_MSG_CH_2_TX=y -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_2" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_3" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_TX_NAME="IPM_0" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_0_IPM_RX_NAME="IPM_1" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_TX_NAME="IPM_2" +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_1_IPM_RX_NAME="IPM_3" diff --git a/samples/subsys/ipc/ipc_service/remote/prj.conf b/samples/subsys/ipc/ipc_service/remote/prj.conf index 3620f48d34b..627f64d3e40 100644 --- a/samples/subsys/ipc/ipc_service/remote/prj.conf +++ b/samples/subsys/ipc/ipc_service/remote/prj.conf @@ -6,14 +6,14 @@ CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096 # Configuration IPC Service CONFIG_IPC_SERVICE=y -CONFIG_IPC_SERVICE_BACKEND_RPMSG_MULTI_INSTANCE=y +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_REMOTE=y +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI=y # Configuration backend for IPC Service CONFIG_OPENAMP=y CONFIG_OPENAMP_MASTER=n -CONFIG_RPMSG_MULTI_INSTANCE_REMOTE=y -CONFIG_RPMSG_MULTI_INSTANCES_NO=2 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_NUM_INSTANCES=2 CONFIG_LOG=y CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/rpmsg_multi_instance/CMakeLists.txt b/samples/subsys/ipc/rpmsg_multi_instance/CMakeLists.txt deleted file mode 100644 index b1a16e83e78..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# - -cmake_minimum_required(VERSION 3.20.0) - -set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/rpmsg_multi_instance_remote-prefix/src/rpmsg_multi_instance_remote-build/zephyr) - -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") - set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") -elseif("${BOARD}" STREQUAL "bl5340_dvk_cpuapp") - set(BOARD_REMOTE "bl5340_dvk_cpunet") -else() - message(FATAL_ERROR "${BOARD} is not supported for this sample") -endif() - -message(INFO " ${BOARD} compile as Master in this sample") - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(rpmsg_multi_instance) - -enable_language(C ASM) - -target_sources(app PRIVATE src/main.c) - -include(ExternalProject) - -ExternalProject_Add( - rpmsg_multi_instance_remote - SOURCE_DIR ${APPLICATION_SOURCE_DIR}/remote - INSTALL_COMMAND "" # This particular build system has no install command - CMAKE_CACHE_ARGS -DBOARD:STRING=${BOARD_REMOTE} - CMAKE_CACHE_ARGS -DDTC_OVERLAY_FILE:STRING=${DTC_OVERLAY_FILE} - BUILD_BYPRODUCTS "${REMOTE_ZEPHYR_DIR}/${KERNEL_BIN_NAME}" - # NB: Do we need to pass on more CMake variables? - BUILD_ALWAYS True -) diff --git a/samples/subsys/ipc/rpmsg_multi_instance/README.rst b/samples/subsys/ipc/rpmsg_multi_instance/README.rst deleted file mode 100644 index 47feb0bdc45..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/README.rst +++ /dev/null @@ -1,135 +0,0 @@ -.. _Multiple_instance_RPMsg_sample: - -Multiple instance of RPMsg -########################## - -Overview -******** - -Multiple instance of RPMsg is an abstraction created over OpenAMP. -It simplifies the initialization and endpoint creation process. -This sample demonstrates how to use multi-instance RPMsg in Zephyr. - -Building the application for nrf5340dk_nrf5340_cpuapp -***************************************************** - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/ipc/rpmsg_multi_instance - :board: nrf5340dk_nrf5340_cpuapp - :goals: debug - -Open a serial terminal (for example Minicom or PuTTY) and connect the board with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -When you reset the development kit, the following messages (one for master and one for remote) will appear on the corresponding serial ports: - -.. code-block:: console - - *** Booting Zephyr OS build zephyr-v2.5.0-3564-gf89886d69a8c *** - Starting application thread! - - RPMsg Multiple instance [master no 1] demo started - - RPMsg Multiple instance [master no 2] demo started - Master [no 1] core received a message: 1 - Master [no 2] core received a message: 1 - Master [no 1] core received a message: 3 - Master [no 2] core received a message: 3 - Master [no 1] core received a message: 5 - Master [no 2] core received a message: 5 - ... - Master [no 1] core received a message: 99 - RPMsg Multiple instance [no 1] demo ended. - Master [no 2] core received a message: 99 - RPMsg Multiple instance [no 2] demo ended. - - -.. code-block:: console - - *** Booting Zephyr OS build zephyr-v2.5.0-3564-gf89886d69a8c *** - Starting application thread! - - RPMsg Multiple instance [remote no 1] demo started - - RPMsg Multiple instance [remote no 2] demo started - Remote [no 1] core received a message: 0 - Remote [no 2] core received a message: 0 - Remote [no 1] core received a message: 2 - Remote [no 2] core received a message: 2 - Remote [no 1] core received a message: 4 - Remote [no 2] core received a message: 4 - ... - Remote [no 1] core received a message: 98 - RPMsg Multiple instance [no 1] demo ended. - Remote [no 2] core received a message: 98 - RPMsg Multiple instance [no 2] demo ended. - -Building the application for bl5340_dvk_cpuapp -********************************************** - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/ipc/rpmsg_multi_instance - :board: bl5340_dvk_cpuapp - :goals: debug - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/ipc/rpmsg_multi_instance/remote - :board: bl5340_dvk_cpunet - :goals: debug - -Open a serial terminal (for example Minicom or PuTTY) and connect to the board -with the following settings on both serial ports: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -When you reset the development kit after having flashed both the application -and network core images, the following messages (one for master and one for -remote) will appear on the corresponding serial ports: - -.. code-block:: console - - *** Booting Zephyr OS build v2.7.0-rc1-103-ge19875c88916 *** - Starting application thread! - - RPMsg Multiple instance [master no 1] demo started - - RPMsg Multiple instance [master no 2] demo started - Master [no 1] core received a message: 1 - Master [no 2] core received a message: 1 - Master [no 1] core received a message: 3 - Master [no 2] core received a message: 3 - Master [no 1] core received a message: 5 - Master [no 2] core received a message: 5 - ... - Master [no 1] core received a message: 99 - RPMsg Multiple instance [no 1] demo ended. - Master [no 2] core received a message: 99 - RPMsg Multiple instance [no 2] demo ended. - - -.. code-block:: console - - *** Booting Zephyr OS build v2.7.0-rc1-103-ge19875c88916 *** - Starting application thread! - - RPMsg Multiple instance [remote no 1] demo started - - RPMsg Multiple instance [remote no 2] demo started - Remote [no 1] core received a message: 0 - Remote [no 2] core received a message: 0 - Remote [no 1] core received a message: 2 - Remote [no 2] core received a message: 2 - Remote [no 1] core received a message: 4 - Remote [no 2] core received a message: 4 - ... - Remote [no 1] core received a message: 98 - RPMsg Multiple instance [no 1] demo ended. - Remote [no 2] core received a message: 98 - RPMsg Multiple instance [no 2] demo ended. diff --git a/samples/subsys/ipc/rpmsg_multi_instance/boards/bl5340_dvk_cpuapp.conf b/samples/subsys/ipc/rpmsg_multi_instance/boards/bl5340_dvk_cpuapp.conf deleted file mode 100644 index 9ca315f4ea8..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/boards/bl5340_dvk_cpuapp.conf +++ /dev/null @@ -1,24 +0,0 @@ -CONFIG_BOARD_ENABLE_CPUNET=y - -#IPM Configuration -CONFIG_IPM=y -CONFIG_IPM_NRFX=y - -# Enable all needed IPM channels -CONFIG_IPM_MSG_CH_0_ENABLE=y -CONFIG_IPM_MSG_CH_1_ENABLE=y -CONFIG_IPM_MSG_CH_2_ENABLE=y -CONFIG_IPM_MSG_CH_3_ENABLE=y - -# Configure all RX channels -CONFIG_IPM_MSG_CH_0_RX=y -CONFIG_IPM_MSG_CH_2_RX=y - -# Configure all TX channels -CONFIG_IPM_MSG_CH_1_TX=y -CONFIG_IPM_MSG_CH_3_TX=y - -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_3" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_2" diff --git a/samples/subsys/ipc/rpmsg_multi_instance/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/subsys/ipc/rpmsg_multi_instance/boards/nrf5340dk_nrf5340_cpuapp.conf deleted file mode 100644 index 9ca315f4ea8..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/boards/nrf5340dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,24 +0,0 @@ -CONFIG_BOARD_ENABLE_CPUNET=y - -#IPM Configuration -CONFIG_IPM=y -CONFIG_IPM_NRFX=y - -# Enable all needed IPM channels -CONFIG_IPM_MSG_CH_0_ENABLE=y -CONFIG_IPM_MSG_CH_1_ENABLE=y -CONFIG_IPM_MSG_CH_2_ENABLE=y -CONFIG_IPM_MSG_CH_3_ENABLE=y - -# Configure all RX channels -CONFIG_IPM_MSG_CH_0_RX=y -CONFIG_IPM_MSG_CH_2_RX=y - -# Configure all TX channels -CONFIG_IPM_MSG_CH_1_TX=y -CONFIG_IPM_MSG_CH_3_TX=y - -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_3" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_2" diff --git a/samples/subsys/ipc/rpmsg_multi_instance/prj.conf b/samples/subsys/ipc/rpmsg_multi_instance/prj.conf deleted file mode 100644 index c443ed44983..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/prj.conf +++ /dev/null @@ -1,16 +0,0 @@ -CONFIG_PRINTK=y -CONFIG_IPM=y -CONFIG_TIMESLICE_SIZE=1 -CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_HEAP_MEM_POOL_SIZE=4096 - -# Enable RPMsg multiple instance -CONFIG_RPMSG_MULTI_INSTANCE=y -CONFIG_RPMSG_MULTI_INSTANCE_MASTER=y -CONFIG_RPMSG_MULTI_INSTANCES_NO=2 - -CONFIG_OPENAMP=y -CONFIG_OPENAMP_SLAVE=n - -CONFIG_LOG=y -CONFIG_RPMSG_MULTI_INSTANCE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/rpmsg_multi_instance/remote/CMakeLists.txt b/samples/subsys/ipc/rpmsg_multi_instance/remote/CMakeLists.txt deleted file mode 100644 index 39ed135bf83..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/remote/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# - -cmake_minimum_required(VERSION 3.20.0) - -if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpunet" - OR "${BOARD}" STREQUAL "bl5340_dvk_cpunet") - message(INFO " ${BOARD} compile as slave in this sample") -else() - message(FATAL_ERROR "${BOARD} is not supported for this sample") -endif() - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(rpmsg_multi_instance_remote) - -target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/ipc/rpmsg_multi_instance/remote/boards/bl5340_dvk_cpunet.conf b/samples/subsys/ipc/rpmsg_multi_instance/remote/boards/bl5340_dvk_cpunet.conf deleted file mode 100644 index c477f043c4d..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/remote/boards/bl5340_dvk_cpunet.conf +++ /dev/null @@ -1,22 +0,0 @@ -#IPM Configuration -CONFIG_IPM=y -CONFIG_IPM_NRFX=y - -# Enable all needed IPM channels -CONFIG_IPM_MSG_CH_0_ENABLE=y -CONFIG_IPM_MSG_CH_1_ENABLE=y -CONFIG_IPM_MSG_CH_2_ENABLE=y -CONFIG_IPM_MSG_CH_3_ENABLE=y - -# Configure all RX channels -CONFIG_IPM_MSG_CH_1_RX=y -CONFIG_IPM_MSG_CH_3_RX=y - -# Configure all TX channels -CONFIG_IPM_MSG_CH_0_TX=y -CONFIG_IPM_MSG_CH_2_TX=y - -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_2" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_3" diff --git a/samples/subsys/ipc/rpmsg_multi_instance/remote/boards/nrf5340dk_nrf5340_cpunet.conf b/samples/subsys/ipc/rpmsg_multi_instance/remote/boards/nrf5340dk_nrf5340_cpunet.conf deleted file mode 100644 index c477f043c4d..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/remote/boards/nrf5340dk_nrf5340_cpunet.conf +++ /dev/null @@ -1,22 +0,0 @@ -#IPM Configuration -CONFIG_IPM=y -CONFIG_IPM_NRFX=y - -# Enable all needed IPM channels -CONFIG_IPM_MSG_CH_0_ENABLE=y -CONFIG_IPM_MSG_CH_1_ENABLE=y -CONFIG_IPM_MSG_CH_2_ENABLE=y -CONFIG_IPM_MSG_CH_3_ENABLE=y - -# Configure all RX channels -CONFIG_IPM_MSG_CH_1_RX=y -CONFIG_IPM_MSG_CH_3_RX=y - -# Configure all TX channels -CONFIG_IPM_MSG_CH_0_TX=y -CONFIG_IPM_MSG_CH_2_TX=y - -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME="IPM_0" -CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME="IPM_1" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME="IPM_2" -CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME="IPM_3" diff --git a/samples/subsys/ipc/rpmsg_multi_instance/remote/prj.conf b/samples/subsys/ipc/rpmsg_multi_instance/remote/prj.conf deleted file mode 100644 index ab6c7c85a42..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/remote/prj.conf +++ /dev/null @@ -1,16 +0,0 @@ -CONFIG_STDOUT_CONSOLE=n -CONFIG_PRINTK=n -CONFIG_IPM=y -CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096 - -# Enable Rpmsg multiple instance -CONFIG_RPMSG_MULTI_INSTANCE=y -CONFIG_RPMSG_MULTI_INSTANCE_REMOTE=y -CONFIG_RPMSG_MULTI_INSTANCES_NO=2 - -CONFIG_OPENAMP=y -CONFIG_OPENAMP_MASTER=n - -CONFIG_LOG=y -CONFIG_RPMSG_MULTI_INSTANCE_LOG_LEVEL_INF=y diff --git a/samples/subsys/ipc/rpmsg_multi_instance/remote/src/main.c b/samples/subsys/ipc/rpmsg_multi_instance/remote/src/main.c deleted file mode 100644 index f3ddfbd4d5b..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/remote/src/main.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define IPM_WORK_QUEUE_STACK_SIZE 1024 -#define APP_TASK_STACK_SIZE 1024 - -#define IPM_MSG_ID 0 - -K_THREAD_STACK_DEFINE(ipm_stack_area_1, IPM_WORK_QUEUE_STACK_SIZE); -K_THREAD_STACK_DEFINE(ipm_stack_area_2, IPM_WORK_QUEUE_STACK_SIZE); - -K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE); -K_THREAD_STACK_DEFINE(thread_stack_2, APP_TASK_STACK_SIZE); - -static struct k_thread thread_data_1; -static struct k_thread thread_data_2; - -static K_SEM_DEFINE(bound_ept1_sem, 0, 1); -static K_SEM_DEFINE(bound_ept2_sem, 0, 1); - -static K_SEM_DEFINE(data_rx1_sem, 0, 1); -static K_SEM_DEFINE(data_rx2_sem, 0, 1); - -static volatile uint8_t received_data_1; -static volatile uint8_t received_data_2; - -static struct rpmsg_mi_ctx ctx_1; -static struct rpmsg_mi_ctx ctx_2; - -static struct rpmsg_mi_ept ept_1; -static struct rpmsg_mi_ept ept_2; - -static void boud1_cb(void *priv) -{ - k_sem_give(&bound_ept1_sem); -} - -static void received1_cb(const void *data, size_t len, void *priv) -{ - received_data_1 = *((uint8_t *)data); - k_sem_give(&data_rx1_sem); -} - -static void boud2_cb(void *priv) -{ - k_sem_give(&bound_ept2_sem); -} - -static void received2_cb(const void *data, size_t len, void *priv) -{ - received_data_2 = *((uint8_t *)data); - k_sem_give(&data_rx2_sem); -} - -static struct rpmsg_mi_ctx_shm_cfg shm = { - .addr = SHM_START_ADDR, - .size = SHM_SIZE, -}; - -static const struct rpmsg_mi_ctx_cfg cfg_1 = { - .name = "instance 1", - .ipm_stack_area = ipm_stack_area_1, - .ipm_stack_size = K_THREAD_STACK_SIZEOF(ipm_stack_area_1), - .ipm_thread_name = "ipm_work_q_1", - .ipm_work_q_prio = 0, - .ipm_tx_name = CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME, - .ipm_rx_name = CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME, - .ipm_tx_id = IPM_MSG_ID, - .shm = &shm, -}; - -static const struct rpmsg_mi_ctx_cfg cfg_2 = { - .name = "instance 2", - .ipm_stack_area = ipm_stack_area_2, - .ipm_stack_size = K_THREAD_STACK_SIZEOF(ipm_stack_area_2), - .ipm_thread_name = "ipm_work_q_2", - .ipm_work_q_prio = 0, - .ipm_tx_name = CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME, - .ipm_rx_name = CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME, - .ipm_tx_id = IPM_MSG_ID, - .shm = &shm, -}; - -static struct rpmsg_mi_cb cb_1 = { - .bound = boud1_cb, - .received = received1_cb, -}; - -static struct rpmsg_mi_cb cb_2 = { - .bound = boud2_cb, - .received = received2_cb, -}; -static struct rpmsg_mi_ept_cfg ept_cfg_1 = { - .name = "ept1", - .cb = &cb_1, - .priv = &ept_1, -}; - -static struct rpmsg_mi_ept_cfg ept_cfg_2 = { - .name = "ept2", - .cb = &cb_2, - .priv = &ept_2, -}; - -void app_task_1(void *arg1, void *arg2, void *arg3) -{ - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); - ARG_UNUSED(arg3); - int status = 0; - uint8_t message = 0U; - - printk("\r\nRPMsg Multiple instance [remote no 1] demo started\r\n"); - - /* Initialization of 1 instance */ - status = rpmsg_mi_ctx_init(&ctx_1, &cfg_1); - if (status < 0) { - printk("rpmsg_mi_init [no 1] failed with status %d\n", status); - } - - status = rpmsg_mi_ept_register(&ctx_1, &ept_1, &ept_cfg_1); - if (status < 0) { - printk("rpmsg_mi_ept_register [no 1] failed with status %d\n", - status); - } - - /* Waiting to be bound. */ - k_sem_take(&bound_ept1_sem, K_FOREVER); - - - while (message < 99) { - k_sem_take(&data_rx1_sem, K_FOREVER); - message = received_data_1; - printk("Remote [no 1] core received a message: %d\n", message); - - message++; - status = rpmsg_mi_send(&ept_1, &message, sizeof(message)); - if (status < 0) { - printk("send_message(%d) failed with status %d\n", - message, status); - } - } - - printk("RPMsg Multiple instance [no 1] demo ended.\n"); -} - -void app_task_2(void *arg1, void *arg2, void *arg3) -{ - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); - ARG_UNUSED(arg3); - int status = 0; - uint8_t message = 0U; - - printk("\r\nRPMsg Multiple instance [remote no 2] demo started\r\n"); - - /* Initialization of 2 instance */ - status = rpmsg_mi_ctx_init(&ctx_2, &cfg_2); - if (status < 0) { - printk("rpmsg_mi_init [no 2] failed with status %d\n", status); - } - - status = rpmsg_mi_ept_register(&ctx_2, &ept_2, &ept_cfg_2); - if (status < 0) { - printk("rpmsg_mi_ept_register [no 2] failed with status %d\n", - status); - } - - /* Waiting to be bound. */ - k_sem_take(&bound_ept2_sem, K_FOREVER); - - - while (message < 99) { - k_sem_take(&data_rx2_sem, K_FOREVER); - message = received_data_2; - printk("Remote [no 2] core received a message: %d\n", message); - - /* k_sleep(K_MSEC(1));*/ /* for testing*/ - - message++; - status = rpmsg_mi_send(&ept_2, &message, sizeof(message)); - if (status < 0) { - printk("send_message(%d) failed with status %d\n", - message, status); - } - } - - printk("RPMsg Multiple instance [no 2] demo ended.\n"); -} - -void main(void) -{ - printk("Starting application thread!\n"); - - k_thread_create(&thread_data_1, thread_stack_1, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task_1, - NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); - - k_thread_create(&thread_data_2, thread_stack_2, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task_2, - NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); -} diff --git a/samples/subsys/ipc/rpmsg_multi_instance/sample.yaml b/samples/subsys/ipc/rpmsg_multi_instance/sample.yaml deleted file mode 100644 index 23dcb7ba01d..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/sample.yaml +++ /dev/null @@ -1,11 +0,0 @@ -sample: - description: This app provides an example of how to integrate - RPMsg Multiple Instance with Zephyr. - name: RPMsg Multiple Instance example integration -tests: - sample.ipc.rpmsg_multiple_instance.nrf: - platform_allow: nrf5340dk_nrf5340_cpuapp bl5340_dvk_cpuapp - integration_platforms: - - nrf5340dk_nrf5340_cpuapp bl5340_dvk_cpuapp - tags: ipm - build_only: true diff --git a/samples/subsys/ipc/rpmsg_multi_instance/src/main.c b/samples/subsys/ipc/rpmsg_multi_instance/src/main.c deleted file mode 100644 index bb9fa3f7bd5..00000000000 --- a/samples/subsys/ipc/rpmsg_multi_instance/src/main.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define IPM_WORK_QUEUE_STACK_SIZE 1024 -#define APP_TASK_STACK_SIZE 1024 - -#define IPM_MSG_ID 0 - -K_THREAD_STACK_DEFINE(ipm_stack_area_1, IPM_WORK_QUEUE_STACK_SIZE); -K_THREAD_STACK_DEFINE(ipm_stack_area_2, IPM_WORK_QUEUE_STACK_SIZE); - -K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE); -K_THREAD_STACK_DEFINE(thread_stack_2, APP_TASK_STACK_SIZE); - -static struct k_thread thread_data_1; -static struct k_thread thread_data_2; - -static K_SEM_DEFINE(bound_ept1_sem, 0, 1); -static K_SEM_DEFINE(bound_ept2_sem, 0, 1); - -static K_SEM_DEFINE(data_rx1_sem, 0, 1); -static K_SEM_DEFINE(data_rx2_sem, 0, 1); - -static volatile uint8_t received_data_1; -static volatile uint8_t received_data_2; - -static struct rpmsg_mi_ctx ctx_1; -static struct rpmsg_mi_ctx ctx_2; - -static struct rpmsg_mi_ept ept_1; -static struct rpmsg_mi_ept ept_2; - -static void boud1_cb(void *priv) -{ - k_sem_give(&bound_ept1_sem); -} - -static void received1_cb(const void *data, size_t len, void *priv) -{ - received_data_1 = *((uint8_t *)data); - k_sem_give(&data_rx1_sem); -} - -static void boud2_cb(void *priv) -{ - k_sem_give(&bound_ept2_sem); -} - -static void received2_cb(const void *data, size_t len, void *priv) -{ - received_data_2 = *((uint8_t *)data); - k_sem_give(&data_rx2_sem); -} - -static struct rpmsg_mi_ctx_shm_cfg shm = { - .addr = SHM_START_ADDR, - .size = SHM_SIZE, -}; - -static const struct rpmsg_mi_ctx_cfg cfg_1 = { - .name = "instance 1", - .ipm_stack_area = ipm_stack_area_1, - .ipm_stack_size = K_THREAD_STACK_SIZEOF(ipm_stack_area_1), - .ipm_thread_name = "ipm_work_q_1", - .ipm_work_q_prio = 0, - .ipm_tx_name = CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_TX_NAME, - .ipm_rx_name = CONFIG_RPMSG_MULTI_INSTANCE_0_IPM_RX_NAME, - .ipm_tx_id = IPM_MSG_ID, - .shm = &shm, -}; - -static const struct rpmsg_mi_ctx_cfg cfg_2 = { - .name = "instance 2", - .ipm_stack_area = ipm_stack_area_2, - .ipm_stack_size = K_THREAD_STACK_SIZEOF(ipm_stack_area_2), - .ipm_thread_name = "ipm_work_q_2", - .ipm_work_q_prio = 0, - .ipm_tx_name = CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_TX_NAME, - .ipm_rx_name = CONFIG_RPMSG_MULTI_INSTANCE_1_IPM_RX_NAME, - .ipm_tx_id = IPM_MSG_ID, - .shm = &shm, -}; - -static struct rpmsg_mi_cb cb_1 = { - .bound = boud1_cb, - .received = received1_cb, -}; - -static struct rpmsg_mi_cb cb_2 = { - .bound = boud2_cb, - .received = received2_cb, -}; - -static struct rpmsg_mi_ept_cfg ept_cfg_1 = { - .name = "ept1", - .cb = &cb_1, - .priv = &ept_1, -}; - -static struct rpmsg_mi_ept_cfg ept_cfg_2 = { - .name = "ept2", - .cb = &cb_2, - .priv = &ept_2, -}; - -void app_task_1(void *arg1, void *arg2, void *arg3) -{ - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); - ARG_UNUSED(arg3); - int status = 0; - uint8_t message = 0U; - - printk("\r\nRPMsg Multiple instance [master no 1] demo started\r\n"); - - /* Initialization of 1 instance */ - status = rpmsg_mi_ctx_init(&ctx_1, &cfg_1); - if (status < 0) { - printk("rpmsg_mi_init for [no 1] failed with status %d\n", - status); - } - - status = rpmsg_mi_ept_register(&ctx_1, &ept_1, &ept_cfg_1); - if (status < 0) { - printk("rpmsg_mi_ept_register [no 1] failed with status %d\n", - status); - } - - /* Waiting to be bound. */ - k_sem_take(&bound_ept1_sem, K_FOREVER); - - while (message < 100) { - status = rpmsg_mi_send(&ept_1, &message, sizeof(message)); - if (status < 0) { - printk("send_message(%d) failed with status %d\n", - message, status); - } - - k_sem_take(&data_rx1_sem, K_FOREVER); - message = received_data_1; - - printk("Master [no 1] core received a message: %d\n", message); - message++; - } - - printk("RPMsg Multiple instance [no 1] demo ended.\n"); -} - -void app_task_2(void *arg1, void *arg2, void *arg3) -{ - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); - ARG_UNUSED(arg3); - int status = 0; - uint8_t message = 0U; - - printk("\r\nRPMsg Multiple instance [master no 2] demo started\r\n"); - - /* Initialization of 2 instance */ - status = rpmsg_mi_ctx_init(&ctx_2, &cfg_2); - if (status < 0) { - printk("rpmsg_mi_init [no 2] failed with status %d\n", status); - } - - status = rpmsg_mi_ept_register(&ctx_2, &ept_2, &ept_cfg_2); - if (status < 0) { - printk("rpmsg_mi_ept_register [no 2] failed with status %d\n", - status); - } - - /* Waiting to be bound. */ - k_sem_take(&bound_ept2_sem, K_FOREVER); - - while (message < 100) { - status = rpmsg_mi_send(&ept_2, &message, sizeof(message)); - if (status < 0) { - printk("send_message(%d) failed with status %d\n", - message, status); - } - - k_sem_take(&data_rx2_sem, K_FOREVER); - message = received_data_2; - - printk("Master [no 2] core received a message: %d\n", message); - - message++; - } - - printk("RPMsg Multiple instance [no 2] demo ended.\n"); -} - -void main(void) -{ - printk("Starting application thread!\n"); - - k_thread_create(&thread_data_1, thread_stack_1, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task_1, - NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); - - k_thread_create(&thread_data_2, thread_stack_2, APP_TASK_STACK_SIZE, - (k_thread_entry_t)app_task_2, - NULL, NULL, NULL, K_PRIO_COOP(8), 0, K_NO_WAIT); -} diff --git a/subsys/ipc/CMakeLists.txt b/subsys/ipc/CMakeLists.txt index 76bf54bcc60..d7df0d0b2dd 100644 --- a/subsys/ipc/CMakeLists.txt +++ b/subsys/ipc/CMakeLists.txt @@ -1,5 +1,4 @@ # SPDX-License-Identifier: Apache-2.0 add_subdirectory_ifdef(CONFIG_RPMSG_SERVICE rpmsg_service) -add_subdirectory_ifdef(CONFIG_RPMSG_MULTI_INSTANCE rpmsg_multi_instance) add_subdirectory_ifdef(CONFIG_IPC_SERVICE ipc_service) diff --git a/subsys/ipc/Kconfig b/subsys/ipc/Kconfig index 38cbf7a1ef9..f8e2445d4cf 100644 --- a/subsys/ipc/Kconfig +++ b/subsys/ipc/Kconfig @@ -6,7 +6,6 @@ menu "Inter Processor Communication" source "subsys/ipc/rpmsg_service/Kconfig" -source "subsys/ipc/rpmsg_multi_instance/Kconfig" source "subsys/ipc/ipc_service/Kconfig" endmenu diff --git a/subsys/ipc/ipc_service/Kconfig b/subsys/ipc/ipc_service/Kconfig index 1829589ec07..3c84e3e65f1 100644 --- a/subsys/ipc/ipc_service/Kconfig +++ b/subsys/ipc/ipc_service/Kconfig @@ -11,23 +11,15 @@ menuconfig IPC_SERVICE if IPC_SERVICE -choice IPC_SERVICE_BACKEND - prompt "IPC Service backend" +rsource "backends/Kconfig" -config IPC_SERVICE_BACKEND_RPMSG_MULTI_INSTANCE - bool "RPMsg multiple instance backend" - select RPMSG_MULTI_INSTANCE +config IPC_SERVICE_NUM_ENDPOINTS_PER_INSTANCE + int "Max number of registered endpoints per instance" + default 2 + help + Maximal number of endpoints that can be registered for one instance. -endchoice - -if IPC_SERVICE_BACKEND_RPMSG_MULTI_INSTANCE - -rsource "backends/Kconfig.rpmsg_mi" - -endif # IPC_SERVICE_BACKEND_RPMSG_MULTI_INSTANCE - - -config IPC_SERVICE_BACKEND_REG_PRIORITY +config IPC_SERVICE_REG_BACKEND_PRIORITY int "Initialization priority of modules registering IPC backend" default 46 help diff --git a/subsys/ipc/ipc_service/backends/CMakeLists.txt b/subsys/ipc/ipc_service/backends/CMakeLists.txt index 00d8b30ba78..e7e7078fb96 100644 --- a/subsys/ipc/ipc_service/backends/CMakeLists.txt +++ b/subsys/ipc/ipc_service/backends/CMakeLists.txt @@ -1,3 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 -zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_RPMSG_MULTI_INSTANCE ipc_rpmsg_multi_instance.c) +# libraries +zephyr_sources_ifdef(CONFIG_IPC_SERVICE_RPMSG ipc_rpmsg.c) +zephyr_sources_ifdef(CONFIG_IPC_SERVICE_STATIC_VRINGS ipc_static_vrings.c) + +# backends +zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI ipc_rpmsg_static_vrings_mi.c) diff --git a/subsys/ipc/ipc_service/backends/Kconfig b/subsys/ipc/ipc_service/backends/Kconfig new file mode 100644 index 00000000000..50c9dc63fb0 --- /dev/null +++ b/subsys/ipc/ipc_service/backends/Kconfig @@ -0,0 +1,30 @@ +# Copyright (c) 2021 Nordic Semiconductor (ASA) +# SPDX-License-Identifier: Apache-2.0 + +choice IPC_SERVICE_BACKEND + prompt "IPC service backend" + +config IPC_SERVICE_BACKEND_RPMSG_MI + bool "RPMSG backend - static VRINGs (multi-instance)" + select IPC_SERVICE_RPMSG + select IPC_SERVICE_STATIC_VRINGS + select OPENAMP + select IPM + +endchoice + +if IPC_SERVICE_BACKEND_RPMSG_MI + +rsource "Kconfig.rpmsg_mi" + +endif # IP_SERVICE_BACKEND_RPMSG_MI + +config IPC_SERVICE_RPMSG + bool "RPMsg support library" + help + "RPMsg library" + +config IPC_SERVICE_STATIC_VRINGS + bool "Static VRINGs support library" + help + "Static VRINGs library" diff --git a/subsys/ipc/rpmsg_multi_instance/Kconfig.ipm_name_instance b/subsys/ipc/ipc_service/backends/Kconfig.ipm_name_instance similarity index 73% rename from subsys/ipc/rpmsg_multi_instance/Kconfig.ipm_name_instance rename to subsys/ipc/ipc_service/backends/Kconfig.ipm_name_instance index bd80decdc60..ccb6fe14ee6 100644 --- a/subsys/ipc/rpmsg_multi_instance/Kconfig.ipm_name_instance +++ b/subsys/ipc/ipc_service/backends/Kconfig.ipm_name_instance @@ -1,13 +1,13 @@ # Copyright (c) 2021 Nordic Semiconductor (ASA) # SPDX-License-Identifier: Apache-2.0 -config RPMSG_MULTI_INSTANCE_$(ipm_name_instance_num)_IPM_TX_NAME +config IPC_SERVICE_BACKEND_RPMSG_MI_$(ipm_name_instance_num)_IPM_TX_NAME string "TX IPM channel name for instance $(ipm_name_instance_num)" help This option specifies the IPM device name to be used for TX communication. -config RPMSG_MULTI_INSTANCE_$(ipm_name_instance_num)_IPM_RX_NAME +config IPC_SERVICE_BACKEND_RPMSG_MI_$(ipm_name_instance_num)_IPM_RX_NAME string "RX IPM channel name for instance $(ipm_name_instance_num)" help This option specifies the IPM device name to be used for diff --git a/subsys/ipc/ipc_service/backends/Kconfig.rpmsg_mi b/subsys/ipc/ipc_service/backends/Kconfig.rpmsg_mi index f52491b01a5..7eebe8102b5 100644 --- a/subsys/ipc/ipc_service/backends/Kconfig.rpmsg_mi +++ b/subsys/ipc/ipc_service/backends/Kconfig.rpmsg_mi @@ -1,17 +1,60 @@ # Copyright (c) 2020-2021 Nordic Semiconductor (ASA) # SPDX-License-Identifier: Apache-2.0 -config IPC_BACKEND_RPMSG_MI_WORK_QUEUE_STACK_SIZE -int "Size of RX work queue stack" +choice IPC_SERVICE_BACKEND_RPMSG_MI_ROLE + prompt "IPC service device role" + +config IPC_SERVICE_BACKEND_RPMSG_MI_REMOTE + bool "Remote" + +config IPC_SERVICE_BACKEND_RPMSG_MI_MASTER + bool "Master" + +endchoice + +config IPC_SERVICE_BACKEND_RPMSG_MI_WQ_STACK_SIZE + int "Size of RX work queue stack" default 1024 help Size of stack used by work queue RX thread. This work queue is - created in the multi-instance RPMsg backend module to prevent notifying - service users about received data from the system work queue. - Size is the same for all instances. + created in the multi-instance / multi-core RPMsg backend module to + prevent notifying service users about received data from the system + work queue. Size is the same for all instances. -config IPC_BACKEND_RPMSG_MI_NUM_ENDPOINTS_PER_INSTANCE - int "Max number of registered endpoints per instance" - default 2 +config IPC_SERVICE_BACKEND_RPMSG_MI_SHM_BASE_ADDRESS + hex + default "$(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_IPC_SHM))" help - Maximal number of endpoints that can be registered for one instance. + This option specifies base address of the memory region to + be used for the OpenAMP IPC shared memory. + +config IPC_SERVICE_BACKEND_RPMSG_MI_SHM_SIZE + hex + default "$(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_IPC_SHM))" + help + This option specifies size of the memory region to be used + for the OpenAMP IPC shared memory. + +config IPC_SERVICE_BACKEND_RPMSG_MI_NUM_INSTANCES + int "Number of RPMsg instances" + default 2 + range 1 8 + help + How many instances are to be used. + +ipm_name_instance_num = 0 +rsource "Kconfig.ipm_name_instance" +ipm_name_instance_num = 1 +rsource "Kconfig.ipm_name_instance" +ipm_name_instance_num = 2 +rsource "Kconfig.ipm_name_instance" +ipm_name_instance_num = 3 +rsource "Kconfig.ipm_name_instance" +ipm_name_instance_num = 4 +rsource "Kconfig.ipm_name_instance" +ipm_name_instance_num = 5 +rsource "Kconfig.ipm_name_instance" +ipm_name_instance_num = 6 +rsource "Kconfig.ipm_name_instance" +ipm_name_instance_num = 7 +rsource "Kconfig.ipm_name_instance" diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg.c new file mode 100644 index 00000000000..5504b0d3716 --- /dev/null +++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static void rpmsg_service_unbind(struct rpmsg_endpoint *ep) +{ + rpmsg_destroy_ept(ep); +} + +static void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest) +{ + struct rpmsg_virtio_device *p_rvdev; + struct ipc_rpmsg_instance *instance; + struct ipc_ept *ept; + int err; + + p_rvdev = CONTAINER_OF(rdev, struct rpmsg_virtio_device, rdev); + instance = CONTAINER_OF(p_rvdev->shpool, struct ipc_rpmsg_instance, shm_pool); + + for (size_t i = 0; i < NUM_ENDPOINTS; i++) { + ept = &instance->endpoint[i]; + + if (strcmp(name, ept->name) == 0) { + err = rpmsg_create_ept(&ept->ep, rdev, name, RPMSG_ADDR_ANY, + dest, instance->cb, rpmsg_service_unbind); + if (err != 0) { + return; + } + + ept->bound = true; + if (instance->bound_cb) { + instance->bound_cb(ept); + } + } + } +} + +int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role, + struct ipc_ept *ept) +{ + struct rpmsg_device *rdev; + + if (!instance || !ept) { + return -EINVAL; + } + + rdev = rpmsg_virtio_get_rpmsg_device(&instance->rvdev); + + if (role == RPMSG_REMOTE) { + return rpmsg_create_ept(&ept->ep, rdev, ept->name, RPMSG_ADDR_ANY, + RPMSG_ADDR_ANY, instance->cb, rpmsg_service_unbind); + } + + return RPMSG_SUCCESS; +} + +int ipc_rpmsg_init(struct ipc_rpmsg_instance *instance, + unsigned int role, + struct metal_io_region *shm_io, + struct virtio_device *vdev, + void *shb, size_t size, + rpmsg_ns_bind_cb p_bind_cb) +{ + rpmsg_ns_bind_cb bind_cb = p_bind_cb; + + if (!instance || !shb) { + return -EINVAL; + } + + if (p_bind_cb == NULL) { + bind_cb = ns_bind_cb; + } + + if (role == RPMSG_MASTER) { + rpmsg_virtio_init_shm_pool(&instance->shm_pool, shb, size); + return rpmsg_init_vdev(&instance->rvdev, vdev, bind_cb, + shm_io, &instance->shm_pool); + } else { + return rpmsg_init_vdev(&instance->rvdev, vdev, bind_cb, shm_io, NULL); + } +} diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg_multi_instance.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg_multi_instance.c deleted file mode 100644 index 00849937e73..00000000000 --- a/subsys/ipc/ipc_service/backends/ipc_rpmsg_multi_instance.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2020-2021, Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#include -#include - -#include -#include -#include -#include - -LOG_MODULE_REGISTER(ipc_rpmsg_multi_instance, CONFIG_IPC_SERVICE_LOG_LEVEL); - -#define NUM_INSTANCES CONFIG_RPMSG_MULTI_INSTANCES_NO -#define NUM_ENDPOINTS CONFIG_IPC_BACKEND_RPMSG_MI_NUM_ENDPOINTS_PER_INSTANCE - -#define WORK_QUEUE_STACK_SIZE CONFIG_IPC_BACKEND_RPMSG_MI_WORK_QUEUE_STACK_SIZE - -#define PRIO_INIT_VAL INT_MAX -#define INSTANCE_NAME_SIZE 16 -#define IPM_MSG_ID 0 - -#define CH_NAME(idx, sub) (CONFIG_RPMSG_MULTI_INSTANCE_ ## idx ## _IPM_ ## sub ## _NAME) - -static char *ipm_rx_name[] = { - FOR_EACH_FIXED_ARG(CH_NAME, (,), RX, 0, 1, 2, 3, 4, 5, 6, 7), -}; - -static char *ipm_tx_name[] = { - FOR_EACH_FIXED_ARG(CH_NAME, (,), TX, 0, 1, 2, 3, 4, 5, 6, 7), -}; - -BUILD_ASSERT(ARRAY_SIZE(ipm_rx_name) >= NUM_INSTANCES, "Invalid configuration"); -BUILD_ASSERT(ARRAY_SIZE(ipm_tx_name) >= NUM_INSTANCES, "Invalid configuration"); - -K_THREAD_STACK_ARRAY_DEFINE(ipm_stack, NUM_INSTANCES, WORK_QUEUE_STACK_SIZE); - -struct ipc_ept { - struct rpmsg_mi_ept rpmsg_ep; - struct ipc_service_cb cb; - const char *name; - void *priv; -}; - -struct ipc_rpmsg_mi_instances { - struct ipc_ept endpoints[NUM_ENDPOINTS]; - char name[INSTANCE_NAME_SIZE]; - struct rpmsg_mi_ctx ctx; - bool is_initialized; - int prio; -}; - -static struct ipc_rpmsg_mi_instances instances[NUM_INSTANCES]; - -static struct rpmsg_mi_ctx_shm_cfg shm = { - .addr = SHM_START_ADDR, - .size = SHM_SIZE, -}; - -static void common_bound_cb(void *priv) -{ - struct ipc_ept *ept = (struct ipc_ept *)priv; - - if (ept->cb.bound) { - ept->cb.bound(ept->priv); - } -} - -static void common_recv_cb(const void *data, size_t len, void *priv) -{ - struct ipc_ept *ept = (struct ipc_ept *)priv; - - if (ept->cb.received) { - ept->cb.received(data, len, ept->priv); - } -} - -static struct rpmsg_mi_cb cb = { - .bound = common_bound_cb, - .received = common_recv_cb, -}; - -static int send(struct ipc_ept *ept, const void *data, size_t len) -{ - return rpmsg_mi_send(&ept->rpmsg_ep, data, len); -} - -static int get_available_instance(const struct ipc_ept_cfg *cfg) -{ - /* Endpoints with the same priority are - * registered to the same instance. - */ - for (size_t i = 0; i < NUM_INSTANCES; i++) { - if (instances[i].prio == cfg->prio || instances[i].prio == PRIO_INIT_VAL) { - return (int)i; - } - } - return -ENOMEM; -} - -static int get_available_ept_slot(struct ipc_rpmsg_mi_instances *instance) -{ - for (size_t i = 0; i < NUM_ENDPOINTS; i++) { - if (!(instance->endpoints[i].name)) { - return (int)i; - } - } - return -ENOMEM; -} - -static int register_ept(struct ipc_ept **ept, const struct ipc_ept_cfg *cfg) -{ - struct rpmsg_mi_ept_cfg ept_cfg = { 0 }; - int i_idx, e_idx; - - if (!cfg || !ept) { - return -EINVAL; - } - - i_idx = get_available_instance(cfg); - if (i_idx < 0) { - LOG_ERR("Available instance not found"); - return -EIO; - } - - /* Initialization of the instance context is performed only once. - * When registering the first endpoint for the instance. - */ - if (!instances[i_idx].is_initialized) { - struct rpmsg_mi_ctx_cfg ctx_cfg = { 0 }; - - snprintf(instances[i_idx].name, INSTANCE_NAME_SIZE, "rpmsg_mi_%d", i_idx); - - ctx_cfg.name = instances[i_idx].name; - ctx_cfg.ipm_stack_area = ipm_stack[i_idx]; - ctx_cfg.ipm_stack_size = K_THREAD_STACK_SIZEOF(ipm_stack[i_idx]); - ctx_cfg.ipm_work_q_prio = cfg->prio; - ctx_cfg.ipm_thread_name = instances[i_idx].name; - ctx_cfg.ipm_rx_name = ipm_rx_name[i_idx]; - ctx_cfg.ipm_tx_name = ipm_tx_name[i_idx]; - ctx_cfg.ipm_tx_id = IPM_MSG_ID; - - ctx_cfg.shm = &shm; - - if (rpmsg_mi_ctx_init(&instances[i_idx].ctx, &ctx_cfg) < 0) { - LOG_ERR("Instance initialization failed"); - return -EIO; - } - - instances[i_idx].is_initialized = true; - } - - e_idx = get_available_ept_slot(&instances[i_idx]); - if (e_idx < 0) { - LOG_ERR("No free slots to register endpoint %s", log_strdup(cfg->name)); - return -EIO; - } - - instances[i_idx].endpoints[e_idx].priv = cfg->priv; - instances[i_idx].endpoints[e_idx].cb = cfg->cb; - - ept_cfg.cb = &cb; - ept_cfg.priv = &instances[i_idx].endpoints[e_idx]; - ept_cfg.name = cfg->name; - - if (rpmsg_mi_ept_register(&instances[i_idx].ctx, - &instances[i_idx].endpoints[e_idx].rpmsg_ep, &ept_cfg) < 0) { - LOG_ERR("Register endpoint failed"); - return -EIO; - } - - instances[i_idx].endpoints[e_idx].name = cfg->name; - instances[i_idx].prio = cfg->prio; - - *ept = &instances[i_idx].endpoints[e_idx]; - - return 0; -} - -const static struct ipc_service_backend backend = { - .name = "RPMsg multi-instace backend", - .send = send, - .register_endpoint = register_ept, -}; - -static int backend_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - for (size_t i = 0; i < NUM_INSTANCES; i++) { - instances[i].prio = PRIO_INIT_VAL; - } - - return ipc_service_register_backend(&backend); -} - -SYS_INIT(backend_init, POST_KERNEL, CONFIG_IPC_SERVICE_BACKEND_REG_PRIORITY); diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.c new file mode 100644 index 00000000000..9b20b4b55a5 --- /dev/null +++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2020-2021, Nordic Semiconductor ASA + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ipc_rpmsg_static_vrings_mi.h" + +LOG_MODULE_REGISTER(ipc_rpmsg_multi_instance, CONFIG_IPC_SERVICE_LOG_LEVEL); + +#define WQ_STACK_SIZE CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_WQ_STACK_SIZE + +#define PRIO_INIT_VAL INT_MAX +#define INST_NAME_SIZE 16 +#define IPM_MSG_ID 0 + +#define CH_NAME(idx, sub) (CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_ ## idx ## _IPM_ ## sub ## _NAME) + +static char *ipm_rx_name[] = { + FOR_EACH_FIXED_ARG(CH_NAME, (,), RX, 0, 1, 2, 3, 4, 5, 6, 7), +}; + +static char *ipm_tx_name[] = { + FOR_EACH_FIXED_ARG(CH_NAME, (,), TX, 0, 1, 2, 3, 4, 5, 6, 7), +}; + +BUILD_ASSERT(ARRAY_SIZE(ipm_rx_name) >= NUM_INSTANCES, "Invalid configuration"); +BUILD_ASSERT(ARRAY_SIZE(ipm_tx_name) >= NUM_INSTANCES, "Invalid configuration"); + +K_THREAD_STACK_ARRAY_DEFINE(ipm_stack, NUM_INSTANCES, WQ_STACK_SIZE); + +struct rpmsg_mi_instance { + /* RPMsg */ + struct ipc_rpmsg_instance rpmsg_inst; + + /* Static VRINGs */ + struct ipc_static_vrings vr; + + /* General */ + char name[INST_NAME_SIZE]; + bool is_initialized; + unsigned int id; + + /* IPM */ + const struct device *ipm_tx_handle; + const struct device *ipm_rx_handle; + struct k_work_q ipm_wq; + struct k_work ipm_work; + int priority; + + /* Role */ + unsigned int role; +}; + +struct { + uintptr_t addr; + size_t size; + size_t instance; +} shm = { + .addr = SHM_START_ADDR, + .size = SHM_SIZE, +}; + +static struct rpmsg_mi_instance instance[NUM_INSTANCES]; + +static int send(struct ipc_ept *ept, const void *data, size_t len) +{ + return rpmsg_send(&ept->ep, data, len); +} + +static struct rpmsg_mi_instance *get_available_instance(const struct ipc_ept_cfg *cfg) +{ + /* Endpoints with the same priority are registered to the same instance. */ + for (size_t i = 0; i < NUM_INSTANCES; i++) { + if (instance[i].priority == cfg->prio || instance[i].priority == PRIO_INIT_VAL) { + return &instance[i]; + } + } + return NULL; +} + +static struct ipc_ept *get_available_ept_slot(struct ipc_rpmsg_instance *rpmsg_instance) +{ + for (size_t i = 0; i < NUM_ENDPOINTS; i++) { + if (rpmsg_instance->endpoint[i].name == NULL) { + return &rpmsg_instance->endpoint[i]; + } + } + return NULL; +} + +static void ipm_callback_process(struct k_work *item) +{ + struct rpmsg_mi_instance *instance; + unsigned int id; + + instance = CONTAINER_OF(item, struct rpmsg_mi_instance, ipm_work); + id = (instance->role == VIRTIO_DEV_MASTER) ? + VIRTQUEUE_ID_MASTER : VIRTQUEUE_ID_REMOTE; + + virtqueue_notification(instance->vr.vq[id]); +} + +static void ipm_callback(const struct device *dev, void *context, uint32_t id, volatile void *data) +{ + struct rpmsg_mi_instance *instance = (struct rpmsg_mi_instance *) context; + + k_work_submit_to_queue(&instance->ipm_wq, &instance->ipm_work); +} + +static int ipm_setup(struct rpmsg_mi_instance *instance) +{ + instance->ipm_tx_handle = device_get_binding(ipm_tx_name[instance->id]); + if (instance->ipm_tx_handle == NULL) { + return -ENODEV; + } + + instance->ipm_rx_handle = device_get_binding(ipm_rx_name[instance->id]); + if (instance->ipm_rx_handle == NULL) { + return -ENODEV; + } + + k_work_queue_start(&instance->ipm_wq, ipm_stack[instance->id], + K_THREAD_STACK_SIZEOF(ipm_stack[instance->id]), + instance->priority, NULL); + + k_thread_name_set(&instance->ipm_wq.thread, instance->name); + + k_work_init(&instance->ipm_work, ipm_callback_process); + + ipm_register_callback(instance->ipm_rx_handle, ipm_callback, instance); + + return ipm_set_enabled(instance->ipm_rx_handle, 1); +} + +static void shm_configure(struct rpmsg_mi_instance *instance) +{ + size_t vring_size, shm_size, shm_local_size; + size_t rpmsg_reg_size, vring_reg_size; + uintptr_t shm_addr, shm_local_addr; + + vring_size = VRING_SIZE_GET(shm.size); + shm_addr = SHMEM_INST_ADDR_AUTOALLOC_GET(shm.addr, shm.size, shm.instance); + shm_size = SHMEM_INST_SIZE_AUTOALLOC_GET(shm.size); + + shm_local_addr = shm_addr + VDEV_STATUS_SIZE; + shm_local_size = shm_size - VDEV_STATUS_SIZE; + + rpmsg_reg_size = VRING_COUNT * VIRTQUEUE_SIZE_GET(vring_size); + vring_reg_size = VRING_SIZE_COMPUTE(vring_size, VRING_ALIGNMENT); + + instance->vr.status_reg_addr = shm_addr; + instance->vr.vring_size = vring_size; + instance->vr.rx_addr = shm_local_addr + rpmsg_reg_size; + instance->vr.tx_addr = instance->vr.rx_addr + vring_reg_size; + instance->vr.shm_addr = shm_local_addr; + instance->vr.shm_size = shm_local_size; +} + +static void bound_cb(struct ipc_ept *ept) +{ + /* Notify the remote site that binding has occurred */ + rpmsg_send(&ept->ep, (uint8_t *)"", 0); + + if (ept->cb->bound) { + ept->cb->bound(ept->priv); + } +} + +static int ept_cb(struct rpmsg_endpoint *ep, void *data, size_t len, uint32_t src, void *priv) +{ + struct ipc_ept *ept; + + ept = (struct ipc_ept *) priv; + + if (len == 0) { + if (!ept->bound) { + ept->bound = true; + bound_cb(ept); + } + return RPMSG_SUCCESS; + } + + if (ept->cb->received) { + ept->cb->received(data, len, ept->priv); + } + + return RPMSG_SUCCESS; +} + +static void virtio_notify_cb(struct virtqueue *vq, void *priv) +{ + struct rpmsg_mi_instance *instance; + + instance = (struct rpmsg_mi_instance *) priv; + + if (instance) { + ipm_send(instance->ipm_tx_handle, 0, IPM_MSG_ID, NULL, 0); + } +} + +static int init_instance(struct rpmsg_mi_instance *instance) +{ + int err = 0; + + /* Check if there is enough space in the SHM */ + if (SHMEM_INST_SIZE_AUTOALLOC_GET(shm.size) * NUM_INSTANCES > shm.size) { + return -ENOMEM; + } + + shm_configure(instance); + + instance->vr.notify_cb = virtio_notify_cb; + instance->vr.priv = instance; + + ipc_static_vrings_init(&instance->vr, instance->role); + if (err != 0) { + return err; + } + + err = ipm_setup(instance); + if (err != 0) { + return err; + } + + shm.instance++; + + return 0; +} + +static int register_ept(struct ipc_ept **r_ept, const struct ipc_ept_cfg *cfg) +{ + struct ipc_rpmsg_instance *rpmsg_instance; + struct rpmsg_mi_instance *instance; + struct ipc_ept *ept; + int err; + + if (!cfg || !r_ept) { + return -EINVAL; + } + + instance = get_available_instance(cfg); + if (instance == NULL) { + return -ENODEV; + } + + rpmsg_instance = &instance->rpmsg_inst; + + if (!instance->is_initialized) { + snprintf(instance->name, INST_NAME_SIZE, "rpmsg_mi_%d", instance->id); + + instance->priority = cfg->prio; + + err = init_instance(instance); + if (err) { + return err; + } + + rpmsg_instance->bound_cb = bound_cb; + rpmsg_instance->cb = ept_cb; + + err = ipc_rpmsg_init(rpmsg_instance, + instance->role, + instance->vr.shm_io, + &instance->vr.vdev, + (void *) instance->vr.shm_device.regions->virt, + instance->vr.shm_device.regions->size, NULL); + if (err != 0) { + return err; + } + + instance->is_initialized = true; + } + + ept = get_available_ept_slot(rpmsg_instance); + if (ept == NULL) { + return -ENODEV; + } + + ept->name = cfg->name; + ept->cb = &cfg->cb; + ept->priv = cfg->priv; + ept->bound = false; + ept->ep.priv = ept; + + err = ipc_rpmsg_register_ept(rpmsg_instance, instance->role, ept); + if (err != 0) { + return err; + } + + *r_ept = ept; + + return 0; +} + +const static struct ipc_service_backend backend = { + .name = "RPMSG backend - static VRINGs (multi-instance)", + .send = send, + .register_endpoint = register_ept, +}; + +static int backend_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + for (size_t i = 0; i < NUM_INSTANCES; i++) { + instance[i].priority = PRIO_INIT_VAL; + instance[i].id = i; + instance[i].role = IS_ENABLED(CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_MASTER) ? + VIRTIO_DEV_MASTER : VIRTIO_DEV_SLAVE; + } + + return ipc_service_register_backend(&backend); +} +SYS_INIT(backend_init, POST_KERNEL, CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY); diff --git a/subsys/ipc/rpmsg_multi_instance/rpmsg_multi_instance.h b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.h similarity index 83% rename from subsys/ipc/rpmsg_multi_instance/rpmsg_multi_instance.h rename to subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.h index ac31f7a3729..10db446b1d9 100644 --- a/subsys/ipc/rpmsg_multi_instance/rpmsg_multi_instance.h +++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.h @@ -4,13 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define SHM_DEVICE_NAME "sram0.shm" +#define SHM_START_ADDR CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_SHM_BASE_ADDRESS +#define SHM_SIZE CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_SHM_SIZE + +#define VRING_ALIGNMENT (4) /* Alignment of vring buffer */ +#define VDEV_STATUS_SIZE (0x4) /* Size of status region */ -#define RPMSG_VQ_0 (0) /* TX virtqueue queue index */ -#define RPMSG_VQ_1 (1) /* RX virtqueue queue index */ #define VRING_COUNT (2) /* Number of used vring buffers. */ -#define IPC_INSTANCE_COUNT (CONFIG_RPMSG_MULTI_INSTANCES_NO) /* Number of IPC instances.*/ +#define NUM_INSTANCES (CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_NUM_INSTANCES) /* Private macros. */ #define VRING_DESC_SIZEOF(num) ((num) * (sizeof(struct vring_desc))) @@ -37,7 +39,7 @@ (VRING_ALIGNMENT)))) /* Returns size of used shared memory consumed by all IPC instances*/ -#define SHMEM_CONSUMED_SIZE_GET(vring_size) (IPC_INSTANCE_COUNT * \ +#define SHMEM_CONSUMED_SIZE_GET(vring_size) (NUM_INSTANCES * \ SHMEM_INST_SIZE_GET((vring_size))) /* Returns maximum allowable size of vring buffers to fit memory requirements. */ @@ -60,8 +62,5 @@ ((shmem_addr) + \ ((id) * (SHMEM_INST_SIZE_AUTOALLOC_GET(shmem_size)))) -#ifdef CONFIG_RPMSG_MULTI_INSTANCE_MASTER -#define VIRTQUEUE_ID (0) -#else -#define VIRTQUEUE_ID (1) -#endif +#define VIRTQUEUE_ID_MASTER (0) +#define VIRTQUEUE_ID_REMOTE (1) diff --git a/subsys/ipc/ipc_service/backends/ipc_static_vrings.c b/subsys/ipc/ipc_service/backends/ipc_static_vrings.c new file mode 100644 index 00000000000..a6372f5fd2a --- /dev/null +++ b/subsys/ipc/ipc_service/backends/ipc_static_vrings.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define SHM_DEVICE_NAME "sram0.shm" + +#define VRING_ALIGNMENT (4) /* Alignment of vring buffer */ + +#define RPMSG_VQ_0 (0) /* TX virtqueue queue index */ +#define RPMSG_VQ_1 (1) /* RX virtqueue queue index */ + +static void virtio_notify(struct virtqueue *vq) +{ + struct ipc_static_vrings *vr; + + vr = CONTAINER_OF(vq->vq_dev, struct ipc_static_vrings, vdev); + + if (vr->notify_cb) { + vr->notify_cb(vq, vr->priv); + } +} + +static void virtio_set_features(struct virtio_device *vdev, uint32_t features) +{ + /* No need for implementation */ +} + +static void virtio_set_status(struct virtio_device *p_vdev, unsigned char status) +{ + struct ipc_static_vrings *vr; + + if (p_vdev->role != VIRTIO_DEV_MASTER) { + return; + } + + vr = CONTAINER_OF(p_vdev, struct ipc_static_vrings, vdev); + + sys_write8(status, vr->status_reg_addr); + sys_cache_data_range((void *) vr->status_reg_addr, + sizeof(status), K_CACHE_WB); +} + +static uint32_t virtio_get_features(struct virtio_device *vdev) +{ + return BIT(VIRTIO_RPMSG_F_NS); +} + +static unsigned char virtio_get_status(struct virtio_device *p_vdev) +{ + struct ipc_static_vrings *vr; + uint8_t ret; + + vr = CONTAINER_OF(p_vdev, struct ipc_static_vrings, vdev); + + ret = VIRTIO_CONFIG_STATUS_DRIVER_OK; + + if (p_vdev->role == VIRTIO_DEV_SLAVE) { + sys_cache_data_range((void *) vr->status_reg_addr, + sizeof(ret), K_CACHE_INVD); + ret = sys_read8(vr->status_reg_addr); + } + + return ret; +} + +const static struct virtio_dispatch dispatch = { + .get_status = virtio_get_status, + .get_features = virtio_get_features, + .set_status = virtio_set_status, + .set_features = virtio_set_features, + .notify = virtio_notify, +}; + +static int libmetal_setup(struct ipc_static_vrings *vr) +{ + struct metal_init_params metal_params = METAL_INIT_DEFAULTS; + struct metal_device *device; + int err; + + err = metal_init(&metal_params); + if (err != 0) { + return err; + } + + err = metal_register_generic_device(&vr->shm_device); + if (err != 0) { + return err; + } + + err = metal_device_open("generic", SHM_DEVICE_NAME, &device); + if (err != 0) { + return err; + } + + vr->shm_io = metal_device_io_region(device, 0); + if (vr->shm_io == NULL) { + return err; + } + + return 0; +} + +static int vq_setup(struct ipc_static_vrings *vr, unsigned int role) +{ + vr->vq[RPMSG_VQ_0] = virtqueue_allocate(vr->vring_size); + if (vr->vq[RPMSG_VQ_0] == NULL) { + return -ENOMEM; + } + + vr->vq[RPMSG_VQ_1] = virtqueue_allocate(vr->vring_size); + if (vr->vq[RPMSG_VQ_1] == NULL) { + return -ENOMEM; + } + + vr->rvrings[RPMSG_VQ_0].io = vr->shm_io; + vr->rvrings[RPMSG_VQ_0].info.vaddr = (void *) vr->tx_addr; + vr->rvrings[RPMSG_VQ_0].info.num_descs = vr->vring_size; + vr->rvrings[RPMSG_VQ_0].info.align = VRING_ALIGNMENT; + vr->rvrings[RPMSG_VQ_0].vq = vr->vq[RPMSG_VQ_0]; + + vr->rvrings[RPMSG_VQ_1].io = vr->shm_io; + vr->rvrings[RPMSG_VQ_1].info.vaddr = (void *) vr->rx_addr; + vr->rvrings[RPMSG_VQ_1].info.num_descs = vr->vring_size; + vr->rvrings[RPMSG_VQ_1].info.align = VRING_ALIGNMENT; + vr->rvrings[RPMSG_VQ_1].vq = vr->vq[RPMSG_VQ_1]; + + vr->vdev.role = role; + + vr->vdev.vrings_num = VRING_COUNT; + vr->vdev.func = &dispatch; + vr->vdev.vrings_info = &vr->rvrings[0]; + + return 0; +} + +int ipc_static_vrings_init(struct ipc_static_vrings *vr, unsigned int role) +{ + int err = 0; + + if (!vr) { + return -EINVAL; + } + + vr->shm_device.name = SHM_DEVICE_NAME; + vr->shm_device.num_regions = 1; + vr->shm_physmap[0] = vr->shm_addr; + + metal_io_init(vr->shm_device.regions, (void *) vr->shm_addr, + vr->shm_physmap, vr->shm_size, -1, 0, NULL); + + err = libmetal_setup(vr); + if (err != 0) { + return err; + } + + return vq_setup(vr, role); +} diff --git a/subsys/ipc/rpmsg_multi_instance/CMakeLists.txt b/subsys/ipc/rpmsg_multi_instance/CMakeLists.txt deleted file mode 100644 index 7e6afffd7da..00000000000 --- a/subsys/ipc/rpmsg_multi_instance/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_sources(rpmsg_multi_instance.c) diff --git a/subsys/ipc/rpmsg_multi_instance/Kconfig b/subsys/ipc/rpmsg_multi_instance/Kconfig deleted file mode 100644 index 43617de65bb..00000000000 --- a/subsys/ipc/rpmsg_multi_instance/Kconfig +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor (ASA) -# SPDX-License-Identifier: Apache-2.0 - -# Workaround for not being able to have commas in macro arguments -DT_CHOSEN_Z_IPC_SHM := zephyr,ipc_shm - -menuconfig RPMSG_MULTI_INSTANCE - bool "RPMsg multiple instance" - select IPM - select OPENAMP - help - Enables support for RPMsg multiple instance. - -if RPMSG_MULTI_INSTANCE - -choice RPMSG_ROLE - prompt "RPMSG device role" - default RPMSG_MULTI_INSTANCE_REMOTE - -config RPMSG_MULTI_INSTANCE_REMOTE - bool "Remote" - -config RPMSG_MULTI_INSTANCE_MASTER - bool "Master" -endchoice - -config RPMSG_MULTI_INSTANCES_NO - int "Number of RPMSG instances." - default 2 - range 1 8 - help - How many instances are to be used. - -ipm_name_instance_num = 0 -rsource "Kconfig.ipm_name_instance" -ipm_name_instance_num = 1 -rsource "Kconfig.ipm_name_instance" -ipm_name_instance_num = 2 -rsource "Kconfig.ipm_name_instance" -ipm_name_instance_num = 3 -rsource "Kconfig.ipm_name_instance" -ipm_name_instance_num = 4 -rsource "Kconfig.ipm_name_instance" -ipm_name_instance_num = 5 -rsource "Kconfig.ipm_name_instance" -ipm_name_instance_num = 6 -rsource "Kconfig.ipm_name_instance" -ipm_name_instance_num = 7 -rsource "Kconfig.ipm_name_instance" - -config RPMSG_MULTI_INSTANCE_SHM_BASE_ADDRESS - hex - default "$(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_IPC_SHM))" - help - This option specifies base address of the memory region to - be used for the OpenAMP IPC shared memory. - -config RPMSG_MULTI_INSTANCE_SHM_SIZE - hex - default "$(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_IPC_SHM))" - help - This option specifies size of the memory region to be used - for the OpenAMP IPC shared memory. - -config RPMSG_MULTI_INSTANCE_INIT_PRIORITY - int "Initialization priority of RPMsg muliple instances" - default 46 - help - If in doubt, do not modify this value. - -module = RPMSG_MULTI_INSTANCE -module-str = RPMsg multi instance -source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" - -endif # RPMSG_MULTI_INSTANCE diff --git a/subsys/ipc/rpmsg_multi_instance/rpmsg_multi_instance.c b/subsys/ipc/rpmsg_multi_instance/rpmsg_multi_instance.c deleted file mode 100644 index 4ed22003a67..00000000000 --- a/subsys/ipc/rpmsg_multi_instance/rpmsg_multi_instance.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "rpmsg_multi_instance.h" - -LOG_MODULE_REGISTER(rpmsg_multi_instance, CONFIG_RPMSG_MULTI_INSTANCE_LOG_LEVEL); - -K_MUTEX_DEFINE(shm_mutex); - -static void rpmsg_service_unbind(struct rpmsg_endpoint *p_ep) -{ - rpmsg_destroy_ept(p_ep); -} - -static unsigned char virtio_get_status(struct virtio_device *p_vdev) -{ - struct rpmsg_mi_ctx *ctx = metal_container_of(p_vdev, struct rpmsg_mi_ctx, vdev); - uint8_t ret = VIRTIO_CONFIG_STATUS_DRIVER_OK; - - if (!IS_ENABLED(CONFIG_RPMSG_MULTI_INSTANCE_MASTER)) { - sys_cache_data_range(&ctx->shm_status_reg_addr, - sizeof(ctx->shm_status_reg_addr), K_CACHE_INVD); - ret = sys_read8(ctx->shm_status_reg_addr); - } - - return ret; -} - -static uint32_t virtio_get_features(struct virtio_device *vdev) -{ - return BIT(VIRTIO_RPMSG_F_NS); -} - -#ifdef CONFIG_RPMSG_MULTI_INSTANCE_MASTER - -static void virtio_set_status(struct virtio_device *p_vdev, unsigned char status) -{ - struct rpmsg_mi_ctx *ctx = metal_container_of(p_vdev, struct rpmsg_mi_ctx, vdev); - - sys_write8(status, ctx->shm_status_reg_addr); - sys_cache_data_range(&ctx->shm_status_reg_addr, - sizeof(ctx->shm_status_reg_addr), K_CACHE_WB); -} - -static void virtio_set_features(struct virtio_device *vdev, uint32_t features) -{ - /* No need for implementation */ -} -#endif /* CONFIG_RPMSG_MULTI_INSTANCE_MASTER */ - -static void virtio_notify(struct virtqueue *vq) -{ - struct rpmsg_mi_ctx *ctx = metal_container_of(vq->vq_dev, struct rpmsg_mi_ctx, vdev); - int status; - - if (ctx) { - status = ipm_send(ctx->ipm_tx_handle, 0, ctx->ipm_tx_id, NULL, 0); - if (status != 0) { - LOG_WRN("Failed to notify: %d", status); - } - } -} - -const static struct virtio_dispatch dispatch = { - .get_status = virtio_get_status, - .get_features = virtio_get_features, -#ifdef CONFIG_RPMSG_MULTI_INSTANCE_MASTER - .set_status = virtio_set_status, - .set_features = virtio_set_features, -#endif /* CONFIG_RPMSG_MULTI_INSTANCE_MASTER */ - .notify = virtio_notify, -}; - -static void ipm_callback_process(struct k_work *item) -{ - struct rpmsg_mi_ctx *ctx = CONTAINER_OF(item, struct rpmsg_mi_ctx, ipm_work); - - LOG_DBG("Process callback. Instance name: %s", ctx->name); - virtqueue_notification(ctx->vq[VIRTQUEUE_ID]); -} - -static void ipm_callback(const struct device *dev, void *context, uint32_t id, volatile void *data) -{ - ARG_UNUSED(dev); - struct rpmsg_mi_ctx *ctx = (struct rpmsg_mi_ctx *)context; - - k_work_submit_to_queue(&ctx->ipm_work_q, &ctx->ipm_work); -} - -static void rpmsg_mi_configure_shm(struct rpmsg_mi_ctx *ctx, const struct rpmsg_mi_ctx_cfg *cfg) -{ - size_t vring_size = VRING_SIZE_GET(cfg->shm->size); - uintptr_t shm_addr = SHMEM_INST_ADDR_AUTOALLOC_GET(cfg->shm->addr, - cfg->shm->size, - cfg->shm->instance); - size_t shm_size = SHMEM_INST_SIZE_AUTOALLOC_GET(cfg->shm->size); - - uintptr_t shm_local_start_addr = shm_addr + VDEV_STATUS_SIZE; - size_t shm_local_size = shm_size - VDEV_STATUS_SIZE; - - size_t rpmsg_reg_size = VRING_COUNT * VIRTQUEUE_SIZE_GET(vring_size); - size_t vring_region_size = VRING_SIZE_COMPUTE(vring_size, VRING_ALIGNMENT); - - ctx->shm_status_reg_addr = shm_addr; - ctx->shm_physmap[0] = shm_local_start_addr; - - ctx->shm_device.name = SHM_DEVICE_NAME; - ctx->shm_device.bus = NULL; - ctx->shm_device.num_regions = 1; - - ctx->shm_device.regions->virt = (void *)shm_local_start_addr; - ctx->shm_device.regions->physmap = ctx->shm_physmap; - - ctx->shm_device.regions->size = shm_local_size; - ctx->shm_device.regions->page_shift = 0xffffffff; - ctx->shm_device.regions->page_mask = 0xffffffff; - ctx->shm_device.regions->mem_flags = 0; - - ctx->shm_device.irq_num = 0; - ctx->shm_device.irq_info = NULL; - - ctx->vring_rx_addr = shm_local_start_addr + rpmsg_reg_size; - ctx->vring_tx_addr = ctx->vring_rx_addr + vring_region_size; -} - -static int ept_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) -{ - struct rpmsg_mi_ept *mi_ep = (struct rpmsg_mi_ept *)priv; - - if (len == 0) { - if (!mi_ep->bound) { - LOG_DBG("Handshake done"); - rpmsg_send(ept, (uint8_t *) "", 0); - mi_ep->bound = true; - if (mi_ep->cb->bound) { - mi_ep->cb->bound(mi_ep->priv); - } - } - return 0; - } - - if (mi_ep->cb->received) { - mi_ep->cb->received(data, len, mi_ep->priv); - } - - return 0; -} - -static void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest) -{ - sys_snode_t *node; - struct rpmsg_virtio_device *p_rvdev = metal_container_of(rdev, - struct rpmsg_virtio_device, rdev); - struct rpmsg_mi_ctx *ctx = metal_container_of(p_rvdev, struct rpmsg_mi_ctx, rvdev); - - LOG_DBG("bind_cb endpoint: %s, for instance: %s", name ? log_strdup(name) : "", ctx->name); - - SYS_SLIST_FOR_EACH_NODE(&ctx->endpoints, node) { - struct rpmsg_mi_ept *ept = CONTAINER_OF(node, struct rpmsg_mi_ept, node); - - if (strcmp(name, ept->name) == 0) { - LOG_DBG("Master - Create endpoint: %s", ept->name); - - int err = rpmsg_create_ept(&ept->ep, rdev, name, RPMSG_ADDR_ANY, - dest, ept_cb, rpmsg_service_unbind); - if (err != 0) { - LOG_ERR("Creating remote endpoint %s" - " failed wirh error %d", name, err); - } else { - /* Notify the remote site that binding has occurred */ - rpmsg_send(&ept->ep, (uint8_t *)"", 0); - - ept->bound = true; - ept->cb->bound(ept->priv); - } - - break; - } - } -} - -static bool rpmsg_mi_config_verify(const struct rpmsg_mi_ctx_cfg *cfg) -{ - if (SHMEM_INST_SIZE_AUTOALLOC_GET(cfg->shm->size) * IPC_INSTANCE_COUNT > cfg->shm->size) { - LOG_ERR("Not enough memory"); - return false; - } - - return true; -} - -static int libmetal_setup(struct rpmsg_mi_ctx *ctx) -{ - struct metal_init_params metal_params = METAL_INIT_DEFAULTS; - struct metal_device *device; - int err; - - err = metal_init(&metal_params); - if (err) { - LOG_ERR("metal_init: failed - error code %d", err); - return err; - } - - err = metal_register_generic_device(&ctx->shm_device); - if (err) { - LOG_ERR("Could not register shared memory device: %d", err); - return err; - } - - err = metal_device_open("generic", SHM_DEVICE_NAME, &device); - if (err) { - LOG_ERR("metal_device_open failed: %d", err); - return err; - } - - ctx->shm_io = metal_device_io_region(device, 0); - if (!ctx->shm_io) { - LOG_ERR("metal_device_io_region failed to get region"); - return -ENODEV; - } - - return 0; -} - -static int ipm_setup(struct rpmsg_mi_ctx *ctx, const struct rpmsg_mi_ctx_cfg *cfg) -{ - int err; - - ctx->ipm_tx_handle = device_get_binding(cfg->ipm_tx_name); - if (!ctx->ipm_tx_handle) { - LOG_ERR("Could not get TX IPM device handle"); - return -ENODEV; - } - - ctx->ipm_tx_id = cfg->ipm_tx_id; - - ctx->ipm_rx_handle = device_get_binding(cfg->ipm_rx_name); - if (!ctx->ipm_rx_handle) { - LOG_ERR("Could not get RX IPM device handle"); - return -ENODEV; - } - - k_work_queue_start(&ctx->ipm_work_q, cfg->ipm_stack_area, - cfg->ipm_stack_size, cfg->ipm_work_q_prio, NULL); - k_thread_name_set(&ctx->ipm_work_q.thread, cfg->ipm_thread_name); - - k_work_init(&ctx->ipm_work, ipm_callback_process); - - ipm_register_callback(ctx->ipm_rx_handle, ipm_callback, ctx); - - err = ipm_set_enabled(ctx->ipm_rx_handle, 1); - if (err != 0) { - LOG_ERR("Could not enable IPM interrupts and callbacks for RX"); - return err; - } - - return 0; -} - -static int vq_setup(struct rpmsg_mi_ctx *ctx, size_t vring_size) -{ - ctx->vq[RPMSG_VQ_0] = virtqueue_allocate(vring_size); - if (!ctx->vq[RPMSG_VQ_0]) { - LOG_ERR("virtqueue_allocate failed to alloc vq[RPMSG_VQ_0]"); - return -ENOMEM; - } - - ctx->vq[RPMSG_VQ_1] = virtqueue_allocate(vring_size); - if (!ctx->vq[RPMSG_VQ_1]) { - LOG_ERR("virtqueue_allocate failed to alloc vq[RPMSG_VQ_1]"); - return -ENOMEM; - } - - ctx->rvrings[RPMSG_VQ_0].io = ctx->shm_io; - ctx->rvrings[RPMSG_VQ_0].info.vaddr = (void *)ctx->vring_tx_addr; - ctx->rvrings[RPMSG_VQ_0].info.num_descs = vring_size; - ctx->rvrings[RPMSG_VQ_0].info.align = VRING_ALIGNMENT; - ctx->rvrings[RPMSG_VQ_0].vq = ctx->vq[RPMSG_VQ_0]; - - ctx->rvrings[RPMSG_VQ_1].io = ctx->shm_io; - ctx->rvrings[RPMSG_VQ_1].info.vaddr = (void *)ctx->vring_rx_addr; - ctx->rvrings[RPMSG_VQ_1].info.num_descs = vring_size; - ctx->rvrings[RPMSG_VQ_1].info.align = VRING_ALIGNMENT; - ctx->rvrings[RPMSG_VQ_1].vq = ctx->vq[RPMSG_VQ_1]; - - ctx->vdev.role = IS_ENABLED(CONFIG_RPMSG_MULTI_INSTANCE_MASTER) ? - RPMSG_MASTER : RPMSG_REMOTE; - - ctx->vdev.vrings_num = VRING_COUNT; - ctx->vdev.func = &dispatch; - ctx->vdev.vrings_info = &ctx->rvrings[0]; - - return 0; -} - -int rpmsg_mi_ctx_init(struct rpmsg_mi_ctx *ctx, const struct rpmsg_mi_ctx_cfg *cfg) -{ - int err = 0; - - if (!ctx || !cfg) { - return -EINVAL; - } - - LOG_DBG("RPMsg multiple instance initialization"); - - if (!rpmsg_mi_config_verify(cfg)) { - return -EIO; - } - - k_mutex_lock(&shm_mutex, K_FOREVER); - - /* Configure shared memory */ - rpmsg_mi_configure_shm(ctx, cfg); - - /* Setup libmetal */ - err = libmetal_setup(ctx); - if (err) { - LOG_ERR("Failed to setup libmetal"); - goto out; - } - - /* Setup IPM */ - err = ipm_setup(ctx, cfg); - if (err) { - LOG_ERR("Failed to setup IPM"); - goto out; - } - - /* Setup VQs / VRINGs */ - err = vq_setup(ctx, VRING_SIZE_GET(cfg->shm->size)); - if (err) { - LOG_ERR("Failed to setup VQs / VRINGs"); - goto out; - } - - ctx->name = cfg->name; - sys_slist_init(&ctx->endpoints); - - if (IS_ENABLED(CONFIG_RPMSG_MULTI_INSTANCE_MASTER)) { - /* This step is only required if you are VirtIO device master. - * Initialize the shared buffers pool. - */ - rpmsg_virtio_init_shm_pool(&ctx->shpool, (void *) ctx->shm_device.regions->virt, - ctx->shm_device.regions->size); - - err = rpmsg_init_vdev(&ctx->rvdev, &ctx->vdev, ns_bind_cb, - ctx->shm_io, &ctx->shpool); - } else { - err = rpmsg_init_vdev(&ctx->rvdev, &ctx->vdev, NULL, ctx->shm_io, NULL); - } - - if (err) { - LOG_ERR("RPMSG vdev initialization failed %d", err); - goto out; - } - - /* Get RPMsg device from RPMsg VirtIO device. */ - ctx->rdev = rpmsg_virtio_get_rpmsg_device(&ctx->rvdev); - - cfg->shm->instance++; - - LOG_DBG("RPMsg multiple instance initialization done"); - -out: - k_mutex_unlock(&shm_mutex); - - return err; -} - -int rpmsg_mi_ept_register(struct rpmsg_mi_ctx *ctx, struct rpmsg_mi_ept *ept, - struct rpmsg_mi_ept_cfg *cfg) -{ - if (!ctx || !ept || !cfg) { - return -EINVAL; - } - - ept->cb = cfg->cb; - ept->priv = cfg->priv; - ept->ep.priv = ept; - ept->bound = false; - ept->name = cfg->name; - - sys_slist_append(&ctx->endpoints, &ept->node); - - if (!IS_ENABLED(CONFIG_RPMSG_MULTI_INSTANCE_MASTER)) { - LOG_DBG("Remote - Create endpoint: %s", ept->name); - - int err = rpmsg_create_ept(&ept->ep, ctx->rdev, ept->name, RPMSG_ADDR_ANY, - RPMSG_ADDR_ANY, ept_cb, rpmsg_service_unbind); - - if (err != 0) { - LOG_ERR("RPMSG endpoint create failed %d", err); - return err; - } - } - - return 0; -} - -int rpmsg_mi_send(struct rpmsg_mi_ept *ept, const void *data, size_t len) -{ - return rpmsg_send(&ept->ep, data, len); -}