ipc: Remove multi-instance backend
Remove the legacy multi-instance backend and the sample. Signed-off-by: Carlo Caione <ccaione@baylibre.com>
This commit is contained in:
parent
499c4fb1e3
commit
93b0ea9782
|
@ -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}/ipc_service_remote-prefix/src/ipc_service_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(STATUS "${BOARD} compile as Master in this sample")
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(ipc_service)
|
||||
|
||||
enable_language(C ASM)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
ExternalProject_Add(
|
||||
ipc_service_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
|
||||
)
|
|
@ -1,132 +0,0 @@
|
|||
.. _IPC_Service_sample:
|
||||
|
||||
IPC Service
|
||||
###########
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
IPC Service is an abstraction layer.
|
||||
It needs the corresponding backend registered for proper operation.
|
||||
You can use any IPC mechanism as a backend.
|
||||
In this sample, it is a multiple instance of RPMsg.
|
||||
This sample demonstrates how to integrate IPC Service with Zephyr.
|
||||
|
||||
Building the application for nrf5340dk_nrf5340_cpuapp
|
||||
*****************************************************
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/subsys/ipc/ipc_service/static_vrings_mi
|
||||
: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 v2.6.0-rc3-5-g026dfb6f1b71 ***
|
||||
|
||||
IPC Service [master 1] demo started
|
||||
|
||||
IPC Service [master 2] demo started
|
||||
Master [1] received a message: 1
|
||||
Master [2] received a message: 1
|
||||
Master [1] received a message: 3
|
||||
Master [2] received a message: 3
|
||||
|
||||
...
|
||||
Master [1] received a message: 99
|
||||
IPC Service [master 1] demo ended.
|
||||
Master [2] received a message: 99
|
||||
IPC Service [master 2] demo ended.
|
||||
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
*** Booting Zephyr OS build v2.6.0-rc3-5-g026dfb6f1b71 ***
|
||||
|
||||
IPC Service [remote 1] demo started
|
||||
|
||||
IPC Service [remote 2] demo started
|
||||
Remote [1] received a message: 0
|
||||
Remote [2] received a message: 0
|
||||
Remote [1] received a message: 2
|
||||
Remote [2] received a message: 2
|
||||
Remote [1] received a message: 4
|
||||
Remote [2] received a message: 4
|
||||
...
|
||||
Remote [1] received a message: 98
|
||||
IPC Service [remote 1] demo ended.
|
||||
Remote [2] received a message: 98
|
||||
IPC Service [remote 2] demo ended.
|
||||
|
||||
Building the application for bl5340_dvk_cpuapp
|
||||
**********************************************
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/subsys/ipc/ipc_service/static_vrings_mi
|
||||
:board: bl5340_dvk_cpuapp
|
||||
:goals: debug
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/subsys/ipc/ipc_service/static_vrings_mi/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 ***
|
||||
|
||||
IPC Service [master 1] demo started
|
||||
|
||||
IPC Service [master 2] demo started
|
||||
Master [1] received a message: 1
|
||||
Master [2] received a message: 1
|
||||
Master [1] received a message: 3
|
||||
Master [2] received a message: 3
|
||||
|
||||
...
|
||||
Master [1] received a message: 99
|
||||
IPC Service [master 1] demo ended.
|
||||
Master [2] received a message: 99
|
||||
IPC Service [master 2] demo ended.
|
||||
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
*** Booting Zephyr OS build v2.7.0-rc1-103-ge19875c88916 ***
|
||||
|
||||
IPC Service [remote 1] demo started
|
||||
|
||||
IPC Service [remote 2] demo started
|
||||
Remote [1] received a message: 0
|
||||
Remote [2] received a message: 0
|
||||
Remote [1] received a message: 2
|
||||
Remote [2] received a message: 2
|
||||
Remote [1] received a message: 4
|
||||
Remote [2] received a message: 4
|
||||
...
|
||||
Remote [1] received a message: 98
|
||||
IPC Service [remote 1] demo ended.
|
||||
Remote [2] received a message: 98
|
||||
IPC Service [remote 2] demo ended.
|
|
@ -1,24 +0,0 @@
|
|||
CONFIG_BOARD_ENABLE_CPUNET=y
|
||||
|
||||
# Backend configuration for IPC Service
|
||||
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_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"
|
|
@ -1,24 +0,0 @@
|
|||
CONFIG_BOARD_ENABLE_CPUNET=y
|
||||
|
||||
# Backend configuration for IPC Service
|
||||
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_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"
|
|
@ -1,19 +0,0 @@
|
|||
CONFIG_PRINTK=y
|
||||
CONFIG_IPM=y
|
||||
CONFIG_TIMESLICE_SIZE=1
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=4096
|
||||
|
||||
# Configuration IPC Service
|
||||
CONFIG_IPC_SERVICE=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_IPC_SERVICE_BACKEND_RPMSG_MI_NUM_INSTANCES=2
|
||||
|
||||
CONFIG_LOG=y
|
||||
CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y
|
|
@ -1,18 +0,0 @@
|
|||
# Copyright (c) 2018-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(STATUS "${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(ipc_service_remote)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
|
@ -1,22 +0,0 @@
|
|||
# Backend configuration for IPC Service
|
||||
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_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"
|
|
@ -1,22 +0,0 @@
|
|||
# Backend configuration for IPC Service
|
||||
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_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"
|
|
@ -1,19 +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
|
||||
|
||||
# Configuration IPC Service
|
||||
CONFIG_IPC_SERVICE=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_IPC_SERVICE_BACKEND_RPMSG_MI_NUM_INSTANCES=2
|
||||
|
||||
CONFIG_LOG=y
|
||||
CONFIG_IPC_SERVICE_LOG_LEVEL_INF=y
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <drivers/ipm.h>
|
||||
#include <sys/printk.h>
|
||||
#include <device.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ipc/ipc_service.h>
|
||||
|
||||
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
|
||||
|
||||
#define APP_TASK_STACK_SIZE 1024
|
||||
|
||||
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 volatile uint8_t received_data_1;
|
||||
static volatile uint8_t received_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 struct ipc_ept ept_1;
|
||||
static struct ipc_ept ept_2;
|
||||
|
||||
static void ept_bound_1(void *priv)
|
||||
{
|
||||
k_sem_give(&bound_ept1_sem);
|
||||
}
|
||||
|
||||
static void ept_recv_1(const void *data, size_t len, void *priv)
|
||||
{
|
||||
received_data_1 = *((uint8_t *) data);
|
||||
k_sem_give(&data_rx1_sem);
|
||||
}
|
||||
|
||||
static void ept_error_1(const char *message, void *priv)
|
||||
{
|
||||
printk("Endpoint [1] error: %s", message);
|
||||
}
|
||||
|
||||
static void ept_bound_2(void *priv)
|
||||
{
|
||||
k_sem_give(&bound_ept2_sem);
|
||||
}
|
||||
|
||||
static void ept_recv_2(const void *data, size_t len, void *priv)
|
||||
{
|
||||
received_data_2 = *((uint8_t *) data);
|
||||
k_sem_give(&data_rx2_sem);
|
||||
}
|
||||
|
||||
static void ept_error_2(const char *message, void *priv)
|
||||
{
|
||||
printk("Endpoint [2] error: %s", message);
|
||||
}
|
||||
|
||||
void app_task_1(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
ARG_UNUSED(arg1);
|
||||
ARG_UNUSED(arg2);
|
||||
ARG_UNUSED(arg3);
|
||||
|
||||
const struct device *ipc_instance;
|
||||
int status = 0;
|
||||
uint8_t message = 0U;
|
||||
|
||||
printk("\r\nIPC Service [remote 1] demo started\r\n");
|
||||
|
||||
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
|
||||
|
||||
static struct ipc_ept_cfg ept_cfg = {
|
||||
.name = "ep_1",
|
||||
.prio = 0,
|
||||
.priv = NULL,
|
||||
.cb = {
|
||||
.bound = ept_bound_1,
|
||||
.received = ept_recv_1,
|
||||
.error = ept_error_1,
|
||||
},
|
||||
};
|
||||
|
||||
status = ipc_service_register_endpoint(ipc_instance, &ept_1, &ept_cfg);
|
||||
if (status < 0) {
|
||||
printk("ipc_service_register_endpoint failed %d\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
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 [1] received a message: %d\n", message);
|
||||
|
||||
message++;
|
||||
status = ipc_service_send(&ept_1, &message, sizeof(message));
|
||||
if (status < 0) {
|
||||
printk("send_message(%d) failed with status %d\n",
|
||||
message, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printk("IPC Service [remote 1] demo ended.\n");
|
||||
}
|
||||
|
||||
void app_task_2(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
ARG_UNUSED(arg1);
|
||||
ARG_UNUSED(arg2);
|
||||
ARG_UNUSED(arg3);
|
||||
|
||||
const struct device *ipc_instance;
|
||||
int status = 0;
|
||||
uint8_t message = 0U;
|
||||
|
||||
printk("\r\nIPC Service [remote 2] demo started\r\n");
|
||||
|
||||
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
|
||||
|
||||
static struct ipc_ept_cfg ept_cfg = {
|
||||
.name = "ep_2",
|
||||
.prio = 0,
|
||||
.priv = NULL,
|
||||
.cb = {
|
||||
.bound = ept_bound_2,
|
||||
.received = ept_recv_2,
|
||||
.error = ept_error_2,
|
||||
},
|
||||
};
|
||||
|
||||
status = ipc_service_register_endpoint(ipc_instance, &ept_2, &ept_cfg);
|
||||
|
||||
if (status < 0) {
|
||||
printk("ipc_service_register_endpoint failed %d\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
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 [2] received a message: %d\n", message);
|
||||
|
||||
message++;
|
||||
status = ipc_service_send(&ept_2, &message, sizeof(message));
|
||||
if (status < 0) {
|
||||
printk("send_message(%d) failed with status %d\n",
|
||||
message, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printk("IPC Service [remote 2] demo ended.\n");
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
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(7), 0, K_NO_WAIT);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
sample:
|
||||
description: This app provides an example of how to integrate
|
||||
IPC Service with Zephyr (static_vrings_mi backend)
|
||||
name: IPC Service example integration (static_vrings_mi backend)
|
||||
tests:
|
||||
sample.ipc.static_vrings_mi.nrf:
|
||||
platform_allow: nrf5340dk_nrf5340_cpuapp bl5340_dvk_cpuapp
|
||||
integration_platforms:
|
||||
- nrf5340dk_nrf5340_cpuapp
|
||||
- bl5340_dvk_cpuapp
|
||||
tags: ipc
|
||||
build_only: true
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <drivers/ipm.h>
|
||||
#include <sys/printk.h>
|
||||
#include <device.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <init.h>
|
||||
|
||||
#include <ipc/ipc_service.h>
|
||||
|
||||
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
|
||||
|
||||
#define APP_TASK_STACK_SIZE 1024
|
||||
|
||||
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 volatile uint8_t received_data_1;
|
||||
static volatile uint8_t received_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 struct ipc_ept ept_1;
|
||||
static struct ipc_ept ept_2;
|
||||
|
||||
static void ept_bound_1(void *priv)
|
||||
{
|
||||
k_sem_give(&bound_ept1_sem);
|
||||
}
|
||||
|
||||
static void ept_recv_1(const void *data, size_t len, void *priv)
|
||||
{
|
||||
received_data_1 = *((uint8_t *) data);
|
||||
k_sem_give(&data_rx1_sem);
|
||||
}
|
||||
|
||||
static void ept_error_1(const char *message, void *priv)
|
||||
{
|
||||
printk("Endpoint [1] error: %s", message);
|
||||
}
|
||||
|
||||
static void ept_bound_2(void *priv)
|
||||
{
|
||||
k_sem_give(&bound_ept2_sem);
|
||||
}
|
||||
|
||||
static void ept_recv_2(const void *data, size_t len, void *priv)
|
||||
{
|
||||
received_data_2 = *((uint8_t *) data);
|
||||
k_sem_give(&data_rx2_sem);
|
||||
}
|
||||
|
||||
static void ept_error_2(const char *message, void *priv)
|
||||
{
|
||||
printk("Endpoint [2] error: %s", message);
|
||||
}
|
||||
|
||||
void app_task_1(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
ARG_UNUSED(arg1);
|
||||
ARG_UNUSED(arg2);
|
||||
ARG_UNUSED(arg3);
|
||||
|
||||
const struct device *ipc_instance;
|
||||
int status = 0;
|
||||
uint8_t message = 0U;
|
||||
|
||||
printk("\r\nIPC Service [master 1] demo started\r\n");
|
||||
|
||||
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
|
||||
|
||||
static struct ipc_ept_cfg ept_cfg = {
|
||||
.name = "ep_1",
|
||||
.prio = 0,
|
||||
.priv = NULL,
|
||||
.cb = {
|
||||
.bound = ept_bound_1,
|
||||
.received = ept_recv_1,
|
||||
.error = ept_error_1,
|
||||
},
|
||||
};
|
||||
|
||||
status = ipc_service_register_endpoint(ipc_instance, &ept_1, &ept_cfg);
|
||||
if (status < 0) {
|
||||
printk("ipc_service_register_endpoint failed %d\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
k_sem_take(&bound_ept1_sem, K_FOREVER);
|
||||
|
||||
while (message < 100) {
|
||||
status = ipc_service_send(&ept_1, &message, sizeof(message));
|
||||
if (status < 0) {
|
||||
printk("send_message(%d) failed with status %d\n",
|
||||
message, status);
|
||||
break;
|
||||
}
|
||||
|
||||
k_sem_take(&data_rx1_sem, K_FOREVER);
|
||||
message = received_data_1;
|
||||
|
||||
printk("Master [1] received a message: %d\n", message);
|
||||
message++;
|
||||
}
|
||||
|
||||
printk("IPC Service [master 1] demo ended.\n");
|
||||
}
|
||||
|
||||
void app_task_2(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
ARG_UNUSED(arg1);
|
||||
ARG_UNUSED(arg2);
|
||||
ARG_UNUSED(arg3);
|
||||
|
||||
const struct device *ipc_instance;
|
||||
int status = 0;
|
||||
uint8_t message = 0U;
|
||||
|
||||
printk("\r\nIPC Service [master 2] demo started\r\n");
|
||||
|
||||
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
|
||||
|
||||
static struct ipc_ept_cfg ept_cfg = {
|
||||
.name = "ep_2",
|
||||
.prio = 0,
|
||||
.priv = NULL,
|
||||
.cb = {
|
||||
.bound = ept_bound_2,
|
||||
.received = ept_recv_2,
|
||||
.error = ept_error_2,
|
||||
},
|
||||
};
|
||||
|
||||
status = ipc_service_register_endpoint(ipc_instance, &ept_2, &ept_cfg);
|
||||
|
||||
if (status < 0) {
|
||||
printk("ipc_service_register_endpoint failed %d\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
k_sem_take(&bound_ept2_sem, K_FOREVER);
|
||||
|
||||
while (message < 100) {
|
||||
status = ipc_service_send(&ept_2, &message, sizeof(message));
|
||||
if (status < 0) {
|
||||
printk("send_message(%d) failed with status %d\n",
|
||||
message, status);
|
||||
break;
|
||||
}
|
||||
|
||||
k_sem_take(&data_rx2_sem, K_FOREVER);
|
||||
message = received_data_2;
|
||||
|
||||
printk("Master [2] received a message: %d\n", message);
|
||||
message++;
|
||||
}
|
||||
|
||||
printk("IPC Service [master 2] demo ended.\n");
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
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(7), 0, K_NO_WAIT);
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI ipc_rpmsg_static_vrings_mi.c)
|
||||
zephyr_sources_ifdef(CONFIG_IPC_SERVICE_BACKEND_RPMSG ipc_rpmsg_static_vrings.c)
|
||||
|
|
|
@ -4,13 +4,6 @@
|
|||
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
|
||||
|
||||
config IPC_SERVICE_BACKEND_RPMSG
|
||||
bool "OpenAMP RPMSG backend with static VRINGs"
|
||||
depends on MBOX
|
||||
|
@ -53,5 +46,4 @@ config IPC_SERVICE_STATIC_VRINGS_ALIGNMENT
|
|||
help
|
||||
Static VRINGs alignment
|
||||
|
||||
rsource "Kconfig.rpmsg_mi"
|
||||
rsource "Kconfig.rpmsg"
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
# Copyright (c) 2021 Nordic Semiconductor (ASA)
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
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 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
|
||||
RX communication.
|
|
@ -1,64 +0,0 @@
|
|||
# Copyright (c) 2020-2021 Nordic Semiconductor (ASA)
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if IPC_SERVICE_BACKEND_RPMSG_MI
|
||||
|
||||
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 / 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_SERVICE_BACKEND_RPMSG_MI_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 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"
|
||||
|
||||
endif # IP_SERVICE_BACKEND_RPMSG_MI
|
|
@ -1,340 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021, Nordic Semiconductor ASA
|
||||
* Copyright (c) 2021 Carlo Caione <ccaione@baylibre.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <ipc/ipc_service_backend.h>
|
||||
#include <ipc/ipc_rpmsg.h>
|
||||
#include <ipc/ipc_static_vrings.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
#include <zephyr.h>
|
||||
#include <cache.h>
|
||||
#include <device.h>
|
||||
#include <drivers/ipm.h>
|
||||
|
||||
#include "ipc_rpmsg_static_vrings_mi.h"
|
||||
|
||||
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
|
||||
|
||||
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(const struct device *instance, void *token,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
struct ipc_rpmsg_ept *rpmsg_ept;
|
||||
|
||||
rpmsg_ept = (struct ipc_rpmsg_ept *) token;
|
||||
|
||||
return rpmsg_send(&rpmsg_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_rpmsg_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[0] == '\0') {
|
||||
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_rpmsg_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_rpmsg_ept *ept;
|
||||
|
||||
ept = (struct ipc_rpmsg_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(const struct device *dev,
|
||||
void **token,
|
||||
const struct ipc_ept_cfg *cfg)
|
||||
{
|
||||
struct ipc_rpmsg_instance *rpmsg_instance;
|
||||
struct rpmsg_mi_instance *instance;
|
||||
struct ipc_rpmsg_ept *rpmsg_ept;
|
||||
int err;
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (!cfg || !token) {
|
||||
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;
|
||||
}
|
||||
|
||||
rpmsg_ept = get_available_ept_slot(rpmsg_instance);
|
||||
if (rpmsg_ept == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
strncpy(rpmsg_ept->name, cfg->name ? cfg->name : "", sizeof(rpmsg_ept->name));
|
||||
|
||||
rpmsg_ept->cb = &cfg->cb;
|
||||
rpmsg_ept->priv = cfg->priv;
|
||||
rpmsg_ept->bound = false;
|
||||
rpmsg_ept->ep.priv = rpmsg_ept;
|
||||
|
||||
err = ipc_rpmsg_register_ept(rpmsg_instance, instance->role, rpmsg_ept);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
(*token) = rpmsg_ept;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const static struct ipc_service_backend backend_ops = {
|
||||
.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 0;
|
||||
}
|
||||
|
||||
DEVICE_DEFINE(mi_backend, MI_BACKEND_DRIVER_NAME, &backend_init, NULL, NULL,
|
||||
NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&backend_ops);
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#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 CONFIG_IPC_SERVICE_STATIC_VRINGS_ALIGNMENT
|
||||
#define VDEV_STATUS_SIZE (0x4) /* Size of status region */
|
||||
|
||||
#define VRING_COUNT (2) /* Number of used vring buffers. */
|
||||
|
||||
#define NUM_INSTANCES (CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_NUM_INSTANCES)
|
||||
|
||||
/* Private macros. */
|
||||
#define VRING_DESC_SIZEOF(num) ((num) * (sizeof(struct vring_desc)))
|
||||
#define VRING_AVAIL_SIZEOF(num) (sizeof(struct vring_avail) + \
|
||||
((num) * sizeof(uint16_t)) + sizeof(uint16_t))
|
||||
#define VRING_USED_SIZEOF(num) (sizeof(struct vring_used) + \
|
||||
((num) * sizeof(struct vring_used_elem)) + \
|
||||
sizeof(uint16_t))
|
||||
|
||||
#define VRING_FIRST_SUM(num) (VRING_DESC_SIZEOF(num) + VRING_AVAIL_SIZEOF(num))
|
||||
|
||||
|
||||
/* Compute size of vring buffer based on its size and alignment. */
|
||||
#define VRING_SIZE_COMPUTE(vring_size, align) (ROUND_UP(VRING_FIRST_SUM((vring_size)), \
|
||||
(align)) + VRING_USED_SIZEOF((vring_size)))
|
||||
|
||||
/* Macro for calculating used memory by virtqueue buffers for remote device. */
|
||||
#define VIRTQUEUE_SIZE_GET(vring_size) (RPMSG_BUFFER_SIZE * (vring_size))
|
||||
|
||||
/* Macro for getting the size of shared memory occupied by single IPC instance. */
|
||||
#define SHMEM_INST_SIZE_GET(vring_size) (VDEV_STATUS_SIZE + \
|
||||
(VRING_COUNT * VIRTQUEUE_SIZE_GET((vring_size))) + \
|
||||
(VRING_COUNT * VRING_SIZE_COMPUTE((vring_size), \
|
||||
(VRING_ALIGNMENT))))
|
||||
|
||||
/* Returns size of used shared memory consumed by all IPC instances*/
|
||||
#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. */
|
||||
#define VRING_SIZE_GET(shmem_size) ((SHMEM_CONSUMED_SIZE_GET(32)) < (shmem_size) ? 32 : \
|
||||
(SHMEM_CONSUMED_SIZE_GET(16)) < (shmem_size) ? 16 : \
|
||||
(SHMEM_CONSUMED_SIZE_GET(8)) < (shmem_size) ? 8 : \
|
||||
(SHMEM_CONSUMED_SIZE_GET(4)) < (shmem_size) ? 4 : \
|
||||
(SHMEM_CONSUMED_SIZE_GET(2)) < (shmem_size) ? 2 : 1)
|
||||
|
||||
/* Returns size of used shared memory of single instance in case of using
|
||||
* maximum allowable vring buffer size.
|
||||
*/
|
||||
#define SHMEM_INST_SIZE_AUTOALLOC_GET(shmem_size) \
|
||||
(SHMEM_INST_SIZE_GET(VRING_SIZE_GET((shmem_size))))
|
||||
|
||||
/* Returns start address of ipc instance in shared memory. It assumes that
|
||||
* maximum allowable vring buffer size is used.
|
||||
*/
|
||||
#define SHMEM_INST_ADDR_AUTOALLOC_GET(shmem_addr, shmem_size, id) \
|
||||
((shmem_addr) + \
|
||||
((id) * (SHMEM_INST_SIZE_AUTOALLOC_GET(shmem_size))))
|
||||
|
||||
#define VIRTQUEUE_ID_MASTER (0)
|
||||
#define VIRTQUEUE_ID_REMOTE (1)
|
Loading…
Reference in a new issue