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:
Carlo Caione 2022-01-13 10:47:02 +01:00 committed by Anas Nashif
parent 499c4fb1e3
commit 93b0ea9782
18 changed files with 0 additions and 1188 deletions

View file

@ -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
)

View file

@ -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.

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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)

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}

View file

@ -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)

View file

@ -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"

View file

@ -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.

View file

@ -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

View file

@ -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);

View file

@ -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)