From e0f42a4e8084bbe5b61347919dbf287fef52af4c Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 26 Apr 2020 16:06:08 +0800 Subject: [PATCH] apps: add msg-test-rpmsg-nocopy-ping test to demo the usage of zero copy API Signed-off-by: Xiang Xiao --- apps/tests/msg/CMakeLists.txt | 4 +- apps/tests/msg/rpmsg-nocopy-ping.c | 199 +++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 apps/tests/msg/rpmsg-nocopy-ping.c diff --git a/apps/tests/msg/CMakeLists.txt b/apps/tests/msg/CMakeLists.txt index 982b6dbdb..7242ae6e7 100644 --- a/apps/tests/msg/CMakeLists.txt +++ b/apps/tests/msg/CMakeLists.txt @@ -15,7 +15,7 @@ collector_list (_deps PROJECT_LIB_DEPS) set (OPENAMP_LIB open_amp) -foreach (_app msg-test-rpmsg-ping msg-test-rpmsg-update msg-test-rpmsg-flood-ping) +foreach (_app msg-test-rpmsg-ping msg-test-rpmsg-update msg-test-rpmsg-flood-ping msg-test-rpmsg-nocopy-ping) collector_list (_sources APP_COMMON_SOURCES) if (${_app} STREQUAL "msg-test-rpmsg-ping") list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-ping.c") @@ -23,6 +23,8 @@ foreach (_app msg-test-rpmsg-ping msg-test-rpmsg-update msg-test-rpmsg-flood-pin list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-update.c") elseif (${_app} STREQUAL "msg-test-rpmsg-flood-ping") list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-flood-ping.c") + elseif (${_app} STREQUAL "msg-test-rpmsg-nocopy-ping") + list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-nocopy-ping.c") endif (${_app} STREQUAL "msg-test-rpmsg-ping") if (WITH_SHARED_LIB) diff --git a/apps/tests/msg/rpmsg-nocopy-ping.c b/apps/tests/msg/rpmsg-nocopy-ping.c new file mode 100644 index 000000000..c65e167b2 --- /dev/null +++ b/apps/tests/msg/rpmsg-nocopy-ping.c @@ -0,0 +1,199 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2020, Xiaomi Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include "platform_info.h" +#include "rpmsg-ping.h" + +#define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) +#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) + +struct _payload { + unsigned long num; + unsigned long size; + unsigned char data[]; +}; + +static int err_cnt; + +#define PAYLOAD_MIN_SIZE 1 + +/* Globals */ +static struct rpmsg_endpoint lept; +static int rnum; +static int err_cnt; +static int ept_deleted; + +/* External functions */ +extern int init_system(void); +extern void cleanup_system(void); + +static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, + uint32_t src, void *priv) +{ + int i; + struct _payload *r_payload = (struct _payload *)data; + + (void)ept; + (void)src; + (void)priv; + LPRINTF(" received payload number %lu of size %lu \r\n", + r_payload->num, (unsigned long)len); + + if (r_payload->size == 0) { + LPERROR(" Invalid size of package is received.\r\n"); + err_cnt++; + return RPMSG_SUCCESS; + } + /* Validate data buffer integrity. */ + for (i = 0; i < (int)r_payload->size; i++) { + if (r_payload->data[i] != 0xA5) { + LPRINTF("Data corruption at index %d\r\n", i); + err_cnt++; + break; + } + } + rnum = r_payload->num + 1; + return RPMSG_SUCCESS; +} + +static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) +{ + (void)ept; + rpmsg_destroy_ept(&lept); + LPRINTF("echo test: service is destroyed\r\n"); + ept_deleted = 1; +} + +static void rpmsg_name_service_bind_cb(struct rpmsg_device *rdev, + const char *name, uint32_t dest) +{ + LPRINTF("new endpoint notification is received.\r\n"); + if (strcmp(name, RPMSG_SERVICE_NAME)) + LPERROR("Unexpected name service %s.\r\n", name); + else + (void)rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, + RPMSG_ADDR_ANY, dest, + rpmsg_endpoint_cb, + rpmsg_service_unbind); + +} + +static int app(struct rpmsg_device *rdev, void *priv) +{ + int ret; + int i, num_payloads; + uint32_t size, max_size; + int expect_rnum = 0; + + LPRINTF(" 1 - Send data to remote core, retrieve the echo"); + LPRINTF(" and validate its integrity ..\r\n"); + + max_size = rpmsg_virtio_get_buffer_size(rdev); + if ((int32_t)max_size < 0) { + LPERROR("No available buffer size.\r\n"); + return -1; + } + max_size -= sizeof(struct _payload); + num_payloads = max_size - PAYLOAD_MIN_SIZE + 1; + + /* Create RPMsg endpoint */ + ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + rpmsg_endpoint_cb, rpmsg_service_unbind); + + if (ret) { + LPERROR("Failed to create RPMsg endpoint.\r\n"); + return ret; + } + + while (!is_rpmsg_ept_ready(&lept)) + platform_poll(priv); + + LPRINTF("RPMSG endpoint is binded with remote.\r\n"); + for (i = 0, size = PAYLOAD_MIN_SIZE; i < num_payloads; i++, size++) { + struct _payload *i_payload; + + i_payload = rpmsg_get_tx_payload_buffer(&lept, &max_size, 1); + if (!i_payload) { + LPERROR("Failed to get payload...\r\n"); + break; + } + + i_payload->num = i; + i_payload->size = size; + + /* Mark the data buffer. */ + memset(&(i_payload->data[0]), 0xA5, size); + + LPRINTF("sending payload number %lu of size %lu\r\n", + i_payload->num, + (unsigned long)(2 * sizeof(unsigned long)) + size); + + ret = rpmsg_send_nocopy(&lept, i_payload, + (2 * sizeof(unsigned long)) + size); + + if (ret < 0) { + LPERROR("Failed to send data...\r\n"); + break; + } + LPRINTF("echo test: sent : %lu\r\n", + (unsigned long)(2 * sizeof(unsigned long)) + size); + + expect_rnum++; + do { + platform_poll(priv); + } while ((rnum < expect_rnum) && !err_cnt && !ept_deleted); + + } + + LPRINTF("**********************************\r\n"); + LPRINTF(" Test Results: Error count = %d \r\n", err_cnt); + LPRINTF("**********************************\r\n"); + /* Destroy the RPMsg endpoint */ + rpmsg_destroy_ept(&lept); + LPRINTF("Quitting application .. Echo test end\r\n"); + + return 0; +} + +int main(int argc, char *argv[]) +{ + void *platform; + struct rpmsg_device *rpdev; + int ret; + + /* Initialize platform */ + ret = platform_init(argc, argv, &platform); + if (ret) { + LPERROR("Failed to initialize platform.\r\n"); + ret = -1; + } else { + rpdev = platform_create_rpmsg_vdev(platform, 0, + VIRTIO_DEV_MASTER, + NULL, + rpmsg_name_service_bind_cb); + if (!rpdev) { + LPERROR("Failed to create rpmsg virtio device.\r\n"); + ret = -1; + } else { + app(rpdev, platform); + platform_release_rpmsg_vdev(rpdev, platform); + ret = 0; + } + } + + LPRINTF("Stopping application...\r\n"); + platform_cleanup(platform); + + return ret; +} +