This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 45f6d86f37fceed4e0267bb05ef22a6f2344b6bf Author: mazhuang <[email protected]> AuthorDate: Fri Sep 20 15:18:01 2024 +0800 drivers/rpmsg: add rpmsg_test to test rpmsg hold/release rx buffer rpmsg_test is a rpmsg api test service inside the kernel, and user can use ioctl to start this test. Signed-off-by: mazhuang <[email protected]> Signed-off-by: Bowen Wang <[email protected]> Signed-off-by: wangshaoxin <[email protected]> --- boards/sim/sim/sim/configs/rpproxy/defconfig | 1 + boards/sim/sim/sim/configs/rpserver/defconfig | 1 + drivers/rpmsg/CMakeLists.txt | 4 + drivers/rpmsg/Kconfig | 4 + drivers/rpmsg/Make.defs | 4 + drivers/rpmsg/rpmsg.c | 13 ++ drivers/rpmsg/rpmsg_test.c | 281 ++++++++++++++++++++++++++ drivers/rpmsg/rpmsg_test.h | 43 ++++ include/nuttx/rpmsg/rpmsg.h | 4 + 9 files changed, 355 insertions(+) diff --git a/boards/sim/sim/sim/configs/rpproxy/defconfig b/boards/sim/sim/sim/configs/rpproxy/defconfig index a774deee3e6..6300b3a9782 100644 --- a/boards/sim/sim/sim/configs/rpproxy/defconfig +++ b/boards/sim/sim/sim/configs/rpproxy/defconfig @@ -53,6 +53,7 @@ CONFIG_READLINE_CMD_HISTORY=y CONFIG_READLINE_TABCOMPLETION=y CONFIG_RPMSGMTD=y CONFIG_RPMSG_PING=y +CONFIG_RPMSG_TEST=y CONFIG_RPMSG_UART=y CONFIG_RPTUN=y CONFIG_RTC=y diff --git a/boards/sim/sim/sim/configs/rpserver/defconfig b/boards/sim/sim/sim/configs/rpserver/defconfig index bf476ec5b79..e569476f3ca 100644 --- a/boards/sim/sim/sim/configs/rpserver/defconfig +++ b/boards/sim/sim/sim/configs/rpserver/defconfig @@ -70,6 +70,7 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_RPMSG=y CONFIG_RPMSGMTD_SERVER=y CONFIG_RPMSG_PING=y +CONFIG_RPMSG_TEST=y CONFIG_RPMSG_UART=y CONFIG_RPTUN=y CONFIG_RTC=y diff --git a/drivers/rpmsg/CMakeLists.txt b/drivers/rpmsg/CMakeLists.txt index 3c53305e8b1..753e8bc3cf6 100644 --- a/drivers/rpmsg/CMakeLists.txt +++ b/drivers/rpmsg/CMakeLists.txt @@ -59,6 +59,10 @@ if(CONFIG_RPMSG) list(APPEND SRCS rpmsg_router_hub.c rpmsg_router_edge.c) endif() + if(CONFIG_RPMSG_TEST) + list(APPEND SRCS rpmsg_test.c) + endif() + target_include_directories(drivers PRIVATE ${NUTTX_DIR}/openamp/open-amp/lib) target_sources(drivers PRIVATE ${SRCS}) endif() diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index 3d10914868a..80fde24e6bf 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -21,6 +21,10 @@ config RPMSG_PING This is for debugging & profiling, create ping rpmsg channel, user can use it to get send/recv speed & latency. +config RPMSG_TEST + bool "rpmsg test support" + default n + endif # RPMSG config RPMSG_ROUTER diff --git a/drivers/rpmsg/Make.defs b/drivers/rpmsg/Make.defs index f83f4696e43..164fabf1762 100644 --- a/drivers/rpmsg/Make.defs +++ b/drivers/rpmsg/Make.defs @@ -30,6 +30,10 @@ ifeq ($(CONFIG_RPMSG_PING),y) CSRCS += rpmsg_ping.c endif +ifeq ($(CONFIG_RPMSG_TEST),y) +CSRCS += rpmsg_test.c +endif + ifeq ($(CONFIG_RPMSG_ROUTER),y) CSRCS += rpmsg_router_hub.c rpmsg_router_edge.c endif diff --git a/drivers/rpmsg/rpmsg.c b/drivers/rpmsg/rpmsg.c index 8c63aff2afd..cb6a0960ad1 100644 --- a/drivers/rpmsg/rpmsg.c +++ b/drivers/rpmsg/rpmsg.c @@ -34,6 +34,7 @@ #include <nuttx/rpmsg/rpmsg.h> #include "rpmsg_ping.h" +#include "rpmsg_test.h" /**************************************************************************** * Private Types @@ -124,6 +125,11 @@ static int rpmsg_dev_ioctl_(FAR struct rpmsg_s *rpmsg, int cmd, case RPMSGIOC_PING: ret = rpmsg_ping(&rpmsg->ping, (FAR const struct rpmsg_ping_s *)arg); break; +#endif +#ifdef CONFIG_RPMSG_TEST + case RPMSGIOC_TEST: + ret = rpmsg_test(&rpmsg->test, arg); + break; #endif default: if (rpmsg->ops->ioctl) @@ -432,6 +438,9 @@ void rpmsg_device_created(FAR struct rpmsg_s *rpmsg) #ifdef CONFIG_RPMSG_PING rpmsg_ping_init(rpmsg->rdev, &rpmsg->ping); #endif +#ifdef CONFIG_RPMSG_TEST + rpmsg_test_init(rpmsg->rdev, &rpmsg->test); +#endif } void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg) @@ -444,6 +453,10 @@ void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg) rpmsg_ping_deinit(&rpmsg->ping); #endif +#ifdef CONFIG_RPMSG_TEST + rpmsg_test_deinit(&rpmsg->test); +#endif + nxrmutex_lock(&rpmsg->lock); metal_list_for_each_safe(&rpmsg->bind, tmp, node) { diff --git a/drivers/rpmsg/rpmsg_test.c b/drivers/rpmsg/rpmsg_test.c new file mode 100644 index 00000000000..f3d18283913 --- /dev/null +++ b/drivers/rpmsg/rpmsg_test.c @@ -0,0 +1,281 @@ +/**************************************************************************** + * drivers/rpmsg/rpmsg_test.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <nuttx/clock.h> +#include <nuttx/kmalloc.h> +#include <nuttx/list.h> +#include <nuttx/wqueue.h> + +#include "rpmsg_test.h" + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#define RPMSG_TEST_EPT_NAME "rpmsg-test" + +#define RPMSG_TEST_CMD(type, value) (((type) << 16) | (value)) +#define RPMSG_TEST_GET_TYPE(cmd) ((cmd) >> 16) +#define RPMSG_TEST_GET_VALUE(cmd) ((cmd) & 0xffff) + +/* Rpmsg test type,value and cmd definition */ + +#define RPMSG_TEST_TYPE_HOLD_RX 1 +#define RPMSG_TEST_VAL_HOLD_RX 0 +#define RPMSG_TEST_VAL_HOLD_RX_END 1 + +#define RPMSG_TEST_CMD_HOLD_RX \ + RPMSG_TEST_CMD(RPMSG_TEST_TYPE_HOLD_RX, RPMSG_TEST_VAL_HOLD_RX) +#define RPMSG_TEST_CMD_HOLD_RX_END \ + RPMSG_TEST_CMD(RPMSG_TEST_TYPE_HOLD_RX, RPMSG_TEST_VAL_HOLD_RX_END) + +/* Magic number used in test case */ + +#define RPMSG_TEST_MAGIC1 0x55 +#define RPMSG_TEST_MAGIC2 0xaa + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rpmsg_test_priv_s +{ + FAR struct rpmsg_endpoint *ept; + struct list_node rxhead; + struct work_s work; +}; + +begin_packed_struct struct rpmsg_test_msg_s +{ + uint32_t node[4]; /* Used for the list node */ + uint32_t cmd; + uint32_t len; + uint8_t data[1]; +} end_packed_struct; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rpmsg_test_memcmp + ****************************************************************************/ + +static bool rpmsg_test_memcmp(FAR const uint8_t *buf, uint8_t ch, + size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + { + if (buf[i] != ch) + { + return false; + } + } + + return true; +} + +/**************************************************************************** + * Name: rpmsg_test_hold_rx_work + ****************************************************************************/ + +static void rpmsg_test_hold_rx_work(FAR void *arg) +{ + FAR struct rpmsg_test_priv_s *priv = arg; + FAR struct rpmsg_test_msg_s *msg; + bool ret; + + /* Check all the rx buffer value (should still be MAGIC2) and release + * all the held rx buffers. + */ + + syslog(LOG_EMERG, "Rpmsg Test: release rx buffers start\n"); + + while (!list_is_empty(&priv->rxhead)) + { + msg = (FAR struct rpmsg_test_msg_s *)list_remove_head(&priv->rxhead); + ret = rpmsg_test_memcmp(msg->data, RPMSG_TEST_MAGIC2, msg->len); + DEBUGASSERT(ret); + rpmsg_release_rx_buffer(priv->ept, msg); + } + + syslog(LOG_EMERG, "Rpmsg Test: release rx buffers end\n"); +} + +/**************************************************************************** + * Name: rpmsg_test_hold_rx_cb + ****************************************************************************/ + +static void rpmsg_test_hold_rx_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *_priv) +{ + FAR struct rpmsg_test_priv_s *priv = _priv; + FAR struct rpmsg_test_msg_s *msg = data; + uint32_t value = RPMSG_TEST_GET_VALUE(msg->cmd); + bool ret; + + /* Hold the rx buffer and fill the rx buffer data with MAGIC2 */ + + ret = rpmsg_test_memcmp(msg->data, RPMSG_TEST_MAGIC1, msg->len); + DEBUGASSERT(ret); + memset(msg->data, RPMSG_TEST_MAGIC2, msg->len); + rpmsg_hold_rx_buffer(ept, data); + + list_add_tail(&priv->rxhead, (FAR struct list_node *)data); + + if (value == RPMSG_TEST_VAL_HOLD_RX_END) + { + syslog(LOG_EMERG, "Rpmsg Test: hold rx buffer finish\n"); + + /* Delay 10ms to release all the rx buffers, to make sure + * the hold rx buffer api is valid. + */ + + work_queue(LPWORK, &priv->work, rpmsg_test_hold_rx_work, priv, + MSEC2TICK(10)); + } +} + +/**************************************************************************** + * Name: rpmsg_test_ept_cb + ****************************************************************************/ + +static int rpmsg_test_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv) +{ + FAR struct rpmsg_test_msg_s *msg = data; + + switch (RPMSG_TEST_GET_TYPE(msg->cmd)) + { + case RPMSG_TEST_TYPE_HOLD_RX: + rpmsg_test_hold_rx_cb(ept, data, len, src, priv); + break; + default: + break; + } + + return 0; +} + +/**************************************************************************** + * Name: rpmsg_test_hold_rx + ****************************************************************************/ + +static int rpmsg_test_hold_rx(FAR struct rpmsg_test_priv_s *priv) +{ + FAR struct rpmsg_endpoint *ept = priv->ept; + FAR struct rpmsg_test_msg_s *msg; + FAR struct rpmsg_test_msg_s *nmsg; + uint32_t space; + uint32_t nspace; + int num = 0; + int ret; + + syslog(LOG_EMERG, "Rpmsg Test: start send\n"); + + /* Send all the tx buffer to remote core, remote core will hold this + * buffer. + */ + + msg = rpmsg_get_tx_payload_buffer(ept, &space, false); + if (msg == NULL) + { + return -ENOMEM; + } + + for (; ; ) + { + nmsg = rpmsg_get_tx_payload_buffer(ept, &nspace, false); + num++; + msg->cmd = nmsg ? RPMSG_TEST_CMD_HOLD_RX : + RPMSG_TEST_CMD_HOLD_RX_END; + msg->len = space - sizeof(*msg) + 1; + memset(msg->data, RPMSG_TEST_MAGIC1, msg->len); + ret = rpmsg_send_nocopy(ept, msg, space); + DEBUGASSERT(ret >= 0); + if (nmsg == NULL) + { + break; + } + + msg = nmsg; + space = nspace; + } + + syslog(LOG_EMERG, "Rpmsg Test: tx buffer num=%d space=%" PRIu32 "\n", + num, space); + + syslog(LOG_EMERG, "Rpmsg Test: send finish\n"); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int rpmsg_test(FAR struct rpmsg_endpoint *ept, unsigned long arg) +{ + FAR struct rpmsg_test_priv_s *priv = ept->priv; + + /* Only support rx hold buffer test case for now */ + + return rpmsg_test_hold_rx(priv); +} + +int rpmsg_test_init(FAR struct rpmsg_device *rdev, + FAR struct rpmsg_endpoint *ept) +{ + FAR struct rpmsg_test_priv_s *priv; + + priv = kmm_zalloc(sizeof(*priv)); + if (priv == NULL) + { + return -ENOMEM; + } + + list_initialize(&priv->rxhead); + priv->ept = ept; + ept->priv = priv; + return rpmsg_create_ept(ept, rdev, RPMSG_TEST_EPT_NAME, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + rpmsg_test_ept_cb, NULL); +} + +void rpmsg_test_deinit(FAR struct rpmsg_endpoint *ept) +{ + FAR struct rpmsg_test_priv_s *priv = ept->priv; + + rpmsg_destroy_ept(ept); + kmm_free(priv); +} diff --git a/drivers/rpmsg/rpmsg_test.h b/drivers/rpmsg/rpmsg_test.h new file mode 100644 index 00000000000..fecfbd31d3f --- /dev/null +++ b/drivers/rpmsg/rpmsg_test.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * drivers/rpmsg/rpmsg_test.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_RPMSG_RPMSG_TEST_H +#define __DRIVERS_RPMSG_RPMSG_TEST_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/rpmsg/rpmsg.h> + +#ifdef CONFIG_RPMSG_TEST + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int rpmsg_test_init(FAR struct rpmsg_device *rdev, + FAR struct rpmsg_endpoint *ept); +void rpmsg_test_deinit(FAR struct rpmsg_endpoint *ept); +int rpmsg_test(FAR struct rpmsg_endpoint *ept, + unsigned long test); + +#endif /* CONFIG_RPMSG_TEST */ +#endif /* __DRIVERS_RPMSG_RPMSG_TEST_H */ diff --git a/include/nuttx/rpmsg/rpmsg.h b/include/nuttx/rpmsg/rpmsg.h index c6c124efb76..b31b56e2998 100644 --- a/include/nuttx/rpmsg/rpmsg.h +++ b/include/nuttx/rpmsg/rpmsg.h @@ -42,6 +42,7 @@ #define RPMSGIOC_PANIC _RPMSGIOC(1) #define RPMSGIOC_DUMP _RPMSGIOC(2) #define RPMSGIOC_PING _RPMSGIOC(3) +#define RPMSGIOC_TEST _RPMSGIOC(4) #define RPMSG_SIGNAL_RUNNING TIOCM_CD @@ -58,6 +59,9 @@ struct rpmsg_s FAR const struct rpmsg_ops_s *ops; #ifdef CONFIG_RPMSG_PING struct rpmsg_endpoint ping; +#endif +#ifdef CONFIG_RPMSG_TEST + struct rpmsg_endpoint test; #endif struct rpmsg_device rdev[0]; };
