From 9724f7bcff08fbdceb62858eef24d50669346a5a Mon Sep 17 00:00:00 2001 From: zhaohonghao Date: Mon, 4 Aug 2025 19:48:33 +0800 Subject: [PATCH] smp: add smp support code for hi3095 and cxx add smp support code for hi3095 and cxx testcase Signed-off-by: zhaohonghao --- demos/hi3095/CMakeLists.txt | 22 +- demos/hi3095/apps/openamp/main.c | 108 ++++++++++ demos/hi3095/bsp/hi3095/cpu_config.h | 4 +- demos/hi3095/bsp/uart/serial.h | 2 +- demos/hi3095/build/build_app.sh | 8 +- demos/hi3095/build/build_fetch.sh | 6 +- doc/component_guide/UniProton_smp.md | 66 ++++++ src/component/mica/rpmsg_service.c | 4 +- src/core/kernel/task/smp/prt_task_init.c | 4 + testsuites/cxx-test/smp/smp_test.cc | 258 +++++++++++++++++++++++ testsuites/cxx-test/tools/CMakeLists.txt | 9 +- 11 files changed, 474 insertions(+), 17 deletions(-) create mode 100644 doc/component_guide/UniProton_smp.md create mode 100644 testsuites/cxx-test/smp/smp_test.cc diff --git a/demos/hi3095/CMakeLists.txt b/demos/hi3095/CMakeLists.txt index 0db94089..67357597 100644 --- a/demos/hi3095/CMakeLists.txt +++ b/demos/hi3095/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) set(HOME_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../..) -if (${APP} STREQUAL "cxxTest" OR ${APP} STREQUAL "eigenTest") +if (${APP} STREQUAL "cxxTest" OR ${APP} STREQUAL "eigenTest" OR ${APP} STREQUAL "UniProton_SMP_test") set(CMAKE_C_COMPILER ${CXX_TOOLCHAIN_PATH}/bin/aarch64-openeuler-linux-gcc) set(CMAKE_CXX_COMPILER ${CXX_TOOLCHAIN_PATH}/bin/aarch64-openeuler-linux-g++) set(CMAKE_ASM_COMPILER ${CXX_TOOLCHAIN_PATH}/bin/aarch64-openeuler-linux-gcc) @@ -16,7 +16,7 @@ endif() project(exmaples LANGUAGES C CXX ASM) -set(CC_OPTION "-g -march=armv8.2-a -nostdlib -nostdinc -Wl,--build-id=none -fno-builtin -fno-PIE -Wall -fno-dwarf2-cfi-asm -O0 -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-common -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -fno-builtin -finline-limit=20 -mstrict-align -mlittle-endian -nostartfiles -funwind-tables") +set(CC_OPTION "-g -march=armv8.2-a+nosimd -nostdlib -nostdinc -Wl,--build-id=none -fno-builtin -fno-PIE -Wall -fno-dwarf2-cfi-asm -O0 -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-common -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -fno-builtin -finline-limit=20 -mstrict-align -mlittle-endian -nostartfiles -funwind-tables") set(AS_OPTION "-g -march=armv8.2-a -Wl,--build-id=none -fno-builtin -fno-PIE -Wall -fno-dwarf2-cfi-asm -O0 -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-common -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -fno-builtin -finline-limit=20 -mstrict-align -mlittle-endian -nostartfiles -mgeneral-regs-only -DENV_EL1") set(LD_OPTION "-static -no-pie -Wl,--wrap=memset -Wl,--wrap=memcpy -Wl,-gc-sections -Wl,--eh-frame-hdr") set(CMAKE_C_FLAGS "${CC_OPTION} ${POSIX_OPTION}") @@ -71,7 +71,7 @@ link_libraries( -Wl,--end-group ) -if (${APP} STREQUAL "cxxTest" OR ${APP} STREQUAL "eigenTest") +if (${APP} STREQUAL "cxxTest" OR ${APP} STREQUAL "eigenTest" OR ${APP} STREQUAL "UniProton_SMP_test") link_libraries( "${CMAKE_CURRENT_SOURCE_DIR}/component/libcxx/lib/libstdc++.a" "${CXX_TOOLCHAIN_PATH}/lib64/gcc/aarch64-openeuler-linux-gnu/10.3.1/libgcc.a" @@ -87,7 +87,7 @@ add_subdirectory(${HOME_PATH}/src/component/proxy proxy) add_subdirectory(bsp) add_subdirectory(config) add_subdirectory(apps) -if (${APP} STREQUAL "cxxTest" OR ${APP} STREQUAL "eigenTest") +if (${APP} STREQUAL "cxxTest" OR ${APP} STREQUAL "eigenTest" OR ${APP} STREQUAL "UniProton_SMP_test") add_subdirectory(component/boost_1_54_0) endif() if(${CONFIG_OS_SUPPORT_LIBXML2}) @@ -208,6 +208,20 @@ elseif (${APP} STREQUAL "UniProton_cyclictest") target_compile_options(rpmsg PUBLIC -DCYCLIC_TESTCASE) list(APPEND OBJS $ $ $ $ $ $) add_executable(${APP} ${OBJS}) +elseif (${APP} STREQUAL "UniProton_SMP_test") + if (${CONFIG_OS_SUPPORT_CXX}) + add_subdirectory(${HOME_PATH}/testsuites/cxx-test tmp) + target_compile_options(rpmsg PUBLIC -DSMP_CXX_TESTCASE) + target_compile_options(cxxtest PUBLIC -D_POSIX_THREADS -DBOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) + list(APPEND OBJS $ $ $ $ $ $ $) + if (${CONFIG_OS_SUPPORT_LIBXML2}) + list(APPEND OBJS $) + endif() + else() + target_compile_options(rpmsg PUBLIC -DSMP_TESTCASE) + list(APPEND OBJS $ $ $ $ $) + endif() + add_executable(${APP} ${OBJS}) else() list(APPEND OBJS $ $ $ $ $) if (${CONFIG_LOSCFG_SHELL_TEST}) diff --git a/demos/hi3095/apps/openamp/main.c b/demos/hi3095/apps/openamp/main.c index c4174671..2395b3ee 100644 --- a/demos/hi3095/apps/openamp/main.c +++ b/demos/hi3095/apps/openamp/main.c @@ -2,11 +2,15 @@ #include #include #include +#include +#include +#include #include "securec.h" #include "prt_config.h" #include "prt_config_internal.h" #include "prt_hwi.h" #include "prt_task.h" +#include "prt_sem.h" #include "prt_log.h" #include "test.h" #include "rpmsg_backend.h" @@ -148,6 +152,102 @@ extern void interrupt_jitter_test_entry(); extern void cyclictest_entry(U64 interval, U64 loopNums); #endif +#if defined(OS_OPTION_SMP) && defined(SMP_CXX_TESTCASE) +extern void test_smp_cxx(); +extern void test_smp_rcv_data(); +extern SemHandle smp_msg_sem; + +#if defined(OS_SUPPORT_LIBXML2) +extern void test_smp_xml2(); +#endif + +void master_task_entry() +{ + test_smp_cxx(); +} + +void slave_task_entry() +{ +#if defined(OS_SUPPORT_LIBXML2) + test_smp_xml2(); +#endif + test_smp_rcv_data(); +} + +void master_task_init() +{ + U32 ret; + U8 ptNo = OS_MEM_DEFAULT_FSC_PT; + struct TskInitParam param = {0}; + TskHandle testTskHandle; + + // task 2 + param.stackAddr = (uintptr_t)PRT_MemAllocAlign(0, ptNo, 0x3000, MEM_ADDR_ALIGN_016); + param.taskEntry = (TskEntryFunc)master_task_entry; + param.taskPrio = 15; + param.name = "master_task"; + param.stackSize = 0x3000; + + ret = PRT_TaskCreate(&testTskHandle, ¶m); + if (ret) { + PRT_Printf("PRT_TaskCreate master task failed, ret: %d\n", ret); + return; + } + + ret = PRT_TaskResume(testTskHandle); + if (ret) { + PRT_Printf("PRT_TaskResume master task failed, ret: %d\n", ret); + } +} + +void slave_task_init(U32 slaveId) +{ + U32 ret; + U8 ptNo = OS_MEM_DEFAULT_FSC_PT; + struct TskInitParam param = {0}; + TskHandle testTskHandle; + // task 1 + param.stackAddr = PRT_MemAllocAlign(0, ptNo, 0x3000, MEM_ADDR_ALIGN_016); + param.taskEntry = (TskEntryFunc)slave_task_entry; + param.taskPrio = 20; + param.name = "slave_task"; + param.stackSize = 0x3000; + + ret = PRT_TaskCreate(&testTskHandle, ¶m); + if (ret) { + PRT_Printf("PRT_TaskCreate slave task failed, ret: %d\n", ret); + return; + } + + ret = PRT_TaskCoreBind(testTskHandle, 1 << (PRT_GetPrimaryCore() + slaveId)); + if (ret) { + PRT_Printf("PRT_TaskCoreBind slave task failed, ret: %d\n", ret); + return; + } + + ret = PRT_TaskResume(testTskHandle); + if (ret) { + PRT_Printf("PRT_TaskResume slave task failed, ret: %d\n", ret); + } +} + +void smp_test() +{ + U32 ret = PRT_SemCreate(0, &smp_msg_sem); + if (ret) { + PRT_Printf("SMP SemCreate failed, ret: %d\n", ret); + return; + } + + master_task_init(); + for (U32 slaveId = 1; slaveId < OS_SYS_CORE_RUN_NUM; slaveId++) { + slave_task_init(slaveId); + } + + PRT_SemDelete(smp_msg_sem); +} +#endif + void TestTaskEntry() { #if defined(OS_OPTION_OPENAMP) @@ -172,6 +272,10 @@ void TestTaskEntry() soem_test("eth3"); #endif +#if defined(OS_OPTION_SMP) && defined(SMP_CXX_TESTCASE) + smp_test(); +#endif + #if defined(POSIX_TESTCASE) || defined(CXX_TESTCASE) || defined(EIGEN_TESTCASE) || defined(RHEALSTONE_TESTCASE) PRT_Printf("ENTER INIT\n"); Init(0, 0, 0, 0); @@ -196,6 +300,10 @@ void TestTaskEntry() #if defined(CYCLIC_TESTCASE) cyclictest_entry(1000, 1000); #endif + +#if defined(RCV_TEST) + rcv_test(); +#endif } #if defined(DRIVER_TESTCASE) diff --git a/demos/hi3095/bsp/hi3095/cpu_config.h b/demos/hi3095/bsp/hi3095/cpu_config.h index 536b4cfc..7c6d7b38 100644 --- a/demos/hi3095/bsp/hi3095/cpu_config.h +++ b/demos/hi3095/bsp/hi3095/cpu_config.h @@ -5,9 +5,9 @@ #define MMU_IMAGE_ADDR 0xb3000000ULL #define MMU_GIC_ADDR 0x1a000000ULL -#define MMU_UART_ADDR 0x18340000ULL +#define MMU_UART_ADDR 0x18330000ULL #define MMU_OPENAMP_ADDR 0xb0000000ULL -#define OPENAMP_SHM_SIZE 0x100000 +#define OPENAMP_SHM_SIZE 0x1000000 #define MMU_LOG_MEM_ADDR 0xd3000000ULL #define MMU_DRIVER_ADDR1 0x0c000000ULL #define MMU_DRIVER_ADDR2 0x08600000ULL diff --git a/demos/hi3095/bsp/uart/serial.h b/demos/hi3095/bsp/uart/serial.h index 5332b750..8d2cbf0a 100644 --- a/demos/hi3095/bsp/uart/serial.h +++ b/demos/hi3095/bsp/uart/serial.h @@ -4,7 +4,7 @@ #include "uart_regs.h" #include "prt_typedef.h" -#define SERIAL_SEL_UART_PORT 1 +#define SERIAL_SEL_UART_PORT 0 #define SERIAL_TIMEOUT_MS 10 #define SERIAL_NAME_SIZE 32 diff --git a/demos/hi3095/build/build_app.sh b/demos/hi3095/build/build_app.sh index c80c3ce8..75904dd4 100644 --- a/demos/hi3095/build/build_app.sh +++ b/demos/hi3095/build/build_app.sh @@ -8,7 +8,7 @@ else export APP=hi3095 fi -if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" ]] +if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" || "${APP}" == "UniProton_SMP_test" ]] then export CXX_TOOLCHAIN_PATH=/opt/openeuler/oecore-x86_64/sysroots/x86_64-openeulersdk-linux/usr fi @@ -19,12 +19,12 @@ sh ./build_fetch.sh sh ./build_static.sh hi3095 sh ./build_openamp.sh $TOOLCHAIN_PATH -if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" ]] && [ ! -d "./../component/libcxx" ] +if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" || "${APP}" == "UniProton_SMP_test" ]] && [ ! -d "./../component/libcxx" ] then sh ./libcxx_build.sh fi -if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" ]] +if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" || "${APP}" == "UniProton_SMP_test" ]] then cmake -S .. -B $TMP_DIR -DAPP:STRING=$APP -DTOOLCHAIN_PATH:STRING=$TOOLCHAIN_PATH -DCXX_TOOLCHAIN_PATH:STRING=$CXX_TOOLCHAIN_PATH -DCPU_TYPE:SRTING="hi3095" -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY else @@ -36,7 +36,7 @@ make $APP popd cp ./$TMP_DIR/$APP $APP.elf -if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" ]] +if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" || "${APP}" == "UniProton_SMP_test" ]] then python ./../../../bin_helper.py -f ./$APP.elf --nocopy $CXX_TOOLCHAIN_PATH/bin/aarch64-openeuler-linux-objcopy -O binary ./$APP.elf $APP.bin diff --git a/demos/hi3095/build/build_fetch.sh b/demos/hi3095/build/build_fetch.sh index 08e08c7e..77ce5198 100644 --- a/demos/hi3095/build/build_fetch.sh +++ b/demos/hi3095/build/build_fetch.sh @@ -31,7 +31,7 @@ fi popd pushd ../component -if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" ]] && [ ! -d "./boost_1_54_0" ] +if [[ "${APP}" == "cxxTest" || "${APP}" == "eigenTest" || "${APP}" == "UniProton_SMP_test" ]] && [ ! -d "./boost_1_54_0" ] then echo "################# get boost #################" rm -rf boost_1_54_0* @@ -44,7 +44,7 @@ fi popd pushd ../component -if [[ "${APP}" == "eigenTest" && ! -d "./eigen-3.4.0" ]] +if [[ "${APP}" == "eigenTest" || "${APP}" == "UniProton_SMP_test" ]] && [ ! -d "./eigen-3.4.0" ] then echo "################# get eigen #################" rm -rf eigen-3.4.0* @@ -55,7 +55,7 @@ fi popd pushd ../component -if [[ "${APP}" == "UniPorton_test_libxml2_interface" && ! -d "./libxml2" ]] +if [[ "${APP}" == "UniPorton_test_libxml2_interface" || "${APP}" == "UniProton_SMP_test" ]] && [ ! -d "./libxml2" ] then echo "################# get libxml2 #################" rm -rf ./libxml2 diff --git a/doc/component_guide/UniProton_smp.md b/doc/component_guide/UniProton_smp.md new file mode 100644 index 00000000..04f0508d --- /dev/null +++ b/doc/component_guide/UniProton_smp.md @@ -0,0 +1,66 @@ +# Uniproton 多核SMP使用指南 + +## 1 整体方案 + +在多核场景下,可通过SMP机制支持UniProton的多核运行,使同一OS实例的多个任务同时在不同核上同时处理。以上特性可显著提升系统的实时性能与并行性能,应用场景广泛。 + +## 2 开发环境说明 + +- 开发平台:armv8 +- 芯片型号:hi3095 +- OS版本信息:UniProton master +- 集成开发环境:UniProton-docker + +## 3 多核SMP部署 + +### 3.1 SMP镜像编译 + +1) 以hi3095平台为例,修改开关配置文件build/uniproton_config/config_armv8_kp920_lite/defconfig: +``` +CONFIG_OS_MAX_CORE_NUM=4 // 配置为最大可支持的核数 +CONFIG_OS_OPTION_CPU64=y // 是否为64位操作系统 +CONFIG_OS_OPTION_SMP=y // 是否启用SMP功能,开启 +CONFIG_OS_OPTION_HWI_AFFINITY=y // 是否启用中断绑核功能,开启 +CONFIG_INTERNAL_OS_SPIN_LOCK=y // 是否启用自旋锁功能,开启 +CONFIG_OS_OPTION_TASK_AFFINITY_STATIC=y // 是否支持任务亲和性静态特性,开启 +# CONFIG_INTERNAL_OS_SCHEDULE_SINGLE_CORE_BY_CCODE is not set // 内部函数宏,单核使用C语言实现调度部分时使用,关闭 +``` +通过对以上开关进行配置,SMP的主要功能便可支持。 + +2) 修改配置文件demos/hi3095/config/prt_config.h +``` +/* 实时系统实际运行的核数,单位:个 */ +#define OS_SYS_CORE_RUN_NUM 2 +/* 最大可支持的核数,单位:个 */ +#define OS_SYS_CORE_MAX_NUM 4 +/* 主核ID */ +#define OS_SYS_CORE_PRIMARY 2 +``` +以上配置项设置了SMP运行的主核为CPU 2,系统的模块注册和初始化操作都是在主核上完成。除主核外,配置了从核CPU 3上的系统任务运行。 + +3) 可通过以下命令,在demos/hi3095/build目录下编译SMP测试用例,生成用例镜像UniProton_SMP_test.elf。 +``` +sh build_app.sh UniProton_SMP_test +``` + +### 3.2 SMP镜像部署运行 + +1) 以hi3095为例,CPU 3在欧拉侧已预留,只需要将CPU 2下线即可: +``` +echo 0 > /sys/bus/cpu/devices/cpu2/online +``` + +2) 设置mica conf文件: +``` +[Mica] +Name=uniproton-hi3095-smp +CPU=2 +ClientPath=/mcs/UniProton_SMP_test.elf +AutoBoot=no +``` + +3) 基于上述conf文件配置,将UniProton_SMP_test.elf使用mica拉起,成功后进入tty界面,便可查看多核任务打印情况。 + +### 3.3 SMP多核任务设置 + +在以上测试用例中,实现了SMP多核任务的设置。与单核任务创建不同,SMP多核在使用PRT_TaskCreate接口创建任务后,还需要调用PRT_TaskCoreBind接口将任务与指定从核绑定,以实现多核任务同时运行。相关功能测试代码在demos/hi3095/apps/openamp/main.c中的smp_test函数中实现。 diff --git a/src/component/mica/rpmsg_service.c b/src/component/mica/rpmsg_service.c index 73704c80..c19e607b 100644 --- a/src/component/mica/rpmsg_service.c +++ b/src/component/mica/rpmsg_service.c @@ -249,7 +249,7 @@ int rcv_data_from_nrtos(void *rcv_data, int *data_len) g_umt_send_data_addr = msg->phy_addr + OPENAMP_SHM_COPY_SIZE; init ++; } - memcpy(rcv_data, (void *)msg->phy_addr, msg->data_len); + __real_memcpy(rcv_data, (void *)msg->phy_addr, msg->data_len); *data_len = msg->data_len; rpmsg_release_rx_buffer(&umt_ept, umt_msg.data); return OS_OK; @@ -276,7 +276,7 @@ int send_data_to_nrtos(void *send_data, int data_len) if (data_len > OPENAMP_SHM_COPY_SIZE) return OS_ERROR; - memcpy(g_umt_send_data_addr, send_data, data_len); + __real_memcpy(g_umt_send_data_addr, send_data, data_len); rpmsg_data_len = data_len; ret = rpmsg_send(&umt_ept, &rpmsg_data_len, sizeof(int)); if (ret < 0) { diff --git a/src/core/kernel/task/smp/prt_task_init.c b/src/core/kernel/task/smp/prt_task_init.c index 9dd619e1..b64c12a9 100644 --- a/src/core/kernel/task/smp/prt_task_init.c +++ b/src/core/kernel/task/smp/prt_task_init.c @@ -441,6 +441,10 @@ OS_SEC_L4_TEXT locale_t *PRT_LocaleCurrent(void) return NULL; } + if (!tskCb->locale) { + tskCb->locale = (locale_t)libc_global_locale; + } + return &tskCb->locale; } #endif \ No newline at end of file diff --git a/testsuites/cxx-test/smp/smp_test.cc b/testsuites/cxx-test/smp/smp_test.cc new file mode 100644 index 00000000..69cc9f0f --- /dev/null +++ b/testsuites/cxx-test/smp/smp_test.cc @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Shape { +public: + virtual double calculateArea() const = 0; + virtual ~Shape() {} +}; + +class Circle : public Shape { + double radius; +public: + Circle(double r) : radius(r) { + if(r <= 0) throw std::invalid_argument("Radius must be positive"); + } + double calculateArea() const override { + return 3.14159 * radius * radius; + } +}; + +template +class Container { + T* elements; + size_t capacity; +public: + Container(size_t size) : capacity(size), elements(new T[size]) {} + ~Container() { delete[] elements; } + + T& operator[](size_t index) { + if(index >= capacity) throw std::out_of_range("Index out of bounds"); + return elements[index]; + } +}; + +void cxx_test_func() +{ + Shape *shapes[] = {new Circle(2.5), new Circle(1.0)}; + for(auto shape : shapes) { + try { + std::cout << "Area: " << shape->calculateArea() << std::endl; + delete shape; + } catch(const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + delete shape; + } + } + + Container container(3); + container[0] = 3.14; + container[1] = 2.71; + std::cout << "Element 0: " << container[0] << std::endl; + + try { + Shape *shape = new Circle(-1.0); + } catch(const std::exception& e) { + std::cerr << "Caught exception: " << e.what() << std::endl; + } + + try { + container[5] = 1.618; + } catch(const std::exception& e) { + std::cerr << "Caught exception: " << e.what() << std::endl; + } + + std::cout << "cxx func test success" << std::endl; +} + +void eigen_test_func() +{ + std::cout << "=== Matrix Operations ===" << std::endl; + Eigen::Matrix3d A; + A << 1, 2, 3, + 4, 5, 6, + 7, 8, 9; + Eigen::Matrix3d B = Eigen::Matrix3d::Random(); + + std::cout << "Matrix A:\n" << A << std::endl; + std::cout << "Matrix B (random):\n" << B << std::endl; + std::cout << "A + B:\n" << A + B << std::endl; + std::cout << "A * B:\n" << A * B << std::endl; + std::cout << "A.transpose():\n" << A.transpose() << std::endl; + + std::cout << "\n=== Vector Operations ===" << std::endl; + Eigen::Vector3d v(1, 2, 3); + Eigen::Vector3d w(4, 5, 6); + + std::cout << "Vector v:\n" << v << std::endl; + std::cout << "Vector w:\n" << w << std::endl; + std::cout << "Dot product: " << v.dot(w) << std::endl; + std::cout << "Cross product:\n" << v.cross(w) << std::endl; + + std::cout << "\n=== Linear Equation Solving ===" << std::endl; + Eigen::Vector3d b(1, 1, 1); + Eigen::Vector3d x = A.colPivHouseholderQr().solve(b); + std::cout << "Solution x to Ax = b:\n" << x << std::endl; + std::cout << "Residual norm: " << (A * x - b).norm() << std::endl; + + std::cout << "\n=== Eigenvalue Computation ===" << std::endl; + Eigen::SelfAdjointEigenSolver eigensolver(A); + if (eigensolver.info() != Eigen::Success) { + std::cout << "Eigenvalue computation failed!" << std::endl; + } else { + std::cout << "Eigenvalues:\n" << eigensolver.eigenvalues() << std::endl; + std::cout << "Eigenvectors:\n" << eigensolver.eigenvectors() << std::endl; + } + + std::cout << "eigen func test success" << std::endl; +} + +extern "C" { +#include +#include +#include +#include +#include + +#define STR_SIZE 1024 * 1024 + +SemHandle smp_msg_sem; +bool smp_data_finish = false; +char *rcv_buffer = NULL , *result_buffer = NULL; +int data_len = 0; +int cxx_test_result = 0; + +void create_random_char(char *buffer) +{ + for (int i = 0; i < STR_SIZE; i++) { + buffer[i] = 'B' + rand() % 26; + } +} + +// 通信接口测试用例 +void test_smp_rcv_data() +{ + printf("test_smp_rcv_data: start\n"); + char msg[] = "rtos rcv ok"; + int ret = 0, i = 0; + + srand(time(NULL)); + rcv_buffer = (char *)malloc(STR_SIZE + 1); + if (rcv_buffer == NULL) { + printf("test_smp_rcv_data: rcv_buffer malloc failed\n"); + } + + result_buffer = (char *)malloc(STR_SIZE + 1); + if (result_buffer == NULL) { + printf("test_smp_rcv_data: result_buffer malloc failed\n"); + } + + rcv_buffer[STR_SIZE] = 0; + result_buffer[STR_SIZE] = 0; + create_random_char(result_buffer); + + while(1) { + memset(rcv_buffer, 0, STR_SIZE); + ret = rcv_data_from_nrtos(rcv_buffer, &data_len); + if (ret != 0) + break; + printf("test_smp_rcv_data: rcv buffer %s data_len %d \n", rcv_buffer + STR_SIZE - 10, data_len); + PRT_SemPost(smp_msg_sem); + PRT_TaskDelay(100); + result_buffer[STR_SIZE - 1] = '0' + cxx_test_result; + printf("test_smp_rcv_data: result buffer %s data_len %d \n", result_buffer + STR_SIZE - 10, STR_SIZE); + send_data_to_nrtos(result_buffer, STR_SIZE); + } +} + +// C++测试用例,包含C++基础功能与Eigen功能测试 +void test_smp_cxx() +{ + printf("test_smp_cxx: start\n"); + while(1) { + PRT_SemPend(smp_msg_sem, OS_WAIT_FOREVER); + printf("test_smp_cxx: rcv data len from nrtos %d\n", data_len); + cxx_test_func(); + eigen_test_func(); + cxx_test_result++; + printf("test_smp_cxx: cxx test result %d\n", cxx_test_result); + } +} + +// libxml2测试用例 +#if defined(OS_SUPPORT_LIBXML2) +int uniproton_testapi(int argc, char **argv); +int uniproton_testchar(void); +int uniproton_testdict(void); +int uniproton_testrecurse(int argc, char **argv); + +static int uniproton_testchar_arg(int argc, char **argv) { + return uniproton_testchar(); +} + +static int uniproton_testdict_arg(int argc, char **argv) { + return uniproton_testdict(); +} + +int uniproton_runtest(int argc, char **argv); + +typedef int (*test_fn)(int argc, char **argv); + +typedef struct test_case { + char *name; + test_fn fn; + int skip; +} test_case_t; + +#define TEST_CASE(func, s) { \ + .name = #func, \ + .fn = func, \ + .skip = s \ +} + +#define TEST_CASE_Y(func) TEST_CASE(func, 0) +#define TEST_CASE_N(func) TEST_CASE(func, 1) + +static test_case_t g_cases[] = { + TEST_CASE_Y(uniproton_runtest), + TEST_CASE_Y(uniproton_testrecurse), + TEST_CASE_Y(uniproton_testchar_arg), + TEST_CASE_Y(uniproton_testdict_arg), + TEST_CASE_Y(uniproton_testapi), +}; + +void test_smp_xml2() +{ + int i = 0; + int cnt = 0; + int fails = 0; + int len = sizeof(g_cases) / sizeof(test_case_t); + printf("\n===test start=== \n"); + for (i = 0, cnt = 0; i < len; i++) { + test_case_t *tc = &g_cases[i]; + printf("\n===%s start === \n", tc->name); + if (tc->skip) { + continue; + } + cnt++; + int ret = tc->fn(0, NULL); + if (ret) { + fails++; + printf("\n===%s failed ===\n", tc->name); + } else { + printf("\n===%s success ===\n", tc->name); + } + } + printf("\n===test end, total: %d, fails:%d ===\n", cnt, fails); +} +#endif +} \ No newline at end of file diff --git a/testsuites/cxx-test/tools/CMakeLists.txt b/testsuites/cxx-test/tools/CMakeLists.txt index 19233da7..6129a6f0 100644 --- a/testsuites/cxx-test/tools/CMakeLists.txt +++ b/testsuites/cxx-test/tools/CMakeLists.txt @@ -4,6 +4,9 @@ include_directories( file(GLOB TEST_UTIL ${CMAKE_CURRENT_SOURCE_DIR}/../util/*.cc) file(GLOB TEST_BOOST ${CMAKE_CURRENT_SOURCE_DIR}/../boost/system/*.cc) +if (${APP} STREQUAL "UniProton_SMP_test") + file(GLOB TEST_SMP ${CMAKE_CURRENT_SOURCE_DIR}/../smp/*.cc) +endif() execute_process( COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test_helper.py @@ -13,7 +16,11 @@ execute_process( file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/.compiles_list SRC_LIST) -set(ALL_SRC ${TEST_UTIL} ${TEST_BOOST} ${SRC_LIST} .run_test.cc) +if (${APP} STREQUAL "UniProton_SMP_test") + set(ALL_SRC ${TEST_UTIL} ${TEST_BOOST} ${TEST_SMP} ${SRC_LIST} .run_test.cc) +else() + set(ALL_SRC ${TEST_UTIL} ${TEST_BOOST} ${SRC_LIST} .run_test.cc) +endif() add_library(cxxtest OBJECT ${ALL_SRC}) -- Gitee