From 85d3dd8656ccce4c2d929a69484fb8d88ec6c6c3 Mon Sep 17 00:00:00 2001 From: "Michal Princ (nxa17570)" Date: Thu, 18 Jan 2024 17:10:14 +0100 Subject: [PATCH] Apply 1.12.0 release update --- .circleci/config.yml | 49 +- .clang-format | 63 +- .clang-format-ignore | 9 + .github/workflows/clang-format.yml | 11 +- LICENSE | 2 +- README.md | 4 +- doxygen/Doxyfile.erpc | 2 +- doxygen/Doxyfile.erpcgen | 2 +- erpc_c/Makefile | 8 +- .../infra/erpc_arbitrated_client_manager.cpp | 3 +- .../infra/erpc_arbitrated_client_manager.hpp | 6 +- erpc_c/infra/erpc_basic_codec.cpp | 69 +- erpc_c/infra/erpc_basic_codec.hpp | 59 +- erpc_c/infra/erpc_client_manager.cpp | 17 +- erpc_c/infra/erpc_client_manager.h | 22 +- erpc_c/infra/erpc_client_server_common.hpp | 12 +- erpc_c/infra/erpc_codec.hpp | 73 +- erpc_c/infra/erpc_crc16.cpp | 10 +- erpc_c/infra/erpc_framed_transport.cpp | 112 +- erpc_c/infra/erpc_framed_transport.hpp | 50 +- erpc_c/infra/erpc_manually_constructed.hpp | 2 +- erpc_c/infra/erpc_message_buffer.cpp | 92 +- erpc_c/infra/erpc_message_buffer.hpp | 343 +++-- erpc_c/infra/erpc_message_loggers.hpp | 9 +- erpc_c/infra/erpc_pre_post_action.h | 4 +- erpc_c/infra/erpc_server.cpp | 4 +- erpc_c/infra/erpc_server.hpp | 14 +- erpc_c/infra/erpc_simple_server.cpp | 85 +- erpc_c/infra/erpc_simple_server.hpp | 27 +- erpc_c/infra/erpc_static_queue.hpp | 1 + erpc_c/infra/erpc_transport.hpp | 9 + erpc_c/infra/erpc_transport_arbitrator.cpp | 84 +- erpc_c/infra/erpc_transport_arbitrator.hpp | 103 +- erpc_c/infra/erpc_utils.cpp | 26 + erpc_c/infra/erpc_utils.hpp | 17 + erpc_c/infra/erpc_version.h | 4 +- erpc_c/port/erpc_config_internal.h | 3 +- erpc_c/port/erpc_port_stdlib.cpp | 2 + erpc_c/port/erpc_port_zephyr.cpp | 4 +- erpc_c/port/erpc_serial.cpp | 2 +- .../port/erpc_setup_extensions_freertos.cpp | 30 +- erpc_c/port/erpc_threading.h | 21 +- erpc_c/port/erpc_threading_freertos.cpp | 45 +- erpc_c/port/erpc_threading_mbed.cpp | 24 +- erpc_c/port/erpc_threading_pthreads.cpp | 24 +- erpc_c/port/erpc_threading_threadx.cpp | 27 +- erpc_c/port/erpc_threading_win32.cpp | 28 +- erpc_c/port/erpc_threading_zephyr.cpp | 42 +- erpc_c/setup/erpc_arbitrated_client_setup.cpp | 7 +- erpc_c/setup/erpc_arbitrated_client_setup.h | 3 +- erpc_c/setup/erpc_client_setup.cpp | 7 +- erpc_c/setup/erpc_mbf_setup.h | 28 +- erpc_c/setup/erpc_server_setup.cpp | 2 +- erpc_c/setup/erpc_setup_dspi_master.cpp | 43 +- erpc_c/setup/erpc_setup_dspi_slave.cpp | 43 +- erpc_c/setup/erpc_setup_i2c_slave.cpp | 42 +- erpc_c/setup/erpc_setup_lpi2c_slave.cpp | 42 +- erpc_c/setup/erpc_setup_lpspi_slave.cpp | 43 +- erpc_c/setup/erpc_setup_mbf_dynamic.cpp | 37 +- erpc_c/setup/erpc_setup_mbf_rpmsg.cpp | 52 +- erpc_c/setup/erpc_setup_mbf_rpmsg_tty.cpp | 119 -- erpc_c/setup/erpc_setup_mbf_static.cpp | 40 +- erpc_c/setup/erpc_setup_mu.cpp | 43 +- erpc_c/setup/erpc_setup_rpmsg_linux.cpp | 53 +- erpc_c/setup/erpc_setup_rpmsg_lite_master.cpp | 43 +- erpc_c/setup/erpc_setup_rpmsg_lite_remote.cpp | 44 +- .../erpc_setup_rpmsg_lite_rtos_master.cpp | 57 +- .../erpc_setup_rpmsg_lite_rtos_remote.cpp | 44 +- .../erpc_setup_rpmsg_tty_rtos_remote.cpp | 43 +- erpc_c/setup/erpc_setup_serial.cpp | 42 +- erpc_c/setup/erpc_setup_spi_master.cpp | 43 +- erpc_c/setup/erpc_setup_spi_slave.cpp | 43 +- erpc_c/setup/erpc_setup_spidev_master.cpp | 43 +- erpc_c/setup/erpc_setup_tcp.cpp | 50 +- erpc_c/setup/erpc_setup_uart_cmsis.cpp | 42 +- erpc_c/setup/erpc_setup_uart_zephyr.cpp | 39 + erpc_c/setup/erpc_setup_usb_cdc.cpp | 49 +- erpc_c/setup/erpc_transport_setup.h | 353 +++-- .../transports/erpc_dspi_master_transport.cpp | 25 +- .../transports/erpc_dspi_master_transport.hpp | 8 +- .../transports/erpc_dspi_slave_transport.cpp | 80 +- .../transports/erpc_dspi_slave_transport.hpp | 8 +- .../transports/erpc_i2c_slave_transport.cpp | 57 +- .../transports/erpc_i2c_slave_transport.hpp | 9 +- .../erpc_inter_thread_buffer_transport.hpp | 13 +- .../transports/erpc_lpi2c_slave_transport.cpp | 52 +- .../transports/erpc_lpi2c_slave_transport.hpp | 7 +- .../transports/erpc_lpspi_slave_transport.cpp | 10 +- .../transports/erpc_lpspi_slave_transport.hpp | 7 +- erpc_c/transports/erpc_mu_transport.cpp | 26 +- erpc_c/transports/erpc_mu_transport.hpp | 9 +- .../transports/erpc_rpmsg_linux_transport.cpp | 6 +- .../transports/erpc_rpmsg_linux_transport.hpp | 11 +- ...transport.hpp => erpc_rpmsg_lite_base.hpp} | 16 +- .../erpc_rpmsg_lite_rtos_transport.cpp | 45 +- .../erpc_rpmsg_lite_rtos_transport.hpp | 30 +- .../transports/erpc_rpmsg_lite_transport.cpp | 39 +- .../transports/erpc_rpmsg_lite_transport.hpp | 32 +- .../erpc_rpmsg_tty_rtos_transport.cpp | 107 +- .../erpc_rpmsg_tty_rtos_transport.hpp | 68 +- erpc_c/transports/erpc_serial_transport.cpp | 6 +- erpc_c/transports/erpc_serial_transport.hpp | 19 +- .../transports/erpc_spi_master_transport.cpp | 29 +- .../transports/erpc_spi_master_transport.hpp | 10 +- .../transports/erpc_spi_slave_transport.cpp | 77 +- .../transports/erpc_spi_slave_transport.hpp | 9 +- .../erpc_spidev_master_transport.cpp | 10 +- .../erpc_spidev_master_transport.hpp | 7 +- erpc_c/transports/erpc_tcp_transport.cpp | 159 +- erpc_c/transports/erpc_tcp_transport.hpp | 23 +- .../transports/erpc_uart_cmsis_transport.cpp | 8 +- .../transports/erpc_uart_cmsis_transport.hpp | 7 +- .../transports/erpc_uart_zephyr_transport.cpp | 208 +++ .../transports/erpc_uart_zephyr_transport.hpp | 109 ++ erpc_c/transports/erpc_usb_cdc_transport.cpp | 14 +- erpc_c/transports/erpc_usb_cdc_transport.hpp | 9 +- erpc_java/.gitignore | 39 + erpc_java/checkstyle.xml | 206 +++ erpc_java/deploy.xml | 195 +++ erpc_java/pom.xml | 129 ++ erpc_java/readme.md | 105 ++ .../embeddedrpc/erpc/auxiliary/Crc16.java | 69 + .../erpc/auxiliary/MessageInfo.java | 22 + .../erpc/auxiliary/MessageType.java | 68 + .../embeddedrpc/erpc/auxiliary/Reference.java | 49 + .../erpc/auxiliary/RequestContext.java | 21 + .../erpc/auxiliary/RequestError.java | 30 + .../embeddedrpc/erpc/auxiliary/Utils.java | 166 ++ .../erpc/client/ClientManager.java | 81 + .../embeddedrpc/erpc/codec/BasicCodec.java | 291 ++++ .../erpc/codec/BasicCodecFactory.java | 23 + .../github/embeddedrpc/erpc/codec/Codec.java | 281 ++++ .../embeddedrpc/erpc/codec/CodecError.java | 21 + .../embeddedrpc/erpc/codec/CodecFactory.java | 35 + .../embeddedrpc/erpc/server/Server.java | 99 ++ .../embeddedrpc/erpc/server/Service.java | 73 + .../embeddedrpc/erpc/server/SimpleServer.java | 66 + .../embeddedrpc/erpc/server/ThreadServer.java | 13 + .../erpc/transport/FramedTransport.java | 97 ++ .../erpc/transport/RequestError.java | 21 + .../erpc/transport/SerialTransport.java | 76 + .../erpc/transport/TCPTransport.java | 89 ++ .../embeddedrpc/erpc/transport/Transport.java | 31 + .../erpc/transport/TransportError.java | 38 + .../erpc/codec/BasicCodecTest.java | 367 +++++ .../embeddedrpc/erpc/codec/CRC16Test.java | 74 + erpc_python/erpc/erpc_version.py | 2 +- erpc_python/erpc/transport.py | 26 +- erpcgen/.gitignore | 2 +- erpcgen/Makefile | 43 +- erpcgen/VisualStudio_v14/.gitignore | 12 +- erpcgen/VisualStudio_v14/erpcgen.vcxproj | 68 +- .../VisualStudio_v14/erpcgen.vcxproj.filters | 55 +- erpcgen/VisualStudio_v14/erpcgen.vcxproj.user | 5 +- erpcgen/src/AstNode.cpp | 7 +- erpcgen/src/AstNode.hpp | 18 +- erpcgen/src/AstWalker.hpp | 5 +- erpcgen/src/CGenerator.cpp | 866 ++++++----- erpcgen/src/CGenerator.hpp | 96 +- erpcgen/src/ErpcLexer.cpp | 12 +- erpcgen/src/ErpcLexer.hpp | 10 +- erpcgen/src/Generator.cpp | 178 ++- erpcgen/src/Generator.hpp | 54 +- erpcgen/src/InterfaceDefinition.cpp | 39 +- erpcgen/src/InterfaceDefinition.hpp | 2 +- erpcgen/src/JavaGenerator.cpp | 1359 +++++++++++++++++ erpcgen/src/JavaGenerator.hpp | 340 +++++ erpcgen/src/Logging.cpp | 14 +- erpcgen/src/Logging.hpp | 20 +- erpcgen/src/ParseErrors.hpp | 50 +- erpcgen/src/PythonGenerator.cpp | 157 +- erpcgen/src/PythonGenerator.hpp | 35 +- erpcgen/src/SearchPath.hpp | 5 +- erpcgen/src/SymbolScanner.cpp | 314 ++-- erpcgen/src/SymbolScanner.hpp | 25 +- erpcgen/src/Token.cpp | 5 +- erpcgen/src/Token.hpp | 29 +- erpcgen/src/UniqueIdChecker.cpp | 10 +- erpcgen/src/UniqueIdChecker.hpp | 6 +- erpcgen/src/Value.hpp | 71 +- erpcgen/src/annotations.h | 6 +- erpcgen/src/cpptemplate/cpptempl.cpp | 333 ++-- erpcgen/src/cpptemplate/cpptempl.hpp | 2 +- erpcgen/src/erpcgen.cpp | 78 +- erpcgen/src/erpcgen_lexer.l | 2 + erpcgen/src/erpcgen_parser.y | 62 +- erpcgen/src/options.cpp | 128 +- erpcgen/src/options.hpp | 20 +- erpcgen/src/smart_ptr.hpp | 22 +- .../src/templates/c_client_header.template | 70 + .../src/templates/c_client_source.template | 239 +-- .../src/templates/c_common_header.template | 59 +- .../src/templates/c_server_header.template | 83 +- .../src/templates/c_server_source.template | 292 +--- .../src/templates/cpp_client_header.template | 36 + .../src/templates/cpp_client_source.template | 198 +++ ...{c_coders.template => cpp_coders.template} | 20 +- ...template => cpp_common_functions.template} | 49 +- .../templates/cpp_interface_header.template | 60 + .../templates/cpp_interface_source.template | 57 + .../src/templates/cpp_server_header.template | 46 + .../src/templates/cpp_server_source.template | 253 +++ erpcgen/src/templates/java_client.template | 88 ++ erpcgen/src/templates/java_coders.template | 236 +++ erpcgen/src/templates/java_const.template | 27 + erpcgen/src/templates/java_enum.template | 51 + erpcgen/src/templates/java_interface.template | 42 + erpcgen/src/templates/java_server.template | 87 ++ erpcgen/src/templates/java_struct.template | 95 ++ erpcgen/src/types/AliasType.hpp | 10 +- erpcgen/src/types/Annotation.hpp | 28 +- erpcgen/src/types/ArrayType.hpp | 6 +- erpcgen/src/types/BuiltinType.hpp | 29 +- erpcgen/src/types/ConstType.hpp | 6 +- erpcgen/src/types/DataType.hpp | 35 +- erpcgen/src/types/EnumMember.hpp | 12 +- erpcgen/src/types/EnumType.hpp | 10 +- erpcgen/src/types/Function.hpp | 49 +- erpcgen/src/types/FunctionType.hpp | 7 +- erpcgen/src/types/Group.hpp | 11 +- erpcgen/src/types/Interface.hpp | 35 +- erpcgen/src/types/ListType.hpp | 6 +- erpcgen/src/types/Program.hpp | 5 +- erpcgen/src/types/StructMember.hpp | 36 +- erpcgen/src/types/StructType.hpp | 10 +- erpcgen/src/types/Symbol.hpp | 46 +- erpcgen/src/types/SymbolScope.hpp | 7 +- erpcgen/src/types/Type.cpp | 30 +- erpcgen/src/types/UnionCase.hpp | 22 +- erpcgen/src/types/UnionType.hpp | 16 +- erpcgen/src/types/VoidType.hpp | 5 +- erpcgen/test/conftest.py | 139 +- erpcgen/test/test_builtin_types.yml | 6 +- erpcgen/test/test_comments.yml | 10 +- erpcgen/test/test_enum.yml | 12 +- erpcgen/test/test_error_checks_c.yml | 24 +- erpcgen/test/test_error_return_c.yml | 4 +- erpcgen/test/test_expressions.yml | 2 +- erpcgen/test/test_extern_c.yml | 4 +- erpcgen/test/test_forward_declaration_c.yml | 43 +- erpcgen/test/test_import.yml | 8 +- erpcgen/test/test_include.yml | 21 +- .../test/test_includes/test_includes_union.h | 7 +- erpcgen/test/test_name_c.yml | 15 +- erpcgen/test/test_nullable_c.yml | 19 +- erpcgen/test/test_redundant_definitions.yml | 36 +- erpcgen/test/test_scope_c.yml | 8 +- erpcgen/test/test_service_c.yml | 16 +- erpcgen/test/test_struct.yml | 10 +- erpcgen/test/test_types_header.yml | 33 - erpcgen/test/test_union_c.yml | 17 +- erpcsniffer/src/Sniffer.cpp | 119 +- erpcsniffer/src/Sniffer.hpp | 10 +- erpcsniffer/src/erpc_config.h | 28 +- erpcsniffer/src/erpcsniffer.cpp | 90 +- examples/matrix_multiply_java/.gitignore | 38 + examples/matrix_multiply_java/pom.xml | 68 + examples/matrix_multiply_java/readme.md | 81 + .../github/embeddedrpc/erpc/example/Main.java | 180 +++ .../erpc/example/MatrixMultiplyService.java | 35 + .../client/MatrixMultiplyServiceClient.java | 86 ++ .../common/Constants.java | 24 + .../interfaces/IMatrixMultiplyService.java | 24 + .../AbstractMatrixMultiplyServiceService.java | 89 ++ .../main/resources/erpc_matrix_multiply.erpc | 21 + .../service/__init__.py | 2 +- .../service/erpc_matrix_multiply/__init__.py | 6 +- .../service/erpc_matrix_multiply/client.py | 2 +- .../service/erpc_matrix_multiply/common.py | 2 +- .../service/erpc_matrix_multiply/interface.py | 2 +- .../service/erpc_matrix_multiply/server.py | 2 +- .../matrix_multiply_rpmsglite/CMakeLists.txt | 36 + .../zephyr/matrix_multiply_rpmsglite/Kconfig | 11 + .../Kconfig.sysbuild | 15 + .../matrix_multiply_rpmsglite/README.rst | 118 ++ .../boards/lpcxpresso54114_m4.conf | 2 + .../boards/lpcxpresso54114_m4.overlay | 21 + .../boards/lpcxpresso55s69_cpu0.conf | 1 + .../boards/lpcxpresso55s69_cpu0.overlay | 23 + .../boards/mimxrt1160_evk_cm7.conf | 2 + .../boards/mimxrt1160_evk_cm7.overlay | 24 + .../boards/mimxrt1170_evk_cm7.conf | 2 + .../boards/mimxrt1170_evk_cm7.overlay | 24 + .../boards/mimxrt1170_evkb_cm7.conf | 7 + .../boards/mimxrt1170_evkb_cm7.overlay | 24 + .../matrix_multiply_rpmsglite/erpc_config.h | 187 +++ .../zephyr/matrix_multiply_rpmsglite/prj.conf | 22 + .../remote/CMakeLists.txt | 35 + .../remote/boards/lpcxpresso54114_m0.conf | 2 + .../remote/boards/lpcxpresso54114_m0.overlay | 21 + .../remote/boards/lpcxpresso55s69_cpu1.conf | 2 + .../boards/lpcxpresso55s69_cpu1.overlay | 23 + .../remote/boards/mimxrt1160_evk_cm4.conf | 3 + .../remote/boards/mimxrt1160_evk_cm4.overlay | 51 + .../remote/boards/mimxrt1170_evk_cm4.conf | 3 + .../remote/boards/mimxrt1170_evk_cm4.overlay | 51 + .../remote/boards/mimxrt1170_evkb_cm4.conf | 8 + .../remote/boards/mimxrt1170_evkb_cm4.overlay | 51 + .../matrix_multiply_rpmsglite/remote/prj.conf | 24 + .../remote/src/erpc_error_handler.cpp | 106 ++ .../remote/src/erpc_error_handler.h | 47 + .../remote/src/main.cpp | 127 ++ .../service/c_erpc_matrix_multiply_server.cpp | 78 + .../service/c_erpc_matrix_multiply_server.h | 58 + .../src/service/erpc_matrix_multiply.erpc | 24 + .../src/service/erpc_matrix_multiply_common.h | 56 + .../service/erpc_matrix_multiply_common.hpp | 49 + .../erpc_matrix_multiply_interface.cpp | 28 + .../erpc_matrix_multiply_interface.hpp | 40 + .../service/erpc_matrix_multiply_server.cpp | 147 ++ .../service/erpc_matrix_multiply_server.hpp | 57 + .../matrix_multiply_rpmsglite/rpmsg_config.h | 86 ++ .../matrix_multiply_rpmsglite/sample.yaml | 3 + .../src/erpc_error_handler.cpp | 106 ++ .../src/erpc_error_handler.h | 47 + .../matrix_multiply_rpmsglite/src/main.cpp | 143 ++ .../service/c_erpc_matrix_multiply_client.cpp | 58 + .../service/c_erpc_matrix_multiply_client.h | 53 + .../src/service/erpc_matrix_multiply.erpc | 24 + .../service/erpc_matrix_multiply_client.cpp | 126 ++ .../service/erpc_matrix_multiply_client.hpp | 42 + .../src/service/erpc_matrix_multiply_common.h | 56 + .../service/erpc_matrix_multiply_common.hpp | 49 + .../erpc_matrix_multiply_interface.cpp | 28 + .../erpc_matrix_multiply_interface.hpp | 40 + .../matrix_multiply_rpmsglite/sysbuild.cmake | 21 + .../matrix_multiply_uart/CMakeLists.txt | 24 + .../zephyr/matrix_multiply_uart/README.rst | 106 ++ examples/zephyr/matrix_multiply_uart/prj.conf | 17 + .../zephyr/matrix_multiply_uart/sample.yaml | 3 + .../matrix_multiply_uart/src/erpc_config.h | 187 +++ .../src/erpc_error_handler.cpp | 106 ++ .../src/erpc_error_handler.h | 47 + .../zephyr/matrix_multiply_uart/src/main.cpp | 130 ++ .../service/c_erpc_matrix_multiply_server.cpp | 78 + .../service/c_erpc_matrix_multiply_server.h | 58 + .../src/service/erpc_matrix_multiply.erpc | 24 + .../src/service/erpc_matrix_multiply_common.h | 56 + .../service/erpc_matrix_multiply_common.hpp | 49 + .../erpc_matrix_multiply_interface.cpp | 28 + .../erpc_matrix_multiply_interface.hpp | 40 + .../service/erpc_matrix_multiply_server.cpp | 147 ++ .../service/erpc_matrix_multiply_server.hpp | 57 + mk/common.mk | 23 +- mk/flags.mk | 10 +- mk/targets.mk | 4 +- run_clang_format.py | 16 +- run_tests.sh | 3 +- test/common/config/erpc_config.h | 40 +- test/common/gtest/gtest.cpp | 2 + test/common/gtest/gtest.h | 2 + test/common/gtestListener.hpp | 8 +- test/common/myAlloc.hpp | 12 +- test/common/retarget_cpp_streamed_io.c | 2 +- test/common/unit_test_arbitrator_app0.cpp | 55 +- test/common/unit_test_arbitrator_app1.cpp | 63 +- test/common/unit_test_client.cpp | 17 +- test/common/unit_test_serial_client.cpp | 15 +- test/common/unit_test_serial_server.cpp | 58 +- test/common/unit_test_server.cpp | 21 +- .../unit_test_tcp_arbitrator_client.cpp | 15 +- .../unit_test_tcp_arbitrator_server.cpp | 25 +- test/common/unit_test_tcp_client.cpp | 15 +- test/common/unit_test_tcp_server.cpp | 58 +- test/common/unit_test_wrapped.h | 7 + test/java_impl_tests/.gitignore | 41 + test/java_impl_tests/pom.xml | 31 + test/java_impl_tests/readme.md | 104 ++ test/java_impl_tests/run_tests.py | 136 ++ .../embeddedrpc/erpc/tests/common/myEnum.java | 47 + .../client/CommonClient.java | 78 + .../common/Constants.java | 21 + .../interfaces/ICommon.java | 35 + .../server/AbstractCommonService.java | 67 + .../client/CommonClient.java | 77 + .../common/Constants.java | 21 + .../common/enums/enumColor.java | 57 + .../common/enums/myEnum.java | 57 + .../common/enums/numbers.java | 62 + .../interfaces/ICommon.java | 34 + .../server/AbstractCommonService.java | 66 + .../embeddedrpc/erpc/tests/Connection.java | 70 + .../embeddedrpc/erpc/tests/TestingClient.java | 28 + .../embeddedrpc/erpc/tests/TestingServer.java | 38 + .../erpc/tests/client/TestAnnotations.java | 31 + .../erpc/tests/client/TestArrays.java | 441 ++++++ .../erpc/tests/client/TestBinary.java | 55 + .../erpc/tests/client/TestBuiltin.java | 193 +++ .../erpc/tests/client/TestConst.java | 40 + .../erpc/tests/client/TestEnums.java | 111 ++ .../erpc/tests/client/TestLists.java | 274 ++++ .../erpc/tests/client/TestStruct.java | 177 +++ .../erpc/tests/client/TestTypedef.java | 103 ++ .../tests/server/TestAnnotationsServer.java | 15 + .../erpc/tests/server/TestArraysServer.java | 16 + .../erpc/tests/server/TestBinaryServer.java | 16 + .../erpc/tests/server/TestBuiltinServer.java | 16 + .../erpc/tests/server/TestConstServer.java | 16 + .../erpc/tests/server/TestEnumsServer.java | 16 + .../erpc/tests/server/TestListsServer.java | 16 + .../erpc/tests/server/TestStructServer.java | 20 + .../erpc/tests/server/TestTypedefServer.java | 18 + .../tests/server/services/CommonService.java | 17 + .../services/TestAnnotationsService.java | 28 + .../server/services/TestArraysService.java | 277 ++++ .../server/services/TestBinaryService.java | 26 + .../server/services/TestBuiltinService.java | 131 ++ .../server/services/TestConstService.java | 6 + .../server/services/TestEnumsService.java | 66 + .../server/services/TestListsService.java | 173 +++ .../server/services/TestStructService1.java | 42 + .../server/services/TestStructService2.java | 94 ++ .../server/services/TestTypedefService.java | 56 + test/mk/erpc_src.mk | 7 +- test/mk/test.mk | 21 +- test/mk/unit_test.mk | 20 +- test/python_impl_tests/README.md | 7 + test/python_impl_tests/scripts.code-workspace | 162 ++ .../scripts/common/common.py | 41 + test/python_impl_tests/scripts/conftest.py | 23 + .../scripts/server/clientTCP.py | 40 + .../scripts/server/clientUART.py | 39 + .../scripts/server/connection.py | 54 + .../scripts/server/runner.py | 67 + .../scripts/server/serverTCP.py | 52 + .../scripts/server/serverUART.py | 51 + .../scripts/service/__init__.py | 12 + .../scripts/service/test_binary/__init__.py | 0 .../scripts/service/test_builtin/__init__.py | 0 .../scripts/service/test_const/__init__.py | 0 .../scripts/service/test_enums/__init__.py | 0 .../scripts/service/test_group/__init__.py | 0 .../scripts/service/test_lists/__init__.py | 0 .../scripts/service/test_typedef/__init__.py | 0 .../scripts/service/test_unions/__init__.py | 0 .../test_annotations/test_annotations.py | 103 ++ .../scripts/test_arrays/test_arrays.py | 620 ++++++++ .../scripts/test_binary/test_binary.py | 116 ++ .../scripts/test_builtin/test_builtin.py | 343 +++++ .../scripts/test_const/test_const.py | 82 + .../scripts/test_enums/test_enums.py | 215 +++ .../scripts/test_lists/test_lists.py | 396 +++++ .../scripts/test_struct/test_struct.py | 315 ++++ .../scripts/test_typedef/test_typedef.py | 165 ++ .../scripts/test_unions/test_unions.py | 266 ++++ test/run_unit_tests.py | 41 +- test/test_annotations/external.h | 2 + test/test_annotations/test_annotations.erpc | 1 + .../test_annotations_client_impl.cpp | 8 +- .../test_annotations_server_impl.cpp | 42 +- test/test_arbitrator/client.mk | 9 +- test/test_arbitrator/config/erpc_config.h | 41 +- test/test_arbitrator/server.mk | 8 + test/test_arbitrator/test_arbitrator.erpc | 3 +- .../test_arbitrator_client_impl.cpp | 43 +- .../test_arbitrator_server_impl.cpp | 64 +- test/test_arrays/test_arrays_client_impl.cpp | 8 +- test/test_arrays/test_arrays_server_impl.cpp | 192 ++- test/test_binary/test_binary_client_impl.cpp | 8 +- test/test_binary/test_binary_server_impl.cpp | 30 +- .../test_builtin/test_builtin_client_impl.cpp | 8 +- .../test_builtin/test_builtin_server_impl.cpp | 104 +- test/test_callbacks/callbacks1.h | 11 - test/test_callbacks/callbacks2.h | 9 - test/test_callbacks/client.mk | 44 + test/test_callbacks/server.mk | 44 + test/test_callbacks/test_callbacks.erpc | 17 +- .../test_callbacks_client_impl.cpp | 9 +- .../test_callbacks_server_impl.cpp | 132 +- test/test_const/test_const_client_impl.cpp | 5 +- test/test_const/test_const_server_impl.cpp | 10 +- test/test_enums/test_enums_client_impl.cpp | 8 +- test/test_enums/test_enums_server_impl.cpp | 61 +- test/test_lists/test_lists_client_impl.cpp | 12 +- test/test_lists/test_lists_server_impl.cpp | 121 +- test/test_shared/test_shared_client_impl.cpp | 12 +- test/test_shared/test_shared_server_impl.cpp | 30 +- test/test_struct/test_struct_client_impl.cpp | 9 +- test/test_struct/test_struct_java.erpc | 152 ++ test/test_struct/test_struct_server_impl.cpp | 144 +- .../test_typedef/test_typedef_client_impl.cpp | 8 +- .../test_typedef/test_typedef_server_impl.cpp | 68 +- test/test_unions/test_unions_client_impl.cpp | 8 +- test/test_unions/test_unions_server_impl.cpp | 88 +- zephyr/CMakeLists.txt | 74 + zephyr/Kconfig | 45 + zephyr/module.yml | 6 + zephyr/readme.md | 63 + 488 files changed, 24439 insertions(+), 4147 deletions(-) create mode 100644 .clang-format-ignore create mode 100644 erpc_c/infra/erpc_utils.cpp create mode 100644 erpc_c/infra/erpc_utils.hpp delete mode 100644 erpc_c/setup/erpc_setup_mbf_rpmsg_tty.cpp create mode 100644 erpc_c/setup/erpc_setup_uart_zephyr.cpp rename erpc_c/transports/{erpc_rpmsg_lite_base_transport.hpp => erpc_rpmsg_lite_base.hpp} (87%) mode change 100755 => 100644 create mode 100644 erpc_c/transports/erpc_uart_zephyr_transport.cpp create mode 100644 erpc_c/transports/erpc_uart_zephyr_transport.hpp create mode 100644 erpc_java/.gitignore create mode 100644 erpc_java/checkstyle.xml create mode 100644 erpc_java/deploy.xml create mode 100644 erpc_java/pom.xml create mode 100644 erpc_java/readme.md create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Crc16.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageInfo.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageType.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Reference.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestContext.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestError.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Utils.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/client/ClientManager.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodec.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodecFactory.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/Codec.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecError.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecFactory.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Server.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Service.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/SimpleServer.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/ThreadServer.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/FramedTransport.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/RequestError.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/SerialTransport.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TCPTransport.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/Transport.java create mode 100644 erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TransportError.java create mode 100644 erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/BasicCodecTest.java create mode 100644 erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/CRC16Test.java create mode 100644 erpcgen/src/JavaGenerator.cpp create mode 100644 erpcgen/src/JavaGenerator.hpp create mode 100644 erpcgen/src/templates/c_client_header.template create mode 100644 erpcgen/src/templates/cpp_client_header.template create mode 100644 erpcgen/src/templates/cpp_client_source.template rename erpcgen/src/templates/{c_coders.template => cpp_coders.template} (92%) rename erpcgen/src/templates/{c_common_functions.template => cpp_common_functions.template} (95%) create mode 100644 erpcgen/src/templates/cpp_interface_header.template create mode 100644 erpcgen/src/templates/cpp_interface_source.template create mode 100644 erpcgen/src/templates/cpp_server_header.template create mode 100644 erpcgen/src/templates/cpp_server_source.template create mode 100644 erpcgen/src/templates/java_client.template create mode 100644 erpcgen/src/templates/java_coders.template create mode 100644 erpcgen/src/templates/java_const.template create mode 100644 erpcgen/src/templates/java_enum.template create mode 100644 erpcgen/src/templates/java_interface.template create mode 100644 erpcgen/src/templates/java_server.template create mode 100644 erpcgen/src/templates/java_struct.template delete mode 100644 erpcgen/test/test_types_header.yml create mode 100644 examples/matrix_multiply_java/.gitignore create mode 100644 examples/matrix_multiply_java/pom.xml create mode 100644 examples/matrix_multiply_java/readme.md create mode 100644 examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/Main.java create mode 100644 examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/MatrixMultiplyService.java create mode 100644 examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/client/MatrixMultiplyServiceClient.java create mode 100644 examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/common/Constants.java create mode 100644 examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/interfaces/IMatrixMultiplyService.java create mode 100644 examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/server/AbstractMatrixMultiplyServiceService.java create mode 100644 examples/matrix_multiply_java/src/main/resources/erpc_matrix_multiply.erpc create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/CMakeLists.txt create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/Kconfig create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/Kconfig.sysbuild create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/README.rst create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/erpc_config.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/prj.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/CMakeLists.txt create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.overlay create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/prj.conf create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/main.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply.erpc create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.hpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.hpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.hpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/rpmsg_config.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/sample.yaml create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/main.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply.erpc create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.hpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.h create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.hpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.cpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.hpp create mode 100644 examples/zephyr/matrix_multiply_rpmsglite/sysbuild.cmake create mode 100644 examples/zephyr/matrix_multiply_uart/CMakeLists.txt create mode 100644 examples/zephyr/matrix_multiply_uart/README.rst create mode 100644 examples/zephyr/matrix_multiply_uart/prj.conf create mode 100644 examples/zephyr/matrix_multiply_uart/sample.yaml create mode 100644 examples/zephyr/matrix_multiply_uart/src/erpc_config.h create mode 100644 examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.cpp create mode 100644 examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.h create mode 100644 examples/zephyr/matrix_multiply_uart/src/main.cpp create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.cpp create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.h create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply.erpc create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.h create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.hpp create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.cpp create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.hpp create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.cpp create mode 100644 examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.hpp create mode 100644 test/java_impl_tests/.gitignore create mode 100644 test/java_impl_tests/pom.xml create mode 100644 test/java_impl_tests/readme.md create mode 100644 test/java_impl_tests/run_tests.py create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/common/myEnum.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/client/CommonClient.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/common/Constants.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/interfaces/ICommon.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/server/AbstractCommonService.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/client/CommonClient.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/Constants.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/enumColor.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/myEnum.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/numbers.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/interfaces/ICommon.java create mode 100644 test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/server/AbstractCommonService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/Connection.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingClient.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestAnnotations.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestArrays.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBinary.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBuiltin.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestConst.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestEnums.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestLists.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestStruct.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestTypedef.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestAnnotationsServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestArraysServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBinaryServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBuiltinServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestConstServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestEnumsServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestListsServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestStructServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestTypedefServer.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/CommonService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestAnnotationsService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestArraysService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBinaryService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBuiltinService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestConstService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestEnumsService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestListsService.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService1.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService2.java create mode 100644 test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestTypedefService.java create mode 100644 test/python_impl_tests/README.md create mode 100644 test/python_impl_tests/scripts.code-workspace create mode 100644 test/python_impl_tests/scripts/common/common.py create mode 100644 test/python_impl_tests/scripts/conftest.py create mode 100644 test/python_impl_tests/scripts/server/clientTCP.py create mode 100644 test/python_impl_tests/scripts/server/clientUART.py create mode 100644 test/python_impl_tests/scripts/server/connection.py create mode 100644 test/python_impl_tests/scripts/server/runner.py create mode 100644 test/python_impl_tests/scripts/server/serverTCP.py create mode 100644 test/python_impl_tests/scripts/server/serverUART.py create mode 100644 test/python_impl_tests/scripts/service/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_binary/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_builtin/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_const/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_enums/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_group/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_lists/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_typedef/__init__.py create mode 100644 test/python_impl_tests/scripts/service/test_unions/__init__.py create mode 100644 test/python_impl_tests/scripts/test_annotations/test_annotations.py create mode 100644 test/python_impl_tests/scripts/test_arrays/test_arrays.py create mode 100644 test/python_impl_tests/scripts/test_binary/test_binary.py create mode 100644 test/python_impl_tests/scripts/test_builtin/test_builtin.py create mode 100644 test/python_impl_tests/scripts/test_const/test_const.py create mode 100644 test/python_impl_tests/scripts/test_enums/test_enums.py create mode 100644 test/python_impl_tests/scripts/test_lists/test_lists.py create mode 100644 test/python_impl_tests/scripts/test_struct/test_struct.py create mode 100644 test/python_impl_tests/scripts/test_typedef/test_typedef.py create mode 100644 test/python_impl_tests/scripts/test_unions/test_unions.py delete mode 100644 test/test_callbacks/callbacks1.h delete mode 100644 test/test_callbacks/callbacks2.h create mode 100644 test/test_callbacks/client.mk create mode 100644 test/test_callbacks/server.mk create mode 100644 test/test_struct/test_struct_java.erpc create mode 100644 zephyr/CMakeLists.txt create mode 100644 zephyr/Kconfig create mode 100644 zephyr/module.yml create mode 100644 zephyr/readme.md diff --git a/.circleci/config.yml b/.circleci/config.yml index d37ef48a..d714b6b7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,45 +3,69 @@ version: 2.1 orbs: win: circleci/windows@5.0 # The Windows orb gives you everything you need to start using the +commands: + install_dependencies: + parameters: + compiler: + default: "" + type: string + steps: + - run: chmod u+x install_dependencies.sh && ./install_dependencies.sh <> + run_tests: + parameters: + compiler: + default: "" + type: string + steps: + - run: chmod u+x run_tests.sh && ./run_tests.sh <> + jobs: build-linux-gcc: machine: image: ubuntu-2204:2022.04.2 #https://circleci.com/developer/machine/image/ubuntu-2204 pick LTS steps: - checkout - - run: chmod u+x install_dependencies.sh && ./install_dependencies.sh - - run: chmod u+x run_tests.sh && ./run_tests.sh + - install_dependencies + - run_tests - store_artifacts: path: ./Release/Linux/erpcgen/erpcgen + build-linux-clang: machine: image: ubuntu-2204:2022.04.2 #https://circleci.com/developer/machine/image/ubuntu-2204 pick LTS steps: - checkout - - run: chmod u+x install_dependencies.sh && ./install_dependencies.sh clang - - run: chmod u+x run_tests.sh && ./run_tests.sh clang + - install_dependencies: + compiler: "clang" + - run_tests: + compiler: "clang" # - store_artifacts: # path: ./Release/Linux/erpcgen/erpcgen + build-mac-gcc: macos: xcode: 12.5.1 # https://circleci.com/docs/using-macos/#supported-xcode-versions https://en.wikipedia.org/wiki/MacOS_version_history#Releases - resource_class: medium + resource_class: macos.x86.medium.gen2 steps: - checkout - - run: chmod u+x install_dependencies.sh && ./install_dependencies.sh - - run: chmod u+x run_tests.sh && ./run_tests.sh + - install_dependencies + - run_tests - store_artifacts: path: ./Release/Darwin/erpcgen/erpcgen + build-mac-clang: macos: xcode: 12.5.1 # https://circleci.com/docs/using-macos/#supported-xcode-versions https://en.wikipedia.org/wiki/MacOS_version_history#Releases - resource_class: medium + resource_class: macos.x86.medium.gen2 steps: - checkout - - run: chmod u+x install_dependencies.sh && ./install_dependencies.sh clang - - run: chmod u+x run_tests.sh && ./run_tests.sh clang + - install_dependencies: + compiler: "clang" + - run_tests: + compiler: "clang" # - store_artifacts: # path: ./Release/Darwin/erpcgen/erpcgen + build-windows-mingw: executor: name: win/default @@ -49,9 +73,11 @@ jobs: steps: - checkout - run: powershell.exe .\install_dependencies.ps1 - - run: powershell.exe .\mingw64\bin\mingw32-make erpcgen + - run: .\mingw64\bin\mingw32-make all + - run: .\mingw64\opt\bin\python3.exe .\test\run_unit_tests.py -m"..\\..\\mingw64\\bin\\mingw32-make" # - store_artifacts: # path: ./Release/MINGW64/erpcgen/erpcgen.exe + build-windows-VS: executor: name: win/default @@ -65,6 +91,7 @@ jobs: - run: powershell.exe "& 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe' .\erpcgen\VisualStudio_v14\erpcgen.sln /property:Configuration=Release" - store_artifacts: path: ./erpcgen/VisualStudio_v14/Release/erpcgen.exe + workflows: build-workflow: jobs: diff --git a/.clang-format b/.clang-format index eeed4bea..6cec9388 100644 --- a/.clang-format +++ b/.clang-format @@ -1,15 +1,17 @@ -#https://releases.llvm.org/5.0.2/tools/clang/docs/ClangFormatStyleOptions.html -AlignTrailingComments: true +#https://releases.llvm.org/16.0.0/tools/clang/docs/ClangFormatStyleOptions.html +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortFunctionsOnASingleLine: "Inline" -AllowShortIfStatementsOnASingleLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false AlwaysBreakBeforeMultilineStrings: true -BasedOnStyle: "Google" +BasedOnStyle: Google #BinPackParameters : false -BreakBeforeBinaryOperators: false -BreakBeforeBraces: "Custom" +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom BreakBeforeTernaryOperators: false ColumnLimit: 120 ContinuationIndentWidth: 4 @@ -18,54 +20,61 @@ DisableFormat: false IndentCaseLabels: true IndentWrappedFunctionNames: false IndentWidth: 4 -Language: "Cpp" +Language: Cpp MaxEmptyLinesToKeep: 1 -PointerBindsToType: false SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: "ControlStatements" +SpaceBeforeParens: ControlStatements SpacesBeforeTrailingComments: 1 SpacesInCStyleCastParentheses: false SpacesInParentheses: false -Standard: "Cpp03" +Standard: c++11 TabWidth: 1 -UseTab: "Never" +UseTab: Never AccessModifierOffset: -4 -AlignAfterOpenBracket: "Align" -AlignEscapedNewlines: "Left" -AlignOperands: true +AlignAfterOpenBracket: Align +AlignEscapedNewlines: Left +AlignOperands: Align AllowShortCaseLabelsOnASingleLine: false -AlwaysBreakAfterReturnType: "None" -AlwaysBreakTemplateDeclarations: true -BreakBeforeInheritanceComma: false -BreakConstructorInitializers: "BeforeComma" +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: Yes +BreakInheritanceList: AfterColon +BreakConstructorInitializers: AfterColon CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 0 Cpp11BracedListStyle: false FixNamespaceComments: true -NamespaceIndentation: "None" -PointerAlignment: "Right" -SortIncludes: true -SortUsingDeclarations: true -SpacesInAngles: false +NamespaceIndentation: None +PointerAlignment: Right +SortIncludes: Never +SortUsingDeclarations: Lexicographic +SpacesInAngles: Never SpaceAfterCStyleCast: false SpaceInEmptyParentheses: false SpacesInSquareBrackets: false KeepEmptyLinesAtTheStartOfBlocks: true BraceWrapping: + AfterCaseLabel: true AfterClass: true - AfterControlStatement: true + AfterControlStatement: Always AfterEnum: true AfterFunction: true AfterNamespace: false AfterObjCDeclaration: true AfterStruct: true AfterUnion: true + AfterExternBlock: false BeforeCatch: true BeforeElse: true -#IncludeBlocks: "Preserve" # for future version of clang + BeforeWhile: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true + +IncludeBlocks: Preserve IncludeCategories: - Regex: "^<" # system includes Priority: 10 - Regex: '^"erpc_' # erpc public includes Priority: 1 +CommentPragmas: "#" diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 00000000..d103944b --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1,9 @@ +#list of ignored files to format +./erpc_c/port/erpc_serial.cpp +./erpcgen/src/cpptemplate/cpptempl.hpp +./erpcgen/src/cpptemplate/cpptempl.cpp +./erpcgen/src/cpptemplate/cpptempl_test.cpp +./erpcgen/test/test_includes/test_includes_union.h +./test/common/gtest/gtest.h +./test/common/gtest/gtest.cpp +./test/common/retarget_cpp_streamed_io.c diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 8c7729ba..f5be8afe 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -1,15 +1,14 @@ name: clang-format lint -on: [push] +on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: DoozyX/clang-format-lint-action@v0.10 + - uses: actions/checkout@v4 + - uses: DoozyX/clang-format-lint-action@v0.16.2 with: - source: '.' - exclude: 'test/common/gtest/gtest.h test/common/gtest/gtest.cpp erpcgen/src/cpptemplate/cpptempl.h erpcgen/src/cpptemplate/cpptempl.cpp erpcgen/src/cpptemplate/cpptempl_test.cpp' - clangFormatVersion: 10 + source: '.' + clangFormatVersion: 16 diff --git a/LICENSE b/LICENSE index cfe35768..062e8f37 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ Copyright 2014-2016 Freescale Semiconductor, Inc. -Copyright 2016-2023 NXP +Copyright 2016-2024 NXP All rights reserved. The BSD 3 Clause License diff --git a/README.md b/README.md index 40cd0260..eb913c22 100644 --- a/README.md +++ b/README.md @@ -246,9 +246,9 @@ To install the Python infrastructure for eRPC see instructions in the [erpc_pyth ## Code providing -Repository on Github contains two main branches. __Master__ and __develop__. Code is developed on __develop__ branch. Release version is created via merging __develop__ branch into __master__ branch. +Repository on Github contains two main branches: __main__ and __develop__. Code is developed on __develop__ branch. Release version is created via merging __develop__ branch into __main__ branch. --- Copyright 2014-2016 Freescale Semiconductor, Inc. -Copyright 2016-2023 NXP +Copyright 2016-2024 NXP diff --git a/doxygen/Doxyfile.erpc b/doxygen/Doxyfile.erpc index cb3003e4..f56fb310 100644 --- a/doxygen/Doxyfile.erpc +++ b/doxygen/Doxyfile.erpc @@ -38,7 +38,7 @@ PROJECT_NAME = "eRPC API Reference" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "Rev. 1.11.0" +PROJECT_NUMBER = "Rev. 1.12.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doxygen/Doxyfile.erpcgen b/doxygen/Doxyfile.erpcgen index 97ff2321..77190978 100644 --- a/doxygen/Doxyfile.erpcgen +++ b/doxygen/Doxyfile.erpcgen @@ -38,7 +38,7 @@ PROJECT_NAME = "eRPC Generator (erpcgen)" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "Rev. 1.11.0" +PROJECT_NUMBER = "Rev. 1.12.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/erpc_c/Makefile b/erpc_c/Makefile index 9ad45d15..71957b44 100644 --- a/erpc_c/Makefile +++ b/erpc_c/Makefile @@ -60,10 +60,10 @@ SOURCES += $(ERPC_C_ROOT)/infra/erpc_arbitrated_client_manager.cpp \ $(ERPC_C_ROOT)/infra/erpc_server.cpp \ $(ERPC_C_ROOT)/infra/erpc_simple_server.cpp \ $(ERPC_C_ROOT)/infra/erpc_transport_arbitrator.cpp \ + $(ERPC_C_ROOT)/infra/erpc_utils.cpp \ $(ERPC_C_ROOT)/infra/erpc_pre_post_action.cpp \ $(ERPC_C_ROOT)/port/erpc_port_stdlib.cpp \ $(ERPC_C_ROOT)/port/erpc_threading_pthreads.cpp \ - $(ERPC_C_ROOT)/port/erpc_serial.cpp \ $(ERPC_C_ROOT)/setup/erpc_arbitrated_client_setup.cpp \ $(ERPC_C_ROOT)/setup/erpc_client_setup.cpp \ $(ERPC_C_ROOT)/setup/erpc_setup_mbf_dynamic.cpp \ @@ -72,8 +72,11 @@ SOURCES += $(ERPC_C_ROOT)/infra/erpc_arbitrated_client_manager.cpp \ $(ERPC_C_ROOT)/setup/erpc_setup_serial.cpp \ $(ERPC_C_ROOT)/setup/erpc_setup_tcp.cpp \ $(ERPC_C_ROOT)/transports/erpc_inter_thread_buffer_transport.cpp \ - $(ERPC_C_ROOT)/transports/erpc_serial_transport.cpp \ $(ERPC_C_ROOT)/transports/erpc_tcp_transport.cpp +ifeq "$(is_mingw)" "" + SOURCES += $(ERPC_C_ROOT)/transports/erpc_serial_transport.cpp \ + $(ERPC_C_ROOT)/port/erpc_serial.cpp +endif HEADERS += $(ERPC_C_ROOT)/config/erpc_config.h \ $(ERPC_C_ROOT)/infra/erpc_arbitrated_client_manager.hpp \ @@ -91,6 +94,7 @@ HEADERS += $(ERPC_C_ROOT)/config/erpc_config.h \ $(ERPC_C_ROOT)/infra/erpc_static_queue.hpp \ $(ERPC_C_ROOT)/infra/erpc_transport_arbitrator.hpp \ $(ERPC_C_ROOT)/infra/erpc_transport.hpp \ + $(ERPC_C_ROOT)/infra/erpc_utils.hpp \ $(ERPC_C_ROOT)/infra/erpc_client_server_common.hpp \ $(ERPC_C_ROOT)/infra/erpc_pre_post_action.h \ $(ERPC_C_ROOT)/port/erpc_setup_extensions.h \ diff --git a/erpc_c/infra/erpc_arbitrated_client_manager.cpp b/erpc_c/infra/erpc_arbitrated_client_manager.cpp index 7338189f..f46682a7 100644 --- a/erpc_c/infra/erpc_arbitrated_client_manager.cpp +++ b/erpc_c/infra/erpc_arbitrated_client_manager.cpp @@ -9,6 +9,7 @@ */ #include "erpc_arbitrated_client_manager.hpp" + #include "erpc_transport_arbitrator.hpp" #if ERPC_THREADS_IS(NONE) @@ -73,7 +74,7 @@ void ArbitratedClientManager::performClientRequest(RequestContext &request) // Send the request. if (request.getCodec()->isStatusOk() == true) { - err = m_arbitrator->send(request.getCodec()->getBuffer()); + err = m_arbitrator->send(&request.getCodec()->getBufferRef()); request.getCodec()->updateStatus(err); } diff --git a/erpc_c/infra/erpc_arbitrated_client_manager.hpp b/erpc_c/infra/erpc_arbitrated_client_manager.hpp index fa2e45a1..dc271345 100644 --- a/erpc_c/infra/erpc_arbitrated_client_manager.hpp +++ b/erpc_c/infra/erpc_arbitrated_client_manager.hpp @@ -45,11 +45,7 @@ class ArbitratedClientManager : public ClientManager * * This function initializes object attributes. */ - ArbitratedClientManager(void) - : ClientManager() - , m_arbitrator(NULL) - { - } + ArbitratedClientManager(void) : ClientManager(), m_arbitrator(NULL) {} /*! * @brief Sets the transport arbitrator instance. diff --git a/erpc_c/infra/erpc_basic_codec.cpp b/erpc_c/infra/erpc_basic_codec.cpp index a1ee9ccc..6bdb68e3 100644 --- a/erpc_c/infra/erpc_basic_codec.cpp +++ b/erpc_c/infra/erpc_basic_codec.cpp @@ -27,6 +27,10 @@ using namespace erpc; const uint32_t BasicCodec::kBasicCodecVersion = 1UL; +BasicCodec::BasicCodec(void) : Codec() {} + +BasicCodec::~BasicCodec(void) {} + void BasicCodec::startWriteMessage(message_type_t type, uint32_t service, uint32_t request, uint32_t sequence) { uint32_t header = @@ -158,38 +162,7 @@ void BasicCodec::startWriteUnion(int32_t discriminator) void BasicCodec::writeNullFlag(bool isNull) { - write(static_cast(isNull ? kIsNull : kNotNull)); -} - -void BasicCodec::writeCallback(arrayOfFunPtr callbacks, uint8_t callbacksCount, funPtr callback) -{ - uint8_t i; - - erpc_assert(callbacksCount > 1U); - - // callbacks = callbacks table - for (i = 0; i < callbacksCount; i++) - { - if (callbacks[i] == callback) - { - write(i); - break; - } - if ((i + 1U) == callbacksCount) - { - updateStatus(kErpcStatus_UnknownCallback); - } - } -} - -void BasicCodec::writeCallback(funPtr callback1, funPtr callback2) -{ - // callbacks = callback directly - // When declared only one callback function no serialization is needed. - if (callback1 != callback2) - { - updateStatus(kErpcStatus_UnknownCallback); - } + write(static_cast(isNull ? null_flag_t::kIsNull : null_flag_t::kNotNull)); } void BasicCodec::startReadMessage(message_type_t &type, uint32_t &service, uint32_t &request, uint32_t &sequence) @@ -392,39 +365,15 @@ void BasicCodec::readNullFlag(bool &isNull) read(flag); if (isStatusOk()) { - isNull = (flag == (uint8_t)kIsNull); + isNull = (flag == static_cast(null_flag_t::kIsNull)); } } -void BasicCodec::readCallback(arrayOfFunPtr callbacks, uint8_t callbacksCount, funPtr *callback) -{ - uint8_t _tmp_local; - - erpc_assert(callbacksCount > 1U); - - // callbacks = callbacks table - read(_tmp_local); - if (isStatusOk()) - { - if (_tmp_local < callbacksCount) - { - *callback = callbacks[_tmp_local]; - } - else - { - *callback = NULL; - m_status = kErpcStatus_UnknownCallback; - } - } -} +ERPC_MANUALLY_CONSTRUCTED_ARRAY_STATIC(BasicCodec, s_basicCodecManual, ERPC_CODEC_COUNT); -void BasicCodec::readCallback(funPtr callbacks1, funPtr *callback2) -{ - // callbacks = callback directly - *callback2 = callbacks1; -} +BasicCodecFactory::BasicCodecFactory(void) : CodecFactory() {} -ERPC_MANUALLY_CONSTRUCTED_ARRAY_STATIC(BasicCodec, s_basicCodecManual, ERPC_CODEC_COUNT); +BasicCodecFactory::~BasicCodecFactory(void) {} Codec *BasicCodecFactory::create(void) { diff --git a/erpc_c/infra/erpc_basic_codec.hpp b/erpc_c/infra/erpc_basic_codec.hpp index 581f6c7c..3dc0faa9 100644 --- a/erpc_c/infra/erpc_basic_codec.hpp +++ b/erpc_c/infra/erpc_basic_codec.hpp @@ -27,7 +27,7 @@ namespace erpc { /*! * @brief Values of the uint8 flag prefixing nullable values. */ -enum _null_flag +enum class null_flag_t { kNotNull = 0, kIsNull @@ -43,10 +43,15 @@ class BasicCodec : public Codec public: static const uint32_t kBasicCodecVersion; /*!< Codec version. */ - BasicCodec(void) - : Codec() - { - } + /*! + * @brief Constructor. + */ + BasicCodec(void); + + /*! + * @brief CodecFactory destructor + */ + virtual ~BasicCodec(void); //! @name Encoding //@{ @@ -189,23 +194,6 @@ class BasicCodec : public Codec * @param[in] isNull Null flag to send. */ virtual void writeNullFlag(bool isNull) override; - - /*! - * @brief Writes an order ID of callback function. - * - * @param[in] callbacks Pointer to array of callbacks. - * @param[in] callbacksCount Size of array of callbacks. - * @param[in] callback Callback which ID should be serialized. - */ - virtual void writeCallback(arrayOfFunPtr callbacks, uint8_t callbacksCount, funPtr callback) override; - - /*! - * @brief Writes an order ID of callback function. - * - * @param[in] callback1 Pointer to existing callback. - * @param[out] callback2 Callback which ID should be serialized. - */ - virtual void writeCallback(funPtr callback1, funPtr callback2) override; //@} //! @name Decoding @@ -350,23 +338,6 @@ class BasicCodec : public Codec * @param[in] isNull Null flag to read. */ virtual void readNullFlag(bool &isNull) override; - - /*! - * @brief Read an callback function id and return address of callback function. - * - * @param[in] callbacks Pointer to array of callbacks. - * @param[in] callbacksCount Size of array of callbacks. - * @param[out] callback Callback which is deserialized. Null in case of error. - */ - virtual void readCallback(arrayOfFunPtr callbacks, uint8_t callbacksCount, funPtr *callback) override; - - /*! - * @brief Read an callback function id and return address of callback function. - * - * @param[in] callback1 Pointer to existing callback. - * @param[out] callback2 Callback which is deserialized. - */ - virtual void readCallback(funPtr callbacks1, funPtr *callback2) override; //@} }; @@ -378,6 +349,16 @@ class BasicCodec : public Codec class BasicCodecFactory : public CodecFactory { public: + /*! + * @brief Constructor. + */ + BasicCodecFactory(void); + + /*! + * @brief CodecFactory destructor + */ + virtual ~BasicCodecFactory(void); + /*! * @brief Return created codec. * diff --git a/erpc_c/infra/erpc_client_manager.cpp b/erpc_c/infra/erpc_client_manager.cpp index c13a6c05..ef064b3d 100644 --- a/erpc_c/infra/erpc_client_manager.cpp +++ b/erpc_c/infra/erpc_client_manager.cpp @@ -78,7 +78,7 @@ void ClientManager::performClientRequest(RequestContext &request) // Send invocation request to server. if (request.getCodec()->isStatusOk() == true) { - err = m_transport->send(request.getCodec()->getBuffer()); + err = m_transport->send(&request.getCodec()->getBufferRef()); request.getCodec()->updateStatus(err); } @@ -88,7 +88,7 @@ void ClientManager::performClientRequest(RequestContext &request) if (request.getCodec()->isStatusOk() == true) { // Receive reply. - err = m_transport->receive(request.getCodec()->getBuffer()); + err = m_transport->receive(&request.getCodec()->getBufferRef()); request.getCodec()->updateStatus(err); } @@ -126,7 +126,7 @@ void ClientManager::performNestedClientRequest(RequestContext &request) // Send invocation request to server. if (request.getCodec()->isStatusOk() == true) { - err = m_transport->send(request.getCodec()->getBuffer()); + err = m_transport->send(&request.getCodec()->getBufferRef()); request.getCodec()->updateStatus(err); } @@ -167,7 +167,7 @@ void ClientManager::verifyReply(RequestContext &request) // Some transport layers change the request's message buffer pointer (for things like zero // copy support), so inCodec must be reset to work with correct buffer. - request.getCodec()->reset(); + request.getCodec()->reset(m_transport->reserveHeaderSize()); // Extract the reply header. request.getCodec()->startReadMessage(msgType, service, requestNumber, sequence); @@ -175,7 +175,7 @@ void ClientManager::verifyReply(RequestContext &request) if (request.getCodec()->isStatusOk() == true) { // Verify that this is a reply to the request we just sent. - if ((msgType != kReplyMessage) || (sequence != request.getSequence())) + if ((msgType != message_type_t::kReplyMessage) || (sequence != request.getSequence())) { request.getCodec()->updateStatus(kErpcStatus_ExpectedReply); } @@ -186,13 +186,14 @@ Codec *ClientManager::createBufferAndCodec(void) { Codec *codec = m_codecFactory->create(); MessageBuffer message; + uint8_t reservedMessageSpace = m_transport->reserveHeaderSize(); if (codec != NULL) { - message = m_messageFactory->create(); + message = m_messageFactory->create(reservedMessageSpace); if (NULL != message.get()) { - codec->setBuffer(message); + codec->setBuffer(message, reservedMessageSpace); } else { @@ -209,7 +210,7 @@ void ClientManager::releaseRequest(RequestContext &request) { if (request.getCodec() != NULL) { - m_messageFactory->dispose(request.getCodec()->getBuffer()); + m_messageFactory->dispose(&request.getCodec()->getBufferRef()); m_codecFactory->dispose(request.getCodec()); } } diff --git a/erpc_c/infra/erpc_client_manager.h b/erpc_c/infra/erpc_client_manager.h index 8544fb99..63a8bd12 100644 --- a/erpc_c/infra/erpc_client_manager.h +++ b/erpc_c/infra/erpc_client_manager.h @@ -25,6 +25,8 @@ */ extern "C" { +#else +#include "erpc_common.h" #endif typedef void (*client_error_handler_t)(erpc_status_t err, @@ -59,13 +61,11 @@ class ClientManager : public ClientServerCommon * * This function initializes object attributes. */ - ClientManager(void) - : ClientServerCommon() - , m_sequence(0) - , m_errorHandler(NULL) + ClientManager(void) : + ClientServerCommon(), m_sequence(0), m_errorHandler(NULL) #if ERPC_NESTED_CALLS - , m_server(NULL) - , m_serverThreadId(NULL) + , + m_server(NULL), m_serverThreadId(NULL) #endif { } @@ -130,8 +130,8 @@ class ClientManager : public ClientServerCommon #endif protected: - uint32_t m_sequence; //!< Sequence number. - client_error_handler_t m_errorHandler; //!< Pointer to function error handler. + uint32_t m_sequence; //!< Sequence number. + client_error_handler_t m_errorHandler; //!< Pointer to function error handler. #if ERPC_NESTED_CALLS Server *m_server; //!< Server used for nested calls. Thread::thread_id_t m_serverThreadId; //!< Thread in which server run function is called. @@ -193,10 +193,8 @@ class RequestContext * @param[in] codec Set in inout codec. * @param[in] isOneway Set information if codec is only oneway or bidirectional. */ - RequestContext(uint32_t sequence, Codec *codec, bool argIsOneway) - : m_sequence(sequence) - , m_codec(codec) - , m_oneway(argIsOneway) + RequestContext(uint32_t sequence, Codec *codec, bool argIsOneway) : + m_sequence(sequence), m_codec(codec), m_oneway(argIsOneway) { } diff --git a/erpc_c/infra/erpc_client_server_common.hpp b/erpc_c/infra/erpc_client_server_common.hpp index 0c172461..159d3d8e 100644 --- a/erpc_c/infra/erpc_client_server_common.hpp +++ b/erpc_c/infra/erpc_client_server_common.hpp @@ -10,8 +10,8 @@ #ifndef _EMBEDDED_RPC__CLIENTSERVERCOMMON_H_ #define _EMBEDDED_RPC__CLIENTSERVERCOMMON_H_ -#include "erpc_config_internal.h" #include "erpc_codec.hpp" +#include "erpc_config_internal.h" #if ERPC_MESSAGE_LOGGING #include "erpc_message_loggers.hpp" #endif @@ -100,21 +100,21 @@ class ClientServerCommon * * @param[in] factory Message buffer factory to use. */ - void setMessageBufferFactory(MessageBufferFactory *factory) { m_messageFactory = factory; } + void setMessageBufferFactory(MessageBufferFactory * factory) { m_messageFactory = factory; } /*! * @brief This function sets codec factory to use. * * @param[in] factory Codec factory to use. */ - void setCodecFactory(CodecFactory *factory) { m_codecFactory = factory; } + void setCodecFactory(CodecFactory * factory) { m_codecFactory = factory; } /*! * @brief This function sets codec factory to use. * * @return CodecFactory * Codec factory to use. */ - CodecFactory * getCodecFactory(void) { return m_codecFactory; } + CodecFactory *getCodecFactory(void) { return m_codecFactory; } /*! * @brief This function sets transport layer to use. @@ -123,14 +123,14 @@ class ClientServerCommon * * @param[in] transport Transport layer to use. */ - void setTransport(Transport *transport) { m_transport = transport; } + void setTransport(Transport * transport) { m_transport = transport; } /*! * @brief This function gets transport instance. * * @return Transport * Pointer to transport instance. */ - Transport * getTransport(void) { return m_transport; } + Transport *getTransport(void) { return m_transport; } protected: MessageBufferFactory *m_messageFactory; //!< Message buffer factory to use. diff --git a/erpc_c/infra/erpc_codec.hpp b/erpc_c/infra/erpc_codec.hpp index 02ac7395..763cb377 100644 --- a/erpc_c/infra/erpc_codec.hpp +++ b/erpc_c/infra/erpc_codec.hpp @@ -15,8 +15,8 @@ #include "erpc_message_buffer.hpp" #include "erpc_transport.hpp" +#include #include -#include /*! * @addtogroup infra_codec @@ -32,13 +32,13 @@ namespace erpc { /*! * @brief Types of messages that can be encoded. */ -typedef enum _message_type +enum class message_type_t { kInvocationMessage = 0, kOnewayMessage, kReplyMessage, kNotificationMessage -} message_type_t; +}; typedef void *funPtr; // Pointer to functions typedef funPtr *arrayOfFunPtr; // Pointer to array of functions @@ -58,12 +58,7 @@ class Codec * * This function initializes object attributes. */ - Codec(void) - : m_buffer() - , m_cursor() - , m_status(kErpcStatus_Success) - { - } + Codec(void) : m_cursor(), m_status(kErpcStatus_Success) {} /*! * @brief Codec destructor @@ -75,24 +70,31 @@ class Codec * * @return Pointer to used message buffer. */ - MessageBuffer *getBuffer(void) { return &m_buffer; } + MessageBuffer getBuffer(void) { return m_cursor.getBuffer(); } + + MessageBuffer &getBufferRef(void) { return m_cursor.getBufferRef(); } /*! * @brief Prototype for set message buffer used for read and write data. * * @param[in] buf Message buffer to set. + * @param[in] skip How many bytes to skip from reading. */ - virtual void setBuffer(MessageBuffer &buf) + virtual void setBuffer(MessageBuffer &buf, uint8_t skip = 0) { - m_buffer = buf; - m_cursor.set(&m_buffer); + m_cursor.setBuffer(buf, skip); m_status = kErpcStatus_Success; } - /*! @brief Reset the codec to initial state. */ - virtual void reset(void) + /*! + * @brief Reset the codec to initial state. + * + * @param[in] skip How many bytes to skip from reading. + */ + virtual void reset(uint8_t skip = 0) { - m_cursor.set(&m_buffer); + MessageBuffer buffer = m_cursor.getBuffer(); + m_cursor.setBuffer(buffer, skip); m_status = kErpcStatus_Success; } @@ -257,23 +259,6 @@ class Codec * @param[in] isNull Null flag to send. */ virtual void writeNullFlag(bool isNull) = 0; - - /*! - * @brief Writes an order ID of callback function. - * - * @param[in] callbacks Pointer to array of callbacks. - * @param[in] callbacksCount Size of array of callbacks. - * @param[in] callback Callback which ID should be serialized. - */ - virtual void writeCallback(arrayOfFunPtr callbacks, uint8_t callbacksCount, funPtr callback) = 0; - - /*! - * @brief Writes an order ID of callback function. - * - * @param[in] callback1 Pointer to existing callback. - * @param[out] callback2 Callback which ID should be serialized. - */ - virtual void writeCallback(funPtr callback1, funPtr callback2) = 0; //@} //! @name Decoding @@ -410,27 +395,9 @@ class Codec */ virtual void readNullFlag(bool &isNull) = 0; - /*! - * @brief Read an callback function id and return address of callback function. - * - * @param[in] callbacks Pointer to array of callbacks. - * @param[in] callbacksCount Size of array of callbacks. - * @param[out] callback Callback which is deserialized. Null in case of error. - */ - virtual void readCallback(arrayOfFunPtr callbacks, uint8_t callbacksCount, funPtr *callback) = 0; - - /*! - * @brief Read an callback function id and return address of callback function. - * - * @param[in] callback1 Pointer to existing callback. - * @param[out] callback2 Callback which is deserialized. - */ - virtual void readCallback(funPtr callbacks1, funPtr *callback2) = 0; - protected: - MessageBuffer m_buffer; /*!< Message buffer object */ - MessageBuffer::Cursor m_cursor; /*!< Copy data to message buffers. */ - erpc_status_t m_status; /*!< Status of serialized data. */ + Cursor m_cursor; /*!< Copy data to message buffers. */ + erpc_status_t m_status; /*!< Status of serialized data. */ }; /*! diff --git a/erpc_c/infra/erpc_crc16.cpp b/erpc_c/infra/erpc_crc16.cpp index 8408a12e..ebaf498b 100644 --- a/erpc_c/infra/erpc_crc16.cpp +++ b/erpc_c/infra/erpc_crc16.cpp @@ -15,15 +15,9 @@ using namespace erpc; // Code //////////////////////////////////////////////////////////////////////////////// -Crc16::Crc16(uint32_t crcStart) -: m_crcStart(crcStart) -{ -} +Crc16::Crc16(uint32_t crcStart) : m_crcStart(crcStart) {} -Crc16::Crc16(void) -: m_crcStart(0xEF4A) -{ -} +Crc16::Crc16(void) : m_crcStart(0xEF4A) {} Crc16::~Crc16(void) {} diff --git a/erpc_c/infra/erpc_framed_transport.cpp b/erpc_c/infra/erpc_framed_transport.cpp index a27dfb05..9e1a002e 100644 --- a/erpc_c/infra/erpc_framed_transport.cpp +++ b/erpc_c/infra/erpc_framed_transport.cpp @@ -22,18 +22,23 @@ using namespace erpc; // Code //////////////////////////////////////////////////////////////////////////////// -FramedTransport::FramedTransport(void) -: Transport() -, m_crcImpl(NULL) +FramedTransport::FramedTransport(void) : +Transport(), m_crcImpl(NULL) #if !ERPC_THREADS_IS(NONE) -, m_sendLock() -, m_receiveLock() +, +m_sendLock(), m_receiveLock() #endif { } FramedTransport::~FramedTransport(void) {} +uint8_t FramedTransport::reserveHeaderSize(void) +{ + return sizeof(FramedTransport::Header::m_crcHeader) + sizeof(FramedTransport::Header::m_messageSize) + + sizeof(FramedTransport::Header::m_crcBody); +} + void FramedTransport::setCrc16(Crc16 *crcImpl) { erpc_assert(crcImpl); @@ -47,36 +52,57 @@ Crc16 *FramedTransport::getCrc16(void) erpc_status_t FramedTransport::receive(MessageBuffer *message) { - Header h; + Header h = { 0, 0, 0 }; erpc_status_t retVal; uint16_t computedCrc; + uint8_t offset = 0; erpc_assert((m_crcImpl != NULL) && ("Uninitialized Crc16 object." != NULL)); + // e.g. rpmsg tty may have nullptr and buffer is assigned in receive function. + if ((message->get() != nullptr) && (message->getLength() < reserveHeaderSize())) + { + retVal = kErpcStatus_MemoryError; + } + else { #if !ERPC_THREADS_IS(NONE) Mutex::Guard lock(m_receiveLock); #endif // Receive header first. - retVal = underlyingReceive((uint8_t *)&h, sizeof(h)); + retVal = underlyingReceive(message, reserveHeaderSize(), 0); + if ((retVal == kErpcStatus_Success) && (message->getLength() < reserveHeaderSize())) + { + retVal = kErpcStatus_MemoryError; + } if (retVal == kErpcStatus_Success) { + static_cast(memcpy(&h.m_crcHeader, message->get(), sizeof(h.m_crcHeader))); + offset = sizeof(h.m_crcHeader); + static_cast(memcpy(&h.m_messageSize, &message->get()[offset], sizeof(h.m_messageSize))); + offset += sizeof(h.m_messageSize); + static_cast(memcpy(&h.m_crcBody, &message->get()[offset], sizeof(h.m_crcBody))); + offset += sizeof(h.m_crcBody); + + ERPC_READ_AGNOSTIC_16(h.m_crcHeader); ERPC_READ_AGNOSTIC_16(h.m_messageSize); - ERPC_READ_AGNOSTIC_16(h.m_crc); + ERPC_READ_AGNOSTIC_16(h.m_crcBody); - // received size can't be zero. - if (h.m_messageSize == 0U) + computedCrc = + m_crcImpl->computeCRC16(reinterpret_cast(&h.m_messageSize), sizeof(h.m_messageSize)) + + m_crcImpl->computeCRC16(reinterpret_cast(&h.m_crcBody), sizeof(h.m_crcBody)); + if (computedCrc != h.m_crcHeader) { - retVal = kErpcStatus_ReceiveFailed; + retVal = kErpcStatus_CrcCheckFailed; } } if (retVal == kErpcStatus_Success) { // received size can't be larger then buffer length. - if (h.m_messageSize > message->getLength()) + if ((h.m_messageSize + reserveHeaderSize()) > message->getLength()) { retVal = kErpcStatus_ReceiveFailed; } @@ -84,20 +110,20 @@ erpc_status_t FramedTransport::receive(MessageBuffer *message) if (retVal == kErpcStatus_Success) { - // Receive rest of the message now we know its size. - retVal = underlyingReceive(message->get(), h.m_messageSize); + // rpmsg tty can receive all data in one buffer, others need second call. + if (message->getUsed() < (h.m_messageSize + reserveHeaderSize())) + { + // Receive rest of the message now we know its size. + retVal = underlyingReceive(message, h.m_messageSize, offset); + } } } if (retVal == kErpcStatus_Success) { // Verify CRC. - computedCrc = m_crcImpl->computeCRC16(message->get(), h.m_messageSize); - if (computedCrc == h.m_crc) - { - message->setUsed(h.m_messageSize); - } - else + computedCrc = m_crcImpl->computeCRC16(&message->get()[offset], h.m_messageSize); + if (computedCrc != h.m_crcBody) { retVal = kErpcStatus_CrcCheckFailed; } @@ -111,27 +137,51 @@ erpc_status_t FramedTransport::send(MessageBuffer *message) erpc_status_t ret; uint16_t messageLength; Header h; + uint8_t offset; erpc_assert((m_crcImpl != NULL) && ("Uninitialized Crc16 object." != NULL)); -#if !ERPC_THREADS_IS(NONE) - Mutex::Guard lock(m_sendLock); -#endif - - messageLength = message->getUsed(); + messageLength = message->getUsed() - reserveHeaderSize(); // Send header first. h.m_messageSize = messageLength; - h.m_crc = m_crcImpl->computeCRC16(message->get(), messageLength); + h.m_crcBody = m_crcImpl->computeCRC16(&message->get()[reserveHeaderSize()], messageLength); + h.m_crcHeader = + m_crcImpl->computeCRC16(reinterpret_cast(&h.m_messageSize), sizeof(h.m_messageSize)) + + m_crcImpl->computeCRC16(reinterpret_cast(&h.m_crcBody), sizeof(h.m_crcBody)); + ERPC_WRITE_AGNOSTIC_16(h.m_crcHeader); ERPC_WRITE_AGNOSTIC_16(h.m_messageSize); - ERPC_WRITE_AGNOSTIC_16(h.m_crc); + ERPC_WRITE_AGNOSTIC_16(h.m_crcBody); - ret = underlyingSend((uint8_t *)&h, sizeof(h)); - if (ret == kErpcStatus_Success) + static_cast(memcpy(message->get(), reinterpret_cast(&h.m_crcHeader), sizeof(h.m_crcHeader))); + offset = sizeof(h.m_crcHeader); + static_cast( + memcpy(&message->get()[offset], reinterpret_cast(&h.m_messageSize), sizeof(h.m_messageSize))); + offset += sizeof(h.m_messageSize); + static_cast( + memcpy(&message->get()[offset], reinterpret_cast(&h.m_crcBody), sizeof(h.m_crcBody))); + + ret = underlyingSend(message, message->getUsed(), 0); + + return ret; +} + +erpc_status_t FramedTransport::underlyingSend(MessageBuffer *message, uint32_t size, uint32_t offset) +{ + erpc_status_t retVal = underlyingSend(&message->get()[offset], size); + + return retVal; +} + +erpc_status_t FramedTransport::underlyingReceive(MessageBuffer *message, uint32_t size, uint32_t offset) +{ + erpc_status_t retVal = underlyingReceive(&message->get()[offset], size); + + if (retVal == kErpcStatus_Success) { - ret = underlyingSend(message->get(), messageLength); + message->setUsed(size + offset); } - return ret; + return retVal; } diff --git a/erpc_c/infra/erpc_framed_transport.hpp b/erpc_c/infra/erpc_framed_transport.hpp index dac35770..443f1cf4 100644 --- a/erpc_c/infra/erpc_framed_transport.hpp +++ b/erpc_c/infra/erpc_framed_transport.hpp @@ -56,6 +56,14 @@ namespace erpc { class FramedTransport : public Transport { public: + /*! @brief Contents of the header that prefixes each message. */ + struct Header + { + uint16_t m_crcHeader; //!< CRC-16 over this header structure data + uint16_t m_messageSize; //!< Size in bytes of the message, excluding the header. + uint16_t m_crcBody; //!< CRC-16 over the message data. + }; + /*! * @brief Constructor. */ @@ -66,6 +74,13 @@ class FramedTransport : public Transport */ virtual ~FramedTransport(void); + /** + * @brief Size of data placed in MessageBuffer before serializing eRPC data. + * + * @return uint8_t Amount of bytes, reserved before serialized data. + */ + virtual uint8_t reserveHeaderSize(void) override; + /*! * @brief Receives an entire message. * @@ -95,13 +110,6 @@ class FramedTransport : public Transport */ virtual erpc_status_t send(MessageBuffer *message) override; - /*! @brief Contents of the header that prefixes each message. */ - struct Header - { - uint16_t m_messageSize; //!< Size in bytes of the message, excluding the header. - uint16_t m_crc; //!< CRC-16 over the message data. - }; - /*! * @brief This functions sets the CRC-16 implementation. * @@ -114,7 +122,7 @@ class FramedTransport : public Transport * * @return Crc16* Pointer to CRC-16 object containing crc-16 compute function. */ - virtual Crc16 *getCrc16() override; + virtual Crc16 *getCrc16(void) override; protected: Crc16 *m_crcImpl; /*!< CRC object. */ @@ -124,6 +132,32 @@ class FramedTransport : public Transport Mutex m_receiveLock; //!< Mutex protecting receive. #endif + /*! + * @brief Adds ability to framed transport to overwrite MessageBuffer when sending data. + * + * Usually we don't want to do that. + * + * @param message MessageBuffer to send. + * @param size size of message to send. + * @param offset data start address offset + * + * @return erpc_status_t kErpcStatus_Success when it finished successful otherwise error. + */ + virtual erpc_status_t underlyingSend(MessageBuffer *message, uint32_t size, uint32_t offset); + + /*! + * @brief Adds ability to framed transport to overwrite MessageBuffer when receiving data. + * + * Usually we don't want to do that. + * + * @param message MessageBuffer to send. + * @param size size of message to send. + * @param offset data start address offset + * + * @return erpc_status_t kErpcStatus_Success when it finished successful otherwise error. + */ + virtual erpc_status_t underlyingReceive(MessageBuffer *message, uint32_t size, uint32_t offset); + /*! * @brief Subclasses must implement this function to send data. * diff --git a/erpc_c/infra/erpc_manually_constructed.hpp b/erpc_c/infra/erpc_manually_constructed.hpp index 119c4a02..de4f9f7e 100644 --- a/erpc_c/infra/erpc_manually_constructed.hpp +++ b/erpc_c/infra/erpc_manually_constructed.hpp @@ -161,7 +161,7 @@ class ManuallyConstructed * @brief Returns information if object is free or is used. * * @return true Object is constructed and used. - * @return false Object wasn't constructer or it is destructed and free. + * @return false Object wasn't constructed or it was destructed already. */ bool isUsed(void) { return m_isConstructed; } diff --git a/erpc_c/infra/erpc_message_buffer.cpp b/erpc_c/infra/erpc_message_buffer.cpp index 8c2cfc90..0d959058 100644 --- a/erpc_c/infra/erpc_message_buffer.cpp +++ b/erpc_c/infra/erpc_message_buffer.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -9,6 +9,7 @@ */ #include "erpc_message_buffer.hpp" + #include "erpc_config_internal.h" #include @@ -20,6 +21,13 @@ using namespace std; // Code //////////////////////////////////////////////////////////////////////////////// +MessageBuffer::MessageBuffer(const MessageBuffer &buffer) +{ + m_buf = buffer.m_buf; + m_len = buffer.m_len; + m_used = buffer.m_used; +} + void MessageBuffer::setUsed(uint16_t used) { erpc_assert(used <= m_len); @@ -100,70 +108,84 @@ void MessageBuffer::swap(MessageBuffer *other) m_buf = temp.m_buf; } -void MessageBuffer::Cursor::set(MessageBuffer *buffer) +void Cursor::setBuffer(MessageBuffer &buffer, uint8_t reserved) { - erpc_assert(buffer != NULL); - - m_buffer = buffer; // RPMSG when nested calls are enabled can set NULL buffer. // erpc_assert(buffer->get() && "Data buffer wasn't set to MessageBuffer."); // receive function should return err if it couldn't set data buffer. - m_pos = buffer->get(); + + // erpc_assert(buffer != NULL); + + m_buffer = buffer; + if (buffer != NULL) + { + m_pos = buffer.get() + reserved; + } } -uint8_t &MessageBuffer::Cursor::operator[](int index) +MessageBuffer Cursor::getBuffer(void) { - erpc_assert(((m_pos + index) >= m_buffer->get()) && - ((uint16_t)(m_pos - m_buffer->get()) + index <= m_buffer->getLength())); + return m_buffer; +} + +MessageBuffer &Cursor::getBufferRef(void) +{ + return m_buffer; +} + +uint8_t &Cursor::operator[](int index) +{ + erpc_assert(((m_pos + index) >= m_buffer.get()) && + ((uint16_t)(m_pos - m_buffer.get()) + index <= m_buffer.getLength())); return m_pos[index]; } -const uint8_t &MessageBuffer::Cursor::operator[](int index) const +const uint8_t &Cursor::operator[](int index) const { - erpc_assert(((m_pos + index) >= m_buffer->get()) && - ((uint16_t)(m_pos - m_buffer->get()) + index <= m_buffer->getLength())); + erpc_assert(((m_pos + index) >= m_buffer.get()) && + ((uint16_t)(m_pos - m_buffer.get()) + index <= m_buffer.getLength())); return m_pos[index]; } -MessageBuffer::Cursor &MessageBuffer::Cursor::operator+=(uint16_t n) +Cursor &Cursor::operator+=(uint16_t n) { - erpc_assert((uint32_t)(m_pos - m_buffer->get()) + n <= m_buffer->getLength()); + erpc_assert((uint32_t)(m_pos - m_buffer.get()) + n <= m_buffer.getLength()); m_pos += n; return *this; } -MessageBuffer::Cursor &MessageBuffer::Cursor::operator-=(uint16_t n) +Cursor &Cursor::operator-=(uint16_t n) { - erpc_assert(((uintptr_t)m_pos >= n) && (m_pos - n) >= m_buffer->get()); + erpc_assert(((uintptr_t)m_pos >= n) && (m_pos - n) >= m_buffer.get()); m_pos -= n; return *this; } -MessageBuffer::Cursor &MessageBuffer::Cursor::operator++(void) +Cursor &Cursor::operator++(void) { - erpc_assert((uint16_t)(m_pos - m_buffer->get()) < m_buffer->getLength()); + erpc_assert((uint16_t)(m_pos - m_buffer.get()) < m_buffer.getLength()); ++m_pos; return *this; } -MessageBuffer::Cursor &MessageBuffer::Cursor::operator--(void) +Cursor &Cursor::operator--(void) { - erpc_assert(m_pos > m_buffer->get()); + erpc_assert(m_pos > m_buffer.get()); --m_pos; return *this; } -erpc_status_t MessageBuffer::Cursor::read(void *data, uint32_t length) +erpc_status_t Cursor::read(void *data, uint32_t length) { erpc_assert((m_pos != NULL) && ("Data buffer wasn't set to MessageBuffer." != NULL)); @@ -193,10 +215,10 @@ erpc_status_t MessageBuffer::Cursor::read(void *data, uint32_t length) return err; } -erpc_status_t MessageBuffer::Cursor::write(const void *data, uint32_t length) +erpc_status_t Cursor::write(const void *data, uint32_t length) { erpc_assert((m_pos != NULL) && ("Data buffer wasn't set to MessageBuffer." != NULL)); - erpc_assert(m_pos == (m_buffer->get() + m_buffer->getUsed())); + erpc_assert(m_pos == (m_buffer.get() + m_buffer.getUsed())); erpc_status_t err = kErpcStatus_Success; @@ -214,15 +236,33 @@ erpc_status_t MessageBuffer::Cursor::write(const void *data, uint32_t length) { (void)memcpy(m_pos, data, length); m_pos += length; - m_buffer->setUsed(m_buffer->getUsed() + length); + m_buffer.setUsed(m_buffer.getUsed() + length); } } return err; } -erpc_status_t MessageBufferFactory::prepareServerBufferForSend(MessageBuffer *message) +MessageBufferFactory::MessageBufferFactory(void) {} + +MessageBufferFactory::~MessageBufferFactory(void) {} + +MessageBuffer MessageBufferFactory::create(uint8_t reserveHeaderSize) +{ + MessageBuffer messageBuffer = create(); + + messageBuffer.setUsed(reserveHeaderSize); + + return messageBuffer; +} + +bool MessageBufferFactory::createServerBuffer(void) +{ + return true; +} + +erpc_status_t MessageBufferFactory::prepareServerBufferForSend(MessageBuffer &message, uint8_t reserveHeaderSize) { - message->setUsed(0); + message.setUsed(reserveHeaderSize); return kErpcStatus_Success; } diff --git a/erpc_c/infra/erpc_message_buffer.hpp b/erpc_c/infra/erpc_message_buffer.hpp index bfd67edd..f70bafa9 100644 --- a/erpc_c/infra/erpc_message_buffer.hpp +++ b/erpc_c/infra/erpc_message_buffer.hpp @@ -42,12 +42,7 @@ class MessageBuffer * * This function initializes object attributes. */ - MessageBuffer(void) - : m_buf(NULL) - , m_len(0) - , m_used(0) - { - } + MessageBuffer(void) : m_buf(NULL), m_len(0), m_used(0) {} /*! * @brief Constructor. @@ -57,12 +52,9 @@ class MessageBuffer * @param[in] buffer Pointer to buffer. * @param[in] length Length of buffer. */ - MessageBuffer(uint8_t *buffer, uint16_t length) - : m_buf(buffer) - , m_len(length) - , m_used(0) - { - } + MessageBuffer(uint8_t *buffer, uint16_t length) : m_buf(buffer), m_len(length), m_used(0) {} + + MessageBuffer(const MessageBuffer &buffer); /*! * @brief This function set new buffer and his length. @@ -183,164 +175,167 @@ class MessageBuffer */ const uint8_t &operator[](int index) const { return m_buf[index]; } - /*! - * @brief Cursor within a MessageBuffer. - */ - class Cursor - { - public: - /*! - * @brief Constructor. - * - * This function initializes object attributes. - */ - Cursor(void) - : m_buffer(NULL) - , m_pos(NULL) - { - } - - /*! - * @brief Constructor. - * - * This function initializes object attributes. - * - * @param[in] buffer MessageBuffer for sending/receiving. - */ - explicit Cursor(MessageBuffer *buffer) - : m_buffer(buffer) - , m_pos(buffer->get()) - { - } - - /*! - * @brief Set message buffer. - * - * @param[in] buffer Message buffer to set. - */ - void set(MessageBuffer *buffer); - - /*! - * @brief Return position in buffer. - * - * Return position, where it last write/read. - * - * @return Return position in buffer. - */ - uint8_t *get(void) { return m_pos; } - - /*! - * @brief Return position in buffer. - * - * Return position, where it last write/read. - * - * @return Return position in buffer. - */ - const uint8_t *get(void) const { return m_pos; } - - /*! - * @brief Return remaining free space in current buffer. - * - * @return Remaining free space in current buffer. - */ - uint16_t getRemaining(void) const { return m_buffer->getLength() - (uint16_t)(m_pos - m_buffer->get()); } - - /*! - * @brief Return remaining space from used of current buffer. - * - * @return Remaining space from used of current buffer. - */ - uint16_t getRemainingUsed(void) const { return m_buffer->getUsed() - (uint16_t)(m_pos - m_buffer->get()); } - - /*! - * @brief Read data from current buffer. - * - * @param[out] data Pointer to value, where copy read data. - * @param[in] length How much bytes need be read. - * - * @retval kErpcStatus_Success - * @retval kErpcStatus_BufferOverrun - */ - erpc_status_t read(void *data, uint32_t length); - - /*! - * @brief Read data from current buffer. - * - * @param[out] data Pointer to value to be sent. - * @param[in] length How much bytes need be wrote. - * - * @retval kErpcStatus_Success - * @retval kErpcStatus_BufferOverrun - */ - erpc_status_t write(const void *data, uint32_t length); - - /*! - * @brief Casting operator return local buffer. - */ - operator uint8_t *(void) { return m_pos; } - - /*! - * @brief Casting operator return local buffer. - */ - operator const uint8_t *(void) const { return m_pos; } - - /*! - * @brief Array operator return value of buffer at given index. - * - * @param[in] index Index in buffer. - */ - uint8_t &operator[](int index); - - /*! - * @brief Array operator return value of buffer at given index. - * - * @param[in] index Index in buffer. - */ - const uint8_t &operator[](int index) const; - - /*! - * @brief Sum operator return local buffer. - * - * @param[in] n Summing with n. - * - * @return Current cursor instance. - */ - Cursor &operator+=(uint16_t n); - - /*! - * @brief Substract operator return local buffer. - * - * @param[in] n Substracting with n. - * - * @return Current cursor instance. - */ - Cursor &operator-=(uint16_t n); - - /*! - * @brief Sum +1 operator. - * - * @return Current cursor instance. - */ - Cursor &operator++(void); - - /*! - * @brief Substract -1 operator. - * - * @return Current cursor instance. - */ - Cursor &operator--(void); - - private: - MessageBuffer *m_buffer; /*!< Buffer for reading or writing data. */ - uint8_t *m_pos; /*!< Position in buffer, where it last write/read */ - }; - private: uint8_t *volatile m_buf; /*!< Buffer used to read write data. */ uint16_t volatile m_len; /*!< Length of buffer. */ uint16_t volatile m_used; /*!< Used buffer bytes. */ }; +/*! + * @brief Cursor within a MessageBuffer. + */ +class Cursor +{ +public: + /*! + * @brief Constructor. + * + * This function initializes object attributes. + */ + Cursor(void) : m_buffer(), m_pos(NULL) {} + + /*! + * @brief Constructor. + * + * This function initializes object attributes. + * + * @param[in] buffer MessageBuffer for sending/receiving. + */ + explicit Cursor(MessageBuffer &buffer) : m_buffer(buffer), m_pos(buffer.get()) {} + + /*! + * @brief Set message buffer. + * + * @param[in] buffer Message buffer to set. + * @param[in] reserved Moved cursor position outside of reserved memory. + */ + void setBuffer(MessageBuffer &buffer, uint8_t reserved = 0); + + /*! + * @brief Get message buffer. + */ + MessageBuffer getBuffer(void); + + /*! + * @brief Get message buffer. + */ + MessageBuffer &getBufferRef(void); + + /*! + * @brief Return position in buffer. + * + * Return position, where it last write/read. + * + * @return Return position in buffer. + */ + uint8_t *get(void) { return m_pos; } + + /*! + * @brief Return position in buffer. + * + * Return position, where it last write/read. + * + * @return Return position in buffer. + */ + const uint8_t *get(void) const { return m_pos; } + + /*! + * @brief Return remaining free space in current buffer. + * + * @return Remaining free space in current buffer. + */ + uint16_t getRemaining(void) const { return m_buffer.getLength() - (uint16_t)(m_pos - m_buffer.get()); } + + /*! + * @brief Return remaining space from used of current buffer. + * + * @return Remaining space from used of current buffer. + */ + uint16_t getRemainingUsed(void) const { return m_buffer.getUsed() - (uint16_t)(m_pos - m_buffer.get()); } + + /*! + * @brief Read data from current buffer. + * + * @param[out] data Pointer to value, where copy read data. + * @param[in] length How much bytes need be read. + * + * @retval kErpcStatus_Success + * @retval kErpcStatus_BufferOverrun + */ + erpc_status_t read(void *data, uint32_t length); + + /*! + * @brief Read data from current buffer. + * + * @param[out] data Pointer to value to be sent. + * @param[in] length How much bytes need be wrote. + * + * @retval kErpcStatus_Success + * @retval kErpcStatus_BufferOverrun + */ + erpc_status_t write(const void *data, uint32_t length); + + /*! + * @brief Casting operator return local buffer. + */ + operator uint8_t *(void) { return m_pos; } + + /*! + * @brief Casting operator return local buffer. + */ + operator const uint8_t *(void) const { return m_pos; } + + /*! + * @brief Array operator return value of buffer at given index. + * + * @param[in] index Index in buffer. + */ + uint8_t &operator[](int index); + + /*! + * @brief Array operator return value of buffer at given index. + * + * @param[in] index Index in buffer. + */ + const uint8_t &operator[](int index) const; + + /*! + * @brief Sum operator return local buffer. + * + * @param[in] n Summing with n. + * + * @return Current cursor instance. + */ + Cursor &operator+=(uint16_t n); + + /*! + * @brief Subtract operator return local buffer. + * + * @param[in] n Subtracting with n. + * + * @return Current cursor instance. + */ + Cursor &operator-=(uint16_t n); + + /*! + * @brief Sum +1 operator. + * + * @return Current cursor instance. + */ + Cursor &operator++(void); + + /*! + * @brief Subtract -1 operator. + * + * @return Current cursor instance. + */ + Cursor &operator--(void); + +private: + MessageBuffer m_buffer; /*!< Buffer for reading or writing data. */ + uint8_t *m_pos; /*!< Position in buffer, where it last write/read */ +}; + /*! * @brief Abstract interface for message buffer factory. * @@ -354,12 +349,12 @@ class MessageBufferFactory * * This function initializes object attributes. */ - MessageBufferFactory(void) {} + MessageBufferFactory(void); /*! * @brief MessageBufferFactory destructor */ - virtual ~MessageBufferFactory(void) {} + virtual ~MessageBufferFactory(void); /*! * @brief This function creates new message buffer. @@ -368,12 +363,23 @@ class MessageBufferFactory */ virtual MessageBuffer create(void) = 0; + /*! + * @brief This function creates new message buffer with reserved bytes at the beginning + * + * Reserved bytes can be used by transport to write transport related header file data. + * + * @param[in] reserveHeaderSize Reserved amount of bytes at the beginning of message buffer. + * + * @return New created MessageBuffer. + */ + MessageBuffer create(uint8_t reserveHeaderSize); + /*! * @brief This function informs server if it has to create buffer for received message. * * @return Has to return TRUE when server need create buffer for receiving message. */ - virtual bool createServerBuffer(void) { return true; } + virtual bool createServerBuffer(void); /*! * @brief This function is preparing output buffer on server side. @@ -382,8 +388,9 @@ class MessageBufferFactory * In case of using new buffer function has to free given buffer. * * @param[in] message MessageBuffer which can be reused. + * @param[in] reserveHeaderSize Reserved amount of bytes at the beginning of message buffer. */ - virtual erpc_status_t prepareServerBufferForSend(MessageBuffer *message); + virtual erpc_status_t prepareServerBufferForSend(MessageBuffer &message, uint8_t reserveHeaderSize = 0); /*! * @brief This function disposes message buffer. diff --git a/erpc_c/infra/erpc_message_loggers.hpp b/erpc_c/infra/erpc_message_loggers.hpp index a060d163..7d259abe 100644 --- a/erpc_c/infra/erpc_message_loggers.hpp +++ b/erpc_c/infra/erpc_message_loggers.hpp @@ -34,9 +34,7 @@ class MessageLogger /*! * @brief MessageLogger constructor. */ - explicit MessageLogger(Transport *transport) - : m_next(NULL) - , m_transport(transport){}; + explicit MessageLogger(Transport *transport) : m_next(NULL), m_transport(transport){}; /*! * @brief MessageLogger destructor @@ -80,13 +78,12 @@ class MessageLoggers /*! * @brief Constructor. */ - MessageLoggers(void) - : m_logger(NULL){}; + MessageLoggers(void) : m_logger(NULL){}; /*! * @brief Transport destructor */ - virtual ~MessageLoggers(void); + ~MessageLoggers(void); /*! * @brief This function add given transport to newly created MessageLogger object. diff --git a/erpc_c/infra/erpc_pre_post_action.h b/erpc_c/infra/erpc_pre_post_action.h index f38a0be9..3f8574e1 100644 --- a/erpc_c/infra/erpc_pre_post_action.h +++ b/erpc_c/infra/erpc_pre_post_action.h @@ -42,9 +42,7 @@ class PrePostAction /*! * @brief PrePostAction constructor. */ - PrePostAction(void) - : m_preCB(NULL) - , m_postCB(NULL){}; + PrePostAction(void) : m_preCB(NULL), m_postCB(NULL){}; /*! * @brief This function sets "before eRPC call start" callback function. diff --git a/erpc_c/infra/erpc_server.cpp b/erpc_c/infra/erpc_server.cpp index 3dd19d15..0a2d558e 100644 --- a/erpc_c/infra/erpc_server.cpp +++ b/erpc_c/infra/erpc_server.cpp @@ -75,7 +75,7 @@ erpc_status_t Server::processMessage(Codec *codec, message_type_t msgType, uint3 erpc_status_t err = kErpcStatus_Success; Service *service; - if ((msgType != kInvocationMessage) && (msgType != kOnewayMessage)) + if ((msgType != message_type_t::kInvocationMessage) && (msgType != message_type_t::kOnewayMessage)) { err = kErpcStatus_InvalidArgument; } @@ -91,7 +91,7 @@ erpc_status_t Server::processMessage(Codec *codec, message_type_t msgType, uint3 if (err == kErpcStatus_Success) { - err = service->handleInvocation(methodId, sequence, codec, m_messageFactory); + err = service->handleInvocation(methodId, sequence, codec, m_messageFactory, m_transport); } return err; diff --git a/erpc_c/infra/erpc_server.hpp b/erpc_c/infra/erpc_server.hpp index ea0ea203..b7ec3f24 100644 --- a/erpc_c/infra/erpc_server.hpp +++ b/erpc_c/infra/erpc_server.hpp @@ -44,11 +44,7 @@ class Service * * This function initializes object attributes. */ - Service(uint32_t serviceId) - : m_serviceId(serviceId) - , m_next(NULL) - { - } + Service(uint32_t serviceId) : m_serviceId(serviceId), m_next(NULL) {} /*! * @brief Service destructor @@ -87,7 +83,7 @@ class Service * @return Based on handleInvocation implementation. */ virtual erpc_status_t handleInvocation(uint32_t methodId, uint32_t sequence, Codec *codec, - MessageBufferFactory *messageFactory) = 0; + MessageBufferFactory *messageFactory, Transport *transport) = 0; protected: uint32_t m_serviceId; /*!< Service unique id. */ @@ -107,11 +103,7 @@ class Server : public ClientServerCommon * * This function initializes object attributes. */ - Server(void) - : ClientServerCommon() - , m_firstService(NULL) - { - } + Server(void) : ClientServerCommon(), m_firstService(NULL) {} /*! * @brief Server destructor diff --git a/erpc_c/infra/erpc_simple_server.cpp b/erpc_c/infra/erpc_simple_server.cpp index ac97e9cc..58738707 100644 --- a/erpc_c/infra/erpc_simple_server.cpp +++ b/erpc_c/infra/erpc_simple_server.cpp @@ -15,17 +15,46 @@ using namespace erpc; //////////////////////////////////////////////////////////////////////////////// // Code //////////////////////////////////////////////////////////////////////////////// +SimpleServer::SimpleServer(void) : m_isServerOn(true) {} -void SimpleServer::disposeBufferAndCodec(Codec *codec) +SimpleServer::~SimpleServer(void) {} + +erpc_status_t SimpleServer::run(void) { - if (codec != NULL) + erpc_status_t err = kErpcStatus_Success; + while ((err == kErpcStatus_Success) && m_isServerOn) { - if (codec->getBuffer() != NULL) + err = runInternal(); + } + return err; +} + +erpc_status_t SimpleServer::poll(void) +{ + erpc_status_t err; + + if (m_isServerOn) + { + if (m_transport->hasMessage() == true) { - m_messageFactory->dispose(codec->getBuffer()); + err = runInternal(); } - m_codecFactory->dispose(codec); + else + { + err = kErpcStatus_Success; + } + } + else + { + err = kErpcStatus_ServerIsDown; } + + return err; +} + +void SimpleServer::stop(void) +{ + m_isServerOn = false; } erpc_status_t SimpleServer::runInternal(void) @@ -103,7 +132,7 @@ erpc_status_t SimpleServer::runInternalBegin(Codec **codec, MessageBuffer &buff, if (err == kErpcStatus_Success) { - (*codec)->setBuffer(buff); + (*codec)->setBuffer(buff, m_transport->reserveHeaderSize()); err = readHeadOfMessage(*codec, msgType, serviceId, methodId, sequence); if (err != kErpcStatus_Success) @@ -123,14 +152,14 @@ erpc_status_t SimpleServer::runInternalEnd(Codec *codec, message_type_t msgType, if (err == kErpcStatus_Success) { - if (msgType != kOnewayMessage) + if (msgType != message_type_t::kOnewayMessage) { #if ERPC_MESSAGE_LOGGING err = logMessage(codec->getBuffer()); if (err == kErpcStatus_Success) { #endif - err = m_transport->send(codec->getBuffer()); + err = m_transport->send(&codec->getBufferRef()); #if ERPC_MESSAGE_LOGGING } #endif @@ -151,16 +180,6 @@ erpc_status_t SimpleServer::runInternalEnd(Codec *codec, message_type_t msgType, return err; } -erpc_status_t SimpleServer::run(void) -{ - erpc_status_t err = kErpcStatus_Success; - while ((err == kErpcStatus_Success) && m_isServerOn) - { - err = runInternal(); - } - return err; -} - #if ERPC_NESTED_CALLS erpc_status_t SimpleServer::run(RequestContext &request) { @@ -183,12 +202,12 @@ erpc_status_t SimpleServer::run(RequestContext &request) break; } - if (msgType == kReplyMessage) + if (msgType == message_type_t::kReplyMessage) { if (sequence == request.getSequence()) { // Swap the received message buffer with the client's message buffer. - request.getCodec()->getBuffer()->swap(&buff); + request.getCodec()->getBufferRef().swap(&buff); codec->setBuffer(buff); } @@ -212,30 +231,14 @@ erpc_status_t SimpleServer::run(RequestContext &request) } #endif -erpc_status_t SimpleServer::poll(void) +void SimpleServer::disposeBufferAndCodec(Codec *codec) { - erpc_status_t err; - - if (m_isServerOn) + if (codec != NULL) { - if (m_transport->hasMessage() == true) - { - err = runInternal(); - } - else + if (codec->getBuffer() != NULL) { - err = kErpcStatus_Success; + m_messageFactory->dispose(&codec->getBufferRef()); } + m_codecFactory->dispose(codec); } - else - { - err = kErpcStatus_ServerIsDown; - } - - return err; -} - -void SimpleServer::stop(void) -{ - m_isServerOn = false; } diff --git a/erpc_c/infra/erpc_simple_server.hpp b/erpc_c/infra/erpc_simple_server.hpp index 21083348..efe0ebc0 100644 --- a/erpc_c/infra/erpc_simple_server.hpp +++ b/erpc_c/infra/erpc_simple_server.hpp @@ -37,10 +37,9 @@ class SimpleServer : public Server * * This function initializes object attributes. */ - SimpleServer(void) - : m_isServerOn(true) - { - } + SimpleServer(void); + + virtual ~SimpleServer(void); /*! * @brief Run server in infinite loop. @@ -66,6 +65,16 @@ class SimpleServer : public Server virtual void stop(void) override; protected: + bool m_isServerOn; /*!< Information if server is ON or OFF. */ + + /*! + * @brief Run server implementation. + * + * This function call functions for receiving data, process this data and + * if reply exist, send it back. + */ + erpc_status_t runInternal(void); + /*! * @brief This function handle receiving request message and reading base info about message. * @@ -104,22 +113,12 @@ class SimpleServer : public Server virtual erpc_status_t run(RequestContext &request) override; #endif - /*! - * @brief Run server implementation. - * - * This function call functions for receiving data, process this data and - * if reply exist, send it back. - */ - erpc_status_t runInternal(void); - /*! * @brief Disposing message buffers and codecs. * * @param[in] codec Pointer to codec to dispose. It contains also message buffer to dispose. */ void disposeBufferAndCodec(Codec *codec); - - bool m_isServerOn; /*!< Information if server is ON or OFF. */ }; } // namespace erpc diff --git a/erpc_c/infra/erpc_static_queue.hpp b/erpc_c/infra/erpc_static_queue.hpp index 2bedfeba..d1996fbb 100644 --- a/erpc_c/infra/erpc_static_queue.hpp +++ b/erpc_c/infra/erpc_static_queue.hpp @@ -11,6 +11,7 @@ #define __embedded_rpc__static_queue__ #include +#include /*! * @addtogroup infra_utility diff --git a/erpc_c/infra/erpc_transport.hpp b/erpc_c/infra/erpc_transport.hpp index 88fe2e16..88fde0e3 100644 --- a/erpc_c/infra/erpc_transport.hpp +++ b/erpc_c/infra/erpc_transport.hpp @@ -46,6 +46,13 @@ class Transport */ virtual ~Transport(void) {} + /** + * @brief Size of data placed in MessageBuffer before serializing eRPC data. + * + * @return uint8_t Amount of bytes, reserved before serialized data. + */ + virtual uint8_t reserveHeaderSize(void) { return 0; } + /*! * @brief Prototype for receiving message. * @@ -106,10 +113,12 @@ class TransportFactory * @brief Constructor. */ TransportFactory(void) {} + /*! * @brief TransportFactory destructor */ virtual ~TransportFactory(void) {} + /*! * @brief Return created transport object. * diff --git a/erpc_c/infra/erpc_transport_arbitrator.cpp b/erpc_c/infra/erpc_transport_arbitrator.cpp index bb748723..dce2f021 100644 --- a/erpc_c/infra/erpc_transport_arbitrator.cpp +++ b/erpc_c/infra/erpc_transport_arbitrator.cpp @@ -8,6 +8,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ #include "erpc_transport_arbitrator.hpp" + #include "erpc_config_internal.h" #include "erpc_manually_constructed.hpp" @@ -27,13 +28,8 @@ using namespace erpc; ERPC_MANUALLY_CONSTRUCTED_ARRAY_STATIC(TransportArbitrator::PendingClientInfo, s_pendingClientInfoArray, ERPC_CLIENTS_THREADS_AMOUNT); -TransportArbitrator::TransportArbitrator(void) -: Transport() -, m_sharedTransport(NULL) -, m_codec(NULL) -, m_clientList(NULL) -, m_clientFreeList(NULL) -, m_clientListMutex() +TransportArbitrator::TransportArbitrator(void) : +Transport(), m_sharedTransport(NULL), m_codec(NULL), m_clientList(NULL), m_clientFreeList(NULL), m_clientListMutex() { } @@ -44,24 +40,9 @@ TransportArbitrator::~TransportArbitrator(void) freeClientList(m_clientFreeList); } -void TransportArbitrator::setCrc16(Crc16 *crcImpl) +uint8_t TransportArbitrator::reserveHeaderSize(void) { - erpc_assert(crcImpl != NULL); - erpc_assert(m_sharedTransport != NULL); - m_sharedTransport->setCrc16(crcImpl); -} - -Crc16 *TransportArbitrator::getCrc16(void) -{ - erpc_assert(m_sharedTransport != NULL); - return m_sharedTransport->getCrc16(); -} - -bool TransportArbitrator::hasMessage(void) -{ - erpc_assert((m_sharedTransport != NULL) && ("shared transport is not set" != NULL)); - - return m_sharedTransport->hasMessage(); + return m_sharedTransport->reserveHeaderSize(); } erpc_status_t TransportArbitrator::receive(MessageBuffer *message) @@ -96,7 +77,7 @@ erpc_status_t TransportArbitrator::receive(MessageBuffer *message) break; } - m_codec->setBuffer(*message); + m_codec->setBuffer(*message, m_sharedTransport->reserveHeaderSize()); // Parse the message header. m_codec->startReadMessage(msgType, service, requestNumber, sequence); @@ -107,13 +88,13 @@ erpc_status_t TransportArbitrator::receive(MessageBuffer *message) } // If this message is an invocation, return it to the calling server. - if ((msgType == kInvocationMessage) || (msgType == kOnewayMessage)) + if ((msgType == message_type_t::kInvocationMessage) || (msgType == message_type_t::kOnewayMessage)) { break; } // Just ignore messages we don't know what to do with. - if (msgType != kReplyMessage) + if (msgType != message_type_t::kReplyMessage) { continue; } @@ -125,7 +106,7 @@ erpc_status_t TransportArbitrator::receive(MessageBuffer *message) if (client->m_isValid && (sequence == client->m_request->getSequence())) { // Swap the received message buffer with the client's message buffer. - client->m_request->getCodec()->getBuffer()->swap(message); + client->m_request->getCodec()->getBufferRef().swap(message); // Wake up the client receive thread. client->m_sem.put(); @@ -151,6 +132,46 @@ erpc_status_t TransportArbitrator::send(MessageBuffer *message) return m_sharedTransport->send(message); } +bool TransportArbitrator::hasMessage(void) +{ + erpc_assert((m_sharedTransport != NULL) && ("shared transport is not set" != NULL)); + + return m_sharedTransport->hasMessage(); +} + +void TransportArbitrator::setCrc16(Crc16 *crcImpl) +{ + erpc_assert(crcImpl != NULL); + erpc_assert(m_sharedTransport != NULL); + m_sharedTransport->setCrc16(crcImpl); +} + +Crc16 *TransportArbitrator::getCrc16(void) +{ + erpc_assert(m_sharedTransport != NULL); + return m_sharedTransport->getCrc16(); +} + +void TransportArbitrator::setSharedTransport(Transport *shared) +{ + m_sharedTransport = shared; +} + +Transport *TransportArbitrator::getSharedTransport(void) +{ + return m_sharedTransport; +} + +void TransportArbitrator::setCodec(Codec *codec) +{ + m_codec = codec; +} + +Codec *TransportArbitrator::getCodec(void) +{ + return m_codec; +} + TransportArbitrator::client_token_t TransportArbitrator::prepareClientReceive(RequestContext &request) { PendingClientInfo *info = addPendingClient(); @@ -252,11 +273,8 @@ void TransportArbitrator::freeClientList(PendingClientInfo *list) } } -TransportArbitrator::PendingClientInfo::PendingClientInfo(void) -: m_request(NULL) -, m_sem(0) -, m_isValid(false) -, m_next(NULL) +TransportArbitrator::PendingClientInfo::PendingClientInfo(void) : +m_request(NULL), m_sem(0), m_isValid(false), m_next(NULL) { } diff --git a/erpc_c/infra/erpc_transport_arbitrator.hpp b/erpc_c/infra/erpc_transport_arbitrator.hpp index 34bad73b..049c58af 100644 --- a/erpc_c/infra/erpc_transport_arbitrator.hpp +++ b/erpc_c/infra/erpc_transport_arbitrator.hpp @@ -53,44 +53,84 @@ class TransportArbitrator : public Transport */ virtual ~TransportArbitrator(void); + /** + * @brief Size of data placed in MessageBuffer before serializing eRPC data. + * + * @return uint8_t Amount of bytes, reserved before serialized data. + */ + virtual uint8_t reserveHeaderSize(void) override; + + /*! + * @brief Prototype for receiving message. + * + * Each transport layer need define this function. + * + * @param[out] message Will return pointer to received message buffer. + * + * @return based on receive implementation. + */ + virtual erpc_status_t receive(MessageBuffer *message) override; + + /*! + * @brief Prototype for send message. + * + * Each transport layer need define this function. + * + * @param[in] message Pass message buffer to send. + * + * @return based on send implementation. + */ + virtual erpc_status_t send(MessageBuffer *message) override; + + /*! + * @brief Check if the underlying shared transport has a message + * + * @retval The underlying transport is expected to return true when a message is available to + * process and false otherwise. + */ + virtual bool hasMessage(void) override; + + /*! + * @brief This functions sets the CRC-16 implementation. + * + * @param[in] crcImpl Object containing crc-16 compute function. + */ + virtual void setCrc16(Crc16 *crcImpl) override; + + /*! + * @brief This functions gets the CRC-16 object. + * + * @return Crc16* Pointer to CRC-16 object containing crc-16 compute function. + */ + virtual Crc16 *getCrc16(void) override; + /*! * @brief This function set shared client/server transport. * * @param[in] shared Shared client/server transport. */ - void setSharedTransport(Transport *shared) { m_sharedTransport = shared; } + void setSharedTransport(Transport *shared); /*! * @brief This function returns shared client/server transport. * * @return Transport * Returns shared client/server transport. */ - Transport *getSharedTransport(void) { return m_sharedTransport; } + Transport *getSharedTransport(void); /*! * @brief This function set codec. * * @param[in] codec Codec. */ - void setCodec(Codec *codec) { m_codec = codec; } + void setCodec(Codec *codec); /*! * @brief This function get codec. * * @return Codec * Pointer to codec used within transport. */ - Codec *getCodec(void) { return m_codec; } - - /*! - * @brief Prototype for receiving message. - * - * Each transport layer need define this function. - * - * @param[out] message Will return pointer to received message buffer. - * - * @return based on receive implementation. - */ - virtual erpc_status_t receive(MessageBuffer *message) override; + Codec *getCodec(void); /*! * @brief Add a client request to the client list. @@ -117,39 +157,6 @@ class TransportArbitrator : public Transport */ erpc_status_t clientReceive(client_token_t token); - /*! - * @brief Prototype for send message. - * - * Each transport layer need define this function. - * - * @param[in] message Pass message buffer to send. - * - * @return based on send implementation. - */ - virtual erpc_status_t send(MessageBuffer *message) override; - - /*! - * @brief This functions sets the CRC-16 implementation. - * - * @param[in] crcImpl Object containing crc-16 compute function. - */ - virtual void setCrc16(Crc16 *crcImpl) override; - - /*! - * @brief This functions gets the CRC-16 object. - * - * @return Crc16* Pointer to CRC-16 object containing crc-16 compute function. - */ - virtual Crc16 *getCrc16(void) override; - - /*! - * @brief Check if the underlying shared transport has a message - * - * @retval The underlying transport is expected to return true when a message is available to - * process and false otherwise. - */ - virtual bool hasMessage(void) override; - /*! * @brief Request info for a client trying to receive a response. */ diff --git a/erpc_c/infra/erpc_utils.cpp b/erpc_c/infra/erpc_utils.cpp new file mode 100644 index 00000000..f59acbb6 --- /dev/null +++ b/erpc_c/infra/erpc_utils.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2023 ACRIOS Systems s.r.o. + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "erpc_utils.hpp" + +bool erpc::findIndexOfFunction(const arrayOfFunctionPtr_t sourceArrayOfFunctionPtr, uint16_t sourceArrayLength, + const functionPtr_t functionPtr, uint16_t &retVal) +{ + uint32_t index; + bool find = false; + for (index = 0; index < sourceArrayLength; index++) + { + if (sourceArrayOfFunctionPtr[index] == functionPtr) + { + retVal = index; + find = true; + break; + } + } + return find; +} diff --git a/erpc_c/infra/erpc_utils.hpp b/erpc_c/infra/erpc_utils.hpp new file mode 100644 index 00000000..060aec3a --- /dev/null +++ b/erpc_c/infra/erpc_utils.hpp @@ -0,0 +1,17 @@ +/* + * Copyright 2023 ACRIOS Systems s.r.o. + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +namespace erpc { +typedef void *functionPtr_t; +typedef functionPtr_t *arrayOfFunctionPtr_t; + +bool findIndexOfFunction(const arrayOfFunctionPtr_t sourceArrayOfFunctionPtr, uint16_t sourceArrayLength, + const functionPtr_t functionPtr, uint16_t &retVal); +} // namespace erpc diff --git a/erpc_c/infra/erpc_version.h b/erpc_c/infra/erpc_version.h index 7490eedc..1f5188f8 100644 --- a/erpc_c/infra/erpc_version.h +++ b/erpc_c/infra/erpc_version.h @@ -20,9 +20,9 @@ //////////////////////////////////////////////////////////////////////////////// //! @brief String version of eRPC. -#define ERPC_VERSION "1.11.0" +#define ERPC_VERSION "1.12.0" //! @brief Integer version of eRPC. -#define ERPC_VERSION_NUMBER 11100 +#define ERPC_VERSION_NUMBER 11200 /*! @} */ diff --git a/erpc_c/port/erpc_config_internal.h b/erpc_c/port/erpc_config_internal.h index 482de9ea..f5209c65 100644 --- a/erpc_c/port/erpc_config_internal.h +++ b/erpc_c/port/erpc_config_internal.h @@ -22,7 +22,8 @@ #if !defined(ERPC_HAS_POSIX) // Detect Linux, BSD, Cygwin, and Mac OS X. #if defined(__linux__) || defined(__GNU__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) || defined(__DragonFly__) || defined(__CYGWIN__) || defined(__MACH__) + defined(__OpenBSD__) || defined(__DragonFly__) || defined(__CYGWIN__) || defined(__MACH__) || \ + defined(__MINGW32__) #define ERPC_HAS_POSIX (1) #else #define ERPC_HAS_POSIX (0) diff --git a/erpc_c/port/erpc_port_stdlib.cpp b/erpc_c/port/erpc_port_stdlib.cpp index 2413ed44..19d9ed70 100644 --- a/erpc_c/port/erpc_port_stdlib.cpp +++ b/erpc_c/port/erpc_port_stdlib.cpp @@ -15,6 +15,7 @@ using namespace std; +#if !defined(__MINGW32__) void *operator new(size_t count) THROW_BADALLOC { void *p = erpc_malloc(count); @@ -62,6 +63,7 @@ void operator delete[](void *ptr, std::size_t count) THROW NOEXCEPT (void)count; erpc_free(ptr); } +#endif void *erpc_malloc(size_t size) { diff --git a/erpc_c/port/erpc_port_zephyr.cpp b/erpc_c/port/erpc_port_zephyr.cpp index d106afdd..64b32b9e 100644 --- a/erpc_c/port/erpc_port_zephyr.cpp +++ b/erpc_c/port/erpc_port_zephyr.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 NXP + * Copyright 2017-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -12,7 +12,7 @@ #include extern "C" { -#include "kernel.h" +#include }; using namespace std; diff --git a/erpc_c/port/erpc_serial.cpp b/erpc_c/port/erpc_serial.cpp index 9f94799d..2423ca8e 100644 --- a/erpc_c/port/erpc_serial.cpp +++ b/erpc_c/port/erpc_serial.cpp @@ -135,7 +135,7 @@ int serial_setup(int fd, speed_t speed) #ifdef __APPLE__ return ioctl(fd, IOSSIOSPEED, &speed); -#endif //#ifdef __APPLE__ +#endif // #ifdef __APPLE__ #endif // _WIN32 return 0; diff --git a/erpc_c/port/erpc_setup_extensions_freertos.cpp b/erpc_c/port/erpc_setup_extensions_freertos.cpp index 5f878016..0d446b43 100644 --- a/erpc_c/port/erpc_setup_extensions_freertos.cpp +++ b/erpc_c/port/erpc_setup_extensions_freertos.cpp @@ -23,11 +23,15 @@ ERPC_MANUALLY_CONSTRUCTED_STATIC(Semaphore, s_semaphore); void erpc::erpc_pre_cb_default(void) { - erpc_assert((s_erpc_call_in_progress != NULL) && - ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != NULL)); + erpc_assert( + (s_erpc_call_in_progress != NULL) && + ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != + NULL)); (void)s_erpc_call_in_progress->get(s_erpc_call_in_progress->kWaitForever); - erpc_assert((s_erpc_call_timer_cb != NULL) && - ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != NULL)); + erpc_assert( + (s_erpc_call_timer_cb != NULL) && + ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != + NULL)); (void)xTimerStart(s_erpc_call_timer_cb, 0); } @@ -85,8 +89,10 @@ void erpc_deinit_call_progress_detection_default(void) bool erpc_is_call_in_progress_default(void) { - erpc_assert((s_erpc_call_in_progress != NULL) && - ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != NULL)); + erpc_assert( + (s_erpc_call_in_progress != NULL) && + ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != + NULL)); if (s_erpc_call_in_progress->get(0)) { s_erpc_call_in_progress->put(); @@ -98,12 +104,16 @@ bool erpc_is_call_in_progress_default(void) void erpc_reset_in_progress_state_default(void) { - erpc_assert((s_erpc_call_in_progress != NULL) && - ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != NULL)); + erpc_assert( + (s_erpc_call_in_progress != NULL) && + ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != + NULL)); s_erpc_call_in_progress->get(0); s_erpc_call_in_progress->put(); - erpc_assert((s_erpc_call_timer_cb != NULL) && - ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != NULL)); + erpc_assert( + (s_erpc_call_timer_cb != NULL) && + ("If you want use default pre cb action, do not forget call erpc_init_call_progress_detection_default." != + NULL)); (void)xTimerStop(s_erpc_call_timer_cb, 0); } diff --git a/erpc_c/port/erpc_threading.h b/erpc_c/port/erpc_threading.h index 1f3d66ad..b8b662ea 100644 --- a/erpc_c/port/erpc_threading.h +++ b/erpc_c/port/erpc_threading.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -25,7 +25,7 @@ #include "semphr.h" #include "task.h" #elif ERPC_THREADS_IS(ZEPHYR) -#include "kernel.h" +#include #elif ERPC_THREADS_IS(MBED) #if MBED_CONF_RTOS_PRESENT #include "rtos.h" @@ -99,7 +99,7 @@ class Thread * @param[in] stackPtr Mandatory task stack pointer for static api usage. */ Thread(thread_entry_t entry, uint32_t priority = 0, uint32_t stackSize = 0, const char *name = 0, - thread_stack_pointer stackPtr = 0); + thread_stack_pointer stackPtr = NULL); /*! * @brief Destructor. @@ -128,7 +128,7 @@ class Thread * @param[in] stackSize Stack size. * @param[in] stackPtr Mandatory task stack pointer for static api usage. */ - void init(thread_entry_t entry, uint32_t priority = 0, uint32_t stackSize = 0, thread_stack_pointer stackPtr = 0); + void init(thread_entry_t entry, uint32_t priority = 0, uint32_t stackSize = 0, thread_stack_pointer stackPtr = NULL); /*! * @brief This function starts thread execution. @@ -156,7 +156,7 @@ class Thread #elif ERPC_THREADS_IS(FREERTOS) return reinterpret_cast(m_task); #elif ERPC_THREADS_IS(ZEPHYR) - return reinterpret_cast(m_thread); + return reinterpret_cast(m_thread_id); #elif ERPC_THREADS_IS(MBED) return reinterpret_cast(m_thread->get_id()); #elif ERPC_THREADS_IS(WIN32) @@ -238,7 +238,8 @@ class Thread StaticTask_t m_staticTask; /*!< Hold static task data. */ #endif #elif ERPC_THREADS_IS(ZEPHYR) - struct k_thread m_thread; /*!< Current thread. */ + struct k_thread m_thread; /*!< Current thread. */ + k_tid_t m_thread_id; k_thread_stack_t *m_stack; /*!< Pointer to stack. */ #elif ERPC_THREADS_IS(MBED) rtos::Thread *m_thread; /*!< Underlying Thread instance */ @@ -282,7 +283,7 @@ class Thread * @param[in] arg2 * @param[in] arg3 */ - static void *threadEntryPointStub(void *arg1, void *arg2, void *arg3); + static void threadEntryPointStub(void *arg1, void *arg2, void *arg3); #elif ERPC_THREADS_IS(MBED) @@ -349,11 +350,7 @@ class Mutex * * @param[in] mutex to lock. */ - Guard(Mutex &mutex) - : m_mutex(mutex) - { - (void)m_mutex.lock(); - } + Guard(Mutex &mutex) : m_mutex(mutex) { (void)m_mutex.lock(); } /*! * @brief Destructor. */ diff --git a/erpc_c/port/erpc_threading_freertos.cpp b/erpc_c/port/erpc_threading_freertos.cpp index bb9eae46..afef5e9d 100644 --- a/erpc_c/port/erpc_threading_freertos.cpp +++ b/erpc_c/port/erpc_threading_freertos.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -26,26 +26,15 @@ Thread *Thread::s_first = NULL; // Code //////////////////////////////////////////////////////////////////////////////// -Thread::Thread(const char *name) -: m_name(name) -, m_entry(0) -, m_arg(0) -, m_stackSize(0) -, m_priority(0) -, m_task(0) -, m_next(0) +Thread::Thread(const char *name) : +m_name(name), m_entry(NULL), m_arg(0), m_stackSize(0), m_priority(0), m_stackPtr(NULL), m_task(0), m_next(0) { } Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name, - thread_stack_pointer stackPtr) -: m_name(name) -, m_entry(entry) -, m_arg(0) -, m_stackSize(stackSize) -, m_priority(priority) -, m_task(0) -, m_next(0) + thread_stack_pointer stackPtr) : +m_name(name), +m_entry(entry), m_arg(0), m_stackSize(stackSize), m_priority(priority), m_stackPtr(stackPtr), m_task(0), m_next(0) { } @@ -73,10 +62,10 @@ void Thread::start(void *arg) #if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC if (m_stackPtr != NULL) { - m_task = - xTaskCreateStatic(threadEntryPointStub, (m_name != NULL ? m_name : "task"), - (configSTACK_DEPTH_TYPE)((m_stackSize + sizeof(uint32_t) - 1U) / sizeof(uint32_t)), // Round up number of words. - this, m_priority, m_stackPtr, &m_staticTask); + m_task = xTaskCreateStatic(threadEntryPointStub, (m_name != NULL ? m_name : "task"), + (configSTACK_DEPTH_TYPE)((m_stackSize + sizeof(uint32_t) - 1U) / + sizeof(uint32_t)), // Round up number of words. + this, m_priority, m_stackPtr, &m_staticTask); taskCreated = true; } #endif @@ -84,10 +73,10 @@ void Thread::start(void *arg) #if configSUPPORT_DYNAMIC_ALLOCATION if (m_stackPtr == NULL) { - if (pdPASS == - xTaskCreate(threadEntryPointStub, (m_name != NULL ? m_name : "task"), - (configSTACK_DEPTH_TYPE)((m_stackSize + sizeof(uint32_t) - 1U) / sizeof(uint32_t)), // Round up number of words. - this, m_priority, &m_task)) + if (pdPASS == xTaskCreate(threadEntryPointStub, (m_name != NULL ? m_name : "task"), + (configSTACK_DEPTH_TYPE)((m_stackSize + sizeof(uint32_t) - 1U) / + sizeof(uint32_t)), // Round up number of words. + this, m_priority, &m_task)) { taskCreated = true; } @@ -201,8 +190,7 @@ void Thread::threadEntryPointStub(void *arg) #endif // INCLUDE_vTaskDelete } -Mutex::Mutex(void) -: m_mutex(0) +Mutex::Mutex(void) : m_mutex(0) { #if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC m_mutex = xSemaphoreCreateRecursiveMutexStatic(&m_staticQueue); @@ -234,8 +222,7 @@ bool Mutex::unlock(void) return (pdTRUE == xSemaphoreGiveRecursive(m_mutex) ? true : false); } -Semaphore::Semaphore(int count) -: m_sem(0) +Semaphore::Semaphore(int count) : m_sem(0) { // Set max count to highest signed int. #if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC diff --git a/erpc_c/port/erpc_threading_mbed.cpp b/erpc_c/port/erpc_threading_mbed.cpp index 9f537a9a..ca59756c 100644 --- a/erpc_c/port/erpc_threading_mbed.cpp +++ b/erpc_c/port/erpc_threading_mbed.cpp @@ -28,26 +28,15 @@ Thread *Thread::s_first = NULL; // Code //////////////////////////////////////////////////////////////////////////////// -Thread::Thread(const char *name) -: m_name(name) -, m_entry(0) -, m_arg(0) -, m_stackSize(0) -, m_priority(0) -, m_thread(NULL) -, m_next(NULL) +Thread::Thread(const char *name) : +m_name(name), m_entry(0), m_arg(0), m_stackSize(0), m_priority(0), m_thread(NULL), m_next(NULL) { } Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name, - thread_stack_pointer stackPtr) -: m_name(name) -, m_entry(entry) -, m_arg(0) -, m_stackSize(stackSize) -, m_priority(priority) -, m_thread(NULL) -, m_next(NULL) + thread_stack_pointer stackPtr) : +m_name(name), +m_entry(entry), m_arg(0), m_stackSize(stackSize), m_priority(priority), m_thread(NULL), m_next(NULL) { } @@ -198,8 +187,7 @@ bool Mutex::unlock(void) return m_mutex->unlock(); } -Semaphore::Semaphore(int count) -: m_count(count) +Semaphore::Semaphore(int count) : m_count(count) { m_sem = new rtos::Semaphore(m_count); } diff --git a/erpc_c/port/erpc_threading_pthreads.cpp b/erpc_c/port/erpc_threading_pthreads.cpp index 18ba49d3..418cbf4e 100644 --- a/erpc_c/port/erpc_threading_pthreads.cpp +++ b/erpc_c/port/erpc_threading_pthreads.cpp @@ -34,24 +34,12 @@ const uint32_t sToUs = 1000000; // Code //////////////////////////////////////////////////////////////////////////////// -Thread::Thread(const char *name) -: m_name(name) -, m_entry(0) -, m_arg(0) -, m_stackSize(0) -, m_priority(0) -, m_thread(0) -{ -} +Thread::Thread(const char *name) : m_name(name), m_entry(0), m_arg(0), m_stackSize(0), m_priority(0), m_thread(0) {} Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name, - thread_stack_pointer stackPtr) -: m_name(name) -, m_entry(entry) -, m_arg(0) -, m_stackSize(stackSize) -, m_priority(priority) -, m_thread(0) + thread_stack_pointer stackPtr) : +m_name(name), +m_entry(entry), m_arg(0), m_stackSize(stackSize), m_priority(priority), m_thread(0) { } @@ -163,9 +151,7 @@ bool Mutex::unlock(void) return pthread_mutex_unlock(&m_mutex) == 0; } -Semaphore::Semaphore(int count) -: m_count(count) -, m_mutex() +Semaphore::Semaphore(int count) : m_count(count), m_mutex() { pthread_cond_init(&m_cond, NULL); } diff --git a/erpc_c/port/erpc_threading_threadx.cpp b/erpc_c/port/erpc_threading_threadx.cpp index 2c4939ff..397749c7 100644 --- a/erpc_c/port/erpc_threading_threadx.cpp +++ b/erpc_c/port/erpc_threading_threadx.cpp @@ -31,26 +31,15 @@ static TX_BYTE_POOL tx_app_byte_pool; // Code //////////////////////////////////////////////////////////////////////////////// -Thread::Thread(const char *name) -: m_name(name) -, m_entry(0) -, m_arg(0) -, m_stackSize(0) -, m_priority(0) -, m_thread() -, m_next() +Thread::Thread(const char *name) : +m_name(name), m_entry(0), m_arg(0), m_stackSize(0), m_priority(0), m_thread(), m_next() { } Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name, - thread_stack_pointer stackPtr) -: m_name(name) -, m_entry(entry) -, m_arg(0) -, m_stackSize(stackSize) -, m_priority(priority) -, m_thread() -, m_next() + thread_stack_pointer stackPtr) : +m_name(name), +m_entry(entry), m_arg(0), m_stackSize(stackSize), m_priority(priority), m_thread(), m_next() { } @@ -209,8 +198,7 @@ void Thread::threadEntryPointStub(ULONG arg) tx_interrupt_control(my_old_posture); } -Mutex::Mutex(void) -: m_mutex() +Mutex::Mutex(void) : m_mutex() { CHAR name[] = "erpc_mutex"; tx_mutex_create(&m_mutex, name, TX_INHERIT); @@ -239,8 +227,7 @@ bool Mutex::unlock(void) return (status == TX_SUCCESS); } -Semaphore::Semaphore(int count) -: m_sem() +Semaphore::Semaphore(int count) : m_sem() { CHAR name[] = "erpc_sem"; tx_semaphore_create(&m_sem, name, count); diff --git a/erpc_c/port/erpc_threading_win32.cpp b/erpc_c/port/erpc_threading_win32.cpp index 459c5b0a..7d13d5dd 100644 --- a/erpc_c/port/erpc_threading_win32.cpp +++ b/erpc_c/port/erpc_threading_win32.cpp @@ -29,28 +29,15 @@ CRITICAL_SECTION Thread::m_critical_section; // Code //////////////////////////////////////////////////////////////////////////////// -Thread::Thread(const char *name) -: m_name(name) -, m_entry(0) -, m_arg(0) -, m_stackSize(0) -, m_priority(0) -, m_thread(0) -, m_thrdaddr(0) -, m_next(0) +Thread::Thread(const char *name) : +m_name(name), m_entry(0), m_arg(0), m_stackSize(0), m_priority(0), m_thread(0), m_thrdaddr(0), m_next(0) { } Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name, - thread_stack_pointer stackPtr) -: m_name(name) -, m_entry(entry) -, m_arg(0) -, m_stackSize(stackSize) -, m_priority(priority) -, m_thread(0) -, m_thrdaddr(0) -, m_next(0) + thread_stack_pointer stackPtr) : +m_name(name), +m_entry(entry), m_arg(0), m_stackSize(stackSize), m_priority(priority), m_thread(0), m_thrdaddr(0), m_next(0) { } @@ -172,10 +159,7 @@ bool Mutex::unlock(void) return ReleaseMutex(m_mutex); } -Semaphore::Semaphore(int count) -: m_count(count) -, m_sem() -, m_mutex() +Semaphore::Semaphore(int count) : m_count(count), m_sem(), m_mutex() { m_sem = CreateSemaphore(NULL, m_count, 1, ""); } diff --git a/erpc_c/port/erpc_threading_zephyr.cpp b/erpc_c/port/erpc_threading_zephyr.cpp index 24928cc3..6bc4b8ec 100644 --- a/erpc_c/port/erpc_threading_zephyr.cpp +++ b/erpc_c/port/erpc_threading_zephyr.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 NXP + * Copyright 2017-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -17,26 +17,15 @@ using namespace erpc; // Code //////////////////////////////////////////////////////////////////////////////// -Thread::Thread(const char *name) -: m_name(name) -, m_entry(0) -, m_arg(0) -, m_stackSize(0) -, m_priority(0) -, m_thread(0) -, m_stack(0) +Thread::Thread(const char *name) : +m_name(name), m_entry(0), m_arg(0), m_stackSize(0), m_priority(0), m_thread(), m_stack(0) { } Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name, - thread_stack_pointer stackPtr) -: m_name(name) -, m_entry(entry) -, m_arg(0) -, m_stackSize(stackSize) -, m_priority(priority) -, m_thread(0) -, m_stack(0) + thread_stack_pointer stackPtr) : +m_name(name), +m_entry(entry), m_arg(0), m_stackSize(stackSize), m_priority(priority), m_thread(), m_stack(0) { } @@ -55,12 +44,13 @@ void Thread::start(void *arg) m_arg = arg; erpc_assert((m_stack != NULL) && ("Set stack address" != NULL)); - k_thread_create(&m_thread, m_stack, m_stackSize, threadEntryPointStub, this, NULL, NULL, m_priority, 0, K_NO_WAIT); + m_thread_id = k_thread_create(&m_thread, m_stack, m_stackSize, threadEntryPointStub, this, NULL, NULL, m_priority, + 0, K_NO_WAIT); } bool Thread::operator==(Thread &o) { - return m_thread == o.m_thread; + return &m_thread == &o.m_thread; } Thread *Thread::getCurrentThread(void) @@ -70,7 +60,7 @@ Thread *Thread::getCurrentThread(void) void Thread::sleep(uint32_t usecs) { - k_sleep(usecs / 1000); + k_sleep(K_USEC(usecs)); } void Thread::threadEntryPoint(void) @@ -81,7 +71,7 @@ void Thread::threadEntryPoint(void) } } -void *Thread::threadEntryPointStub(void *arg1, void *arg2, void *arg3) +void Thread::threadEntryPointStub(void *arg1, void *arg2, void *arg3) { Thread *_this = reinterpret_cast(arg1); erpc_assert((_this != NULL) && ("Reinterpreting 'void *arg1' to 'Thread *' failed." != NULL)); @@ -92,8 +82,7 @@ void *Thread::threadEntryPointStub(void *arg1, void *arg2, void *arg3) k_thread_abort(k_current_get()); } -Mutex::Mutex(void) -: m_mutex(0) +Mutex::Mutex(void) : m_mutex() { k_mutex_init(&m_mutex); } @@ -116,8 +105,7 @@ bool Mutex::unlock(void) return true; } -Semaphore::Semaphore(int count) -: m_sem(0) +Semaphore::Semaphore(int count) : m_sem() { // Set max count to highest signed int. k_sem_init(&m_sem, count, 0x7fffffff); @@ -144,12 +132,12 @@ bool Semaphore::get(uint32_t timeoutUsecs) } } - return (k_sem_take(&m_sem, timeoutUsecs) == 0); + return (k_sem_take(&m_sem, K_USEC(timeoutUsecs)) == 0); } int Semaphore::getCount(void) const { - return k_sem_count_get(m_sem); + return k_sem_count_get(const_cast(&m_sem)); } #endif /* ERPC_THREADS_IS(ZEPHYR) */ diff --git a/erpc_c/setup/erpc_arbitrated_client_setup.cpp b/erpc_c/setup/erpc_arbitrated_client_setup.cpp index 7057c041..5ebcdbee 100644 --- a/erpc_c/setup/erpc_arbitrated_client_setup.cpp +++ b/erpc_c/setup/erpc_arbitrated_client_setup.cpp @@ -31,8 +31,13 @@ using namespace erpc; // global client variables ERPC_MANUALLY_CONSTRUCTED_STATIC(ArbitratedClientManager, s_client); -ClientManager *g_client; +#if defined(__MINGW32__) +__declspec(selectany) +#endif + ClientManager *g_client; +#if !defined(__MINGW32__) #pragma weak g_client +#endif ERPC_MANUALLY_CONSTRUCTED_STATIC(BasicCodecFactory, s_codecFactory); ERPC_MANUALLY_CONSTRUCTED_STATIC(TransportArbitrator, s_arbitrator); diff --git a/erpc_c/setup/erpc_arbitrated_client_setup.h b/erpc_c/setup/erpc_arbitrated_client_setup.h index d8ed7bf7..d8775d60 100644 --- a/erpc_c/setup/erpc_arbitrated_client_setup.h +++ b/erpc_c/setup/erpc_arbitrated_client_setup.h @@ -66,7 +66,8 @@ extern "C" { * * @return erpc_client_t Pointer to client structure. */ -erpc_client_t erpc_arbitrated_client_init(erpc_transport_t transport, erpc_mbf_t message_buffer_factory, erpc_transport_t *arbitrator); +erpc_client_t erpc_arbitrated_client_init(erpc_transport_t transport, erpc_mbf_t message_buffer_factory, + erpc_transport_t *arbitrator); /*! * @brief This function sets error handler function. diff --git a/erpc_c/setup/erpc_client_setup.cpp b/erpc_c/setup/erpc_client_setup.cpp index 52abbd03..cd669f7e 100644 --- a/erpc_c/setup/erpc_client_setup.cpp +++ b/erpc_c/setup/erpc_client_setup.cpp @@ -29,8 +29,13 @@ using namespace erpc; // global client variables ERPC_MANUALLY_CONSTRUCTED_STATIC(ClientManager, s_client); -ClientManager *g_client; +#if defined(__MINGW32__) +__declspec(selectany) +#endif + ClientManager *g_client; +#if !defined(__MINGW32__) #pragma weak g_client +#endif ERPC_MANUALLY_CONSTRUCTED_STATIC(BasicCodecFactory, s_codecFactory); ERPC_MANUALLY_CONSTRUCTED_STATIC(Crc16, s_crc16); diff --git a/erpc_c/setup/erpc_mbf_setup.h b/erpc_c/setup/erpc_mbf_setup.h index 6cd79b3c..87ba45d3 100644 --- a/erpc_c/setup/erpc_mbf_setup.h +++ b/erpc_c/setup/erpc_mbf_setup.h @@ -37,14 +37,16 @@ extern "C" { //@{ /*! - * @brief Create MessageBuffer factory which is using static allocated buffers. + * @brief Create MessageBuffer factory which is using dynamic allocated buffers. */ -erpc_mbf_t erpc_mbf_static_init(void); +erpc_mbf_t erpc_mbf_dynamic_init(void); /*! - * @brief Create MessageBuffer factory which is using dynamic allocated buffers. + * @brief Deinit MessageBuffer factory. + * + * @param[in] mbf MessageBuffer factory which was initialized in init function. */ -erpc_mbf_t erpc_mbf_dynamic_init(void); +void erpc_mbf_dynamic_deinit(erpc_mbf_t mbf); /*! * @brief Create MessageBuffer factory which is using RPMSG LITE zero copy buffers. @@ -54,11 +56,23 @@ erpc_mbf_t erpc_mbf_dynamic_init(void); erpc_mbf_t erpc_mbf_rpmsg_init(erpc_transport_t transport); /*! - * @brief Create MessageBuffer factory which is using RPMSG LITE TTY buffers. + * @brief Deinit MessageBuffer factory. + * + * @param[in] mbf MessageBuffer factory which was initialized in init function. + */ +void erpc_mbf_rpmsg_deinit(erpc_mbf_t mbf); + +/*! + * @brief Create MessageBuffer factory which is using static allocated buffers. + */ +erpc_mbf_t erpc_mbf_static_init(void); + +/*! + * @brief Deinit MessageBuffer factory. * - * Has to be used with RPMSG lite TTY transport. + * @param[in] mbf MessageBuffer factory which was initialized in init function. */ -erpc_mbf_t erpc_mbf_rpmsg_tty_init(erpc_transport_t transport); +void erpc_mbf_static_deinit(erpc_mbf_t mbf); //@} diff --git a/erpc_c/setup/erpc_server_setup.cpp b/erpc_c/setup/erpc_server_setup.cpp index 2fd5580e..aff5e6ab 100644 --- a/erpc_c/setup/erpc_server_setup.cpp +++ b/erpc_c/setup/erpc_server_setup.cpp @@ -200,7 +200,7 @@ void erpc_client_add_pre_cb_action(erpc_server_t server, pre_post_action_cb preC void erpc_client_add_post_cb_action(erpc_server_t server, pre_post_action_cb postCB) { - erpc_assert(server) != NULL; + erpc_assert(server != NULL); SimpleServer *simpleServer = reinterpret_cast(server); diff --git a/erpc_c/setup/erpc_setup_dspi_master.cpp b/erpc_c/setup/erpc_setup_dspi_master.cpp index 8361b15d..b83f7af7 100644 --- a/erpc_c/setup/erpc_setup_dspi_master.cpp +++ b/erpc_c/setup/erpc_setup_dspi_master.cpp @@ -17,7 +17,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(DspiMasterTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(DspiMasterTransport, s_dspiTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -25,7 +25,42 @@ ERPC_MANUALLY_CONSTRUCTED(DspiMasterTransport, s_transport); erpc_transport_t erpc_transport_dspi_master_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz) { - s_transport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + DspiMasterTransport *dspiTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_dspiTransport.isUsed()) + { + dspiTransport = NULL; + } + else + { + s_dspiTransport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); + dspiTransport = s_dspiTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + dspiTransport = new DspiMasterTransport(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (dspiTransport != NULL) + { + (void)dspiTransport->init(); + } + + return reinterpret_cast(dspiTransport); +} + +void erpc_transport_dspi_master_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_dspiTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + DspiMasterTransport *dspiTransport = reinterpret_cast(transport); + + delete dspiTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_dspi_slave.cpp b/erpc_c/setup/erpc_setup_dspi_slave.cpp index 016d1a72..02a165a1 100644 --- a/erpc_c/setup/erpc_setup_dspi_slave.cpp +++ b/erpc_c/setup/erpc_setup_dspi_slave.cpp @@ -17,7 +17,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(DspiSlaveTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(DspiSlaveTransport, s_dspiTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -25,7 +25,42 @@ ERPC_MANUALLY_CONSTRUCTED(DspiSlaveTransport, s_transport); erpc_transport_t erpc_transport_dspi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz) { - s_transport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + DspiSlaveTransport *dspiTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_dspiTransport.isUsed()) + { + dspiTransport = NULL; + } + else + { + s_dspiTransport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); + dspiTransport = s_dspiTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + dspiTransport = new DspiSlaveTransport(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (dspiTransport != NULL) + { + (void)dspiTransport->init(); + } + + return reinterpret_cast(dspiTransport); +} + +void erpc_transport_dspi_slave_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_dspiTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + DspiSlaveTransport *dspiTransport = reinterpret_cast(transport); + + delete dspiTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_i2c_slave.cpp b/erpc_c/setup/erpc_setup_i2c_slave.cpp index 1181639f..9e3678b7 100644 --- a/erpc_c/setup/erpc_setup_i2c_slave.cpp +++ b/erpc_c/setup/erpc_setup_i2c_slave.cpp @@ -16,7 +16,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -static ManuallyConstructed s_transport; +ERPC_MANUALLY_CONSTRUCTED_STATIC(I2cSlaveTransport, s_i2cTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -24,7 +24,41 @@ static ManuallyConstructed s_transport; erpc_transport_t erpc_transport_i2c_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz) { - s_transport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + I2cSlaveTransport *i2cTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_i2cTransport.isUsed()) + { + i2cTransport = NULL; + } + else + { + s_i2cTransport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); + i2cTransport = s_i2cTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + i2cTransport = new I2cSlaveTransport(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (i2cTransport != NULL) + { + (void)i2cTransport->init(); + } + + return reinterpret_cast(i2cTransport); +} +void erpc_transport_i2c_slave_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_i2cTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + I2cSlaveTransport *i2cTransport = reinterpret_cast(transport); + + delete i2cTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_lpi2c_slave.cpp b/erpc_c/setup/erpc_setup_lpi2c_slave.cpp index f527e1d1..3fefcbb7 100644 --- a/erpc_c/setup/erpc_setup_lpi2c_slave.cpp +++ b/erpc_c/setup/erpc_setup_lpi2c_slave.cpp @@ -16,7 +16,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -static ManuallyConstructed s_transport; +ERPC_MANUALLY_CONSTRUCTED_STATIC(LPI2cSlaveTransport, s_lpi2cTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -24,7 +24,41 @@ static ManuallyConstructed s_transport; erpc_transport_t erpc_transport_lpi2c_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz) { - s_transport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + LPI2cSlaveTransport *lpi2cTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_lpi2cTransport.isUsed()) + { + lpi2cTransport = NULL; + } + else + { + s_lpi2cTransport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); + lpi2cTransport = s_lpi2cTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + lpi2cTransport = new LPI2cSlaveTransport(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (lpi2cTransport != NULL) + { + (void)lpi2cTransport->init(); + } + + return reinterpret_cast(lpi2cTransport); +} +void erpc_transport_lpi2c_slave_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_lpi2cTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + LPI2cSlaveTransport *lpi2cTransport = reinterpret_cast(transport); + + delete lpi2cTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_lpspi_slave.cpp b/erpc_c/setup/erpc_setup_lpspi_slave.cpp index 3e254107..0ddc3e06 100644 --- a/erpc_c/setup/erpc_setup_lpspi_slave.cpp +++ b/erpc_c/setup/erpc_setup_lpspi_slave.cpp @@ -14,7 +14,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(LPSpiSlaveTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(LPSpiSlaveTransport, s_lpspiTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -22,7 +22,42 @@ ERPC_MANUALLY_CONSTRUCTED(LPSpiSlaveTransport, s_transport); erpc_transport_t erpc_transport_lpspi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz) { - s_transport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + LPSpiSlaveTransport *lpspiTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_lpspiTransport.isUsed()) + { + lpspiTransport = NULL; + } + else + { + s_lpspiTransport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); + lpspiTransport = s_lpspiTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + lpspiTransport = new LPSpiSlaveTransport(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (lpspiTransport != NULL) + { + (void)lpspiTransport->init(); + } + + return reinterpret_cast(lpspiTransport); +} + +void erpc_transport_lpspi_slave_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_lpspiTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + LPSpiSlaveTransport *lpspiTransport = reinterpret_cast(transport); + + delete lpspiTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_mbf_dynamic.cpp b/erpc_c/setup/erpc_setup_mbf_dynamic.cpp index d9273c26..7ff6366e 100644 --- a/erpc_c/setup/erpc_setup_mbf_dynamic.cpp +++ b/erpc_c/setup/erpc_setup_mbf_dynamic.cpp @@ -47,10 +47,41 @@ class DynamicMessageBufferFactory : public MessageBufferFactory // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(DynamicMessageBufferFactory, s_msgFactory); +ERPC_MANUALLY_CONSTRUCTED_STATIC(DynamicMessageBufferFactory, s_msgFactory); erpc_mbf_t erpc_mbf_dynamic_init(void) { - s_msgFactory.construct(); - return reinterpret_cast(s_msgFactory.get()); + DynamicMessageBufferFactory *msgFactory; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_msgFactory.isUsed()) + { + msgFactory = NULL; + } + else + { + s_msgFactory.construct(); + msgFactory = s_msgFactory.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + msgFactory = new DynamicMessageBufferFactory(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + return reinterpret_cast(msgFactory); +} + +void erpc_mbf_dynamic_deinit(erpc_mbf_t mbf) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)mbf; + s_msgFactory.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(mbf != NULL); + + DynamicMessageBufferFactory *msgFactory = reinterpret_cast(mbf); + + delete msgFactory; +#endif } diff --git a/erpc_c/setup/erpc_setup_mbf_rpmsg.cpp b/erpc_c/setup/erpc_setup_mbf_rpmsg.cpp index 2c44746a..86d2aa66 100644 --- a/erpc_c/setup/erpc_setup_mbf_rpmsg.cpp +++ b/erpc_c/setup/erpc_setup_mbf_rpmsg.cpp @@ -12,7 +12,7 @@ #include "erpc_manually_constructed.hpp" #include "erpc_mbf_setup.h" #include "erpc_message_buffer.hpp" -#include "erpc_rpmsg_lite_base_transport.hpp" +#include "erpc_rpmsg_lite_base.hpp" extern "C" { #include "rpmsg_lite.h" @@ -20,6 +20,8 @@ extern "C" { using namespace erpc; +#define TIMEOUT_MS 10 + //////////////////////////////////////////////////////////////////////////////// // Classes //////////////////////////////////////////////////////////////////////////////// @@ -51,7 +53,7 @@ class RPMsgMessageBufferFactory : public MessageBufferFactory { void *buf = NULL; uint32_t size = 0; - buf = rpmsg_lite_alloc_tx_buffer(m_rpmsg, &size, RL_BLOCK); + buf = rpmsg_lite_alloc_tx_buffer(m_rpmsg, &size, TIMEOUT_MS); erpc_assert(NULL != buf); return MessageBuffer(reinterpret_cast(buf), size); @@ -77,14 +79,15 @@ class RPMsgMessageBufferFactory : public MessageBufferFactory } } - virtual erpc_status_t prepareServerBufferForSend(MessageBuffer *message) + virtual erpc_status_t prepareServerBufferForSend(MessageBuffer &message, uint8_t reserveHeaderSize = 0) { erpc_status_t status; - dispose(message); - *message = create(); - if (message->get() != NULL) + dispose(&message); + message = create(); + if (message.get() != NULL) { + message.setUsed(reserveHeaderSize); status = kErpcStatus_Success; } else @@ -105,10 +108,41 @@ class RPMsgMessageBufferFactory : public MessageBufferFactory // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(RPMsgMessageBufferFactory, s_msgFactory); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgMessageBufferFactory, s_msgFactory); erpc_mbf_t erpc_mbf_rpmsg_init(erpc_transport_t transport) { - s_msgFactory.construct(reinterpret_cast(transport)->get_rpmsg_lite_instance()); - return reinterpret_cast(s_msgFactory.get()); + RPMsgMessageBufferFactory *msgFactory; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_msgFactory.isUsed()) + { + msgFactory = NULL; + } + else + { + s_msgFactory.construct(reinterpret_cast(transport)->get_rpmsg_lite_instance()); + msgFactory = s_msgFactory.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + msgFactory = new RPMsgMessageBufferFactory(reinterpret_cast(transport)->get_rpmsg_lite_instance()); +#else +#error "Unknown eRPC allocation policy!" +#endif + + return reinterpret_cast(msgFactory); +} + +void erpc_mbf_rpmsg_deinit(erpc_mbf_t mbf) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)mbf; + s_msgFactory.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(mbf != NULL); + + RPMsgMessageBufferFactory *msgFactory = reinterpret_cast(mbf); + + delete msgFactory; +#endif } diff --git a/erpc_c/setup/erpc_setup_mbf_rpmsg_tty.cpp b/erpc_c/setup/erpc_setup_mbf_rpmsg_tty.cpp deleted file mode 100644 index 6c043b3f..00000000 --- a/erpc_c/setup/erpc_setup_mbf_rpmsg_tty.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2016, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP - * Copyright 2021 ACRIOS Systems s.r.o. - * All rights reserved. - * - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "erpc_config_internal.h" -#include "erpc_framed_transport.hpp" -#include "erpc_manually_constructed.hpp" -#include "erpc_mbf_setup.h" -#include "erpc_message_buffer.hpp" -#include "erpc_rpmsg_lite_base_transport.hpp" - -extern "C" { -#include "rpmsg_lite.h" -} - -using namespace erpc; - -#define TIMEOUT_MS 10 - -//////////////////////////////////////////////////////////////////////////////// -// Classes -//////////////////////////////////////////////////////////////////////////////// - -/*! - * @brief RPMsg TTY message buffer factory - */ -class RPMsgTTYMessageBufferFactory : public MessageBufferFactory -{ -public: - /*! - * @brief Constructor. - * - * @param [in] rpmsg Pointer to instance of RPMSG lite. - */ - explicit RPMsgTTYMessageBufferFactory(struct rpmsg_lite_instance *rpmsg) { m_rpmsg = rpmsg; } - - /*! - * @brief Destructor - */ - virtual ~RPMsgTTYMessageBufferFactory(void) {} - - /*! - * @brief This function creates new message buffer. - * - * @return MessageBuffer New created MessageBuffer. - */ - virtual MessageBuffer create(void) - { - void *buf = NULL; - uint32_t size = 0; - buf = rpmsg_lite_alloc_tx_buffer(m_rpmsg, &size, TIMEOUT_MS); - - erpc_assert(NULL != buf); - return MessageBuffer(&(reinterpret_cast(buf))[sizeof(FramedTransport::Header)], - size - sizeof(FramedTransport::Header)); - } - - /*! - * @brief This function disposes message buffer. - * - * @param[in] buf MessageBuffer to dispose. - */ - virtual void dispose(MessageBuffer *buf) - { - erpc_assert(buf != NULL); - void *tmp = reinterpret_cast(buf->get()); - if (tmp != NULL) - { - int32_t ret; - ret = rpmsg_lite_release_rx_buffer( - m_rpmsg, reinterpret_cast(reinterpret_cast(tmp) - sizeof(FramedTransport::Header))); - if (ret != RL_SUCCESS) - { - // error - } - } - } - - virtual erpc_status_t prepareServerBufferForSend(MessageBuffer *message) - { - erpc_status_t status; - - dispose(message); - *message = create(); - if (message->get() != NULL) - { - status = kErpcStatus_Success; - } - else - { - status = kErpcStatus_MemoryError; - } - - return status; - } - - virtual bool createServerBuffer(void) { return false; } - -protected: - struct rpmsg_lite_instance *m_rpmsg; /*!< Pointer to instance of RPMSG lite. */ -}; - -//////////////////////////////////////////////////////////////////////////////// -// Variables -//////////////////////////////////////////////////////////////////////////////// - -ERPC_MANUALLY_CONSTRUCTED(RPMsgTTYMessageBufferFactory, s_msgFactory); - -erpc_mbf_t erpc_mbf_rpmsg_tty_init(erpc_transport_t transport) -{ - s_msgFactory.construct(reinterpret_cast(transport)->get_rpmsg_lite_instance()); - return reinterpret_cast(s_msgFactory.get()); -} diff --git a/erpc_c/setup/erpc_setup_mbf_static.cpp b/erpc_c/setup/erpc_setup_mbf_static.cpp index 6f5abbd1..52b62d33 100644 --- a/erpc_c/setup/erpc_setup_mbf_static.cpp +++ b/erpc_c/setup/erpc_setup_mbf_static.cpp @@ -38,7 +38,8 @@ class StaticMessageBufferFactory : public MessageBufferFactory */ StaticMessageBufferFactory(void) #if !ERPC_THREADS_IS(NONE) - : m_semaphore(1) + : + m_semaphore(1) #endif { (void)memset(m_freeBufferBitmap, 0xff, sizeof(m_freeBufferBitmap)); @@ -124,10 +125,41 @@ class StaticMessageBufferFactory : public MessageBufferFactory // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(StaticMessageBufferFactory, s_msgFactory); +ERPC_MANUALLY_CONSTRUCTED_STATIC(StaticMessageBufferFactory, s_msgFactory); erpc_mbf_t erpc_mbf_static_init(void) { - s_msgFactory.construct(); - return reinterpret_cast(s_msgFactory.get()); + StaticMessageBufferFactory *msgFactory; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_msgFactory.isUsed()) + { + msgFactory = NULL; + } + else + { + s_msgFactory.construct(); + msgFactory = s_msgFactory.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + msgFactory = new StaticMessageBufferFactory(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + return reinterpret_cast(msgFactory); +} + +void erpc_mbf_static_deinit(erpc_mbf_t mbf) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)mbf; + s_msgFactory.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(mbf != NULL); + + StaticMessageBufferFactory *msgFactory = reinterpret_cast(mbf); + + delete msgFactory; +#endif } diff --git a/erpc_c/setup/erpc_setup_mu.cpp b/erpc_c/setup/erpc_setup_mu.cpp index 8b5b1b5f..4875643f 100644 --- a/erpc_c/setup/erpc_setup_mu.cpp +++ b/erpc_c/setup/erpc_setup_mu.cpp @@ -16,7 +16,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(MUTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(MUTransport, s_muTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -24,7 +24,42 @@ ERPC_MANUALLY_CONSTRUCTED(MUTransport, s_transport); erpc_transport_t erpc_transport_mu_init(void *baseAddr) { - s_transport.construct(); - (void)s_transport->init(reinterpret_cast(baseAddr)); - return reinterpret_cast(s_transport.get()); + MUTransport *muTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_muTransport.isUsed()) + { + muTransport = NULL; + } + else + { + s_muTransport.construct(); + muTransport = s_muTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + muTransport = new MUTransport(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (muTransport != NULL) + { + (void)muTransport->init(reinterpret_cast(baseAddr)); + } + + return reinterpret_cast(muTransport); +} + +void erpc_transport_mu_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_muTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + MUTransport *muTransport = reinterpret_cast(transport); + + delete muTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_rpmsg_linux.cpp b/erpc_c/setup/erpc_setup_rpmsg_linux.cpp index 2fc6cdd5..1ce70c48 100644 --- a/erpc_c/setup/erpc_setup_rpmsg_linux.cpp +++ b/erpc_c/setup/erpc_setup_rpmsg_linux.cpp @@ -13,8 +13,8 @@ using namespace erpc; -ERPC_MANUALLY_CONSTRUCTED(RPMsgLinuxTransport, s_transport); -ERPC_MANUALLY_CONSTRUCTED(RPMsgEndpoint, s_endpoint); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgLinuxTransport, s_rpmsgTransport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgEndpoint, s_endpoint); erpc_transport_t erpc_transport_rpmsg_linux_init(int16_t local_addr, int8_t type, int16_t remote_addr) { @@ -22,6 +22,7 @@ erpc_transport_t erpc_transport_rpmsg_linux_init(int16_t local_addr, int8_t type int16_t _local_addr; int8_t _type; int16_t _remote_addr; + RPMsgLinuxTransport *rpmsgTransport; if (local_addr == -1) { @@ -50,23 +51,57 @@ erpc_transport_t erpc_transport_rpmsg_linux_init(int16_t local_addr, int8_t type _remote_addr = remote_addr; } - s_endpoint.construct(_local_addr, _type, _remote_addr); - s_transport.construct(s_endpoint.get(), _remote_addr); - - if (s_transport->init() == kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_endpoint.isUsed() || s_rpmsgTransport.isUsed()) + { + rpmsgTransport = NULL; + } + else + { + s_endpoint.construct(_local_addr, _type, _remote_addr); + s_rpmsgTransport.construct(s_endpoint.get(), _remote_addr); + rpmsgTransport = s_rpmsgTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + RPMsgEndpoint *endpoint = new RPMsgEndpoint(_local_addr, _type, _remote_addr); + if (endpoint == NULL) { - transport = reinterpret_cast(s_transport.get()); + rpmsgTransport = NULL; } else { - transport = NULL; + rpmsgTransport = new RPMsgLinuxTransport(endpoint, _remote_addr); + } +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(rpmsgTransport); + + if (rpmsgTransport != NULL) + { + if (rpmsgTransport->init() != kErpcStatus_Success) + { + erpc_transport_rpmsg_linux_deinit(transport); + transport = NULL; + } } return transport; } -void erpc_transport_rpmsg_linux_deinit(void) +void erpc_transport_rpmsg_linux_deinit(erpc_transport_t transport) { +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; s_endpoint.destroy(); s_transport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + RPMsgLinuxTransport *rpmsgTransport = reinterpret_cast(transport); + + delete rpmsgTransport->getRpmsgEndpoint(); + delete rpmsgTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_rpmsg_lite_master.cpp b/erpc_c/setup/erpc_setup_rpmsg_lite_master.cpp index 42632d72..75275726 100644 --- a/erpc_c/setup/erpc_setup_rpmsg_lite_master.cpp +++ b/erpc_c/setup/erpc_setup_rpmsg_lite_master.cpp @@ -33,7 +33,7 @@ char rpmsg_lite_base[SH_MEM_TOTAL_SIZE] __attribute__((section(".noinit.$rpmsg_s #error "RPMsg: Please provide your definition of rpmsg_lite_base[]!" #endif -ERPC_MANUALLY_CONSTRUCTED(RPMsgTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgTransport, s_rpmsgTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -42,16 +42,49 @@ ERPC_MANUALLY_CONSTRUCTED(RPMsgTransport, s_transport); erpc_transport_t erpc_transport_rpmsg_lite_master_init(uint32_t src_addr, uint32_t dst_addr, uint32_t rpmsg_link_id) { erpc_transport_t transport; + RPMsgTransport *rpmsgTransport; - s_transport.construct(); - if (s_transport->init(src_addr, dst_addr, rpmsg_lite_base, SH_MEM_TOTAL_SIZE, rpmsg_link_id) == kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_rpmsgTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + rpmsgTransport = NULL; } else { - transport = NULL; + s_rpmsgTransport.construct(); + rpmsgTransport = s_rpmsgTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + rpmsgTransport = new RPMsgTransport(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(rpmsgTransport); + + if (rpmsgTransport != NULL) + { + if (rpmsgTransport->init(src_addr, dst_addr, rpmsg_lite_base, SH_MEM_TOTAL_SIZE, rpmsg_link_id) != + kErpcStatus_Success) + { + erpc_transport_rpmsg_lite_master_deinit(transport); + transport = NULL; + } } return transport; } + +void erpc_transport_rpmsg_lite_master_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_rpmsgTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + RPMsgTransport *rpmsgTransport = reinterpret_cast(transport); + + delete rpmsgTransport; +#endif +} diff --git a/erpc_c/setup/erpc_setup_rpmsg_lite_remote.cpp b/erpc_c/setup/erpc_setup_rpmsg_lite_remote.cpp index d6a07d9a..b5ec2e0a 100644 --- a/erpc_c/setup/erpc_setup_rpmsg_lite_remote.cpp +++ b/erpc_c/setup/erpc_setup_rpmsg_lite_remote.cpp @@ -18,7 +18,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(RPMsgTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgTransport, s_rpmsgTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -29,17 +29,49 @@ erpc_transport_t erpc_transport_rpmsg_lite_remote_init(uint32_t src_addr, uint32 char *nameservice_name) { erpc_transport_t transport; + RPMsgTransport *rpmsgTransport; - s_transport.construct(); - if (s_transport->init(src_addr, dst_addr, start_address, rpmsg_link_id, ready, nameservice_name) == - kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_rpmsgTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + rpmsgTransport = NULL; } else { - transport = NULL; + s_rpmsgTransport.construct(); + rpmsgTransport = s_rpmsgTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + rpmsgTransport = new RPMsgTransport(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(rpmsgTransport); + + if (rpmsgTransport != NULL) + { + if (rpmsgTransport->init(src_addr, dst_addr, start_address, rpmsg_link_id, ready, nameservice_name) != + kErpcStatus_Success) + { + erpc_transport_rpmsg_lite_remote_deinit(transport); + transport = NULL; + } } return transport; } + +void erpc_transport_rpmsg_lite_remote_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_rpmsgTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + RPMsgTransport *rpmsgTransport = reinterpret_cast(transport); + + delete rpmsgTransport; +#endif +} diff --git a/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_master.cpp b/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_master.cpp index 89695d91..1ea8f2df 100644 --- a/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_master.cpp +++ b/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_master.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2020 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -11,17 +11,25 @@ #include "erpc_rpmsg_lite_rtos_transport.hpp" #include "erpc_transport_setup.h" +#if defined(__ZEPHYR__) +#include +#endif + using namespace erpc; //////////////////////////////////////////////////////////////////////////////// // Variables //////////////////////////////////////////////////////////////////////////////// -#if !defined(SH_MEM_TOTAL_SIZE) +#if !defined(SH_MEM_TOTAL_SIZE) && !defined(__ZEPHYR__) #define SH_MEM_TOTAL_SIZE (6144U) #endif -#if defined(__ICCARM__) /* IAR Workbench */ +#if defined(__ZEPHYR__) +#define SHM_MEM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) +#define SH_MEM_TOTAL_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) +void *rpmsg_lite_base = (void *)SHM_MEM_ADDR; +#elif defined(__ICCARM__) /* IAR Workbench */ #pragma location = "rpmsg_sh_mem_section" char rpmsg_lite_base[SH_MEM_TOTAL_SIZE]; #elif defined(__CC_ARM) || defined(__ARMCC_VERSION) /* Keil MDK */ @@ -32,7 +40,7 @@ char rpmsg_lite_base[SH_MEM_TOTAL_SIZE] __attribute__((section(".noinit.$rpmsg_s #error "RPMsg: Please provide your definition of rpmsg_lite_base[]!" #endif -ERPC_MANUALLY_CONSTRUCTED(RPMsgRTOSTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgRTOSTransport, s_rpmsgTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -42,16 +50,49 @@ erpc_transport_t erpc_transport_rpmsg_lite_rtos_master_init(uint32_t src_addr, u uint32_t rpmsg_link_id) { erpc_transport_t transport; + RPMsgRTOSTransport *rpmsgTransport; - s_transport.construct(); - if (s_transport->init(src_addr, dst_addr, rpmsg_lite_base, SH_MEM_TOTAL_SIZE, rpmsg_link_id) == kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_rpmsgTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + rpmsgTransport = NULL; } else { - transport = NULL; + s_rpmsgTransport.construct(); + rpmsgTransport = s_rpmsgTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + rpmsgTransport = new RPMsgRTOSTransport(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(rpmsgTransport); + + if (rpmsgTransport != NULL) + { + if (rpmsgTransport->init(src_addr, dst_addr, rpmsg_lite_base, SH_MEM_TOTAL_SIZE, rpmsg_link_id) != + kErpcStatus_Success) + { + erpc_transport_rpmsg_lite_rtos_master_deinit(transport); + transport = NULL; + } } return transport; } + +void erpc_transport_rpmsg_lite_rtos_master_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_rpmsgTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + RPMsgRTOSTransport *rpmsgTransport = reinterpret_cast(transport); + + delete rpmsgTransport; +#endif +} diff --git a/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp b/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp index 6ea4fefd..544d50f5 100644 --- a/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp +++ b/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp @@ -18,7 +18,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(RPMsgRTOSTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgRTOSTransport, s_rpmsgTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -29,17 +29,49 @@ erpc_transport_t erpc_transport_rpmsg_lite_rtos_remote_init(uint32_t src_addr, u char *nameservice_name) { erpc_transport_t transport; + RPMsgRTOSTransport *rpmsgTransport; - s_transport.construct(); - if (s_transport->init(src_addr, dst_addr, start_address, rpmsg_link_id, ready, nameservice_name) == - kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_rpmsgTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + rpmsgTransport = NULL; } else { - transport = NULL; + s_rpmsgTransport.construct(); + rpmsgTransport = s_rpmsgTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + rpmsgTransport = new RPMsgRTOSTransport(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(rpmsgTransport); + + if (rpmsgTransport != NULL) + { + if (rpmsgTransport->init(src_addr, dst_addr, start_address, rpmsg_link_id, ready, nameservice_name) != + kErpcStatus_Success) + { + erpc_transport_rpmsg_lite_rtos_remote_deinit(transport); + transport = NULL; + } } return transport; } + +void erpc_transport_rpmsg_lite_rtos_remote_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_rpmsgTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + RPMsgRTOSTransport *rpmsgTransport = reinterpret_cast(transport); + + delete rpmsgTransport; +#endif +} diff --git a/erpc_c/setup/erpc_setup_rpmsg_tty_rtos_remote.cpp b/erpc_c/setup/erpc_setup_rpmsg_tty_rtos_remote.cpp index 60214efd..62d24254 100644 --- a/erpc_c/setup/erpc_setup_rpmsg_tty_rtos_remote.cpp +++ b/erpc_c/setup/erpc_setup_rpmsg_tty_rtos_remote.cpp @@ -18,7 +18,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(RPMsgTTYRTOSTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(RPMsgTTYRTOSTransport, s_rpmsgTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -29,22 +29,49 @@ erpc_transport_t erpc_transport_rpmsg_lite_tty_rtos_remote_init(uint32_t src_add rpmsg_ready_cb ready, char *nameservice_name) { erpc_transport_t transport; + RPMsgTTYRTOSTransport *rpmsgTransport; - s_transport.construct(); - if (s_transport->init(src_addr, dst_addr, start_address, rpmsg_link_id, ready, nameservice_name) == - kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_rpmsgTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + rpmsgTransport = NULL; } else { - transport = NULL; + s_rpmsgTransport.construct(); + rpmsgTransport = s_rpmsgTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + rpmsgTransport = new RPMsgTTYRTOSTransport(); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(rpmsgTransport); + + if (rpmsgTransport != NULL) + { + if (rpmsgTransport->init(src_addr, dst_addr, start_address, rpmsg_link_id, ready, nameservice_name) != + kErpcStatus_Success) + { + erpc_transport_rpmsg_lite_tty_rtos_remote_deinit(transport); + transport = NULL; + } } return transport; } -void erpc_transport_rpmsg_lite_tty_rtos_deinit(void) +void erpc_transport_rpmsg_lite_tty_rtos_remote_deinit(erpc_transport_t transport) { - s_transport.destroy(); +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_rpmsgTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + RPMsgTTYRTOSTransport *rpmsgTransport = reinterpret_cast(transport); + + delete rpmsgTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_serial.cpp b/erpc_c/setup/erpc_setup_serial.cpp index ff0690d6..5c62385b 100644 --- a/erpc_c/setup/erpc_setup_serial.cpp +++ b/erpc_c/setup/erpc_setup_serial.cpp @@ -18,7 +18,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(SerialTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(SerialTransport, s_serialTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -27,18 +27,50 @@ ERPC_MANUALLY_CONSTRUCTED(SerialTransport, s_transport); erpc_transport_t erpc_transport_serial_init(const char *portName, long baudRate) { erpc_transport_t transport; + SerialTransport *serialTransport; const uint8_t vtime = 0; const uint8_t vmin = 1; - s_transport.construct(portName, baudRate); - if (s_transport->init(vtime, vmin) == kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_serialTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + serialTransport = NULL; } else { - transport = NULL; + s_serialTransport.construct(portName, baudRate); + serialTransport = s_serialTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + serialTransport = new SerialTransport(portName, baudRate); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(serialTransport); + + if (serialTransport != NULL) + { + if (serialTransport->init(vtime, vmin) != kErpcStatus_Success) + { + erpc_transport_serial_deinit(transport); + transport = NULL; + } } return transport; } + +void erpc_transport_serial_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_serialTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + SerialTransport *serialTransport = reinterpret_cast(transport); + + delete serialTransport; +#endif +} diff --git a/erpc_c/setup/erpc_setup_spi_master.cpp b/erpc_c/setup/erpc_setup_spi_master.cpp index eeaa4723..7dcbfd0c 100644 --- a/erpc_c/setup/erpc_setup_spi_master.cpp +++ b/erpc_c/setup/erpc_setup_spi_master.cpp @@ -17,7 +17,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(SpiMasterTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(SpiMasterTransport, s_spiTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -25,7 +25,42 @@ ERPC_MANUALLY_CONSTRUCTED(SpiMasterTransport, s_transport); erpc_transport_t erpc_transport_spi_master_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz) { - s_transport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + SpiMasterTransport *spiTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_spiTransport.isUsed()) + { + spiTransport = NULL; + } + else + { + s_spiTransport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); + spiTransport = s_spiTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + spiTransport = new SpiMasterTransport(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (spiTransport != NULL) + { + (void)spiTransport->init(); + } + + return reinterpret_cast(spiTransport); +} + +void erpc_transport_spi_master_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_spiTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + SpiMasterTransport *spiTransport = reinterpret_cast(transport); + + delete spiTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_spi_slave.cpp b/erpc_c/setup/erpc_setup_spi_slave.cpp index 8d569b3f..ba8daf8e 100644 --- a/erpc_c/setup/erpc_setup_spi_slave.cpp +++ b/erpc_c/setup/erpc_setup_spi_slave.cpp @@ -17,7 +17,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(SpiSlaveTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(SpiSlaveTransport, s_spiTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -25,7 +25,42 @@ ERPC_MANUALLY_CONSTRUCTED(SpiSlaveTransport, s_transport); erpc_transport_t erpc_transport_spi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz) { - s_transport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + SpiSlaveTransport *spiTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_spiTransport.isUsed()) + { + spiTransport = NULL; + } + else + { + s_spiTransport.construct(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); + spiTransport = s_spiTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + spiTransport = new SpiSlaveTransport(reinterpret_cast(baseAddr), baudRate, srcClock_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (spiTransport != NULL) + { + (void)spiTransport->init(); + } + + return reinterpret_cast(spiTransport); +} + +void erpc_transport_spi_slave_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_spiTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + SpiSlaveTransport *spiTransport = reinterpret_cast(transport); + + delete spiTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_spidev_master.cpp b/erpc_c/setup/erpc_setup_spidev_master.cpp index bd1eef4e..92b94f79 100644 --- a/erpc_c/setup/erpc_setup_spidev_master.cpp +++ b/erpc_c/setup/erpc_setup_spidev_master.cpp @@ -16,7 +16,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(SpidevMasterTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(SpidevMasterTransport, s_spidevTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -24,7 +24,42 @@ ERPC_MANUALLY_CONSTRUCTED(SpidevMasterTransport, s_transport); erpc_transport_t erpc_transport_spidev_master_init(const char *spidev, uint32_t speed_Hz) { - s_transport.construct(spidev, speed_Hz); - (void)s_transport->init(); - return reinterpret_cast(s_transport.get()); + SpidevMasterTransport *spidevTransport; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_spidevTransport.isUsed()) + { + spidevTransport = NULL; + } + else + { + s_spidevTransport.construct(spidev, speed_Hz); + spidevTransport = s_spidevTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + spidevTransport = new SpidevMasterTransport(spidev, speed_Hz); +#else +#error "Unknown eRPC allocation policy!" +#endif + + if (spidevTransport != NULL) + { + (void)spidevTransport->init(); + } + + return reinterpret_cast(spidevTransport); +} + +void erpc_transport_spidev_master_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_spidevTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + SpidevMasterTransport *spidevTransport = reinterpret_cast(transport); + + delete spidevTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_tcp.cpp b/erpc_c/setup/erpc_setup_tcp.cpp index ebf21209..793354b6 100644 --- a/erpc_c/setup/erpc_setup_tcp.cpp +++ b/erpc_c/setup/erpc_setup_tcp.cpp @@ -17,7 +17,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(TCPTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(TCPTransport, s_tcpTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -26,21 +26,57 @@ ERPC_MANUALLY_CONSTRUCTED(TCPTransport, s_transport); erpc_transport_t erpc_transport_tcp_init(const char *host, uint16_t port, bool isServer) { erpc_transport_t transport; + TCPTransport *tcpTransport; - s_transport.construct(host, port, isServer); - if (kErpcStatus_Success == s_transport->open()) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_tcpTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + tcpTransport = NULL; } else { - transport = NULL; + s_tcpTransport.construct(host, port, isServer); + tcpTransport = s_tcpTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + tcpTransport = new TCPTransport(host, port, isServer); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(tcpTransport); + + if (tcpTransport != NULL) + { + if (tcpTransport->open() != kErpcStatus_Success) + { + erpc_transport_tcp_deinit(transport); + transport = NULL; + } } return transport; } -void erpc_transport_tcp_close(void) +void erpc_transport_tcp_close(erpc_transport_t transport) { - s_transport.get()->close(true); + erpc_assert(transport != NULL); + + TCPTransport *tcpTransport = reinterpret_cast(transport); + + tcpTransport->close(true); +} + +void erpc_transport_tcp_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_tcpTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + TCPTransport *tcpTransport = reinterpret_cast(transport); + + delete tcpTransport; +#endif } diff --git a/erpc_c/setup/erpc_setup_uart_cmsis.cpp b/erpc_c/setup/erpc_setup_uart_cmsis.cpp index 615601f3..4c1115fa 100644 --- a/erpc_c/setup/erpc_setup_uart_cmsis.cpp +++ b/erpc_c/setup/erpc_setup_uart_cmsis.cpp @@ -18,7 +18,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(UartTransport, s_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(UartTransport, s_uartTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -27,16 +27,48 @@ ERPC_MANUALLY_CONSTRUCTED(UartTransport, s_transport); erpc_transport_t erpc_transport_cmsis_uart_init(void *uartDrv) { erpc_transport_t transport; + UartTransport *uartTransport; - s_transport.construct(reinterpret_cast(uartDrv)); - if (s_transport->init() == kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_uartTransport.isUsed()) { - transport = reinterpret_cast(s_transport.get()); + uartTransport = NULL; } else { - transport = NULL; + s_uartTransport.construct(reinterpret_cast(uartDrv)); + uartTransport = s_uartTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + uartTransport = new UartTransport(reinterpret_cast(uartDrv)); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(uartTransport); + + if (uartTransport != NULL) + { + if (uartTransport->init() != kErpcStatus_Success) + { + erpc_transport_cmsis_uart_deinit(transport); + transport = NULL; + } } return transport; } + +void erpc_transport_cmsis_uart_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_uartTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + UartTransport *uartTransport = reinterpret_cast(transport); + + delete uartTransport; +#endif +} diff --git a/erpc_c/setup/erpc_setup_uart_zephyr.cpp b/erpc_c/setup/erpc_setup_uart_zephyr.cpp new file mode 100644 index 00000000..42c7242f --- /dev/null +++ b/erpc_c/setup/erpc_setup_uart_zephyr.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 2023 NXP + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "erpc_manually_constructed.hpp" +#include "erpc_transport_setup.h" +#include "erpc_uart_zephyr_transport.hpp" + +using namespace erpc; + +//////////////////////////////////////////////////////////////////////////////// +// Variables +//////////////////////////////////////////////////////////////////////////////// + +ERPC_MANUALLY_CONSTRUCTED(UartTransport, s_transport); + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +erpc_transport_t erpc_transport_zephyr_uart_init(void *dev) +{ + erpc_transport_t transport; + + s_transport.construct((struct device *)dev); + if (s_transport->init() == kErpcStatus_Success) + { + transport = reinterpret_cast(s_transport.get()); + } + else + { + transport = NULL; + } + + return transport; +} diff --git a/erpc_c/setup/erpc_setup_usb_cdc.cpp b/erpc_c/setup/erpc_setup_usb_cdc.cpp index 46f26d67..4cb9d678 100644 --- a/erpc_c/setup/erpc_setup_usb_cdc.cpp +++ b/erpc_c/setup/erpc_setup_usb_cdc.cpp @@ -17,7 +17,7 @@ using namespace erpc; // Variables //////////////////////////////////////////////////////////////////////////////// -ERPC_MANUALLY_CONSTRUCTED(UsbCdcTransport, s_usb_transport); +ERPC_MANUALLY_CONSTRUCTED_STATIC(UsbCdcTransport, s_usbTransport); //////////////////////////////////////////////////////////////////////////////// // Code @@ -27,19 +27,52 @@ erpc_transport_t erpc_transport_usb_cdc_init(void *serialHandle, void *serialCon uint8_t *usbRingBuffer, uint32_t usbRingBufferLength) { erpc_transport_t transport; + UsbCdcTransport *usbTransport; - s_usb_transport.construct( - reinterpret_cast(serialHandle), reinterpret_cast(serialConfig), - reinterpret_cast(usbCdcConfig), reinterpret_cast(usbRingBuffer), - reinterpret_cast(usbRingBufferLength)); - if (s_usb_transport->init() == kErpcStatus_Success) +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (s_usbTransport.isUsed()) { - transport = reinterpret_cast(s_usb_transport.get()); + usbTransport = NULL; } else { - transport = NULL; + s_usbTransport.construct( + reinterpret_cast(serialHandle), reinterpret_cast(serialConfig), + reinterpret_cast(usbCdcConfig), usbRingBuffer, usbRingBufferLength); + usbTransport = s_usbTransport.get(); + } +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + usbTransport = new UsbCdcTransport( + reinterpret_cast(serialHandle), reinterpret_cast(serialConfig), + reinterpret_cast(usbCdcConfig), usbRingBuffer, usbRingBufferLength); +#else +#error "Unknown eRPC allocation policy!" +#endif + + transport = reinterpret_cast(usbTransport); + + if (usbTransport != NULL) + { + if (usbTransport->init() != kErpcStatus_Success) + { + erpc_transport_usb_cdc_deinit(transport); + transport = NULL; + } } return transport; } + +void erpc_transport_usb_cdc_deinit(erpc_transport_t transport) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + (void)transport; + s_usbTransport.destroy(); +#elif ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(transport != NULL); + + UsbCdcTransport *usbTransport = reinterpret_cast(transport); + + delete usbTransport; +#endif +} diff --git a/erpc_c/setup/erpc_transport_setup.h b/erpc_c/setup/erpc_transport_setup.h index a86f9840..fa90a6af 100644 --- a/erpc_c/setup/erpc_transport_setup.h +++ b/erpc_c/setup/erpc_transport_setup.h @@ -40,96 +40,99 @@ extern "C" { //! @name Transport setup //@{ -//! @name CMSIS UART transport setup +//! @name DSPI transport setup //@{ /*! - * @brief Create a CMSIS UART transport. + * @brief Create a DSPI master transport. * - * Create a CMSIS UART transport instance, to be used on both the server - * and the client side. + * Create DSPI master transport instance, to be used at master core. * - * @param[in] uartDrv CMSIS USART driver structure address (Driver Control Block). + * @param[in] baseAddr Base address of DSPI peripheral used in this transport layer. + * @param[in] baudRate DSPI baud rate. + * @param[in] srcClock_Hz DSPI source clock in Hz. * * @return Return NULL or erpc_transport_t instance pointer. */ -erpc_transport_t erpc_transport_cmsis_uart_init(void *uartDrv); -//@} +erpc_transport_t erpc_transport_dspi_master_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); -//! @name Host PC serial port transport setup -//@{ +/*! + * @brief Deinitialize DSPI master transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_dspi_master_deinit(erpc_transport_t transport); /*! - * @brief Create a host PC serial port transport. + * @brief Create a DSPI slave transport. * - * Create a host PC serial port transport instance. + * Create DSPI slave transport instance, to be used at slave core. * - * @param[in] portName Port name. - * @param[in] baudRate Baud rate. + * @param[in] baseAddr Base address of DSPI peripheral used in this transport layer. + * @param[in] baudRate DSPI baud rate. + * @param[in] srcClock_Hz DSPI source clock in Hz. * * @return Return NULL or erpc_transport_t instance pointer. */ -erpc_transport_t erpc_transport_serial_init(const char *portName, long baudRate); +erpc_transport_t erpc_transport_dspi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); + +/*! + * @brief Deinitialize DSPI slave transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_dspi_slave_deinit(erpc_transport_t transport); + //@} -//! @name SPI transport setup +//! @name I2C transport setup //@{ /*! - * @brief Create a SPI master transport. + * @brief Create an I2C slave transport. * - * Create SPI master transport instance, to be used at master core. + * Create I2C slave transport instance, to be used at slave core. * - * @param[in] baseAddr Base address of SPI peripheral used in this transport layer. + * @param[in] baseAddr Base address of I2C peripheral used in this transport layer. * @param[in] baudRate SPI baud rate. - * @param[in] srcClock_Hz SPI source clock in Hz. + * @param[in] srcClock_Hz I2C source clock in Hz. * * @return Return NULL or erpc_transport_t instance pointer. */ -erpc_transport_t erpc_transport_spi_master_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); +erpc_transport_t erpc_transport_i2c_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); /*! - * @brief Create a SPI slave transport. - * - * Create SPI slave transport instance, to be used at slave core. - * - * @param[in] baseAddr Base address of SPI peripheral used in this transport layer. - * @param[in] baudRate SPI baud rate. - * @param[in] srcClock_Hz SPI source clock in Hz. + * @brief Deinitialize I2C slave transport. * - * @return Return NULL or erpc_transport_t instance pointer. + * @param[in] transport Transport which was initialized with init function. */ -erpc_transport_t erpc_transport_spi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); +void erpc_transport_i2c_slave_deinit(erpc_transport_t transport); + //@} -//! @name DSPI transport setup +//! @name LPI2C transport setup //@{ /*! - * @brief Create a DSPI master transport. + * @brief Create an LPI2C slave transport. * - * Create DSPI master transport instance, to be used at master core. + * Create LPI2C slave transport instance, to be used at slave core. * - * @param[in] baseAddr Base address of DSPI peripheral used in this transport layer. - * @param[in] baudRate DSPI baud rate. - * @param[in] srcClock_Hz DSPI source clock in Hz. + * @param[in] baseAddr Base address of LPI2C peripheral used in this transport layer. + * @param[in] baudRate SPI baud rate. + * @param[in] srcClock_Hz LPI2C source clock in Hz. * * @return Return NULL or erpc_transport_t instance pointer. */ -erpc_transport_t erpc_transport_dspi_master_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); +erpc_transport_t erpc_transport_lpi2c_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); /*! - * @brief Create a DSPI slave transport. - * - * Create DSPI slave transport instance, to be used at slave core. + * @brief Deinitialize LPI2C slave transport. * - * @param[in] baseAddr Base address of DSPI peripheral used in this transport layer. - * @param[in] baudRate DSPI baud rate. - * @param[in] srcClock_Hz DSPI source clock in Hz. - * - * @return Return NULL or erpc_transport_t instance pointer. + * @param[in] transport Transport which was initialized with init function. */ -erpc_transport_t erpc_transport_dspi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); +void erpc_transport_lpi2c_slave_deinit(erpc_transport_t transport); + //@} //! @name LPSPI transport setup @@ -147,22 +150,14 @@ erpc_transport_t erpc_transport_dspi_slave_init(void *baseAddr, uint32_t baudRat * @return Return NULL or erpc_transport_t instance pointer. */ erpc_transport_t erpc_transport_lpspi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); -//@} - -//! @name SPIdev transport setup -//@{ /*! - * @brief Create a SPIdev transport. - * - * Create SPIdev master transport instance, to be used at master core. - * - * @param[in] spidev SPI device name. - * @param[in] speed_Hz SPI clock speed in Hz. + * @brief Deinitialize LPSPI slave transport. * - * @return Return NULL or erpc_transport_t instance pointer. + * @param[in] transport Transport which was initialized with init function. */ -erpc_transport_t erpc_transport_spidev_master_init(const char *spidev, uint32_t speed_Hz); +void erpc_transport_lpspi_slave_deinit(erpc_transport_t transport); + //@} //! @name MU transport setup @@ -179,6 +174,45 @@ erpc_transport_t erpc_transport_spidev_master_init(const char *spidev, uint32_t * @return Return NULL or erpc_transport_t instance pointer. */ erpc_transport_t erpc_transport_mu_init(void *baseAddr); + +/*! + * @brief Deinitialize MU transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_mu_deinit(erpc_transport_t transport); + +//@} + +//! @name Linux RPMSG endpoint setup +//@{ + +/*! + * @brief Create an Linux RPMSG endpoint transport. + * + * This function is using RPMSG endpoints based on this implementation: + * github.com/nxp-mcuxpresso/rpmsg-sysfs/tree/0aa1817545a765c200b1b2f9b6680a420dcf9171 . + * + * When local/remote address is set to '-1', then default addresses will be used. + * When type is set to '0', then Datagram model will be used, else Stream. + * + * @param[in] local_addr Local endpoint address. + * @param[in] type Datagram (0) or Stream (1). + * @param[in] remote_addr Remote endpoint address. + * + * @return Return NULL or erpc_transport_t instance pointer. + */ +erpc_transport_t erpc_transport_rpmsg_linux_init(int16_t local_addr, int8_t type, int16_t remote_addr); + +/*! + * @brief Deinitialize an Linux RPMSG endpoint transport. + * + * This function deinitialize the Linux RPMSG endpoint transport. + * + * @param[in] transport Transport which was returned from init function. + */ +void erpc_transport_rpmsg_linux_deinit(erpc_transport_t transport); + //@} //! @name RPMsg-Lite transport setup @@ -198,6 +232,13 @@ erpc_transport_t erpc_transport_mu_init(void *baseAddr); */ erpc_transport_t erpc_transport_rpmsg_lite_master_init(uint32_t src_addr, uint32_t dst_addr, uint32_t rpmsg_link_id); +/*! + * @brief Deinitialize RPMsg-Lite transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_rpmsg_lite_master_deinit(erpc_transport_t transport); + /*! * @brief Create an RPMsg-Lite transport. * @@ -221,6 +262,13 @@ erpc_transport_t erpc_transport_rpmsg_lite_remote_init(uint32_t src_addr, uint32 uint32_t rpmsg_link_id, rpmsg_ready_cb ready, char *nameservice_name); +/*! + * @brief Deinitialize RPMsg-Lite transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_rpmsg_lite_remote_deinit(erpc_transport_t transport); + /*! * @brief Create an RPMsg-Lite RTOS transport. * @@ -236,6 +284,13 @@ erpc_transport_t erpc_transport_rpmsg_lite_remote_init(uint32_t src_addr, uint32 erpc_transport_t erpc_transport_rpmsg_lite_rtos_master_init(uint32_t src_addr, uint32_t dst_addr, uint32_t rpmsg_link_id); +/*! + * @brief Deinitialize RPMsg-Lite RTOS transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_rpmsg_lite_rtos_master_deinit(erpc_transport_t transport); + /*! * @brief Create an RPMsg-Lite RTOS transport. * @@ -258,6 +313,13 @@ erpc_transport_t erpc_transport_rpmsg_lite_rtos_remote_init(uint32_t src_addr, u uint32_t rpmsg_link_id, rpmsg_ready_cb ready, char *nameservice_name); +/*! + * @brief Deinitialize RPMsg-Lite RTOS transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_rpmsg_lite_rtos_remote_deinit(erpc_transport_t transport); + /*! * @brief Create an RPMsg-Lite TTY transport. * @@ -284,37 +346,104 @@ erpc_transport_t erpc_transport_rpmsg_lite_tty_rtos_remote_init(uint32_t src_add /*! * @brief Deinitialize an RPMSG lite tty rtos transport. * - * This function deinitializes the RPMSG lite tty rtos transport. + * This function deinitialize the RPMSG lite tty rtos transport. + * + * @param[in] transport Transport which was returned from init function. */ -void erpc_transport_rpmsg_lite_tty_rtos_deinit(void); +void erpc_transport_rpmsg_lite_tty_rtos_remote_deinit(erpc_transport_t transport); //@} -//! @name Linux RPMSG endpoint setup +//! @name Host PC serial port transport setup //@{ /*! - * @brief Create an Linux RPMSG endpoint transport. + * @brief Create a host PC serial port transport. * - * This function is using RPMSG endpoints based on this implementation: - * github.com/nxp-mcuxpresso/rpmsg-sysfs/tree/0aa1817545a765c200b1b2f9b6680a420dcf9171 . + * Create a host PC serial port transport instance. * - * When local/remote address is set to '-1', then default addresses will be used. - * When type is set to '0', then Datagram model will be used, else Stream. + * @param[in] portName Port name. + * @param[in] baudRate Baud rate. * - * @param[in] local_addr Local endpoint address. - * @param[in] type Datagram (0) or Stream (1). - * @param[in] remote_addr Remote endpoint address. + * @return Return NULL or erpc_transport_t instance pointer. + */ +erpc_transport_t erpc_transport_serial_init(const char *portName, long baudRate); + +/*! + * @brief Deinitialize a host PC serial port transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_serial_deinit(erpc_transport_t transport); + +//@} + +//! @name SPI transport setup +//@{ + +/*! + * @brief Create a SPI master transport. + * + * Create SPI master transport instance, to be used at master core. + * + * @param[in] baseAddr Base address of SPI peripheral used in this transport layer. + * @param[in] baudRate SPI baud rate. + * @param[in] srcClock_Hz SPI source clock in Hz. * * @return Return NULL or erpc_transport_t instance pointer. */ -erpc_transport_t erpc_transport_rpmsg_linux_init(int16_t local_addr, int8_t type, int16_t remote_addr); +erpc_transport_t erpc_transport_spi_master_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); /*! - * @brief Deinitialize an Linux RPMSG endpoint transport. + * @brief Deinitialize SPI master transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_spi_master_deinit(erpc_transport_t transport); + +/*! + * @brief Create a SPI slave transport. + * + * Create SPI slave transport instance, to be used at slave core. + * + * @param[in] baseAddr Base address of SPI peripheral used in this transport layer. + * @param[in] baudRate SPI baud rate. + * @param[in] srcClock_Hz SPI source clock in Hz. + * + * @return Return NULL or erpc_transport_t instance pointer. + */ +erpc_transport_t erpc_transport_spi_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); + +/*! + * @brief Deinitialize SPI slave transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_spi_slave_deinit(erpc_transport_t transport); + +//@} + +//! @name SPIdev transport setup +//@{ + +/*! + * @brief Create a SPIdev transport. + * + * Create SPIdev master transport instance, to be used at master core. + * + * @param[in] spidev SPI device name. + * @param[in] speed_Hz SPI clock speed in Hz. * - * This function deinitializes the Linux RPMSG endpoint transport. + * @return Return NULL or erpc_transport_t instance pointer. */ -void erpc_transport_rpmsg_linux_deinit(void); +erpc_transport_t erpc_transport_spidev_master_init(const char *spidev, uint32_t speed_Hz); + +/*! + * @brief Deinitialize SPIdev transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_spidev_master_deinit(erpc_transport_t transport); + //@} //! @name TCP transport setup @@ -344,9 +473,53 @@ erpc_transport_t erpc_transport_tcp_init(const char *host, uint16_t port, bool i * socket or select() shoudl be used * For client, close server connection * - * @return Return TRUE if listen/connection successful + * @param[in] transport Transport which was returned from init function. + */ +void erpc_transport_tcp_close(erpc_transport_t transport); + +/*! + * @brief Deinitialize TCP transport. + * + * @param[in] transport Transport which was initialized with init function. */ -void erpc_transport_tcp_close(void); +void erpc_transport_tcp_deinit(erpc_transport_t transport); + +//@} + +//! @name CMSIS UART transport setup +//@{ + +/*! + * @brief Create a CMSIS UART transport. + * + * Create a CMSIS UART transport instance, to be used on both the server + * and the client side. + * + * @param[in] uartDrv CMSIS USART driver structure address (Driver Control Block). + * + * @return Return NULL or erpc_transport_t instance pointer. + */ +erpc_transport_t erpc_transport_cmsis_uart_init(void *uartDrv); + +/*! + * @brief Deinitialize CMSIS UART transport. + * + * @param[in] transport Transport which was initialized with init function. + */ +void erpc_transport_cmsis_uart_deinit(erpc_transport_t transport); + +/*! + * @brief Create a Zephyr UART transport. + * + * Create a Zephyr UART transport instance, to be used on both the server + * and the client side. + * + * @param[in] dev Zephyr UART device address. + * + * @return Return NULL or erpc_transport_t instance pointer. + */ +erpc_transport_t erpc_transport_zephyr_uart_init(void *dev); + //@} //! @name USB CDC transport setup @@ -371,40 +544,14 @@ void erpc_transport_tcp_close(void); */ erpc_transport_t erpc_transport_usb_cdc_init(void *serialHandle, void *serialConfig, void *usbCdcConfig, uint8_t *usbRingBuffer, uint32_t usbRingBufferLength); -//@} - -//! @name I2C transport setup -//@{ /*! - * @brief Create an I2C slave transport. + * @brief Deinitialize USB CDC transport. * - * Create I2C slave transport instance, to be used at slave core. - * - * @param[in] baseAddr Base address of I2C peripheral used in this transport layer. - * @param[in] baudRate SPI baud rate. - * @param[in] srcClock_Hz I2C source clock in Hz. - * - * @return Return NULL or erpc_transport_t instance pointer. + * @param[in] transport Transport which was initialized with init function. */ -erpc_transport_t erpc_transport_i2c_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); -//@} - -//! @name LPI2C transport setup -//@{ +void erpc_transport_usb_cdc_deinit(erpc_transport_t transport); -/*! - * @brief Create an LPI2C slave transport. - * - * Create LPI2C slave transport instance, to be used at slave core. - * - * @param[in] baseAddr Base address of LPI2C peripheral used in this transport layer. - * @param[in] baudRate SPI baud rate. - * @param[in] srcClock_Hz LPI2C source clock in Hz. - * - * @return Return NULL or erpc_transport_t instance pointer. - */ -erpc_transport_t erpc_transport_lpi2c_slave_init(void *baseAddr, uint32_t baudRate, uint32_t srcClock_Hz); //@} //@} diff --git a/erpc_c/transports/erpc_dspi_master_transport.cpp b/erpc_c/transports/erpc_dspi_master_transport.cpp index fa2abc8d..5e5531a3 100644 --- a/erpc_c/transports/erpc_dspi_master_transport.cpp +++ b/erpc_c/transports/erpc_dspi_master_transport.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -100,10 +100,8 @@ static inline void DSpidevMasterTransport_WaitForSlaveReadyMarker(SPI_Type *spiB } #endif -DspiMasterTransport::DspiMasterTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) -: m_spiBaseAddr(spiBaseAddr) -, m_baudRate(baudRate) -, m_srcClock_Hz(srcClock_Hz) +DspiMasterTransport::DspiMasterTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) : +m_spiBaseAddr(spiBaseAddr), m_baudRate(baudRate), m_srcClock_Hz(srcClock_Hz) { } @@ -155,11 +153,26 @@ erpc_status_t DspiMasterTransport::underlyingSend(const uint8_t *data, uint32_t { status_t status; dspi_transfer_t masterXfer; + uint32_t header_size = reserveHeaderSize(); + /* send the header first */ masterXfer.txData = (uint8_t *)data; masterXfer.rxData = NULL; - masterXfer.dataSize = size; + masterXfer.dataSize = header_size; masterXfer.configFlags = (uint32_t)kDSPI_MasterCtar0 | (uint32_t)kDSPI_MasterPcs0; + /* send the header first */ +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + DSpidevMasterTransport_WaitForSlaveReadyGpio(); +#endif + + status = DSPI_MasterTransferBlocking(m_spiBaseAddr, &masterXfer); +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + s_isSlaveReady = false; +#endif + + /* send the payload now */ + masterXfer.txData = (uint8_t *)data + header_size; + masterXfer.dataSize = size - header_size; #ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO DSpidevMasterTransport_WaitForSlaveReadyGpio(); diff --git a/erpc_c/transports/erpc_dspi_master_transport.hpp b/erpc_c/transports/erpc_dspi_master_transport.hpp index 3605542d..bba057c5 100644 --- a/erpc_c/transports/erpc_dspi_master_transport.hpp +++ b/erpc_c/transports/erpc_dspi_master_transport.hpp @@ -11,6 +11,7 @@ #define _EMBEDDED_RPC__DSPI_MASTER_TRANSPORT_H_ #include "erpc_framed_transport.hpp" + #include extern "C" { @@ -63,6 +64,9 @@ class DspiMasterTransport : public FramedTransport uint32_t m_srcClock_Hz; /*!< Source clock of DSPI peripheral used in this transport layer */ private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from DSPI peripheral. * @@ -72,7 +76,7 @@ class DspiMasterTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed DSPI failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to DSPI peripheral. @@ -83,7 +87,7 @@ class DspiMasterTransport : public FramedTransport * @retval kErpcStatus_SendFailed DSPI failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_dspi_slave_transport.cpp b/erpc_c/transports/erpc_dspi_slave_transport.cpp index 1c5a9487..4757a4f3 100644 --- a/erpc_c/transports/erpc_dspi_slave_transport.cpp +++ b/erpc_c/transports/erpc_dspi_slave_transport.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -8,9 +8,10 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "erpc_dspi_slave_transport.hpp" + #include #include -#include "erpc_dspi_slave_transport.hpp" extern "C" { #include "board.h" @@ -93,13 +94,11 @@ static void DSPI_SlaveUserCallback(SPI_Type *base, dspi_slave_handle_t *handle, transport->transfer_cb(); } -DspiSlaveTransport::DspiSlaveTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) -: m_spiBaseAddr(spiBaseAddr) -, m_baudRate(baudRate) -, m_srcClock_Hz(srcClock_Hz) -, m_isInited(false) +DspiSlaveTransport::DspiSlaveTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) : +m_spiBaseAddr(spiBaseAddr), m_baudRate(baudRate), m_srcClock_Hz(srcClock_Hz), m_isInited(false) #if ERPC_THREADS -, m_txrxSemaphore() +, +m_txrxSemaphore() #endif { s_dspi_slave_instance = this; @@ -175,24 +174,81 @@ erpc_status_t DspiSlaveTransport::underlyingSend(const uint8_t *data, uint32_t s status_t status; dspi_transfer_t slaveXfer = { 0 }; s_isTransferCompleted = false; + uint32_t header_size = reserveHeaderSize(); + /* send the header first */ #ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO slaveXfer.txData = (uint8_t *)data; slaveXfer.rxData = NULL; - slaveXfer.dataSize = size; + slaveXfer.dataSize = header_size; + slaveXfer.configFlags = (uint32_t)kDSPI_SlaveCtar0; + { +#else + uint8_t *dspiData = new (nothrow) uint8_t[header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN]; + if (dspiData != NULL) + { + dspiData[0] = ERPC_BOARD_SPI_SLAVE_READY_MARKER1; + dspiData[1] = ERPC_BOARD_SPI_SLAVE_READY_MARKER2; + (void)memcpy(&dspiData[ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN], data, header_size); + + slaveXfer.txData = dspiData; + slaveXfer.rxData = NULL; + slaveXfer.dataSize = header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN; + slaveXfer.configFlags = (uint32_t)kDSPI_SlaveCtar0; +#endif + + status = DSPI_SlaveTransferNonBlocking(m_spiBaseAddr, &s_handle, &slaveXfer); + + if (kStatus_Success == status) + { +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + DSpiSlaveTransport_NotifyTransferGpioReady(); +#endif + +/* wait until the sending is finished */ +#if ERPC_THREADS + m_txrxSemaphore.get(); +#else + while (!s_isTransferCompleted) + { + } +#endif + +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + DSpiSlaveTransport_NotifyTransferGpioCompleted(); +#endif + } +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + } +#else + delete[] dspiData; + } + else + { + status = kErpcStatus_SendFailed; + } +#endif + + /* send the payload now */ + s_isTransferCompleted = false; + +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + slaveXfer.txData = (uint8_t *)data + header_size; + slaveXfer.rxData = NULL; + slaveXfer.dataSize = size - header_size; slaveXfer.configFlags = (uint32_t)kDSPI_SlaveCtar0; { #else - uint8_t *dspiData = new (nothrow) uint8_t[size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN]; + uint8_t *dspiData = new (nothrow) uint8_t[size - header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN]; if (dspiData != NULL) { dspiData[0] = ERPC_BOARD_SPI_SLAVE_READY_MARKER1; dspiData[1] = ERPC_BOARD_SPI_SLAVE_READY_MARKER2; - (void)memcpy(&dspiData[ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN], data, size); + (void)memcpy(&dspiData[ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN], data + header_size, size - header_size); slaveXfer.txData = dspiData; slaveXfer.rxData = NULL; - slaveXfer.dataSize = size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN; + slaveXfer.dataSize = size - header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN; slaveXfer.configFlags = (uint32_t)kDSPI_SlaveCtar0; #endif diff --git a/erpc_c/transports/erpc_dspi_slave_transport.hpp b/erpc_c/transports/erpc_dspi_slave_transport.hpp index f9d8039a..e2cf0604 100644 --- a/erpc_c/transports/erpc_dspi_slave_transport.hpp +++ b/erpc_c/transports/erpc_dspi_slave_transport.hpp @@ -15,6 +15,7 @@ #include "erpc_threading.h" #endif #include "erpc_framed_transport.hpp" + #include extern "C" { @@ -78,6 +79,9 @@ class DspiSlaveTransport : public FramedTransport #endif private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from DSPI peripheral. * @@ -87,7 +91,7 @@ class DspiSlaveTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed DSPI failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to DSPI peripheral. @@ -98,7 +102,7 @@ class DspiSlaveTransport : public FramedTransport * @retval kErpcStatus_SendFailed DSPI failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_i2c_slave_transport.cpp b/erpc_c/transports/erpc_i2c_slave_transport.cpp index 991f864f..b96224f8 100644 --- a/erpc_c/transports/erpc_i2c_slave_transport.cpp +++ b/erpc_c/transports/erpc_i2c_slave_transport.cpp @@ -1,14 +1,15 @@ /* - * Copyright 2021 NXP + * Copyright 2021-2023 NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause */ +#include "erpc_i2c_slave_transport.hpp" + #include #include -#include "erpc_i2c_slave_transport.hpp" extern "C" { #include "board.h" @@ -143,13 +144,11 @@ static void I2C_SlaveUserCallback(I2C_Type *base, volatile i2c_slave_transfer_t } } -I2cSlaveTransport::I2cSlaveTransport(I2C_Type *i2cBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) -: m_i2cBaseAddr(i2cBaseAddr) -, m_baudRate(baudRate) -, m_srcClock_Hz(srcClock_Hz) -, m_isInited(false) +I2cSlaveTransport::I2cSlaveTransport(I2C_Type *i2cBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) : +m_i2cBaseAddr(i2cBaseAddr), m_baudRate(baudRate), m_srcClock_Hz(srcClock_Hz), m_isInited(false) #if ERPC_THREADS -, m_txrxSemaphore() +, +m_txrxSemaphore() #endif { s_i2c_slave_instance = this; @@ -217,31 +216,51 @@ erpc_status_t I2cSlaveTransport::underlyingSend(const uint8_t *data, uint32_t si { status_t status; s_isTransferCompleted = false; + uint32_t header_size = reserveHeaderSize(); + /* send the header first */ s_callback_user_data.rx_buffer = NULL; s_callback_user_data.rx_size = 0; s_callback_user_data.tx_buffer = (uint8_t *)data; - s_callback_user_data.tx_size = size; + s_callback_user_data.tx_size = header_size; + status = + I2C_SlaveTransferNonBlocking(m_i2cBaseAddr, &s_handle, kI2C_SlaveAddressMatchEvent | kI2C_SlaveCompletionEvent); + if (kStatus_Success == status) { - status = I2C_SlaveTransferNonBlocking(m_i2cBaseAddr, &s_handle, - kI2C_SlaveAddressMatchEvent | kI2C_SlaveCompletionEvent); + I2cSlaveTransport_NotifyTransferGpioReady(); - if (kStatus_Success == status) +/* wait until the sending is finished */ +#if ERPC_THREADS + m_txrxSemaphore.get(); +#else + while (!s_isTransferCompleted) { - I2cSlaveTransport_NotifyTransferGpioReady(); + } +#endif + I2cSlaveTransport_NotifyTransferGpioCompleted(); + } + + /* send the payload now */ + s_callback_user_data.tx_buffer = (uint8_t *)data + header_size; + s_callback_user_data.tx_size = size - header_size; + s_isTransferCompleted = false; + status = + I2C_SlaveTransferNonBlocking(m_i2cBaseAddr, &s_handle, kI2C_SlaveAddressMatchEvent | kI2C_SlaveCompletionEvent); + if (kStatus_Success == status) + { + I2cSlaveTransport_NotifyTransferGpioReady(); /* wait until the sending is finished */ #if ERPC_THREADS - m_txrxSemaphore.get(); + m_txrxSemaphore.get(); #else - while (!s_isTransferCompleted) - { - } + while (!s_isTransferCompleted) + { + } #endif - I2cSlaveTransport_NotifyTransferGpioCompleted(); - } + I2cSlaveTransport_NotifyTransferGpioCompleted(); } return (status != kStatus_Success) ? kErpcStatus_SendFailed : kErpcStatus_Success; diff --git a/erpc_c/transports/erpc_i2c_slave_transport.hpp b/erpc_c/transports/erpc_i2c_slave_transport.hpp index bd10280a..6cd23287 100644 --- a/erpc_c/transports/erpc_i2c_slave_transport.hpp +++ b/erpc_c/transports/erpc_i2c_slave_transport.hpp @@ -9,8 +9,8 @@ #ifndef _EMBEDDED_RPC__I2C_SLAVE_TRANSPORT_H_ #define _EMBEDDED_RPC__I2C_SLAVE_TRANSPORT_H_ -#include #include "erpc_config_internal.h" +#include #if ERPC_THREADS #include "erpc_threading.h" #endif @@ -78,6 +78,9 @@ class I2cSlaveTransport : public FramedTransport #endif private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from I2C peripheral. * @@ -87,7 +90,7 @@ class I2cSlaveTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed I2C failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to I2C peripheral. @@ -98,7 +101,7 @@ class I2cSlaveTransport : public FramedTransport * @retval kErpcStatus_SendFailed I2C failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_inter_thread_buffer_transport.hpp b/erpc_c/transports/erpc_inter_thread_buffer_transport.hpp index 907a92f0..dabba2bb 100644 --- a/erpc_c/transports/erpc_inter_thread_buffer_transport.hpp +++ b/erpc_c/transports/erpc_inter_thread_buffer_transport.hpp @@ -44,21 +44,16 @@ namespace erpc { class InterThreadBufferTransport : public Transport { public: - InterThreadBufferTransport(void) - : Transport() - , m_state(NULL) - , m_peer(NULL) - , m_inSem() - , m_outSem(1) - , m_inBuffer(NULL) + InterThreadBufferTransport(void) : + Transport(), m_state(NULL), m_peer(NULL), m_inSem(), m_outSem(1), m_inBuffer(NULL) { } virtual ~InterThreadBufferTransport(void); void linkWithPeer(InterThreadBufferTransport *peer); - virtual erpc_status_t receive(MessageBuffer *message); - virtual erpc_status_t send(MessageBuffer *message); + virtual erpc_status_t receive(MessageBuffer *message) override; + virtual erpc_status_t send(MessageBuffer *message) override; virtual int32_t getAvailable(void) const { return 0; } diff --git a/erpc_c/transports/erpc_lpi2c_slave_transport.cpp b/erpc_c/transports/erpc_lpi2c_slave_transport.cpp index 96e3e7dc..6a2a6769 100644 --- a/erpc_c/transports/erpc_lpi2c_slave_transport.cpp +++ b/erpc_c/transports/erpc_lpi2c_slave_transport.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * All rights reserved. * * @@ -106,7 +106,6 @@ static void LPI2C_SlaveUserCallback(LPI2C_Type *base, lpi2c_slave_transfer_t *tr LPI2cSlaveTransport *transport = s_lpi2c_slave_instance; switch (transfer->event) { - break; /* Transmit request */ case kLPI2C_SlaveTransmitEvent: /* Update information for transmit process */ @@ -138,13 +137,11 @@ static void LPI2C_SlaveUserCallback(LPI2C_Type *base, lpi2c_slave_transfer_t *tr } } -LPI2cSlaveTransport::LPI2cSlaveTransport(LPI2C_Type *lpi2cBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) -: m_lpi2cBaseAddr(lpi2cBaseAddr) -, m_baudRate(baudRate) -, m_srcClock_Hz(srcClock_Hz) -, m_isInited(false) +LPI2cSlaveTransport::LPI2cSlaveTransport(LPI2C_Type *lpi2cBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) : +m_lpi2cBaseAddr(lpi2cBaseAddr), m_baudRate(baudRate), m_srcClock_Hz(srcClock_Hz), m_isInited(false) #if ERPC_THREADS -, m_txrxSemaphore() +, +m_txrxSemaphore() #endif { s_lpi2c_slave_instance = this; @@ -212,30 +209,49 @@ erpc_status_t LPI2cSlaveTransport::underlyingSend(const uint8_t *data, uint32_t { status_t status; s_isTransferCompleted = false; + uint32_t header_size = reserveHeaderSize(); + /* send the header first */ s_callback_user_data.rx_buffer = NULL; s_callback_user_data.rx_size = 0; s_callback_user_data.tx_buffer = (uint8_t *)data; - s_callback_user_data.tx_size = size; + s_callback_user_data.tx_size = header_size; + status = LPI2C_SlaveTransferNonBlocking(m_lpi2cBaseAddr, &s_handle, kLPI2C_SlaveCompletionEvent); + if (kStatus_Success == status) { - status = LPI2C_SlaveTransferNonBlocking(m_lpi2cBaseAddr, &s_handle, kLPI2C_SlaveCompletionEvent); + LPI2cSlaveTransport_NotifyTransferGpioReady(); - if (kStatus_Success == status) +/* wait until the sending is finished */ +#if ERPC_THREADS + m_txrxSemaphore.get(); +#else + while (!s_isTransferCompleted) { - LPI2cSlaveTransport_NotifyTransferGpioReady(); + } +#endif + LPI2cSlaveTransport_NotifyTransferGpioCompleted(); + } + + /* send the payload now */ + s_callback_user_data.tx_buffer = (uint8_t *)data + header_size; + s_callback_user_data.tx_size = size - header_size; + s_isTransferCompleted = false; + status = LPI2C_SlaveTransferNonBlocking(m_lpi2cBaseAddr, &s_handle, kLPI2C_SlaveCompletionEvent); + if (kStatus_Success == status) + { + LPI2cSlaveTransport_NotifyTransferGpioReady(); /* wait until the sending is finished */ #if ERPC_THREADS - m_txrxSemaphore.get(); + m_txrxSemaphore.get(); #else - while (!s_isTransferCompleted) - { - } + while (!s_isTransferCompleted) + { + } #endif - LPI2cSlaveTransport_NotifyTransferGpioCompleted(); - } + LPI2cSlaveTransport_NotifyTransferGpioCompleted(); } return (status != kStatus_Success) ? kErpcStatus_SendFailed : kErpcStatus_Success; diff --git a/erpc_c/transports/erpc_lpi2c_slave_transport.hpp b/erpc_c/transports/erpc_lpi2c_slave_transport.hpp index 407ed7ac..53ab6c9a 100644 --- a/erpc_c/transports/erpc_lpi2c_slave_transport.hpp +++ b/erpc_c/transports/erpc_lpi2c_slave_transport.hpp @@ -77,6 +77,9 @@ class LPI2cSlaveTransport : public FramedTransport #endif private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from LPI2C peripheral. * @@ -86,7 +89,7 @@ class LPI2cSlaveTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed LPI2C failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to LPI2C peripheral. @@ -97,7 +100,7 @@ class LPI2cSlaveTransport : public FramedTransport * @retval kErpcStatus_SendFailed LPI2C failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_lpspi_slave_transport.cpp b/erpc_c/transports/erpc_lpspi_slave_transport.cpp index 94f3ecc2..7d8ee191 100644 --- a/erpc_c/transports/erpc_lpspi_slave_transport.cpp +++ b/erpc_c/transports/erpc_lpspi_slave_transport.cpp @@ -108,13 +108,11 @@ static void LPSPI_SlaveUserCallback(LPSPI_Type *base, lpspi_slave_handle_t *hand transport->transfer_cb(); } -LPSpiSlaveTransport::LPSpiSlaveTransport(LPSPI_Type *lpspiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) -: m_lpspiBaseAddr(lpspiBaseAddr) -, m_baudRate(baudRate) -, m_srcClock_Hz(srcClock_Hz) -, m_isInited(false) +LPSpiSlaveTransport::LPSpiSlaveTransport(LPSPI_Type *lpspiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) : +m_lpspiBaseAddr(lpspiBaseAddr), m_baudRate(baudRate), m_srcClock_Hz(srcClock_Hz), m_isInited(false) #if ERPC_THREADS -, m_txrxSemaphore() +, +m_txrxSemaphore() #endif { s_lpspi_slave_instance = this; diff --git a/erpc_c/transports/erpc_lpspi_slave_transport.hpp b/erpc_c/transports/erpc_lpspi_slave_transport.hpp index 7c5c726a..8e0bd40f 100644 --- a/erpc_c/transports/erpc_lpspi_slave_transport.hpp +++ b/erpc_c/transports/erpc_lpspi_slave_transport.hpp @@ -78,6 +78,9 @@ class LPSpiSlaveTransport : public FramedTransport #endif private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from LPSPI peripheral. * @@ -87,7 +90,7 @@ class LPSpiSlaveTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed LPSPI failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to LPSPI peripheral. @@ -98,7 +101,7 @@ class LPSpiSlaveTransport : public FramedTransport * @retval kErpcStatus_SendFailed LPSPI failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_mu_transport.cpp b/erpc_c/transports/erpc_mu_transport.cpp index 15de63f8..af7832b5 100644 --- a/erpc_c/transports/erpc_mu_transport.cpp +++ b/erpc_c/transports/erpc_mu_transport.cpp @@ -76,22 +76,15 @@ void MUTransport::mu_irq_callback(void) } #endif /* ERPC_TRANSPORT_MU_USE_MCMGR */ -MUTransport::MUTransport(void) -: Transport() -, m_newMessage(false) -, m_rxMsgSize(0) -, m_rxCntBytes(0) -, m_rxBuffer(NULL) -, m_txMsgSize(0) -, m_txCntBytes(0) -, m_txBuffer(NULL) +MUTransport::MUTransport(void) : +Transport(), m_newMessage(false), m_rxMsgSize(0), m_rxCntBytes(0), m_rxBuffer(NULL), m_txMsgSize(0), m_txCntBytes(0), +m_txBuffer(NULL) #if !ERPC_THREADS_IS(NONE) -, m_rxSemaphore() -, m_txSemaphore() -, m_sendLock() -, m_receiveLock() +, +m_rxSemaphore(), m_txSemaphore(), m_sendLock(), m_receiveLock() #endif -, m_muBase(NULL) +, +m_muBase(NULL) { s_mu_instance = this; } @@ -287,6 +280,11 @@ erpc_status_t MUTransport::send(MessageBuffer *message) return status; } +bool MUTransport::hasMessage(void) +{ + return m_newMessage; +} + extern "C" { #if ERPC_TRANSPORT_MU_USE_MCMGR diff --git a/erpc_c/transports/erpc_mu_transport.hpp b/erpc_c/transports/erpc_mu_transport.hpp index b2c38afe..2c3602ec 100644 --- a/erpc_c/transports/erpc_mu_transport.hpp +++ b/erpc_c/transports/erpc_mu_transport.hpp @@ -48,7 +48,8 @@ extern "C" { #define MU_REG_COUNT (MU_RR_COUNT) /*!< Count of MU tx/rx registers to be used by this transport layer */ #endif /* ERPC_TRANSPORT_MU_USE_MCMGR */ -#if (defined(MIMXRT1187_cm7_SERIES) || defined(MIMXRT1187_cm33_SERIES) || defined(MIMXRT1189_cm7_SERIES) || defined(MIMXRT1189_cm33_SERIES)) +#if (defined(MIMXRT1187_cm7_SERIES) || defined(MIMXRT1187_cm33_SERIES) || defined(MIMXRT1189_cm7_SERIES) || \ + defined(MIMXRT1189_cm33_SERIES)) #define MU_TX_SHIFT (1UL << (MU_REG_COUNT - 1U)) #define MU_RX_SHIFT (1UL << (MU_REG_COUNT - 1U)) #define MU_RX_INTR_MASK (MU_RX_INTR(MU_RX_SHIFT)) @@ -126,7 +127,7 @@ class MUTransport : public Transport * * @return kErpcStatus_Success */ - virtual erpc_status_t receive(MessageBuffer *message); + virtual erpc_status_t receive(MessageBuffer *message) override; /*! * @brief Function to send prepared message. @@ -136,7 +137,7 @@ class MUTransport : public Transport * @retval kErpcStatus_SendFailed Failed to send message buffer. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t send(MessageBuffer *message); + virtual erpc_status_t send(MessageBuffer *message) override; /*! * @brief Function to check if is new message to receive. @@ -145,7 +146,7 @@ class MUTransport : public Transport * * @return True if exist new message, else false. */ - virtual bool hasMessage(void) { return m_newMessage; } + virtual bool hasMessage(void) override; #if ERPC_TRANSPORT_MU_USE_MCMGR /*! diff --git a/erpc_c/transports/erpc_rpmsg_linux_transport.cpp b/erpc_c/transports/erpc_rpmsg_linux_transport.cpp index 2b229429..17a756bb 100644 --- a/erpc_c/transports/erpc_rpmsg_linux_transport.cpp +++ b/erpc_c/transports/erpc_rpmsg_linux_transport.cpp @@ -17,10 +17,8 @@ using namespace erpc; // Code //////////////////////////////////////////////////////////////////////////////// -RPMsgLinuxTransport::RPMsgLinuxTransport(RPMsgEndpoint *endPoint, int16_t remote) -: Transport() -, m_endPoint(endPoint) -, m_remote(remote) +RPMsgLinuxTransport::RPMsgLinuxTransport(RPMsgEndpoint *endPoint, int16_t remote) : +Transport(), m_endPoint(endPoint), m_remote(remote) { } diff --git a/erpc_c/transports/erpc_rpmsg_linux_transport.hpp b/erpc_c/transports/erpc_rpmsg_linux_transport.hpp index 968780d7..b66dc8ab 100644 --- a/erpc_c/transports/erpc_rpmsg_linux_transport.hpp +++ b/erpc_c/transports/erpc_rpmsg_linux_transport.hpp @@ -33,6 +33,13 @@ class RPMsgLinuxTransport : public Transport virtual ~RPMsgLinuxTransport(void); + /*! + * @brief This function returns rpmsg endpoint object. + * + * @return RPMsgEndpoint * Rpmsg endpoint. + */ + RPMsgEndpoint *getRpmsgEndpoint(void) { return m_endPoint; } + /*! * @brief This function initializes Linux environment for sending and receiving messages. * @@ -49,7 +56,7 @@ class RPMsgLinuxTransport : public Transport * @retval kErpcStatus_Success When message was received successfully. * @retval kErpcStatus_Fail When message wasn't received successfully. */ - virtual erpc_status_t receive(MessageBuffer *message); + virtual erpc_status_t receive(MessageBuffer *message) override; /*! * @brief This function sends the eRPC messages. @@ -59,7 +66,7 @@ class RPMsgLinuxTransport : public Transport * @retval kErpcStatus_Success When message was sent successfully. * @retval kErpcStatus_Fail When message wasn't sent successfully. */ - virtual erpc_status_t send(MessageBuffer *message); + virtual erpc_status_t send(MessageBuffer *message) override; private: RPMsgEndpoint *m_endPoint; /*!< Object operating with endpoints. */ diff --git a/erpc_c/transports/erpc_rpmsg_lite_base_transport.hpp b/erpc_c/transports/erpc_rpmsg_lite_base.hpp old mode 100755 new mode 100644 similarity index 87% rename from erpc_c/transports/erpc_rpmsg_lite_base_transport.hpp rename to erpc_c/transports/erpc_rpmsg_lite_base.hpp index 32433d52..bc30c4dc --- a/erpc_c/transports/erpc_rpmsg_lite_base_transport.hpp +++ b/erpc_c/transports/erpc_rpmsg_lite_base.hpp @@ -8,15 +8,14 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef _EMBEDDED_RPC__RPMSG_LITE_BASE_TRANSPORT_H_ -#define _EMBEDDED_RPC__RPMSG_LITE_BASE_TRANSPORT_H_ +#ifndef _EMBEDDED_RPC__RPMSG_LITE_BASE_H_ +#define _EMBEDDED_RPC__RPMSG_LITE_BASE_H_ #include "erpc_config_internal.h" -#include "erpc_transport.hpp" extern "C" { -#include "rpmsg_lite.h" #include "rpmsg_env_specific.h" +#include "rpmsg_lite.h" } #if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC @@ -47,13 +46,12 @@ namespace erpc { * @ingroup rpmsg_lite_transport * @ingroup rpmsg_lite_rtos_transport */ -class RPMsgBaseTransport : public Transport +class RPMsgBase { public: - RPMsgBaseTransport(void) - : Transport(){}; + RPMsgBase(void){}; - virtual ~RPMsgBaseTransport(void) {} + virtual ~RPMsgBase(void) {} /*! * @brief This function returns pointer to instance of RPMSG lite @@ -82,4 +80,4 @@ class RPMsgBaseTransport : public Transport /*! @} */ -#endif // _EMBEDDED_RPC__RPMSG_LITE_BASE_TRANSPORT_H_ +#endif // _EMBEDDED_RPC__RPMSG_LITE_BASE_H_ diff --git a/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp b/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp index 76858d91..a1b05b80 100644 --- a/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp +++ b/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2022 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -9,6 +9,7 @@ */ #include "erpc_rpmsg_lite_rtos_transport.hpp" + #include "erpc_config_internal.h" extern "C" { @@ -20,21 +21,16 @@ using namespace erpc; //////////////////////////////////////////////////////////////////////////////// // Variables //////////////////////////////////////////////////////////////////////////////// -uint8_t RPMsgBaseTransport::s_initialized = 0U; -struct rpmsg_lite_instance *RPMsgBaseTransport::s_rpmsg; +uint8_t RPMsgBase::s_initialized = 0U; +struct rpmsg_lite_instance *RPMsgBase::s_rpmsg; //////////////////////////////////////////////////////////////////////////////// // Code //////////////////////////////////////////////////////////////////////////////// -RPMsgRTOSTransport::RPMsgRTOSTransport(void) -: RPMsgBaseTransport() -, m_rdev(NULL) -, m_app_rp_chnl(NULL) -, m_dst_addr(0) -, m_rpmsg_queue(NULL) -, m_rpmsg_ept(NULL) -, m_crcImpl(NULL) +RPMsgRTOSTransport::RPMsgRTOSTransport(void) : +Transport(), RPMsgBase(), m_rdev(NULL), m_app_rp_chnl(NULL), m_dst_addr(0), m_rpmsg_queue(NULL), m_rpmsg_ept(NULL), +m_crcImpl(NULL) { } @@ -71,17 +67,6 @@ RPMsgRTOSTransport::~RPMsgRTOSTransport(void) } } -void RPMsgRTOSTransport::setCrc16(Crc16 *crcImpl) -{ - erpc_assert(crcImpl != NULL); - m_crcImpl = crcImpl; -} - -Crc16 *RPMsgRTOSTransport::getCrc16(void) -{ - return m_crcImpl; -} - erpc_status_t RPMsgRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, void *base_address, uint32_t length, uint32_t rpmsg_link_id) { @@ -288,3 +273,19 @@ erpc_status_t RPMsgRTOSTransport::send(MessageBuffer *message) return status; } + +bool RPMsgRTOSTransport::hasMessage(void) +{ + return ((rpmsg_queue_get_current_size(m_rpmsg_queue) > 0) ? true : false); +} + +void RPMsgRTOSTransport::setCrc16(Crc16 *crcImpl) +{ + erpc_assert(crcImpl != NULL); + m_crcImpl = crcImpl; +} + +Crc16 *RPMsgRTOSTransport::getCrc16(void) +{ + return m_crcImpl; +} diff --git a/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.hpp b/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.hpp index f237d0b0..8bbd6547 100644 --- a/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.hpp +++ b/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.hpp @@ -12,7 +12,8 @@ #include "erpc_crc16.hpp" #include "erpc_message_buffer.hpp" -#include "erpc_rpmsg_lite_base_transport.hpp" +#include "erpc_rpmsg_lite_base.hpp" +#include "erpc_transport.hpp" extern "C" { #include "rpmsg_lite.h" @@ -39,7 +40,7 @@ namespace erpc { * * @ingroup rpmsg_lite_rtos_transport */ -class RPMsgRTOSTransport : public RPMsgBaseTransport +class RPMsgRTOSTransport : public Transport, public RPMsgBase { public: /*! @@ -96,7 +97,7 @@ class RPMsgRTOSTransport : public RPMsgBaseTransport * @retval kErpcStatus_ReceiveFailed Failed to receive message buffer. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t receive(MessageBuffer *message); + virtual erpc_status_t receive(MessageBuffer *message) override; /*! * @brief Function to send prepared message. @@ -106,29 +107,30 @@ class RPMsgRTOSTransport : public RPMsgBaseTransport * @retval kErpcStatus_SendFailed Failed to send message buffer. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t send(MessageBuffer *message); + virtual erpc_status_t send(MessageBuffer *message) override; + + /*! + * @brief Function to check if is message in receive queue and wait for processing. + * + * This function should be called before function receive() to avoid waiting for new message. + * + * @return True if exist received message, else false. + */ + virtual bool hasMessage(void) override; /*! * @brief This functions sets the CRC-16 implementation. * * @param[in] crcImpl Object containing crc-16 compute function. */ - virtual void setCrc16(Crc16 *crcImpl); + virtual void setCrc16(Crc16 *crcImpl) override; /*! * @brief This functions gets the CRC-16 object. * * @return Crc16* Pointer to CRC-16 object containing crc-16 compute function. */ - virtual Crc16 *getCrc16(void); - /*! - * @brief Function to check if is message in receive queue and wait for processing. - * - * This function should be called before function receive() to avoid waiting for new message. - * - * @return True if exist received message, else false. - */ - virtual bool hasMessage(void) { return ((rpmsg_queue_get_current_size(m_rpmsg_queue) > 0) ? true : false); } + virtual Crc16 *getCrc16(void) override; protected: /* Remote device */ diff --git a/erpc_c/transports/erpc_rpmsg_lite_transport.cpp b/erpc_c/transports/erpc_rpmsg_lite_transport.cpp index 3211bc75..3f5f1c4a 100644 --- a/erpc_c/transports/erpc_rpmsg_lite_transport.cpp +++ b/erpc_c/transports/erpc_rpmsg_lite_transport.cpp @@ -20,8 +20,8 @@ using namespace erpc; //////////////////////////////////////////////////////////////////////////////// // Variables //////////////////////////////////////////////////////////////////////////////// -uint8_t RPMsgBaseTransport::s_initialized = 0U; -struct rpmsg_lite_instance *RPMsgBaseTransport::s_rpmsg = NULL; +uint8_t RPMsgBase::s_initialized = 0U; +struct rpmsg_lite_instance *RPMsgBase::s_rpmsg = NULL; //////////////////////////////////////////////////////////////////////////////// // Code @@ -39,13 +39,7 @@ int32_t RPMsgTransport::rpmsg_read_cb(void *payload, uint32_t payload_len, uint3 return RL_HOLD; } -RPMsgTransport::RPMsgTransport(void) -: RPMsgBaseTransport() -, m_dst_addr(0) -, m_rpmsg_ept(NULL) -, m_crcImpl(NULL) -{ -} +RPMsgTransport::RPMsgTransport(void) : Transport(), RPMsgBase(), m_dst_addr(0), m_rpmsg_ept(NULL), m_crcImpl(NULL) {} RPMsgTransport::~RPMsgTransport(void) { @@ -72,17 +66,6 @@ RPMsgTransport::~RPMsgTransport(void) } } -void RPMsgTransport::setCrc16(Crc16 *crcImpl) -{ - erpc_assert(crcImpl != NULL); - m_crcImpl = crcImpl; -} - -Crc16 *RPMsgTransport::getCrc16(void) -{ - return m_crcImpl; -} - erpc_status_t RPMsgTransport::init(uint32_t src_addr, uint32_t dst_addr, void *base_address, uint32_t length, uint32_t rpmsg_link_id) { @@ -227,3 +210,19 @@ erpc_status_t RPMsgTransport::send(MessageBuffer *message) return (ret_val != RL_SUCCESS) ? kErpcStatus_SendFailed : kErpcStatus_Success; } + +bool RPMsgTransport::hasMessage(void) +{ + return ((0UL < m_messageQueue.size()) ? true : false); +} + +void RPMsgTransport::setCrc16(Crc16 *crcImpl) +{ + erpc_assert(crcImpl != NULL); + m_crcImpl = crcImpl; +} + +Crc16 *RPMsgTransport::getCrc16(void) +{ + return m_crcImpl; +} diff --git a/erpc_c/transports/erpc_rpmsg_lite_transport.hpp b/erpc_c/transports/erpc_rpmsg_lite_transport.hpp index 8ac958ff..78738a8f 100644 --- a/erpc_c/transports/erpc_rpmsg_lite_transport.hpp +++ b/erpc_c/transports/erpc_rpmsg_lite_transport.hpp @@ -10,11 +10,12 @@ #ifndef _EMBEDDED_RPC__RPMSG_LITE_TRANSPORT_H_ #define _EMBEDDED_RPC__RPMSG_LITE_TRANSPORT_H_ -#include "erpc_crc16.hpp" #include "erpc_config_internal.h" +#include "erpc_crc16.hpp" #include "erpc_message_buffer.hpp" -#include "erpc_rpmsg_lite_base_transport.hpp" +#include "erpc_rpmsg_lite_base.hpp" #include "erpc_static_queue.hpp" +#include "erpc_transport.hpp" extern "C" { #include "rpmsg_lite.h" @@ -40,7 +41,7 @@ namespace erpc { * * @ingroup rpmsg_lite_transport */ -class RPMsgTransport : public RPMsgBaseTransport +class RPMsgTransport : public Transport, public RPMsgBase { public: /*! @@ -100,7 +101,7 @@ class RPMsgTransport : public RPMsgBaseTransport * * @return kErpcStatus_Success */ - virtual erpc_status_t receive(MessageBuffer *message); + virtual erpc_status_t receive(MessageBuffer *message) override; /*! * @brief Function to send prepared message. @@ -110,29 +111,30 @@ class RPMsgTransport : public RPMsgBaseTransport * @retval kErpcStatus_SendFailed Failed to send message buffer. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t send(MessageBuffer *message); + virtual erpc_status_t send(MessageBuffer *message) override; + + /*! + * @brief Function to check if is message in receive queue and wait for processing. + * + * This function should be called before function receive() to avoid waiting for new message. + * + * @return True if exist received message, else false. + */ + virtual bool hasMessage(void) override; /*! * @brief This functions sets the CRC-16 implementation. * * @param[in] crcImpl Object containing crc-16 compute function. */ - virtual void setCrc16(Crc16 *crcImpl); + virtual void setCrc16(Crc16 *crcImpl) override; /*! * @brief This functions gets the CRC-16 object. * * @return Crc16* Pointer to CRC-16 object containing crc-16 compute function. */ - virtual Crc16 *getCrc16(void); - /*! - * @brief Function to check if is message in receive queue and wait for processing. - * - * This function should be called before function receive() to avoid waiting for new message. - * - * @return True if exist received message, else false. - */ - virtual bool hasMessage(void) { return ((0UL < m_messageQueue.size()) ? true: false); } + virtual Crc16 *getCrc16(void) override; protected: /*! diff --git a/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp b/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp index 62272787..b3da88b0 100644 --- a/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp +++ b/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp @@ -11,7 +11,6 @@ #include "erpc_rpmsg_tty_rtos_transport.hpp" #include "erpc_config_internal.h" -#include "erpc_framed_transport.hpp" extern "C" { #include "rpmsg_ns.h" @@ -23,19 +22,15 @@ using namespace std; //////////////////////////////////////////////////////////////////////////////// // Variables //////////////////////////////////////////////////////////////////////////////// -uint8_t RPMsgBaseTransport::s_initialized = 0U; -struct rpmsg_lite_instance *RPMsgBaseTransport::s_rpmsg; +uint8_t RPMsgBase::s_initialized = 0U; +struct rpmsg_lite_instance *RPMsgBase::s_rpmsg; //////////////////////////////////////////////////////////////////////////////// // Code //////////////////////////////////////////////////////////////////////////////// -RPMsgTTYRTOSTransport::RPMsgTTYRTOSTransport(void) -: RPMsgBaseTransport() -, m_dst_addr(0) -, m_rpmsg_queue(NULL) -, m_rpmsg_ept(NULL) -, m_crcImpl(NULL) +RPMsgTTYRTOSTransport::RPMsgTTYRTOSTransport(void) : +FramedTransport(), RPMsgBase(), m_dst_addr(0), m_rpmsg_queue(NULL), m_rpmsg_ept(NULL) { } @@ -72,17 +67,6 @@ RPMsgTTYRTOSTransport::~RPMsgTTYRTOSTransport(void) } } -void RPMsgTTYRTOSTransport::setCrc16(Crc16 *crcImpl) -{ - erpc_assert(crcImpl != NULL); - m_crcImpl = crcImpl; -} - -Crc16 *RPMsgTTYRTOSTransport::getCrc16(void) -{ - return m_crcImpl; -} - erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, void *base_address, uint32_t length, uint32_t rpmsg_link_id) { @@ -179,7 +163,7 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, ready_cb(); } - (void)rpmsg_lite_wait_for_link_up(s_rpmsg, RL_BLOCK); + static_cast(rpmsg_lite_wait_for_link_up(s_rpmsg, RL_BLOCK)); #if RL_USE_STATIC_API m_rpmsg_queue = rpmsg_queue_create(s_rpmsg, m_queue_stack, &m_queue_context); @@ -252,70 +236,65 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, return status; } -erpc_status_t RPMsgTTYRTOSTransport::receive(MessageBuffer *message) +erpc_status_t RPMsgTTYRTOSTransport::underlyingSend(MessageBuffer *message, uint32_t size, uint32_t offset) { - erpc_status_t status = kErpcStatus_Success; - FramedTransport::Header h; - char *buf = NULL; - uint32_t length = 0; - int32_t ret_val = rpmsg_queue_recv_nocopy(s_rpmsg, m_rpmsg_queue, &m_dst_addr, &buf, &length, RL_BLOCK); - uint16_t computedCrc; - - erpc_assert((m_crcImpl != NULL) && ("Uninitialized Crc16 object." != NULL)); - erpc_assert(buf != NULL); + erpc_status_t status; + int32_t ret_val; + ret_val = rpmsg_lite_send_nocopy(s_rpmsg, m_rpmsg_ept, m_dst_addr, &message->get()[offset], size); if (ret_val == RL_SUCCESS) { - (void)memcpy(reinterpret_cast(&h), buf, sizeof(h)); - message->set(&(reinterpret_cast(buf))[sizeof(h)], length - sizeof(h)); - /* Verify CRC. */ - computedCrc = m_crcImpl->computeCRC16(&(reinterpret_cast(buf))[sizeof(h)], h.m_messageSize); - if (computedCrc != h.m_crc) - { - status = kErpcStatus_CrcCheckFailed; - } - else - { - message->setUsed(h.m_messageSize); - } + message->set(NULL, 0); + status = kErpcStatus_Success; } else { - status = kErpcStatus_ReceiveFailed; + status = kErpcStatus_SendFailed; } return status; } -erpc_status_t RPMsgTTYRTOSTransport::send(MessageBuffer *message) +erpc_status_t RPMsgTTYRTOSTransport::underlyingReceive(MessageBuffer *message, uint32_t size, uint32_t offset) { - erpc_status_t status = kErpcStatus_Success; - FramedTransport::Header h; - uint8_t *buf = message->get(); - uint32_t length = message->getLength(); - uint32_t used = message->getUsed(); - int32_t ret_val; - - erpc_assert((m_crcImpl != NULL) && ("Uninitialized Crc16 object." != NULL)); - message->set(NULL, 0); - - h.m_crc = m_crcImpl->computeCRC16(buf, used); - h.m_messageSize = used; - - (void)memcpy(&buf[-sizeof(h)], (uint8_t *)&h, sizeof(h)); - - ret_val = rpmsg_lite_send_nocopy(s_rpmsg, m_rpmsg_ept, m_dst_addr, &buf[-sizeof(h)], used + sizeof(h)); + char *buf = NULL; + uint32_t length = 0; + int32_t ret_val = rpmsg_queue_recv_nocopy(s_rpmsg, m_rpmsg_queue, &m_dst_addr, &buf, &length, RL_BLOCK); + erpc_status_t status; if (ret_val == RL_SUCCESS) { + if (offset == 0) + { + message->set(reinterpret_cast(buf), length); + message->setUsed(length); + } + else + { + erpc_assert(buf != NULL); + erpc_assert((length + offset) <= ERPC_DEFAULT_BUFFER_SIZE); + static_cast(memcpy(&message->get()[offset], buf, length)); + message->setUsed(length + offset); + static_cast(rpmsg_lite_release_rx_buffer(s_rpmsg, buf)); + } status = kErpcStatus_Success; } else { - message->set(buf, length); - message->setUsed(used); - status = kErpcStatus_SendFailed; + status = kErpcStatus_ReceiveFailed; } return status; } + +erpc_status_t RPMsgTTYRTOSTransport::underlyingReceive(uint8_t *data, uint32_t size) +{ + // unused as underlyingReceive(MessageBuffer *message, uint32_t size, uint32_t offset) + return kErpcStatus_ReceiveFailed; +} + +erpc_status_t RPMsgTTYRTOSTransport::underlyingSend(const uint8_t *data, uint32_t size) +{ + // unused as underlyingReceive(MessageBuffer *message, uint32_t size, uint32_t offset) + return kErpcStatus_SendFailed; +} diff --git a/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.hpp b/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.hpp index a1baf11b..5d97ae49 100644 --- a/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.hpp +++ b/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.hpp @@ -11,8 +11,9 @@ #define _EMBEDDED_RPC__RPMSG_LITE_TTY_RTOS_TRANSPORT_H_ #include "erpc_crc16.hpp" +#include "erpc_framed_transport.hpp" #include "erpc_message_buffer.hpp" -#include "erpc_rpmsg_lite_base_transport.hpp" +#include "erpc_rpmsg_lite_base.hpp" extern "C" { #include "rpmsg_lite.h" @@ -40,7 +41,7 @@ namespace erpc { * * @ingroup rpmsg_tty_rtos_transport */ -class RPMsgTTYRTOSTransport : public RPMsgBaseTransport +class RPMsgTTYRTOSTransport : public FramedTransport, public RPMsgBase { public: /*! @@ -94,48 +95,63 @@ class RPMsgTTYRTOSTransport : public RPMsgBaseTransport virtual erpc_status_t init(uint32_t src_addr, uint32_t dst_addr, void *base_address, uint32_t rpmsg_link_id, void (*ready_cb)(void), char *nameservice_name); +protected: + uint32_t m_dst_addr; /*!< Destination address used by rpmsg. */ + rpmsg_queue_handle m_rpmsg_queue; /*!< Handle of RPMsg queue. */ + struct rpmsg_lite_endpoint *m_rpmsg_ept; /*!< Pointer to RPMsg Lite Endpoint structure. */ + + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! - * @brief Store incoming message to message buffer. + * @brief Adds ability to framed transport to overwrite MessageBuffer when receiving data. * - * In loop while no message come. + * Usually we don't want to do that. * - * @param[in] message Message buffer, to which will be stored incoming - * message. + * @param message MessageBuffer to send. + * @param size size of message to send. + * @param offset data start address offset * - * @retval kErpcStatus_ReceiveFailed Failed to receive message buffer. - * @retval kErpcStatus_Success Successfully received all data. + * @return erpc_status_t kErpcStatus_Success when it finished successful otherwise error. */ - virtual erpc_status_t receive(MessageBuffer *message); + virtual erpc_status_t underlyingReceive(MessageBuffer *message, uint32_t size, uint32_t offset) override; /*! - * @brief Function to send prepared message. + * @brief Adds ability to framed transport to overwrite MessageBuffer when sending data. + * + * Usually we don't want to do that. * - * @param[in] message Pass message buffer to send. + * @param message MessageBuffer to send. + * @param size size of message to send. + * @param offset data start address offset * - * @retval kErpcStatus_SendFailed Failed to send message buffer. - * @retval kErpcStatus_Success Successfully sent all data. + * @return erpc_status_t kErpcStatus_Success when it finished successful otherwise error. */ - virtual erpc_status_t send(MessageBuffer *message); + virtual erpc_status_t underlyingSend(MessageBuffer *message, uint32_t size, uint32_t offset) override; /*! - * @brief This functions sets the CRC-16 implementation. + * @brief This function read data. * - * @param[in] crcImpl Object containing crc-16 compute function. + * @param[inout] data Preallocated buffer for receiving data. + * @param[in] size Size of data to read. + * + * @retval #kErpcStatus_Success When data was read successfully. + * @retval #kErpcStatus_ReceiveFailed When reading data ends with error. + * @retval #kErpcStatus_ConnectionClosed Peer closed the connection. */ - virtual void setCrc16(Crc16 *crcImpl); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! - * @brief This functions gets the CRC-16 object. + * @brief This function writes data. + * + * @param[in] data Buffer to send. + * @param[in] size Size of data to send. * - * @return Crc16* Pointer to CRC-16 object containing crc-16 compute function. + * @retval #kErpcStatus_Success When data was written successfully. + * @retval #kErpcStatus_SendFailed When writing data ends with error. + * @retval #kErpcStatus_ConnectionClosed Peer closed the connection. */ - virtual Crc16 *getCrc16(void); - -protected: - uint32_t m_dst_addr; /*!< Destination address used by rpmsg. */ - rpmsg_queue_handle m_rpmsg_queue; /*!< Handle of RPMsg queue. */ - struct rpmsg_lite_endpoint *m_rpmsg_ept; /*!< Pointer to RPMsg Lite Endpoint structure. */ - Crc16 *m_crcImpl; //!< CRC object. + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_serial_transport.cpp b/erpc_c/transports/erpc_serial_transport.cpp index 80d9b45c..ea882eb7 100644 --- a/erpc_c/transports/erpc_serial_transport.cpp +++ b/erpc_c/transports/erpc_serial_transport.cpp @@ -32,10 +32,8 @@ using namespace erpc; // Code //////////////////////////////////////////////////////////////////////////////// -SerialTransport::SerialTransport(const char *portName, speed_t baudRate) -: m_serialHandle(0) -, m_portName(portName) -, m_baudRate(baudRate) +SerialTransport::SerialTransport(const char *portName, speed_t baudRate) : +m_serialHandle(0), m_portName(portName), m_baudRate(baudRate) { } diff --git a/erpc_c/transports/erpc_serial_transport.hpp b/erpc_c/transports/erpc_serial_transport.hpp index ea0033bb..6b41ae11 100644 --- a/erpc_c/transports/erpc_serial_transport.hpp +++ b/erpc_c/transports/erpc_serial_transport.hpp @@ -65,27 +65,30 @@ class SerialTransport : public FramedTransport erpc_status_t init(uint8_t vtime, uint8_t vmin); private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! - * @brief Write data to Serial peripheral. + * @brief Receive data from Serial peripheral. * - * @param[in] data Buffer to send. - * @param[in] size Size of data to send. + * @param[inout] data Preallocated buffer for receiving data. + * @param[in] size Size of data to read. * * @retval kErpcStatus_ReceiveFailed Serial failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! - * @brief Receive data from Serial peripheral. + * @brief Write data to Serial peripheral. * - * @param[inout] data Preallocated buffer for receiving data. - * @param[in] size Size of data to read. + * @param[in] data Buffer to send. + * @param[in] size Size of data to send. * * @retval kErpcStatus_ReceiveFailed Serial failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; private: int m_serialHandle; /*!< Serial handle id. */ diff --git a/erpc_c/transports/erpc_spi_master_transport.cpp b/erpc_c/transports/erpc_spi_master_transport.cpp index da4f36ee..6c05c610 100644 --- a/erpc_c/transports/erpc_spi_master_transport.cpp +++ b/erpc_c/transports/erpc_spi_master_transport.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -8,9 +8,10 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include #include "erpc_spi_master_transport.hpp" +#include + extern "C" { #include "board.h" #include "fsl_gpio.h" @@ -100,10 +101,8 @@ static inline void SpidevMasterTransport_WaitForSlaveReadyMarker(SPI_Type *spiBa } #endif -SpiMasterTransport::SpiMasterTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) -: m_spiBaseAddr(spiBaseAddr) -, m_baudRate(baudRate) -, m_srcClock_Hz(srcClock_Hz) +SpiMasterTransport::SpiMasterTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) : +m_spiBaseAddr(spiBaseAddr), m_baudRate(baudRate), m_srcClock_Hz(srcClock_Hz) { } @@ -154,10 +153,26 @@ erpc_status_t SpiMasterTransport::underlyingSend(const uint8_t *data, uint32_t s { status_t status; spi_transfer_t masterXfer; + uint32_t header_size = reserveHeaderSize(); + /* send the header first */ masterXfer.txData = (uint8_t *)data; masterXfer.rxData = NULL; - masterXfer.dataSize = size; + masterXfer.dataSize = header_size; + + /* send the header first */ +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + SpidevMasterTransport_WaitForSlaveReadyGpio(); +#endif + + status = SPI_MasterTransferBlocking(m_spiBaseAddr, &masterXfer); +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + s_isSlaveReady = false; +#endif + + /* send the payload now */ + masterXfer.txData = (uint8_t *)data + header_size; + masterXfer.dataSize = size - header_size; #ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO SpidevMasterTransport_WaitForSlaveReadyGpio(); diff --git a/erpc_c/transports/erpc_spi_master_transport.hpp b/erpc_c/transports/erpc_spi_master_transport.hpp index 8614b623..e2de9bae 100644 --- a/erpc_c/transports/erpc_spi_master_transport.hpp +++ b/erpc_c/transports/erpc_spi_master_transport.hpp @@ -10,9 +10,10 @@ #ifndef _EMBEDDED_RPC__SPI_MASTER_TRANSPORT_H_ #define _EMBEDDED_RPC__SPI_MASTER_TRANSPORT_H_ +#include "erpc_framed_transport.hpp" + #include #include -#include "erpc_framed_transport.hpp" extern "C" { #include "fsl_spi.h" @@ -64,6 +65,9 @@ class SpiMasterTransport : public FramedTransport uint32_t m_srcClock_Hz; /*!< Source clock of SPI peripheral used in this transport layer */ private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from SPI peripheral. * @@ -73,7 +77,7 @@ class SpiMasterTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed SPI failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to SPI peripheral. @@ -84,7 +88,7 @@ class SpiMasterTransport : public FramedTransport * @retval kErpcStatus_SendFailed SPI failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_spi_slave_transport.cpp b/erpc_c/transports/erpc_spi_slave_transport.cpp index dadd77de..a87a0e26 100644 --- a/erpc_c/transports/erpc_spi_slave_transport.cpp +++ b/erpc_c/transports/erpc_spi_slave_transport.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2023 NXP * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * @@ -8,9 +8,10 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "erpc_spi_slave_transport.hpp" + #include #include -#include "erpc_spi_slave_transport.hpp" extern "C" { #include "board.h" @@ -111,13 +112,11 @@ static void SPI_SlaveUserCallback(SPI_Type *base, spi_slave_handle_t *handle, st transport->transfer_cb(); } -SpiSlaveTransport::SpiSlaveTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) -: m_spiBaseAddr(spiBaseAddr) -, m_baudRate(baudRate) -, m_srcClock_Hz(srcClock_Hz) -, m_isInited(false) +SpiSlaveTransport::SpiSlaveTransport(SPI_Type *spiBaseAddr, uint32_t baudRate, uint32_t srcClock_Hz) : +m_spiBaseAddr(spiBaseAddr), m_baudRate(baudRate), m_srcClock_Hz(srcClock_Hz), m_isInited(false) #if ERPC_THREADS -, m_txrxSemaphore() +, +m_txrxSemaphore() #endif { s_spi_slave_instance = this; @@ -192,22 +191,76 @@ erpc_status_t SpiSlaveTransport::underlyingSend(const uint8_t *data, uint32_t si status_t status; spi_transfer_t slaveXfer = { 0 }; s_isTransferCompleted = false; + uint32_t header_size = reserveHeaderSize(); + /* send the header first */ #ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO slaveXfer.txData = (uint8_t *)data; slaveXfer.rxData = NULL; - slaveXfer.dataSize = size; + slaveXfer.dataSize = header_size; + { +#else + uint8_t *spiData = new (nothrow) uint8_t[header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN]; + if (spiData != NULL) + { + spiData[0] = ERPC_BOARD_SPI_SLAVE_READY_MARKER1; + spiData[1] = ERPC_BOARD_SPI_SLAVE_READY_MARKER2; + (void)memcpy(&spiData[ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN], data, header_size); + slaveXfer.txData = spiData; + slaveXfer.rxData = NULL; + slaveXfer.dataSize = header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN; +#endif + + status = SPI_SlaveTransferNonBlocking(m_spiBaseAddr, &s_handle, &slaveXfer); + + if (kStatus_Success == status) + { +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + SpiSlaveTransport_NotifyTransferGpioReady(); +#endif + +/* wait until the sending is finished */ +#if ERPC_THREADS + m_txrxSemaphore.get(); +#else + while (!s_isTransferCompleted) + { + } +#endif + +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + SpiSlaveTransport_NotifyTransferGpioCompleted(); +#endif + } +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + } +#else + delete[] spiData; + } + else + { + status = kErpcStatus_SendFailed; + } +#endif + + /* send the payload now */ + s_isTransferCompleted = false; + +#ifdef ERPC_BOARD_SPI_SLAVE_READY_USE_GPIO + slaveXfer.txData = (uint8_t *)data + header_size; + slaveXfer.rxData = NULL; + slaveXfer.dataSize = size - header_size; { #else - uint8_t *spiData = new (nothrow) uint8_t[size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN]; + uint8_t *spiData = new (nothrow) uint8_t[size - header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN]; if (spiData != NULL) { spiData[0] = ERPC_BOARD_SPI_SLAVE_READY_MARKER1; spiData[1] = ERPC_BOARD_SPI_SLAVE_READY_MARKER2; - (void)memcpy(&spiData[ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN], data, size); + (void)memcpy(&spiData[ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN], data + header_size, size - header_size); slaveXfer.txData = spiData; slaveXfer.rxData = NULL; - slaveXfer.dataSize = size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN; + slaveXfer.dataSize = size - header_size + ERPC_BOARD_SPI_SLAVE_READY_MARKER_LEN; #endif status = SPI_SlaveTransferNonBlocking(m_spiBaseAddr, &s_handle, &slaveXfer); diff --git a/erpc_c/transports/erpc_spi_slave_transport.hpp b/erpc_c/transports/erpc_spi_slave_transport.hpp index 4a6de45a..865cb2b9 100644 --- a/erpc_c/transports/erpc_spi_slave_transport.hpp +++ b/erpc_c/transports/erpc_spi_slave_transport.hpp @@ -10,8 +10,8 @@ #ifndef _EMBEDDED_RPC__SPI_SLAVE_TRANSPORT_H_ #define _EMBEDDED_RPC__SPI_SLAVE_TRANSPORT_H_ -#include #include "erpc_config_internal.h" +#include #if ERPC_THREADS #include "erpc_threading.h" #endif @@ -79,6 +79,9 @@ class SpiSlaveTransport : public FramedTransport #endif private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from SPI peripheral. * @@ -88,7 +91,7 @@ class SpiSlaveTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed SPI failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to SPI peripheral. @@ -99,7 +102,7 @@ class SpiSlaveTransport : public FramedTransport * @retval kErpcStatus_SendFailed SPI failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_spidev_master_transport.cpp b/erpc_c/transports/erpc_spidev_master_transport.cpp index 577634c4..0d7d3a08 100644 --- a/erpc_c/transports/erpc_spidev_master_transport.cpp +++ b/erpc_c/transports/erpc_spidev_master_transport.cpp @@ -84,10 +84,8 @@ static inline void SpidevMasterTransport_WaitForSlaveReadyMarker(int spi_fd) } #endif -SpidevMasterTransport::SpidevMasterTransport(const char *spidev, uint32_t speed_Hz) -: m_spidevHandle(0) -, m_spidev(spidev) -, m_speed_Hz(speed_Hz) +SpidevMasterTransport::SpidevMasterTransport(const char *spidev, uint32_t speed_Hz) : +m_spidevHandle(0), m_spidev(spidev), m_speed_Hz(speed_Hz) { } @@ -108,7 +106,7 @@ SpidevMasterTransport::~SpidevMasterTransport(void) erpc_status_t SpidevMasterTransport::init(void) { - erpc_status_t status; + erpc_status_t status = kErpcStatus_Success; /* Initialize the SPI device */ /* Open SPI device file descriptor */ @@ -217,7 +215,7 @@ erpc_status_t SpidevMasterTransport::underlyingReceive(uint8_t *data, uint32_t s if (ERPC_SPIDEV_STATUS_SUCCESS != spidev_transfer(m_spidevHandle, NULL, data, size)) { - status = kErpcStatus_SendFailed; + status = kErpcStatus_ReceiveFailed; } return status; diff --git a/erpc_c/transports/erpc_spidev_master_transport.hpp b/erpc_c/transports/erpc_spidev_master_transport.hpp index 1af54c34..354af858 100644 --- a/erpc_c/transports/erpc_spidev_master_transport.hpp +++ b/erpc_c/transports/erpc_spidev_master_transport.hpp @@ -56,6 +56,9 @@ class SpidevMasterTransport : public FramedTransport uint32_t m_speed_Hz; /*!< SPI clock speed in Hz. */ private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from SPI peripheral. * @@ -65,7 +68,7 @@ class SpidevMasterTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed SPI failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to SPI peripheral. @@ -76,7 +79,7 @@ class SpidevMasterTransport : public FramedTransport * @retval kErpcStatus_SendFailed SPI failed to send data. * @retval kErpcStatus_Success Successfully sent all data. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_tcp_transport.cpp b/erpc_c/transports/erpc_tcp_transport.cpp index 59fac360..9712ce6c 100644 --- a/erpc_c/transports/erpc_tcp_transport.cpp +++ b/erpc_c/transports/erpc_tcp_transport.cpp @@ -13,24 +13,34 @@ #include extern "C" { +// Set this to 1 to enable debug logging. +// TODO fix issue with the transport not working on Linux if debug logging is disabled. +//#define TCP_TRANSPORT_DEBUG_LOG (1) + +#if TCP_TRANSPORT_DEBUG_LOG #if ERPC_HAS_POSIX +#if defined(__MINGW32__) +#error Missing implementation for mingw. +#endif #include #endif +#endif #include +#if defined(__MINGW32__) +#include +#include +#else #include #include -#include #include +#endif +#include #include #include } using namespace erpc; -// Set this to 1 to enable debug logging. -// TODO fix issue with the transport not working on Linux if debug logging is disabled. -//#define TCP_TRANSPORT_DEBUG_LOG (1) - #if TCP_TRANSPORT_DEBUG_LOG #define TCP_DEBUG_PRINT(_fmt_, ...) printf(_fmt_, ##__VA_ARGS__) #define TCP_DEBUG_ERR(_msg_) err(errno, _msg_) @@ -39,28 +49,50 @@ using namespace erpc; #define TCP_DEBUG_ERR(_msg_) #endif +#if defined(__MINGW32__) +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0x00000008 // Servicename must be a numeric port number +#endif +#endif + //////////////////////////////////////////////////////////////////////////////// // Code //////////////////////////////////////////////////////////////////////////////// -TCPTransport::TCPTransport(bool isServer) -: m_isServer(isServer) -, m_host(NULL) -, m_port(0) -, m_socket(-1) -, m_serverThread(serverThreadStub) -, m_runServer(true) +TCPTransport::TCPTransport(bool isServer) : +m_isServer(isServer), m_host(NULL), m_port(0) +#if defined(__MINGW32__) +, +m_socket(INVALID_SOCKET) +#else +, +m_socket(-1) +#endif +, +m_serverThread(serverThreadStub), m_runServer(true) { +#if defined(__MINGW32__) + WSADATA ws; + WSAStartup(MAKEWORD(2, 2), &ws); +#endif } -TCPTransport::TCPTransport(const char *host, uint16_t port, bool isServer) -: m_isServer(isServer) -, m_host(host) -, m_port(port) -, m_socket(-1) -, m_serverThread(serverThreadStub) -, m_runServer(true) +TCPTransport::TCPTransport(const char *host, uint16_t port, bool isServer) : +m_isServer(isServer), m_host(host), m_port(port) +#if defined(__MINGW32__) +, +m_socket(INVALID_SOCKET) +#else +, +m_socket(-1) +#endif +, +m_serverThread(serverThreadStub), m_runServer(true) { +#if defined(__MINGW32__) + WSADATA ws; + WSAStartup(MAKEWORD(2, 2), &ws); +#endif } TCPTransport::~TCPTransport(void) {} @@ -96,10 +128,18 @@ erpc_status_t TCPTransport::connectClient(void) char portString[8]; struct addrinfo *res0; int result, set; +#if defined(__MINGW32__) + SOCKET sock = INVALID_SOCKET; +#else int sock = -1; +#endif struct addrinfo *res; +#if defined(__MINGW32__) + if (m_socket != INVALID_SOCKET) +#else if (m_socket != -1) +#endif { TCP_DEBUG_PRINT("%s", "socket already connected\n"); } @@ -138,7 +178,11 @@ erpc_status_t TCPTransport::connectClient(void) { // Create the socket. sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); +#if defined(__MINGW32__) + if (sock == INVALID_SOCKET) +#else if (sock < 0) +#endif { continue; } @@ -146,8 +190,13 @@ erpc_status_t TCPTransport::connectClient(void) // Attempt to connect. if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { +#if defined(__MINGW32__) + closesocket(sock); + sock = INVALID_SOCKET; +#else ::close(sock); sock = -1; +#endif continue; } @@ -159,7 +208,11 @@ erpc_status_t TCPTransport::connectClient(void) freeaddrinfo(res0); // Check if we were able to open a connection. +#if defined(__MINGW32__) + if (sock == INVALID_SOCKET) +#else if (sock < 0) +#endif { // TODO check EADDRNOTAVAIL: TCP_DEBUG_ERR("connecting failed"); @@ -170,9 +223,17 @@ erpc_status_t TCPTransport::connectClient(void) if (status == kErpcStatus_Success) { set = 1; +#if defined(__MINGW32__) + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&set, sizeof(int)) < 0) +#else if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&set, sizeof(int)) < 0) +#endif { +#if defined(__MINGW32__) + closesocket(sock); +#else ::close(sock); +#endif TCP_DEBUG_ERR("setsockopt failed"); status = kErpcStatus_Fail; } @@ -187,9 +248,17 @@ erpc_status_t TCPTransport::connectClient(void) // Disable SIGPIPE for this socket. This will cause write() to return an EPIPE statusor if the // other side has disappeared instead of our process receiving a SIGPIPE. set = 1; +#if defined(__MINGW32__) + if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set, sizeof(int)) < 0) +#else if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)) < 0) +#endif { +#if defined(__MINGW32__) + closesocket(sock); +#else ::close(sock); +#endif TCP_DEBUG_ERR("setsockopt failed"); status = kErpcStatus_Fail; } @@ -199,7 +268,9 @@ erpc_status_t TCPTransport::connectClient(void) { #else // globally disable the SIGPIPE signal +#if !defined(__MINGW32__) signal(SIGPIPE, SIG_IGN); +#endif #endif // defined(SO_NOSIGPIPE) m_socket = sock; } @@ -215,11 +286,19 @@ erpc_status_t TCPTransport::close(bool stopServer) m_runServer = false; } +#if defined(__MINGW32__) + if (m_socket != INVALID_SOCKET) + { + closesocket(m_socket); + m_socket = INVALID_SOCKET; + } +#else if (m_socket != -1) { ::close(m_socket); m_socket = -1; } +#endif return kErpcStatus_Success; } @@ -230,7 +309,11 @@ erpc_status_t TCPTransport::underlyingReceive(uint8_t *data, uint32_t size) erpc_status_t status = kErpcStatus_Success; // Block until we have a valid connection. +#if defined(__MINGW32__) + while (m_socket == INVALID_SOCKET) +#else while (m_socket <= 0) +#endif { // Sleep 10 ms. Thread::sleep(10000); @@ -239,7 +322,11 @@ erpc_status_t TCPTransport::underlyingReceive(uint8_t *data, uint32_t size) // Loop until all requested data is received. while (size > 0U) { +#if defined(__MINGW32__) + length = recv(m_socket, (char *)data, size, 0); +#else length = read(m_socket, data, size); +#endif // Length will be zero if the connection is closed. if (length > 0) @@ -271,7 +358,11 @@ erpc_status_t TCPTransport::underlyingSend(const uint8_t *data, uint32_t size) erpc_status_t status = kErpcStatus_Success; ssize_t result; +#if defined(__MINGW32__) + if (m_socket == INVALID_SOCKET) +#else if (m_socket <= 0) +#endif { // we should not pretend to have a succesful Send or we create a deadlock status = kErpcStatus_ConnectionFailure; @@ -281,7 +372,11 @@ erpc_status_t TCPTransport::underlyingSend(const uint8_t *data, uint32_t size) // Loop until all data is sent. while (size > 0U) { +#if defined(__MINGW32__) + result = ::send(m_socket, (const char *)data, size, 0); +#else result = write(m_socket, data, size); +#endif if (result >= 0) { size -= result; @@ -310,7 +405,11 @@ erpc_status_t TCPTransport::underlyingSend(const uint8_t *data, uint32_t size) void TCPTransport::serverThread(void) { int yes = 1; +#if defined(__MINGW32__) + SOCKET serverSocket; +#else int serverSocket; +#endif int result; struct sockaddr incomingAddress; socklen_t incomingAddressLength; @@ -322,7 +421,11 @@ void TCPTransport::serverThread(void) // Create socket. serverSocket = socket(AF_INET, SOCK_STREAM, 0); +#if defined(__MINGW32__) + if (serverSocket == INVALID_SOCKET) +#else if (serverSocket < 0) +#endif { TCP_DEBUG_ERR("failed to create server socket"); } @@ -335,7 +438,11 @@ void TCPTransport::serverThread(void) serverAddress.sin_port = htons(m_port); // Turn on reuse address option. - result = setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); +#if defined(__MINGW32__) + result = setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes)); +#else + result = setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const void *)&yes, sizeof(yes)); +#endif if (result < 0) { TCP_DEBUG_ERR("setsockopt failed"); @@ -373,13 +480,21 @@ void TCPTransport::serverThread(void) incomingAddressLength = sizeof(struct sockaddr); // we should use select() otherwise we can't end the server properly incomingSocket = accept(serverSocket, &incomingAddress, &incomingAddressLength); +#if defined(__MINGW32__) + if (incomingSocket != INVALID_SOCKET) +#else if (incomingSocket > 0) +#endif { // Successfully accepted a connection. m_socket = incomingSocket; // should be inherited from accept() socket but it's not always ... yes = 1; +#if defined(__MINGW32__) + setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&yes, sizeof(yes)); +#else setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, (void *)&yes, sizeof(yes)); +#endif } else { @@ -387,7 +502,11 @@ void TCPTransport::serverThread(void) } } } +#if defined(__MINGW32__) + closesocket(serverSocket); +#else ::close(serverSocket); +#endif } } diff --git a/erpc_c/transports/erpc_tcp_transport.hpp b/erpc_c/transports/erpc_tcp_transport.hpp index 4d7ed579..7e1f4da9 100644 --- a/erpc_c/transports/erpc_tcp_transport.hpp +++ b/erpc_c/transports/erpc_tcp_transport.hpp @@ -9,6 +9,10 @@ #ifndef _EMBEDDED_RPC__TCP_TRANSPORT_H_ #define _EMBEDDED_RPC__TCP_TRANSPORT_H_ +#if defined(__MINGW32__) +#include +#endif + #include "erpc_framed_transport.hpp" #include "erpc_threading.h" @@ -82,13 +86,20 @@ class TCPTransport : public FramedTransport virtual erpc_status_t close(bool stopServer = true); protected: - bool m_isServer; /*!< If true then server is using transport, else client. */ - const char *m_host; /*!< Specify the host name or IP address of the computer. */ - uint16_t m_port; /*!< Specify the listening port number. */ - int m_socket; /*!< Socket number. */ + bool m_isServer; /*!< If true then server is using transport, else client. */ + const char *m_host; /*!< Specify the host name or IP address of the computer. */ + uint16_t m_port; /*!< Specify the listening port number. */ +#if defined(__MINGW32__) + SOCKET m_socket; /*!< Socket number. */ +#else + int m_socket; /*!< Socket number. */ +#endif Thread m_serverThread; /*!< Pointer to server thread. */ bool m_runServer; /*!< Thread is executed while this is true. */ + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief This function connect client to the server. * @@ -107,7 +118,7 @@ class TCPTransport : public FramedTransport * @retval #kErpcStatus_ReceiveFailed When reading data ends with error. * @retval #kErpcStatus_ConnectionClosed Peer closed the connection. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief This function writes data. @@ -119,7 +130,7 @@ class TCPTransport : public FramedTransport * @retval #kErpcStatus_SendFailed When writing data ends with error. * @retval #kErpcStatus_ConnectionClosed Peer closed the connection. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; /*! * @brief Server thread function. diff --git a/erpc_c/transports/erpc_uart_cmsis_transport.cpp b/erpc_c/transports/erpc_uart_cmsis_transport.cpp index 9dddd85d..3d69e710 100644 --- a/erpc_c/transports/erpc_uart_cmsis_transport.cpp +++ b/erpc_c/transports/erpc_uart_cmsis_transport.cpp @@ -26,11 +26,11 @@ static UartTransport *s_uart_instance = NULL; // Code //////////////////////////////////////////////////////////////////////////////// -UartTransport::UartTransport(ARM_DRIVER_USART *uartDrv) -: m_uartDrv(uartDrv) +UartTransport::UartTransport(ARM_DRIVER_USART *uartDrv) : +m_uartDrv(uartDrv) #if !ERPC_THREADS_IS(NONE) -, m_rxSemaphore() -, m_txSemaphore() +, +m_rxSemaphore(), m_txSemaphore() #endif { s_uart_instance = this; diff --git a/erpc_c/transports/erpc_uart_cmsis_transport.hpp b/erpc_c/transports/erpc_uart_cmsis_transport.hpp index 42e5e831..04fb5751 100644 --- a/erpc_c/transports/erpc_uart_cmsis_transport.hpp +++ b/erpc_c/transports/erpc_uart_cmsis_transport.hpp @@ -83,6 +83,9 @@ class UartTransport : public FramedTransport Semaphore m_txSemaphore; /*!< Semaphore used by RTOS to block task until the sending is not complete */ #endif private: + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from UART peripheral. * @@ -92,7 +95,7 @@ class UartTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed UART failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to UART peripheral. @@ -102,7 +105,7 @@ class UartTransport : public FramedTransport * * @retval kErpcStatus_Success Always returns success status. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_c/transports/erpc_uart_zephyr_transport.cpp b/erpc_c/transports/erpc_uart_zephyr_transport.cpp new file mode 100644 index 00000000..fe08982a --- /dev/null +++ b/erpc_c/transports/erpc_uart_zephyr_transport.cpp @@ -0,0 +1,208 @@ +/* + * Copyright 2023 NXP + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "erpc_uart_zephyr_transport.hpp" +#include +#include +#include + +using namespace erpc; + +//////////////////////////////////////////////////////////////////////////////// +// Variables +//////////////////////////////////////////////////////////////////////////////// + +static volatile bool s_isTransferReceiveCompleted = false; +static volatile bool s_isTransferSendCompleted = false; +static volatile uint32_t s_transferReceiveRequireBytes = 0; +static UartTransport *s_uart_instance = NULL; + +#define UART_BUFFER_SIZE ERPC_DEFAULT_BUFFER_SIZE + +RING_BUF_DECLARE(uart_receive_buf, UART_BUFFER_SIZE); +RING_BUF_DECLARE(uart_send_buf, UART_BUFFER_SIZE); + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +UartTransport::UartTransport(struct device *dev) : +m_dev(dev) +#if !ERPC_THREADS_IS(NONE) +, +m_rxSemaphore(), m_txSemaphore() +#endif +{ + s_uart_instance = this; +} + +UartTransport::~UartTransport(void) {} + +void UartTransport::tx_cb(void) +{ +#if !ERPC_THREADS_IS(NONE) + m_txSemaphore.put(); +#else + s_isTransferSendCompleted = true; +#endif +} + +void UartTransport::rx_cb(void) +{ +#if !ERPC_THREADS_IS(NONE) + m_rxSemaphore.put(); +#else + s_isTransferReceiveCompleted = true; +#endif + s_transferReceiveRequireBytes = UART_BUFFER_SIZE; +} + +/* Transfer callback */ +static void TransferCallback(const struct device *dev, void *user_data) +{ + uint8_t c; + uint32_t size; + uint32_t rx_size; + uint32_t tx_size; + uint8_t *data; + int err; + + if (!uart_irq_update(dev)) + { + return; + } + + if (uart_irq_rx_ready(dev)) + { + size = ring_buf_put_claim(&uart_receive_buf, &data, UART_BUFFER_SIZE); + + /* read until FIFO empty */ + rx_size = uart_fifo_read(dev, data, size); + + if (rx_size < 0) + { + /* Error */ + } + + if (rx_size == size) + { + if (uart_fifo_read(dev, &c, 1) == 1) + { + /* Error - more data in fifo */ + } + } + + err = ring_buf_put_finish(&uart_receive_buf, rx_size); + if (err != 0) + { + /* This shouldn't happen unless rx_size > size */ + } + + /* Enough bytes was received, call receive callback */ + if (ring_buf_size_get(&uart_receive_buf) >= s_transferReceiveRequireBytes) + { + s_uart_instance->rx_cb(); + } + } + + if (uart_irq_tx_ready(dev) && ring_buf_size_get(&uart_send_buf) > 0) + { + /* read one byte from queue */ + size = ring_buf_get_claim(&uart_send_buf, &data, UART_BUFFER_SIZE); + + /* send it thought UART */ + tx_size = uart_fifo_fill(dev, data, size); + if (tx_size < 0) + { + /* Error */ + } + + err = ring_buf_get_finish(&uart_send_buf, tx_size); + if (err != 0) + { + /* bytes_send exceeds amount of valid data in a ring buffer. */ + } + + if (ring_buf_size_get(&uart_send_buf) == 0) + { + /* no more bytes to send; disable tx interrupt */ + uart_irq_tx_disable(dev); + s_uart_instance->tx_cb(); + } + } +} + +erpc_status_t UartTransport::init(void) +{ + erpc_status_t erpcStatus = kErpcStatus_InitFailed; + + int32_t status = uart_irq_callback_user_data_set(m_dev, TransferCallback, this); + + if (status == 0) + { + uart_irq_rx_enable(m_dev); + erpcStatus = kErpcStatus_Success; + } + + return erpcStatus; +} + +erpc_status_t UartTransport::underlyingReceive(uint8_t *data, uint32_t size) +{ + erpc_status_t erpcStatus = kErpcStatus_ReceiveFailed; + + if (ring_buf_size_get(&uart_receive_buf) < size) + { + s_transferReceiveRequireBytes = size; + +/* wait until the receiving is finished */ +#if !ERPC_THREADS_IS(NONE) + (void)m_rxSemaphore.get(); +#else + s_isTransferReceiveCompleted = false; + while (!s_isTransferReceiveCompleted) + { + } +#endif + erpcStatus = kErpcStatus_Success; + } + + /* read data from buffer */ + if (ring_buf_get(&uart_receive_buf, data, size) != size) + { + /* reading error, should not happen */ + erpcStatus = kErpcStatus_ReceiveFailed; + } + + return erpcStatus; +} + +erpc_status_t UartTransport::underlyingSend(const uint8_t *data, uint32_t size) +{ + erpc_status_t erpcStatus = kErpcStatus_SendFailed; + + s_isTransferSendCompleted = false; + + /* fill buffer */ + ring_buf_put(&uart_send_buf, data, size); + + /* enable transport */ + uart_irq_tx_enable(m_dev); + +/* wait until the sending is finished */ +#if !ERPC_THREADS_IS(NONE) + (void)m_txSemaphore.get(); +#else + while (!s_isTransferSendCompleted) + { + } +#endif + + erpcStatus = kErpcStatus_Success; + + return erpcStatus; +} diff --git a/erpc_c/transports/erpc_uart_zephyr_transport.hpp b/erpc_c/transports/erpc_uart_zephyr_transport.hpp new file mode 100644 index 00000000..19009400 --- /dev/null +++ b/erpc_c/transports/erpc_uart_zephyr_transport.hpp @@ -0,0 +1,109 @@ +/* + * Copyright 2023 NXP + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _EMBEDDED_RPC_ZEPHYR_UART_TRANSPORT_H_ +#define _EMBEDDED_RPC_ZEPHYR_UART_TRANSPORT_H_ + +#include "erpc_config_internal.h" +#if !ERPC_THREADS_IS(NONE) +#include "erpc_threading.h" +#endif +#include "erpc_framed_transport.hpp" + +extern "C" { +#include +#include +} + +/*! + * @addtogroup uart_transport + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// Classes +//////////////////////////////////////////////////////////////////////////////// + +namespace erpc { +/*! + * @brief Transport to send/receive messages via UART. + * + * @ingroup uart_transport + */ +class UartTransport : public FramedTransport +{ +public: + /*! + * @brief Constructor. + * + * @param[in] dev Zephyr uart device. + */ + UartTransport(struct device *dev); + + /*! + * @brief Destructor. + */ + virtual ~UartTransport(void); + + /*! + * @brief Initialize Zephyr UART peripheral configuration structure with values specified in UartTransport + * constructor. + * + * @retval kErpcStatus_InitFailed When UART init function failed. + * @retval kErpcStatus_Success When UART init function was executed successfully. + */ + virtual erpc_status_t init(void); + + /*! + * @brief Function called from ARM_USART_SignalEvent when ARM_USART_EVENT_RECEIVE_COMPLETE event is asserted + * + * Unblocks the receive function. + */ + void rx_cb(void); + + /*! + * @brief Function called from ARM_USART_SignalEvent when ARM_USART_EVENT_SEND_COMPLETE event is asserted + * + * Unblocks the send function. + */ + void tx_cb(void); + +protected: + struct device *m_dev; /*!< Access structure of the UART device */ +#if !ERPC_THREADS_IS(NONE) + Semaphore m_rxSemaphore; /*!< Semaphore used by RTOS to block task until the receiving is not complete */ + Semaphore m_txSemaphore; /*!< Semaphore used by RTOS to block task until the sending is not complete */ +#endif +private: + /*! + * @brief Receive data from UART peripheral. + * + * @param[inout] data Preallocated buffer for receiving data. + * @param[in] size Size of data to read. + * + * @retval kErpcStatus_ReceiveFailed UART failed to receive data. + * @retval kErpcStatus_Success Successfully received all data. + */ + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + + /*! + * @brief Write data to UART peripheral. + * + * @param[in] data Buffer to send. + * @param[in] size Size of data to send. + * + * @retval kErpcStatus_Success Always returns success status. + */ + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); +}; + +} // namespace erpc + +/*! @} */ + +#endif // _EMBEDDED_RPC_ZEPHYR_UART_TRANSPORT_H_ diff --git a/erpc_c/transports/erpc_usb_cdc_transport.cpp b/erpc_c/transports/erpc_usb_cdc_transport.cpp index a960077a..67bf3008 100644 --- a/erpc_c/transports/erpc_usb_cdc_transport.cpp +++ b/erpc_c/transports/erpc_usb_cdc_transport.cpp @@ -83,15 +83,13 @@ void UsbCdcTransport::rx_cb(void) UsbCdcTransport::UsbCdcTransport(serial_handle_t serialHandle, serial_manager_config_t *serialConfig, serial_port_usb_cdc_config_t *usbCdcConfig, uint8_t *usbRingBuffer, - uint32_t usbRingBufferLength) -: m_serialHandle(serialHandle) -, m_serialConfig(serialConfig) -, m_usbCdcConfig(usbCdcConfig) -, m_usbRingBuffer(usbRingBuffer) -, m_usbRingBufferLength(usbRingBufferLength) + uint32_t usbRingBufferLength) : +m_serialHandle(serialHandle), +m_serialConfig(serialConfig), m_usbCdcConfig(usbCdcConfig), m_usbRingBuffer(usbRingBuffer), +m_usbRingBufferLength(usbRingBufferLength) #if !ERPC_THREADS_IS(NONE) -, m_rxSemaphore() -, m_txSemaphore() +, +m_rxSemaphore(), m_txSemaphore() #endif { s_usbcdc_instance = this; diff --git a/erpc_c/transports/erpc_usb_cdc_transport.hpp b/erpc_c/transports/erpc_usb_cdc_transport.hpp index a32df59d..ccd7b5ab 100644 --- a/erpc_c/transports/erpc_usb_cdc_transport.hpp +++ b/erpc_c/transports/erpc_usb_cdc_transport.hpp @@ -9,8 +9,8 @@ #ifndef _EMBEDDED_RPC__USB_CDC_TRANSPORT_H_ #define _EMBEDDED_RPC__USB_CDC_TRANSPORT_H_ -#include #include "erpc_config_internal.h" +#include #if !ERPC_THREADS_IS(NONE) #include "erpc_threading.h" #endif @@ -96,6 +96,9 @@ class UsbCdcTransport : public FramedTransport uint8_t *m_usbRingBuffer; uint32_t m_usbRingBufferLength; + using FramedTransport::underlyingReceive; + using FramedTransport::underlyingSend; + /*! * @brief Receive data from USB CDC peripheral. * @@ -105,7 +108,7 @@ class UsbCdcTransport : public FramedTransport * @retval kErpcStatus_ReceiveFailed USB CDC failed to receive data. * @retval kErpcStatus_Success Successfully received all data. */ - virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override; /*! * @brief Write data to USB CDC peripheral. @@ -115,7 +118,7 @@ class UsbCdcTransport : public FramedTransport * * @retval kErpcStatus_Success Always returns success status. */ - virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size); + virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override; }; } // namespace erpc diff --git a/erpc_java/.gitignore b/erpc_java/.gitignore new file mode 100644 index 00000000..a91c35d3 --- /dev/null +++ b/erpc_java/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store +/.idea/ diff --git a/erpc_java/checkstyle.xml b/erpc_java/checkstyle.xml new file mode 100644 index 00000000..b5397fb4 --- /dev/null +++ b/erpc_java/checkstyle.xml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/erpc_java/deploy.xml b/erpc_java/deploy.xml new file mode 100644 index 00000000..1adf2193 --- /dev/null +++ b/erpc_java/deploy.xml @@ -0,0 +1,195 @@ + + + 4.0.0 + + io.github.embeddedrpc.erpc + erpc + 0.1.0 + + eRPC + eRPC (Embedded RPC) is an open source Remote Procedure Call (RPC) system for multichip embedded systems + and heterogeneous multicore SoCs. + + https://github.com/EmbeddedRPC/erpc + + + + The 3-Clause BSD License + https://opensource.org/license/bsd-3-clause/ + + + + + + Jan Komarek + jan.komarek@nxp.com + nxp.com + http://www.nxp.com + + + + + scm:git:git://github.com/EmbeddedRPC/erpc.git + scm:git:ssh://github.com/EmbeddedRPC/erpc.git + https://github.com/EmbeddedRPC/erpc/tree/develop + + + + + 21 + 21 + UTF-8 + + + 5.6.0 + 3.0.0-M3 + 3.3.0 + 3.0.0-M5 + 3.0.0 + + + internal.repo + Internal maven repository + file:c:\maven_repository + + + + + + com.fazecast + jSerialComm + 2.10.3 + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.codehaus.groovy + groovy + 2.5.14 + + + + + + ossrh + https://s01.oss.sonatype.org/content/repositories/snapshots + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + + enforce + + + + + 3.6.3 + + + true + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven-checkstyle-plugin.version} + + checkstyle.xml + + + + checkstyle + validate + + check + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + utf-8 + -Dfile.encoding=utf-8 + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + + attach-javadocs + verify + + jar + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://s01.oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + \ No newline at end of file diff --git a/erpc_java/pom.xml b/erpc_java/pom.xml new file mode 100644 index 00000000..934b688f --- /dev/null +++ b/erpc_java/pom.xml @@ -0,0 +1,129 @@ + + + 4.0.0 + + io.github.embeddedrpc.erpc + erpc + 0.1.0 + + eRPC + eRPC (Embedded RPC) is an open source Remote Procedure Call (RPC) system for multichip embedded systems + and heterogeneous multicore SoCs. + + https://github.com/EmbeddedRPC/erpc + + + + The 3-Clause BSD License + https://opensource.org/license/bsd-3-clause/ + + + + + + Jan Komarek + jan.komarek@nxp.com + nxp.com + http://www.nxp.com + + + + + scm:git:git://github.com/EmbeddedRPC/erpc.git + scm:git:ssh://github.com/EmbeddedRPC/erpc.git + https://github.com/EmbeddedRPC/erpc/tree/develop + + + + + 21 + 21 + UTF-8 + + + 5.6.0 + 3.0.0-M3 + 3.3.0 + 3.0.0-M5 + + + + + + com.fazecast + jSerialComm + 2.10.3 + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.codehaus.groovy + groovy + 2.5.14 + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + + enforce + + + + + 3.6.3 + + + true + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven-checkstyle-plugin.version} + + checkstyle.xml + + + + checkstyle + validate + + check + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + utf-8 + -Dfile.encoding=utf-8 + + + + + + \ No newline at end of file diff --git a/erpc_java/readme.md b/erpc_java/readme.md new file mode 100644 index 00000000..dd47cbfe --- /dev/null +++ b/erpc_java/readme.md @@ -0,0 +1,105 @@ +# eRPC Java Infrastructure + +This folder contains the Java implementation of the eRPC infrastructure. + +## Contents + +- `/src/main/java/io/github/embeddedrpc/erpc` - Java package containing eRPC infrastructure. +- `pom.xml` - Maven config file. +- `checkstyle.xml` - Check style config file. + +## Prerequisites + +- [Java 21 SDK](https://jdk.java.net/21/) +- [Maven 3.9.5](https://maven.apache.org/download.cgi) + +To check that all the prerequisites are correctly installed, run `mvn -v`. You should get something like this: + +``` +Apache Maven 3.9.5 (***) +Maven home: c:\Program Files\maven\apache-maven-3.9.5 +Java version: 21, vendor: Oracle Corporation, runtime: c:\Program Files\Java\jdk-21 +Default locale: en_US, platform encoding: UTF-8 +OS name: "***", version: "***", arch: "***", family: "***" +``` + +- If `mvn -v` fails, check that you have added maven to the `PATH` variable. +- If you do not see the correct Java version, check that you have set the `JAVA_HOME` and `PATH` variables correctly. + + +## Installation + +1. Run `mvn install` to download all dependencies and install eRPC to local maven repository. + +## Usage + +### Client + +```Java +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.client.ClientManager; +import io.github.embeddedrpc.erpc.codec.BasicCodecFactory; +import io.github.embeddedrpc.erpc.transport.TCPTransport; +import io.github.embeddedrpc.erpc.transport.Transport; + +import com.example.app.client.MyTestClient; + +public class Main { + public static void main(String[] args) { + Transport transport = new TCPTransport("localhost", 40); + //Transport transport = new SerialTransport("COM4", 115200); + + ClientManager clientManager = new ClientManager(transport, new BasicCodecFactory()); + MyTestClient client = new MyTestClient(clientManager); + + Reference out; + int result; + + result = client.foo(42, 8); + client.boo("John", out); + } +} +``` + +### Server +#### Main.java +```Java +import io.github.embeddedrpc.erpc.server.Server; +import io.github.embeddedrpc.erpc.server.SimpleServer; +import io.github.embeddedrpc.erpc.codec.BasicCodecFactory; +import io.github.embeddedrpc.erpc.transport.TCPTransport; +import io.github.embeddedrpc.erpc.transport.Transport; + +import com.example.app.MyTestService; + +public class Main { + public static void main(String[] args) { + Transport transport = new TCPTransport("localhost", 40); + //Transport transport = new SerialTransport("COM4", 115200); + + Server server = new SimpleServer(transport, new BasicCodecFactory()); + + server.addService(new MyTestService()); + + server.run(); + } +} +``` +#### MyTestService.java + +```Java +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import com.example.app.server.AbstractMyTestService; + +public class MyTestService extends AbstractMyTestService { + @Override + public int foo(int a, int b) { + return a + b; + } + + @Override + public void boo(String in, Reference out) { + out.set("Hello " + in); + } +} +``` \ No newline at end of file diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Crc16.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Crc16.java new file mode 100644 index 00000000..92146b56 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Crc16.java @@ -0,0 +1,69 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.auxiliary; + +/** + * Class for computing ITU-CCITT CRC-16. + */ +public class Crc16 { + private static final int POLY = 0x1021; + private final int crcStart; + private final int[] table; + + /** + * CRC16 constructor. + * + * @param crcStart CRC16 start position + */ + @SuppressWarnings("magicnumber") + public Crc16(int crcStart) { + this.crcStart = crcStart; + this.table = new int[256]; + for (int i = 0; i < 256; i++) { + this.table[i] = this.computeTable(i); + } + } + + /** + * CRC16 constructor with start position 0xEF4A. + */ + @SuppressWarnings("magicnumber") + public Crc16() { + this(0xEF4A); + } + + /** + * Function return CRC16 for given byte array. + * + * @param data Input byte array + * @return Computed CRC16 + */ + @SuppressWarnings("magicnumber") + public int computeCRC16(byte[] data) { + int crc = this.crcStart; + for (byte c : data) { + crc = ((crc << 8) ^ this.table[((crc >> 8) ^ c) & 0xFF]) & 0xFFFF; + } + return crc; + } + + @SuppressWarnings("magicnumber") + private int computeTable(int i) { + int crc = 0; + int y = i; + y <<= 8; + for (int b = 0; b < 8; b++) { + int temp = crc ^ y; + crc <<= 1; + if ((temp & 0x8000) != 0) { + crc ^= POLY; + } + y <<= 1; + } + return crc; + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageInfo.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageInfo.java new file mode 100644 index 00000000..781404b0 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageInfo.java @@ -0,0 +1,22 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.auxiliary; + +/** + * Record storing information about message. + * + * @param type Message type + * @param service Service identification + * @param request Request identification + * @param sequence Sequence number + */ +public record MessageInfo( + MessageType type, + int service, + int request, + int sequence) { +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageType.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageType.java new file mode 100644 index 00000000..bc79c4e3 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/MessageType.java @@ -0,0 +1,68 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.auxiliary; + +/** + * Message type. + */ +public enum MessageType { + /** + * Invocation message. + */ + kInvocationMessage(0), + + /** + * One way message. + */ + kOnewayMessage(1), + + /** + * Reply message. + */ + kReplyMessage(2), + + /** + * Notification message. + */ + kNotificationMessage(3); + + private final int value; + + /** + * MessageType constructor. + * + * @param value Value to be assigned + */ + MessageType(int value) { + this.value = value; + } + + /** + * Get message type value. + * + * @return message value + */ + public int getValue() { + return value; + } + + /** + * Function returns @{MessageType} base on value. + * + * @param value Value to be converted to MessageType + * @return Corresponding MessageType + */ + public static MessageType getMessageType(int value) { + return switch (value) { + case 0 -> kInvocationMessage; + case 1 -> kOnewayMessage; + case 2 -> kReplyMessage; + case 3 -> kNotificationMessage; + default -> throw new RuntimeException("Invalid MessageType " + value); + }; + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Reference.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Reference.java new file mode 100644 index 00000000..5d9cb4fb --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Reference.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.auxiliary; + +/** + * This class is used for out/inout parameters. + * + * @param Type of value stored in Reference + */ +public final class Reference { + private T referent; + + /** + * Reference constructor with initial value. + * + * @param initialValue default value + */ + public Reference(T initialValue) { + referent = initialValue; + } + + /** + * Reference constructor. + */ + public Reference() { + } + + /** + * Set reference value. + * + * @param newVal new value + */ + public void set(T newVal) { + referent = newVal; + } + + /** + * Get reference value. + * + * @return value + */ + public T get() { + return referent; + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestContext.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestContext.java new file mode 100644 index 00000000..f539b714 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestContext.java @@ -0,0 +1,21 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.auxiliary; + +import io.github.embeddedrpc.erpc.codec.Codec; +import groovyjarjarantlr.ByteBuffer; + +/** + * Record storing request context. + * + * @param sequence Sequence number + * @param message Message to be sent + * @param codec Codec used to store send and received message + * @param isOneWay Request direction + */ +public record RequestContext(int sequence, ByteBuffer message, Codec codec, Boolean isOneWay) { +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestError.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestError.java new file mode 100644 index 00000000..3b03cf12 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/RequestError.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.auxiliary; + +/** + * Request error thrown when unexpected situation occurred during sending and receiving message. + */ +public class RequestError extends RuntimeException { + /** + * Request error. + * + * @param message error message + */ + public RequestError(String message) { + super(message); + } + + /** + * Request error. + * @param message error message + * @param cause error chain + */ + public RequestError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Utils.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Utils.java new file mode 100644 index 00000000..5120b147 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/auxiliary/Utils.java @@ -0,0 +1,166 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.auxiliary; + +/** + * Utility class. + */ +public final class Utils { + private static final int HEX_BASE = 16; + + private Utils() { + } + + /** + * Check if UInt8 value is in valid range. + * + * @param value UInt8 value + */ + public static void checkUInt8(short value) { + if (value < 0 || value > 0xFF) { + throw new IllegalArgumentException("Value has to be in rage from 0 to 2^8"); + } + } + + /** + * Check if UInt16 value is in valid range. + * + * @param value UInt16 value + */ + public static void checkUInt16(int value) { + if (value < 0 || value > 0xFFFF) { + throw new IllegalArgumentException("Value has to be in rage from 0 to 2^16"); + } + } + + /** + * Check if Object is null. + * + * @param object Object to be checked + * @param errorMessage Message for exception + */ + public static void checkNotNull(Object object, String errorMessage) { + if (object == null) { + throw new IllegalArgumentException(errorMessage); + } + } + + /** + * Check if UInt32 value is in valid range. + * + * @param value UInt32 value + */ + public static void checkUInt32(long value) { + if (value < 0 || value > 0xFFFFFFFFL) { + throw new IllegalArgumentException("Value has to be in rage from 0 to 2^32"); + } + } + + /** + * Convert long representing uint32 to int. Persist 32 lower bites. + * long 4294967295 (0xFFFFFFFF, UINT32_MAX) -> int -1 (0xFFFFFFFF) + * + * @param value Value to be converted + * @return uint32 as int + */ + public static int uInt32toInt(long value) { + return (int) (value & 0xFFFFFFFFL); + } + + /** + * Convert int representing uint16 to short. Persist 16 lower bites. + * + * @param value Value to be converted + * @return uint16 as short + */ + public static short uInt16toShort(int value) { + return (short) (value & 0xFFFF); + } + + /** + * Convert int representing uint8 to byte. Persist 8 lower bites. + * + * @param value Value to be converted + * @return uint8 as byte + */ + public static byte uInt8toByte(short value) { + return (byte) (value & 0xFF); + } + + /** + * Convert int representing uint32 to long. + * + * @param value Value to be converted + * @return uint32 as long + */ + public static long intToUInt32(int value) { + return ((long) value) & 0xFFFFFFFFL; + } + + /** + * Convert short representing uint16 to int. + * + * @param value Value to be converted + * @return uint16 as int + */ + public static int shortToUInt16(short value) { + return ((int) value) & 0xFFFF; + } + + /** + * Convert byte representing uint8 to short. + * + * @param value Value to be converted + * @return uint8 as short + */ + public static short byteToUInt8(byte value) { + return (short) (((short) value) & (short) 0xFF); + } + + /** + * Conver int representing uint16 to bytearray (little endian). + * + * @param value Value to by converted + * @return uint16 as bytes + */ + public static byte[] uInt16ToBytes(int value) { + checkUInt16(value); + return new byte[]{(byte) (value & 0xFF), (byte) ((value >> 8) & 0xFF)}; + } + + /** + * Function creates string representing byte array as hex. + * + * @param a Byte array + * @return String representing byte array + */ + public static String byteArrayToHex(byte[] a) { + StringBuilder sb = new StringBuilder(a.length * 2); + for (byte b : a) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } + + /** + * Function converts string to byte array. + * + * @param string String to be converted + * @return Byte array + */ + public static byte[] hexToByteArray(String string) { + byte[] array = new byte[string.length() / 2]; + + for (int i = 0; i < array.length; i++) { + int index = i * 2; + int j = Integer.parseInt(string.substring(index, index + 2), HEX_BASE); + array[i] = (byte) j; + } + + return array; + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/client/ClientManager.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/client/ClientManager.java new file mode 100644 index 00000000..3e036240 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/client/ClientManager.java @@ -0,0 +1,81 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.client; + +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.codec.CodecFactory; +import io.github.embeddedrpc.erpc.transport.Transport; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.RequestContext; +import io.github.embeddedrpc.erpc.auxiliary.RequestError; + +/** + * Client manager. + */ +public class ClientManager { + private final Transport transport; + private final CodecFactory codecFactory; + private int sequence; + + /** + * ClientManager constructor. + * + * @param transport Transport used for communication + * @param codecFactory Codec factory used for creating codec instances + */ + public ClientManager(final Transport transport, + final CodecFactory codecFactory) { + this.transport = transport; + this.codecFactory = codecFactory; + this.sequence = 0; + } + + private int getSequence() { + sequence += 1; + return sequence; + } + + /** + * Function creates new request context. + * + * @param isOneWay Specify request direction + * @return New request context + */ + public RequestContext createRequest(Boolean isOneWay) { + Codec codec = codecFactory.create(); + + return new RequestContext(getSequence(), null, codec, isOneWay); + } + + /** + * Function takes @{RequestContext} and perform data exchange with server. + * If request is not one way, read incoming data and save them to request's + * codec. + * + * @param request Request to be performed + */ + public void performRequest(RequestContext request) { + this.transport.send(request.codec().array()); + + if (!request.isOneWay()) { + request.codec().setArray(this.transport.receive()); + + MessageInfo info = request.codec().startReadMessage(); + + if (info.type() != MessageType.kReplyMessage) { + throw new RequestError("Invalid reply message type."); + } + + if (info.sequence() != request.sequence()) { + throw new RequestError("Unexpected sequence number in reply (was " + info.sequence() + ", expected " + + request.sequence() + ")."); + } + } + } + +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodec.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodec.java new file mode 100644 index 00000000..a21263fe --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodec.java @@ -0,0 +1,291 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.codec; + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.Utils; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * Basic implementation of the Codec. + */ +@SuppressWarnings("checkstyle:MagicNumber") +public final class BasicCodec implements Codec { + private static final int BASIC_CODEC_VERSION = 1; + private static final int DEFAULT_BUFFER_SIZE = 256; + + private ByteBuffer buffer; + + /** + * Basic codec constructor. Create empty buffer. + */ + public BasicCodec() { + this.reset(); + } + + /** + * Basic codec constructor. Create buffer from byte array. + * + * @param byteArray byte array + */ + public BasicCodec(final byte[] byteArray) { + this.buffer = ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN); + } + + private void prepareForWrite(final int bytesToWrite) { + if (this.buffer.remaining() < bytesToWrite) { + ByteBuffer newBuffer = ByteBuffer.allocate( + (this.buffer.capacity() + bytesToWrite) * 2 + ); + newBuffer.order(ByteOrder.LITTLE_ENDIAN); + this.buffer.flip(); + + newBuffer.put(this.buffer); + this.buffer = newBuffer; + } + } + + @Override + public void reset() { + this.buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE) + .order(ByteOrder.LITTLE_ENDIAN); + } + + @Override + public byte[] array() { + int position = buffer.position(); + byte[] data = new byte[position]; + buffer.position(0); + buffer.get(data); + buffer.position(position); + return data; + } + + @Override + public void setArray(final byte[] array) { + this.buffer = ByteBuffer.wrap(array).order(ByteOrder.LITTLE_ENDIAN); + } + + @Override + public void startWriteMessage(final MessageInfo msgInfo) { + long header = (BASIC_CODEC_VERSION << 24) + | ((msgInfo.service() & 0xff) << 16) + | ((msgInfo.request() & 0xff) << 8) + | (msgInfo.type().getValue() & 0xff); + + this.writeUInt32(header); + this.writeUInt32(msgInfo.sequence()); + } + + @Override + public void writeBool(final Boolean value) { + prepareForWrite(1); + this.buffer.put(value ? (byte) 1 : (byte) 0); + } + + @Override + public void writeInt8(final byte value) { + prepareForWrite(1); + this.buffer.put(value); + } + + @Override + public void writeInt16(final short value) { + prepareForWrite(2); + this.buffer.putShort(value); + } + + @Override + public void writeInt32(final int value) { + prepareForWrite(4); + this.buffer.putInt(value); + } + + @Override + public void writeInt64(final long value) { + prepareForWrite(8); + this.buffer.putLong(value); + } + + @Override + public void writeUInt8(final short value) { + Utils.checkUInt8(value); + prepareForWrite(1); + this.buffer.put(Utils.uInt8toByte(value)); + } + + @Override + public void writeUInt16(final int value) { + Utils.checkUInt16(value); + prepareForWrite(2); + this.buffer.putShort(Utils.uInt16toShort(value)); + } + + @Override + public void writeUInt32(final long value) { + Utils.checkUInt32(value); + prepareForWrite(4); + this.buffer.putInt(Utils.uInt32toInt(value)); + } + + @Override + public void writeUInt64(final long value) { + throw new UnsupportedOperationException( + "Java implementation of the eRPC does not support 'uint64'" + ); + } + + @Override + public void writeFloat(final float value) { + prepareForWrite(4); + this.buffer.putFloat(value); + } + + @Override + public void writeDouble(final double value) { + prepareForWrite(8); + this.buffer.putDouble(value); + } + + @Override + public void writeString(final String value) { + this.writeBinary(value.getBytes()); + } + + @Override + public void writeBinary(final byte[] value) { + this.writeInt32(value.length); + prepareForWrite(value.length); + this.buffer.put(value); + } + + @Override + public void startWriteList(final int length) { + this.writeUInt32(length); + } + + @Override + public void startWriteUnion(final int discriminator) { + this.writeUInt32(discriminator); + } + + @Override + public void writeNullFlag(final int value) { + this.writeUInt32(value != 0 ? 1 : 0); + } + + @Override + public MessageInfo startReadMessage() { + int header = (int) this.readUInt32(); + int sequence = (int) this.readUInt32(); + int version = header >> 24; + + if (version != BASIC_CODEC_VERSION) { + throw new CodecError("Unsupported codec version" + version); + } + + int service = (header >> 16) & 0xff; + int request = (header >> 8) & 0xff; + MessageType msgType = MessageType.getMessageType(header & 0xff); + + return new MessageInfo(msgType, service, request, sequence); + } + + @Override + public Boolean readBool() { + return this.buffer.get() != 0; + } + + @Override + public byte readInt8() { + return this.buffer.get(); + } + + @Override + public short readInt16() { + return this.buffer.getShort(); + } + + @Override + public int readInt32() { + return this.buffer.getInt(); + } + + @Override + public long readInt64() { + return this.buffer.getLong(); + } + + @Override + public short readUInt8() { + return Utils.byteToUInt8(this.buffer.get()); + } + + @Override + public int readUInt16() { + return Utils.shortToUInt16(this.buffer.getShort()); + } + + @Override + public long readUInt32() { + return Utils.intToUInt32(this.buffer.getInt()); + } + + @Override + public long readUInt64() { + throw new UnsupportedOperationException( + "Java implementation of the eRPC does not support 'uint64'" + ); + } + + @Override + public float readFloat() { + return this.buffer.getFloat(); + } + + @Override + public double readDouble() { + return this.buffer.getDouble(); + } + + @Override + public String readString() { + return new String(this.readBinary()); + } + + @Override + public byte[] readBinary() { + long length = readUInt32(); + byte[] data = new byte[(int) length]; + this.buffer.get(data, 0, (int) length); + + return data; + } + + @Override + public long startReadList() { + return this.readUInt32(); + } + + @Override + public int startReadUnion() { + return this.readInt8(); + } + + @Override + public Boolean readNullFlag() { + return this.readUInt8() != 0; + } + + @Override + public ByteBuffer getBuffer() { + return buffer; + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodecFactory.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodecFactory.java new file mode 100644 index 00000000..d30b8f48 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/BasicCodecFactory.java @@ -0,0 +1,23 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.codec; + +/** + * Implementation of CodeFactory for BasicCodec. + */ +public final class BasicCodecFactory extends CodecFactory { + @Override + protected Codec createCodec() { + return new BasicCodec(); + } + + @Override + protected Codec createCodec(final byte[] array) { + return new BasicCodec(array); + } + +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/Codec.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/Codec.java new file mode 100644 index 00000000..7267937e --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/Codec.java @@ -0,0 +1,281 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.codec; + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; + +import java.nio.ByteBuffer; + +/** + * Interface for Codec. + */ +public interface Codec { + /** + * Reset codec. + */ + void reset(); + + /** + * Return bytea array from code's buffer. + * + * @return buffer data + */ + byte[] array(); + + /** + * Return code's ByteBuffer. + * + * @return buffer + */ + ByteBuffer getBuffer(); + + /** + * Set buffer data. + * + * @param array data to be set + */ + void setArray(byte[] array); + + /** + * Write message info to buffer. + * + * @param msgInfo message info + */ + void startWriteMessage(MessageInfo msgInfo); + + /** + * Write bool to buffer. + * + * @param value bool value + */ + void writeBool(Boolean value); + + /** + * Write int8 to buffer. + * + * @param value int8 value + */ + void writeInt8(byte value); + + /** + * Write int16 to buffer. + * + * @param value 16 value + */ + void writeInt16(short value); + + /** + * Write int32 to buffer. + * + * @param value int32 value + */ + void writeInt32(int value); + + /** + * Write int64 to buffer. + * + * @param value int64 value + */ + void writeInt64(long value); + + /** + * Write uint8 to buffer. + * + * @param value uint8 value + */ + void writeUInt8(short value); + + /** + * Write uint16 to buffer. + * + * @param value uint16 value + */ + void writeUInt16(int value); + + /** + * Write uint32 to buffer. + * + * @param value uint32 value + */ + void writeUInt32(long value); + + /** + * Java implementation does not support uint64. + * + * @param value value + */ + void writeUInt64(long value); + + /** + * Write float to buffer. + * + * @param value float value + */ + void writeFloat(float value); + + /** + * Write double to buffer. + * + * @param value double value + */ + void writeDouble(double value); + + /** + * Write string to buffer. + * + * @param value string value + */ + void writeString(String value); + + /** + * Write binary (byte array) to buffer. + * + * @param value binary value + */ + void writeBinary(byte[] value); + + /** + * Write list length to buffer. + * + * @param length list length + */ + void startWriteList(int length); + + /** + * Write union discriminator to buffer. + * + * @param discriminator discriminator + */ + void startWriteUnion(int discriminator); + + /** + * Write null flag to buffer. + * + * @param value flag value + */ + void writeNullFlag(int value); + + /** + * Read message info. + * + * @return Message info + */ + MessageInfo startReadMessage(); + + /** + * Read bool from buffer. + * + * @return bool value + */ + Boolean readBool(); + + /** + * Read int8 from buffer. + * + * @return int8 value + */ + byte readInt8(); + + /** + * Read int16 from buffer. + * + * @return int16 value + */ + short readInt16(); + + /** + * Read int32 from buffer. + * + * @return int32 value + */ + int readInt32(); + + /** + * Read int64 from buffer. + * + * @return int64 value + */ + long readInt64(); + + /** + * Read uint8 from buffer. + * + * @return uint8 value + */ + short readUInt8(); + + /** + * Read uint16 from buffer. + * + * @return uint16 value + */ + int readUInt16(); + + /** + * Read uint32 from buffer. + * + * @return uin32 value + */ + long readUInt32(); + + /** + * Java implementation does not support uint64. + * + * @return bool value + */ + long readUInt64(); + + /** + * Read float from buffer. + * + * @return float value + */ + float readFloat(); + + /** + * Read double from buffer. + * + * @return double value + */ + double readDouble(); + + /** + * Read string from buffer. + * + * @return string value + */ + String readString(); + + /** + * Read binary from buffer. + * + * @return binary value + */ + byte[] readBinary(); + + /** + * Read bool from buffer. + * + * @return bool value + */ + long startReadList(); + + /** + * Read bool from buffer. + * + * @return bool value + */ + int startReadUnion(); + + /** + * Read bool from buffer. + * + * @return bool value + */ + Boolean readNullFlag(); + +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecError.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecError.java new file mode 100644 index 00000000..4a04a496 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecError.java @@ -0,0 +1,21 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.codec; + +/** + * Codec error. + */ +public class CodecError extends RuntimeException { + /** + * Request error. + * + * @param message error message + */ + public CodecError(String message) { + super(message); + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecFactory.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecFactory.java new file mode 100644 index 00000000..0875bf99 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/codec/CodecFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.codec; + +/** + * Abstract class for Code factory. Allow to create specific codec. + */ +public abstract class CodecFactory { + /** + * Create new empty Codec. + * + * @return Empty Codec + */ + public Codec create() { + return createCodec(); + } + + /** + * Create new Codec from initial bytes. + * + * @param array Initial bytes for Codec + * @return New Codec + */ + public Codec create(byte[] array) { + return createCodec(array); + } + + protected abstract Codec createCodec(); + + protected abstract Codec createCodec(byte[] array); +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Server.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Server.java new file mode 100644 index 00000000..8046babe --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Server.java @@ -0,0 +1,99 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.server; + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.RequestError; +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.codec.CodecFactory; +import io.github.embeddedrpc.erpc.transport.Transport; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Abstract server class. + */ +public abstract class Server { + private final CodecFactory codecFactory; + private final Transport transport; + private final Map services = new HashMap<>(); + + /** + * Server constructor. + * + * @param transport transport used in server + * @param codecFactory codec factory used for creating codec + */ + public Server(Transport transport, CodecFactory codecFactory) { + this.transport = transport; + this.codecFactory = codecFactory; + } + + protected final CodecFactory getCodecFactory() { + return codecFactory; + } + + protected final Transport getTransport() { + return transport; + } + + /** + * Get unmodifiable map of all services. + * + * @return map of services. + */ + public Map getServices() { + return Collections.unmodifiableMap(services); + } + + /** + * Add new service to the server. + * + * @param service Service to be added + */ + public void addService(Service service) { + services.put(service.getServiceId(), service); + } + + /** + * Takes Codec with received data and process them. + * + * @param codec Codec with data + */ + protected void processRequest(Codec codec) { + MessageInfo info = codec.startReadMessage(); + + if (info.type() != MessageType.kInvocationMessage && info.type() != MessageType.kOnewayMessage) { + throw new RequestError("Invalid type of incoming request"); + } + + Service service = services.get(info.service()); + + if (service == null) { + throw new RequestError("Invalid service ID (" + info.service() + ")"); + } + + service.handleInvocation(info.request(), info.sequence(), codec); + + if (info.type() == MessageType.kOnewayMessage) { + codec.reset(); + } + } + + /** + * Run the server. + */ + public abstract void run(); + + /** + * Stop the server. + */ + public abstract void stop(); +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Service.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Service.java new file mode 100644 index 00000000..4cbe3994 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/Service.java @@ -0,0 +1,73 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.server; + +import io.github.embeddedrpc.erpc.auxiliary.RequestError; +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.codec.CodecError; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +/** + * Abstract class representing server's service. Service handle its methods invocation. + */ +public abstract class Service { + private final int serviceId; + private final Map> methodHandlers = new HashMap<>(); + + /** + * Create new service with ID. + * + * @param serviceId service ID + */ + public Service(int serviceId) { + this.serviceId = serviceId; + } + + /** + * Return service ID. + * + * @return ID + */ + public int getServiceId() { + return serviceId; + } + + /** + * Add method to the service. + * + * @param methodId method id + * @param handler function that handle method + */ + protected void addMethodHandler(int methodId, BiConsumer handler) { + methodHandlers.put(methodId, handler); + } + + /** + * Handle service invocation. Find corresponding handler for method and execute it. + * + * @param methodId Method ID + * @param sequence Message sequence number + * @param codec Codec with method's data + */ + public void handleInvocation(int methodId, int sequence, Codec codec) { + BiConsumer method = methodHandlers.get(methodId); + + if (method == null) { + throw new RequestError("Invalid method ID (" + methodId + ")."); + } + + try { + method.accept(sequence, codec); + } catch (CodecError | RequestError e) { + throw new RequestError( + "Invalid method ID (" + methodId + ") or method implementation.", e); + } + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/SimpleServer.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/SimpleServer.java new file mode 100644 index 00000000..80a96a17 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/SimpleServer.java @@ -0,0 +1,66 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.server; + +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.codec.CodecFactory; +import io.github.embeddedrpc.erpc.transport.RequestError; +import io.github.embeddedrpc.erpc.transport.Transport; +import io.github.embeddedrpc.erpc.transport.TransportError; + +/** + * Simple server implementation. Single thread. + */ +public final class SimpleServer extends Server { + private boolean runFlag; + + /** + * Crea simple server. + * + * @param transport transport used in server + * @param codecFactory codec factory used for creating codec on request + */ + public SimpleServer(Transport transport, CodecFactory codecFactory) { + super(transport, codecFactory); + } + + private void receiveRequest() { + byte[] data = getTransport().receive(); + Codec codec = getCodecFactory().create(data); + + processRequest(codec); + + byte[] responseData = codec.array(); + + if (responseData.length != 0) { + getTransport().send(responseData); + } + } + + @Override + public void run() { + runFlag = true; + + while (runFlag) { + try { + receiveRequest(); + } catch (TransportError e) { + System.err.println("Transport error: " + e); + stop(); + } catch (RequestError e) { + System.err.println("Error while processing request: " + e); + stop(); + } + } + } + + @Override + public void stop() { + runFlag = false; + } + +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/ThreadServer.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/ThreadServer.java new file mode 100644 index 00000000..78df5b3e --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/server/ThreadServer.java @@ -0,0 +1,13 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.server; + +/** + * Threaded server. + */ +public class ThreadServer { +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/FramedTransport.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/FramedTransport.java new file mode 100644 index 00000000..3c4cca54 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/FramedTransport.java @@ -0,0 +1,97 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.transport; + +import io.github.embeddedrpc.erpc.auxiliary.Crc16; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import io.github.embeddedrpc.erpc.codec.BasicCodec; +import io.github.embeddedrpc.erpc.codec.Codec; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Abstract class for framed transports implementations. + */ +public abstract class FramedTransport implements Transport { + private static final int HEADER_LEN = 6; + + private final Crc16 crc16 = new Crc16(); + private final Lock receiveLock = new ReentrantLock(); + private final Lock sendLock = new ReentrantLock(); + + @Override + public final byte[] receive() { + try { + receiveLock.lock(); + byte[] headerData = baseReceive(HEADER_LEN); + Codec codec = new BasicCodec(headerData); + + int crcHeader = codec.readUInt16(); + int messageLength = codec.readUInt16(); + int crcBody = codec.readUInt16(); + + int computedCrc = crc16.computeCRC16(Utils.uInt16ToBytes(messageLength)) + + crc16.computeCRC16(Utils.uInt16ToBytes(crcBody)); + computedCrc &= 0xFFFF; // 2 bytes + + if (computedCrc != crcHeader) { + throw new RequestError("Invalid message (header) CRC"); + } + + byte[] data = baseReceive(messageLength); + + int computedBodyCrc16 = crc16.computeCRC16(data); + + if (computedBodyCrc16 != crcBody) { + throw new RequestError("Invalid message (body) CRC"); + } + + return data; + } finally { + receiveLock.unlock(); + } + + } + + @Override + public final void send(byte[] message) { + try { + sendLock.lock(); + + Codec codec = new BasicCodec(); + + int messageLength = message.length; + int crcBody = crc16.computeCRC16(message); + int crcHeader = crc16.computeCRC16(Utils.uInt16ToBytes(messageLength)) + + crc16.computeCRC16(Utils.uInt16ToBytes(crcBody)); + crcHeader &= 0xFFFF; // 2 bytes + + codec.writeUInt16(crcHeader); + codec.writeUInt16(messageLength); + codec.writeUInt16(crcBody); + + byte[] header = codec.array(); + + assert header.length == HEADER_LEN; + + byte[] data = new byte[message.length + header.length]; + + System.arraycopy(header, 0, data, 0, header.length); + System.arraycopy(message, 0, data, header.length, message.length); + + baseSend(data); + } finally { + sendLock.unlock(); + } + + } + + abstract void baseSend(byte[] data); + + abstract byte[] baseReceive(int count); +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/RequestError.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/RequestError.java new file mode 100644 index 00000000..dc6ff137 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/RequestError.java @@ -0,0 +1,21 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.transport; + +/** + * Request error. + */ +public class RequestError extends RuntimeException { + /** + * Request error. + * + * @param message error message + */ + public RequestError(String message) { + super(message); + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/SerialTransport.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/SerialTransport.java new file mode 100644 index 00000000..df172f85 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/SerialTransport.java @@ -0,0 +1,76 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.transport; + +import com.fazecast.jSerialComm.SerialPort; + +import static com.fazecast.jSerialComm.SerialPort.TIMEOUT_READ_BLOCKING; +import static com.fazecast.jSerialComm.SerialPort.TIMEOUT_WRITE_BLOCKING; + +/** + * Serial transport implementation. + */ +public final class SerialTransport extends FramedTransport { + private static final int READ_TIMEOUT = 500; + private static final int WRITE_TIMEOUT = 500; + private final SerialPort serial; + + /** + * Serial transport constructor. + * + * @param url Serial port URL + * @param baudrate Communication baud rate + */ + public SerialTransport(String url, int baudrate) { + super(); + + serial = SerialPort.getCommPort(url); + serial.setBaudRate(baudrate); + serial.setComPortTimeouts( + TIMEOUT_READ_BLOCKING | TIMEOUT_WRITE_BLOCKING, + READ_TIMEOUT, + WRITE_TIMEOUT + ); + + if (!serial.openPort()) { + throw new TransportError("Unable to open port \"" + url + "\""); + } + } + + @Override + public void baseSend(byte[] message) { + assert serial.isOpen(); + + int bytesSent = serial.writeBytes(message, message.length); + + if (bytesSent != message.length) { + throw new TransportError("Should send: " + message.length + ", but sent: " + bytesSent); + } + } + + @Override + public byte[] baseReceive(int count) { + assert serial.isOpen(); + + byte[] received = new byte[count]; + int bytesRead = serial.readBytes(received, count); + + if (bytesRead != count) { + throw new TransportError("Should read: " + count + ", but read: " + bytesRead); + } + + return received; + } + + @Override + public void close() { + if (serial.isOpen()) { + serial.closePort(); + } + } + +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TCPTransport.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TCPTransport.java new file mode 100644 index 00000000..cf189e91 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TCPTransport.java @@ -0,0 +1,89 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.transport; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * Implementation of the TCP transport. + */ +public final class TCPTransport extends FramedTransport { + private final Socket socket; + private final DataInputStream in; + private final DataOutputStream out; + + /** + * TCPTransport constructor. + * + * @param ip IP of the eRPC server + * @param port Port of the eRPC server + * @throws UnknownHostException + * @throws IOException + */ + public TCPTransport(String ip, int port) throws UnknownHostException, IOException { + socket = new Socket(ip, port); + out = new DataOutputStream(socket.getOutputStream()); + in = new DataInputStream(socket.getInputStream()); + } + + /** + * Create TCP transport. + * + * @param port TCP port + * @throws IOException TCP error + */ + public TCPTransport(int port) throws IOException { + try (ServerSocket serverSocket = new ServerSocket(port)) { + socket = serverSocket.accept(); + } + out = new DataOutputStream(socket.getOutputStream()); + in = new DataInputStream(socket.getInputStream()); + } + + /** + * Function closes all opened connections and streams. + */ + @Override + public void close() { + try { + in.close(); + out.close(); + socket.close(); + } catch (IOException e) { + throw new TransportError("Error closing TCP connection", e); + } + } + + @Override + public byte[] baseReceive(int count) { + byte[] buffer = new byte[count]; + try { + if (in.read(buffer, 0, count) != count) { + throw new TransportError("Error receiving TCP data."); + } + } catch (IOException e) { + throw new TransportError("Error receiving TCP.", e); + } + return buffer; + } + + @Override + public void baseSend(byte[] message) { + try { + out.write(message, 0, message.length); + out.flush(); + } catch (IOException e) { + throw new TransportError("Error sending TCP data", e); + } + + } +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/Transport.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/Transport.java new file mode 100644 index 00000000..5b5108d5 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/Transport.java @@ -0,0 +1,31 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.transport; + +/** + * Transport interface. + */ +public interface Transport { + /** + * Send data through transport layer. + * + * @param message data to be sent. + */ + void send(byte[] message); + + /** + * Receive data from transport layer. + * + * @return byte array + */ + byte[] receive(); + + /** + * Close transport layer. + */ + void close(); +} diff --git a/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TransportError.java b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TransportError.java new file mode 100644 index 00000000..0bb1c8b4 --- /dev/null +++ b/erpc_java/src/main/java/io/github/embeddedrpc/erpc/transport/TransportError.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.transport; + +/** + * Transport runtime exception. + */ +public class TransportError extends RuntimeException { + /** + * Transport error. + */ + public TransportError() { + super(); + } + + /** + * Transport error. + * + * @param message error message + */ + public TransportError(String message) { + super(message); + } + + /** + * Transport error. + * + * @param message error message + * @param cause error chain + */ + public TransportError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/BasicCodecTest.java b/erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/BasicCodecTest.java new file mode 100644 index 00000000..8ae514ae --- /dev/null +++ b/erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/BasicCodecTest.java @@ -0,0 +1,367 @@ +package io.github.embeddedrpc.erpc.codec; + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import java.util.Arrays; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Unit tests for BasicCodec. + */ +@SuppressWarnings("magicnumber") +class BasicCodecTest { + /** + * Rigorous Test. + */ + + @Test + void boolTest() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeBool(false); + codec.writeBool(true); + + codec.getBuffer().position(0); + + assertEquals(false, codec.readBool()); + assertEquals(true, codec.readBool()); + } + + @Test + void int8Test() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeInt8((byte) 42); + codec.writeInt8((byte) -42); + codec.writeUInt8((byte) 42); + + assertThrows(IllegalArgumentException.class, () -> { + codec.writeUInt8((byte) -42); + }); + assertThrows(IllegalArgumentException.class, () -> { + codec.writeUInt8((byte) 0xff); + }); + assertDoesNotThrow(() -> { + codec.writeUInt8((byte) 0); + }); + assertDoesNotThrow(() -> { + codec.readUInt8(); + }); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + assertEquals(42, codec.readInt8()); + assertEquals(-42, codec.readInt8()); + assertEquals(42, codec.readUInt8()); + } + + @Test + void int16Test() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeInt16((short) 42); + codec.writeInt16((short) -42); + codec.writeUInt16((short) 42); + + assertThrows(IllegalArgumentException.class, () -> { + codec.writeUInt16((short) -42); + }); + assertThrows(IllegalArgumentException.class, () -> { + codec.writeUInt16((short) 0xffff); + }); + assertDoesNotThrow(() -> { + codec.writeUInt16((short) 0); + }); + assertDoesNotThrow(() -> { + codec.readUInt16(); + }); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + assertEquals(42, codec.readInt16()); + assertEquals(-42, codec.readInt16()); + assertEquals(42, codec.readUInt16()); + } + + @Test + void int32Test() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeInt32(42); + codec.writeInt32(-42); + codec.writeUInt32(42); + + assertThrows(IllegalArgumentException.class, () -> { + codec.writeUInt32(-42); + }); + assertThrows(IllegalArgumentException.class, () -> { + codec.writeUInt32(0xffffffff1L); + }); + assertDoesNotThrow(() -> { + codec.writeUInt32(0); + }); + assertDoesNotThrow(() -> { + codec.readUInt32(); + }); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + assertEquals(42, codec.readInt32()); + assertEquals(-42, codec.readInt32()); + assertEquals(42, codec.readUInt32()); + } + + @Test + void int64Test() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeInt64(42); + codec.writeInt64(-42); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + assertEquals(42, codec.readInt64()); + assertEquals(-42, codec.readInt64()); + } + + @Test + void floatTest() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeFloat(42); + codec.writeFloat(-42); + codec.writeFloat(0.125F); + codec.writeFloat(-0.125F); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + assertEquals(42, codec.readFloat()); + assertEquals(-42, codec.readFloat()); + assertEquals(0.125F, codec.readFloat()); + assertEquals(-0.125F, codec.readFloat()); + } + + @Test + void doubleTest() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeDouble(42); + codec.writeDouble(-42); + codec.writeDouble(0.125F); + codec.writeDouble(-0.00000125F); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + assertEquals(42, codec.readDouble()); + assertEquals(-42, codec.readDouble()); + assertEquals(0.125F, codec.readDouble()); + assertEquals(-0.00000125F, codec.readDouble()); + } + + @Test + void stringTest() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeString("HelloWord"); + codec.writeString("+ěščřžýáíé="); + codec.writeString("Ḽơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįʈ"); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + assertEquals("HelloWord", codec.readString()); + assertEquals("+ěščřžýáíé=", codec.readString()); + assertEquals("Ḽơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįʈ", codec.readString()); + + } + + @Test + void longStringTest() { + // Testing data + String testString = "Ḽơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįʈḼơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċť" + + "ᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįḼơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįḼơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ," + + "ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįḼơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįḼơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐ" + + "ť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįḼơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłįḼơᶉëᶆ ȋṕšᶙṁ " + + "ḍỡḽǭᵳ ʂǐť ӓṁệẗ, ĉṓɲṩḙċťᶒțûɾ ấɖḯƥĭṩčįɳġ ḝłį"; + + // New codec + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeString(testString); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + + assertEquals(testString, codec.readString()); + + } + + @Test + void longBinaryTest() { + // Testing data + byte[] array = new byte[65536]; + Arrays.fill(array, (byte) 42); + + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeBinary(array); + codec.writeBinary(array); + codec.writeBinary(array); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + + assertArrayEquals(array, codec.readBinary()); + assertArrayEquals(array, codec.readBinary()); + assertArrayEquals(array, codec.readBinary()); + } + + @Test + void byteRepresentationTest() { + Codec codec = new BasicCodec(); + + // Push data to codec + codec.writeBool(true); + codec.writeBool(false); + + codec.writeInt8((byte) -42); + codec.writeInt8((byte) 42); + codec.writeUInt8((short) 42); + + codec.writeInt16((byte) -42); + codec.writeInt16((byte) 42); + codec.writeUInt16((short) 42); + + codec.writeInt32((byte) -42); + codec.writeInt32((byte) 42); + codec.writeUInt32((short) 42); + + codec.writeString("Ḽơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ"); + + // Get bytes length + int dataLength = codec.getBuffer().position(); + + // Reset buffer position + codec.getBuffer().position(0); + + // Read data from codec + byte[] array = new byte[dataLength]; + codec.getBuffer().get(array, 0, dataLength); + + // Assert equality (bytes string from Python implementation) + assertEquals("0100d62a2ad6ff2a002a00d6ffffff2a0000002a0000003d000000e1b8bcc6a1e1b689c3abe1b68620c88be1b995c5a1e" + + "1b699e1b98120e1b88de1bba1e1b8bdc7ade1b5b320ca82c790c5a520d393e1b981e1bb87e1ba97", + Utils.byteArrayToHex(array)); + } + + @Test + void fromBytesTest() { + String testString = "0100d62a2ad6ff2a002a00d6ffffff2a0000002a0000003d000000e1b8bcc6a1e1b689c3abe1b68620c88be1b9" + + "95c5a1e1b699e1b98120e1b88de1bba1e1b8bdc7ade1b5b320ca82c790c5a520d393e1b981e1bb87e1ba97"; + Codec codec = new BasicCodec(Utils.hexToByteArray(testString)); + + assertEquals(true, codec.readBool()); + assertEquals(false, codec.readBool()); + assertEquals(-42, codec.readInt8()); + assertEquals(42, codec.readInt8()); + assertEquals(42, codec.readUInt8()); + assertEquals(-42, codec.readInt16()); + assertEquals(42, codec.readInt16()); + assertEquals(42, codec.readUInt16()); + assertEquals(-42, codec.readInt32()); + assertEquals(42, codec.readInt32()); + assertEquals(42, codec.readUInt32()); + assertEquals("Ḽơᶉëᶆ ȋṕšᶙṁ ḍỡḽǭᵳ ʂǐť ӓṁệẗ", codec.readString()); + } + + @Test + void writeMessageTest() { + Codec codec = new BasicCodec(); + MessageInfo msgInfo = new MessageInfo(MessageType.kNotificationMessage, 1, 5, 4); + + codec.startWriteMessage(msgInfo); + + // Reset buffer position + codec.getBuffer().position(0); + + MessageInfo msgInfoRead = codec.startReadMessage(); + + // Assert equality + assertEquals(msgInfo, msgInfoRead); + } + + @Test + void readMessageTest() { + String testString = "020101012a000000"; + MessageInfo msgInfoExpected = new MessageInfo(MessageType.kReplyMessage, 1, 1, 42); + + Codec codec = new BasicCodec(Utils.hexToByteArray(testString)); + + MessageInfo msgInfo = codec.startReadMessage(); + + assertEquals(msgInfoExpected, msgInfo); + } + + @Test + void codecToArrayTest() { + Codec codec = new BasicCodec(); + + codec.writeInt32(1); + + byte[] array = codec.array(); + + assertEquals(4, array.length); + assertEquals(1, array[0]); + assertEquals(0, array[1]); + assertEquals(0, array[2]); + assertEquals(0, array[3]); + + codec.writeUInt32(0xFFFFFFFFL); + + array = codec.array(); + + assertEquals(8, array.length); + assertEquals(1, array[0]); + assertEquals(0, array[1]); + assertEquals(0, array[2]); + assertEquals(0, array[3]); + assertEquals((byte) 0xFF, array[4]); + assertEquals((byte) 0xFF, array[5]); + assertEquals((byte) 0xFF, array[6]); + assertEquals((byte) 0xFF, array[7]); + + } +} diff --git a/erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/CRC16Test.java b/erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/CRC16Test.java new file mode 100644 index 00000000..20288319 --- /dev/null +++ b/erpc_java/src/test/java/io/github/embeddedrpc/erpc/codec/CRC16Test.java @@ -0,0 +1,74 @@ +package io.github.embeddedrpc.erpc.codec; + +import io.github.embeddedrpc.erpc.auxiliary.Crc16; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for CRC16. + */ +@SuppressWarnings("magicnumber") +public class CRC16Test { + private final Crc16 crc = new Crc16(); + + @Test + void crc16ByteBufferTest() { + assertEquals(0x4547, crc.computeCRC16(Utils.hexToByteArray("5b108fe061377bb0844f6a469b7b2544"))); + assertEquals(0xf033, crc.computeCRC16(Utils.hexToByteArray("6ebe6f4b01a33686310102398daf883f"))); + assertEquals(0x60bc, crc.computeCRC16(Utils.hexToByteArray("82121c9510a01971366a71fc46c27eff"))); + assertEquals(0xd127, crc.computeCRC16(Utils.hexToByteArray("311275c4ce315456aea1a75993403be3"))); + assertEquals(0x2fba, crc.computeCRC16(Utils.hexToByteArray("4fd3abc6b911c737c66f750f55fc4216"))); + assertEquals(0x45a, crc.computeCRC16(Utils.hexToByteArray("5a63996ab77d2202f480687069ca8ffe"))); + assertEquals(0x4a0a, crc.computeCRC16(Utils.hexToByteArray("b8dbfee5a566214c0f1b39a4028d9b20"))); + assertEquals(0x9a37, crc.computeCRC16(Utils.hexToByteArray("6ba116397d22b71869581742e3886867"))); + assertEquals(0x8af4, crc.computeCRC16(Utils.hexToByteArray("00de0fad00cc885707a2b13ce999eb1c"))); + assertEquals(0x7a0, crc.computeCRC16(Utils.hexToByteArray("da61c52377ca5bb717de30f44df43cb3"))); + assertEquals(0x82fa, crc.computeCRC16(Utils.hexToByteArray("00396c95c8733faa47ee70aeaa123942"))); + assertEquals(0xde52, crc.computeCRC16(Utils.hexToByteArray("99ce4dbe8a0588c03f81a071b6df26e1"))); + assertEquals(0x3429, crc.computeCRC16(Utils.hexToByteArray("72f68bc19da85b9e077c46d8a190d497"))); + assertEquals(0x6e45, crc.computeCRC16(Utils.hexToByteArray("aa6ca4918b16fac5c69c463da851edb3"))); + assertEquals(0x5df, crc.computeCRC16(Utils.hexToByteArray("373610cb7d89a2c52089bb7cad7603ae"))); + assertEquals(0xb3d7, crc.computeCRC16(Utils.hexToByteArray("d47cdd4425e5e96b70f8ff0c15716433"))); + assertEquals(0x451, crc.computeCRC16(Utils.hexToByteArray("b8337e68949d675e71e27340a18d1d2b"))); + assertEquals(0x8e36, crc.computeCRC16(Utils.hexToByteArray("1fe2ae3bdb44afbe591d777ce9a0a352"))); + assertEquals(0xcd8c, crc.computeCRC16(Utils.hexToByteArray("eab6d63286db5d7b5d33fa3193ec1650"))); + assertEquals(0xa92c, crc.computeCRC16(Utils.hexToByteArray("14d39b146713049a646cb16e812fa04a"))); + assertEquals(0x492d, crc.computeCRC16(Utils.hexToByteArray("7b7e00e55ed3ec0dc12ad60ff9d5d2cf"))); + assertEquals(0x88ba, crc.computeCRC16(Utils.hexToByteArray("9f10125c276cdc518b4d61fe2ec7d5fa"))); + assertEquals(0x247a, crc.computeCRC16(Utils.hexToByteArray("a0a5763a92b232b886f95094f50c95b4"))); + assertEquals(0x751, crc.computeCRC16(Utils.hexToByteArray("1db2fa23acbf6c6bc60e6a4d8f1b6266"))); + assertEquals(0xa7ba, crc.computeCRC16(Utils.hexToByteArray("b7286f6879db13d871bc9b06aeee8932"))); + assertEquals(0x2082, crc.computeCRC16(Utils.hexToByteArray("e067284662792f25583655e547a07227"))); + assertEquals(0xa92c, crc.computeCRC16(Utils.hexToByteArray("2615f97b172ff6b8799f88afddd1e189"))); + assertEquals(0xfbb9, crc.computeCRC16(Utils.hexToByteArray("df70b5e237c110f452b1acc965140911"))); + assertEquals(0xaf5, crc.computeCRC16(Utils.hexToByteArray("d5f91e44cb9be394e5831d3d291eee7c"))); + assertEquals(0x9209, crc.computeCRC16(Utils.hexToByteArray("5e74de47e74fc901fb76e278f9abb541"))); + assertEquals(0x7a2e, crc.computeCRC16(Utils.hexToByteArray("416c54f49c8dcf093d72cc8a3aa195c9"))); + assertEquals(0xe915, crc.computeCRC16(Utils.hexToByteArray("d0593cb671d8899448f603863aca5c0b"))); + assertEquals(0xff91, crc.computeCRC16(Utils.hexToByteArray("a106b5858d9e5464eb01a388e4829f36"))); + assertEquals(0x6524, crc.computeCRC16(Utils.hexToByteArray("21705e23f29cb1465db3f410a887bf4f"))); + assertEquals(0xa82e, crc.computeCRC16(Utils.hexToByteArray("8d39ccf4c244963a29c6dd531f8861f9"))); + assertEquals(0x7765, crc.computeCRC16(Utils.hexToByteArray("8a31810b0c634ff15e5540a36b075504"))); + assertEquals(0x491, crc.computeCRC16(Utils.hexToByteArray("b48ac1deffbbc515f82508408470344a"))); + assertEquals(0x8435, crc.computeCRC16(Utils.hexToByteArray("265d6a6e206aa888190a512a9120f2d3"))); + assertEquals(0x2a56, crc.computeCRC16(Utils.hexToByteArray("514a168af0a8cd99145e0cab1f311707"))); + assertEquals(0x39f1, crc.computeCRC16(Utils.hexToByteArray("89cf0b02699b14c375b6c21fef58b572"))); + assertEquals(0x7e5d, crc.computeCRC16(Utils.hexToByteArray("7ea6196fe85f569065957e14206d8f75"))); + assertEquals(0x912a, crc.computeCRC16(Utils.hexToByteArray("fdd1e68dcfae80ae3dad3aefbe7ef158"))); + assertEquals(0x395e, crc.computeCRC16(Utils.hexToByteArray("4cf3ee7c96b9d3679295b2cb93a979bf"))); + assertEquals(0xea51, crc.computeCRC16(Utils.hexToByteArray("b6f3691f7401ed685f23ace4f7b3b3db"))); + assertEquals(0x1b39, crc.computeCRC16(Utils.hexToByteArray("0e86d611995e8a2ed6c4b0e0d97304a5"))); + assertEquals(0x530c, crc.computeCRC16(Utils.hexToByteArray("70dc6ed45f9410813dfd1600629a6080"))); + assertEquals(0xc2df, crc.computeCRC16(Utils.hexToByteArray("dc96ad1d88643f01df321e9a6fa43e0c"))); + assertEquals(0xd9e7, crc.computeCRC16(Utils.hexToByteArray("ab5cc581ff755a28aa91bc1a23272630"))); + assertEquals(0xf1de, crc.computeCRC16(Utils.hexToByteArray("24db03e36048be8da3b268fd7d7580f5"))); + assertEquals(0xf1ad, crc.computeCRC16(Utils.hexToByteArray("d66c1a23d5bf97808c662a595a474125"))); + } + + @Test + void crc16StringTest() { + assertEquals(0x89ac, crc.computeCRC16("123456789".getBytes())); + } +} diff --git a/erpc_python/erpc/erpc_version.py b/erpc_python/erpc/erpc_version.py index e32900af..3efec812 100644 --- a/erpc_python/erpc/erpc_version.py +++ b/erpc_python/erpc/erpc_version.py @@ -6,4 +6,4 @@ # SPDX-License-Identifier: BSD-3-Clause # Should be same as in erpc_version.h -ERPC_VERSION = "1.11.0" +ERPC_VERSION = "1.12.0" diff --git a/erpc_python/erpc/transport.py b/erpc_python/erpc/transport.py index 725a0abb..cc3b33d2 100644 --- a/erpc_python/erpc/transport.py +++ b/erpc_python/erpc/transport.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2015-2016 Freescale Semiconductor, Inc. -# Copyright 2016-2022 NXP +# Copyright 2016-2023 NXP # Copyright 2022 ACRIOS Systems s.r.o. # All rights reserved. # @@ -48,7 +48,7 @@ def receive(self): class FramedTransport(Transport): - HEADER_LEN = 4 + HEADER_LEN = 6 def __init__(self): super(FramedTransport, self).__init__() @@ -70,9 +70,12 @@ def send(self, message): try: self._sendLock.acquire() - crc = self._Crc16.computeCRC16(message) + crcBody = self._Crc16.computeCRC16(message) + messageLength = len(message) + crcHeader = self._Crc16.computeCRC16(bytearray(struct.pack(' - python.exe ..\bin\txt_to_c.py --output .\c_coders.cpp ..\src\templates\c_coders.template -python.exe ..\bin\txt_to_c.py --output .\c_client_source.cpp ..\src\templates\c_client_source.template + python.exe ..\bin\txt_to_c.py --output .\cpp_coders.cpp ..\src\templates\cpp_coders.template python.exe ..\bin\txt_to_c.py --output .\c_common_header.cpp ..\src\templates\c_common_header.template +python.exe ..\bin\txt_to_c.py --output .\cpp_interface_header.cpp ..\src\templates\cpp_interface_header.template +python.exe ..\bin\txt_to_c.py --output .\cpp_interface_source.cpp ..\src\templates\cpp_interface_source.template +python.exe ..\bin\txt_to_c.py --output .\cpp_client_header.cpp ..\src\templates\cpp_client_header.template +python.exe ..\bin\txt_to_c.py --output .\cpp_client_source.cpp ..\src\templates\cpp_client_source.template +python.exe ..\bin\txt_to_c.py --output .\cpp_server_source.cpp ..\src\templates\cpp_server_source.template +python.exe ..\bin\txt_to_c.py --output .\cpp_server_header.cpp ..\src\templates\cpp_server_header.template +python.exe ..\bin\txt_to_c.py --output .\c_client_header.cpp ..\src\templates\c_client_header.template +python.exe ..\bin\txt_to_c.py --output .\c_client_source.cpp ..\src\templates\c_client_source.template python.exe ..\bin\txt_to_c.py --output .\c_server_source.cpp ..\src\templates\c_server_source.template python.exe ..\bin\txt_to_c.py --output .\c_server_header.cpp ..\src\templates\c_server_header.template -python.exe ..\bin\txt_to_c.py --output .\c_common_functions.cpp ..\src\templates\c_common_functions.template +python.exe ..\bin\txt_to_c.py --output .\cpp_common_functions.cpp ..\src\templates\cpp_common_functions.template python.exe ..\bin\txt_to_c.py --output .\c_crc.cpp ..\src\templates\c_crc.template python.exe ..\bin\txt_to_c.py --output .\py_client.cpp ..\src\templates\py_client.template python.exe ..\bin\txt_to_c.py --output .\py_coders.cpp ..\src\templates\py_coders.template @@ -110,7 +117,14 @@ python.exe ..\bin\txt_to_c.py --output .\py_common.cpp ..\src\templates\py_commo python.exe ..\bin\txt_to_c.py --output .\py_init.cpp ..\src\templates\py_init.template python.exe ..\bin\txt_to_c.py --output .\py_interface.cpp ..\src\templates\py_interface.template python.exe ..\bin\txt_to_c.py --output .\py_server.cpp ..\src\templates\py_server.template -python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_global_init.template +python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_global_init.template +python.exe ..\bin\txt_to_c.py --output .\java_coders.cpp ..\src\templates\java_coders.template +python.exe ..\bin\txt_to_c.py --output .\java_enum.cpp ..\src\templates\java_enum.template +python.exe ..\bin\txt_to_c.py --output .\java_interface.cpp ..\src\templates\java_interface.template +python.exe ..\bin\txt_to_c.py --output .\java_struct.cpp ..\src\templates\java_struct.template +python.exe ..\bin\txt_to_c.py --output .\java_server.cpp ..\src\templates\java_server.template +python.exe ..\bin\txt_to_c.py --output .\java_client.cpp ..\src\templates\java_client.template +python.exe ..\bin\txt_to_c.py --output .\java_const.cpp ..\src\templates\java_const.template @@ -137,12 +151,19 @@ python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_ %(AdditionalLibraryDirectories) - python.exe ..\bin\txt_to_c.py --output .\c_coders.cpp ..\src\templates\c_coders.template -python.exe ..\bin\txt_to_c.py --output .\c_client_source.cpp ..\src\templates\c_client_source.template + python.exe ..\bin\txt_to_c.py --output .\cpp_coders.cpp ..\src\templates\cpp_coders.template python.exe ..\bin\txt_to_c.py --output .\c_common_header.cpp ..\src\templates\c_common_header.template +python.exe ..\bin\txt_to_c.py --output .\cpp_interface_header.cpp ..\src\templates\cpp_interface_header.template +python.exe ..\bin\txt_to_c.py --output .\cpp_interface_source.cpp ..\src\templates\cpp_interface_source.template +python.exe ..\bin\txt_to_c.py --output .\cpp_client_header.cpp ..\src\templates\cpp_client_header.template +python.exe ..\bin\txt_to_c.py --output .\cpp_client_source.cpp ..\src\templates\cpp_client_source.template +python.exe ..\bin\txt_to_c.py --output .\cpp_server_source.cpp ..\src\templates\cpp_server_source.template +python.exe ..\bin\txt_to_c.py --output .\cpp_server_header.cpp ..\src\templates\cpp_server_header.template +python.exe ..\bin\txt_to_c.py --output .\c_client_header.cpp ..\src\templates\c_client_header.template +python.exe ..\bin\txt_to_c.py --output .\c_client_source.cpp ..\src\templates\c_client_source.template python.exe ..\bin\txt_to_c.py --output .\c_server_source.cpp ..\src\templates\c_server_source.template python.exe ..\bin\txt_to_c.py --output .\c_server_header.cpp ..\src\templates\c_server_header.template -python.exe ..\bin\txt_to_c.py --output .\c_common_functions.cpp ..\src\templates\c_common_functions.template +python.exe ..\bin\txt_to_c.py --output .\cpp_common_functions.cpp ..\src\templates\cpp_common_functions.template python.exe ..\bin\txt_to_c.py --output .\c_crc.cpp ..\src\templates\c_crc.template python.exe ..\bin\txt_to_c.py --output .\py_client.cpp ..\src\templates\py_client.template python.exe ..\bin\txt_to_c.py --output .\py_coders.cpp ..\src\templates\py_coders.template @@ -150,7 +171,14 @@ python.exe ..\bin\txt_to_c.py --output .\py_common.cpp ..\src\templates\py_commo python.exe ..\bin\txt_to_c.py --output .\py_init.cpp ..\src\templates\py_init.template python.exe ..\bin\txt_to_c.py --output .\py_interface.cpp ..\src\templates\py_interface.template python.exe ..\bin\txt_to_c.py --output .\py_server.cpp ..\src\templates\py_server.template -python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_global_init.template +python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_global_init.template +python.exe ..\bin\txt_to_c.py --output .\java_coders.cpp ..\src\templates\java_coders.template +python.exe ..\bin\txt_to_c.py --output .\java_enum.cpp ..\src\templates\java_enum.template +python.exe ..\bin\txt_to_c.py --output .\java_interface.cpp ..\src\templates\java_interface.template +python.exe ..\bin\txt_to_c.py --output .\java_struct.cpp ..\src\templates\java_struct.template +python.exe ..\bin\txt_to_c.py --output .\java_server.cpp ..\src\templates\java_server.template +python.exe ..\bin\txt_to_c.py --output .\java_client.cpp ..\src\templates\java_client.template +python.exe ..\bin\txt_to_c.py --output .\java_const.cpp ..\src\templates\java_const.template $(ProjectDir)\%(Filename).flex.cpp @@ -166,6 +194,7 @@ python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_ + @@ -211,6 +240,7 @@ python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_ + @@ -229,17 +259,31 @@ python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_ - - + + + + + + + + + - + 4005;4244;%(DisableSpecificWarnings) + + + + + + + @@ -269,4 +313,4 @@ python.exe ..\bin\txt_to_c.py --output .\py_global_init.cpp ..\src\templates\py_ - + \ No newline at end of file diff --git a/erpcgen/VisualStudio_v14/erpcgen.vcxproj.filters b/erpcgen/VisualStudio_v14/erpcgen.vcxproj.filters index 29c6416c..b6824c9b 100644 --- a/erpcgen/VisualStudio_v14/erpcgen.vcxproj.filters +++ b/erpcgen/VisualStudio_v14/erpcgen.vcxproj.filters @@ -156,6 +156,9 @@ Header Files + + Header Files + @@ -164,13 +167,34 @@ Source Files\cpptemplate - + Source Files - + Source Files - + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + Source Files @@ -254,7 +278,7 @@ Source Files - + Source Files @@ -272,6 +296,27 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -282,4 +327,4 @@ - \ No newline at end of file + diff --git a/erpcgen/VisualStudio_v14/erpcgen.vcxproj.user b/erpcgen/VisualStudio_v14/erpcgen.vcxproj.user index a375ae35..6d231c5b 100644 --- a/erpcgen/VisualStudio_v14/erpcgen.vcxproj.user +++ b/erpcgen/VisualStudio_v14/erpcgen.vcxproj.user @@ -1,4 +1,7 @@  - + + -g java -p "com.nxp.erpc.app" -v .\erpcgen_mockup.erpc + WindowsLocalDebugger + \ No newline at end of file diff --git a/erpcgen/src/AstNode.cpp b/erpcgen/src/AstNode.cpp index a04e7012..05b868b7 100644 --- a/erpcgen/src/AstNode.cpp +++ b/erpcgen/src/AstNode.cpp @@ -22,9 +22,7 @@ using namespace std; // Code //////////////////////////////////////////////////////////////////////////////// -AstNode::AstNode(const AstNode &other) -: m_token(other.m_token) -, m_parent(other.m_parent) +AstNode::AstNode(const AstNode &other) : m_token(other.m_token), m_parent(other.m_parent) { // Clone children. for (auto it : other.m_children) @@ -220,7 +218,8 @@ string AstNode::getDescription() const case TOK_ARRAY: case TOK_UNION_CASE: break; - default: { + default: + { output += " " + valToString + " "; if (valToString.size() == 1) { diff --git a/erpcgen/src/AstNode.hpp b/erpcgen/src/AstNode.hpp index a2ed1878..e748e854 100644 --- a/erpcgen/src/AstNode.hpp +++ b/erpcgen/src/AstNode.hpp @@ -53,11 +53,7 @@ class AstNode * @see AstNode::AstNode(Token * token, AstNode * parent) * @see AstNode::AstNode(const AstNode & other) */ - explicit AstNode(const Token &token) - : m_token(token) - , m_parent(nullptr) - { - } + explicit AstNode(const Token &token) : m_token(token), m_parent(nullptr) {} /*! * @brief This function is constructor of AstNode class. @@ -71,11 +67,7 @@ class AstNode * @see AstNode::AstNode(Token * token) * @see AstNode::AstNode(const AstNode & other) */ - AstNode(Token &token, AstNode *parent) - : m_token(token) - , m_parent(parent) - { - } + AstNode(Token &token, AstNode *parent) : m_token(token), m_parent(parent) {} /*! * @brief This function is copy constructor of AstNode class. @@ -401,11 +393,7 @@ class AstPrinter * * @param[in] root Pointer to root node. */ - explicit AstPrinter(AstNode *root) - : m_root(root) - , m_depth(0) - { - } + explicit AstPrinter(AstNode *root) : m_root(root), m_depth(0) {} /*! * @brief This function call for dispatch function. diff --git a/erpcgen/src/AstWalker.hpp b/erpcgen/src/AstWalker.hpp index 4f4a7ddb..459225b5 100644 --- a/erpcgen/src/AstWalker.hpp +++ b/erpcgen/src/AstWalker.hpp @@ -53,10 +53,7 @@ class AstWalker * * @param[in] inputFile Parsed file name. */ - explicit AstWalker(const std::string &inputFile) - : m_fileName(inputFile) - { - } + explicit AstWalker(const std::string &inputFile) : m_fileName(inputFile) {} /*! * @brief destructor diff --git a/erpcgen/src/CGenerator.cpp b/erpcgen/src/CGenerator.cpp index b3fe5808..f891a06a 100644 --- a/erpcgen/src/CGenerator.cpp +++ b/erpcgen/src/CGenerator.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2020 NXP + * Copyright 2016-2023 NXP * All rights reserved. * * @@ -15,6 +15,7 @@ #include "format_string.hpp" #include +#include #include #include @@ -31,11 +32,19 @@ static const char *const kIdentifierChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHI // Templates strings converted from text files by txt_to_c.py. extern const char *const kCCommonHeader; -extern const char *const kCServerHeader; +extern const char *const kCppCommonHeader; +extern const char *const kCppInterfaceHeader; +extern const char *const kCppInterfaceSource; +extern const char *const kCppClientHeader; +extern const char *const kCppClientSource; +extern const char *const kCppServerHeader; +extern const char *const kCppServerSource; +extern const char *const kCppCoders; +extern const char *const kCppCommonFunctions; +extern const char *const kCClientHeader; extern const char *const kCClientSource; +extern const char *const kCServerHeader; extern const char *const kCServerSource; -extern const char *const kCCoders; -extern const char *const kCCommonFunctions; extern const char *const kCCrc; // number which makes list temporary variables unique. @@ -44,8 +53,7 @@ static uint8_t listCounter = 0; //////////////////////////////////////////////////////////////////////////////// // Code //////////////////////////////////////////////////////////////////////////////// -CGenerator::CGenerator(InterfaceDefinition *def) -: Generator(def, kC) +CGenerator::CGenerator(InterfaceDefinition *def) : Generator(def, generator_type_t::kC) { /* Set copyright rules. */ if (m_def->hasProgramSymbol()) @@ -70,81 +78,138 @@ CGenerator::CGenerator(InterfaceDefinition *def) void CGenerator::generateOutputFiles(const string &fileName) { - generateClientSourceFile(fileName); + generateCommonCHeaderFiles(fileName); + generateCommonCppHeaderFiles(fileName); + + generateInterfaceCppHeaderFile(fileName); + generateInterfaceCppSourceFile(fileName); + + generateClientCppHeaderFile(fileName); + generateClientCppSourceFile(fileName); - generateServerHeaderFile(fileName); - generateServerSourceFile(fileName); + generateServerCppHeaderFile(fileName); + generateServerCppSourceFile(fileName); - generateCommonHeaderFiles(fileName); + generateClientCHeaderFile(fileName); + generateClientCSourceFile(fileName); + + generateServerCHeaderFile(fileName); + generateServerCSourceFile(fileName); } -void CGenerator::generateTypesHeaderFile() +void CGenerator::generateCommonCHeaderFiles(string fileName) { - string typesHeaderFileName = m_templateData["commonTypesFile"]->getvalue(); + fileName += "_common.h"; + m_templateData["commonGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["commonCHeaderName"] = fileName; + m_templateData["cCommonHeaderFile"] = true; + generateOutputFile(fileName, "c_common_header", m_templateData, kCCommonHeader); +} - m_templateData["commonGuardMacro"] = generateIncludeGuardName(typesHeaderFileName); - m_templateData["genCommonTypesFile"] = true; - m_templateData["commonTypesFile"] = ""; +void CGenerator::generateCommonCppHeaderFiles(string fileName) +{ + fileName += "_common.hpp"; + m_templateData["commonGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["commonCppHeaderName"] = fileName; + m_templateData["cCommonHeaderFile"] = false; + generateOutputFile(fileName, "c_common_header", m_templateData, kCCommonHeader); +} - generateOutputFile(typesHeaderFileName, "c_common_header", m_templateData, kCCommonHeader); +void CGenerator::generateInterfaceCppHeaderFile(string fileName) +{ + fileName += "_interface.hpp"; + m_templateData["interfaceCppGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["interfaceCppHeaderName"] = fileName; + generateOutputFile(fileName, "cpp_interface_header", m_templateData, kCppInterfaceHeader); } -void CGenerator::generateCommonHeaderFiles(const string &fileName) +void CGenerator::generateInterfaceCppSourceFile(string fileName) { - m_templateData["commonGuardMacro"] = generateIncludeGuardName(fileName + ".h"); - m_templateData["genCommonTypesFile"] = false; + fileName += "_interface.cpp"; + m_templateData["interfaceCppSourceName"] = fileName; + generateOutputFile(fileName, "cpp_interface_source", m_templateData, kCppInterfaceSource); +} - generateOutputFile(fileName + ".h", "c_common_header", m_templateData, kCCommonHeader); +void CGenerator::generateClientCppHeaderFile(string fileName) +{ + fileName += "_client.hpp"; + m_templateData["clientCppGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["clientCppHeaderName"] = fileName; + generateOutputFile(fileName, "cpp_client_header", m_templateData, kCppClientHeader); } -void CGenerator::generateClientSourceFile(string fileName) +void CGenerator::generateClientCppSourceFile(string fileName) { - m_templateData["source"] = "client"; fileName += "_client.cpp"; - m_templateData["clientSourceName"] = fileName; + m_templateData["clientCppSourceName"] = fileName; + + generateOutputFile(fileName, "cpp_client_source", m_templateData, kCppClientSource); +} - // TODO: temporary workaround for tests - m_templateData["unitTest"] = (fileName.compare("test_unit_test_common_client.cpp") == 0 ? false : true); +void CGenerator::generateServerCppHeaderFile(string fileName) +{ + fileName += "_server.hpp"; + m_templateData["serverCppGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["serverCppHeaderName"] = fileName; + generateOutputFile(fileName, "cpp_server_header", m_templateData, kCppServerHeader); +} + +void CGenerator::generateServerCppSourceFile(string fileName) +{ + fileName += "_server.cpp"; + m_templateData["serverCppSourceName"] = fileName; + + generateOutputFile(fileName, "cpp_server_source", m_templateData, kCppServerSource); +} + +void CGenerator::generateClientCHeaderFile(string fileName) +{ + fileName = "c_" + fileName + "_client.h"; + m_templateData["clientCGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["clientCHeaderName"] = fileName; + generateOutputFile(fileName, "c_client_header", m_templateData, kCClientHeader); +} + +void CGenerator::generateClientCSourceFile(string fileName) +{ + fileName = "c_" + fileName + "_client.cpp"; + m_templateData["clientCSourceName"] = fileName; generateOutputFile(fileName, "c_client_source", m_templateData, kCClientSource); } -void CGenerator::generateServerHeaderFile(string fileName) +void CGenerator::generateServerCHeaderFile(string fileName) { - fileName += "_server.h"; - m_templateData["serverGuardMacro"] = generateIncludeGuardName(fileName); - m_templateData["serverHeaderName"] = fileName; + fileName = "c_" + fileName + "_server.h"; + m_templateData["serverCGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["serverCHeaderName"] = fileName; generateOutputFile(fileName, "c_server_header", m_templateData, kCServerHeader); } -void CGenerator::generateServerSourceFile(string fileName) +void CGenerator::generateServerCSourceFile(string fileName) { - m_templateData["source"] = "server"; - fileName += "_server.cpp"; - m_templateData["serverSourceName"] = fileName; - - // TODO: temporary workaround for tests - m_templateData["unitTest"] = (fileName.compare("test_unit_test_common_server.cpp") == 0 ? false : true); + fileName = "c_" + fileName + "_server.cpp"; + m_templateData["serverCSourceName"] = fileName; generateOutputFile(fileName, "c_server_source", m_templateData, kCServerSource); } void CGenerator::generateCrcFile() { - string filenName = "erpc_crc16.hpp"; - m_templateData["crcGuardMacro"] = generateIncludeGuardName(filenName); - m_templateData["crcHeaderName"] = filenName; - generateOutputFile(filenName, "c_crc", m_templateData, kCCrc); + string fileName = "erpc_crc16.hpp"; + m_templateData["crcGuardMacro"] = generateIncludeGuardName(fileName); + m_templateData["crcHeaderName"] = fileName; + generateOutputFile(fileName, "c_crc", m_templateData, kCCrc); } void CGenerator::parseSubtemplates() { - string templateName = "c_coders"; + string templateName = "cpp_coders"; try { - parse(kCCoders, m_templateData); - templateName = "c_common_functions"; - parse(kCCommonFunctions, m_templateData); + parse(kCppCoders, m_templateData); + templateName = "cpp_common_functions"; + parse(kCppCommonFunctions, m_templateData); } catch (TemplateException &e) { @@ -166,19 +231,22 @@ DataType *CGenerator::findChildDataType(set &dataTypes, DataType *da switch (dataType->getDataType()) { - case DataType::kAliasType: { + case DataType::data_type_t::kAliasType: + { AliasType *aliasType = dynamic_cast(dataType); assert(aliasType); aliasType->setElementType(findChildDataType(dataTypes, aliasType->getElementType())); break; } - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { ArrayType *arrayType = dynamic_cast(dataType); assert(arrayType); arrayType->setElementType(findChildDataType(dataTypes, arrayType->getElementType())); break; } - case DataType::kBuiltinType: { + case DataType::data_type_t::kBuiltinType: + { if (dataType->isBinary()) { // check if binary data type was replaced with structure wrapper @@ -209,7 +277,8 @@ DataType *CGenerator::findChildDataType(set &dataTypes, DataType *da dataTypes.insert(dataType); break; } - case DataType::kFunctionType: { + case DataType::data_type_t::kFunctionType: + { FunctionType *funcType = dynamic_cast(dataType); assert(funcType); @@ -232,7 +301,8 @@ DataType *CGenerator::findChildDataType(set &dataTypes, DataType *da } break; } - case DataType::kListType: { + case DataType::data_type_t::kListType: + { // The only child node of a list node is the element type. ListType *listType = dynamic_cast(dataType); DataType *trueContainerDataType = listType->getTrueContainerDataType(); @@ -324,7 +394,8 @@ DataType *CGenerator::findChildDataType(set &dataTypes, DataType *da break; } } - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *structType = dynamic_cast(dataType); assert(structType); @@ -349,7 +420,8 @@ DataType *CGenerator::findChildDataType(set &dataTypes, DataType *da } break; } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { // Keil need extra pragma option when unions are used. m_templateData["usedUnionType"] = true; UnionType *currentUnion = dynamic_cast(dataType); @@ -363,7 +435,8 @@ DataType *CGenerator::findChildDataType(set &dataTypes, DataType *da } break; } - default: { + default: + { break; } } @@ -373,7 +446,7 @@ DataType *CGenerator::findChildDataType(set &dataTypes, DataType *da void CGenerator::transformAliases() { - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kAliasType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kAliasType)) { AliasType *aliasType = dynamic_cast(it); assert(aliasType); @@ -414,7 +487,7 @@ void CGenerator::generate() } /* Generate file with shim code version. */ m_templateData["versionGuardMacro"] = - generateIncludeGuardName(format_string("erpc_generated_shim_code_crc_%d", m_idlCrc16).c_str()); + generateIncludeGuardName(format_string("erpc_generated_shim_code_crc_%d", m_idlCrc16)); m_templateData["generateInfraErrorChecks"] = generateInfraErrorChecks; m_templateData["generateAllocErrorChecks"] = generateAllocErrorChecks; @@ -426,7 +499,6 @@ void CGenerator::generate() m_templateData["structs"] = empty; m_templateData["unions"] = empty; m_templateData["consts"] = empty; - m_templateData["functions"] = empty; m_templateData["nonExternalStructUnion"] = false; @@ -434,10 +506,10 @@ void CGenerator::generate() m_templateData["usedUnionType"] = false; /* Set directions constants*/ - m_templateData["InDirection"] = getDirection(kInDirection); - m_templateData["OutDirection"] = getDirection(kOutDirection); - m_templateData["InoutDirection"] = getDirection(kInoutDirection); - m_templateData["ReturnDirection"] = getDirection(kReturn); + m_templateData["InDirection"] = getDirection(param_direction_t::kInDirection); + m_templateData["OutDirection"] = getDirection(param_direction_t::kOutDirection); + m_templateData["InoutDirection"] = getDirection(param_direction_t::kInoutDirection); + m_templateData["ReturnDirection"] = getDirection(param_direction_t::kReturn); parseSubtemplates(); @@ -448,21 +520,14 @@ void CGenerator::generate() } // check if structure/function parameters annotations are valid. - for (Symbol *symbol : getDataTypesFromSymbolScope(m_globals, DataType::kFunctionType)) - { - FunctionType *functionType = dynamic_cast(symbol); - assert(functionType); - scanStructForAnnotations(&functionType->getParameters(), true); - } - - for (Symbol *symbol : getDataTypesFromSymbolScope(m_globals, DataType::kStructType)) + for (Symbol *symbol : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kStructType)) { StructType *structType = dynamic_cast(symbol); assert(structType); scanStructForAnnotations(structType, false); } - for (Symbol *symbol : m_globals->getSymbolsOfType(Symbol::kInterfaceSymbol)) + for (Symbol *symbol : m_globals->getSymbolsOfType(Symbol::symbol_type_t::kInterfaceSymbol)) { Interface *interface = dynamic_cast(symbol); assert(interface); @@ -470,6 +535,11 @@ void CGenerator::generate() { scanStructForAnnotations(&function->getParameters(), true); } + + for (FunctionType *functionType : interface->getFunctionTypes()) + { + scanStructForAnnotations(&functionType->getParameters(), true); + } } // transform alias data types @@ -489,15 +559,20 @@ void CGenerator::generate() // for common header, only C specific makeSymbolsDeclarationTemplateData(); - // check if types header annotation is used - if (m_def->hasProgramSymbol()) - { - m_templateData["commonTypesFile"] = getAnnStringValue(program, TYPES_HEADER_ANNOTATION); - } - else + data_list interfacesFilesList; + string commonFilesFilename; + for (Group *group : m_groups) { - m_templateData["commonTypesFile"] = ""; + commonFilesFilename = getGroupCommonFileName(group); + for (auto iface : group->getInterfaces()) + { + data_map interfaceFile; + interfaceFile["interfaceName"] = iface->getName(); + interfaceFile["interfaceCommonFileName"] = commonFilesFilename; + interfacesFilesList.push_back(interfaceFile); + } } + m_templateData["interfacesFiles"] = interfacesFilesList; for (Group *group : m_groups) { @@ -506,24 +581,17 @@ void CGenerator::generate() groupTemplate["includes"] = makeGroupIncludesTemplateData(group); groupTemplate["symbolsMap"] = makeGroupSymbolsTemplateData(group); groupTemplate["interfaces"] = makeGroupInterfacesTemplateData(group); - groupTemplate["callbacks"] = makeGroupCallbacksTemplateData(group); group->setTemplate(groupTemplate); generateGroupOutputFiles(group); } - - // generate types header if used - if (!m_templateData["commonTypesFile"]->getvalue().empty()) - { - generateTypesHeaderFile(); - } } void CGenerator::makeConstTemplateData() { Log::info("Constant globals:\n"); data_list consts; - for (auto it : m_globals->getSymbolsOfType(Symbol::kConstSymbol)) + for (auto it : m_globals->getSymbolsOfType(Symbol::symbol_type_t::kConstSymbol)) { ConstType *constVar = dynamic_cast(it); assert(constVar); @@ -537,7 +605,7 @@ void CGenerator::makeConstTemplateData() if (nullptr == constVarValue) { throw semantic_error( - format_string("line %d: Const pointing to null Value object.", constVar->getLastLine()).c_str()); + format_string("line %d: Const pointing to null Value object.", constVar->getLastLine())); } /* Use char[] for constants. */ @@ -558,8 +626,7 @@ void CGenerator::makeConstTemplateData() if (constVarValue->getType() != kIntegerValue) { throw semantic_error(format_string("line %d: Const enum pointing to non-integer Value object.", - constVar->getLastLine()) - .c_str()); + constVar->getLastLine())); } EnumType *constEnum = dynamic_cast(constVarType); @@ -576,9 +643,8 @@ void CGenerator::makeConstTemplateData() if (value.compare("") == 0) { value = "(" + constVarType->getName() + ") " + constVarValue->toString(); - Log::warning(format_string("Enum value '%s' is not pointing to any '%s' variable \n", - constVarValue->toString().c_str(), constVarType->getName().c_str()) - .c_str()); + Log::warning("Enum value '%s' is not pointing to any '%s' variable \n", + constVarValue->toString().c_str(), constVarType->getName().c_str()); } } else @@ -605,7 +671,7 @@ void CGenerator::makeEnumsTemplateData() Log::info("Enums:\n"); data_list enums; int n = 0; - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kEnumType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kEnumType)) { EnumType *enumType = dynamic_cast(it); assert(enumType); @@ -661,11 +727,11 @@ void CGenerator::makeAliasesTemplateData() int n = 0; // All existing type declarations - datatype_vector_t aliasTypeVector = getDataTypesFromSymbolScope(m_globals, DataType::kAliasType); + datatype_vector_t aliasTypeVector = getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kAliasType); /* type definitions of structures */ int i = 0; - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kStructType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kStructType)) { StructType *structType = dynamic_cast(it); assert(structType); @@ -677,7 +743,7 @@ void CGenerator::makeAliasesTemplateData() } /* type definitions of non-encapsulated unions */ - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kUnionType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kUnionType)) { UnionType *unionType = dynamic_cast(it); assert(unionType); @@ -688,81 +754,6 @@ void CGenerator::makeAliasesTemplateData() } } - /* type definitions of functions and table of functions */ - data_list functions; - for (auto functionTypeSymbol : getDataTypesFromSymbolScope(m_globals, DataType::kFunctionType)) - { - FunctionType *functionType = dynamic_cast(functionTypeSymbol); - assert(functionType); - data_map functionInfo; - - // aware of external function definitions - if (!findAnnotation(functionType, EXTERNAL_ANNOTATION)) - { - AliasType *a = new AliasType(getFunctionPrototype(nullptr, functionType), functionType); - a->setMlComment(functionType->getMlComment()); - a->setIlComment(functionType->getIlComment()); - - /* Function type definition need be inserted after all parameters types definitions. */ - DataType *callbackParamType = functionType->getReturnStructMemberType()->getDataType(); - for (StructMember *callbackParam : functionType->getParameters().getMembers()) - { - DataType *callbackParamDataType = callbackParam->getDataType(); - if (!callbackParamType || callbackParamDataType->getFirstLine() > callbackParamType->getFirstLine()) - { - callbackParamType = callbackParamDataType; - } - } - if (!callbackParamType || !callbackParamType->isAlias()) - { - /* order isn't important */ - aliasTypeVector.insert(aliasTypeVector.begin() + i++, a); - } - else - { - /* skip structure, unions and functions type definitions */ - for (unsigned int aliasTypesIt = i; aliasTypesIt < aliasTypeVector.size(); ++aliasTypesIt) - { - if (callbackParamType == aliasTypeVector[aliasTypesIt]) - { - // Add aliases in IDL declaration order. - unsigned int nextIt = aliasTypesIt + 1; - while (nextIt < aliasTypeVector.size()) - { - AliasType *nextAlias = dynamic_cast(aliasTypeVector[nextIt]); - assert(nextAlias); - if (nextAlias->getElementType()->isFunction()) - { - ++nextIt; - } - else - { - break; - } - } - - aliasTypeVector.insert(aliasTypeVector.begin() + nextIt, a); - break; - } - } - } - } - - /* Table template data. */ - data_list callbacks; - for (Function *fun : functionType->getCallbackFuns()) - { - data_map callbacksInfo; - callbacksInfo["name"] = fun->getName(); - callbacks.push_back(callbacksInfo); - } - functionInfo["callbacks"] = callbacks; - /* Function type name. */ - functionInfo["name"] = functionType->getName(); - functions.push_back(functionInfo); - } - m_templateData["functions"] = functions; - for (auto it : aliasTypeVector) { AliasType *aliasType = dynamic_cast(it); @@ -812,7 +803,8 @@ void CGenerator::makeAliasesTemplateData() aliasInfo["unnamedName"] = getOutputName(aliasType); switch (elementDataType->getDataType()) { - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *structType = dynamic_cast(elementDataType); assert(structType); aliasInfo["unnamed"] = getStructDefinitionTemplateData( @@ -820,7 +812,8 @@ void CGenerator::makeAliasesTemplateData() aliasInfo["unnamedType"] = "struct"; break; } - case DataType::kEnumType: { + case DataType::data_type_t::kEnumType: + { EnumType *enumType = dynamic_cast(elementDataType); assert(enumType); aliasInfo["unnamed"] = getEnumTemplateData(enumType); @@ -840,7 +833,7 @@ void CGenerator::makeAliasesTemplateData() AliasType *CGenerator::getAliasType(DataType *dataType) { - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kAliasType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kAliasType)) { AliasType *aliasType = dynamic_cast(it); assert(aliasType); @@ -926,7 +919,7 @@ data_map CGenerator::makeGroupSymbolsTemplateData(Group *group) for (Symbol *symbol : group->getSymbols()) { data_map info; - const set<_param_direction> dirs = group->getSymbolDirections(symbol); + const set dirs = group->getSymbolDirections(symbol); if (dirs.size()) { if (symbol->isDatatypeSymbol()) @@ -1016,43 +1009,6 @@ data_map CGenerator::makeGroupSymbolsTemplateData(Group *group) return symbolsTemplate; } -data_list CGenerator::makeGroupCallbacksTemplateData(Group *group) -{ - data_list functionTypes; - std::map functionTypeMap; - - // need go trough functions instead of group symbols. - for (Interface *interface : group->getInterfaces()) - { - for (Function *function : interface->getFunctions()) - { - FunctionType *functionType = function->getFunctionType(); - if (functionType) - { - bool isPresent = (functionTypeMap.find(functionType) != functionTypeMap.end()); - if (isPresent) - { - ++functionTypeMap[functionType]; - } - else - { - functionTypeMap[functionType] = 1; - } - } - } - } - - for (std::map::iterator it = functionTypeMap.begin(); it != functionTypeMap.end(); ++it) - { - if (it->second > 1) - { - functionTypes.push_back(getFunctionTypeTemplateData(group, it->first)); - } - } - - return functionTypes; -} - data_map CGenerator::getStructDeclarationTemplateData(StructType *structType) { data_map info; @@ -1082,8 +1038,8 @@ data_map CGenerator::getStructDeclarationTemplateData(StructType *structType) DataType *trueDataType = member->getDataType()->getTrueDataType(); // Check if member is byRef type. Add "*" for type and allocate space for data on server side. - if (member->isByref() && - (trueDataType->isStruct() || trueDataType->isUnion() || trueDataType->isScalar() || trueDataType->isEnum())) + if (member->isByref() && (trueDataType->isStruct() || trueDataType->isUnion() || trueDataType->isScalar() || + trueDataType->isEnum() || trueDataType->isFunction())) { memberName = "*" + memberName; } @@ -1157,8 +1113,7 @@ data_map CGenerator::getStructDefinitionTemplateData(Group *group, StructType *s { throw syntax_error( format_string("line %d: Struct member shall use byref option. Member is using forward declared type.", - member->getFirstLine()) - .c_str()); + member->getFirstLine())); } // Handle nullable annotation bool isNullable = @@ -1364,14 +1319,16 @@ void CGenerator::setTemplateComments(Symbol *symbol, data_map &symbolInfo) bool CGenerator::isServerNullParam(StructMember *param) { DataType *paramTrueDataType = param->getDataType()->getTrueDataType(); - return (!paramTrueDataType->isScalar() && !paramTrueDataType->isEnum() && !paramTrueDataType->isArray()); + return (!paramTrueDataType->isScalar() && !paramTrueDataType->isEnum() && !paramTrueDataType->isArray() && + !paramTrueDataType->isFunction()); } bool CGenerator::isPointerParam(StructMember *param) { DataType *paramTrueDataType = param->getDataType()->getTrueDataType(); return (isServerNullParam(param) || - ((paramTrueDataType->isScalar() || paramTrueDataType->isEnum()) && param->getDirection() != kInDirection)); + ((paramTrueDataType->isScalar() || paramTrueDataType->isEnum() || paramTrueDataType->isFunction()) && + param->getDirection() != param_direction_t::kInDirection)); } bool CGenerator::isNullableParam(StructMember *param) @@ -1383,6 +1340,8 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) { data_map info; Symbol *fnSymbol = dynamic_cast(fn); + data_list externalInterfacesDataList; + list externalInterfacesList; // reset list numbering. listCounter = 0; @@ -1393,6 +1352,8 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) setTemplateComments(fnSymbol, info); info["needTempVariableServerI32"] = false; info["needTempVariableClientI32"] = false; + info["needTempVariableServerU16"] = false; + info["needTempVariableClientU16"] = false; info["needNullVariableOnServer"] = false; /* Is function declared as external? */ @@ -1436,7 +1397,7 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) returnInfo["lengthName"] = ""; returnInfo["nullVariable"] = ""; - returnInfo["direction"] = getDirection(kReturn); + returnInfo["direction"] = getDirection(param_direction_t::kReturn); returnInfo["coderCall"] = getEncodeDecodeCall(result, group, dataType, nullptr, false, structMember, needTempVariableI32, true); returnInfo["shared"] = isShared; @@ -1444,7 +1405,8 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) info["needTempVariableClientI32"] = needTempVariableI32; returnInfo["resultVariable"] = resultVariable; returnInfo["errorReturnValue"] = getErrorReturnValue(fn); - returnInfo["isNullReturnType"] = (!trueDataType->isScalar() && !trueDataType->isEnum()); + returnInfo["isNullReturnType"] = + (!trueDataType->isScalar() && !trueDataType->isEnum() && !trueDataType->isFunction()); } info["returnValue"] = returnInfo; @@ -1498,7 +1460,7 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) // Directions in which list/union is serializing reference if (referencedFrom->getDirection() == param->getDirection()) { - paramInfo["serializedDirection"] = getDirection(kInoutDirection); + paramInfo["serializedDirection"] = getDirection(param_direction_t::kInoutDirection); } else { @@ -1542,7 +1504,7 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) // Special case when scalar variables are @nullable string nullableName = getOutputName(param); paramInfo["nullableName"] = nullableName; - if (paramTrueType->isScalar() || paramTrueType->isEnum()) + if (paramTrueType->isScalar() || paramTrueType->isEnum() || paramTrueType->isFunction()) { paramInfo["nullVariable"] = getTypenameName(paramTrueType, "*_" + nullableName); } @@ -1569,7 +1531,7 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) { StructMember *symbolStructMember = dynamic_cast(symbol); assert(symbolStructMember); - if (symbolStructMember->getDirection() != kInDirection) + if (symbolStructMember->getDirection() != param_direction_t::kInDirection) { throw semantic_error( format_string("line %d, ref %d: The parameter named by a max_length annotation must be " @@ -1580,12 +1542,41 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) } } + string ifaceScope = ""; + if (paramTrueType->isFunction()) + { + FunctionType *funType = dynamic_cast(paramTrueType); + if (funType->getCallbackFuns().size() > 1) + { + info["needTempVariableServerU16"] = true; + info["needTempVariableClientU16"] = true; + } + if (funType->getInterface() != fn->getInterface()) + { + ifaceScope = funType->getInterface()->getName(); + } + } + paramInfo["mallocServer"] = firstAllocOnServerWhenIsNeed(name, param); setCallingFreeFunctions(param, paramInfo, false); // Use shared memory feature instead of serializing/deserializing data. bool isShared = (isPointerParam(param) && findAnnotation(param, SHARED_ANNOTATION) != nullptr); + + string pureCName = ""; + if ((param->getDirection() != param_direction_t::kInDirection) && paramTrueType->isFunction()) + { + pureCName += "&"; + } + if (paramTrueType->isFunction()) + { + pureCName += "_"; + } + pureCName += name; + paramInfo["shared"] = isShared; + paramInfo["pureName"] = name; + paramInfo["pureNameC"] = pureCName; string encodeDecodeName; if (isShared) { @@ -1602,6 +1593,12 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) paramInfo["variable"] = getTypenameName(paramType, name); paramInfo["name"] = name; + if (ifaceScope != "") + { + externalInterfacesList.push_back(ifaceScope); + } + paramInfo["ifaceScope"] = ifaceScope; + paramInfo["isFunction"] = paramTrueType->isFunction(); Log::debug("Calling EncodeDecode param %s with paramType %s.\n", param->getName().c_str(), paramType->getName().c_str()); @@ -1613,11 +1610,12 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) setSymbolDataToSide(param, group->getSymbolDirections(param), paramsToClient, paramsToServer, paramInfo); - if (needTempVariableI32 && param->getDirection() != kInDirection) + if (needTempVariableI32 && param->getDirection() != param_direction_t::kInDirection) { info["needTempVariableClientI32"] = true; } - if (needTempVariableI32 && (param->getDirection() == kInDirection || param->getDirection() == kInoutDirection)) + if (needTempVariableI32 && (param->getDirection() == param_direction_t::kInDirection || + param->getDirection() == param_direction_t::kInoutDirection)) { info["needTempVariableServerI32"] = true; } @@ -1631,6 +1629,11 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) paramsToFree.push_back(paramInfo); } } + externalInterfacesList.unique(); + for (auto externalInterface : externalInterfacesList) + { + externalInterfacesDataList.push_back(externalInterface); + } if (paramsToClient.size() > 0) { info["isReturnValue"] = true; @@ -1643,6 +1646,7 @@ data_map CGenerator::getFunctionBaseTemplateData(Group *group, FunctionBase *fn) info["paramsToFree"] = paramsToFree; info["parametersToClient"] = paramsToClient; info["parametersToServer"] = paramsToServer; + info["externalInterfaces"] = externalInterfacesDataList; return info; } @@ -1658,9 +1662,9 @@ data_map CGenerator::getFunctionTemplateData(Group *group, Function *fn) if (fn->getFunctionType()) { int similarFunctions = 0; - for (Interface *interface : group->getInterfaces()) + for (Interface *_interface : group->getInterfaces()) { - for (Function *function : interface->getFunctions()) + for (Function *function : _interface->getFunctions()) { if (fn->getFunctionType() == function->getFunctionType()) { @@ -1678,6 +1682,7 @@ data_map CGenerator::getFunctionTemplateData(Group *group, Function *fn) if (useCommonFunction) { std::string callbackFName = getOutputName(fn->getFunctionType()); + info["callbackFNameNoGroup"] = callbackFName; if (!group->getName().empty()) { callbackFName += "_" + group->getName(); @@ -1689,13 +1694,36 @@ data_map CGenerator::getFunctionTemplateData(Group *group, Function *fn) else { info["isCallback"] = false; - string serverProto = getFunctionServerCall(fn); - info["serverPrototype"] = serverProto; + info["serverPrototype"] = getFunctionServerCall(fn); info["serviceId"] = ""; } + string serverProtoC = getFunctionServerCall(fn, true); + info["serverPrototypeC"] = serverProtoC; string proto = getFunctionPrototype(group, fn); info["prototype"] = proto; + string protoCpp = getFunctionPrototype(group, fn, getOutputName(fn->getInterface()) + "_client", "", true); + info["prototypeCpp"] = protoCpp; + string protoInterface = getFunctionPrototype(group, fn, "", "", true); + info["prototypeInterface"] = protoInterface; + + data_list callbackParameters; + for (auto parameter : fn->getParameters().getMembers()) + { + if (parameter->getDataType()->isFunction()) + { + data_map paramData; + FunctionType *funType = dynamic_cast(parameter->getDataType()); + paramData["name"] = parameter->getName(); + paramData["type"] = funType->getName(); + paramData["interface"] = funType->getCallbackFuns()[0]->getInterface()->getName() + "_interface"; + paramData["in"] = ((parameter->getDirection() == param_direction_t::kInDirection)); + paramData["out"] = ((parameter->getDirection() == param_direction_t::kOutDirection)); + callbackParameters.push_back(paramData); + } + } + info["callbackParameters"] = callbackParameters; + info["name"] = getOutputName(fn); info["id"] = fn->getUniqueId(); @@ -1722,7 +1750,7 @@ data_map CGenerator::getFunctionTypeTemplateData(Group *group, FunctionType *fn) } } - string proto = getFunctionPrototype(group, fn, name); + string proto = getFunctionPrototype(group, fn, "", name); info = getFunctionBaseTemplateData(group, fn); info["prototype"] = proto; info["name"] = name; @@ -1732,7 +1760,7 @@ data_map CGenerator::getFunctionTypeTemplateData(Group *group, FunctionType *fn) { data_map functionInfo = getFunctionTemplateData(group, function); // set serverPrototype function with parameters of common function. - string serverProto = getFunctionServerCall(function, fn); + string serverProto = getFunctionServerCall(function, true); functionInfo["serverPrototype"] = serverProto; functionInfos.push_back(functionInfo); } @@ -1742,10 +1770,10 @@ data_map CGenerator::getFunctionTypeTemplateData(Group *group, FunctionType *fn) return info; } -void CGenerator::setSymbolDataToSide(const Symbol *symbolType, const set<_param_direction> &directions, +void CGenerator::setSymbolDataToSide(const Symbol *symbolType, const set &directions, data_list &toClient, data_list &toServer, data_map &dataMap) { - _direction direction = kIn; + direction_t direction = direction_t::kIn; if (symbolType->isDatatypeSymbol()) { const DataType *dataType = dynamic_cast(symbolType); @@ -1753,26 +1781,26 @@ void CGenerator::setSymbolDataToSide(const Symbol *symbolType, const set<_param_ if (dataType->isStruct() || dataType->isFunction() || dataType->isUnion()) { - bool in = directions.count(kInDirection); - bool out = directions.count(kOutDirection); - bool inOut = directions.count(kInoutDirection); - bool ret = directions.count(kReturn); + bool in = directions.count(param_direction_t::kInDirection); + bool out = directions.count(param_direction_t::kOutDirection); + bool inOut = directions.count(param_direction_t::kInoutDirection); + bool ret = directions.count(param_direction_t::kReturn); Log::info("Symbol %s has directions: in:%d, out:%d, inOut:%d, ret:%d\n", symbolType->getName().c_str(), in, out, inOut, ret); if (inOut || (in && (ret || out))) { - direction = kInOut; + direction = direction_t::kInOut; } else if (ret || out) { - direction = kOut; + direction = direction_t::kOut; } else if (!in && !out && !ret && !inOut) { // ToDo: shared pointer. - direction = kNone; + direction = direction_t::kNone; } } else @@ -1787,16 +1815,19 @@ void CGenerator::setSymbolDataToSide(const Symbol *symbolType, const set<_param_ assert(structMember); switch (structMember->getDirection()) { - case kOutDirection: - case kInoutDirection: { - direction = kInOut; + case param_direction_t::kOutDirection: + case param_direction_t::kInoutDirection: + { + direction = direction_t::kInOut; break; } - case kInDirection: { - direction = kIn; + case param_direction_t::kInDirection: + { + direction = direction_t::kIn; break; } - default: { + default: + { throw internal_error("Unsupported direction type of structure member."); } } @@ -1809,20 +1840,23 @@ void CGenerator::setSymbolDataToSide(const Symbol *symbolType, const set<_param_ switch (direction) { - case kIn: { + case direction_t::kIn: + { toServer.push_back(dataMap); break; } - case kOut: { + case direction_t::kOut: + { toClient.push_back(dataMap); break; } - case kInOut: { + case direction_t::kInOut: + { toServer.push_back(dataMap); toClient.push_back(dataMap); break; } - case kNone: // ToDo: shared pointer + case direction_t::kNone: // ToDo: shared pointer { break; } @@ -1835,7 +1869,7 @@ data_map CGenerator::getTypeInfo(DataType *t, bool isFunction) { (void)isFunction; data_map info; - info["isNotVoid"] = make_data(t->getDataType() != DataType::kVoidType); + info["isNotVoid"] = make_data(t->getDataType() != DataType::data_type_t::kVoidType); return info; } @@ -1861,7 +1895,7 @@ string CGenerator::getErrorReturnValue(FunctionBase *fn) { BuiltinType *builtinType = dynamic_cast(dataType); assert(builtinType); - if (builtinType->getBuiltinType() == BuiltinType::kBoolType) + if (builtinType->getBuiltinType() == BuiltinType::builtin_type_t::kBoolType) { IntegerValue *integerValue = dynamic_cast(returnVal); assert(integerValue); @@ -1878,22 +1912,28 @@ string CGenerator::getErrorReturnValue(FunctionBase *fn) assert(builtinType); switch (builtinType->getBuiltinType()) { - case BuiltinType::kBoolType: { + case BuiltinType::builtin_type_t::kBoolType: + { return "false"; } - case BuiltinType::kUInt8Type: { + case BuiltinType::builtin_type_t::kUInt8Type: + { return "0xFFU"; } - case BuiltinType::kUInt16Type: { + case BuiltinType::builtin_type_t::kUInt16Type: + { return "0xFFFFU"; } - case BuiltinType::kUInt32Type: { + case BuiltinType::builtin_type_t::kUInt32Type: + { return "0xFFFFFFFFU"; } - case BuiltinType::kUInt64Type: { + case BuiltinType::builtin_type_t::kUInt64Type: + { return "0xFFFFFFFFFFFFFFFFU"; } - default: { + default: + { return "-1"; } } @@ -1909,17 +1949,23 @@ string CGenerator::getErrorReturnValue(FunctionBase *fn) } } -string CGenerator::getFunctionServerCall(Function *fn, FunctionType *functionType) +string CGenerator::getFunctionServerCall(Function *fn, bool isCCall) { string proto = ""; - if (!fn->getReturnType()->isVoid()) + if (!isCCall) { - proto += "result = "; + if (!fn->getReturnType()->isVoid()) + { + proto += "result = "; + } + proto += "m_handler->"; } proto += getOutputName(fn); proto += "("; - auto params = (functionType) ? functionType->getParameters().getMembers() : fn->getParameters().getMembers(); + FunctionType *funcType = fn->getFunctionType(); + + auto params = (funcType) ? funcType->getParameters().getMembers() : fn->getParameters().getMembers(); if (params.size()) { @@ -1930,19 +1976,28 @@ string CGenerator::getFunctionServerCall(Function *fn, FunctionType *functionTyp DataType *trueDataType = it->getDataType()->getTrueDataType(); /* Builtin types and function types. */ - if (((trueDataType->isScalar()) || trueDataType->isEnum()) && it->getDirection() != kInDirection && - findAnnotation(it, NULLABLE_ANNOTATION)) + if (((trueDataType->isScalar()) || trueDataType->isEnum() || trueDataType->isFunction()) && + it->getDirection() != param_direction_t::kInDirection && findAnnotation(it, NULLABLE_ANNOTATION)) { // On server side is created new variable for handle null : "_" + name proto += "_"; } - else if ((it->getDirection() != kInDirection) && (((trueDataType->isScalar()) || trueDataType->isEnum()) || - (findAnnotation(it, SHARED_ANNOTATION)))) + else if ((it->getDirection() != param_direction_t::kInDirection) && + (((trueDataType->isScalar()) || trueDataType->isEnum() || trueDataType->isFunction()) || + (findAnnotation(it, SHARED_ANNOTATION)))) { - proto += "&"; + if (!isCCall) + { + proto += "&"; + } + } + std::string paramName = getOutputName(fn->getParameters().getMembers()[n]); + if ((paramName.empty()) || (funcType && funcType->getCallbackFuns().size() > 1)) + { + paramName = getOutputName(it); } - proto += getOutputName(it); + proto += paramName; if (!isLast) { @@ -1954,34 +2009,40 @@ string CGenerator::getFunctionServerCall(Function *fn, FunctionType *functionTyp return proto + ");"; } -string CGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const std::string name) +string CGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const std::string &interfaceName, + const string &name, bool insideInterfaceCall) { DataType *dataTypeReturn = fn->getReturnType(); string proto = getExtraPointerInReturn(dataTypeReturn); + string ifaceVar = interfaceName; if (proto == "*") { proto += " "; } - Symbol *symbol = dynamic_cast(fn); - assert(symbol); + if (ifaceVar != "") + { + ifaceVar += "::"; + } FunctionType *funType = dynamic_cast(fn); if (name.empty()) { + Symbol *symbol = dynamic_cast(fn); + assert(symbol); string functionName = getOutputName(symbol); if (funType) /* Need add '(*name)' for function type definition. */ { - proto += "(*" + functionName + ")"; + proto += "(" + ifaceVar + "*" + functionName + ")"; } else /* Use function name only. */ { - proto += functionName; + proto += ifaceVar + functionName; } } else { - proto += name; + proto += ifaceVar + name; } proto += "("; @@ -1990,7 +2051,7 @@ string CGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const st // add interface id and function id parameters for common callbacks shim code function if (!name.empty()) { - proto += "uint32_t serviceID, uint32_t functionID"; + proto += "ClientManager *m_clientManager, uint32_t serviceID, uint32_t functionID"; if (params.size() > 0) { proto += ", "; @@ -2009,9 +2070,8 @@ string CGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const st /* Add '*' to data types. */ if (((trueDataType->isBuiltin() || trueDataType->isEnum()) && - (it->getDirection() != kInDirection && !trueDataType->isString())) || - (trueDataType->isFunction() && - (it->getDirection() == kOutDirection || it->getDirection() == kInoutDirection))) + ((it->getDirection() != param_direction_t::kInDirection) && !trueDataType->isString())) || + (trueDataType->isFunction() && (it->getDirection() != param_direction_t::kInDirection))) { paramSignature = "* " + paramSignature; } @@ -2031,7 +2091,7 @@ string CGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const st if ((dataType->isString() || dataType->isFunction() || trueDataType->isStruct() || trueDataType->isList() || trueDataType->isArray() || trueDataType->isBinary() || trueDataType->isUnion()) && - it->getDirection() == kInDirection) + it->getDirection() == param_direction_t::kInDirection) { bool pass = true; if (trueDataType->isArray()) @@ -2071,10 +2131,11 @@ string CGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const st // Todo: Need check if members are/aren't shared. if (group != nullptr) { - const set<_param_direction> directions = group->getSymbolDirections(structType); + const set directions = group->getSymbolDirections(structType); if (!findAnnotation(it, SHARED_ANNOTATION) && - (directions.count(kInoutDirection) && - (directions.count(kOutDirection) || directions.count(kReturn)))) + (directions.count(param_direction_t::kInoutDirection) && + (directions.count(param_direction_t::kOutDirection) || + directions.count(param_direction_t::kReturn)))) { throw syntax_error( format_string("line %d: structs, lists, and binary cannot be used as both " @@ -2084,6 +2145,18 @@ string CGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const st } } + if (insideInterfaceCall) + { + if (trueDataType->isFunction()) + { + FunctionType *funcType = dynamic_cast(trueDataType); + if (fn->getInterface() != funcType->getInterface()) + { + proto += funcType->getInterface()->getName() + "_interface::"; + } + } + } + proto += paramSignature; if (!isLast) { @@ -2132,7 +2205,8 @@ string CGenerator::getTypenameName(DataType *t, const string &name) string returnName; switch (t->getDataType()) { - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { // Array type requires the array element count to come after the variable/member name. returnName = name; ArrayType *a = dynamic_cast(t); @@ -2142,7 +2216,8 @@ string CGenerator::getTypenameName(DataType *t, const string &name) returnName = getTypenameName(a->getElementType(), returnName); break; } - case DataType::kBuiltinType: { + case DataType::data_type_t::kBuiltinType: + { assert(nullptr != dynamic_cast(t)); returnName = getBuiltinTypename(dynamic_cast(t)); if (!(t->isString() && name != "" && name[0] == '*')) @@ -2152,14 +2227,16 @@ string CGenerator::getTypenameName(DataType *t, const string &name) returnName += name; break; } - case DataType::kListType: { + case DataType::data_type_t::kListType: + { const ListType *a = dynamic_cast(t); assert(a); returnName = "* " + name; returnName = getTypenameName(a->getElementType(), returnName); break; } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *unionType = dynamic_cast(t); assert(unionType); if (unionType->isNonEncapsulatedUnion()) @@ -2175,15 +2252,17 @@ string CGenerator::getTypenameName(DataType *t, const string &name) } break; } - case DataType::kVoidType: { + case DataType::data_type_t::kVoidType: + { returnName = "void"; returnName += returnSpaceWhenNotEmpty(name) + name; break; } - case DataType::kAliasType: - case DataType::kEnumType: - case DataType::kFunctionType: - case DataType::kStructType: { + case DataType::data_type_t::kAliasType: + case DataType::data_type_t::kEnumType: + case DataType::data_type_t::kFunctionType: + case DataType::data_type_t::kStructType: + { returnName = getOutputName(t); returnName += returnSpaceWhenNotEmpty(name) + name; break; @@ -2199,33 +2278,33 @@ string CGenerator::getBuiltinTypename(const BuiltinType *t) { switch (t->getBuiltinType()) { - case BuiltinType::kBoolType: + case BuiltinType::builtin_type_t::kBoolType: return "bool"; - case BuiltinType::kInt8Type: + case BuiltinType::builtin_type_t::kInt8Type: return "int8_t"; - case BuiltinType::kInt16Type: + case BuiltinType::builtin_type_t::kInt16Type: return "int16_t"; - case BuiltinType::kInt32Type: + case BuiltinType::builtin_type_t::kInt32Type: return "int32_t"; - case BuiltinType::kInt64Type: + case BuiltinType::builtin_type_t::kInt64Type: return "int64_t"; - case BuiltinType::kUInt8Type: + case BuiltinType::builtin_type_t::kUInt8Type: return "uint8_t"; - case BuiltinType::kUInt16Type: + case BuiltinType::builtin_type_t::kUInt16Type: return "uint16_t"; - case BuiltinType::kUInt32Type: + case BuiltinType::builtin_type_t::kUInt32Type: return "uint32_t"; - case BuiltinType::kUInt64Type: + case BuiltinType::builtin_type_t::kUInt64Type: return "uint64_t"; - case BuiltinType::kFloatType: + case BuiltinType::builtin_type_t::kFloatType: return "float"; - case BuiltinType::kDoubleType: + case BuiltinType::builtin_type_t::kDoubleType: return "double"; - case BuiltinType::kStringType: + case BuiltinType::builtin_type_t::kStringType: return "char *"; - case BuiltinType::kUStringType: + case BuiltinType::builtin_type_t::kUStringType: return "unsigned char*"; - case BuiltinType::kBinaryType: + case BuiltinType::builtin_type_t::kBinaryType: return "uint8_t *"; default: throw internal_error("unknown builtin type"); @@ -2241,10 +2320,11 @@ void CGenerator::getEncodeDecodeBuiltin(Group *group, BuiltinType *t, data_map & if (t->isString()) { templateData["checkStringNull"] = false; - templateData["withoutAlloc"] = ((structMember->getDirection() == kInoutDirection) || - (structType && group->getSymbolDirections(structType).count(kInoutDirection))) ? - true : - false; + templateData["withoutAlloc"] = + ((structMember->getDirection() == param_direction_t::kInoutDirection) || + (structType && group->getSymbolDirections(structType).count(param_direction_t::kInoutDirection))) ? + true : + false; if (!isFunctionParam) { templateData["stringAllocSize"] = getOutputName(structMember) + "_len"; @@ -2262,7 +2342,8 @@ void CGenerator::getEncodeDecodeBuiltin(Group *group, BuiltinType *t, data_map & templateData["checkStringNull"] = true; templateData["stringLocalName"] = getOutputName(structMember); templateData["stringAllocSize"] = getAnnStringValue(structMember, MAX_LENGTH_ANNOTATION); - if (structMember->getDirection() == kInoutDirection || structMember->getDirection() == kOutDirection) + if ((structMember->getDirection() == param_direction_t::kInoutDirection) || + (structMember->getDirection() == param_direction_t::kOutDirection)) { templateData["withoutAlloc"] = true; } @@ -2285,7 +2366,7 @@ void CGenerator::getEncodeDecodeBuiltin(Group *group, BuiltinType *t, data_map & } data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataType *t, StructType *structType, - bool inDataContainer, StructMember *structMember, bool &needTempVariable, + bool inDataContainer, StructMember *structMember, bool &needTempVariableI32, bool isFunctionParam) { // prepare data for template @@ -2317,10 +2398,11 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT (structType && findAnnotation(structType, SHARED_ANNOTATION))) { templateData["funcParam"] = (structType) ? true : false; - templateData["InoutOutDirection"] = (structMember && (structMember->getDirection() == kOutDirection || - structMember->getDirection() == kInoutDirection)) ? - true : - false; + templateData["InoutOutDirection"] = + (structMember && (structMember->getDirection() == param_direction_t::kOutDirection || + structMember->getDirection() == param_direction_t::kInoutDirection)) ? + true : + false; templateData["encode"] = m_templateData["encodeSharedType"]; templateData["decode"] = m_templateData["decodeSharedType"]; templateData["name"] = name; @@ -2356,7 +2438,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT templateData["sharedType"] = "union"; if (setDiscriminatorTemp(u, structType, structMember, isFunctionParam, templateData)) { - needTempVariable = true; + needTempVariableI32 = true; } break; @@ -2370,7 +2452,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT // Check if member is byRef type. Add "*" for type and allocate space for data on server side. if (structMember && structMember->isByref() && !isFunctionParam && - (t->isStruct() || t->isUnion() || t->isScalar() || t->isEnum())) + (t->isStruct() || t->isUnion() || t->isScalar() || t->isEnum() || t->isFunction())) { templateData["freeingCall2"] = m_templateData["freeData"]; templateData["memberAllocation"] = allocateCall(name, t); @@ -2383,13 +2465,13 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT templateData["name"] = localName; - if (t->isScalar() || t->isEnum()) + if (t->isScalar() || t->isEnum() || t->isFunction()) { templateData["pointerScalarTypes"] = false; - if (!inDataContainer && structMember && structMember->getDirection() != kInDirection) + if (!inDataContainer && structMember && structMember->getDirection() != param_direction_t::kInDirection) { DataType *trueDataType = t->getTrueDataType(); - if (trueDataType->isScalar() || trueDataType->isEnum()) + if (trueDataType->isScalar() || trueDataType->isEnum() || t->isFunction()) { templateData["pointerScalarTypes"] = true; } @@ -2398,13 +2480,15 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT switch (t->getDataType()) { - case DataType::kAliasType: { + case DataType::data_type_t::kAliasType: + { AliasType *aliasType = dynamic_cast(t); assert(aliasType); return getEncodeDecodeCall(name, group, aliasType->getElementType(), structType, inDataContainer, - structMember, needTempVariable, isFunctionParam); + structMember, needTempVariableI32, isFunctionParam); } - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { static uint8_t arrayCounter; ArrayType *arrayType = dynamic_cast(t); assert(arrayType); @@ -2417,7 +2501,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT // To improve code serialization/deserialization for scalar types when BasicCodec is used. templateData["builtinTypeName"] = - ((m_def->getCodecType() != InterfaceDefinition::kBasicCodec) || trueElementType->isBool()) ? + ((m_def->getCodecType() != InterfaceDefinition::codec_t::kBasicCodec) || trueElementType->isBool()) ? "" : getScalarTypename(elementType); @@ -2425,7 +2509,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT templateData["forLoopCount"] = format_string("arrayCount%d", arrayCounter); templateData["protoNext"] = getEncodeDecodeCall(format_string("%s[arrayCount%d]", arrayName.c_str(), arrayCounter++), group, - elementType, structType, true, structMember, needTempVariable, isFunctionParam); + elementType, structType, true, structMember, needTempVariableI32, isFunctionParam); templateData["size"] = format_string("%dU", arrayType->getElementCount()); templateData["sizeTemp"] = format_string("%dU", arrayType->getElementCount()); templateData["isElementArrayType"] = trueElementType->isArray(); @@ -2437,13 +2521,15 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT --arrayCounter; break; } - case DataType::kBuiltinType: { + case DataType::data_type_t::kBuiltinType: + { getEncodeDecodeBuiltin(group, dynamic_cast(t), templateData, structType, structMember, isFunctionParam); break; } - case DataType::kEnumType: { - needTempVariable = true; + case DataType::data_type_t::kEnumType: + { + needTempVariableI32 = true; templateData["decode"] = m_templateData["decodeEnumType"]; templateData["encode"] = m_templateData["encodeEnumType"]; string typeName = getOutputName(t); @@ -2457,11 +2543,14 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT } break; } - case DataType::kFunctionType: { + case DataType::data_type_t::kFunctionType: + { FunctionType *funType = dynamic_cast(t); assert(funType); const FunctionType::c_function_list_t &callbacks = funType->getCallbackFuns(); templateData["callbacksCount"] = callbacks.size(); + templateData["cbTypeName"] = funType->getName(); + templateData["cbParamOutName"] = name; if (callbacks.size() > 1) { templateData["callbacks"] = "_" + funType->getName(); @@ -2472,24 +2561,26 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT } else { - throw semantic_error(format_string("line %d: Function has function type parameter (callback " - "parameter), but in IDL is missing function definition, which can " - "be passed there.", - structMember->getFirstLine()) - .c_str()); + throw semantic_error( + format_string("line %d: Function has function type parameter (callback " + "parameter), but in IDL is missing function definition, which can " + "be passed there.", + structMember->getFirstLine())); } templateData["encode"] = m_templateData["encodeFunctionType"]; templateData["decode"] = m_templateData["decodeFunctionType"]; break; } - case DataType::kListType: { + case DataType::data_type_t::kListType: + { ListType *listType = dynamic_cast(t); assert(listType); DataType *elementType = listType->getElementType(); DataType *trueElementType = elementType->getTrueDataType(); - bool isInOut = ((structMember->getDirection() == kInoutDirection) || - (!isFunctionParam && group->getSymbolDirections(structType).count(kInoutDirection))); + bool isInOut = ((structMember->getDirection() == param_direction_t::kInoutDirection) || + (!isFunctionParam && + group->getSymbolDirections(structType).count(param_direction_t::kInoutDirection))); bool isTopDataType = (isFunctionParam && structMember->getDataType()->getTrueDataType() == t); @@ -2504,7 +2595,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT // To improve code serialization/deserialization for scalar types when BasicCodec is used. templateData["builtinTypeName"] = - ((m_def->getCodecType() != InterfaceDefinition::kBasicCodec) || trueElementType->isBool()) ? + ((m_def->getCodecType() != InterfaceDefinition::codec_t::kBasicCodec) || trueElementType->isBool()) ? "" : getScalarTypename(elementType); @@ -2562,7 +2653,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT { StructMember *lengthVariable = dynamic_cast(symbol); assert(lengthVariable); - if (lengthVariable->getDirection() != kInDirection) + if (lengthVariable->getDirection() != param_direction_t::kInDirection) { templateData["pointerScalarTypes"] = true; } @@ -2623,10 +2714,11 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT templateData["size"] = size; templateData["useBinaryCoder"] = isBinaryList(listType); templateData["protoNext"] = getEncodeDecodeCall(nextName, group, elementType, structType, true, - structMember, needTempVariable, isFunctionParam); + structMember, needTempVariableI32, isFunctionParam); break; } - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { // needDealloc(templateData, t, structType, structMember); string typeName = getOutputName(t); if (typeName != "") @@ -2646,7 +2738,8 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT } break; } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *unionType = dynamic_cast(t); assert(unionType); @@ -2654,7 +2747,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT // set discriminator name if (setDiscriminatorTemp(unionType, structType, structMember, isFunctionParam, templateData)) { - needTempVariable = true; + needTempVariableI32 = true; } /* NonEncapsulated unions as a function/structure param/member. */ @@ -2673,7 +2766,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT templateData["discrimPtr"] = false; if (isFunctionParam) { - if (structMember->getDirection() != kInDirection) + if (structMember->getDirection() != param_direction_t::kInDirection) { templateData["discrimPtr"] = true; } @@ -2749,7 +2842,7 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT caseMembers.push_back(memberData); if (casesNeedTempVariable) { - needTempVariable = true; + needTempVariableI32 = true; } } } @@ -2763,7 +2856,8 @@ data_map CGenerator::getEncodeDecodeCall(const string &name, Group *group, DataT } break; } - default: { + default: + { throw internal_error("unknown member type"); } } @@ -2793,12 +2887,13 @@ string CGenerator::getExtraDirectionPointer(StructMember *structMember) { DataType *dataType = structMember->getDataType(); DataType *trueDataType = dataType->getTrueDataType(); - _param_direction structMemberDir = structMember->getDirection(); + param_direction_t structMemberDir = structMember->getDirection(); string result; - if (structMemberDir == kOutDirection) // between out and inout can be differences in future. Maybe not. + if (structMemberDir == + param_direction_t::kOutDirection) // between out and inout can be differences in future. Maybe not. { if (!trueDataType->isBuiltin() && !trueDataType->isEnum() && !trueDataType->isList() && - !trueDataType->isArray()) + !trueDataType->isArray() && !trueDataType->isFunction()) { result = "*"; } @@ -2807,10 +2902,10 @@ string CGenerator::getExtraDirectionPointer(StructMember *structMember) result += "*"; } } - else if (structMemberDir == kInoutDirection) + else if (structMemberDir == param_direction_t::kInoutDirection) { if (!trueDataType->isBuiltin() && !trueDataType->isEnum() && !trueDataType->isList() && - !trueDataType->isArray()) + !trueDataType->isArray() && !trueDataType->isFunction()) { result = "*"; } @@ -2848,27 +2943,28 @@ data_map CGenerator::firstAllocOnServerWhenIsNeed(const string &name, StructMemb { DataType *dataType = structMember->getDataType(); DataType *trueDataType = dataType->getTrueDataType(); - _param_direction structMemberDir = structMember->getDirection(); + param_direction_t structMemberDir = structMember->getDirection(); if (!findAnnotation(structMember, SHARED_ANNOTATION)) { - if (structMemberDir == kInoutDirection) + if (structMemberDir == param_direction_t::kInoutDirection) { if (!trueDataType->isBuiltin() && !trueDataType->isEnum() && !trueDataType->isList() && - !trueDataType->isArray()) + !trueDataType->isArray() && !trueDataType->isFunction()) { return allocateCall(name, structMember); } } - else if (structMemberDir == kInDirection) + else if (structMemberDir == param_direction_t::kInDirection) { if (trueDataType->isStruct() || trueDataType->isUnion()) { return allocateCall(name, structMember); } } - else if (structMember->getDirection() == kOutDirection) + else if (structMember->getDirection() == param_direction_t::kOutDirection) { - if (!trueDataType->isBuiltin() && !trueDataType->isEnum() && !trueDataType->isArray()) + if (!trueDataType->isBuiltin() && !trueDataType->isEnum() && !trueDataType->isArray() && + !trueDataType->isFunction()) { return allocateCall(name, structMember); } @@ -2898,27 +2994,32 @@ bool CGenerator::isNeedCallFree(DataType *dataType) DataType *trueDataType = dataType->getTrueDataType(); switch (trueDataType->getDataType()) { - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { ArrayType *arrayType = dynamic_cast(trueDataType); assert(arrayType); return isNeedCallFree(arrayType->getElementType()); } - case DataType::kBuiltinType: { + case DataType::data_type_t::kBuiltinType: + { BuiltinType *builtinType = dynamic_cast(trueDataType); assert(builtinType); return builtinType->isString() || builtinType->isBinary(); } - case DataType::kListType: { + case DataType::data_type_t::kListType: + { return true; } - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *structType = dynamic_cast(trueDataType); assert(structType); set loopDetection; return structType->containListMember() || structType->containStringMember() || containsByrefParamToFree(structType, loopDetection); } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *unionType = dynamic_cast(trueDataType); assert(unionType); for (auto unionCase : unionType->getCases()) @@ -2955,8 +3056,7 @@ void CGenerator::setCallingFreeFunctions(Symbol *symbol, data_map &info, bool re { if (!returnType) { - if (trueDataType->isStruct() || trueDataType->isUnion() || - (trueDataType->isFunction() && ((structMember->getDirection() == kOutDirection)))) + if (trueDataType->isStruct() || trueDataType->isUnion()) { string name = getOutputName(structMember, false); firstFreeingCall1["firstFreeingCall"] = m_templateData["freeData"]; @@ -3053,12 +3153,14 @@ bool CGenerator::containsString(DataType *dataType) DataType *trueDataType = dataType->getTrueContainerDataType(); switch (trueDataType->getDataType()) { - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *s = dynamic_cast(trueDataType); assert(s); return s->containStringMember(); } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *u = dynamic_cast(trueDataType); assert(u); for (UnionCase *unionCase : u->getUniqueCases()) @@ -3077,7 +3179,8 @@ bool CGenerator::containsString(DataType *dataType) } return false; } - default: { + default: + { if (trueDataType->isString()) { return true; @@ -3096,12 +3199,14 @@ bool CGenerator::containsList(DataType *dataType) DataType *trueDataType = dataType->getTrueContainerDataType(); switch (trueDataType->getDataType()) { - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *s = dynamic_cast(trueDataType); assert(s); return s->containListMember(); } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *u = dynamic_cast(trueDataType); assert(u); for (UnionCase *unionCase : u->getUniqueCases()) @@ -3120,7 +3225,8 @@ bool CGenerator::containsList(DataType *dataType) } return false; } - default: { + default: + { return false; } } @@ -3224,7 +3330,7 @@ void CGenerator::setNoSharedAnn(Symbol *parentSymbol, Symbol *childSymbol) bool CGenerator::setDiscriminatorTemp(UnionType *unionType, StructType *structType, StructMember *structMember, bool isFunctionParam, data_map &templateData) { - bool needTempVariable = false; + bool needTempVariableI32 = false; if (structType) { string discriminatorName; @@ -3269,13 +3375,13 @@ bool CGenerator::setDiscriminatorTemp(UnionType *unionType, StructType *structTy } BuiltinType *disBuiltin = dynamic_cast(disType->getTrueDataType()); - if (disBuiltin && disBuiltin->getBuiltinType() == BuiltinType::kInt32Type) + if (disBuiltin && disBuiltin->getBuiltinType() == BuiltinType::builtin_type_t::kInt32Type) { templateData["castDiscriminator"] = false; } else { - needTempVariable = true; + needTempVariableI32 = true; templateData["castDiscriminator"] = true; templateData["discriminatorType"] = disType->getName(); } @@ -3287,7 +3393,7 @@ bool CGenerator::setDiscriminatorTemp(UnionType *unionType, StructType *structTy templateData["dataLiteral"] = ""; templateData["castDiscriminator"] = false; } - return needTempVariable; + return needTempVariableI32; } string CGenerator::getScalarTypename(DataType *dataType) @@ -3311,17 +3417,17 @@ string CGenerator::getScalarTypename(DataType *dataType) } } -string CGenerator::getDirection(_param_direction direction) +string CGenerator::getDirection(param_direction_t direction) { switch (direction) { - case kInDirection: + case param_direction_t::kInDirection: return "kInDirection"; - case kOutDirection: + case param_direction_t::kOutDirection: return "kOutDirection"; - case kInoutDirection: + case param_direction_t::kInoutDirection: return "kInoutDirection"; - case kReturn: + case param_direction_t::kReturn: return "kReturn"; default: throw semantic_error("Unsupported direction type"); @@ -3498,7 +3604,8 @@ void CGenerator::scanStructForAnnotations(StructType *currentStructType, bool is lengthAnn->getLocation().m_firstLine, structMember->getLocation().m_firstLine)); } // Verify using max_length annotation when referenced variable is out. - else if (isFunction && structMemberRef && structMemberRef->getDirection() == kOutDirection && + else if (isFunction && structMemberRef && + structMemberRef->getDirection() == param_direction_t::kOutDirection && !findAnnotation(structMember, MAX_LENGTH_ANNOTATION)) { throw semantic_error( @@ -3507,8 +3614,9 @@ void CGenerator::scanStructForAnnotations(StructType *currentStructType, bool is lengthAnn->getLocation().m_firstLine, structMember->getLocation().m_firstLine)); } // Verify using max_length annotation when referenced variable is inout. - else if (isFunction && structMemberRef && structMember->getDirection() == kInoutDirection && - structMemberRef->getDirection() == kInoutDirection && + else if (isFunction && structMemberRef && + structMember->getDirection() == param_direction_t::kInoutDirection && + structMemberRef->getDirection() == param_direction_t::kInoutDirection && !findAnnotation(structMember, MAX_LENGTH_ANNOTATION)) { throw semantic_error( diff --git a/erpcgen/src/CGenerator.hpp b/erpcgen/src/CGenerator.hpp index 844ae6bc..c6f01757 100644 --- a/erpcgen/src/CGenerator.hpp +++ b/erpcgen/src/CGenerator.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2023 NXP * All rights reserved. * * @@ -51,7 +51,7 @@ class CGenerator : public Generator virtual void generate() override; private: - enum _direction + enum class direction_t { kIn, kOut, @@ -92,39 +92,88 @@ class CGenerator : public Generator void generateOutputFiles(const std::string &fileNameExtension) override; /*! - * @brief This function generate output common types header file. + * @brief This function generate header file output with common eRPC code. * - * @param[in] fileName Name for output client source file. + * @param[in] fileName Name for common eRPC header file output. + */ + void generateCommonCHeaderFiles(std::string fileName); + + /*! + * @brief This function generate header file output with common eRPC code. + * + * @param[in] fileName Name for common eRPC header file output. + */ + void generateCommonCppHeaderFiles(std::string fileName); + + /*! + * @brief This function generate output interface header file. + * + * @param[in] fileName Name for output interface header file. + */ + void generateInterfaceCppHeaderFile(std::string fileName); + + /*! + * @brief This function generate output interface source file. + * + * @param[in] fileName Name for output interface source file. */ - void generateTypesHeaderFile(); + void generateInterfaceCppSourceFile(std::string fileName); /*! - * @brief This function generate output common header file. + * @brief This function generate output client header file for cpp. + * + * @param[in] fileName Name for output client header file. + */ + void generateClientCppHeaderFile(std::string fileName); + + /*! + * @brief This function generate output client source file for cpp. * * @param[in] fileName Name for output client source file. */ - void generateCommonHeaderFiles(const std::string &fileName); + void generateClientCppSourceFile(std::string fileName); + + /*! + * @brief This function generate output server header file for cpp. + * + * @param[in] fileName Name for output server header file. + */ + void generateServerCppHeaderFile(std::string fileName); + + /*! + * @brief This function generate output server source file for cpp. + * + * @param[in] fileName Name for output server source file. + */ + void generateServerCppSourceFile(std::string fileName); + + /*! + * @brief This function generate output client header file for C. + * + * @param[in] fileName Name for output client header file. + */ + void generateClientCHeaderFile(std::string fileName); /*! - * @brief This function generate output client source file. + * @brief This function generate output client source file for C. * * @param[in] fileName Name for output client source file. */ - void generateClientSourceFile(std::string fileName); + void generateClientCSourceFile(std::string fileName); /*! - * @brief This function generate output server header file. + * @brief This function generate output server header file for C. * * @param[in] fileName Name for output server header file. */ - void generateServerHeaderFile(std::string fileName); + void generateServerCHeaderFile(std::string fileName); /*! - * @brief This function generate output server source file. + * @brief This function generate output server source file for C. * * @param[in] fileName Name for output server source file. */ - void generateServerSourceFile(std::string fileName); + void generateServerCSourceFile(std::string fileName); /*! * @brief This function generate output crc16 source file. @@ -204,7 +253,7 @@ class CGenerator : public Generator * * @return Contains interface function data. */ - cpptempl::data_map getFunctionTypeTemplateData(Group *group, FunctionType *fn); + cpptempl::data_map getFunctionTypeTemplateData(Group *group, FunctionType *fn) override; /*! * @brief This function will get symbol comments and convert to language specific ones @@ -420,21 +469,24 @@ class CGenerator : public Generator * * @param[in] group Group to which function belongs. * @param[in] fn Function for prototyping. - * @param[in] name Name used for FunctionType. + * @param[in] interfaceName Interface name used for function declaration. + * @param[in] name Name used for shared code in case of function type. + * @param[in] insideInterfaceCall interfaceClass specific. * * @return String prototype representation for given function. */ - std::string getFunctionPrototype(Group *group, FunctionBase *fn, const std::string name = ""); + std::string getFunctionPrototype(Group *group, FunctionBase *fn, const std::string &interfaceName = "", + const std::string &name = "", bool insideInterfaceCall = false) override; /*! * @brief This function return interface function representation called by server side. * * @param[in] fn Function for interface function representation. - * @param[in] functionType Inside FunctionType common shim code server call need use FunctionType parameters names. + * @param[in] isCCall C and C++ code is similar, but not same. * * @return String representation for given function. */ - std::string getFunctionServerCall(Function *fn, FunctionType *functionType = nullptr); + std::string getFunctionServerCall(Function *fn, bool isCCall = false); /*! * @brief This function return name with guard. @@ -480,13 +532,13 @@ class CGenerator : public Generator * @param[in] structType Structure holdings structure members. * @param[in] inDataContainer Is inside data container (struct, list, array). * @param[in] structMember Null for return. - * @param[out] needTempVariable Return true, when data type contains enum, function, union type. + * @param[out] needTempVariableI32 Return true, when data type contains enum, function, union type. * @param[in] isFunctionParam True for function param else false (structure member). * * @return Template data for decode or encode data type. */ cpptempl::data_map getEncodeDecodeCall(const std::string &name, Group *group, DataType *t, StructType *structType, - bool inDataContainer, StructMember *structMember, bool &needTempVariable, + bool inDataContainer, StructMember *structMember, bool &needTempVariableI32, bool isFunctionParam); /*! @@ -577,7 +629,7 @@ class CGenerator : public Generator * @param[in,out] toServer List of data types designed for server direction. * @param[in] dataMap Map with information about structure or function parameter. */ - void setSymbolDataToSide(const Symbol *symbolType, const std::set<_param_direction> &directions, + void setSymbolDataToSide(const Symbol *symbolType, const std::set &directions, cpptempl::data_list &toClient, cpptempl::data_list &toServer, cpptempl::data_map &dataMap); /*! @@ -726,7 +778,7 @@ class CGenerator : public Generator * * @return String representation for given direction. */ - std::string getDirection(_param_direction direction); + std::string getDirection(param_direction_t direction); /*! * @brief This function returns information if function parameter on server side need be initialized to NULL. diff --git a/erpcgen/src/ErpcLexer.cpp b/erpcgen/src/ErpcLexer.cpp index 79f0f02c..d3763b86 100644 --- a/erpcgen/src/ErpcLexer.cpp +++ b/erpcgen/src/ErpcLexer.cpp @@ -33,11 +33,7 @@ using namespace std; // Code //////////////////////////////////////////////////////////////////////////////// -ErpcLexer::ErpcLexer(const char *inputFile) -: m_value(nullptr) -, m_indents(0) -, m_currentFileInfo(NULL) -, m_idlCrc16(0) +ErpcLexer::ErpcLexer(const char *inputFile) : m_value(nullptr), m_indents(0), m_currentFileInfo(NULL), m_idlCrc16(0) { m_currentFileInfo = openFile(inputFile); yyrestart(m_currentFileInfo->m_savedFile.get()); // instead of yyFlexLexer(idlFile); @@ -79,14 +75,16 @@ int ErpcLexer::processStringEscapes(const char *in, char *out) { switch (*in) { - case '\\': { + case '\\': + { // start of an escape sequence char c = *++in; switch (c) { case 0: // end of the string, bail break; - case 'x': { + case 'x': + { // start of a hex char escape sequence // read high and low nibbles, checking for end of string diff --git a/erpcgen/src/ErpcLexer.hpp b/erpcgen/src/ErpcLexer.hpp index 42c0358f..e0f0a28a 100644 --- a/erpcgen/src/ErpcLexer.hpp +++ b/erpcgen/src/ErpcLexer.hpp @@ -60,13 +60,9 @@ class CurrentFileInfo * @param[in] fileName Name of analyzed file. * @param[in] currentFolderPath Path to folder of current file. */ - CurrentFileInfo(std::ifstream *savedFile, const std::string &fileName, const std::string ¤tFolderPath) - : m_savedFile(savedFile) - , m_previous(NULL) - , m_line(1) - , m_column(0) - , m_fileName(fileName) - , m_currentFolderPath(currentFolderPath) + CurrentFileInfo(std::ifstream *savedFile, const std::string &fileName, const std::string ¤tFolderPath) : + m_savedFile(savedFile), m_previous(NULL), m_line(1), m_column(0), m_fileName(fileName), + m_currentFolderPath(currentFolderPath) { } diff --git a/erpcgen/src/Generator.cpp b/erpcgen/src/Generator.cpp index fcb06611..1feae797 100644 --- a/erpcgen/src/Generator.cpp +++ b/erpcgen/src/Generator.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2023 NXP * All rights reserved. * * @@ -20,6 +20,7 @@ #include #include #include +#include using namespace erpcgen; using namespace cpptempl; @@ -29,15 +30,13 @@ using namespace std; // Code //////////////////////////////////////////////////////////////////////////////// -Generator::Generator(InterfaceDefinition *def, generator_type_t generatorType) -: m_idlCrc16(def->getIdlCrc16()) -, m_def(def) -, m_globals(&(def->getGlobals())) -, m_generatorType(generatorType) +Generator::Generator(InterfaceDefinition *def, generator_type_t generatorType) : +m_idlCrc16(def->getIdlCrc16()), m_def(def), m_globals(&(def->getGlobals())), m_generatorType(generatorType) { string scopeName = "erpcShim"; string scopeNameC; string scopeNamePrefix = ""; + string namespaceVal = scopeName; m_templateData["erpcVersion"] = ERPC_VERSION; m_templateData["erpcVersionNumber"] = ERPC_VERSION_NUMBER; @@ -90,6 +89,11 @@ Generator::Generator(InterfaceDefinition *def, generator_type_t generatorType) { scopeName = getAnnStringValue(program, SCOPE_NAME_ANNOTATION); } + + if (findAnnotation(program, NAMESPACE_ANNOTATION) != nullptr) + { + namespaceVal = getAnnStringValue(program, NAMESPACE_ANNOTATION); + } } m_templateData["scopeName"] = scopeName; @@ -102,13 +106,14 @@ Generator::Generator(InterfaceDefinition *def, generator_type_t generatorType) } m_templateData["scopeNameC"] = scopeNameC; m_templateData["scopeNamePrefix"] = scopeNamePrefix; + m_templateData["namespace"] = namespaceVal; // get group annotation with vector of theirs interfaces m_groups.clear(); data_list groupNames; Group *defaultGroup = new Group(""); - for (auto it : m_globals->getSymbolsOfType(Symbol::kInterfaceSymbol)) + for (auto it : m_globals->getSymbolsOfType(Symbol::symbol_type_t::kInterfaceSymbol)) { Interface *iface = dynamic_cast(it); assert(iface); @@ -156,12 +161,14 @@ Generator::Generator(InterfaceDefinition *def, generator_type_t generatorType) // set codec information switch (m_def->getCodecType()) { - case InterfaceDefinition::kBasicCodec: { + case InterfaceDefinition::codec_t::kBasicCodec: + { m_templateData["codecClass"] = "BasicCodec"; m_templateData["codecHeader"] = "erpc_basic_codec.hpp"; break; } - default: { + default: + { m_templateData["codecClass"] = "Codec"; m_templateData["codecHeader"] = "erpc_codec.hpp"; break; @@ -311,7 +318,8 @@ DataType *Generator::findChildDataType(set &dataTypes, DataType *dat switch (dataType->getDataType()) { - case DataType::kAliasType: { + case DataType::data_type_t::kAliasType: + { AliasType *aliasType = dynamic_cast(dataType); if (aliasType != nullptr) { @@ -319,7 +327,8 @@ DataType *Generator::findChildDataType(set &dataTypes, DataType *dat } break; } - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { ArrayType *arrayType = dynamic_cast(dataType); if (arrayType != nullptr) { @@ -327,7 +336,8 @@ DataType *Generator::findChildDataType(set &dataTypes, DataType *dat } break; } - case DataType::kListType: { + case DataType::data_type_t::kListType: + { ListType *listType = dynamic_cast(dataType); if (listType != nullptr) { @@ -335,7 +345,8 @@ DataType *Generator::findChildDataType(set &dataTypes, DataType *dat } break; } - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *structType = dynamic_cast(dataType); if (structType != nullptr) { @@ -346,7 +357,8 @@ DataType *Generator::findChildDataType(set &dataTypes, DataType *dat } break; } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { // Keil need extra pragma option when unions are used. m_templateData["usedUnionType"] = true; UnionType *unionType = dynamic_cast(dataType); @@ -359,7 +371,8 @@ DataType *Generator::findChildDataType(set &dataTypes, DataType *dat } break; } - default: { + default: + { break; } } @@ -386,7 +399,7 @@ void Generator::findGroupDataTypes() { for (DataType *dataType : dataTypes) { - group->addDirToSymbolsMap(dataType, kReturn); + group->addDirToSymbolsMap(dataType, param_direction_t::kReturn); } } @@ -430,12 +443,21 @@ data_list Generator::makeGroupInterfacesTemplateData(Group *group) // TODO: for C only? ifaceInfo["serviceClassName"] = getOutputName(iface) + "_service"; + ifaceInfo["clientClassName"] = getOutputName(iface) + "_client"; + ifaceInfo["serverClassName"] = getOutputName(iface) + "_server"; + ifaceInfo["interfaceClassName"] = getOutputName(iface) + "_interface"; Log::info("%d: (%d) %s\n", n++, iface->getUniqueId(), iface->getName().c_str()); /* Has interface function declared as non-external? */ data_list functions = getFunctionsTemplateData(group, iface); ifaceInfo["functions"] = functions; + data_list callbacksInt; + data_list callbacksExt; + data_list callbacksAll; + getCallbacksTemplateData(group, iface, callbacksInt, callbacksExt, callbacksAll); + ifaceInfo["callbacksInt"] = callbacksInt; + ifaceInfo["callbacksAll"] = callbacksAll; ifaceInfo["isNonExternalInterface"] = false; for (unsigned int i = 0; i < functions.size(); ++i) { @@ -455,26 +477,35 @@ data_list Generator::makeGroupInterfacesTemplateData(Group *group) return interfaces; } -void Generator::generateGroupOutputFiles(Group *group) +string Generator::getGroupCommonFileName(Group *group) { - // generate output files only for groups with interfaces or for IDLs with no interfaces at all + string fileName = ""; if (!group->getInterfaces().empty() || (m_groups.size() == 1 && group->getName() == "")) { string groupName = group->getName(); - string fileName = stripExtension(m_def->getOutputFilename()); + fileName = stripExtension(m_def->getOutputFilename()); m_templateData["outputFilename"] = fileName; if (groupName != "") { fileName += "_" + groupName; } Log::info("File name %s\n", fileName.c_str()); - m_templateData["commonHeaderName"] = fileName; + } + return fileName; +} + +void Generator::generateGroupOutputFiles(Group *group) +{ + // generate output files only for groups with interfaces or for IDLs with no interfaces at all + if (!group->getInterfaces().empty() || (m_groups.size() == 1 && group->getName() == "")) + { + string fileName = getGroupCommonFileName(group); // group templates m_templateData["group"] = group->getTemplate(); // Log template data. - if (Log::getLogger()->getFilterLevel() >= Logger::kDebug2) + if (Log::getLogger()->getFilterLevel() >= Logger::log_level_t::kDebug2) { dump_data(m_templateData); } @@ -567,10 +598,8 @@ string Generator::getOutputName(Symbol *symbol, bool check) auto it = reserverdWords.find(annName); if (it != reserverdWords.end()) { - throw semantic_error( - format_string("line %d: Wrong symbol name '%s'. Cannot use program language reserved words.", line, - annName.c_str()) - .c_str()); + throw semantic_error(format_string( + "line %d: Wrong symbol name '%s'. Cannot use program language reserved words.", line, annName.c_str())); } } @@ -579,13 +608,17 @@ string Generator::getOutputName(Symbol *symbol, bool check) Annotation::program_lang_t Generator::getAnnotationLang() { - if (m_generatorType == kC) + if (m_generatorType == generator_type_t::kC) { - return Annotation::kC; + return Annotation::program_lang_t::kC; } - else if (m_generatorType == kPython) + else if (m_generatorType == generator_type_t::kPython) { - return Annotation::kPython; + return Annotation::program_lang_t::kPython; + } + else if (m_generatorType == generator_type_t::kJava) + { + return Annotation::program_lang_t::kJava; } throw internal_error("Unsupported generator type specified for annotation."); @@ -630,7 +663,7 @@ Generator::datatype_vector_t Generator::getDataTypesFromSymbolScope(SymbolScope { datatype_vector_t vector; - for (Symbol *symbol : scope->getSymbolsOfType(Symbol::kTypenameSymbol)) + for (Symbol *symbol : scope->getSymbolsOfType(Symbol::symbol_type_t::kTypenameSymbol)) { DataType *dataType = dynamic_cast(symbol); if (dataType->getDataType() == datatype) @@ -641,3 +674,88 @@ Generator::datatype_vector_t Generator::getDataTypesFromSymbolScope(SymbolScope return vector; } + +void Generator::getCallbacksTemplateData(Group *group, const Interface *iface, data_list &callbackTypesInt, + data_list &callbackTypesExt, data_list &callbackTypesAll) +{ + list callbackTypes; + list interfacesNames; + list callbackTypesNames; + interfacesNames.push_back(iface->getName()); + for (auto function : iface->getFunctions()) + { + for (auto param : function->getParameters().getMembers()) + { + DataType *datatype = param->getDataType()->getTrueDataType(); + if (datatype->isFunction()) + { + FunctionType *funType = dynamic_cast(datatype); + if (funType->getInterface() != iface) + { + interfacesNames.push_back(funType->getInterface()->getName()); + } + if ((std::find(callbackTypesNames.begin(), callbackTypesNames.end(), funType->getName()) == + callbackTypesNames.end())) + { + callbackTypes.push_back(funType); + callbackTypesNames.push_back(funType->getName()); + } + } + } + } + for (auto functionType : iface->getFunctionTypes()) + { + if ((std::find(callbackTypesNames.begin(), callbackTypesNames.end(), functionType->getName()) == + callbackTypesNames.end())) + { + callbackTypes.push_back(functionType); + callbackTypesNames.push_back(functionType->getName()); + } + } + + for (auto functionType : callbackTypes) + { + data_list functionsInt; + data_list functionsExt; + data_list functionsAll; + for (auto fun : functionType->getCallbackFuns()) + { + if ((std::find(interfacesNames.begin(), interfacesNames.end(), fun->getInterface()->getName()) != + interfacesNames.end())) + { + data_map function; + function["name"] = fun->getName(); + if (fun->getInterface() == iface) + { + functionsInt.push_back(function); + } + else + { + functionsExt.push_back(function); + } + functionsAll.push_back(function); + } + } + if (!functionsAll.empty()) + { + data_map callbackType; + callbackType["name"] = functionType->getName(); + callbackType["typenameName"] = getFunctionPrototype(nullptr, functionType); + callbackType["interfaceTypenameName"] = + getFunctionPrototype(nullptr, functionType, iface->getName() + "_interface"); + if (!functionsInt.empty()) + { + callbackType["callbacks"] = functionsInt; + callbackType["callbacksData"] = getFunctionTypeTemplateData(group, functionType); + callbackTypesInt.push_back(callbackType); + } + if (!functionsExt.empty()) + { + callbackType["callbacks"] = functionsExt; + callbackTypesExt.push_back(callbackType); + } + callbackType["callbacks"] = functionsAll; + callbackTypesAll.push_back(callbackType); + } + } +} diff --git a/erpcgen/src/Generator.hpp b/erpcgen/src/Generator.hpp index 4d6c18db..18dfb5a0 100644 --- a/erpcgen/src/Generator.hpp +++ b/erpcgen/src/Generator.hpp @@ -45,10 +45,11 @@ namespace erpcgen { class Generator { public: - enum generator_type_t + enum class generator_type_t { kC, - kPython + kPython, + kJava }; /*!< Type of generator. */ typedef std::vector datatype_vector_t; /*!< Vector of data types. */ @@ -201,12 +202,25 @@ class Generator * * @param[in] group Pointer to a group. * @param[in] fn From this are set interface function template data. - * @param[in] fnIndex Function index. * * @return Contains interface function data. */ virtual cpptempl::data_map getFunctionTemplateData(Group *group, Function *fn) = 0; + /*! + * @brief This function returns function type (callbacks type) template data. + * + * This function returns function type (callbacks type) template data with all data, which + * are necessary for generating output code for output files. Shim code is generating + * common function for serialization/deserialization of data. + * + * @param[in] group Group to which function belongs. + * @param[in] fn From this are set function type template data. + * + * @return Contains interface function data. + */ + virtual cpptempl::data_map getFunctionTypeTemplateData(Group *group, FunctionType *fn) = 0; + /*! * @brief This function will get symbol comments and convert to language specific ones * @@ -238,6 +252,14 @@ class Generator */ virtual void generateOutputFiles(const std::string &fileNameExtension) = 0; + /** + * @brief Function return common fileName part for group generated files. + * + * @param group Pointer to a group. + * @return string Common filename part of group generated files. + */ + std::string getGroupCommonFileName(Group *group); + /*! * @brief This function generates output files for defined interfaces. * @@ -347,6 +369,20 @@ class Generator */ datatype_vector_t getDataTypesFromSymbolScope(SymbolScope *scope, DataType::data_type_t datatype); + /*! + * @brief This function return interface function prototype. + * + * @param[in] group Group to which function belongs. + * @param[in] fn Function for prototyping. + * @param[in] interfaceName Interface name used for function declaration. + * @param[in] name Name used for shared code in case of function type. + * @param[in] insideInterfaceCall interfaceClass specific. + * + * @return String prototype representation for given function. + */ + virtual std::string getFunctionPrototype(Group *group, FunctionBase *fn, const std::string &interfaceName = "", + const std::string &name = "", bool insideInterfaceCall = false) = 0; + private: /*! * @brief This function return interface functions list. @@ -359,6 +395,18 @@ class Generator * @return Contains interface functions data. */ cpptempl::data_list getFunctionsTemplateData(Group *group, Interface *iface); + + /*! + * @brief Get the Callbacks template data and dived them to the interface scope list. + * + * @param[in] group Group to which callbacks belongs. + * @param[in] iface Use callbacks belongs to this interface. + * @param[out] callbackTypesInt Template data for current interface scope callbacks + * @param[out] callbackTypesExt Template data for others interface scope callbacks + * @param[out] callbackTypesAll Template data of all callbacks. + */ + void getCallbacksTemplateData(Group *group, const Interface *iface, cpptempl::data_list &callbackTypesInt, + cpptempl::data_list &callbackTypesExt, cpptempl::data_list &callbackTypesAll); }; } // namespace erpcgen diff --git a/erpcgen/src/InterfaceDefinition.cpp b/erpcgen/src/InterfaceDefinition.cpp index 7d1e268a..3f47e58e 100644 --- a/erpcgen/src/InterfaceDefinition.cpp +++ b/erpcgen/src/InterfaceDefinition.cpp @@ -27,14 +27,9 @@ using namespace std; // Code //////////////////////////////////////////////////////////////////////////////// -InterfaceDefinition::InterfaceDefinition() -: m_ast(nullptr) -, m_globals() -, m_program(nullptr) -, m_programName("") -, m_outputFilename("") -, m_codec(kNotSpecified) -, m_idlCrc16(0) +InterfaceDefinition::InterfaceDefinition() : +m_ast(nullptr), m_globals(), m_program(nullptr), m_programName(""), m_outputFilename(""), +m_codec(codec_t::kNotSpecified), m_idlCrc16(0) { init(); } @@ -73,20 +68,20 @@ void InterfaceDefinition::parse(const char *inputFile) void InterfaceDefinition::createBuiltinTypes() { - m_globals.addSymbol(new BuiltinType("bool", BuiltinType::_builtin_type::kBoolType)); - m_globals.addSymbol(new BuiltinType("int8", BuiltinType::_builtin_type::kInt8Type)); - m_globals.addSymbol(new BuiltinType("int16", BuiltinType::_builtin_type::kInt16Type)); - m_globals.addSymbol(new BuiltinType("int32", BuiltinType::_builtin_type::kInt32Type)); - m_globals.addSymbol(new BuiltinType("int64", BuiltinType::_builtin_type::kInt64Type)); - m_globals.addSymbol(new BuiltinType("uint8", BuiltinType::_builtin_type::kUInt8Type)); - m_globals.addSymbol(new BuiltinType("uint16", BuiltinType::_builtin_type::kUInt16Type)); - m_globals.addSymbol(new BuiltinType("uint32", BuiltinType::_builtin_type::kUInt32Type)); - m_globals.addSymbol(new BuiltinType("uint64", BuiltinType::_builtin_type::kUInt64Type)); - m_globals.addSymbol(new BuiltinType("float", BuiltinType::_builtin_type::kFloatType)); - m_globals.addSymbol(new BuiltinType("double", BuiltinType::_builtin_type::kDoubleType)); - m_globals.addSymbol(new BuiltinType("string", BuiltinType::_builtin_type::kStringType)); - m_globals.addSymbol(new BuiltinType("ustring", BuiltinType::_builtin_type::kUStringType)); - m_globals.addSymbol(new BuiltinType("binary", BuiltinType::_builtin_type::kBinaryType)); + m_globals.addSymbol(new BuiltinType("bool", BuiltinType::builtin_type_t::kBoolType)); + m_globals.addSymbol(new BuiltinType("int8", BuiltinType::builtin_type_t::kInt8Type)); + m_globals.addSymbol(new BuiltinType("int16", BuiltinType::builtin_type_t::kInt16Type)); + m_globals.addSymbol(new BuiltinType("int32", BuiltinType::builtin_type_t::kInt32Type)); + m_globals.addSymbol(new BuiltinType("int64", BuiltinType::builtin_type_t::kInt64Type)); + m_globals.addSymbol(new BuiltinType("uint8", BuiltinType::builtin_type_t::kUInt8Type)); + m_globals.addSymbol(new BuiltinType("uint16", BuiltinType::builtin_type_t::kUInt16Type)); + m_globals.addSymbol(new BuiltinType("uint32", BuiltinType::builtin_type_t::kUInt32Type)); + m_globals.addSymbol(new BuiltinType("uint64", BuiltinType::builtin_type_t::kUInt64Type)); + m_globals.addSymbol(new BuiltinType("float", BuiltinType::builtin_type_t::kFloatType)); + m_globals.addSymbol(new BuiltinType("double", BuiltinType::builtin_type_t::kDoubleType)); + m_globals.addSymbol(new BuiltinType("string", BuiltinType::builtin_type_t::kStringType)); + m_globals.addSymbol(new BuiltinType("ustring", BuiltinType::builtin_type_t::kUStringType)); + m_globals.addSymbol(new BuiltinType("binary", BuiltinType::builtin_type_t::kBinaryType)); } void InterfaceDefinition::setProgramInfo(const string &filename, const string &outputDir, codec_t codec) diff --git a/erpcgen/src/InterfaceDefinition.hpp b/erpcgen/src/InterfaceDefinition.hpp index d4696550..2431aace 100644 --- a/erpcgen/src/InterfaceDefinition.hpp +++ b/erpcgen/src/InterfaceDefinition.hpp @@ -31,7 +31,7 @@ namespace erpcgen { class InterfaceDefinition { public: - enum codec_t + enum class codec_t { kNotSpecified, kBasicCodec, diff --git a/erpcgen/src/JavaGenerator.cpp b/erpcgen/src/JavaGenerator.cpp new file mode 100644 index 00000000..76d20063 --- /dev/null +++ b/erpcgen/src/JavaGenerator.cpp @@ -0,0 +1,1359 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "JavaGenerator.hpp" + +#include "Logging.hpp" +#include "ParseErrors.hpp" +#include "annotations.h" +#include "format_string.hpp" + +#include +#include +#include +#include +#include + +using namespace erpcgen; +using namespace cpptempl; +using namespace std; + +// Templates strings converted from text files by txt_to_c.py. +extern const char *const kJavaCoders; +extern const char *const kJavaEnum; +extern const char *const kJavaStruct; +extern const char *const kJavaServer; +extern const char *const kJavaClient; +extern const char *const kJavaConst; +extern const char *const kJavaInterface; + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +JavaGenerator::JavaGenerator(InterfaceDefinition *def, const std::string javaPackageName) +: Generator(def, generator_type_t::kJava) +, m_javaPackageName(javaPackageName) +, m_suffixStrip("") +, m_suffixStripSize(0) +{ + /* Set copyright rules. */ + if (m_def->hasProgramSymbol()) + { + Symbol *program = m_def->getProgramSymbol(); + assert(program); + setTemplateComments(program, m_templateData); + } +} + +void JavaGenerator::generateOutputFiles(const string &fileName) +{ + // Make sure the package folder is created. + filesystem::path dir(fileName); + dir = m_outputDirectory / dir; + filesystem::create_directories(dir); + + generateCommonFile(fileName); + generateClientFile(fileName); + generateServerFile(fileName); + generateInterfaceFile(fileName); +} + +void JavaGenerator::generateCommonFile(string fileName) +{ + generateEnumFiles(fileName); + generateStructFiles(fileName); + generateConstFile(fileName); +} + +void JavaGenerator::generateConstFile(string fileName) +{ + fileName += "/common/"; + + filesystem::path dir(fileName); + dir = m_outputDirectory / dir; + filesystem::create_directories(dir); + + std::string classFilename = fileName + "/Constants.java"; + generateOutputFile(classFilename, "java_const", m_templateData, kJavaConst); +} + +void JavaGenerator::generateClientFile(string fileName) +{ + data_map &map = m_templateData["group"].get().get()->getmap(); + data_list &list = map["interfaces"]->getlist(); + fileName += "/client"; + + filesystem::path dir(fileName); + dir = m_outputDirectory / dir; + filesystem::create_directories(dir); + + for (data_ptr interface : list) + { + std::string name = interface.get().get()->getmap()["name"].get().get()->getvalue(); + m_templateData["interface"] = interface; + std::string classFilename = fileName + "/" + name + "Client.java"; + generateOutputFile(classFilename, "java_client", m_templateData, kJavaClient); + } +} + +void JavaGenerator::generateServerFile(string fileName) +{ + data_map &map = m_templateData["group"].get().get()->getmap(); + data_list &list = map["interfaces"]->getlist(); + fileName += "/server"; + + filesystem::path dir(fileName); + dir = m_outputDirectory / dir; + filesystem::create_directories(dir); + + for (data_ptr interface : list) + { + std::string name = interface.get().get()->getmap()["name"].get().get()->getvalue(); + m_templateData["interface"] = interface; + std::string classFilename = fileName + "/Abstract" + name + "Service.java"; + generateOutputFile(classFilename, "java_server", m_templateData, kJavaServer); + } +} + +void JavaGenerator::generateInterfaceFile(string fileName) +{ + data_map &map = m_templateData["group"].get().get()->getmap(); + data_list &list = map["interfaces"]->getlist(); + fileName += "/interfaces"; + + filesystem::path dir(fileName); + dir = m_outputDirectory / dir; + filesystem::create_directories(dir); + + for (data_ptr interface : list) + { + std::string name = interface.get().get()->getmap()["name"].get().get()->getvalue(); + m_templateData["interface"] = interface; + std::string classFilename = fileName + "/I" + name + ".java"; + generateOutputFile(classFilename, "java_interface", m_templateData, kJavaInterface); + } +} + +void erpcgen::JavaGenerator::generateEnumFiles(std::string fileName) +{ + data_list &list = m_templateData["enums"]->getlist(); + fileName += "/common/enums"; + + filesystem::path dir(fileName); + dir = m_outputDirectory / dir; + filesystem::create_directories(dir); + + for (data_ptr item : list) + { + std::string name = item.get().get()->getmap()["name"].get().get()->getvalue(); + + if (name.empty()) + { + name = "ConstantEnum"; // TODO: Create in ./common + item.get().get()->getmap()["name"] = make_data("ConstantEnum"); + } + + m_templateData["enum"] = item; + std::string classFilename = fileName + "/" + name + ".java"; + generateOutputFile(classFilename, "java_enum", m_templateData, kJavaEnum); + } +} + +void erpcgen::JavaGenerator::generateStructFiles(std::string fileName) +{ + data_list &list = m_templateData.parse_path("group.symbolsMap.structs").get().get()->getlist(); + fileName += "/common/structs"; + + filesystem::path dir(fileName); + dir = m_outputDirectory / dir; + filesystem::create_directories(dir); + + for (data_ptr item : list) + { + std::string name = item.get().get()->getmap()["name"].get().get()->getvalue(); + + m_templateData["struct"] = item; + // dump_data(item); + std::string classFilename = fileName + "/" + name + ".java"; + generateOutputFile(classFilename, "java_struct", m_templateData, kJavaStruct); + } +} + +void JavaGenerator::parseSubtemplates() +{ + const char *templateName = "java_coders"; + try + { + parse(kJavaCoders, m_templateData); + } + catch (TemplateException &e) + { + throw TemplateException(format_string("Template %s: %s", templateName, e.what())); + } +} + +void JavaGenerator::generate() +{ + data_list empty; + m_templateData["enums"] = empty; + m_templateData["aliases"] = empty; + m_templateData["structs"] = empty; + m_templateData["unions"] = empty; + m_templateData["consts"] = empty; + m_templateData["appPackage"] = make_data(m_javaPackageName); + + parseSubtemplates(); + + if (m_def->hasProgramSymbol()) + { + for (Annotation *anno : getAnnotations(m_def->getProgramSymbol(), PY_TYPES_NAME_STRIP_SUFFIX_ANNOTATION)) + { + m_suffixStrip = anno->getValueObject()->toString(); + m_suffixStripSize = m_suffixStrip.size(); + } + } + + findGroupDataTypes(); + + makeIncludesTemplateData(); + + // makeAliasesTemplateData(); + + makeConstTemplateData(); + + makeEnumsTemplateData(); + + makeFunctionsTemplateData(); + + for (Group *group : m_groups) + { + data_map groupTemplate; + groupTemplate["name"] = group->getName(); + groupTemplate["includes"] = makeGroupIncludesTemplateData(group); + groupTemplate["symbolsMap"] = makeGroupSymbolsTemplateData(group); + groupTemplate["interfaces"] = makeGroupInterfacesTemplateData(group); + group->setTemplate(groupTemplate); + m_templateData["groupPackage"] = getGroupPackageName(group); + generateGroupOutputFiles(group); + } +} + +void JavaGenerator::setTemplateComments(Symbol *symbol, data_map &symbolInfo) +{ + symbolInfo["mlComment"] = symbol->getMlComment(); + symbolInfo["ilComment"] = symbol->getIlComment(); +} + +data_map JavaGenerator::getFunctionTemplateData(Group *group, Function *fn) +{ + (void)group; + data_map info; + string proto = getFunctionPrototype(nullptr, fn); + + info["name"] = getOutputName(fn); + info["prototype"] = proto; + info["id"] = fn->getUniqueId(); + info["isOneway"] = fn->isOneway(); + info["isReturnValue"] = !fn->isOneway(); + setTemplateComments(fn, info); + + /* Is function declared as external? */ + info["isNonExternalFunction"] = findAnnotation(fn, EXTERNAL_ANNOTATION) == nullptr; + + // Get return value info + data_map returnInfo; + DataType *returnDataType = fn->getReturnType()->getTrueDataType(); + returnInfo["type"] = getTypeInfo(returnDataType, false); + if (!returnDataType->isVoid()) + { + returnInfo["call"] = getEncodeDecodeCall("_result", returnDataType, nullptr, false, false, + fn->getReturnStructMemberType(), true, false); + } + // TODO support annotations on function return values + // returnInfo["isNullable"] = (fn->getReturnType()->findAnnotation(NULLABLE_ANNOTATION) != nullptr); + info["returnValue"] = returnInfo; + + // get function parameter info + auto fnParams = fn->getParameters().getMembers(); + data_list params; + data_list inParams; + data_list outParams; + for (StructMember *param : fnParams) + { + data_map paramInfo; + DataType *paramType = param->getDataType(); + DataType *trueDataType = paramType->getTrueDataType(); + string name = getOutputName(param); + paramInfo["name"] = name; + paramInfo["type"] = getTypeInfo(paramType, false); + + bool isNullable = ((findAnnotation(param, NULLABLE_ANNOTATION) != nullptr) && + (trueDataType->isString() || (!trueDataType->isBuiltin() && !trueDataType->isEnum()))); + paramInfo["isNullable"] = isNullable; + + paramInfo["call"] = getEncodeDecodeCall(name, trueDataType, nullptr, false, false, param, false, true); + + // Skip data serialization for variables placed as @length value for lists. + // These prevent to serialized data twice. + StructMember *referencedFrom = findParamReferencedFromAnn(fnParams, name, LENGTH_ANNOTATION); + paramInfo["discriminatorForMember"] = ""; + + if (referencedFrom) + { + paramInfo["lengthForMember"] = getOutputName(referencedFrom); + } + else + { + paramInfo["lengthForMember"] = ""; + // Skip data serialization for variables used as discriminator for unions. + // These prevent to serialized data twice. + referencedFrom = findParamReferencedFromUnion(fnParams, name); + if (referencedFrom) + { + paramInfo["discriminatorForMember"] = getOutputName(referencedFrom); + } + } + + paramInfo["serializedViaMember"] = (referencedFrom) ? getOutputName(referencedFrom) : ""; + + /* Necessary for handling non-discriminated unions */ + paramInfo["discriminator"] = getAnnStringValue(param, DISCRIMINATOR_ANNOTATION); + + param_direction_t dir = param->getDirection(); + switch (dir) + { + case param_direction_t::kInDirection: + paramInfo["direction"] = "in"; + inParams.push_back(paramInfo); + break; + case param_direction_t::kOutDirection: + paramInfo["direction"] = "out"; + outParams.push_back(paramInfo); + break; + case param_direction_t::kInoutDirection: + paramInfo["direction"] = "inout"; + inParams.push_back(paramInfo); + outParams.push_back(paramInfo); + break; + default: + paramInfo["direction"] = "none"; + } + + params.push_back(paramInfo); + } + + info["parameters"] = params; + info["inParameters"] = inParams; + info["outParameters"] = outParams; + + return info; +} + +string JavaGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const string &interfaceName, + const string &name, bool insideInterfaceCall) +{ + FunctionType *functionType = dynamic_cast(fn); + if (functionType) + { + return ""; /*Todo: implement*/ + } + Function *function = dynamic_cast(fn); + + assert(function); + + DataType *dataTypeReturn = fn->getReturnType(); + string proto; + + proto = getTypenameName(dataTypeReturn, false, false) + " "; + proto += getOutputName(function); + + bool isFirst = true; + + proto += "("; + + auto params = function->getParameters().getMembers(); + if (params.size()) + { + for (auto it : params) + { + string paramSignature = getOutputName(it); + + // Skip data serialization for variables placed as @length value for lists. + if (findParamReferencedFromAnn(params, getOutputName(it), LENGTH_ANNOTATION)) + { + continue; + } + + if (!isFirst) + { + proto += ", "; + + } + else + { + isFirst = false; + } + + if (it->getDirection() == param_direction_t::kOutDirection || it->getDirection() == param_direction_t::kInoutDirection) + { + proto += getTypenameName(it->getDataType(), true, true); + } + else + { + proto += getTypenameName(it->getDataType(), false, false); + } + + proto += " "; + proto += getOutputName(it); + } + } + proto += ")"; + return proto; +} + +string JavaGenerator::getTypenameName(DataType *t, bool isReference, bool objectType) +{ + string returnName; + + + + switch (t->getDataType()) + { + case DataType::data_type_t::kArrayType: { + ArrayType *a = dynamic_cast(t); + assert(a); + returnName = getTypenameName(a->getElementType(), false, false) + "[]"; + break; + } + case DataType::data_type_t::kBuiltinType: { + assert(nullptr != dynamic_cast(t)); + if (objectType) + { + returnName = getBuiltinObjectTypename(dynamic_cast(t)); + } + else + { + returnName = getBuiltinTypename(dynamic_cast(t)); + } + + break; + } + case DataType::data_type_t::kListType: { + const ListType *a = dynamic_cast(t); + assert(a); + returnName = "List<" + getTypenameName(a->getElementType(), false, true) + ">"; + break; + } + case DataType::data_type_t::kAliasType: { + AliasType *aliasType = dynamic_cast(t); + return getTypenameName(aliasType->getTrueDataType(), isReference, objectType); + } + case DataType::data_type_t::kVoidType: { + returnName = "void"; + break; + } + case DataType::data_type_t::kUnionType: + case DataType::data_type_t::kEnumType: + case DataType::data_type_t::kStructType: { + returnName = getOutputName(t); + break; + } + default: + throw internal_error(format_string("In getTypenameName: unknown data type: %s value:%d", + t->getName().c_str(), t->getDataType())); + } + + if (isReference) + { + returnName = "Reference<" + returnName + ">"; + } + return returnName; +} + +string JavaGenerator::getArrayInitialization(ArrayType *t) +{ + string result = ""; + + DataType *current = dynamic_cast(t); + while (current->isArray()) + { + ArrayType *arrayType = dynamic_cast(current); + result += format_string("[%d]", arrayType->getElementCount()); + current = arrayType->getElementType(); + } + + if (current->getDataType() == DataType::data_type_t::kListType) + { + result = "List" + result; // Java does not support typed arrays e.g. List. Use untyped List[]. + } + else + { + result = getTypenameName(t->getTrueContainerDataType(), false, false) + result; + } + + result = "new " + result; + + return result; +} + +void JavaGenerator::makeConstTemplateData() +{ + Log::info("Constant globals:\n"); + data_list consts; + for (auto it : m_globals->getSymbolsOfType(Symbol::symbol_type_t::kConstSymbol)) + { + ConstType *constVar = dynamic_cast(it); + assert(constVar); + data_map constInfo; + if (!findAnnotation(constVar, EXTERNAL_ANNOTATION)) + { + constInfo["name"] = getOutputName(constVar); + constInfo["type"] = getTypeInfo(constVar->getDataType(), false, false); + // throw nullptr exception + if (NULL == constVar->getValue()) + { + Log::info("const pointing to null Value object\n"); + } + if (kStringValue == constVar->getValue()->getType()) + { + constInfo["value"] = "\"" + constVar->getValue()->toString() + "\""; + } + else + { + constInfo["value"] = constVar->getValue()->toString(); + } + setTemplateComments(constVar, constInfo); + Log::info("Name=%s\tType=%s\tValue=%s\n", constVar->getName().c_str(), + constVar->getDataType()->getName().c_str(), constVar->getValue()->toString().c_str()); + consts.push_back(constInfo); + } + } + m_templateData["consts"] = consts; +} + +void JavaGenerator::makeEnumsTemplateData() +{ + Log::info("Enums:\n"); + data_list enums; + int n = 0; + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kEnumType)) + { + EnumType *enumType = dynamic_cast(it); + assert(enumType); + if (!findAnnotation(enumType, EXTERNAL_ANNOTATION)) + { + Log::info("%d: %s\n", n, enumType->getName().c_str()); + data_map enumInfo; + enumInfo["name"] = filterName(getOutputName(enumType)); + enumInfo["members"] = getEnumMembersTemplateData(enumType); + setTemplateComments(enumType, enumInfo); + enums.push_back(enumInfo); + ++n; + } + } + m_templateData["enums"] = enums; +} + +data_list JavaGenerator::getEnumMembersTemplateData(EnumType *enumType) +{ + int j = 0; + data_list enumMembersList; + for (auto member : enumType->getMembers()) + { + assert(member->hasValue()); + data_map enumMember; + enumMember["name"] = getOutputName(member); + enumMember["value"] = member->getValue(); + Log::info(" %d: %s = %d\n", j, member->getName().c_str(), member->getValue()); + setTemplateComments(member, enumMember); + enumMembersList.push_back(enumMember); + ++j; + } + return enumMembersList; +} + +void JavaGenerator::makeAliasesTemplateData() +{ + Log::info("Type definition:\n"); + data_list aliases; + int n = 0; + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kAliasType)) + { + AliasType *aliasType = dynamic_cast(it); + assert(aliasType); + // Annotation *externAnnotation = aliasType->findAnnotation(EXTERNAL_ANNOTATION); + // if (!externAnnotation) + // { + Log::info("%d: ", n); + data_map aliasInfo; + DataType *elementDataType = aliasType->getElementType(); + DataType *trueDataType = elementDataType->getTrueDataType(); + + // Only generate aliases for enums, unions and structs in Python. + if (!(trueDataType->isEnum() || trueDataType->isUnion() || trueDataType->isStruct())) + { + continue; + } + + string realType = getOutputName(aliasType); + Log::info("%s\n", realType.c_str()); + + aliasInfo["name"] = filterName(realType); + aliasInfo["elementType"] = getTypeInfo(elementDataType, false); + aliasInfo["trueType"] = getTypeInfo(trueDataType, false); + + setTemplateComments(aliasType, aliasInfo); + + aliases.push_back(aliasInfo); + ++n; + // } + } + m_templateData["aliases"] = aliases; +} + +data_map JavaGenerator::makeGroupSymbolsTemplateData(Group *group) +{ + data_map symbolsTemplate; + set names; + + data_list structs; + data_list unions; + data_list aliases; + + Log::info("Group symbols:\n"); + + // generate templates for group symbols or for all symbols if group has no interface defined + for (Symbol *symbol : (group->getInterfaces().empty() ? m_globals->getSymbolVector() : group->getSymbols())) + { + data_map info; + + if (symbol->isDatatypeSymbol()) + { + DataType *dataType = dynamic_cast(symbol); + assert(dataType); + + switch (dataType->getDataType()) + { + case DataType::data_type_t::kStructType: { + StructType *structType = dynamic_cast(symbol); + if (structType == nullptr) + { + break; + } + + Log::info("%s\n", structType->getDescription().c_str()); + + string name = filterName(getOutputName(structType)); + + // check if template for this structure has not already been generated + if (names.find(name) == names.end()) + { + info["name"] = name; + + setTemplateComments(structType, info); + setStructMembersTemplateData(structType, info); + + names.insert(name); + structs.push_back(info); + } + break; + } + case DataType::data_type_t::kUnionType: { + UnionType *unionType = dynamic_cast(symbol); + if (unionType == nullptr) + { + break; + } + + Log::info("%s\n", unionType->getDescription().c_str()); + + string name = filterName(getOutputName(unionType)); + if (name.find('$') != string::npos) + { + Log::debug("%s is inside struct!\n", name.c_str()); + break; + } + + // check if template for this structure has not already been generated + if (names.find(name) == names.end()) + { + info["name"] = name; + info["type"] = getTypeInfo(unionType, false); + + setTemplateComments(unionType, info); + // setUnionMembersTemplateData(unionType, info); + + names.insert(name); + unions.push_back(info); + } + break; + } + case DataType::data_type_t::kAliasType: { + AliasType *aliasType = dynamic_cast(symbol); + if (aliasType == nullptr) + break; + + DataType *elementDataType = aliasType->getElementType(); + DataType *trueDataType = elementDataType->getTrueDataType(); + // Only generate aliases for enums, unions and structs in Python. + if (!(trueDataType->isEnum() || trueDataType->isUnion() || trueDataType->isStruct())) + break; + + string realType = getOutputName(aliasType); + Log::debug("%s\n", realType.c_str()); + + info["name"] = filterName(realType); + info["elementType"] = getTypeInfo(elementDataType, false); + info["trueType"] = getTypeInfo(trueDataType, false); + + setTemplateComments(aliasType, info); + + aliases.push_back(info); + break; + } + default: + break; + } + } + } + + symbolsTemplate["structs"] = structs; + symbolsTemplate["unions"] = unions; + symbolsTemplate["aliases"] = aliases; + + return symbolsTemplate; +} + +void JavaGenerator::setStructMembersTemplateData(StructType *structType, data_map &structInfo) +{ + data_list members; + for (auto member : structType->getMembers()) + { + data_map member_info; + + // Skip data serialization for variables placed as @length value for lists. + // These prevent to serialized data twice. + StructMember *referencedFrom = + findParamReferencedFromAnn(structType->getMembers(), member->getName(), LENGTH_ANNOTATION); + + member_info["discriminatorForMember"] = ""; + if (referencedFrom) + { + member_info["lengthForMember"] = getOutputName(referencedFrom); + } + else + { + member_info["lengthForMember"] = ""; + // Skip data serialization for variables used as discriminator for unions. + // These prevent to serialized data twice. + referencedFrom = findParamReferencedFromUnion(structType->getMembers(), member->getName()); + if (referencedFrom) + { + member_info["discriminatorForMember"] = getOutputName(referencedFrom); + } + } + + member_info["serializedViaMember"] = (referencedFrom) ? getOutputName(referencedFrom) : ""; + setOneStructMemberTemplateData(member, member_info); + members.push_back(member_info); + } + structInfo["members"] = members; +} + +void JavaGenerator::setOneStructMemberTemplateData(StructMember *member, data_map &member_info) +{ + string memberName = getOutputName(member); + bool needTempVariable = false; + + DataType *trueDataType = member->getDataType()->getTrueDataType(); + + // Info for declaring struct in common header + member_info["name"] = memberName; + bool isNullable = ((findAnnotation(member, NULLABLE_ANNOTATION) != nullptr) && + (trueDataType->isBinary() || trueDataType->isString() || trueDataType->isList())); + member_info["isNullable"] = isNullable; + member_info["call"] = + getEncodeDecodeCall(memberName, trueDataType, nullptr, true, true, member, needTempVariable, false); + // member_info["type"] = getTypeInfo(member->getDataType()); + /* Necessary for handling non-discriminated unions */ + member_info["discriminator"] = getAnnStringValue(member, DISCRIMINATOR_ANNOTATION); + + setTemplateComments(member, member_info); +} + +data_map JavaGenerator::getEncodeDecodeCall(const string &name, DataType *t, StructType *structType, + bool inDataContainer, bool isStructMember, StructMember *structMember, + bool needTypeDeclaration, bool isFunctionParam) +{ + static uint8_t listArrayCounter; // Used for creating nested loops variable names + data_map templateData; + bool isReference = (isStructMember && structMember->isByref()) || + (isFunctionParam && (structMember->getDirection() == param_direction_t::kOutDirection || + structMember->getDirection() == param_direction_t::kInoutDirection)); + templateData["type"] = getTypeInfo(t, isReference); // Type info about variable + templateData["inDataContainer"] = inDataContainer; + templateData["name"] = name; // Name of the variable + templateData["isStructMember"] = isStructMember; // If variable is part of struct + templateData["needTypeDeclaration"] = needTypeDeclaration; // Variable does not exist in the scope + templateData["isFunctionParam"] = isFunctionParam; + templateData["isReference"] = isReference; + + switch (t->getDataType()) + { + case DataType::data_type_t::kAliasType: { + AliasType *aliasType = dynamic_cast(t); + assert(aliasType); + templateData = getEncodeDecodeCall(name, aliasType->getElementType(), structType, inDataContainer, false, + structMember, true, false); + break; + } + case DataType::data_type_t::kArrayType: { + ArrayType *arrayType = dynamic_cast(t); + assert(arrayType); + DataType *elementType = arrayType->getElementType()->getTrueDataType(); + + string arrayName = name; + templateData["decode"] = m_templateData["decodeArrayType"]; + templateData["encode"] = m_templateData["encodeArrayType"]; + + templateData["initialization"] = getArrayInitialization(arrayType); + + listArrayCounter++; + templateData["counter"] = format_string("genLoopVariable%d", listArrayCounter); + templateData["protoNext"] = + getEncodeDecodeCall(format_string("genValueVariable%d", listArrayCounter), elementType, structType, + true, false, structMember, true, false); + listArrayCounter--; + + templateData["size"] = format_string("%d", arrayType->getElementCount()); + templateData["isElementArrayType"] = elementType->isArray(); + break; + } + case DataType::data_type_t::kBuiltinType: { + templateData["decode"] = m_templateData["decodeBuiltinType"]; + templateData["encode"] = m_templateData["encodeBuiltinType"]; + break; + } + case DataType::data_type_t::kEnumType: { + templateData["decode"] = m_templateData["decodeEnumType"]; + templateData["encode"] = m_templateData["encodeEnumType"]; + break; + } + case DataType::data_type_t::kFunctionType: { + throw internal_error("Java does not support functions yet."); + } + case DataType::data_type_t::kListType: { + ListType *listType = dynamic_cast(t); + assert(listType); + DataType *elementType = listType->getElementType()->getTrueDataType(); + + templateData["decode"] = m_templateData["decodeListType"]; + templateData["encode"] = m_templateData["encodeListType"]; + + string nextName; + + listArrayCounter++; + templateData["counter"] = format_string("getLoopVariable%d", listArrayCounter); + templateData["protoNext"] = + getEncodeDecodeCall(format_string("genValueVariable%d", listArrayCounter), elementType, structType, + true, false, structMember, true, false); + listArrayCounter--; + + if (listType->hasLengthVariable()) + { + templateData["hasLengthVariable"] = true; + Symbol *symbol = m_globals->getSymbol(listType->getLengthVariableName()); + if (symbol) + { + ConstType *constType = dynamic_cast(symbol); + assert(constType); + templateData["size"] = constType->getValue()->toString(); + } + else + { + templateData["size"] = listType->getLengthVariableName(); + } + } + else + { + templateData["hasLengthVariable"] = false; + } + + templateData["sizeVariable"] = + isStructMember || isFunctionParam ? + format_string("i%s", capitalize(name).c_str()) : + format_string("genSizeVariable%d", listArrayCounter); // TODO: Const or size variable name + + break; + } + case DataType::data_type_t::kStructType: { + templateData["decode"] = m_templateData["decodeStructType"]; + templateData["encode"] = m_templateData["encodeStructType"]; + break; + } + case DataType::data_type_t::kUnionType: { + break; + } + default: { + throw internal_error("unknown member type"); + } + } + + return templateData; +} + +string JavaGenerator::capitalize(string text) +{ + text[0] = toupper(text[0]); + return text; +} + +void JavaGenerator::makeFunctionsTemplateData() +{ + /* type definitions of functions and table of functions */ + Log::info("Functions:\n"); + data_list functions; + for (Symbol *functionTypeSymbol : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kFunctionType)) + { + FunctionType *functionType = dynamic_cast(functionTypeSymbol); + data_map functionInfo; + + /* Table template data. */ + data_list callbacks; + for (Function *fun : functionType->getCallbackFuns()) + { + data_map callbacksInfo; + callbacksInfo["name"] = fun->getName(); + callbacks.push_back(callbacksInfo); + } + functionInfo["callbacks"] = callbacks; + functionInfo["name"] = functionType->getName(); + /* Function type name. */ + functions.push_back(functionInfo); + } + m_templateData["functions"] = functions; +} + +data_map JavaGenerator::getTypeInfo(DataType *t, int isReference, bool inDataContainer) +{ + data_map info; + std::string name = filterName(getOutputName(t, false)); + info["name"] = name; + info["typeName"] = getTypenameName(t, isReference, isReference); // Java type: Float, List, ... + + info["isNonEncapsulatedUnion"] = false; + switch (t->getDataType()) + { + case DataType::data_type_t::kAliasType: { + info = getTypeInfo(t->getTrueDataType(), false); + break; + } + case DataType::data_type_t::kArrayType: { + // Array type requires the array element count to come after the variable/member name. + info["type"] = "array"; + break; + } + case DataType::data_type_t::kBuiltinType: { + assert(dynamic_cast(t)); + info["type"] = getBuiltinTypename(dynamic_cast(t)); + info["codecTypeName"] = getBuiltinCodecTypeName(dynamic_cast(t)); + break; + } + case DataType::data_type_t::kEnumType: { + info["type"] = "enum"; + break; + } + case DataType::data_type_t::kFunctionType: { + info["type"] = "function"; + break; + } + case DataType::data_type_t::kListType: { + info["type"] = "list"; + break; + } + case DataType::data_type_t::kStructType: { + info["type"] = "struct"; + info["decode"] = m_templateData["decodeStructType"]; + info["encode"] = m_templateData["encodeStructType"]; + break; + } + case DataType::data_type_t::kUnionType: { + UnionType *unionType = dynamic_cast(t); + assert(unionType); + info["type"] = "union"; + info["encode"] = m_templateData["decodeUnionType"]; + info["decode"] = m_templateData["encodeUnionType"]; + + // Different request for encapsulated and nonencapsulated unions + if (unionType->isNonEncapsulatedUnion()) + { + info["isNonEncapsulatedUnion"] = true; + info["discriminatorName"] = "discriminator"; + } + else + { + // Set discriminator field name. + string discriminatorName = unionType->getDiscriminatorName(); + info["discriminatorName"] = discriminatorName; + + // Fill in discriminator type info. + Symbol *discriminatorSym = unionType->getParentStruct()->getScope().getSymbol(discriminatorName); + if (!discriminatorSym) + { + throw semantic_error( + format_string("unable to find union discriminator '%s' in struct", discriminatorName.c_str())); + } + StructMember *discriminatorMember = dynamic_cast(discriminatorSym); + if (!discriminatorMember) + { + throw internal_error(format_string("union discriminator is not a struct member")); + } + info["discriminatorType"] = getTypeInfo(discriminatorMember->getDataType(), false); + } + + data_list unionCases; + for (auto unionCase : unionType->getCases()) + { + data_map caseData; + caseData["name"] = unionCase->getCaseName(); + caseData["value"] = unionCase->getCaseValue(); + if (info.has("discriminatorType") && + (info["discriminatorType"].get().get()->getmap()["type"]->getvalue() == "enum")) + { + caseData["type"] = info["discriminatorType"]; + } + else if (unionCase->getCaseName() != "") + { + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kEnumType)) + { + EnumType *enumType = dynamic_cast(it); + assert(enumType); + for (auto itMember : enumType->getMembers()) + { + if (unionCase->getCaseName() == itMember->getName()) + { + data_map typeInfo; + typeInfo["name"] = enumType->getName(); + typeInfo["type"] = "enum"; + caseData["type"] = typeInfo; + break; + } + } + if (caseData.has("type")) + { + break; + } + } + if (!caseData.has("type")) + { + for (auto it : m_globals->getSymbolsOfType(DataType::symbol_type_t::kConstSymbol)) + { + ConstType *constType = dynamic_cast(it); + assert(constType); + if (unionCase->getCaseName() == constType->getName()) + { + data_map typeInfo; + typeInfo["name"] = ""; + typeInfo["type"] = "const"; + caseData["type"] = typeInfo; + break; + } + } + } + } + else + { + data_map typeInfo; + typeInfo["name"] = ""; + typeInfo["type"] = ""; + caseData["type"] = typeInfo; + } + data_list caseMembers; + data_map caseMembersFree; + + if (unionCase->caseMemberIsVoid()) + { + caseData["isVoid"] = true; + caseData["members"] = data_list(); + } + else + { + caseData["isVoid"] = false; + + // Fill in info for each case member declaration + for (auto caseMemberName : unionCase->getMemberDeclarationNames()) + { + data_map memberData; + StructMember *member = unionCase->getUnionMemberDeclaration(caseMemberName); + setOneStructMemberTemplateData(member, memberData); + + caseMembers.push_back(memberData); + } + + caseData["members"] = caseMembers; + } + + unionCases.push_back(caseData); + } + info["cases"] = unionCases; + break; + } + case DataType::data_type_t::kVoidType: { + info["type"] = "void"; + break; + } + default: + throw internal_error("unknown data type"); + } + return info; +} + +string JavaGenerator::getBuiltinCodecTypeName(const BuiltinType *t) +{ + switch (t->getBuiltinType()) + { + case BuiltinType::builtin_type_t::kBoolType: + return "Bool"; + case BuiltinType::builtin_type_t::kInt8Type: + return "Int8"; + case BuiltinType::builtin_type_t::kInt16Type: + return "Int16"; + case BuiltinType::builtin_type_t::kInt32Type: + return "Int32"; + case BuiltinType::builtin_type_t::kInt64Type: + return "Int64"; + case BuiltinType::builtin_type_t::kUInt8Type: + return "UInt8"; + case BuiltinType::builtin_type_t::kUInt16Type: + return "UInt16"; + case BuiltinType::builtin_type_t::kUInt32Type: + return "UInt32"; + case BuiltinType::builtin_type_t::kUInt64Type: + throw internal_error("Java implementation does not support uint64"); + case BuiltinType::builtin_type_t::kFloatType: + return "Float"; + case BuiltinType::builtin_type_t::kDoubleType: + return "Double"; + case BuiltinType::builtin_type_t::kStringType: + return "String"; + case BuiltinType::builtin_type_t::kBinaryType: + return "Binary"; + default: + throw internal_error("unknown builtin type"); + } +} + +string JavaGenerator::getBuiltinTypename(const BuiltinType *t) +{ + switch (t->getBuiltinType()) + { + case BuiltinType::builtin_type_t::kBoolType: + return "boolean"; + case BuiltinType::builtin_type_t::kInt8Type: + return "byte"; + case BuiltinType::builtin_type_t::kInt16Type: + return "short"; + case BuiltinType::builtin_type_t::kInt32Type: + return "int"; + case BuiltinType::builtin_type_t::kInt64Type: + return "long"; + case BuiltinType::builtin_type_t::kUInt8Type: + return "short"; + case BuiltinType::builtin_type_t::kUInt16Type: + return "int"; + case BuiltinType::builtin_type_t::kUInt32Type: + return "long"; + case BuiltinType::builtin_type_t::kUInt64Type: + throw internal_error("Java implementation does not support uint64"); + case BuiltinType::builtin_type_t::kFloatType: + return "float"; + case BuiltinType::builtin_type_t::kDoubleType: + return "double"; + case BuiltinType::builtin_type_t::kStringType: + return "String"; + case BuiltinType::builtin_type_t::kBinaryType: + return "byte[]"; + default: + throw internal_error("unknown builtin type"); + } +} + +string JavaGenerator::getBuiltinObjectTypename(const BuiltinType *t) +{ + switch (t->getBuiltinType()) + { + case BuiltinType::builtin_type_t::kBoolType: + return "Boolean"; + case BuiltinType::builtin_type_t::kInt8Type: + return "Byte"; + case BuiltinType::builtin_type_t::kInt16Type: + return "Short"; + case BuiltinType::builtin_type_t::kInt32Type: + return "Integer"; + case BuiltinType::builtin_type_t::kInt64Type: + return "Long"; + case BuiltinType::builtin_type_t::kUInt8Type: + return "Short"; + case BuiltinType::builtin_type_t::kUInt16Type: + return "Integer"; + case BuiltinType::builtin_type_t::kUInt32Type: + return "Long"; + case BuiltinType::builtin_type_t::kUInt64Type: + throw internal_error("Java implementation does not support uint64"); + case BuiltinType::builtin_type_t::kFloatType: + return "Float"; + case BuiltinType::builtin_type_t::kDoubleType: + return "Double"; + case BuiltinType::builtin_type_t::kStringType: + return "String"; + case BuiltinType::builtin_type_t::kBinaryType: + return "byte[]"; + default: + throw internal_error("unknown builtin type"); + } +} + +string JavaGenerator::filterName(const string &name) +{ + string result = name; + if (result.size() >= m_suffixStripSize) + { + size_t pos = result.size() - m_suffixStripSize; + if (result.substr(pos, m_suffixStripSize) == m_suffixStrip) + { + result.erase(pos, m_suffixStripSize); + } + } + return result; +} + +std::string erpcgen::JavaGenerator::getGroupPackageName(const Group *group) +{ + string name = m_javaPackageName; + + if (m_def->hasProgramSymbol() && !m_def->getProgramName().empty()) + { + name += "." + m_def->getProgramName(); + + if (!group->getName().empty()) + { + name += "_" + group->getName(); + } + } + else + { + if (!group->getName().empty()) + { + name += "." + group->getName(); + } + } + + return name; +} + +bool JavaGenerator::checkWhitespaceChar(char c) +{ + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + { + return true; + } + return false; +} + +string JavaGenerator::stripWhitespace(const string &s) +{ + string result = s; + int32_t i; + uint32_t n; + + // Strip leading whitespace. + for (n = 0, i = 0; i < (int)result.size(); ++i, ++n) + { + char c = result[i]; + + if ((i < (int)result.size() - 1 && c == ' ' && !checkWhitespaceChar(result[i + 1])) || !checkWhitespaceChar(c)) + { + break; + } + } + if (n > 0) + { + result.erase(0, n); + } + + // Strip trailing whitespace. + for (n = 0, i = (int)result.size() - 1; i > 0; --i, ++n) + { + char c = result[i]; + if (!checkWhitespaceChar(c)) + { + break; + } + } + if (n > 0) + { + result.erase(i + 1, n); + } + + return result; +} + +void JavaGenerator::initJavaReservedWords() +{ + + // Java reserved words + reserverdWords.insert("abstract"); + reserverdWords.insert("continue"); + reserverdWords.insert("for"); + reserverdWords.insert("new"); + reserverdWords.insert("switch"); + reserverdWords.insert("assert"); + reserverdWords.insert("default"); + reserverdWords.insert("goto"); + reserverdWords.insert("package"); + reserverdWords.insert("synchronized"); + reserverdWords.insert("boolean"); + reserverdWords.insert("do"); + reserverdWords.insert("if"); + reserverdWords.insert("private"); + reserverdWords.insert("this"); + reserverdWords.insert("break"); + reserverdWords.insert("double"); + reserverdWords.insert("implements"); + reserverdWords.insert("protected"); + reserverdWords.insert("throw"); + reserverdWords.insert("byte"); + reserverdWords.insert("else"); + reserverdWords.insert("import"); + reserverdWords.insert("public"); + reserverdWords.insert("throws"); + reserverdWords.insert("case"); + reserverdWords.insert("enum"); + reserverdWords.insert("instanceof"); + reserverdWords.insert("return"); + reserverdWords.insert("transient"); + reserverdWords.insert("catch"); + reserverdWords.insert("extends"); + reserverdWords.insert("int"); + reserverdWords.insert("short"); + reserverdWords.insert("try"); + reserverdWords.insert("char"); + reserverdWords.insert("final"); + reserverdWords.insert("interface"); + reserverdWords.insert("static"); + reserverdWords.insert("void"); + reserverdWords.insert("class"); + reserverdWords.insert("finally"); + reserverdWords.insert("long"); + reserverdWords.insert("strictfp"); + reserverdWords.insert("volatile"); + reserverdWords.insert("const"); + reserverdWords.insert("float"); + reserverdWords.insert("native"); + reserverdWords.insert("super"); + reserverdWords.insert("while"); +} diff --git a/erpcgen/src/JavaGenerator.hpp b/erpcgen/src/JavaGenerator.hpp new file mode 100644 index 00000000..c07809c5 --- /dev/null +++ b/erpcgen/src/JavaGenerator.hpp @@ -0,0 +1,340 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _EMBEDDED_RPC__JAVAGENERATOR_H_ +#define _EMBEDDED_RPC__JAVAGENERATOR_H_ + +#include "Generator.hpp" +#include "cpptempl.hpp" + +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +// Classes +//////////////////////////////////////////////////////////////////////////////// + +namespace erpcgen { + +/*! + * @brief Code generator for Jva. + */ +class JavaGenerator : public Generator +{ +public: + /*! + * @brief This function is constructor of JavaGenerator class. + * + * @param[in] def Contains all Symbols parsed from IDL files. + */ + explicit JavaGenerator(InterfaceDefinition *def, const std::string javaPackageName); + + /*! + * @brief This function is destructor of JavaGenerator class. + * + * This function close opened files. + */ + virtual ~JavaGenerator() {} + + /*! + * @brief This function generate output code for output files. + * + * This code call all necessary functions for prepare output code and parse it into output files. + */ + virtual void generate() override; + +protected: + std::string m_suffixStrip; //!< String to remove from suffixes of names. + size_t m_suffixStripSize; //!< Length of the suffix filter string. + std::string m_javaPackageName; //!< Used java package. + + /*! + * @brief This function prepare helpful functions located in template files. + * + * These function may be used while parsing templates + */ + void parseSubtemplates(); + + /*! + * @brief This function generate output files. + * + * This function call functions for generating client/server source files. + * + * @param[in] fileName Name for output files. + */ + void generateOutputFiles(const std::string &fileName) override; + + /*! + * @brief This function generate output common module. + * + * @param[in] fileName Name for output files. + */ + void generateCommonFile(std::string fileName); + + /*! + * @brief This function generate output client file. + * + * @param[in] fileName Name for output files. + */ + void generateClientFile(std::string fileName); + + /*! + * @brief This function generate output server file. + * + * @param[in] fileName Name for output files. + */ + void generateServerFile(std::string fileName); + + /*! + * @brief This function generate output interface file. + * + * @param[in] fileName Name for output files. + */ + void generateInterfaceFile(std::string fileName); + + /*! + * @brief This function generate output enum files. + */ + void generateEnumFiles(std::string fileName); + + /*! + * @brief This function generate output struct files. + */ + void generateStructFiles(std::string fileName); + + /*! + * @brief This function generate output const file. + */ + void generateConstFile(std::string fileName); + + /*! + * @brief This function return interface function template data. + * + * This function return interface function template data with all data, which + * are necessary for generating output code for output files. + * + * @param[in] group Pointer to a group. + * @param[in] fn From this are set interface function template data. + * + * @return Contains interface function data. + */ + cpptempl::data_map getFunctionTemplateData(Group *group, Function *fn) override; + + /*! + * @brief This function returns function type (callbacks type) template data. + * + * This function returns function type (callbacks type) template data with all data, which + * are necessary for generating output code for output files. Shim code is generating + * common function for serialization/deserialization of data. + * + * @param[in] group Group to which function belongs. + * @param[in] fn From this are set function type template data. + * + * @return Contains interface function data. + */ + cpptempl::data_map getFunctionTypeTemplateData(Group *group, FunctionType *fn) override { return {}; }; + + /*! + * @brief This function will get symbol comments and convert to language specific ones + * + * @param[in] symbol Pointer to symbol. + * @param[inout] symbolInfo Data map, which contains information about symbol. + */ + void setTemplateComments(Symbol *symbol, cpptempl::data_map &symbolInfo) override; + + /*! + * @brief This function return interface function prototype. + * + * @param[in] group Group to which function belongs. + * @param[in] fn Function for prototyping. + * @param[in] interfaceName Interface name used for function declaration. + * @param[in] name Name used for shared code in case of function type. + * @param[in] insideInterfaceCall interfaceClass specific. + * + * @return String prototype representation for given function. + */ + std::string getFunctionPrototype(Group *group, FunctionBase *fn, const std::string &interfaceName = "", + const std::string &name = "", bool insideInterfaceCall = false) override; + + /*! + * @brief This function return typename name base on DataType. If objectType is true, + * return builtin object insted of primitive. + * + * @param[in] t data type. + * @param[in] objectType + * + * @return Return data type name. + */ + std::string getTypenameName(DataType *t, bool isReference, bool objectType); + + /* + * TODO + */ + std::string getArrayInitialization(ArrayType *t); + + /*! + * @brief This function sets const template data. + * + * This function sets const template data with all data, which + * are necessary for generating output code for output files. + */ + void makeConstTemplateData(); + + /*! + * @brief This function sets enum template data. + * + * This function sets enum template data with all data, which + * are necessary for generating output code for output files. + */ + void makeEnumsTemplateData(); + + /*! + * @brief This function sets group symbols template data. + * + * This function sets group symbols template data with all data, which + * are necessary for generating output code for output files. + * + * @param[in] group Pointer to a group. + * + * @return Data map with group symbols templates. + */ + cpptempl::data_map makeGroupSymbolsTemplateData(Group *group) override; + + /*! + * @brief This function return enum members template data. + * + * This function return enum members template data with all data, which + * are necessary for generating output code for output files. + * + * @param[in] enumType Pointer to enum. + * + * @return Contains enum members data. + */ + cpptempl::data_list getEnumMembersTemplateData(EnumType *enumType); + + /*! + * @brief Fill in template data for type aliases. + */ + void makeAliasesTemplateData(); + + /*! + * @brief This function sets function type template data. + * + * This is used for registering callback functions in generated output. + */ + void makeFunctionsTemplateData(); + + /*! + * @brief This function sets struct member information to struct data map variable. + * + * This function sets struct member information to struct data map variable, which + * are necessary for generating output code for output files. + * + * @param[in] structType Struct, which contains struct members. + * @param[in,out] structInfo Data map, which contains information about struct and struct members. + */ + void setStructMembersTemplateData(StructType *structType, cpptempl::data_map &structInfo); + + /*! + * @brief Fill in template data for a single struct member. + */ + void setOneStructMemberTemplateData(StructMember *member, cpptempl::data_map &member_info); + + /* + * TODO + */ + cpptempl::data_map getEncodeDecodeCall(const std::string &name, DataType *t, StructType *structType, + bool inDataContainer, bool isStructMember, StructMember *structMember, bool needTypeDeclaration, bool isFunctionParam); + + /* + * TODO + */ + std::string capitalize(std::string text); + + /*! + * @brief This function return necessary template data for data type. + * + * This function return data type template data with all necessary data, which + * are necessary for generating output code for output files. + * + * @param[in] t Data type. From this are set data type template data. + * + * @return Contains data type template data. + */ + cpptempl::data_map getTypeInfo(DataType *t, int isReference, bool inDataContainer = false); + + /*! + * @brief This function return CamelCase string representation for given BuiltinType. + * + * @param[in] t Builtin type. + * + * @return String representation for given builtin type. + */ + + std::string getBuiltinCodecTypeName(const BuiltinType *t); + + /*! + * @brief This function return string representation for given BuiltinType. + * + * @param[in] t Builtin type. + * + * @return String representation for given builtin type. + */ + std::string getBuiltinTypename(const BuiltinType *t); + + /*! + * @brief This function return string representation for given BuiltinType as Object type. + * + * @param[in] t Builtin type. + * + * @return String representation for given builtin object type. + */ + std::string getBuiltinObjectTypename(const BuiltinType *t); + + /*! + * @brief Filter symbol names. + */ + std::string filterName(const std::string &name); + + //! @brief Possible Doxygen comment styles. + enum class comment_type_t + { + kMultilineComment, //!< Leading multi-line comment + kInlineComment, //!< Trailing inline comment. + }; + + /*! + * @brief This function creates Group package name. + * + * @param[in] group Group + * + * @return Package name for given group. + */ + std::string getGroupPackageName(const Group *group); + + /*! + * @brief Strip leading and trailing whitespace. + * + * @param[in] s String from which are stripped white spaces. + */ + std::string stripWhitespace(const std::string &s); + + /*! + * @brief Check if character is whitespace type. + * + * @param[in] c Checked character. + */ + bool checkWhitespaceChar(char c); + + /*! + * Stores reserved words for Java program language. + */ + void initJavaReservedWords(); +}; + +} // namespace erpcgen + +#endif // _EMBEDDED_RPC__JAVAGENERATOR_H_ diff --git a/erpcgen/src/Logging.cpp b/erpcgen/src/Logging.cpp index 0f4b6ed1..82f6fce8 100644 --- a/erpcgen/src/Logging.cpp +++ b/erpcgen/src/Logging.cpp @@ -120,7 +120,7 @@ void Log::urgent(const char *fmt, ...) { va_list args; va_start(args, fmt); - s_logger->log(Logger::kUrgent, fmt, args); + s_logger->log(Logger::log_level_t::kUrgent, fmt, args); va_end(args); } } @@ -131,7 +131,7 @@ void Log::error(const char *fmt, ...) { va_list args; va_start(args, fmt); - s_logger->log(Logger::kError, fmt, args); + s_logger->log(Logger::log_level_t::kError, fmt, args); va_end(args); } } @@ -142,7 +142,7 @@ void Log::warning(const char *fmt, ...) { va_list args; va_start(args, fmt); - s_logger->log(Logger::kWarning, fmt, args); + s_logger->log(Logger::log_level_t::kWarning, fmt, args); va_end(args); } } @@ -153,7 +153,7 @@ void Log::info(const char *fmt, ...) { va_list args; va_start(args, fmt); - s_logger->log(Logger::kInfo, fmt, args); + s_logger->log(Logger::log_level_t::kInfo, fmt, args); va_end(args); } } @@ -164,7 +164,7 @@ void Log::info2(const char *fmt, ...) { va_list args; va_start(args, fmt); - s_logger->log(Logger::kInfo2, fmt, args); + s_logger->log(Logger::log_level_t::kInfo2, fmt, args); va_end(args); } } @@ -175,7 +175,7 @@ void Log::debug(const char *fmt, ...) { va_list args; va_start(args, fmt); - s_logger->log(Logger::kDebug, fmt, args); + s_logger->log(Logger::log_level_t::kDebug, fmt, args); va_end(args); } } @@ -186,7 +186,7 @@ void Log::debug2(const char *fmt, ...) { va_list args; va_start(args, fmt); - s_logger->log(Logger::kDebug2, fmt, args); + s_logger->log(Logger::log_level_t::kDebug2, fmt, args); va_end(args); } } diff --git a/erpcgen/src/Logging.hpp b/erpcgen/src/Logging.hpp index fab7a45a..9369f352 100644 --- a/erpcgen/src/Logging.hpp +++ b/erpcgen/src/Logging.hpp @@ -47,7 +47,7 @@ class Logger { public: //! \brief Logging levels. - enum log_level_t + enum class log_level_t { kUrgent = 0, //!< The lowest level, for messages that must always be logged. kError, //!< For fatal error messages. @@ -62,11 +62,7 @@ class Logger public: //! \brief Default constructor. - Logger() - : m_filter(kInfo) - , m_level(kInfo) - { - } + Logger() : m_filter(log_level_t::kInfo), m_level(log_level_t::kInfo) {} //! \brief Destructor. virtual ~Logger() {} @@ -197,9 +193,8 @@ class Log //! //! Saves the current logging output level of the global logger, //! as managed by the Log class, and sets the new level to \a level. - explicit SetOutputLevel(Logger::log_level_t level) - : m_logger(Log::getLogger()) - , m_saved(Logger::kInfo) + explicit SetOutputLevel(Logger::log_level_t level) : + m_logger(Log::getLogger()), m_saved(Logger::log_level_t::kInfo) { assert(m_logger); m_saved = m_logger->getOutputLevel(); @@ -210,9 +205,7 @@ class Log //! //! Saves the current logging output level of \a logger and sets //! the new level to \a level. - SetOutputLevel(Logger *logger, Logger::log_level_t level) - : m_logger(logger) - , m_saved(logger->getOutputLevel()) + SetOutputLevel(Logger *logger, Logger::log_level_t level) : m_logger(logger), m_saved(logger->getOutputLevel()) { assert(m_logger); m_logger->setOutputLevel(level); @@ -236,8 +229,7 @@ class StdoutLogger : public Logger { public: //! \brief Default constructor. - StdoutLogger(Logger::log_level_t stderrLevel = Logger::kWarning) - : m_stderrLevel(stderrLevel) + explicit StdoutLogger(Logger::log_level_t stderrLevel = Logger::log_level_t::kWarning) : m_stderrLevel(stderrLevel) { } diff --git a/erpcgen/src/ParseErrors.hpp b/erpcgen/src/ParseErrors.hpp index 07a26635..b89a250d 100644 --- a/erpcgen/src/ParseErrors.hpp +++ b/erpcgen/src/ParseErrors.hpp @@ -39,11 +39,7 @@ class erpc_error : public std::runtime_error * * @param[in] __arg Exception error message. */ - explicit erpc_error(const std::string &__arg) - : std::runtime_error(__arg) - , m_message(__arg) - { - } + explicit erpc_error(const std::string &__arg) : std::runtime_error(__arg), m_message(__arg) {} protected: std::string m_message; /*!< Error message. */ @@ -55,10 +51,8 @@ class erpc_error : public std::runtime_error * @param[in] __arg Exception error message. * @param[in] errorName Exception error name. */ - explicit erpc_error(const std::string &__arg, const std::string &errorName) - : std::runtime_error(__arg) - , m_message(__arg) - , m_errName(errorName) + explicit erpc_error(const std::string &__arg, const std::string &errorName) : + std::runtime_error(__arg), m_message(__arg), m_errName(errorName) { } }; @@ -74,10 +68,7 @@ class syntax_error : public erpc_error * * @param[in] __arg Exception error message. */ - explicit syntax_error(const std::string &__arg) - : erpc_error(__arg) - { - } + explicit syntax_error(const std::string &__arg) : erpc_error(__arg) {} }; /*! @@ -93,11 +84,10 @@ class syntax_error2 : public erpc_error * @param[in] loc Location of token. * @param[in] fileName File name where error occurred. */ - explicit syntax_error2(const std::string &__arg, token_loc_t loc, std::string &fileName) - : erpc_error(__arg, "syntax error") - , m_errLoc(loc) - , m_what(format_string("file %s:%d:%d: %s, %s", fileName.c_str(), m_errLoc.m_firstLine, m_errLoc.m_firstChar, - m_errName.c_str(), m_message.c_str())) + explicit syntax_error2(const std::string &__arg, token_loc_t loc, std::string &fileName) : + erpc_error(__arg, "syntax error"), m_errLoc(loc), + m_what(format_string("file %s:%d:%d: %s, %s", fileName.c_str(), m_errLoc.m_firstLine, m_errLoc.m_firstChar, + m_errName.c_str(), m_message.c_str())) { } @@ -108,11 +98,10 @@ class syntax_error2 : public erpc_error * @param[in] loc Location of token for which error occurred. * @param[in] fileName File name where error occurred. */ - explicit syntax_error2(const char *__arg, token_loc_t loc, std::string &fileName) - : erpc_error(std::string(__arg), "syntax error") - , m_errLoc(loc) - , m_what(format_string("file %s:%d:%d: %s, %s", fileName.c_str(), m_errLoc.m_firstLine, m_errLoc.m_firstChar, - m_errName.c_str(), m_message.c_str())) + explicit syntax_error2(const char *__arg, token_loc_t loc, std::string &fileName) : + erpc_error(std::string(__arg), "syntax error"), m_errLoc(loc), + m_what(format_string("file %s:%d:%d: %s, %s", fileName.c_str(), m_errLoc.m_firstLine, m_errLoc.m_firstChar, + m_errName.c_str(), m_message.c_str())) { } @@ -139,10 +128,7 @@ class lexical_error : public erpc_error * * @param[in] __arg Exception error message. */ - explicit lexical_error(const std::string &__arg) - : erpc_error(__arg) - { - } + explicit lexical_error(const std::string &__arg) : erpc_error(__arg) {} }; /*! @@ -156,10 +142,7 @@ class semantic_error : public erpc_error * * @param[in] __arg Exception error message. */ - explicit semantic_error(const std::string &__arg) - : erpc_error(__arg) - { - } + explicit semantic_error(const std::string &__arg) : erpc_error(__arg) {} }; /*! @@ -173,10 +156,7 @@ class internal_error : public erpc_error * * @param[in] __arg Exception error message. */ - explicit internal_error(const std::string &__arg) - : erpc_error(__arg) - { - } + explicit internal_error(const std::string &__arg) : erpc_error(__arg) {} }; /*! diff --git a/erpcgen/src/PythonGenerator.cpp b/erpcgen/src/PythonGenerator.cpp index 2cb07984..3c1f581f 100644 --- a/erpcgen/src/PythonGenerator.cpp +++ b/erpcgen/src/PythonGenerator.cpp @@ -37,10 +37,8 @@ extern const char *const kPyGlobalInit; // Code //////////////////////////////////////////////////////////////////////////////// -PythonGenerator::PythonGenerator(InterfaceDefinition *def) -: Generator(def, kPython) -, m_suffixStrip("") -, m_suffixStripSize(0) +PythonGenerator::PythonGenerator(InterfaceDefinition *def) : +Generator(def, generator_type_t::kPython), m_suffixStrip(""), m_suffixStripSize(0) { /* Set copyright rules. */ if (m_def->hasProgramSymbol()) @@ -122,6 +120,7 @@ void PythonGenerator::generate() m_templateData["structs"] = empty; m_templateData["unions"] = empty; m_templateData["consts"] = empty; + m_templateData["functions"] = empty; parseSubtemplates(); @@ -146,8 +145,6 @@ void PythonGenerator::generate() makeEnumsTemplateData(); - makeFunctionsTemplateData(); - for (Group *group : m_groups) { data_map groupTemplate; @@ -165,15 +162,15 @@ void PythonGenerator::generate() void PythonGenerator::setTemplateComments(Symbol *symbol, data_map &symbolInfo) { - symbolInfo["mlComment"] = convertComment(symbol->getMlComment(), kMultilineComment); - symbolInfo["ilComment"] = convertComment(symbol->getIlComment(), kInlineComment); + symbolInfo["mlComment"] = convertComment(symbol->getMlComment(), comment_type_t::kMultilineComment); + symbolInfo["ilComment"] = convertComment(symbol->getIlComment(), comment_type_t::kInlineComment); } data_map PythonGenerator::getFunctionTemplateData(Group *group, Function *fn) { (void)group; data_map info; - string proto = getFunctionPrototype(fn); + string proto = getFunctionPrototype(nullptr, fn); info["name"] = getOutputName(fn); info["prototype"] = proto; @@ -236,18 +233,18 @@ data_map PythonGenerator::getFunctionTemplateData(Group *group, Function *fn) /* Necessary for handling non-discriminated unions */ paramInfo["discriminator"] = getAnnStringValue(param, DISCRIMINATOR_ANNOTATION); - _param_direction dir = param->getDirection(); + param_direction_t dir = param->getDirection(); switch (dir) { - case kInDirection: + case param_direction_t::kInDirection: paramInfo["direction"] = "in"; inParams.push_back(paramInfo); break; - case kOutDirection: + case param_direction_t::kOutDirection: paramInfo["direction"] = "out"; outParams.push_back(paramInfo); break; - case kInoutDirection: + case param_direction_t::kInoutDirection: paramInfo["direction"] = "inout"; inParams.push_back(paramInfo); outParams.push_back(paramInfo); @@ -266,12 +263,22 @@ data_map PythonGenerator::getFunctionTemplateData(Group *group, Function *fn) return info; } -string PythonGenerator::getFunctionPrototype(Function *fn) +string PythonGenerator::getFunctionPrototype(Group *group, FunctionBase *fn, const string &interfaceName, + const string &name, bool insideInterfaceCall) { - string proto = getOutputName(fn); + FunctionType *functionType = dynamic_cast(fn); + if (functionType) + { + return ""; /*Todo: implement*/ + } + Function *function = dynamic_cast(fn); + + assert(function); + + string proto = getOutputName(function); proto += "(self"; - auto params = fn->getParameters().getMembers(); + auto params = function->getParameters().getMembers(); if (params.size()) { for (auto it : params) @@ -294,7 +301,7 @@ void PythonGenerator::makeConstTemplateData() { Log::info("Constant globals:\n"); data_list consts; - for (auto it : m_globals->getSymbolsOfType(Symbol::kConstSymbol)) + for (auto it : m_globals->getSymbolsOfType(Symbol::symbol_type_t::kConstSymbol)) { ConstType *constVar = dynamic_cast(it); assert(constVar); @@ -330,7 +337,7 @@ void PythonGenerator::makeEnumsTemplateData() Log::info("Enums:\n"); data_list enums; int n = 0; - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kEnumType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kEnumType)) { EnumType *enumType = dynamic_cast(it); assert(enumType); @@ -371,7 +378,7 @@ void PythonGenerator::makeAliasesTemplateData() Log::info("Type definition:\n"); data_list aliases; int n = 0; - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kAliasType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kAliasType)) { AliasType *aliasType = dynamic_cast(it); assert(aliasType); @@ -428,7 +435,8 @@ data_map PythonGenerator::makeGroupSymbolsTemplateData(Group *group) switch (dataType->getDataType()) { - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *structType = dynamic_cast(symbol); if (structType == nullptr) { @@ -452,7 +460,8 @@ data_map PythonGenerator::makeGroupSymbolsTemplateData(Group *group) } break; } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *unionType = dynamic_cast(symbol); if (unionType == nullptr) { @@ -482,7 +491,8 @@ data_map PythonGenerator::makeGroupSymbolsTemplateData(Group *group) } break; } - case DataType::kAliasType: { + case DataType::data_type_t::kAliasType: + { AliasType *aliasType = dynamic_cast(symbol); if (aliasType == nullptr) break; @@ -572,32 +582,6 @@ void PythonGenerator::setOneStructMemberTemplateData(StructMember *member, data_ setTemplateComments(member, member_info); } -void PythonGenerator::makeFunctionsTemplateData() -{ - /* type definitions of functions and table of functions */ - Log::info("Functions:\n"); - data_list functions; - for (Symbol *functionTypeSymbol : getDataTypesFromSymbolScope(m_globals, DataType::kFunctionType)) - { - FunctionType *functionType = dynamic_cast(functionTypeSymbol); - data_map functionInfo; - - /* Table template data. */ - data_list callbacks; - for (Function *fun : functionType->getCallbackFuns()) - { - data_map callbacksInfo; - callbacksInfo["name"] = fun->getName(); - callbacks.push_back(callbacksInfo); - } - functionInfo["callbacks"] = callbacks; - /* Function type name. */ - functionInfo["name"] = functionType->getName(); - functions.push_back(functionInfo); - } - m_templateData["functions"] = functions; -} - data_map PythonGenerator::getTypeInfo(DataType *t) { data_map info; @@ -605,11 +589,13 @@ data_map PythonGenerator::getTypeInfo(DataType *t) info["isNonEncapsulatedUnion"] = false; switch (t->getDataType()) { - case DataType::kAliasType: { + case DataType::data_type_t::kAliasType: + { info = getTypeInfo(t->getTrueDataType()); break; } - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { // Array type requires the array element count to come after the variable/member name. ArrayType *a = dynamic_cast(t); assert(a); @@ -618,16 +604,19 @@ data_map PythonGenerator::getTypeInfo(DataType *t) info["elementType"] = getTypeInfo(a->getElementType()); break; } - case DataType::kBuiltinType: { + case DataType::data_type_t::kBuiltinType: + { assert(dynamic_cast(t)); info["type"] = getBuiltinTypename(dynamic_cast(t)); break; } - case DataType::kEnumType: { + case DataType::data_type_t::kEnumType: + { info["type"] = "enum"; break; } - case DataType::kFunctionType: { + case DataType::data_type_t::kFunctionType: + { info["type"] = "function"; FunctionType *funType = dynamic_cast(t); assert(funType); @@ -643,24 +632,27 @@ data_map PythonGenerator::getTypeInfo(DataType *t) } else { - throw semantic_error(format_string("Function has function type parameter (callback parameter), but in " - "IDL is missing function definition, which can be passed there.") - .c_str()); + throw semantic_error( + "Function has function type parameter (callback parameter), but in " + "IDL is missing function definition, which can be passed there."); } break; } - case DataType::kListType: { + case DataType::data_type_t::kListType: + { const ListType *a = dynamic_cast(t); assert(a); info["type"] = "list"; info["elementType"] = getTypeInfo(a->getElementType()); break; } - case DataType::kStructType: { + case DataType::data_type_t::kStructType: + { info["type"] = "struct"; break; } - case DataType::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *unionType = dynamic_cast(t); assert(unionType); info["type"] = "union"; @@ -687,7 +679,7 @@ data_map PythonGenerator::getTypeInfo(DataType *t) StructMember *discriminatorMember = dynamic_cast(discriminatorSym); if (!discriminatorMember) { - throw internal_error(format_string("union discriminator is not a struct member")); + throw internal_error("union discriminator is not a struct member"); } info["discriminatorType"] = getTypeInfo(discriminatorMember->getDataType()); } @@ -705,7 +697,7 @@ data_map PythonGenerator::getTypeInfo(DataType *t) } else if (unionCase->getCaseName() != "") { - for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::kEnumType)) + for (auto it : getDataTypesFromSymbolScope(m_globals, DataType::data_type_t::kEnumType)) { EnumType *enumType = dynamic_cast(it); assert(enumType); @@ -727,7 +719,7 @@ data_map PythonGenerator::getTypeInfo(DataType *t) } if (!caseData.has("type")) { - for (auto it : m_globals->getSymbolsOfType(DataType::kConstSymbol)) + for (auto it : m_globals->getSymbolsOfType(DataType::symbol_type_t::kConstSymbol)) { ConstType *constType = dynamic_cast(it); assert(constType); @@ -779,7 +771,8 @@ data_map PythonGenerator::getTypeInfo(DataType *t) info["cases"] = unionCases; break; } - case DataType::kVoidType: { + case DataType::data_type_t::kVoidType: + { info["type"] = "void"; break; } @@ -793,31 +786,31 @@ string PythonGenerator::getBuiltinTypename(const BuiltinType *t) { switch (t->getBuiltinType()) { - case BuiltinType::kBoolType: + case BuiltinType::builtin_type_t::kBoolType: return "bool"; - case BuiltinType::kInt8Type: + case BuiltinType::builtin_type_t::kInt8Type: return "int8"; - case BuiltinType::kInt16Type: + case BuiltinType::builtin_type_t::kInt16Type: return "int16"; - case BuiltinType::kInt32Type: + case BuiltinType::builtin_type_t::kInt32Type: return "int32"; - case BuiltinType::kInt64Type: + case BuiltinType::builtin_type_t::kInt64Type: return "int64"; - case BuiltinType::kUInt8Type: + case BuiltinType::builtin_type_t::kUInt8Type: return "uint8"; - case BuiltinType::kUInt16Type: + case BuiltinType::builtin_type_t::kUInt16Type: return "uint16"; - case BuiltinType::kUInt32Type: + case BuiltinType::builtin_type_t::kUInt32Type: return "uint32"; - case BuiltinType::kUInt64Type: + case BuiltinType::builtin_type_t::kUInt64Type: return "uint64"; - case BuiltinType::kFloatType: + case BuiltinType::builtin_type_t::kFloatType: return "float"; - case BuiltinType::kDoubleType: + case BuiltinType::builtin_type_t::kDoubleType: return "double"; - case BuiltinType::kStringType: + case BuiltinType::builtin_type_t::kStringType: return "string"; - case BuiltinType::kBinaryType: + case BuiltinType::builtin_type_t::kBinaryType: return "binary"; default: throw internal_error("unknown builtin type"); @@ -838,11 +831,11 @@ string PythonGenerator::filterName(const string &name) return result; } -string PythonGenerator::convertComment(const string &comment, comment_type commentType) +string PythonGenerator::convertComment(const string &comment, comment_type_t commentType) { (void)commentType; // Longer patterns are ordered earlier than similar shorter patterns. - static const char *const kCommentBegins[] = { "//!<", "//!", "///<", "///", "/*!<", "/*!", "/**<", "/**", 0 }; + static const char *const kCommentBegins[] = { "//!<", "//!", "///<", "///", "/*!<", "/*!", "/**<", "/**", "/*", 0 }; static const char *const kCommentEnds[] = { "*/", 0 }; string result = stripWhitespace(comment); @@ -870,7 +863,7 @@ string PythonGenerator::convertComment(const string &comment, comment_type comme // Check if we failed to find a matching comment begin. if (kCommentBegins[i] == 0) { - throw internal_error("unable to convert Doxygen comment"); + throw internal_error("Unable to convert Doxygen comment in:" + result); } // Search for a matching comment end to strip. There may not be a comment end. @@ -941,7 +934,7 @@ string PythonGenerator::convertComment(const string &comment, comment_type comme return result; } -bool PythonGenerator::checkWhitspaceChar(char c) +bool PythonGenerator::checkWhitespaceChar(char c) { if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { @@ -961,7 +954,7 @@ string PythonGenerator::stripWhitespace(const string &s) { char c = result[i]; - if ((i < (int)result.size() - 1 && c == ' ' && !checkWhitspaceChar(result[i + 1])) || !checkWhitspaceChar(c)) + if ((i < (int)result.size() - 1 && c == ' ' && !checkWhitespaceChar(result[i + 1])) || !checkWhitespaceChar(c)) { break; } @@ -975,7 +968,7 @@ string PythonGenerator::stripWhitespace(const string &s) for (n = 0, i = (int)result.size() - 1; i > 0; --i, ++n) { char c = result[i]; - if (!checkWhitspaceChar(c)) + if (!checkWhitespaceChar(c)) { break; } diff --git a/erpcgen/src/PythonGenerator.hpp b/erpcgen/src/PythonGenerator.hpp index f20179c4..e31ee6a4 100644 --- a/erpcgen/src/PythonGenerator.hpp +++ b/erpcgen/src/PythonGenerator.hpp @@ -117,12 +117,25 @@ class PythonGenerator : public Generator * * @param[in] group Pointer to a group. * @param[in] fn From this are set interface function template data. - * @param[in] fnIndex Function index. * * @return Contains interface function data. */ cpptempl::data_map getFunctionTemplateData(Group *group, Function *fn) override; + /*! + * @brief This function returns function type (callbacks type) template data. + * + * This function returns function type (callbacks type) template data with all data, which + * are necessary for generating output code for output files. Shim code is generating + * common function for serialization/deserialization of data. + * + * @param[in] group Group to which function belongs. + * @param[in] fn From this are set function type template data. + * + * @return Contains interface function data. + */ + cpptempl::data_map getFunctionTypeTemplateData(Group *group, FunctionType *fn) override { return {}; }; + /*! * @brief This function will get symbol comments and convert to language specific ones * @@ -134,11 +147,16 @@ class PythonGenerator : public Generator /*! * @brief This function return interface function prototype. * + * @param[in] group Group to which function belongs. * @param[in] fn Function for prototyping. + * @param[in] interfaceName Interface name used for function declaration. + * @param[in] name Name used for shared code in case of function type. + * @param[in] insideInterfaceCall interfaceClass specific. * * @return String prototype representation for given function. */ - std::string getFunctionPrototype(Function *fn); + std::string getFunctionPrototype(Group *group, FunctionBase *fn, const std::string &interfaceName = "", + const std::string &name = "", bool insideInterfaceCall = false) override; /*! * @brief This function sets const template data. @@ -185,13 +203,6 @@ class PythonGenerator : public Generator */ void makeAliasesTemplateData(); - /*! - * @brief This function sets function type template data. - * - * This is used for registering callback functions in generated output. - */ - void makeFunctionsTemplateData(); - /*! * @brief This function sets struct member information to struct data map variable. * @@ -235,7 +246,7 @@ class PythonGenerator : public Generator std::string filterName(const std::string &name); //! @brief Possible Doxygen comment styles. - enum comment_type + enum class comment_type_t { kMultilineComment, //!< Leading multi-line comment kInlineComment, //!< Trailing inline comment. @@ -249,7 +260,7 @@ class PythonGenerator : public Generator * * @return Python form of the provided comment. */ - std::string convertComment(const std::string &comment, comment_type commentType); + std::string convertComment(const std::string &comment, comment_type_t commentType); /*! * @brief Strip leading and trailing whitespace. @@ -263,7 +274,7 @@ class PythonGenerator : public Generator * * @param[in] c Checked character. */ - bool checkWhitspaceChar(char c); + bool checkWhitespaceChar(char c); /*! * Stores reserved words for Python program language. diff --git a/erpcgen/src/SearchPath.hpp b/erpcgen/src/SearchPath.hpp index 6fde9b36..b5bd62f2 100644 --- a/erpcgen/src/SearchPath.hpp +++ b/erpcgen/src/SearchPath.hpp @@ -23,15 +23,12 @@ class PathSearcher { public: //! - enum _target_type + enum class target_type_t { kFindFile, kFindDirectory }; /*!< Type of searched item. */ - //! - typedef enum _target_type target_type_t; /*!< Type of searched item. */ - protected: //! Global search object singleton. static PathSearcher *s_searcher; diff --git a/erpcgen/src/SymbolScanner.cpp b/erpcgen/src/SymbolScanner.cpp index 94a23e7e..c47b5f23 100644 --- a/erpcgen/src/SymbolScanner.cpp +++ b/erpcgen/src/SymbolScanner.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2023 NXP * Copyright (c) 2020 Texas Instruments Incorporated * All rights reserved. * @@ -45,8 +45,7 @@ void SymbolScanner::handleRoot(AstNode *node, bottom_up) forwardTypes += format_string("type name %s: line %d", it->first.c_str(), it->second->getFirstLine()); } throw syntax_error(format_string("Missing type definitions for one or more forward type declarations: %s", - forwardTypes.c_str()) - .c_str()); + forwardTypes.c_str())); } } @@ -147,37 +146,43 @@ DataType *SymbolScanner::getDataTypeForConst(AstNode *typeNode) AstNode *SymbolScanner::handleType(AstNode *node, top_down) { - // Extract new type name. - AstNode *ident = (*node)[0]; - const Token &tok = ident->getToken(); - const string &name = tok.getStringValue(); - Log::debug("type: %s\n", name.c_str()); - - // Find existing type. - AstNode *typeNode = (*node)[1]; - DataType *dataType = nullptr; - if (!containsStructEnumDeclaration(typeNode)) + if (m_currentInterface == nullptr) { - dataType = lookupDataType(typeNode); - } + // Extract new type name. + AstNode *ident = (*node)[0]; + const Token &tok = ident->getToken(); + const string &name = tok.getStringValue(); + Log::debug("type: %s\n", name.c_str()); + + // Find existing type. + AstNode *typeNode = (*node)[1]; + DataType *dataType = nullptr; + if (!containsStructEnumDeclaration(typeNode)) + { + dataType = lookupDataType(typeNode); + } - AliasType *type = new AliasType(tok, dataType); + AliasType *type = new AliasType(tok, dataType); - // Get comment if exist. - addDoxygenComments(type, node->getChild(3), node->getChild(4)); + // Get comment if exist. + addDoxygenComments(type, node->getChild(3), node->getChild(4)); - m_currentAlias = type; + m_currentAlias = type; + } return nullptr; } AstNode *SymbolScanner::handleType(AstNode *node, bottom_up) { - if (m_currentAlias) + if (m_currentInterface == nullptr) { - addAnnotations(node->getChild(2), m_currentAlias); - addGlobalSymbol(m_currentAlias); - m_currentAlias = nullptr; + if (m_currentAlias) + { + addAnnotations(node->getChild(2), m_currentAlias); + addGlobalSymbol(m_currentAlias); + m_currentAlias = nullptr; + } } return nullptr; } @@ -637,9 +642,8 @@ AstNode *SymbolScanner::handleStruct(AstNode *node, top_down) AstNode *structNameNode = (*node)[0]; if (!structNameNode && m_currentAlias == nullptr) { - throw semantic_error( - format_string("line %d: illegal anonymous struct definition at file level", node->getToken().getFirstLine()) - .c_str()); + throw semantic_error(format_string("line %d: illegal anonymous struct definition at file level", + node->getToken().getFirstLine())); } // Create the struct symbol. @@ -661,10 +665,10 @@ AstNode *SymbolScanner::handleStruct(AstNode *node, top_down) } else { - throw syntax_error(format_string("line %d: Structure definition type name didn't match data type of " - "forward declaration from line %d.", - tok.getFirstLine(), forwardDecl->second->getFirstLine()) - .c_str()); + throw syntax_error( + format_string("line %d: Structure definition type name didn't match data type of " + "forward declaration from line %d.", + tok.getFirstLine(), forwardDecl->second->getFirstLine())); } } else @@ -817,10 +821,10 @@ AstNode *SymbolScanner::handleUnion(AstNode *node, top_down) } else { - throw syntax_error(format_string("line %d: Union definition type name didn't match data type of " - "forward declaration from line %d.", - tok->getFirstLine(), forwardDecl->second->getFirstLine()) - .c_str()); + throw syntax_error( + format_string("line %d: Union definition type name didn't match data type of " + "forward declaration from line %d.", + tok->getFirstLine(), forwardDecl->second->getFirstLine())); } } else @@ -1013,6 +1017,55 @@ AstNode *SymbolScanner::handleInterface(AstNode *node, bottom_up) { addAnnotations(node->getChild(2), m_currentInterface); + /* Check if function callbacks were not used in other interfaces*/ + for (Symbol *funSymbol : m_globals->getSymbolsOfType(Symbol::symbol_type_t::kInterfaceSymbol)) + { + Interface *interface = dynamic_cast(funSymbol); + assert(interface); + + if (interface == m_currentInterface) + { + continue; + } + + for (Function *func : interface->getFunctions()) + { + for (StructMember *param : func->getParameters().getMembers()) + { + DataType *dataType = param->getDataType()->getTrueDataType(); + if (dataType->isFunction()) + { + FunctionType *funcType = dynamic_cast(dataType); + assert(funcType); + + if ((m_currentInterface->getName() == funcType->getInterface()->getName()) && + (m_currentInterface != funcType->getInterface())) + { + bool found = false; + for (FunctionType *funcTypeCurrent : m_currentInterface->getFunctionTypes()) + { + if (funcTypeCurrent->getName() == funcType->getName()) + { + found = true; + delete funcType->getInterface(); + delete funcType; + param->setDataType(funcTypeCurrent); + break; + } + } + if (found == false) + { + throw syntax_error( + format_string("line %d, Callback name %s doesn't exists in interface %s.\n", + funcType->getLocation().m_firstLine, funcType->getName().c_str(), + funcType->getInterface()->getName().c_str())); + } + } + } + } + } + } + // Interfaces cannot be nested, so we can just clear this. If they were nestable, we would // have to keep a stack of open interfaces. m_currentInterface = nullptr; @@ -1027,10 +1080,16 @@ AstNode *SymbolScanner::handleFunction(AstNode *node, top_down) const Token &tok = ident->getToken(); const string &name = tok.getStringValue(); Log::debug("function: %s\n", name.c_str()); + bool isFunctionType = node->getChild(4) != nullptr; // Create function symbol. FunctionBase *func; - if (m_currentInterface) /* function definition */ + if (isFunctionType) + { + func = new FunctionType(tok, m_currentInterface); + m_currentInterface->addFunctionType(dynamic_cast(func)); + } + else { if (m_currentInterface->getFunctions().size() == 0) { @@ -1042,11 +1101,6 @@ AstNode *SymbolScanner::handleFunction(AstNode *node, top_down) } m_currentInterface->addFunction(dynamic_cast(func)); } - else /* function type */ - { - func = new FunctionType(tok); - addGlobalSymbol(dynamic_cast(func)); - } m_currentStruct = &(func->getParameters()); @@ -1123,21 +1177,30 @@ AstNode *SymbolScanner::handleFunction(AstNode *node, top_down) } /* Get comment if exist. */ - addDoxygenComments(dynamic_cast(func), node->getChild(5), node->getChild(6)); + addDoxygenComments(dynamic_cast(func), node->getChild(6), node->getChild(7)); return nullptr; } AstNode *SymbolScanner::handleFunction(AstNode *node, bottom_up) { + bool isFunctionType = node->getChild(4) != nullptr; + + if (isFunctionType) /* function type */ + { + FunctionType *func = m_currentInterface->getFunctionTypes().back(); + func->getParameters().getScope().setParent(&m_currentInterface->getScope()); - if (m_currentInterface) /* function definition */ + /* Function annotations. */ + addAnnotations(node->getChild(5), func); + } + else /* function definition */ { Function *func = m_currentInterface->getFunctions().back(); func->getParameters().getScope().setParent(&m_currentInterface->getScope()); /* Function annotations. */ - addAnnotations(node->getChild(4), func); + addAnnotations(node->getChild(5), func); /* Add missing callbacks parameters. */ FunctionType *callbackFunctionType = func->getFunctionType(); @@ -1162,25 +1225,6 @@ AstNode *SymbolScanner::handleFunction(AstNode *node, bottom_up) } } } - else /* function type */ - { - FunctionType *func = nullptr; - for (Symbol *funSymbol : m_globals->getSymbolsOfType(Symbol::kTypenameSymbol)) - { - DataType *datatype = dynamic_cast(funSymbol); - assert(datatype); - - if (datatype->isFunction()) - { - func = dynamic_cast(datatype); - } - } - assert(func); - func->getParameters().getScope().setParent(m_globals); - - /* Function annotations. */ - addAnnotations(node->getChild(4), func); - } // Handle annotations for function params scanStructForAnnotations(); @@ -1198,34 +1242,27 @@ AstNode *SymbolScanner::handleParam(AstNode *node, top_down) StructMember *callbackParam = nullptr; Function *fun = nullptr; FunctionType *funType = nullptr; - if (m_currentInterface) + bool isFunctionType = m_currentInterface->getFunctions().empty(); + if (!isFunctionType) { fun = m_currentInterface->getFunctions().back(); - for (Symbol *funSymbol : m_globals->getSymbolsOfType(Symbol::kTypenameSymbol)) + for (FunctionType *funType : m_currentInterface->getFunctionTypes()) { - DataType *datatype = dynamic_cast(funSymbol); - assert(datatype); - - if (datatype->isFunction()) + FunctionType::c_function_list_t &callbacks = funType->getCallbackFuns(); + if (find(callbacks.begin(), callbacks.end(), fun) != callbacks.end()) { - funType = dynamic_cast(datatype); - assert(funType); - FunctionType::c_function_list_t &callbacks = funType->getCallbackFuns(); - if (find(callbacks.begin(), callbacks.end(), fun) != callbacks.end()) + if (fun->getParameters().getMembers().size() > funType->getParameters().getMembers().size()) { - if (fun->getParameters().getMembers().size() > funType->getParameters().getMembers().size()) - { - throw syntax_error(format_string("line %d: Function definition contains more parameters than " - "function type definition from %d.\n", - fun->getFirstLine(), funType->getFirstLine()) - .c_str()); - } - else - { - callbackParam = funType->getParameters().getMembers()[fun->getParameters().getMembers().size()]; - } - break; + throw syntax_error( + format_string("line %d: Function definition contains more parameters than " + "function type definition from %d.\n", + fun->getFirstLine(), funType->getFirstLine())); + } + else + { + callbackParam = funType->getParameters().getMembers()[fun->getParameters().getMembers().size()]; } + break; } } } @@ -1260,7 +1297,48 @@ AstNode *SymbolScanner::handleParam(AstNode *node, top_down) /* Extract param data type. */ AstNode *typeNode = (*node)[1]; assert(typeNode); - DataType *dataType = lookupDataType(typeNode); + DataType *dataType = nullptr; + const Token &typeToken = typeNode->getToken(); + if (typeToken.getToken() == TOK_IFACE_SCOPE) + { + /* Find if interface and function definition exist already or create temporary. */ + AstNode *iface = typeNode->getChild(0); + AstNode *type = typeNode->getChild(1); + std::string ifaceName = iface->getToken().getStringValue(); + std::string functionTypeName = type->getToken().getStringValue(); + for (Symbol *funSymbol : m_globals->getSymbolsOfType(Symbol::symbol_type_t::kInterfaceSymbol)) + { + Interface *interface = dynamic_cast(funSymbol); + assert(interface); + + if (interface->getName() == ifaceName) + { + for (FunctionType *funcType : interface->getFunctionTypes()) + { + if (funcType->getName() == functionTypeName) + { + dataType = funcType; + break; + } + } + if (dataType == nullptr) + { + throw syntax_error(format_string("line %d: Callback name %s doesn't exists.\n", + type->getToken().getFirstLine(), functionTypeName.c_str())); + } + break; + } + } + if (dataType == nullptr) + { + /* create temporary */ + dataType = new FunctionType(type->getToken(), new Interface(iface->getToken())); + } + } + else + { + dataType = lookupDataType(typeNode); + } /* Extract param name. */ if (ident) @@ -1268,7 +1346,7 @@ AstNode *SymbolScanner::handleParam(AstNode *node, top_down) Token &tok = ident->getToken(); param = new StructMember(tok, dataType); } - else if (m_currentInterface && !funType) // Functions need param names. Types of functions don't. + else if (!isFunctionType) // Functions need param names. Types of functions don't. { throw syntax_error( format_string("line %d: Missing function param name.\n", node->getToken().getFirstLine())); @@ -1298,19 +1376,19 @@ AstNode *SymbolScanner::handleParam(AstNode *node, bottom_up) void SymbolScanner::setParameterDirection(StructMember *param, AstNode *directionNode) { /* Extract parameter direction: in/out/inout/out byref. */ - _param_direction param_direction; + param_direction_t param_direction; if (nullptr != directionNode) { switch (directionNode->getToken().getToken()) { case TOK_IN: - param_direction = kInDirection; + param_direction = param_direction_t::kInDirection; break; case TOK_OUT: - param_direction = kOutDirection; + param_direction = param_direction_t::kOutDirection; break; case TOK_INOUT: - param_direction = kInoutDirection; + param_direction = param_direction_t::kInoutDirection; break; default: delete param; @@ -1321,7 +1399,7 @@ void SymbolScanner::setParameterDirection(StructMember *param, AstNode *directio } else /* if no direction specified, default case is an 'in' variable */ { - param_direction = kInDirection; + param_direction = param_direction_t::kInDirection; } param->setDirection(param_direction); } @@ -1369,15 +1447,29 @@ DataType *SymbolScanner::lookupDataType(const AstNode *typeNode) switch (typeToken.getToken()) { case TOK_ARRAY: + { return createArrayType(typeNode); + } case TOK_IDENT: - return lookupDataTypeByName(typeToken, m_globals); - + { + DataType *dataType = nullptr; + if (m_currentInterface != nullptr) + { + dataType = lookupDataTypeByName(typeToken, &m_currentInterface->getScope()); + } + if (dataType == nullptr) + { + dataType = lookupDataTypeByName(typeToken, m_globals); + } + return dataType; + } case TOK_LIST: + { return createListType(typeNode); - - case TOK_UNION: { + } + case TOK_UNION: + { assert(nullptr != m_currentStruct); return lookupDataTypeByName(typeNode->getChild(3)->getToken(), &(m_currentStruct->getScope()), false); } @@ -1414,7 +1506,7 @@ DataType *SymbolScanner::createArrayType(const AstNode *typeNode) return array; } -Value *SymbolScanner::getValueFromSymbol(Token &tok) +Value *SymbolScanner::getValueFromSymbol(const Token &tok) { if (tok.getValue() != nullptr) { @@ -1499,7 +1591,7 @@ void SymbolScanner::addAnnotations(AstNode *childNode, Symbol *symbol) { for (auto annotation : *childNode) { - Log::SetOutputLevel logLevel(Logger::kDebug); + Log::SetOutputLevel logLevel(Logger::log_level_t::kDebug); // name can be optional for struct/enum string nameOfType; @@ -1564,19 +1656,22 @@ Annotation::program_lang_t SymbolScanner::getAnnotationLang(AstNode *annotation) string lang = annotation_value->getToken().getValue()->toString(); if (lang.compare("c") == 0) { - return Annotation::kC; + return Annotation::program_lang_t::kC; } else if (lang.compare("py") == 0) { - return Annotation::kPython; + return Annotation::program_lang_t::kPython; + } + else if (lang.compare("java") == 0) + { + return Annotation::program_lang_t::kJava; } throw semantic_error(format_string("line %d: Unsupported programming language '%s' specified.", - annotation->getToken().getFirstLine(), lang.c_str()) - .c_str()); + annotation->getToken().getFirstLine(), lang.c_str())); } - return Annotation::kAll; + return Annotation::program_lang_t::kAll; } void SymbolScanner::checkAnnotationBeforeAdding(AstNode *annotation, Symbol *symbol) @@ -1645,7 +1740,8 @@ void SymbolScanner::scanStructForAnnotations() Symbol *disSymbol; if (unionType->isNonEncapsulatedUnion()) { - string discrimintorName = structMember->getAnnStringValue(DISCRIMINATOR_ANNOTATION, Annotation::kAll); + string discrimintorName = + structMember->getAnnStringValue(DISCRIMINATOR_ANNOTATION, Annotation::program_lang_t::kAll); if (discrimintorName.empty()) { throw syntax_error(format_string("Missing discriminator for union variable %s on line %d", @@ -1750,8 +1846,7 @@ void SymbolScanner::addForwardDeclaration(DataType *dataType) { throw semantic_error(format_string("line %d: Declaring type '%s' already declared here '%d'", dataType->getFirstLine(), dataType->getName().c_str(), - symbol->getFirstLine()) - .c_str()); + symbol->getFirstLine())); } auto findDataTypeIT = m_forwardDeclarations.find(dataType->getName()); @@ -1761,8 +1856,7 @@ void SymbolScanner::addForwardDeclaration(DataType *dataType) { throw semantic_error(format_string("line %d: Declaring type '%s' already declared here '%d'", dataType->getFirstLine(), dataType->getName().c_str(), - findDataTypeIT->second->getFirstLine()) - .c_str()); + findDataTypeIT->second->getFirstLine())); } else { @@ -1781,8 +1875,7 @@ void SymbolScanner::removeForwardDeclaration(DataType *dataType) { throw semantic_error(format_string("line %d: Declaring type '%s' already declared here '%d'", dataType->getFirstLine(), dataType->getName().c_str(), - findDataTypeIT->second->getFirstLine()) - .c_str()); + findDataTypeIT->second->getFirstLine())); } m_forwardDeclarations.erase(findDataTypeIT); } @@ -1795,8 +1888,7 @@ void SymbolScanner::addGlobalSymbol(Symbol *symbol) { throw semantic_error(format_string("line %d: Declaring symbol '%s' already declared here '%d'", symbol->getFirstLine(), symbol->getName().c_str(), - findDataTypeIT->second->getFirstLine()) - .c_str()); + findDataTypeIT->second->getFirstLine())); } m_globals->addSymbol(symbol); } diff --git a/erpcgen/src/SymbolScanner.hpp b/erpcgen/src/SymbolScanner.hpp index 7a2e32a9..da70bc39 100644 --- a/erpcgen/src/SymbolScanner.hpp +++ b/erpcgen/src/SymbolScanner.hpp @@ -39,14 +39,9 @@ class SymbolScanner : public AstWalker * * @param[in] globals Global symbol scope variable. */ - explicit SymbolScanner(SymbolScope *globals) - : m_globals(globals) - , m_currentInterface(nullptr) - , m_currentStruct(nullptr) - , m_currentProgram(nullptr) - , m_currentEnum(nullptr) - , m_currentAlias(nullptr) - , m_currentUnion(nullptr) + explicit SymbolScanner(SymbolScope *globals) : + m_globals(globals), m_currentInterface(nullptr), m_currentStruct(nullptr), m_currentProgram(nullptr), + m_currentEnum(nullptr), m_currentAlias(nullptr), m_currentUnion(nullptr) { } @@ -58,15 +53,9 @@ class SymbolScanner : public AstWalker * @param[in] globals Global symbol scope variable. * @param[in] fileName name of IDL from which AST was built. */ - SymbolScanner(SymbolScope *globals, const std::string &fileName) - : AstWalker(fileName) - , m_globals(globals) - , m_currentInterface(nullptr) - , m_currentStruct(nullptr) - , m_currentProgram(nullptr) - , m_currentEnum(nullptr) - , m_currentAlias(nullptr) - , m_currentUnion(nullptr) + SymbolScanner(SymbolScope *globals, const std::string &fileName) : + AstWalker(fileName), m_globals(globals), m_currentInterface(nullptr), m_currentStruct(nullptr), + m_currentProgram(nullptr), m_currentEnum(nullptr), m_currentAlias(nullptr), m_currentUnion(nullptr) { } @@ -458,7 +447,7 @@ class SymbolScanner : public AstWalker * @exception syntax_error Thrown, when token value is null or when symbol is not defined in global symbol scope. * @exception semantic_error Thrown, when symbol type is not constant or enum member. */ - Value *getValueFromSymbol(Token &tok); + Value *getValueFromSymbol(const Token &tok); /*! * @brief This function returns the data type for a constant variable diff --git a/erpcgen/src/Token.cpp b/erpcgen/src/Token.cpp index 66becef8..634f5269 100644 --- a/erpcgen/src/Token.cpp +++ b/erpcgen/src/Token.cpp @@ -19,10 +19,7 @@ using namespace std; // Code //////////////////////////////////////////////////////////////////////////////// -Token::Token(const Token &other) -: m_token(other.m_token) -, m_value() -, m_location(other.m_location) +Token::Token(const Token &other) : m_token(other.m_token), m_value(), m_location(other.m_location) { if (other.m_value) { diff --git a/erpcgen/src/Token.hpp b/erpcgen/src/Token.hpp index 04b8be69..c1544c05 100644 --- a/erpcgen/src/Token.hpp +++ b/erpcgen/src/Token.hpp @@ -29,13 +29,7 @@ struct token_loc_t int m_lastLine; /*!< Ending line of the token. */ int m_lastChar; /*!< Ending character position on ending line. */ - token_loc_t() - : m_firstLine(0) - , m_firstChar(0) - , m_lastLine(0) - , m_lastChar(0) - { - } + token_loc_t() : m_firstLine(0), m_firstChar(0), m_lastLine(0), m_lastChar(0) {} /*! * @brief Default copy constructor. @@ -71,12 +65,7 @@ class Token * @see Token::Token(int token, Value * value, const token_loc_t & loc) * @see Token::Token(const Token & other) */ - explicit Token(int token) - : m_token(token) - , m_value() - , m_location() - { - } + explicit Token(int token) : m_token(token), m_value(), m_location() {} /*! * @brief Constructor. @@ -91,12 +80,7 @@ class Token * @see Token::Token(int token, Value * value, const token_loc_t & loc) * @see Token::Token(const Token & other) */ - Token(int token, Value *value) - : m_token(token) - , m_value(value) - , m_location() - { - } + Token(int token, Value *value) : m_token(token), m_value(value), m_location() {} /*! * @brief Constructor. @@ -112,12 +96,7 @@ class Token * @see Token::Token(int token, Value * value) * @see Token::Token(const Token & other) */ - Token(int token, Value *value, const token_loc_t &loc) - : m_token(token) - , m_value(value) - , m_location(loc) - { - } + Token(int token, Value *value, const token_loc_t &loc) : m_token(token), m_value(value), m_location(loc) {} /*! * @brief This function is copy constructor. diff --git a/erpcgen/src/UniqueIdChecker.cpp b/erpcgen/src/UniqueIdChecker.cpp index b9587041..b06dd22e 100644 --- a/erpcgen/src/UniqueIdChecker.cpp +++ b/erpcgen/src/UniqueIdChecker.cpp @@ -26,23 +26,23 @@ using namespace std; // Code //////////////////////////////////////////////////////////////////////////////// -void UniqueIdChecker::makeIdsUnique(erpcgen::InterfaceDefinition &def) +void UniqueIdChecker::makeIdsUnique(InterfaceDefinition &def) { - initUsedInterfaceIds(def.getGlobals().getSymbolsOfType(Symbol::kInterfaceSymbol)); + initUsedInterfaceIds(def.getGlobals().getSymbolsOfType(Symbol::symbol_type_t::kInterfaceSymbol)); - for (auto it : def.getGlobals().getSymbolsOfType(Symbol::kInterfaceSymbol)) + for (auto it : def.getGlobals().getSymbolsOfType(Symbol::symbol_type_t::kInterfaceSymbol)) { assert(nullptr != it); Interface *interface = dynamic_cast(it); assert(interface); - if (Annotation *interfaceId = interface->findAnnotation(ID_ANNOTATION, Annotation::kAll)) + if (Annotation *interfaceId = interface->findAnnotation(ID_ANNOTATION, Annotation::program_lang_t::kAll)) { setInterfaceId(interface, interfaceId); } initUsedFunctionIds(interface); for (auto function : interface->getFunctions()) { - if (Annotation *functionId = function->findAnnotation(ID_ANNOTATION, Annotation::kAll)) + if (Annotation *functionId = function->findAnnotation(ID_ANNOTATION, Annotation::program_lang_t::kAll)) { setFunctionId(function, functionId); } diff --git a/erpcgen/src/UniqueIdChecker.hpp b/erpcgen/src/UniqueIdChecker.hpp index 942b680d..c9390b57 100644 --- a/erpcgen/src/UniqueIdChecker.hpp +++ b/erpcgen/src/UniqueIdChecker.hpp @@ -38,7 +38,7 @@ class UniqueIdChecker * * @param[in] def Interface definition variable. */ - void makeIdsUnique(erpcgen::InterfaceDefinition &def); + void makeIdsUnique(InterfaceDefinition &def); private: /*! @@ -46,14 +46,14 @@ class UniqueIdChecker * * @param[in] ifaces Vector of interfaces. */ - void initUsedInterfaceIds(erpcgen::SymbolScope::symbol_vector_t ifaces); + void initUsedInterfaceIds(SymbolScope::symbol_vector_t ifaces); /*! * @brief This function will go through interface functions and set initial value of id number. * * @param[in] iface Interface. */ - void initUsedFunctionIds(erpcgen::Interface *iface); + void initUsedFunctionIds(Interface *iface); /*! * @brief This helper function sets a function symbol's unique id from the specified annotation. diff --git a/erpcgen/src/Value.hpp b/erpcgen/src/Value.hpp index 7ac88972..65e1f41f 100644 --- a/erpcgen/src/Value.hpp +++ b/erpcgen/src/Value.hpp @@ -32,10 +32,7 @@ class Value * * @param[in] theType Value type. */ - Value(value_type_t theType) - : m_type(theType) - { - } + Value(value_type_t theType) : m_type(theType) {} /*! * @brief Destructor. @@ -99,22 +96,15 @@ class IntegerValue : public Value /*! * @brief Constructor. */ - explicit IntegerValue(int_type_t type = kSigned) - : Value(kIntegerValue) - , m_value(0) - , m_intType(type) - { - } + explicit IntegerValue(int_type_t type = kSigned) : Value(kIntegerValue), m_value(0), m_intType(type) {} /*! * @brief Constructor. * * @param[in] value IntegerValue value. */ - explicit IntegerValue(uint64_t value, int_type_t type = kSigned) - : Value(kIntegerValue) - , m_value(value) - , m_intType(type) + explicit IntegerValue(uint64_t value, int_type_t type = kSigned) : + Value(kIntegerValue), m_value(value), m_intType(type) { } @@ -123,10 +113,7 @@ class IntegerValue : public Value * * @param[in] other IntegerValue to copy. */ - IntegerValue(const IntegerValue &other) - : Value(other.getType()) - , m_value(other.m_value) - , m_intType(other.m_intType) + IntegerValue(const IntegerValue &other) : Value(other.getType()), m_value(other.m_value), m_intType(other.m_intType) { } @@ -219,44 +206,28 @@ class FloatValue : public Value /*! * @brief Constructor. */ - FloatValue() - : Value(kFloatValue) - , m_value(0.0) - { - } + FloatValue() : Value(kFloatValue), m_value(0.0) {} /*! * @brief Constructor. * * @param[in] value FloatValue value. */ - explicit FloatValue(double value) - : Value(kFloatValue) - , m_value(value) - { - } + explicit FloatValue(double value) : Value(kFloatValue), m_value(value) {} /*! * @brief Constructor. * * @param[in] value FloatValue value. */ - explicit FloatValue(float value) - : Value(kFloatValue) - , m_value(value) - { - } + explicit FloatValue(float value) : Value(kFloatValue), m_value(value) {} /*! * @brief Copy constructor. * * @param[in] other FloatValue to copy. */ - explicit FloatValue(const FloatValue &other) - : Value(kFloatValue) - , m_value(other.m_value) - { - } + explicit FloatValue(const FloatValue &other) : Value(kFloatValue), m_value(other.m_value) {} /*! * @brief Assign operator. @@ -361,44 +332,28 @@ class StringValue : public Value /*! * @brief Constructor. */ - StringValue() - : Value(kStringValue) - , m_value() - { - } + StringValue() : Value(kStringValue), m_value() {} /*! * @brief Constructor. * * @param[in] value StringValue value. */ - explicit StringValue(const std::string &value) - : Value(kStringValue) - , m_value(value) - { - } + explicit StringValue(const std::string &value) : Value(kStringValue), m_value(value) {} /*! * @brief Constructor. * * @param[in] value StringValue value. */ - explicit StringValue(const std::string *value) - : Value(kStringValue) - , m_value(*value) - { - } + explicit StringValue(const std::string *value) : Value(kStringValue), m_value(*value) {} /*! * @brief Copy constructor. * * @param[in] other StringValue to copy. */ - StringValue(const StringValue &other) - : Value(kStringValue) - , m_value(other.m_value) - { - } + StringValue(const StringValue &other) : Value(kStringValue), m_value(other.m_value) {} /*! * @brief Get StringValue type name. diff --git a/erpcgen/src/annotations.h b/erpcgen/src/annotations.h index afa0cc60..c88f138f 100644 --- a/erpcgen/src/annotations.h +++ b/erpcgen/src/annotations.h @@ -40,6 +40,9 @@ //! Specify the symbol name. #define NAME_ANNOTATION "name" +//! Specify the namespace of program code. +#define NAMESPACE_ANNOTATION "namespace" + //! Turn off error checking code for allocations in generated output #define NO_ALLOC_ERRORS_ANNOTATION "no_alloc_errors" @@ -76,7 +79,4 @@ //! Shared memory area end address #define SHARED_MEMORY_END_ANNOTATION "shared_memory_end" -//! Place all types definitions (e.g. typedef, structs, etc.) into one file -#define TYPES_HEADER_ANNOTATION "types_header" - #endif /* _EMBEDDED_RPC__ANNOTATIONS_H_ */ diff --git a/erpcgen/src/cpptemplate/cpptempl.cpp b/erpcgen/src/cpptemplate/cpptempl.cpp index 9114f3fd..bc07180f 100644 --- a/erpcgen/src/cpptemplate/cpptempl.cpp +++ b/erpcgen/src/cpptemplate/cpptempl.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010-2014 Ryan Ginstrom // Copyright (c) 2014 Martinho Fernandes // Copyright (c) 2014-2016 Freescale Semiconductor, Inc. -// Copyright 2016 NXP +// Copyright 2016-2023 NXP // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -51,7 +51,7 @@ void replaceAll(std::string &str, const std::string &from, const std::string &to namespace impl { // Types of tokens in control statements. -enum TokenType +enum class token_type_t { INVALID_TOKEN, KEY_PATH_TOKEN, @@ -94,16 +94,16 @@ enum TokenType // Represents a token in a control statement. class Token { - TokenType m_type; + token_type_t m_type; std::string m_value; public: - Token(TokenType tokenType) + Token(token_type_t tokenType) : m_type(tokenType) , m_value() { } - Token(TokenType tokenType, const std::string &value) + Token(token_type_t tokenType, const std::string &value) : m_type(tokenType) , m_value(value) { @@ -127,7 +127,7 @@ class Token } ~Token() = default; - TokenType get_type() const { return m_type; } + token_type_t get_type() const { return m_type; } const std::string &get_value() const { return m_value; } }; @@ -157,7 +157,7 @@ class TokenIterator bool is_valid() const { return m_index < size(); } const Token *get() const; const Token *next(); - const Token *match(TokenType tokenType, const char *failure_msg = nullptr); + const Token *match(token_type_t tokenType, const char *failure_msg = nullptr); void reset() { m_index = 0; } TokenIterator &operator++(); @@ -328,7 +328,7 @@ class NodeSet : public Node }; // Lexer states for statement tokenizer. -enum lexer_state_t +enum class lexer_state_t { INIT_STATE, //!< Initial state, skip whitespace, process single char tokens. KEY_PATH_STATE, //!< Scan a key path. @@ -339,7 +339,7 @@ enum lexer_state_t struct KeywordDef { - TokenType tok; + token_type_t tok; const char *keyword; }; @@ -348,12 +348,12 @@ class TemplateParser std::string m_text; node_vector &m_top_nodes; uint32_t m_current_line; - std::stack > m_node_stack; + std::stack > m_node_stack; node_ptr m_current_node; node_vector *m_current_nodes; bool m_eol_precedes; bool m_last_was_eol; - TokenType m_until; + token_type_t m_until; public: TemplateParser(const std::string &text, node_vector &nodes); @@ -365,13 +365,13 @@ class TemplateParser void parse_stmt(); void parse_comment(); - void push_node(Node *new_node, TokenType until); + void push_node(Node *new_node, token_type_t until); void check_omit_eol(size_t pos, bool force_omit); }; std::string indent(int level); inline bool is_key_path_char(char c); -TokenType get_keyword_token(const std::string &s); +token_type_t get_keyword_token(const std::string &s); void create_id_token(token_vector &tokens, const std::string &s); int append_string_escape(std::string &str, std::function peek); token_vector tokenize_statement(const std::string &text); @@ -759,7 +759,7 @@ std::string indent(int level) return result; } -Token TokenIterator::s_endToken(END_TOKEN); +Token TokenIterator::s_endToken(token_type_t::END_TOKEN); const Token *TokenIterator::get() const { @@ -782,7 +782,7 @@ const Token *TokenIterator::next() return get(); } -const Token *TokenIterator::match(TokenType tokenType, const char *failure_msg) +const Token *TokenIterator::match(token_type_t tokenType, const char *failure_msg) { const Token *result = get(); if (result->get_type() != tokenType) @@ -804,33 +804,33 @@ inline bool is_key_path_char(char c) return (isalnum(c) || c == '.' || c == '_'); } -const KeywordDef k_keywords[] = { { TRUE_TOKEN, "true" }, { FALSE_TOKEN, "false" }, { FOR_TOKEN, "for" }, - { IN_TOKEN, "in" }, { IF_TOKEN, "if" }, { ELIF_TOKEN, "elif" }, - { ELSE_TOKEN, "else" }, { DEF_TOKEN, "def" }, { SET_TOKEN, "set" }, - { ENDFOR_TOKEN, "endfor" }, { ENDIF_TOKEN, "endif" }, { ENDDEF_TOKEN, "enddef" }, - { AND_TOKEN, "and" }, { OR_TOKEN, "or" }, { NOT_TOKEN, "not" }, - { INVALID_TOKEN, NULL } }; +const KeywordDef k_keywords[] = { { token_type_t::TRUE_TOKEN, "true" }, { token_type_t::FALSE_TOKEN, "false" }, { token_type_t::FOR_TOKEN, "for" }, + { token_type_t::IN_TOKEN, "in" }, { token_type_t::IF_TOKEN, "if" }, { token_type_t::ELIF_TOKEN, "elif" }, + { token_type_t::ELSE_TOKEN, "else" }, { token_type_t::DEF_TOKEN, "def" }, { token_type_t::SET_TOKEN, "set" }, + { token_type_t::ENDFOR_TOKEN, "endfor" }, { token_type_t::ENDIF_TOKEN, "endif" }, { token_type_t::ENDDEF_TOKEN, "enddef" }, + { token_type_t::AND_TOKEN, "and" }, { token_type_t::OR_TOKEN, "or" }, { token_type_t::NOT_TOKEN, "not" }, + { token_type_t::INVALID_TOKEN, NULL } }; -TokenType get_keyword_token(const std::string &s) +token_type_t get_keyword_token(const std::string &s) { const KeywordDef *k = k_keywords; - for (; k->tok != INVALID_TOKEN; ++k) + for (; k->tok != token_type_t::INVALID_TOKEN; ++k) { if (s == k->keyword) { return k->tok; } } - return INVALID_TOKEN; + return token_type_t::INVALID_TOKEN; } void create_id_token(token_vector &tokens, const std::string &s) { - TokenType t = get_keyword_token(s); - if (t == INVALID_TOKEN) + token_type_t t = get_keyword_token(s); + if (t == token_type_t::INVALID_TOKEN) { // Create key path token. - tokens.emplace_back(KEY_PATH_TOKEN, s); + tokens.emplace_back(token_type_t::KEY_PATH_TOKEN, s); } else { @@ -886,7 +886,7 @@ int append_string_escape(std::string &str, std::function peek) token_vector tokenize_statement(const std::string &text) { token_vector tokens; - lexer_state_t state = INIT_STATE; + lexer_state_t state = lexer_state_t::INIT_STATE; unsigned i = 0; uint32_t pos = 0; char str_open_quote = 0; @@ -902,7 +902,7 @@ token_vector tokenize_statement(const std::string &text) switch (state) { - case INIT_STATE: + case lexer_state_t::INIT_STATE: // Skip any whitespace if (isspace(c)) { @@ -921,97 +921,97 @@ token_vector tokenize_statement(const std::string &text) { is_hex_literal = false; } - state = INT_LITERAL_STATE; + state = lexer_state_t::INT_LITERAL_STATE; } else if (is_key_path_char(c)) { pos = i; - state = KEY_PATH_STATE; + state = lexer_state_t::KEY_PATH_STATE; } else if (c == '(' || c == ')' || c == ',' || c == '+' || c == '*' || c == '/' || c == '%') { - tokens.emplace_back(static_cast(c)); + tokens.emplace_back(static_cast(c)); } else if (c == '\"' || c == '\'') { str_open_quote = c; literal.clear(); - state = STRING_LITERAL_STATE; + state = lexer_state_t::STRING_LITERAL_STATE; } else if (c == '=') { if (peek(1) == '=') { - tokens.emplace_back(EQ_TOKEN); + tokens.emplace_back(token_type_t::EQ_TOKEN); ++i; } else { - tokens.emplace_back(ASSIGN_TOKEN); + tokens.emplace_back(token_type_t::ASSIGN_TOKEN); } } else if (c == '>') { if (peek(1) == '=') { - tokens.emplace_back(GE_TOKEN); + tokens.emplace_back(token_type_t::GE_TOKEN); ++i; } else { - tokens.emplace_back(GT_TOKEN); + tokens.emplace_back(token_type_t::GT_TOKEN); } } else if (c == '<') { if (peek(1) == '=') { - tokens.emplace_back(LE_TOKEN); + tokens.emplace_back(token_type_t::LE_TOKEN); ++i; } else { - tokens.emplace_back(LT_TOKEN); + tokens.emplace_back(token_type_t::LT_TOKEN); } } else if (c == '!') { if (peek(1) == '=') { - tokens.emplace_back(NEQ_TOKEN); + tokens.emplace_back(token_type_t::NEQ_TOKEN); ++i; } else { - tokens.emplace_back(NOT_TOKEN); + tokens.emplace_back(token_type_t::NOT_TOKEN); } } else if (c == '&') { if (peek(1) == '&') { - tokens.emplace_back(AND_TOKEN); + tokens.emplace_back(token_type_t::AND_TOKEN); ++i; } else { - tokens.emplace_back(CONCAT_TOKEN); + tokens.emplace_back(token_type_t::CONCAT_TOKEN); } } else if (c == '|' && peek(1) == '|') { - tokens.emplace_back(OR_TOKEN); + tokens.emplace_back(token_type_t::OR_TOKEN); ++i; } else if (c == '-') { if (peek(1) == '-') { - state = COMMENT_STATE; + state = lexer_state_t::COMMENT_STATE; } else { - tokens.emplace_back(MINUS_TOKEN); + tokens.emplace_back(token_type_t::MINUS_TOKEN); } } else @@ -1023,23 +1023,23 @@ token_vector tokenize_statement(const std::string &text) } break; - case KEY_PATH_STATE: + case lexer_state_t::KEY_PATH_STATE: if (!is_key_path_char(c)) { create_id_token(tokens, text.substr(pos, i - pos)); // Reprocess this char in the initial state. - state = INIT_STATE; + state = lexer_state_t::INIT_STATE; --i; } break; - case STRING_LITERAL_STATE: + case lexer_state_t::STRING_LITERAL_STATE: if (c == str_open_quote) { // Create the string literal token and return to init state. - tokens.emplace_back(STRING_LITERAL_TOKEN, literal); - state = INIT_STATE; + tokens.emplace_back(token_type_t::STRING_LITERAL_TOKEN, literal); + state = lexer_state_t::INIT_STATE; } else if (c == '\\') { @@ -1051,40 +1051,40 @@ token_vector tokenize_statement(const std::string &text) } break; - case INT_LITERAL_STATE: + case lexer_state_t::INT_LITERAL_STATE: if (is_hex_literal ? isxdigit(c) : isdigit(c)) { literal += c; } else { - tokens.emplace_back(INT_LITERAL_TOKEN, literal); - state = INIT_STATE; + tokens.emplace_back(token_type_t::INT_LITERAL_TOKEN, literal); + state = lexer_state_t::INIT_STATE; --i; } break; - case COMMENT_STATE: + case lexer_state_t::COMMENT_STATE: if (c == '\n') { - state = INIT_STATE; + state = lexer_state_t::INIT_STATE; } break; } } // Handle a key path terminated by end of string. - if (state == KEY_PATH_STATE) + if (state == lexer_state_t::KEY_PATH_STATE) { create_id_token(tokens, text.substr(pos, i - pos)); } - else if (state == STRING_LITERAL_STATE) + else if (state == lexer_state_t::STRING_LITERAL_STATE) { throw TemplateException("unterminated string literal"); } - else if (state == INT_LITERAL_STATE) + else if (state == lexer_state_t::INT_LITERAL_STATE) { - tokens.emplace_back(INT_LITERAL_TOKEN, literal); + tokens.emplace_back(token_type_t::INT_LITERAL_TOKEN, literal); } return tokens; @@ -1116,7 +1116,7 @@ data_ptr ExprParser::get_var_value(const std::string &path, data_list ¶ms) // Check if this is a pseudo function. bool is_fn = false; if (path == "count" || path == "empty" || path == "defined" || path == "addIndent" || path == "int" || - path == "str" || path == "upper" || path == "lower") + path == "str" || path == "upper" || path == "lower" || path == "capitalize" || path == "dump") { is_fn = true; } @@ -1191,6 +1191,25 @@ data_ptr ExprParser::get_var_value(const std::string &path, data_list ¶ms) std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); }); result = s; } + else if (path == "capitalize") + { + std::string s = params[0]->getvalue(); + if (!s.empty()) + { + s[0] = std::toupper(s[0]); + } + result = s; + } + else if (path == "dump") + { + std::stringstream buffer; + std::streambuf *old = std::cout.rdbuf(buffer.rdbuf()); + + dump_data(params[0]); + + result = buffer.str(); // text will now contain "Bla\n" + std::cout.rdbuf(old); + } } else { @@ -1217,57 +1236,57 @@ data_ptr ExprParser::get_var_value(const std::string &path, data_list ¶ms) data_ptr ExprParser::parse_factor() { - TokenType tokType = m_tok->get_type(); + token_type_t tokType = m_tok->get_type(); data_ptr result; switch (tokType) { - case NOT_TOKEN: + case token_type_t::NOT_TOKEN: m_tok.next(); result = parse_expr()->empty(); break; - case MINUS_TOKEN: + case token_type_t::MINUS_TOKEN: m_tok.next(); result = -(parse_expr()->getint()); break; - case OPEN_PAREN_TOKEN: + case token_type_t::OPEN_PAREN_TOKEN: m_tok.next(); result = parse_expr(); - m_tok.match(CLOSE_PAREN_TOKEN, "expected close paren"); + m_tok.match(token_type_t::CLOSE_PAREN_TOKEN, "expected close paren"); break; - case STRING_LITERAL_TOKEN: - result = m_tok.match(STRING_LITERAL_TOKEN)->get_value(); + case token_type_t::STRING_LITERAL_TOKEN: + result = m_tok.match(token_type_t::STRING_LITERAL_TOKEN)->get_value(); break; - case TRUE_TOKEN: + case token_type_t::TRUE_TOKEN: m_tok.next(); result = true; break; - case FALSE_TOKEN: + case token_type_t::FALSE_TOKEN: m_tok.next(); result = false; break; - case INT_LITERAL_TOKEN: { - const Token *literal = m_tok.match(INT_LITERAL_TOKEN, "expected int literal"); + case token_type_t::INT_LITERAL_TOKEN: { + const Token *literal = m_tok.match(token_type_t::INT_LITERAL_TOKEN, "expected int literal"); return new DataInt((int)std::strtol(literal->get_value().c_str(), NULL, 0)); break; } - case KEY_PATH_TOKEN: { - const Token *path = m_tok.match(KEY_PATH_TOKEN, "expected key path"); + case token_type_t::KEY_PATH_TOKEN: { + const Token *path = m_tok.match(token_type_t::KEY_PATH_TOKEN, "expected key path"); data_list params; - if (m_tok->get_type() == OPEN_PAREN_TOKEN) + if (m_tok->get_type() == token_type_t::OPEN_PAREN_TOKEN) { - m_tok.match(OPEN_PAREN_TOKEN); + m_tok.match(token_type_t::OPEN_PAREN_TOKEN); - while (m_tok->get_type() != CLOSE_PAREN_TOKEN) + while (m_tok->get_type() != token_type_t::CLOSE_PAREN_TOKEN) { params.push_back(parse_expr()); - if (m_tok->get_type() != CLOSE_PAREN_TOKEN) + if (m_tok->get_type() != token_type_t::CLOSE_PAREN_TOKEN) { - m_tok.match(COMMA_TOKEN, "expected comma"); + m_tok.match(token_type_t::COMMA_TOKEN, "expected comma"); } } - m_tok.match(CLOSE_PAREN_TOKEN, "expected close paren"); + m_tok.match(token_type_t::CLOSE_PAREN_TOKEN, "expected close paren"); } return get_var_value(path->get_value(), params); @@ -1282,8 +1301,8 @@ data_ptr ExprParser::parse_bfactor() { data_ptr ldata = parse_gfactor(); - TokenType tokType = m_tok->get_type(); - if (tokType == EQ_TOKEN || tokType == NEQ_TOKEN) + token_type_t tokType = m_tok->get_type(); + if (tokType == token_type_t::EQ_TOKEN || tokType == token_type_t::NEQ_TOKEN) { m_tok.next(); @@ -1293,10 +1312,10 @@ data_ptr ExprParser::parse_bfactor() std::string rhs = rdata->getvalue(); switch (tokType) { - case EQ_TOKEN: + case token_type_t::EQ_TOKEN: ldata = (lhs == rhs); break; - case NEQ_TOKEN: + case token_type_t::NEQ_TOKEN: ldata = (lhs != rhs); break; default: @@ -1310,8 +1329,8 @@ data_ptr ExprParser::parse_gfactor() { data_ptr ldata = parse_afactor(); - TokenType tokType = m_tok->get_type(); - if (tokType == GT_TOKEN || tokType == GE_TOKEN || tokType == LT_TOKEN || tokType == LE_TOKEN) + token_type_t tokType = m_tok->get_type(); + if (tokType == token_type_t::GT_TOKEN || tokType == token_type_t::GE_TOKEN || tokType == token_type_t::LT_TOKEN || tokType == token_type_t::LE_TOKEN) { m_tok.next(); @@ -1326,16 +1345,16 @@ data_ptr ExprParser::parse_gfactor() int r = ri->getint(); switch (tokType) { - case GT_TOKEN: + case token_type_t::GT_TOKEN: ldata = (l > r); break; - case GE_TOKEN: + case token_type_t::GE_TOKEN: ldata = (l >= r); break; - case LT_TOKEN: + case token_type_t::LT_TOKEN: ldata = (l < r); break; - case LE_TOKEN: + case token_type_t::LE_TOKEN: ldata = (l <= r); break; default: @@ -1348,16 +1367,16 @@ data_ptr ExprParser::parse_gfactor() std::string rhs = rdata->getvalue(); switch (tokType) { - case GT_TOKEN: + case token_type_t::GT_TOKEN: ldata = (lhs > rhs); break; - case GE_TOKEN: + case token_type_t::GE_TOKEN: ldata = (lhs >= rhs); break; - case LT_TOKEN: + case token_type_t::LT_TOKEN: ldata = (lhs < rhs); break; - case LE_TOKEN: + case token_type_t::LE_TOKEN: ldata = (lhs <= rhs); break; default: @@ -1372,8 +1391,8 @@ data_ptr ExprParser::parse_afactor() { data_ptr ldata = parse_mfactor(); - TokenType tokType = m_tok->get_type(); - if (tokType == PLUS_TOKEN || tokType == MINUS_TOKEN || tokType == CONCAT_TOKEN) + token_type_t tokType = m_tok->get_type(); + if (tokType == token_type_t::PLUS_TOKEN || tokType == token_type_t::MINUS_TOKEN || tokType == token_type_t::CONCAT_TOKEN) { m_tok.next(); @@ -1381,13 +1400,13 @@ data_ptr ExprParser::parse_afactor() switch (tokType) { - case CONCAT_TOKEN: + case token_type_t::CONCAT_TOKEN: ldata = ldata->getvalue() + rdata->getvalue(); break; - case PLUS_TOKEN: + case token_type_t::PLUS_TOKEN: ldata = ldata->getint() + rdata->getint(); break; - case MINUS_TOKEN: + case token_type_t::MINUS_TOKEN: ldata = ldata->getint() - rdata->getint(); break; default: @@ -1401,8 +1420,8 @@ data_ptr ExprParser::parse_mfactor() { data_ptr ldata = parse_factor(); - TokenType tokType = m_tok->get_type(); - if (tokType == TIMES_TOKEN || tokType == DIVIDE_TOKEN || tokType == MOD_TOKEN) + token_type_t tokType = m_tok->get_type(); + if (tokType == token_type_t::TIMES_TOKEN || tokType == token_type_t::DIVIDE_TOKEN || tokType == token_type_t::MOD_TOKEN) { m_tok.next(); @@ -1410,10 +1429,10 @@ data_ptr ExprParser::parse_mfactor() switch (tokType) { - case TIMES_TOKEN: + case token_type_t::TIMES_TOKEN: ldata = ldata->getint() * rdata->getint(); break; - case DIVIDE_TOKEN: + case token_type_t::DIVIDE_TOKEN: if (rdata->getint() == 0) { ldata = 0; @@ -1423,7 +1442,7 @@ data_ptr ExprParser::parse_mfactor() ldata = ldata->getint() / rdata->getint(); } break; - case MOD_TOKEN: + case token_type_t::MOD_TOKEN: if (rdata->getint() == 0) { ldata = 0; @@ -1444,9 +1463,9 @@ data_ptr ExprParser::parse_bterm() { data_ptr ldata = parse_bfactor(); - while (m_tok->get_type() == AND_TOKEN) + while (m_tok->get_type() == token_type_t::AND_TOKEN) { - m_tok.match(AND_TOKEN); + m_tok.match(token_type_t::AND_TOKEN); data_ptr rdata = parse_bfactor(); @@ -1459,9 +1478,9 @@ data_ptr ExprParser::parse_oterm() { data_ptr ldata = parse_bterm(); - while (m_tok->get_type() == OR_TOKEN) + while (m_tok->get_type() == token_type_t::OR_TOKEN) { - m_tok.match(OR_TOKEN); + m_tok.match(token_type_t::OR_TOKEN); data_ptr rdata = parse_bterm(); @@ -1478,11 +1497,11 @@ data_ptr ExprParser::parse_expr() { data_ptr ldata = parse_oterm(); - if (m_tok->get_type() == IF_TOKEN) + if (m_tok->get_type() == token_type_t::IF_TOKEN) { - m_tok.match(IF_TOKEN); + m_tok.match(token_type_t::IF_TOKEN); data_ptr predicate = parse_oterm(); - m_tok.match(ELSE_TOKEN); + m_tok.match(token_type_t::ELSE_TOKEN); data_ptr rdata = parse_oterm(); if (predicate->empty()) @@ -1607,21 +1626,21 @@ NodeFor::NodeFor(const token_vector &tokens, bool is_top, uint32_t line) , m_has_predicate(false) { TokenIterator tok(tokens); - tok.match(FOR_TOKEN, "expected 'for'"); - m_val = tok.match(KEY_PATH_TOKEN, "expected key path")->get_value(); - tok.match(IN_TOKEN, "expected 'in'"); - m_key = tok.match(KEY_PATH_TOKEN, "expected key path")->get_value(); - if (tok->get_type() != END_TOKEN) - { - tok.match(IF_TOKEN, "expected 'if'"); - while (tok->get_type() != END_TOKEN) + tok.match(token_type_t::FOR_TOKEN, "expected 'for'"); + m_val = tok.match(token_type_t::KEY_PATH_TOKEN, "expected key path")->get_value(); + tok.match(token_type_t::IN_TOKEN, "expected 'in'"); + m_key = tok.match(token_type_t::KEY_PATH_TOKEN, "expected key path")->get_value(); + if (tok->get_type() != token_type_t::END_TOKEN) + { + tok.match(token_type_t::IF_TOKEN, "expected 'if'"); + while (tok->get_type() != token_type_t::END_TOKEN) { m_predicate_tokens.push_back(*tok.get()); ++tok; } m_has_predicate = true; } - tok.match(END_TOKEN, "expected end of statement"); + tok.match(token_type_t::END_TOKEN, "expected end of statement"); } NodeType NodeFor::gettype() @@ -1704,11 +1723,11 @@ NodeIf::NodeIf(const token_vector &expr, uint32_t line) , m_else_if(nullptr) , m_if_type(NODE_TYPE_IF) { - if (expr[0].get_type() == ELIF_TOKEN) + if (expr[0].get_type() == token_type_t::ELIF_TOKEN) { m_if_type = NODE_TYPE_ELIF; } - else if (expr[0].get_type() == ELSE_TOKEN) + else if (expr[0].get_type() == token_type_t::ELSE_TOKEN) { m_if_type = NODE_TYPE_ELSE; } @@ -1746,21 +1765,21 @@ bool NodeIf::is_true(data_map &data) TokenIterator it(m_expr); if (m_if_type == NODE_TYPE_IF) { - it.match(IF_TOKEN, "expected 'if' keyword"); + it.match(token_type_t::IF_TOKEN, "expected 'if' keyword"); } else if (m_if_type == NODE_TYPE_ELIF) { - it.match(ELIF_TOKEN, "expected 'elif' keyword"); + it.match(token_type_t::ELIF_TOKEN, "expected 'elif' keyword"); } else if (m_if_type == NODE_TYPE_ELSE) { - it.match(ELSE_TOKEN, "expected 'else' keyword"); - it.match(END_TOKEN, "expected end of statement"); + it.match(token_type_t::ELSE_TOKEN, "expected 'else' keyword"); + it.match(token_type_t::END_TOKEN, "expected end of statement"); return true; } ExprParser parser(it, data); data_ptr d = parser.parse_expr(); - it.match(END_TOKEN, "expected end of statement"); + it.match(token_type_t::END_TOKEN, "expected end of statement"); return !d->empty(); } @@ -1781,26 +1800,26 @@ NodeDef::NodeDef(const token_vector &expr, uint32_t line) : NodeParent(line) { TokenIterator tok(expr); - tok.match(DEF_TOKEN, "expected 'def'"); + tok.match(token_type_t::DEF_TOKEN, "expected 'def'"); - m_name = tok.match(KEY_PATH_TOKEN, "expected key path")->get_value(); + m_name = tok.match(token_type_t::KEY_PATH_TOKEN, "expected key path")->get_value(); - if (tok->get_type() == OPEN_PAREN_TOKEN) + if (tok->get_type() == token_type_t::OPEN_PAREN_TOKEN) { - tok.match(OPEN_PAREN_TOKEN); + tok.match(token_type_t::OPEN_PAREN_TOKEN); - while (tok->get_type() != CLOSE_PAREN_TOKEN) + while (tok->get_type() != token_type_t::CLOSE_PAREN_TOKEN) { - m_params.push_back(tok.match(KEY_PATH_TOKEN, "expected key path")->get_value()); + m_params.push_back(tok.match(token_type_t::KEY_PATH_TOKEN, "expected key path")->get_value()); - if (tok->get_type() != CLOSE_PAREN_TOKEN) + if (tok->get_type() != token_type_t::CLOSE_PAREN_TOKEN) { - tok.match(COMMA_TOKEN, "expected comma"); + tok.match(token_type_t::COMMA_TOKEN, "expected comma"); } } - tok.match(CLOSE_PAREN_TOKEN, "expected close paren"); + tok.match(token_type_t::CLOSE_PAREN_TOKEN, "expected close paren"); } - tok.match(END_TOKEN, "expected end of statement"); + tok.match(token_type_t::END_TOKEN, "expected end of statement"); } NodeType NodeDef::gettype() @@ -1832,12 +1851,12 @@ void NodeSet::gettext(std::ostream &stream, data_map &data) { (void)stream; TokenIterator tok(m_expr); - tok.match(SET_TOKEN, "expected 'set'"); - std::string path = tok.match(KEY_PATH_TOKEN, "expected key path")->get_value(); - tok.match(ASSIGN_TOKEN); + tok.match(token_type_t::SET_TOKEN, "expected 'set'"); + std::string path = tok.match(token_type_t::KEY_PATH_TOKEN, "expected key path")->get_value(); + tok.match(token_type_t::ASSIGN_TOKEN); ExprParser parser(tok, data); data_ptr value = parser.parse_expr(); - tok.match(END_TOKEN, "expected end of statement"); + tok.match(token_type_t::END_TOKEN, "expected end of statement"); // Follow the key path, creating the key if missing. data_ptr &target = data.parse_path(path, true); @@ -1863,7 +1882,7 @@ TemplateParser::TemplateParser(const std::string &text, node_vector &nodes) , m_current_nodes(&m_top_nodes) , m_eol_precedes(true) , m_last_was_eol(true) -, m_until(INVALID_TOKEN) +, m_until(token_type_t::INVALID_TOKEN) { } @@ -1974,7 +1993,7 @@ void TemplateParser::parse_var() m_last_was_eol = false; } -void TemplateParser::push_node(Node *new_node, TokenType until) +void TemplateParser::push_node(Node *new_node, token_type_t until) { m_node_stack.push(std::make_pair(m_current_node, m_until)); m_current_node = node_ptr(new_node); @@ -2003,21 +2022,21 @@ void TemplateParser::parse_stmt() token_vector stmt_tokens = tokenize_statement(stmt_text); if (!stmt_tokens.empty()) { - TokenType first_token_type = stmt_tokens[0].get_type(); + token_type_t first_token_type = stmt_tokens[0].get_type(); // Create control statement nodes. switch (first_token_type) { - case FOR_TOKEN: - push_node(new NodeFor(stmt_tokens, m_node_stack.empty(), m_current_line), ENDFOR_TOKEN); + case token_type_t::FOR_TOKEN: + push_node(new NodeFor(stmt_tokens, m_node_stack.empty(), m_current_line), token_type_t::ENDFOR_TOKEN); break; - case IF_TOKEN: - push_node(new NodeIf(stmt_tokens, m_current_line), ENDIF_TOKEN); + case token_type_t::IF_TOKEN: + push_node(new NodeIf(stmt_tokens, m_current_line), token_type_t::ENDIF_TOKEN); break; - case ELIF_TOKEN: - case ELSE_TOKEN: { + case token_type_t::ELIF_TOKEN: + case token_type_t::ELSE_TOKEN: { auto current_if = dynamic_cast(m_current_node.get()); if (!current_if) { @@ -2035,17 +2054,17 @@ void TemplateParser::parse_stmt() break; } - case DEF_TOKEN: - push_node(new NodeDef(stmt_tokens, m_current_line), ENDDEF_TOKEN); + case token_type_t::DEF_TOKEN: + push_node(new NodeDef(stmt_tokens, m_current_line), token_type_t::ENDDEF_TOKEN); break; - case SET_TOKEN: + case token_type_t::SET_TOKEN: m_current_nodes->push_back(node_ptr(new NodeSet(stmt_tokens, m_current_line))); break; - case ENDFOR_TOKEN: - case ENDIF_TOKEN: - case ENDDEF_TOKEN: + case token_type_t::ENDFOR_TOKEN: + case token_type_t::ENDIF_TOKEN: + case token_type_t::ENDDEF_TOKEN: if (m_until == first_token_type) { assert(!m_node_stack.empty()); @@ -2061,7 +2080,7 @@ void TemplateParser::parse_stmt() { m_current_node.reset(); m_current_nodes = &m_top_nodes; - m_until = INVALID_TOKEN; + m_until = token_type_t::INVALID_TOKEN; } } else diff --git a/erpcgen/src/cpptemplate/cpptempl.hpp b/erpcgen/src/cpptemplate/cpptempl.hpp index 1527eed2..cf71a499 100644 --- a/erpcgen/src/cpptemplate/cpptempl.hpp +++ b/erpcgen/src/cpptemplate/cpptempl.hpp @@ -45,10 +45,10 @@ #include #include #include +#include #include #include #include -#include namespace cpptempl { diff --git a/erpcgen/src/erpcgen.cpp b/erpcgen/src/erpcgen.cpp index 0e2d180b..e5288c72 100644 --- a/erpcgen/src/erpcgen.cpp +++ b/erpcgen/src/erpcgen.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016-2023 NXP * All rights reserved. * * @@ -14,6 +14,7 @@ #include "InterfaceDefinition.hpp" #include "Logging.hpp" #include "PythonGenerator.hpp" +#include "JavaGenerator.hpp" #include "SearchPath.hpp" #include "UniqueIdChecker.hpp" #include "options.hpp" @@ -51,6 +52,7 @@ static const char *k_optionsDefinition[] = { "?|help", "I:path ", "g:generate ", "c:codec ", + "p:package ", NULL }; /*! Help string. */ @@ -63,10 +65,12 @@ const char k_usageText[] = -I/--path Add search path for imports\n\ -g/--generate Select the output language (default is C)\n\ -c/--codec Specify used codec type\n\ + -p/--package Java app package (com.example.app) (only for Java)\n\ \n\ Available languages (use with -g option):\n\ c C/C++\n\ py Python\n\ + java Java\n\ \n\ Available codecs (use with --c option):\n\ basic BasicCodec\n\ @@ -86,7 +90,7 @@ Available codecs (use with --c option):\n\ class erpcgenTool { protected: - enum verbose_type_t + enum class verbose_type_t { kWarning, kInfo, @@ -94,10 +98,11 @@ class erpcgenTool kExtraDebug }; /*!< Types of verbose outputs from erpcgen application. */ - enum languages_t + enum class languages_t { kCLanguage, kPythonLanguage, + kJavaLanguage, }; /*!< Generated outputs format. */ typedef vector string_vector_t; /*!< Vector of positional arguments. */ @@ -111,6 +116,7 @@ class erpcgenTool string_vector_t m_positionalArgs; /*!< Positional arguments. */ languages_t m_outputLanguage; /*!< Output language we're generating. */ InterfaceDefinition::codec_t m_codec; /*!< Used codec type. */ + string m_javaPackageName; /*!< Used java package. */ public: /*! @@ -121,19 +127,13 @@ class erpcgenTool * * Creates the singleton logger instance. */ - erpcgenTool(int argc, char *argv[]) - : m_argc(argc) - , m_argv(argv) - , m_logger(0) - , m_verboseType(kWarning) - , m_outputFilePath(NULL) - , m_ErpcFile(NULL) - , m_outputLanguage(kCLanguage) - , m_codec(InterfaceDefinition::kNotSpecified) + erpcgenTool(int argc, char *argv[]) : + m_argc(argc), m_argv(argv), m_logger(0), m_verboseType(verbose_type_t::kWarning), m_outputFilePath(NULL), + m_ErpcFile(NULL), m_outputLanguage(languages_t::kCLanguage), m_codec(InterfaceDefinition::codec_t::kNotSpecified) { // create logger instance m_logger = new StdoutLogger(); - m_logger->setFilterLevel(Logger::kWarning); + m_logger->setFilterLevel(Logger::log_level_t::kWarning); Log::setLogger(m_logger); } @@ -183,7 +183,7 @@ class erpcgenTool break; case 'v': - if (m_verboseType != kExtraDebug) + if (m_verboseType != verbose_type_t::kExtraDebug) { m_verboseType = (verbose_type_t)(((int)m_verboseType) + 1); } @@ -193,38 +193,50 @@ class erpcgenTool PathSearcher::getGlobalSearcher().addSearchPath(optarg); break; - case 'g': { + case 'g': + { string lang = optarg; if (lang == "c") { - m_outputLanguage = kCLanguage; + m_outputLanguage = languages_t::kCLanguage; } else if (lang == "py") { - m_outputLanguage = kPythonLanguage; + m_outputLanguage = languages_t::kPythonLanguage; + } + else if (lang == "java") + { + m_outputLanguage = languages_t::kJavaLanguage; } else { - Log::error(format_string("error: unknown language %s", lang.c_str()).c_str()); + Log::error("error: unknown language %s", lang.c_str()); return 1; } break; } - case 'c': { + case 'c': + { string codec = optarg; if (codec.compare("basic") == 0) { - m_codec = InterfaceDefinition::kBasicCodec; + m_codec = InterfaceDefinition::codec_t::kBasicCodec; } else { - Log::error(format_string("error: unknown codec type %s", codec.c_str()).c_str()); + Log::error("error: unknown codec type %s", codec.c_str()); return 1; } break; } + case 'p': + { + m_javaPackageName = optarg; + break; + } + default: Log::error("error: unrecognized option\n\n"); printUsage(options); @@ -312,12 +324,16 @@ class erpcgenTool switch (m_outputLanguage) { - case kCLanguage: + case languages_t::kCLanguage: CGenerator(&def).generate(); break; - case kPythonLanguage: + case languages_t::kPythonLanguage: PythonGenerator(&def).generate(); break; + case languages_t::kJavaLanguage: + // TODO: Check java package + JavaGenerator(&def, m_javaPackageName).generate(); + break; } } catch (exception &e) @@ -356,17 +372,17 @@ class erpcgenTool // if the user has selected quiet mode, it overrides verbose switch (m_verboseType) { - case kWarning: - Log::getLogger()->setFilterLevel(Logger::kWarning); + case verbose_type_t::kWarning: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kWarning); break; - case kInfo: - Log::getLogger()->setFilterLevel(Logger::kInfo); + case verbose_type_t::kInfo: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kInfo); break; - case kDebug: - Log::getLogger()->setFilterLevel(Logger::kDebug); + case verbose_type_t::kDebug: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kDebug); break; - case kExtraDebug: - Log::getLogger()->setFilterLevel(Logger::kDebug2); + case verbose_type_t::kExtraDebug: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kDebug2); break; } } diff --git a/erpcgen/src/erpcgen_lexer.l b/erpcgen/src/erpcgen_lexer.l index 1c0a1b20..9bbdd998 100644 --- a/erpcgen/src/erpcgen_lexer.l +++ b/erpcgen/src/erpcgen_lexer.l @@ -237,6 +237,8 @@ void { return TOK_VOID; } "->" { return TOK_ARROW; } +"::" { return TOK_IFACE_SCOPE; } + [@{}()\[\]<>=,;:+\-*/%^~&|] { return yytext[0]; } \"(ESC|[^\"])*\" { diff --git a/erpcgen/src/erpcgen_parser.y b/erpcgen/src/erpcgen_parser.y index 46586703..f49eb396 100644 --- a/erpcgen/src/erpcgen_parser.y +++ b/erpcgen/src/erpcgen_parser.y @@ -155,6 +155,7 @@ token_loc_t mergeLocation(const token_loc_t & l1, const token_loc_t & l2); %token TOK_ML_COMMENT "doxygen ml. comment" %token TOK_IL_COMMENT "doxygen il. comment" %token TOK_PROGRAM "program" +%token TOK_IFACE_SCOPE "::" %token END 0 "end of file" // virtual tokens used for AST @@ -210,6 +211,8 @@ token_loc_t mergeLocation(const token_loc_t & l1, const token_loc_t & l2); %type function_return_type %type function_type_base_def %type function_type_def +%type function_cb_type_def +%type function_cb_type_list %type ident %type ident_opt %type int_const_expr @@ -225,6 +228,7 @@ token_loc_t mergeLocation(const token_loc_t & l1, const token_loc_t & l2); %type program %type root_def %type simple_data_type +%type simple_data_type_scope %type string_literal %type struct_def %type struct_data_type @@ -339,11 +343,6 @@ definition_base : const_def { $$ = $interface_def; } - | - function_type_def - { - $$ = $function_type_def; - } ; import_stmt : TOK_IMPORT TOK_STRING_LITERAL @@ -451,7 +450,7 @@ interface_def : TOK_INTERFACE[iface] ident[name] '{' function_def_list_opt[f ; function_def_list_opt - : function_def_list + : function_def_list { $$ = $function_def_list; } @@ -465,7 +464,12 @@ function_def_list_opt * TOK_CHILDREN -> ( function_def* ) */ function_def_list - : function_def + : function_cb_type_list function_def + { + $function_cb_type_list->appendChild($function_def); + $$ = $function_cb_type_list; + } + | function_def { $$ = new AstNode(Token(TOK_CHILDREN)); $$->appendChild($function_def); @@ -477,13 +481,39 @@ function_def_list } ; +function_cb_type_def + : doxy_ml_comment_opt annotation_list_opt TOK_TYPE function_type_def comma_semi_opt doxy_il_comment_opt + { + $$ = $function_type_def; + $$->appendChild(new AstNode(*$TOK_TYPE)); + $$->appendChild($annotation_list_opt); + $$->appendChild($doxy_ml_comment_opt); + $$->appendChild($doxy_il_comment_opt); + } + ; + +function_cb_type_list + : function_cb_type_def + { + $$ = new AstNode(Token(TOK_CHILDREN)); + $$->appendChild($function_cb_type_def); + } + | function_cb_type_list[fun_type_list] function_cb_type_def + { + $fun_type_list->appendChild($function_cb_type_def); + $$ = $fun_type_list; + } + ; + function_def : doxy_ml_comment_opt annotation_list_opt function_type_base_def comma_semi_opt doxy_il_comment_opt { $$ = $function_type_base_def; + $$->appendChild(NULL); /* Compatibility with function type definition */ $$->appendChild($annotation_list_opt); $$->appendChild($doxy_ml_comment_opt); $$->appendChild($doxy_il_comment_opt); } + ; function_type_base_def : function_type_def @@ -592,7 +622,7 @@ param_list_in : param_def_in /* * TOK_PARAM -> ( ident simple_data_type ( TOK_CHILDREN -> TOK_ANNOTATION* ) ) */ -param_def : param_dir[dir] simple_data_type[datatype] ident_opt[name] annotation_list_opt[annotations] +param_def : param_dir[dir] simple_data_type_scope[datatype] ident_opt[name] annotation_list_opt[annotations] { $$ = new AstNode(Token(TOK_PARAM, NULL, @name)); $$->appendChild($name); @@ -603,7 +633,7 @@ param_def : param_dir[dir] simple_data_type[datatype] ident_opt[name] an } ; -param_def_in : param_dir_in[dir] simple_data_type[datatype] ident_opt[name] annotation_list_opt[annotations] +param_def_in : param_dir_in[dir] simple_data_type_scope[datatype] ident_opt[name] annotation_list_opt[annotations] { $$ = new AstNode(Token(TOK_PARAM, NULL, @name)); $$->appendChild($name); @@ -892,6 +922,19 @@ union_member } ; +simple_data_type_scope + : ident TOK_IFACE_SCOPE typename + { + $$ = new AstNode(Token(TOK_IFACE_SCOPE)); + $$->appendChild($ident); + $$->appendChild($typename); + } + | simple_data_type + { + $$ = $simple_data_type; + } + ; + simple_data_type : list_type { @@ -905,7 +948,6 @@ simple_data_type { $$ = $typename; } - ; data_type : simple_data_type diff --git a/erpcgen/src/options.cpp b/erpcgen/src/options.cpp index 07c231ec..db954fbe 100644 --- a/erpcgen/src/options.cpp +++ b/erpcgen/src/options.cpp @@ -74,10 +74,7 @@ static const char endl = '\n'; class ostream { public: - ostream(FILE *fileptr) - : fp(fileptr) - { - } + ostream(FILE *fileptr) : fp(fileptr) {} ostream &operator<<(char ch); @@ -159,12 +156,8 @@ void OptArgvIter::rewind(void) static const char WHITESPACE[] = " \t\n\r\v\f"; const char *OptStrTokIter::default_delims = WHITESPACE; -OptStrTokIter::OptStrTokIter(const char *tokens, const char *arg_delimiters) -: len(unsigned(strlen(tokens))) -, str(tokens) -, seps(arg_delimiters) -, cur(NULLSTR) -, tokstr(NULLSTR) +OptStrTokIter::OptStrTokIter(const char *tokens, const char *arg_delimiters) : +len(unsigned(strlen(tokens))), str(tokens), seps(arg_delimiters), cur(NULLSTR), tokstr(NULLSTR) { if (seps == NULL) seps = default_delims; @@ -220,9 +213,7 @@ enum const unsigned OptIstreamIter::MAX_LINE_LEN = 1024; // Constructor -OptIstreamIter::OptIstreamIter(istream &input) -: is(input) -, tok_iter(NULL) +OptIstreamIter::OptIstreamIter(istream &input) : is(input), tok_iter(NULL) { #ifdef USE_STDIO fprintf(stderr, "%s: Can't use OptIstreamIter class:\n", "OptIstreamIter::OptIstreamIter"); @@ -330,18 +321,18 @@ inline static int isEndOpts(const char *token) inline static int isOption(unsigned flags, const char *arg) { return ((arg != nullptr) && ((*arg != '\0') || (arg[1] != '\0')) && - ((*arg == '-') || ((flags & Options::PLUS) && (*arg == '+')))); + ((*arg == '-') || ((flags & static_cast(Options::OptCtrl::PLUS)) && (*arg == '+')))); } // See if we should be parsing only options or if we also need to // parse positional arguments inline static int isOptsOnly(unsigned flags) { - return (flags & Options::PARSE_POS) ? 0 : 1; + return (flags & static_cast(Options::OptCtrl::PARSE_POS)) ? 0 : 1; } // return values for a keyword matching function -enum kwdmatch_t +enum class kwdmatch_t { NO_MATCH, PARTIAL_MATCH, @@ -381,21 +372,21 @@ static kwdmatch_t kwdmatch(const char *src, const char *attempt, int len = 0) int i; if (src == attempt) - return EXACT_MATCH; + return kwdmatch_t::EXACT_MATCH; if ((src == NULL) || (attempt == NULL)) - return NO_MATCH; + return kwdmatch_t::NO_MATCH; if ((!*src) && (!*attempt)) - return EXACT_MATCH; + return kwdmatch_t::EXACT_MATCH; if ((!*src) || (!*attempt)) - return NO_MATCH; + return kwdmatch_t::NO_MATCH; for (i = 0; ((i < len) || (len == 0)) && (attempt[i]) && (attempt[i] != ' '); i++) { if (TOLOWER(src[i]) != TOLOWER(attempt[i])) - return NO_MATCH; + return kwdmatch_t::NO_MATCH; } - return (src[i]) ? PARTIAL_MATCH : EXACT_MATCH; + return (src[i]) ? kwdmatch_t::PARTIAL_MATCH : kwdmatch_t::EXACT_MATCH; } // **************************************************************** OptionSpec @@ -408,20 +399,14 @@ static kwdmatch_t kwdmatch(const char *src, const char *attempt, int len = 0) class OptionSpec { public: - OptionSpec(const char *decl = NULLSTR) - : hidden(0) - , spec(decl) + OptionSpec(const char *decl = NULLSTR) : hidden(0), spec(decl) { if (spec == NULL) spec = NULL_spec; CheckHidden(); } - OptionSpec(const OptionSpec &cp) - : hidden(cp.hidden) - , spec(cp.spec) - { - } + OptionSpec(const OptionSpec &cp) : hidden(cp.hidden), spec(cp.spec) {} // NOTE: use default destructor! @@ -572,11 +557,13 @@ unsigned OptionSpec::Format(char *buf, unsigned optctrls) const value_len = sizeof(default_value) - 1; } - if ((optctrls & Options::SHORT_ONLY) && ((!isNullOpt(optchar)) || (optctrls & Options::NOGUESSING))) + if ((optctrls & static_cast(Options::OptCtrl::SHORT_ONLY)) && + ((!isNullOpt(optchar)) || (optctrls & static_cast(Options::OptCtrl::NOGUESSING)))) { longopt = NULLSTR; } - if ((optctrls & Options::LONG_ONLY) && (longopt || (optctrls & Options::NOGUESSING))) + if ((optctrls & static_cast(Options::OptCtrl::LONG_ONLY)) && + (longopt || (optctrls & static_cast(Options::OptCtrl::NOGUESSING)))) { optchar = '\0'; } @@ -602,7 +589,8 @@ unsigned OptionSpec::Format(char *buf, unsigned optctrls) const if (longopt) { *(p++) = '-'; - if (!(optctrls & (Options::LONG_ONLY | Options::SHORT_ONLY))) + if (!(optctrls & + (static_cast(Options::OptCtrl::LONG_ONLY) | static_cast(Options::OptCtrl::SHORT_ONLY)))) { *(p++) = '-'; } @@ -642,13 +630,9 @@ unsigned OptionSpec::Format(char *buf, unsigned optctrls) const #define DIR_SEP_CHAR '/' #endif -Options::Options(const char *arg_name, const char *const optv[]) -: explicit_end(0) -, optctrls(DEFAULT) -, optvec(optv) -, nextchar(NULLSTR) -, listopt(NULLSTR) -, cmdname(arg_name) +Options::Options(const char *arg_name, const char *const optv[]) : +explicit_end(0), optctrls(static_cast(OptCtrl::DEFAULT)), optvec(optv), nextchar(NULLSTR), listopt(NULLSTR), +cmdname(arg_name) { const char *basename = ::strrchr(cmdname, DIR_SEP_CHAR); if (basename) @@ -785,11 +769,11 @@ const char *Options::match_longopt(const char *opt, int len, int &ambiguous) con if (longopt == NULL) continue; result = kwdmatch(longopt, opt, len); - if (result == EXACT_MATCH) + if (result == kwdmatch_t::EXACT_MATCH) { return optspec; } - else if (result == PARTIAL_MATCH) + else if (result == kwdmatch_t::PARTIAL_MATCH) { if (matched) { @@ -827,7 +811,7 @@ const char *Options::match_longopt(const char *opt, int len, int &ambiguous) con // ^SIDE-EFFECTS: // - iter is advanced when an argument completely parsed // - optarg is modified to point to any option argument -// - if Options::QUIET is not set, error messages are printed on cerr +// - if Options::OptCtrl::QUIET is not set, error messages are printed on cerr // // ^RETURN-VALUE: // 'c' if the -c option was matched (optarg points to its argument) @@ -842,21 +826,22 @@ int Options::parse_opt(OptIter &iter, const char *&optarg) listopt = NULLSTR; // reset the list pointer if ((optvec == NULL) || (!*optvec)) - return Options::ENDOPTS; + return static_cast(Options::OptRC::ENDOPTS); // Try to match a known option - OptionSpec optspec = match_opt(*(nextchar++), (optctrls & Options::ANYCASE)); + OptionSpec optspec = match_opt(*(nextchar++), (optctrls & static_cast(Options::OptCtrl::ANYCASE))); // Check for an unknown option if (optspec.isNULL()) { // See if this was a long-option in disguise - if (!(optctrls & Options::NOGUESSING)) + if (!(optctrls & static_cast(Options::OptCtrl::NOGUESSING))) { unsigned save_ctrls = optctrls; const char *save_nextchar = nextchar; nextchar -= 1; - optctrls |= (Options::QUIET | Options::NOGUESSING); + optctrls |= + (static_cast(Options::OptCtrl::QUIET) | static_cast(Options::OptCtrl::NOGUESSING)); int optchar = parse_longopt(iter, optarg); optctrls = save_ctrls; if (optchar > 0) @@ -868,12 +853,12 @@ int Options::parse_opt(OptIter &iter, const char *&optarg) nextchar = save_nextchar; } } - if (!(optctrls & Options::QUIET)) + if (!(optctrls & static_cast(Options::OptCtrl::QUIET))) { cerr << cmdname << ": unknown option -" << *(nextchar - 1) << "." << endl; } optarg = (nextchar - 1); // record the bad option in optarg - return Options::BADCHAR; + return static_cast(Options::OptRC::BADCHAR); } // If no argument is taken, then leave now @@ -906,7 +891,7 @@ int Options::parse_opt(OptIter &iter, const char *&optarg) // No argument given - if its required, thats an error optarg = NULLSTR; - if (optspec.isValRequired() && !(optctrls & Options::QUIET)) + if (optspec.isValRequired() && !(optctrls & static_cast(Options::OptCtrl::QUIET))) { cerr << cmdname << ": argument required for -" << optspec.OptChar() << " option." << endl; } @@ -934,7 +919,7 @@ int Options::parse_opt(OptIter &iter, const char *&optarg) // ^SIDE-EFFECTS: // - iter is advanced when an argument completely parsed // - optarg is modified to point to any option argument -// - if Options::QUIET is not set, error messages are printed on cerr +// - if Options::OptCtrl::QUIET is not set, error messages are printed on cerr // // ^RETURN-VALUE: // 'c' if the the long-option corresponding to the -c option was matched @@ -952,7 +937,7 @@ int Options::parse_longopt(OptIter &iter, const char *&optarg) listopt = NULLSTR; // reset the list-spec if ((optvec == NULL) || (!*optvec)) - return Options::ENDOPTS; + return static_cast(Options::OptRC::ENDOPTS); // if a value is supplied in this argv element, get it now const char *val = strpbrk(nextchar, ":="); @@ -969,11 +954,12 @@ int Options::parse_longopt(OptIter &iter, const char *&optarg) if (optspec.isNULL()) { // See if this was a short-option in disguise - if ((!ambiguous) && (!(optctrls & Options::NOGUESSING))) + if ((!ambiguous) && (!(optctrls & static_cast(Options::OptCtrl::NOGUESSING)))) { unsigned save_ctrls = optctrls; const char *save_nextchar = nextchar; - optctrls |= (Options::QUIET | Options::NOGUESSING); + optctrls |= + (static_cast(Options::OptCtrl::QUIET) | static_cast(Options::OptCtrl::NOGUESSING)); int optchar = parse_opt(iter, optarg); optctrls = save_ctrls; if (optchar > 0) @@ -985,22 +971,25 @@ int Options::parse_longopt(OptIter &iter, const char *&optarg) nextchar = save_nextchar; } } - if (!(optctrls & Options::QUIET)) + if (!(optctrls & static_cast(Options::OptCtrl::QUIET))) { cerr << cmdname << ": " << ((ambiguous) ? "ambiguous" : "unknown") << " option " - << ((optctrls & Options::LONG_ONLY) ? "-" : "--") << nextchar << "." << endl; + << ((optctrls & static_cast(Options::OptCtrl::LONG_ONLY)) ? "-" : "--") << nextchar << "." + << endl; } optarg = nextchar; // record the bad option in optarg nextchar = NULLSTR; // we've exhausted this argument - return (ambiguous) ? Options::AMBIGUOUS : Options::BADKWD; + return (ambiguous) ? static_cast(Options::OptRC::AMBIGUOUS) : + static_cast(Options::OptRC::BADKWD); } // If no argument is taken, then leave now if (optspec.isNoArg()) { - if ((val) && !(optctrls & Options::QUIET)) + if ((val) && !(optctrls & static_cast(Options::OptCtrl::QUIET))) { - cerr << cmdname << ": option " << ((optctrls & Options::LONG_ONLY) ? "-" : "--") << optspec.LongOpt() + cerr << cmdname << ": option " + << ((optctrls & static_cast(Options::OptCtrl::LONG_ONLY)) ? "-" : "--") << optspec.LongOpt() << " does NOT take an argument." << endl; } optarg = val; // record the unexpected argument @@ -1032,7 +1021,7 @@ int Options::parse_longopt(OptIter &iter, const char *&optarg) // No argument given - if its required, thats an error optarg = NULLSTR; - if (optspec.isValRequired() && !(optctrls & Options::QUIET)) + if (optspec.isValRequired() && !(optctrls & static_cast(Options::OptCtrl::QUIET))) { const char *longopt = optspec.LongOpt(); const char *spc = ::strchr(longopt, ' '); @@ -1045,7 +1034,8 @@ int Options::parse_longopt(OptIter &iter, const char *&optarg) { longopt_len = (int)::strlen(longopt); } - cerr << cmdname << ": argument required for " << ((optctrls & Options::LONG_ONLY) ? "-" : "--"); + cerr << cmdname << ": argument required for " + << ((optctrls & static_cast(Options::OptCtrl::LONG_ONLY)) ? "-" : "--"); cerr.write(longopt, longopt_len) << " option." << endl; } nextchar = NULLSTR; // we exhausted the rest of this arg @@ -1165,7 +1155,7 @@ void Options::usage(ostream &os, const char *positionals) const // ^SIDE-EFFECTS: // - iter is advanced when an argument is completely parsed // - optarg is modified to point to any option argument -// - if Options::QUIET is not set, error messages are printed on cerr +// - if Options::OptCtrl::QUIET is not set, error messages are printed on cerr // // ^RETURN-VALUE: // 0 if all options have been parsed. @@ -1203,7 +1193,7 @@ int Options::operator()(OptIter &iter, const char *&optarg) if (arg == NULL) { listopt = NULLSTR; - return Options::ENDOPTS; + return static_cast(Options::OptRC::ENDOPTS); } else if ((!explicit_end) && isEndOpts(arg)) { @@ -1211,7 +1201,7 @@ int Options::operator()(OptIter &iter, const char *&optarg) listopt = NULLSTR; explicit_end = 1; if (parse_opts_only) - return Options::ENDOPTS; + return static_cast(Options::OptRC::ENDOPTS); get_next_arg = 1; // make sure we look at the next argument. } } while (get_next_arg); @@ -1221,27 +1211,27 @@ int Options::operator()(OptIter &iter, const char *&optarg) { if (parse_opts_only) { - return Options::ENDOPTS; + return static_cast(Options::OptRC::ENDOPTS); } else { optarg = arg; // set optarg to the positional argument iter.next(); // advance iterator to the next argument - return Options::POSITIONAL; + return static_cast(Options::OptRC::POSITIONAL); } } iter.next(); // pass the argument that arg already points to // See if we have a long option ... - if (!(optctrls & Options::SHORT_ONLY)) + if (!(optctrls & static_cast(Options::OptCtrl::SHORT_ONLY))) { if ((*arg == '-') && (arg[1] == '-')) { nextchar = arg + 2; return parse_longopt(iter, optarg); } - else if ((optctrls & Options::PLUS) && (*arg == '+')) + else if ((optctrls & static_cast(Options::OptCtrl::PLUS)) && (*arg == '+')) { nextchar = arg + 1; return parse_longopt(iter, optarg); @@ -1250,7 +1240,7 @@ int Options::operator()(OptIter &iter, const char *&optarg) if (*arg == '-') { nextchar = arg + 1; - if (optctrls & Options::LONG_ONLY) + if (optctrls & static_cast(Options::OptCtrl::LONG_ONLY)) { return parse_longopt(iter, optarg); } diff --git a/erpcgen/src/options.hpp b/erpcgen/src/options.hpp index 371daca8..9cb83111 100644 --- a/erpcgen/src/options.hpp +++ b/erpcgen/src/options.hpp @@ -102,19 +102,9 @@ class OptArgvIter : public OptIterRwd const char *const *av; // arg vector public: - explicit OptArgvIter(const char *const argv[]) - : ndx(0) - , ac(-1) - , av(argv) - { - } + explicit OptArgvIter(const char *const argv[]) : ndx(0), ac(-1), av(argv) {} - OptArgvIter(int argc, const char *const argv[]) - : ndx(0) - , ac(argc) - , av(argv) - { - } + OptArgvIter(int argc, const char *const argv[]) : ndx(0), ac(argc), av(argv) {} virtual ~OptArgvIter(void); @@ -383,7 +373,7 @@ class Options int parse_longopt(OptIter &iter, const char *&optarg); public: - enum OptCtrl + enum class OptCtrl { DEFAULT = 0x00, //!< Default setting ANYCASE = 0x01, //!< Ignore case when matching short-options @@ -410,7 +400,7 @@ class Options //! Error return values for operator() //! - enum OptRC + enum class OptRC { ENDOPTS = 0, BADCHAR = -1, @@ -464,7 +454,7 @@ class Options //! the positonal argument (and "iter" is advanced to the next argument //! in the iterator). //! - //! Unless Options::QUIET is used, missing option-arguments and + //! Unless Options::OptCtrl::QUIET is used, missing option-arguments and //! invalid options (and the like) will automatically cause error //! messages to be issued to cerr. int operator()(OptIter &iter, const char *&optarg); diff --git a/erpcgen/src/smart_ptr.hpp b/erpcgen/src/smart_ptr.hpp index 23149e78..71918e9d 100644 --- a/erpcgen/src/smart_ptr.hpp +++ b/erpcgen/src/smart_ptr.hpp @@ -37,7 +37,7 @@ struct smart_ptr_delete_array * * This class only supports the single-owner paradigm. */ -template > +template > class smart_ptr { public: @@ -48,23 +48,13 @@ class smart_ptr typedef const T &const_ref_type; //! Default constructor. Initializes with no pointer set. - smart_ptr() - : _p(nullptr) - { - } + smart_ptr() : _p(nullptr) {} //! This constructor takes a pointer to the object to be deleted. - smart_ptr(ptr_type p) - : _p(p) - { - } + smart_ptr(ptr_type p) : _p(p) {} //! @brief Move copy constructor. - smart_ptr(smart_ptr &&other) - : _p(other._p) - { - other._p = nullptr; - } + smart_ptr(smart_ptr &&other) : _p(other._p) { other._p = nullptr; } //! @brief Move assignment operator. smart_ptr &operator=(smart_ptr &&other) @@ -159,10 +149,10 @@ class smart_ptr //! @brief Version of smart_ptr that uses delete []. template -using smart_array_ptr = smart_ptr >; +using smart_array_ptr = smart_ptr>; //! @brief Version of smart_ptr that uses free(). template -using smart_free_ptr = smart_ptr >; +using smart_free_ptr = smart_ptr>; #endif // _smart_ptr_h_ diff --git a/erpcgen/src/templates/c_client_header.template b/erpcgen/src/templates/c_client_header.template new file mode 100644 index 00000000..fb83a8b2 --- /dev/null +++ b/erpcgen/src/templates/c_client_header.template @@ -0,0 +1,70 @@ +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +{$commonHeader()} + +#if !defined({$clientCGuardMacro}) +#define {$clientCGuardMacro} + +#include "{$commonCHeaderName}" +#include "erpc_client_manager.h" +{% for iface in group.interfaces %} +{% for fn in iface.functions %} +{% for externalInterface in fn.externalInterfaces %} +{% for interfaceFile in interfacesFiles %} +{% if externalInterface == interfaceFile.interfaceName %} +#include "c_{$interfaceFile.interfaceCommonFileName}_client.h" +{% endif %} +{% endfor -- interfacesFiles %} +{% endfor -- externalInterface %} +{% endfor -- fn %} +{% endfor -- iface %} + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if !defined({$getFunctionDeclarationMacroName()}) +#define {$getFunctionDeclarationMacroName()} + +{% for iface in group.interfaces %} +{% for cb in iface.callbacksInt%} +typedef {$cb.typenameName}; +{% endfor %} + +/*! @brief {$iface.name} identifiers */ +enum _{$iface.name}_ids +{ + k{$iface.name}_service_id = {$iface.id}, +{% for fn in iface.functions %} + k{$iface.name}_{$fn.name}_id = {$fn.id}, +{% endfor %} +}; + +{% endfor %} +{% for iface in group.interfaces if iface.isNonExternalInterface == true %} +{$> iface.mlComment} +//! @name {$iface.name} +//@{ +{% for fn in iface.functions if fn.isNonExternalFunction == true %} +{$> fn.mlComment} +{$fn.prototype};{$fn.ilComment}{$loop.addNewLineIfNotLast} +{% endfor -- functions %} +//@}{$iface.ilComment} + +{% endfor -- iface %} +#endif // {$getFunctionDeclarationMacroName()} + +{% for iface in group.interfaces %} +void init{$iface.clientClassName}(erpc_client_t client); + +void deinit{$iface.clientClassName}(void); + +{% endfor -- iface %} +#if defined(__cplusplus) +} +#endif + +#endif // {$clientCGuardMacro} diff --git a/erpcgen/src/templates/c_client_source.template b/erpcgen/src/templates/c_client_source.template index 41f4a8fd..619e65cf 100644 --- a/erpcgen/src/templates/c_client_source.template +++ b/erpcgen/src/templates/c_client_source.template @@ -1,197 +1,102 @@ +{% set source = "client" >%} {% if mlComment != "" %} {$mlComment} {% endif %} {$commonHeader()} -#include "erpc_client_manager.h" -#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC -#include "erpc_port.h" -#endif -#include "{$codecHeader}" -extern "C" -{ -#include "{$commonHeaderName}.h" -{% if groupNames %} -// import callbacks declaration from other groups -{% for name in groupNames if name != group.name %} -#include "{$outputFilename}_{$name}.h" -{% endfor %} -{% endif %} -} +#include "{$clientCHeaderName}" +#include "{$clientCppHeaderName}" +#include "erpc_manually_constructed.hpp" +{% set utils = false >%} +{% for iface in group.interfaces %} +{% if (count(iface.callbacksAll) > 0) && (utils == false) %} +#include "erpc_utils.hpp" +{% set utils = true >%} +{% endif %} +{% endfor %} -{$checkVersion()} -{$>checkCrc()} using namespace erpc; using namespace std; +{$usingNamespace() >} +{% for iface in group.interfaces %} +{% if count(iface.callbacksAll) > 0 %} -extern ClientManager *g_client; -{$generateCrcVariable()} -{$> setSharedMemAddresses()} -{% if unitTest %} -{$> callbackTable(functions)} -{% endif %} -{$> constantsDefinitions(consts)} -{$> symbolHeader(group.symbolsMap.symbolsToServer, "serial", "def")} -{$> symbolSource(group.symbolsMap.symbolsToServer, "serial", "def")} -{$> symbolHeader(group.symbolsMap.symbolsToClient, "deserial", "def")} -{$> symbolSource(group.symbolsMap.symbolsToClient, "deserial", "def")} -{$> symbolHeader(group.symbolsMap.symbolsToServer, "serial", "noSharedMem")} -{$> symbolSource(group.symbolsMap.symbolsToServer, "serial", "noSharedMem")} -{$> symbolHeader(group.symbolsMap.symbolsToClient, "deserial", "noSharedMem")} -{$> symbolSource(group.symbolsMap.symbolsToClient, "deserial", "noSharedMem")} -{% def clientShimCode(fn, serverIDName, functionIDName) ------------------------- clientShimCode(fn, serverIDName, functionIDName) %} -{% set clientIndent = "" >%} -{% if generateErrorChecks %} - erpc_status_t err = kErpcStatus_Success; - -{% endif -- generateErrorChecks %} -{% if fn.isReturnValue %} -{% if fn.needTempVariableClientI32 %} - int32_t _tmp_local_i32; +{% for cb in iface.callbacksAll %} +static const {$cb.name} _{$cb.name}[{$count(cb.callbacks)}] = { {% for c in cb.callbacks %}{$c.name}{% if !loop.last %}, {% endif -- loop.last %}{% endfor -- f.callbacks %} }; +{% endfor %} {% endif %} -{% endif %} -{% if fn.returnValue.type.isNotVoid %} - {$fn.returnValue.resultVariable}{% if fn.returnValue.isNullReturnType %} = NULL{% endif %}; -{% endif -- isNotVoid %} +{% endfor %} -#if ERPC_PRE_POST_ACTION - pre_post_action_cb preCB = g_client->getPreCB(); - if (preCB) - { - preCB(); - } +{% for iface in group.interfaces %} +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC +{$iface.clientClassName} *s_{$iface.clientClassName} = nullptr; +#else +ERPC_MANUALLY_CONSTRUCTED_STATIC({$iface.clientClassName}, s_{$iface.clientClassName}); #endif +{% endfor -- iface %} +{% for iface in group.interfaces %} +{% for fn in iface.functions %} - // Get a new request. -{% if !fn.isReturnValue %} - RequestContext request = g_client->createRequest(true); -{% else %} - RequestContext request = g_client->createRequest(false); -{% endif -- isReturnValue %} - - // Encode the request. -{% if codecClass == "Codec" %} - {$codecClass} * codec = request.getCodec(); -{% else %} - {$codecClass} * codec = static_cast<{$codecClass} *>(request.getCodec()); +{$fn.prototype} +{ +{% if count(fn.callbackParameters) > 0 %} + uint16_t _fnIndex; +{% for cb in fn.callbackParameters%} + {% if cb.interface != ""%}{$cb.interface}{% else %}{$iface.interfaceClassName}{% endif %}::{$cb.type} _{$cb.name} = NULL; +{% endfor %} +{% endif%} +{% if fn.returnValue.type.isNotVoid %} + {$fn.returnValue.resultVariable}{% if fn.returnValue.isNullReturnType %} = NULL{% endif %}; {% endif %} +{% if count(fn.callbackParameters) > 0 %} +{% for cb in fn.callbackParameters if cb.in %} -{% if generateAllocErrorChecks %} -{% set clientIndent = " " >%} - if (codec == NULL) + if (findIndexOfFunction((arrayOfFunctionPtr_t)_{$cb.type}, sizeof(_{$cb.type})/sizeof({$cb.type}), (functionPtr_t){$cb.name}, _fnIndex)) { - err = kErpcStatus_MemoryError; + {% if cb.interface != ""%}{$cb.interface}{% else %}{$iface.interfaceClassName}{% endif %}::get_callbackAddress_{$cb.type}(_fnIndex, &_{$cb.name}); } - else - { -{% endif -- generateErrorChecks %} -{$clientIndent} codec->startWriteMessage({% if not fn.isReturnValue %}kOnewayMessage{% else %}kInvocationMessage{% endif %}, {$serverIDName}, {$functionIDName}, request.getSequence()); - -{% if fn.isSendValue %} -{% for param in fn.parameters if (param.serializedDirection == "" || param.serializedDirection == OutDirection || param.referencedName != "") %} -{% if param.isNullable %} -{$ addIndent(clientIndent & " ", f_paramIsNullableEncode(param))} - -{% else -- isNullable %} -{% if param.direction != OutDirection %} -{$addIndent(clientIndent & " ", param.coderCall.encode(param.coderCall))} - -{% endif -- param != OutDirection %} -{% endif -- isNullable %} -{% endfor -- fn parameters %} -{% endif -- isSendValue %} -{$clientIndent} // Send message to server -{$clientIndent} // Codec status is checked inside this function. -{$clientIndent} g_client->performRequest(request); -{% if fn.isReturnValue %} -{% for param in fn.parametersToClient if (param.serializedDirection == "" || param.serializedDirection == InDirection || param.referencedName != "") %} - -{% if param.isNullable %} -{% if ((source == "client") && (param.direction != ReturnDirection) && (empty(param.lengthName) == false)) %} -{% set lengthNameCon = ") && (" & param.lengthName & " != NULL)" >%} -{% else %} -{% set lengthNameCon = "" >%} -{% endif %} -{$clientIndent} if ({% if lengthNameCon != "" %}({% endif %}{$param.nullableName} != NULL{$lengthNameCon}) -{$clientIndent} { -{$addIndent(clientIndent & " ", param.coderCall.decode(param.coderCall))} - } -{% else -- notNullable %} -{$addIndent(clientIndent & " ", param.coderCall.decode(param.coderCall))} -{% endif -- isNullable %} -{% endfor -- fn parametersToClient %} -{% if fn.returnValue.type.isNotVoid %} - -{% if fn.returnValue.isNullable %} -{$clientIndent} bool isNull; -{$addIndent(clientIndent & " ", f_paramIsNullableDecode(fn.returnValue))} -{% else -- isNullable %} -{$> addIndent(clientIndent & " ", allocMem(fn.returnValue.firstAlloc))} -{$addIndent(clientIndent & " ", fn.returnValue.coderCall.decode(fn.returnValue.coderCall))} -{% endif -- isNullable %} -{% endif -- isNotVoid %} -{% endif -- isReturnValue %} -{% if generateErrorChecks %} - -{$clientIndent} err = codec->getStatus(); -{% endif -- generateErrorChecks %} -{% if generateAllocErrorChecks %} - } -{% endif -- generateAllocErrorChecks %} - - // Dispose of the request. - g_client->releaseRequest(request); -{% if generateErrorChecks %} - - // Invoke error handler callback function - g_client->callErrorHandler(err, {$functionIDName}); -{% endif -- generateErrorChecks %} - -#if ERPC_PRE_POST_ACTION - pre_post_action_cb postCB = g_client->getPostCB(); - if (postCB) - { - postCB(); - } -#endif +{% endfor %} -{% if generateErrorChecks && fn.returnValue.type.isNotVoid %} -{% if empty(fn.returnValue.errorReturnValue) == false && fn.returnValue.isNullReturnType == false %} +{%endif%} + {% if fn.returnValue.type.isNotVoid %}result = {% endif %}s_{$iface.clientClassName}->{$fn.name}({% for param in fn.parameters %}{% if !loop.first %}, {% endif %}{$param.pureNameC}{% endfor %}); +{% for cb in fn.callbackParameters if cb.out %} - if (err != kErpcStatus_Success) + if ({% if cb.interface != ""%}{$cb.interface}{% else %}{$iface.interfaceClassName}{% endif %}::get_callbackIdx_{$cb.type}(&_{$cb.name}, _fnIndex)) { - result = {$fn.returnValue.errorReturnValue}; + *{$cb.name}=_{$cb.type}[_fnIndex]; } -{% endif %} -{% endif -- generateErrorChecks %} +{% endfor %} +{% if fn.returnValue.type.isNotVoid %} - return{% if fn.returnValue.type.isNotVoid %} result{% endif -- isNotVoid %}; -{% enddef --------------------------------------------------------------------------------- clientShimCode(fn, serverIDName, functionIDName) %} -{% for callbackType in group.callbacks %} -// Common function for serializing and deserializing callback functions of same type. -static {$callbackType.prototype}; + return result; +{% endif %} +} +{% endfor -- fn %} +{% endfor -- iface %} +{% for iface in group.interfaces %} -{% endfor %} -{% for callbackType in group.callbacks %} -// Common function for serializing and deserializing callback functions of same type. -static {$callbackType.prototype} +void init{$iface.clientClassName}(erpc_client_t client) { -{$ clientShimCode(callbackType, "serviceID", "functionID") >} +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(s_{$iface.clientClassName} == nullptr); + s_{$iface.clientClassName} = new {$iface.clientClassName}(reinterpret_cast(client)); +#else + erpc_assert(!s_{$iface.clientClassName}.isUsed()); + s_{$iface.clientClassName}.construct(reinterpret_cast(client)); +#endif } -{% endfor %} -{% for iface in group.interfaces %} -{% for fn in iface.functions %} - -// {$iface.name} interface {$fn.name} function client shim. -{$fn.prototype} +void deinit{$iface.clientClassName}(void) { -{% if fn.isCallback %} - {% if fn.returnValue.type.isNotVoid %}return {% endif %}{$fn.callbackFName}(k{$iface.name}_service_id, k{$iface.name}_{$fn.name}_id{% for param in fn.parameters %}, {$param.name}{% endfor %}); -{% else -- fn.isCallback >%} -{$ clientShimCode(fn, "k"& iface.name & "_service_id", "k" & iface.name & "_" & fn.name & "_id") >} -{% endif -- fn.isCallback >%} +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + if (s_{$iface.clientClassName} != nullptr) + { + delete s_{$iface.clientClassName}; + s_{$iface.clientClassName} = nullptr; + } +#else + s_{$iface.clientClassName}.destroy(); +#endif } -{% endfor -- fn %} {% endfor -- iface %} diff --git a/erpcgen/src/templates/c_common_header.template b/erpcgen/src/templates/c_common_header.template index 8c093ba7..2083bbd2 100644 --- a/erpcgen/src/templates/c_common_header.template +++ b/erpcgen/src/templates/c_common_header.template @@ -13,33 +13,38 @@ #endif {% endif -- usedUnionType %} -{% if not commonTypesFile == "" %} -// Common types header file -#include "{$commonTypesFile}" -{% else %} +{% for inc in includes %} +#include "{$inc}" +{% endfor -- includes %} + +{% if cCommonHeaderFile %} +#if defined(__cplusplus) +extern "C" +{ +#endif #include #include #include +{% else %} +#include +#include +#include +{% endif %} + #include "erpc_version.h" {% if empty(crc16) == false %} #include "{$crcHeaderName}" {% endif -- empty(crc16) == false %} -{% for inc in includes %} -#include "{$inc}" -{% endfor -- includes %} {$checkVersion()} {$>checkCrc()} -{% endif -- not commonTypesFile %} -{% if commonTypesFile == "" %} + #if !defined(ERPC_TYPE_DEFINITIONS{$scopeNamePrefix}{$scopeNameC}) #define ERPC_TYPE_DEFINITIONS{$scopeNamePrefix}{$scopeNameC} {% if not empty(enums) %} // Enumerators data types declarations {% for enum in enums %} -{% if enum.name != "" %} -{% endif %} {$> enum.mlComment} {% if enum.name %}typedef {% endif --enum.name %}enum{$addIndent(" ", enum.name)} { @@ -103,38 +108,12 @@ extern const {$c.typeAndName};{$c.ilComment}{$loop.addNewLineIfNotLast} {% endif -- consts %} #endif // ERPC_TYPE_DEFINITIONS{$scopeNamePrefix}{$scopeNameC} -{% endif -- commonTypesFile %} - -{% if not genCommonTypesFile %} -{% for iface in group.interfaces %} -/*! @brief {$iface.name} identifiers */ -enum _{$iface.name}_ids -{ - k{$iface.name}_service_id = {$iface.id}, -{% for fn in iface.functions %} - k{$iface.name}_{$fn.name}_id = {$fn.id}, -{% endfor %} -}; - -{% endfor %} -#if defined(__cplusplus) -extern "C" { -#endif -{% for iface in group.interfaces if iface.isNonExternalInterface == true %} - -{$> iface.mlComment} -//! @name {$iface.name} -//@{ -{% for fn in iface.functions if fn.isNonExternalFunction == true %} -{$> fn.mlComment} -{$fn.prototype};{$fn.ilComment}{$loop.addNewLineIfNotLast} -{% endfor -- functions %} -//@}{$iface.ilComment} -{% endfor -- iface %} +{% if cCommonHeaderFile %} #if defined(__cplusplus) } #endif -{% endif -- genCommonTypesFile %} +{% else %} +{% endif %} #endif // {$commonGuardMacro} diff --git a/erpcgen/src/templates/c_server_header.template b/erpcgen/src/templates/c_server_header.template index 082ea3e9..e2a7afcb 100644 --- a/erpcgen/src/templates/c_server_header.template +++ b/erpcgen/src/templates/c_server_header.template @@ -1,51 +1,63 @@ -{% if mlComment != ""%} +{% if mlComment != "" %} {$mlComment} {% endif %} {$commonHeader()} -#if !defined({$serverGuardMacro}) -#define {$serverGuardMacro} +#if !defined({$serverCGuardMacro}) +#define {$serverCGuardMacro} -#ifdef __cplusplus -#include "erpc_server.hpp" -#include "{$codecHeader}" +#include "{$commonCHeaderName}" +{% for iface in group.interfaces %} +{% for fn in iface.functions %} +{% for externalInterface in fn.externalInterfaces %} +{% for interfaceFile in interfacesFiles %} +{% if externalInterface == interfaceFile.interfaceName %} +#include "c_{$interfaceFile.interfaceCommonFileName}_client.h" +{% endif %} +{% endfor -- interfacesFiles %} +{% endfor -- externalInterface %} +{% endfor -- fn %} +{% endfor -- iface %} + +#if defined(__cplusplus) extern "C" { -#include "{$commonHeaderName}.h" -#include -#include -} +#endif -{$checkVersion()} -{$>checkCrc()} -{% for iface in group.interfaces %} +typedef void * erpc_service_t; -/*! - * @brief Service subclass for {$iface.name}. - */ -class {$iface.serviceClassName} : public erpc::Service -{ -public: - {$iface.serviceClassName}() : Service(k{$iface.name}_service_id) {} +#if !defined({$getFunctionDeclarationMacroName()}) +#define {$getFunctionDeclarationMacroName()} - /*! @brief Call the correct server shim based on method unique ID. */ - virtual erpc_status_t handleInvocation(uint32_t methodId, uint32_t sequence, erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory); +{% for iface in group.interfaces %} +{% for cb in iface.callbacksInt%} +typedef {$cb.typenameName}; +{% endfor %} -private: +/*! @brief {$iface.name} identifiers */ +enum _{$iface.name}_ids +{ + k{$iface.name}_service_id = {$iface.id}, {% for fn in iface.functions %} - /*! @brief Server shim for {$fn.name} of {$iface.name} interface. */ - erpc_status_t {$fn.name}_shim(erpc::{$codecClass} * codec, erpc::MessageBufferFactory *messageFactory, uint32_t sequence);{$loop.addNewLineIfNotLast} -{% endfor -- fn %} + k{$iface.name}_{$fn.name}_id = {$fn.id}, +{% endfor %} }; -{% endfor -- iface %} -extern "C" { -#else -#include "{$commonHeaderName}.h" -#endif // __cplusplus +{% endfor %} +{% for iface in group.interfaces if iface.isNonExternalInterface == true %} +{$> iface.mlComment} +//! @name {$iface.name} +//@{ +{% for fn in iface.functions if fn.isNonExternalFunction == true %} +{$> fn.mlComment} +{$fn.prototype};{$fn.ilComment}{$loop.addNewLineIfNotLast} +{% endfor -- functions %} +//@}{$iface.ilComment} -typedef void * erpc_service_t; +{% endfor -- iface %} + +#endif // {$getFunctionDeclarationMacroName()} {% for iface in group.interfaces %} /*! @brief Return {$iface.serviceClassName} service object. */ @@ -55,8 +67,9 @@ erpc_service_t create_{$iface.serviceClassName}(void); void destroy_{$iface.serviceClassName}(erpc_service_t service); {% endfor -- iface %} -#ifdef __cplusplus + +#if defined(__cplusplus) } -#endif // __cplusplus +#endif -#endif // {$serverGuardMacro} +#endif // {$serverCGuardMacro} diff --git a/erpcgen/src/templates/c_server_source.template b/erpcgen/src/templates/c_server_source.template index 0f1e526f..48d9d5ba 100644 --- a/erpcgen/src/templates/c_server_source.template +++ b/erpcgen/src/templates/c_server_source.template @@ -1,255 +1,88 @@ -{% if mlComment != ""%} +{% if mlComment != "" %} {$mlComment} {% endif %} {$commonHeader()} +{% set source = "server" >%} -#include "{$serverHeaderName}" -#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC #include -#include "erpc_port.h" -#endif +#include "{$serverCHeaderName}" +#include "{$serverCppHeaderName}" #include "erpc_manually_constructed.hpp" -{% if empty(group.includes) == false %} -extern "C" -{ -{% for inc in group.includes %} -#include "{$inc}" -{% endfor -- group.includes %} -} -{% endif -- empty(group.includes) %} +{% set utils = false >%} +{% for iface in group.interfaces %} +{% if (count(iface.callbacksAll) > 0) && (utils == false) %} +#include "erpc_utils.hpp" +{% set utils = true >%} +{% endif %} +{% endfor %} -{$checkVersion()} -{$>checkCrc()} using namespace erpc; using namespace std; - -#if ERPC_NESTED_CALLS_DETECTION -extern bool nestingDetection; -#endif - +{$usingNamespace() >} {% for iface in group.interfaces %} -ERPC_MANUALLY_CONSTRUCTED_STATIC({$iface.serviceClassName}, s_{$iface.serviceClassName}); - -{% endfor -- iface %} -{$generateCrcVariable()} -{$> setSharedMemAddresses()} -{% if unitTest %} -{$> callbackTable(functions)} -{% endif %} -{$> constantsDefinitions(consts)} -{$> symbolHeader(group.symbolsMap.symbolsToServer, "deserial", "def")} -{$> symbolSource(group.symbolsMap.symbolsToServer, "deserial", "def")} -{$> symbolHeader(group.symbolsMap.symbolsToClient, "serial", "def")} -{$> symbolSource(group.symbolsMap.symbolsToClient, "serial", "def")} -{$> symbolFreeSpaceHeader(group.symbolsMap.symbolsServerFree, "def")} -{$> symbolFreeSpaceSource(group.symbolsMap.symbolsServerFree, "def")} -{$> symbolHeader(group.symbolsMap.symbolsToServer, "deserial", "noSharedMem")} -{$> symbolSource(group.symbolsMap.symbolsToServer, "deserial", "noSharedMem")} -{$> symbolHeader(group.symbolsMap.symbolsToClient, "serial", "noSharedMem")} -{$> symbolSource(group.symbolsMap.symbolsToClient, "serial", "noSharedMem")} -{$> symbolFreeSpaceHeader(group.symbolsMap.symbolsServerFree, "noSharedMem")} -{$> symbolFreeSpaceSource(group.symbolsMap.symbolsServerFree, "noSharedMem")} -{% def serverShimCode(fn, serverIDName, functionIDName) ------------------------- serverShimCode(fn, serverIDName, functionIDName) %} -{% set serverIndent = "" >%} -{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} - erpc_status_t err = kErpcStatus_Success; +{% if count(iface.callbacksAll) > 0 %} -{% endif -- isReturnValue || isSendValue %} -{% for param in fn.parameters %} - {$param.variable}{% if param.isNullParam %} = NULL{% endif %}; -{% if !empty(param.nullVariable) %} - {$param.nullVariable} = NULL; +{% for cb in iface.callbacksAll %} +static const {$cb.name} _{$cb.name}[{$count(cb.callbacks)}] = { {% for c in cb.callbacks %}{$c.name}{% if !loop.last %}, {% endif -- loop.last %}{% endfor -- f.callbacks %} }; +{% endfor %} {% endif %} -{% if !param.shared %} -{% if param.isNullable == false && param.direction != OutDirection %} -{$> addIndent(" ", allocMem(param.mallocServer))} -{% endif -- !param.isNullable && param.direction != OutDirection %} -{% endif -- shared %} -{% endfor -- param %} -{% if fn.needNullVariableOnServer %} - bool isNull; -{% endif -- needNullVariableOnServer %} -{% if fn.needTempVariableServerI32 %} - int32_t _tmp_local_i32; -{% endif %} -{% if fn.returnValue.type.isNotVoid %} - {$fn.returnValue.resultVariable}{% if fn.returnValue.isNullReturnType %} = NULL{% endif %}; -{% endif %} -{% if fn.isReturnValue || fn.isSendValue %} - -{% endif %} - // startReadMessage() was already called before this shim was invoked. - -{% if fn.isSendValue %} -{% for param in fn.parameters if (param.serializedDirection == "" || param.serializedDirection == OutDirection || param.referencedName != "") %} -{% if param.isNullable %} -{$addIndent(" ", f_paramIsNullableDecode(param))} - -{% else -- notNullable %} -{% if param.direction != OutDirection %} -{$addIndent(" ", param.coderCall.decode(param.coderCall))} - -{% endif -- param != OutDirection %} -{% endif -- isNullable %} -{% endfor -- parametersToServer %} -{% endif -- isSendValue %} -{% for param in fn.parametersToClient %} -{% if !param.shared %} -{% if param.isNullable == false && param.direction == OutDirection && empty(param.mallocServer) == false %} -{$> addIndent(" ", allocMem(param.mallocServer))} - -{% endif -- !param.isNullable && param.direction == OutDirection %} -{% endif -- shared %} -{% endfor -- param %} -{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} -{% set serverIndent = " " >%} - err = codec->getStatus(); - if (err == kErpcStatus_Success) - { -{% endif -- generateErrorChecks %} -{$serverIndent} // Invoke the actual served function. -#if ERPC_NESTED_CALLS_DETECTION -{$serverIndent} nestingDetection = true; -#endif -{% if serverIDName == "serviceID" %} -{% for callbackFunction in callbackType.functions %} -{$serverIndent} {% if loop.first == false %}else {% endif %}if (({$serverIDName} == {$callbackFunction.serviceId}) && ({$functionIDName} == {$callbackFunction.id})) -{$serverIndent} { -{$serverIndent} {$callbackFunction.serverPrototype} -{$serverIndent} } -{% endfor -- callbackFunction in callbackType.functions %} -{% else -- serverIDName == "serviceID" %} -{$serverIndent} {$fn.serverPrototype} -{% endif --serverIDName == "serviceID" %} -#if ERPC_NESTED_CALLS_DETECTION -{$serverIndent} nestingDetection = false; -#endif -{% if fn.isReturnValue %} - -{$serverIndent} // preparing MessageBuffer for serializing data -{$serverIndent} {% if generateErrorChecks %}err = {% endif %}messageFactory->prepareServerBufferForSend(codec->getBuffer()); -{% if generateErrorChecks %} - } - - if (err == kErpcStatus_Success) - { -{% endif -- generateErrorChecks %} -{$serverIndent} // preparing codec for serializing data -{$serverIndent} codec->reset(); - -{$serverIndent} // Build response message. -{$serverIndent} codec->startWriteMessage(kReplyMessage, {$serverIDName}, {$functionIDName}, sequence); -{% for param in fn.parametersToClient if (param.serializedDirection == "" || param.serializedDirection == InDirection || param.referencedName != "") %} - -{% if param.isNullable %} -{$serverIndent} if ({% if source == "server" && empty(param.nullVariable) == false %}_{% endif %}{$param.name} != NULL) -{$serverIndent} { -{$addIndent(serverIndent & " ", param.coderCall.encode(param.coderCall))} -{$serverIndent} } -{% else -- isNullable %} -{$addIndent(serverIndent & " ", param.coderCall.encode(param.coderCall))} -{% endif -- isNullable %} -{% endfor -- parametersToClient %} -{% if fn.returnValue.type.isNotVoid %} - -{% if fn.returnValue.isNullable %} -{$addIndent(serverIndent & " ", f_paramIsNullableEncode(fn.returnValue))} -{% else -- isNullable %} -{$addIndent(serverIndent & " ", fn.returnValue.coderCall.encode(fn.returnValue.coderCall))} -{% endif -- isNullable %} -{% endif -- notVoid %} -{% if generateErrorChecks %} - - err = codec->getStatus(); -{% endif generateErrorChecks %} -{% endif -- isReturnValue %} -{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} - } - -{% endif -- fn.isReturnValue || fn.isSendValue %} -{% for param in fn.paramsToFree %} -{$> addIndent(" ", param.coderCall.freeingCall(param.coderCall))} -{$> addIndent(" ", param.firstFreeingCall1.firstFreeingCall(param.firstFreeingCall1))} - -{% endfor -- parameters %} -{% if fn.returnValue.type.isNotVoid %} -{% set needFreeingCall = fn.returnValue.coderCall.freeingCall(fn.returnValue.coderCall) %} -{% set needFirstFreeingCall = fn.returnValue.firstFreeingCall1.firstFreeingCall(fn.returnValue.firstFreeingCall1) %} -{% if empty(needFreeingCall) == false || empty(needFirstFreeingCall) == false %} -{$> addIndent(" ", needFreeingCall)} -{$> addIndent(" ", needFirstFreeingCall)} - -{% endif -- !empty(needFreeingCall) || !empty(needFirstFreeingCall) %} -{% endif -- notVoid %} -{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} - return err; -{% else %} - return codec->getStatus(); -{% endif %} -{% enddef --------------------------------------------------------------------------------- serverShimCode(fn, serverIDName, functionIDName) %} -{% for callbackType in group.callbacks %} - -// Common function for serializing and deserializing callback functions of same type. -static erpc_status_t {$callbackType.name}_shim(uint32_t serviceID, uint32_t functionID, {$codecClass} * codec, MessageBufferFactory *messageFactory, uint32_t sequence); {% endfor %} -{% for callbackType in group.callbacks %} +{% for iface in group.interfaces %} -// Common function for serializing and deserializing callback functions of same type. -static erpc_status_t {$callbackType.name}_shim(uint32_t serviceID, uint32_t functionID, {$codecClass} * codec, MessageBufferFactory *messageFactory, uint32_t sequence) +class {$iface.serverClassName}: public {$iface.interfaceClassName} { -{$ serverShimCode(callbackType, "serviceID", "functionID") >} -} -{% endfor %} -{% for iface in group.interfaces -- service subclass method impl %} + public: + virtual ~{$iface.serverClassName}() {}; -// Call the correct server shim based on method unique ID. -erpc_status_t {$iface.serviceClassName}::handleInvocation(uint32_t methodId, uint32_t sequence, Codec * codec, MessageBufferFactory *messageFactory) -{ - erpc_status_t erpcStatus; -{% if codecClass != "Codec" %} - {$codecClass} *_codec = static_cast<{$codecClass} *>(codec); -{% endif %} - switch (methodId) - { {% for fn in iface.functions %} - case k{$iface.name}_{$fn.name}_id: - { - erpcStatus = {$fn.name}_shim({%if codecClass == "Codec" %}codec{% else %}_codec{% endif %}, messageFactory, sequence); - break; - } -{% endfor -- fn %} - default: + {$fn.prototypeInterface} { - erpcStatus = kErpcStatus_InvalidArgument; - break; +{% if count(fn.callbackParameters) > 0 %} + uint16_t _fnIndex; +{% for cb in fn.callbackParameters%} + ::{$cb.type} _{$cb.name} = NULL; +{% endfor %} +{% endif %} +{% if fn.returnValue.type.isNotVoid %} + {$fn.returnValue.resultVariable}{% if fn.returnValue.isNullReturnType %} = NULL{% endif %}; +{% endif %} +{% if count(fn.callbackParameters) > 0 %} +{% for cb in fn.callbackParameters if cb.in %} + + if ({% if cb.interface != ""%}{$cb.interface}{% else %}{$iface.interfaceClassName}{% endif %}::get_callbackIdx_{$cb.type}(&{$cb.name}, _fnIndex)) + { + _{$cb.name}=::_{$cb.type}[_fnIndex]; + } +{% endfor %} + +{% endif%} + {% if fn.returnValue.type.isNotVoid %}result = {% endif %}::{$fn.name}({% for param in fn.parameters %}{% if !loop.first %}, {% endif %}{$param.pureNameC}{% endfor %}); +{% for cb in fn.callbackParameters if cb.out %} + + if (findIndexOfFunction((arrayOfFunctionPtr_t)::_{$cb.type}, sizeof(::_{$cb.type})/sizeof(::{$cb.type}), (functionPtr_t)_{$cb.name}, _fnIndex)) + { + {% if cb.interface != ""%}{$cb.interface}{% else %}{$iface.interfaceClassName}{% endif %}::get_callbackAddress_{$cb.type}(_fnIndex, {$cb.name}); + } +{% endfor %} +{% if fn.returnValue.type.isNotVoid %} + + return result; +{% endif %} } - } - - return erpcStatus; -} -{% for fn in iface.functions %} - -// Server shim for {$fn.name} of {$iface.name} interface. -erpc_status_t {$iface.serviceClassName}::{$fn.name}_shim({$codecClass} * codec, MessageBufferFactory *messageFactory, uint32_t sequence) -{ -{% if fn.isCallback %} - return {$fn.callbackFName}_shim(k{$iface.name}_service_id, k{$iface.name}_{$fn.name}_id, codec, messageFactory, sequence); -{% else -- fn.isCallback >%} -{$ serverShimCode(fn, "k"& iface.name & "_service_id", "k" & iface.name & "_" & fn.name & "_id") >} -{% endif -- fn.isCallback >%} -} {% endfor -- fn %} -{% endfor -- iface %} -{% for iface in group.interfaces %} +}; + +ERPC_MANUALLY_CONSTRUCTED_STATIC({$iface.serviceClassName}, s_{$iface.serviceClassName}); +ERPC_MANUALLY_CONSTRUCTED_STATIC({$iface.serverClassName}, s_{$iface.serverClassName}); erpc_service_t create_{$iface.serviceClassName}(void) { erpc_service_t service; #if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC - service = new (nothrow) {$iface.serviceClassName}(); + service = new (nothrow) {$iface.serviceClassName}(new (nothrow){$iface.serverClassName}()); #else if (s_{$iface.serviceClassName}.isUsed()) { @@ -257,7 +90,8 @@ erpc_service_t create_{$iface.serviceClassName}(void) } else { - s_{$iface.serviceClassName}.construct(); + s_{$iface.serverClassName}.construct(); + s_{$iface.serviceClassName}.construct(s_{$iface.serverClassName}.get()); service = s_{$iface.serviceClassName}.get(); } #endif @@ -268,12 +102,16 @@ erpc_service_t create_{$iface.serviceClassName}(void) void destroy_{$iface.serviceClassName}(erpc_service_t service) { #if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC - erpc_assert(service != NULL); - delete ({$iface.serviceClassName} *)service; + if (service) + { + delete ({$iface.serverClassName} *)((({$iface.serviceClassName} *)service)->getHandler()); + delete ({$iface.serviceClassName} *)service; + } #else (void)service; erpc_assert(service == s_{$iface.serviceClassName}.get()); s_{$iface.serviceClassName}.destroy(); + s_{$iface.serverClassName}.destroy(); #endif } diff --git a/erpcgen/src/templates/cpp_client_header.template b/erpcgen/src/templates/cpp_client_header.template new file mode 100644 index 00000000..85d166bb --- /dev/null +++ b/erpcgen/src/templates/cpp_client_header.template @@ -0,0 +1,36 @@ +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +{$commonHeader()} + +#if !defined({$clientCppGuardMacro}) +#define {$clientCppGuardMacro} + +#include "{$interfaceCppHeaderName}" + +#include "erpc_client_manager.h" +{$fillNamespaceBegin()>} + +{% for iface in group.interfaces %} +class {$iface.clientClassName}: public {$iface.interfaceClassName} +{ + public: + {$iface.clientClassName}(erpc::ClientManager *manager); + + virtual ~{$iface.clientClassName}(); +{% for fn in iface.functions if fn.isNonExternalFunction == true %} + +{% if fn.mlComment %} + {$fn.mlComment} +{% endif %} + virtual {$fn.prototypeInterface}; +{% endfor -- fn %} + + protected: + erpc::ClientManager *m_clientManager; +}; + +{% endfor -- iface %} +{$fillNamespaceEnd()} +#endif // {$clientCppGuardMacro} diff --git a/erpcgen/src/templates/cpp_client_source.template b/erpcgen/src/templates/cpp_client_source.template new file mode 100644 index 00000000..ddffe9e0 --- /dev/null +++ b/erpcgen/src/templates/cpp_client_source.template @@ -0,0 +1,198 @@ +{% set source = "client" >%} +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +{$commonHeader()} + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC +#include "erpc_port.h" +#endif +#include "{$codecHeader}" +#include "{$clientCppHeaderName}" +#include "erpc_manually_constructed.hpp" + +{$checkVersion()} +{$>checkCrc()} +using namespace erpc; +using namespace std; +{$usingNamespace() >} +{$generateCrcVariable()} +{$> setSharedMemAddresses()} +{$> constantsDefinitions(consts)} +{$> symbolHeader(group.symbolsMap.symbolsToServer, "serial", "def")} +{$> symbolSource(group.symbolsMap.symbolsToServer, "serial", "def")} +{$> symbolHeader(group.symbolsMap.symbolsToClient, "deserial", "def")} +{$> symbolSource(group.symbolsMap.symbolsToClient, "deserial", "def")} +{$> symbolHeader(group.symbolsMap.symbolsToServer, "serial", "noSharedMem")} +{$> symbolSource(group.symbolsMap.symbolsToServer, "serial", "noSharedMem")} +{$> symbolHeader(group.symbolsMap.symbolsToClient, "deserial", "noSharedMem")} +{$> symbolSource(group.symbolsMap.symbolsToClient, "deserial", "noSharedMem")} + +{% def clientShimCode(client, fn, serverIDName, functionIDName) ------------------------- clientShimCode(fn, serverIDName, functionIDName) %} +{% set clientIndent = "" >%} +{% if generateErrorChecks %} + erpc_status_t err = kErpcStatus_Success; + +{% endif -- generateErrorChecks %} +{% if fn.isReturnValue %} +{% if fn.needTempVariableClientI32 %} + int32_t _tmp_local_i32; +{% endif %} +{% endif %} +{% if fn.needTempVariableClientU16 %} + uint16_t _tmp_local_u16; +{% endif %} +{% if fn.returnValue.type.isNotVoid %} + {$fn.returnValue.resultVariable}{% if fn.returnValue.isNullReturnType %} = NULL{% endif %}; +{% endif -- isNotVoid %} + +#if ERPC_PRE_POST_ACTION + pre_post_action_cb preCB = {$client}->getPreCB(); + if (preCB) + { + preCB(); + } +#endif + + // Get a new request. +{% if !fn.isReturnValue %} + RequestContext request = {$client}->createRequest(true); +{% else %} + RequestContext request = {$client}->createRequest(false); +{% endif -- isReturnValue %} + + // Encode the request. +{% if codecClass == "Codec" %} + {$codecClass} * codec = request.getCodec(); +{% else %} + {$codecClass} * codec = static_cast<{$codecClass} *>(request.getCodec()); +{% endif %} + +{% if generateAllocErrorChecks %} +{% set clientIndent = " " >%} + if (codec == NULL) + { + err = kErpcStatus_MemoryError; + } + else + { +{% endif -- generateErrorChecks %} +{$clientIndent} codec->startWriteMessage({% if not fn.isReturnValue %}message_type_t::kOnewayMessage{% else %}message_type_t::kInvocationMessage{% endif %}, {$serverIDName}, {$functionIDName}, request.getSequence()); + +{% if fn.isSendValue %} +{% for param in fn.parameters if (param.serializedDirection == "" || param.serializedDirection == OutDirection || param.referencedName != "") %} +{% if param.isNullable %} +{$ addIndent(clientIndent & " ", f_paramIsNullableEncode(param))} + +{% else -- isNullable %} +{% if param.direction != OutDirection %} +{$addIndent(clientIndent & " ", param.coderCall.encode(param.coderCall))} + +{% endif -- param != OutDirection %} +{% endif -- isNullable %} +{% endfor -- fn parameters %} +{% endif -- isSendValue %} +{$clientIndent} // Send message to server +{$clientIndent} // Codec status is checked inside this function. +{$clientIndent} {$client}->performRequest(request); +{% if fn.isReturnValue %} +{% for param in fn.parametersToClient if (param.serializedDirection == "" || param.serializedDirection == InDirection || param.referencedName != "") %} + +{% if param.isNullable %} +{% if ((source == "client") && (param.direction != ReturnDirection) && (empty(param.lengthName) == false)) %} +{% set lengthNameCon = ") && (" & param.lengthName & " != NULL)" >%} +{% else %} +{% set lengthNameCon = "" >%} +{% endif %} +{$clientIndent} if ({% if lengthNameCon != "" %}({% endif %}{$param.nullableName} != NULL{$lengthNameCon}) +{$clientIndent} { +{$addIndent(clientIndent & " ", param.coderCall.decode(param.coderCall))} + } +{% else -- notNullable %} +{$addIndent(clientIndent & " ", param.coderCall.decode(param.coderCall))} +{% endif -- isNullable %} +{% endfor -- fn parametersToClient %} +{% if fn.returnValue.type.isNotVoid %} + +{% if fn.returnValue.isNullable %} +{$clientIndent} bool isNull; +{$addIndent(clientIndent & " ", f_paramIsNullableDecode(fn.returnValue))} +{% else -- isNullable %} +{$> addIndent(clientIndent & " ", allocMem(fn.returnValue.firstAlloc))} +{$addIndent(clientIndent & " ", fn.returnValue.coderCall.decode(fn.returnValue.coderCall))} +{% endif -- isNullable %} +{% endif -- isNotVoid %} +{% endif -- isReturnValue %} +{% if generateErrorChecks %} + +{$clientIndent} err = codec->getStatus(); +{% endif -- generateErrorChecks %} +{% if generateAllocErrorChecks %} + } +{% endif -- generateAllocErrorChecks %} + + // Dispose of the request. + {$client}->releaseRequest(request); +{% if generateErrorChecks %} + + // Invoke error handler callback function + {$client}->callErrorHandler(err, {$functionIDName}); +{% endif -- generateErrorChecks %} + +#if ERPC_PRE_POST_ACTION + pre_post_action_cb postCB = {$client}->getPostCB(); + if (postCB) + { + postCB(); + } +#endif + +{% if generateErrorChecks && fn.returnValue.type.isNotVoid %} +{% if empty(fn.returnValue.errorReturnValue) == false && fn.returnValue.isNullReturnType == false %} + + if (err != kErpcStatus_Success) + { + result = {$fn.returnValue.errorReturnValue}; + } +{% endif %} +{% endif -- generateErrorChecks %} + + return{% if fn.returnValue.type.isNotVoid %} result{% endif -- isNotVoid %}; +{% enddef --------------------------------------------------------------------------------- clientShimCode(fn, serverIDName, functionIDName) %} +{% for iface in group.interfaces %} +{% for cb in iface.callbacksInt if (count(cb.callbacks) > 1) %} + +// Common function for serializing and deserializing callback functions of same type. +static {$cb.callbacksData.prototype}; +{% endfor %} +{% for cb in iface.callbacksInt if (count(cb.callbacks) > 1) %} + +// Common function for serializing and deserializing callback functions of same type. +static {$cb.callbacksData.prototype} +{ +{$ clientShimCode("m_clientManager", cb.callbacksData, "serviceID", "functionID") >} +} +{% endfor %} + +{$iface.clientClassName}::{$iface.clientClassName}(ClientManager *manager) +:m_clientManager(manager) +{ +} + +{$iface.clientClassName}::~{$iface.clientClassName}() +{ +} +{% for fn in iface.functions %} + +// {$iface.name} interface {$fn.name} function client shim. +{$fn.prototypeCpp} +{ +{% if fn.isCallback %} + {% if fn.returnValue.type.isNotVoid %}return {% endif %}{$fn.callbackFName}(m_clientManager, m_serviceId, {$getClassFunctionIdName(fn)}{% for param in fn.parameters %}, {$param.pureName}{% endfor %}); +{% else -- fn.isCallback >%} +{$ clientShimCode("m_clientManager", fn, "m_serviceId", getClassFunctionIdName(fn)) >} +{% endif -- fn.isCallback >%} +} +{% endfor -- fn %} +{% endfor -- iface %} diff --git a/erpcgen/src/templates/c_coders.template b/erpcgen/src/templates/cpp_coders.template similarity index 92% rename from erpcgen/src/templates/c_coders.template rename to erpcgen/src/templates/cpp_coders.template index 4bf37fa7..1dd7dacc 100644 --- a/erpcgen/src/templates/c_coders.template +++ b/erpcgen/src/templates/cpp_coders.template @@ -5,7 +5,7 @@ char * {$info.stringLocalName}_local; codec->readString({$info.stringLocalName}_len, &{$info.stringLocalName}_local); {% if info.stringAllocSize != info.stringLocalName & "_len" %} - if ({$info.stringLocalName}_len <= {$info.stringAllocSize}) + if (({$info.stringAllocSize} >= 0) && ({$info.stringLocalName}_len <= static_cast({$info.stringAllocSize}))) { {% set indent = " " >%} {% else %} @@ -209,9 +209,13 @@ switch ({% if info.dataLiteral != "" %}{$info.dataLiteral}{% endif %}{$info.disc {% def decodeFunctionType(info) %} {% if info.callbacksCount == 1 %} -codec->readCallback((funPtr)({$info.callbacks}), (funPtr *)(&{$info.name})); +{% if param.direction != InDirection %}*{% endif %}{$info.name} = &{% if param.ifaceScope != ""%}{$param.ifaceScope}{% else %}{$iface.name}{% endif %}_interface::{$info.callbacks}; {% else -- info.callbacksCount == 1 %} -codec->readCallback((arrayOfFunPtr)({$info.callbacks}), {$info.callbacksCount}, (funPtr *)(&{$info.name})); +codec->read(_tmp_local_u16); +if (!{% if param.ifaceScope != ""%}{$param.ifaceScope}{% else %}{$iface.name}{% endif %}_interface::get_callbackAddress_{$info.cbTypeName}(_tmp_local_u16, {% if param.direction == InDirection %}&{% endif %}{$info.cbParamOutName})) +{ + codec->updateStatus(kErpcStatus_UnknownCallback); +} {% endif -- info.callbacksCount == 1 %} {% enddef -------------------------- FunctionType %} @@ -257,7 +261,8 @@ codec->readData({$info.name}, {$info.sizeTemp} * sizeof({$info.builtinTypeName}) uint32_t {$info.stringLocalName}_len = strlen((const char*){$info.name}); {% if info.stringAllocSize != info.stringLocalName & "_len" %} - erpc_assert({$info.stringLocalName}_len <= {$info.stringAllocSize}); + erpc_assert({$info.stringAllocSize} >= 0); + erpc_assert({$info.stringLocalName}_len <= static_cast({$info.stringAllocSize})); {% endif %} codec->writeString({$info.stringLocalName}_len, (const char*){$info.name}); @@ -340,9 +345,12 @@ switch ({$info.dataLiteral}{$info.discriminatorName}) {% def encodeFunctionType(info) %} {% if info.callbacksCount == 1 %} -codec->writeCallback((funPtr)({$info.callbacks}), (funPtr)({$info.name})); +/* No need to serialize code for {$info.name} when only one cb exists. */ +// (void){% if param.ifaceScope != ""%}{$param.ifaceScope}{% else %}{$iface.name}{% endif %}_interface::get_callbackIdx_{$info.cbTypeName}(&{$info.name}, _tmp_local_u16); +// codec->write(_tmp_local_u16); {% else -- info.callbacksCount == 1 %} -codec->writeCallback((arrayOfFunPtr)({$info.callbacks}), {$info.callbacksCount}, (funPtr)({$info.name})); +(void){% if param.ifaceScope != ""%}{$param.ifaceScope}{% else %}{$iface.name}{% endif %}_interface::get_callbackIdx_{$info.cbTypeName}(&{$info.name}, _tmp_local_u16); +codec->write(_tmp_local_u16); {% endif -- info.callbacksCount == 1 %} {% enddef -------------------------- FunctionType %} diff --git a/erpcgen/src/templates/c_common_functions.template b/erpcgen/src/templates/cpp_common_functions.template similarity index 95% rename from erpcgen/src/templates/c_common_functions.template rename to erpcgen/src/templates/cpp_common_functions.template index 712d3f8d..5891ab3e 100644 --- a/erpcgen/src/templates/c_common_functions.template +++ b/erpcgen/src/templates/cpp_common_functions.template @@ -27,18 +27,48 @@ {% if empty(crc16) == false %} // for mdk/keil do not forgett add "--muldefweak" for linker extern const uint32_t erpc_generated_crc; +#if defined(__MINGW32__) +__declspec( selectany ) +#else #pragma weak erpc_generated_crc +#endif extern const uint32_t erpc_generated_crc = {$crc16}; {% endif -- empty(crc16) == false %} {% enddef --checkCrc %} +{# ---------------- namespace ---------------- #} +{% def fillNamespaceBegin() %} +{% if empty(namespace) == false %} + +namespace {$namespace} +{ +{% endif -- empty(crc16) == false %} +{% enddef --checkCrc %} + +{% def fillNamespaceEnd() %} +{% if empty(namespace) == false %} +} // {$namespace} + +{% endif -- empty(crc16) == false %} +{% enddef --checkCrc %} + +{% def usingNamespace() %} +{% if empty(namespace) == false %} +using namespace {$namespace}; +{% endif -- empty(crc16) == false %} +{% enddef --checkCrc %} + {# ---------------- constantsDefinitions ---------------- #} {% def constantsDefinitions(consts) %} {% if not empty(consts) %} // Constant variable definitions {% for c in consts %} +#if defined(__MINGW32__) +__declspec( selectany ) +#else #pragma weak {$c.name} +#endif extern const {$c.typeAndName} = {$c.value}; {% endfor -- consts %} {% endif %} @@ -341,17 +371,6 @@ static void free_{$union.name}_union(int32_t discriminator, {$union.name} * data } {% enddef -- unionFreeSpaceSource %} -{# ---------------- callbacksTable ---------------- #} -{% def callbackTable(functionsTypes) %} -{% if functionsTypes %} -{% for f in functionsTypes %} -{% if count(f.callbacks) > 1 %} -static const {$f.name} _{$f.name}[] = { {% for c in f.callbacks %}{$c.name}{% if !loop.last %}, {% endif -- loop.last %}{% endfor -- f.callbacks %} }; -{% endif -- f.callbacks.size() %} -{% endfor -- functionsTypes %} -{% endif -- functionsTypes %} -{% enddef ------------------------------- callbackTable %} - {# ---------------- allocMem ---------------- #} {% def allocMem(info) %} {% if empty(info) == false %} @@ -516,3 +535,11 @@ else {% if source == "server" && !empty(param.nullVariable) %}_{% endif %}{$param.nullableName} = NULL; } {% enddef ------------------------------- f_paramIsNullableDecode %} + +{% def getFunctionDeclarationMacroName() %} +ERPC_FUNCTIONS_DEFINITIONS{% if group.name %}_{% endif %}{$upper(group.name)}{%>%} +{% enddef ------------------------------- getFunctionDeclarationMacroName %} + +{% def getClassFunctionIdName(fn) %} +m_{$fn.name}Id{%>%} +{% enddef ------------------------------- getClassFunctionIdName %} diff --git a/erpcgen/src/templates/cpp_interface_header.template b/erpcgen/src/templates/cpp_interface_header.template new file mode 100644 index 00000000..27c52834 --- /dev/null +++ b/erpcgen/src/templates/cpp_interface_header.template @@ -0,0 +1,60 @@ +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +{$commonHeader()} + +#if !defined({$interfaceCppGuardMacro}) +#define {$interfaceCppGuardMacro} + +#include "{$commonCppHeaderName}" +{% for iface in group.interfaces %} +{% for fn in iface.functions %} +{% for externalInterface in fn.externalInterfaces %} +{% for interfaceFile in interfacesFiles %} +{% if externalInterface == interfaceFile.interfaceName %} +#include "{$interfaceFile.interfaceCommonFileName}_interface.hpp" +{% endif %} +{% endfor -- interfacesFiles %} +{% endfor -- externalInterface %} +{% endfor -- fn %} +{% endfor -- iface %} +{$fillNamespaceBegin()} +{% for iface in group.interfaces %} + +// Abstract base class for {$iface.name} +class {$iface.interfaceClassName} +{ + public: +{%if count(iface.callbacksInt) > 0%} +{% for cb in iface.callbacksInt%} + typedef {$cb.interfaceTypenameName}; +{% endfor %} + +{%endif %} + static const uint8_t m_serviceId = {$iface.id}; +{% for fn in iface.functions %} + static const uint8_t {$getClassFunctionIdName(fn)} = {$fn.id}; +{% endfor -- fn %} + + virtual ~{$iface.interfaceClassName}(void); +{% for fn in iface.functions if fn.isNonExternalFunction == true %} + +{% if fn.mlComment %} + {$fn.mlComment} +{% endif %} + virtual {$fn.prototypeInterface} = 0; +{% endfor -- fn %} +{% for cb in iface.callbacksInt %} + + static bool get_callbackAddress_{$cb.name}(uint16_t index, {$cb.name} *callback); + static bool get_callbackIdx_{$cb.name}(const {$cb.name} *callback, uint16_t &index); +{% endfor %} +private: +{% for cb in iface.callbacksInt %} + static {$cb.name} _{$cb.name}[{$count(cb.callbacks)}]; +{% endfor %} +}; +{% endfor -- iface %} +{$fillNamespaceEnd()} +#endif // {$interfaceCppGuardMacro} diff --git a/erpcgen/src/templates/cpp_interface_source.template b/erpcgen/src/templates/cpp_interface_source.template new file mode 100644 index 00000000..86d37e07 --- /dev/null +++ b/erpcgen/src/templates/cpp_interface_source.template @@ -0,0 +1,57 @@ +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +{$commonHeader()} + +#include "{$interfaceCppHeaderName}" + +{$checkVersion()} +{$>checkCrc()} + +using namespace std; +{$usingNamespace() >} + +{% for iface in group.interfaces -- service subclass method impl %} +{$iface.interfaceClassName}::~{$iface.interfaceClassName}(void) +{ +} +{% for cb in iface.callbacksInt %} +{$iface.interfaceClassName}::{$cb.name} {$iface.interfaceClassName}::_{$cb.name}[{$count(cb.callbacks)}] = { {% for c in cb.callbacks %}&{$iface.interfaceClassName}::{$c.name}{% if !loop.last %}, {% endif -- loop.last %}{% endfor -- f.callbacks %} }; +{% endfor %} +{% for cb in iface.callbacksInt %} + +bool {$iface.interfaceClassName}::get_callbackAddress_{$cb.name}(uint16_t index, {$cb.name} *callback) +{ + bool find; + + if (indexcheckCrc()} +{$fillNamespaceBegin()>} + +{% for iface in group.interfaces %} +/*! + * @brief Service subclass for {$iface.name}. + */ +class {$iface.serviceClassName} : public erpc::Service +{ +public: + {$iface.serviceClassName}({$iface.interfaceClassName} *_{$iface.interfaceClassName}); + + virtual ~{$iface.serviceClassName}(); + + /*! @brief return service interface handler. */ + {$iface.interfaceClassName}* getHandler(void); + + /*! @brief Call the correct server shim based on method unique ID. */ + virtual erpc_status_t handleInvocation(uint32_t methodId, uint32_t sequence, erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport); + +private: + {$iface.interfaceClassName} *m_handler; +{% for fn in iface.functions %} + /*! @brief Server shim for {$fn.name} of {$iface.name} interface. */ + erpc_status_t {$fn.name}_shim(erpc::{$codecClass} * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence);{$loop.addNewLineIfNotLast} +{% endfor -- fn %} +}; + +{% endfor -- iface %} +{$fillNamespaceEnd()} +#endif // {$serverCppGuardMacro} diff --git a/erpcgen/src/templates/cpp_server_source.template b/erpcgen/src/templates/cpp_server_source.template new file mode 100644 index 00000000..8667e2bd --- /dev/null +++ b/erpcgen/src/templates/cpp_server_source.template @@ -0,0 +1,253 @@ +{% set source = "server" >%} +{% if mlComment != ""%} +{$mlComment} + +{% endif %} +{$commonHeader()} + +#include "{$serverCppHeaderName}" +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC +#include +#include "erpc_port.h" +#endif +#include "erpc_manually_constructed.hpp" + +{$checkVersion()} +{$>checkCrc()} +using namespace erpc; +using namespace std; +{$usingNamespace() >} + +#if ERPC_NESTED_CALLS_DETECTION +extern bool nestingDetection; +#endif + +{$generateCrcVariable()} +{$> setSharedMemAddresses()} +{$> constantsDefinitions(consts)} +{$> symbolHeader(group.symbolsMap.symbolsToServer, "deserial", "def")} +{$> symbolSource(group.symbolsMap.symbolsToServer, "deserial", "def")} +{$> symbolHeader(group.symbolsMap.symbolsToClient, "serial", "def")} +{$> symbolSource(group.symbolsMap.symbolsToClient, "serial", "def")} +{$> symbolFreeSpaceHeader(group.symbolsMap.symbolsServerFree, "def")} +{$> symbolFreeSpaceSource(group.symbolsMap.symbolsServerFree, "def")} +{$> symbolHeader(group.symbolsMap.symbolsToServer, "deserial", "noSharedMem")} +{$> symbolSource(group.symbolsMap.symbolsToServer, "deserial", "noSharedMem")} +{$> symbolHeader(group.symbolsMap.symbolsToClient, "serial", "noSharedMem")} +{$> symbolSource(group.symbolsMap.symbolsToClient, "serial", "noSharedMem")} +{$> symbolFreeSpaceHeader(group.symbolsMap.symbolsServerFree, "noSharedMem")} +{$> symbolFreeSpaceSource(group.symbolsMap.symbolsServerFree, "noSharedMem")} +{% def serverShimCode(iface, handler, fn, serverIDName, functionIDName) ------------------------- serverShimCode(fn, serverIDName, functionIDName) %} +{% set serverIndent = "" >%} +{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} + erpc_status_t err = kErpcStatus_Success; + +{% endif -- isReturnValue || isSendValue %} +{% for param in fn.parameters %} + {% if param.isFunction %}{% if param.ifaceScope != ""%}{$param.ifaceScope}{% else %}{$iface.name}{% endif %}_interface::{% endif %}{$param.variable}{% if param.isNullParam %} = NULL{% endif %}; +{% if !empty(param.nullVariable) %} + {$param.nullVariable} = NULL; +{% endif %} +{% if !param.shared %} +{% if param.isNullable == false && param.direction != OutDirection %} +{$> addIndent(" ", allocMem(param.mallocServer))} +{% endif -- !param.isNullable && param.direction != OutDirection %} +{% endif -- shared %} +{% endfor -- param %} +{% if fn.needNullVariableOnServer %} + bool isNull; +{% endif -- needNullVariableOnServer %} +{% if fn.needTempVariableServerI32 %} + int32_t _tmp_local_i32; +{% endif %} +{% if fn.needTempVariableServerU16 %} + uint16_t _tmp_local_u16; +{% endif %} +{% if fn.returnValue.type.isNotVoid %} + {$fn.returnValue.resultVariable}{% if fn.returnValue.isNullReturnType %} = NULL{% endif %}; +{% endif %} +{% if fn.isReturnValue || fn.isSendValue %} + +{% endif %} + // startReadMessage() was already called before this shim was invoked. + +{% if fn.isSendValue %} +{% for param in fn.parameters if (param.serializedDirection == "" || param.serializedDirection == OutDirection || param.referencedName != "") %} +{% if param.isNullable %} +{$addIndent(" ", f_paramIsNullableDecode(param))} + +{% else -- notNullable %} +{% if param.direction != OutDirection %} +{$addIndent(" ", param.coderCall.decode(param.coderCall))} + +{% endif -- param != OutDirection %} +{% endif -- isNullable %} +{% endfor -- parametersToServer %} +{% endif -- isSendValue %} +{% for param in fn.parametersToClient %} +{% if !param.shared %} +{% if param.isNullable == false && param.direction == OutDirection && empty(param.mallocServer) == false %} +{$> addIndent(" ", allocMem(param.mallocServer))} + +{% endif -- !param.isNullable && param.direction == OutDirection %} +{% endif -- shared %} +{% endfor -- param %} +{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} +{% set serverIndent = " " >%} + err = codec->getStatus(); + if (err == kErpcStatus_Success) + { +{% endif -- generateErrorChecks %} +{$serverIndent} // Invoke the actual served function. +#if ERPC_NESTED_CALLS_DETECTION +{$serverIndent} nestingDetection = true; +#endif +{% if serverIDName == "serviceID" %} +{% for callbackFunction in fn.functions %} +{$serverIndent} {% if loop.first == false %}else {% endif %}if (({$serverIDName} == {$callbackFunction.serviceId}) && ({$functionIDName} == {$callbackFunction.id})) +{$serverIndent} { +{$serverIndent} m_handler->{$callbackFunction.serverPrototype} +{$serverIndent} } +{% endfor -- callbackFunction in callbackType.functions %} +{% else -- serverIDName == "serviceID" %} +{$serverIndent} {$fn.serverPrototype} +{% endif --serverIDName == "serviceID" %} +#if ERPC_NESTED_CALLS_DETECTION +{$serverIndent} nestingDetection = false; +#endif +{% if fn.isReturnValue %} + +{$serverIndent} // preparing MessageBuffer for serializing data +{$serverIndent} {% if generateErrorChecks %}err = {% endif %}messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize()); +{% if generateErrorChecks %} + } + + if (err == kErpcStatus_Success) + { +{% endif -- generateErrorChecks %} +{$serverIndent} // preparing codec for serializing data +{$serverIndent} codec->reset(transport->reserveHeaderSize()); + +{$serverIndent} // Build response message. +{$serverIndent} codec->startWriteMessage(message_type_t::kReplyMessage, {$serverIDName}, {$functionIDName}, sequence); +{% for param in fn.parametersToClient if (param.serializedDirection == "" || param.serializedDirection == InDirection || param.referencedName != "") %} + +{% if param.isNullable %} +{$serverIndent} if ({% if source == "server" && empty(param.nullVariable) == false %}_{% endif %}{$param.name} != NULL) +{$serverIndent} { +{$addIndent(serverIndent & " ", param.coderCall.encode(param.coderCall))} +{$serverIndent} } +{% else -- isNullable %} +{$addIndent(serverIndent & " ", param.coderCall.encode(param.coderCall))} +{% endif -- isNullable %} +{% endfor -- parametersToClient %} +{% if fn.returnValue.type.isNotVoid %} + +{% if fn.returnValue.isNullable %} +{$addIndent(serverIndent & " ", f_paramIsNullableEncode(fn.returnValue))} +{% else -- isNullable %} +{$addIndent(serverIndent & " ", fn.returnValue.coderCall.encode(fn.returnValue.coderCall))} +{% endif -- isNullable %} +{% endif -- notVoid %} +{% if generateErrorChecks %} + + err = codec->getStatus(); +{% endif generateErrorChecks %} +{% endif -- isReturnValue %} +{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} + } + +{% endif -- fn.isReturnValue || fn.isSendValue %} +{% for param in fn.paramsToFree %} +{$> addIndent(" ", param.coderCall.freeingCall(param.coderCall))} +{$> addIndent(" ", param.firstFreeingCall1.firstFreeingCall(param.firstFreeingCall1))} + +{% endfor -- parameters %} +{% if fn.returnValue.type.isNotVoid %} +{% set needFreeingCall = fn.returnValue.coderCall.freeingCall(fn.returnValue.coderCall) %} +{% set needFirstFreeingCall = fn.returnValue.firstFreeingCall1.firstFreeingCall(fn.returnValue.firstFreeingCall1) %} +{% if empty(needFreeingCall) == false || empty(needFirstFreeingCall) == false %} +{$> addIndent(" ", needFreeingCall)} +{$> addIndent(" ", needFirstFreeingCall)} + +{% endif -- !empty(needFreeingCall) || !empty(needFirstFreeingCall) %} +{% endif -- notVoid %} +{% if (fn.isReturnValue || fn.isSendValue) && generateErrorChecks %} + return err; +{% else %} + return codec->getStatus(); +{% endif %} +{% enddef --------------------------------------------------------------------------------- serverShimCode(fn, serverIDName, functionIDName) %} +{% for iface in group.interfaces %} +{% for cb in iface.callbacksInt if (count(cb.callbacks) > 1) %} +// Common function for serializing and deserializing callback functions of same type. +static erpc_status_t {$iface.interfaceClassName}_{$cb.name}_shim({$iface.interfaceClassName} *m_handler, uint32_t serviceID, uint32_t functionID, {$codecClass} * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence); +{% endfor %} +{% endfor %} +{% for iface in group.interfaces %} +{% for cb in iface.callbacksInt if (count(cb.callbacks) > 1) %} + +// Common function for serializing and deserializing callback functions of same type. +static erpc_status_t {$iface.interfaceClassName}_{$cb.name}_shim({$iface.interfaceClassName} *m_handler, uint32_t serviceID, uint32_t functionID, {$codecClass} * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence) +{ +{$ serverShimCode(iface, "m_handler", cb.callbacksData, "serviceID", "functionID") >} +} +{% endfor %} +{% endfor %} +{% for iface in group.interfaces -- service subclass method impl %} + +{$iface.serviceClassName}::{$iface.serviceClassName}({$iface.interfaceClassName} *_{$iface.interfaceClassName}) + : erpc::Service({$iface.interfaceClassName}::m_serviceId) + , m_handler(_{$iface.interfaceClassName}) +{ +} + +{$iface.serviceClassName}::~{$iface.serviceClassName}() +{ +} + +// return service interface handler. +{$iface.interfaceClassName}* {$iface.serviceClassName}::getHandler(void) +{ + return m_handler; +} + +// Call the correct server shim based on method unique ID. +erpc_status_t {$iface.serviceClassName}::handleInvocation(uint32_t methodId, uint32_t sequence, Codec * codec, MessageBufferFactory *messageFactory, Transport * transport) +{ + erpc_status_t erpcStatus; +{% if codecClass != "Codec" %} + {$codecClass} *_codec = static_cast<{$codecClass} *>(codec); +{% endif %} + switch (methodId) + { +{% for fn in iface.functions %} + case {$iface.interfaceClassName}::{$getClassFunctionIdName(fn)}: + { + erpcStatus = {$fn.name}_shim({%if codecClass == "Codec" %}codec{% else %}_codec{% endif %}, messageFactory, transport, sequence); + break; + } + +{% endfor -- fn %} + default: + { + erpcStatus = kErpcStatus_InvalidArgument; + break; + } + } + + return erpcStatus; +} +{% for fn in iface.functions %} + +// Server shim for {$fn.name} of {$iface.name} interface. +erpc_status_t {$iface.serviceClassName}::{$fn.name}_shim({$codecClass} * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence) +{ +{% if fn.isCallback %} + return {$iface.interfaceClassName}_{$fn.callbackFNameNoGroup}_shim(m_handler, {$iface.interfaceClassName}::m_serviceId, {$iface.interfaceClassName}::{$getClassFunctionIdName(fn)}, codec, messageFactory, transport, sequence); +{% else -- fn.isCallback >%} +{$ serverShimCode(iface, "m_handler", fn, iface.interfaceClassName & "::m_serviceId", iface.interfaceClassName & "::" & getClassFunctionIdName(fn)) >} +{% endif -- fn.isCallback >%} +} +{% endfor -- fn %} +{% endfor -- iface %} diff --git a/erpcgen/src/templates/java_client.template b/erpcgen/src/templates/java_client.template new file mode 100644 index 00000000..3fbeab08 --- /dev/null +++ b/erpcgen/src/templates/java_client.template @@ -0,0 +1,88 @@ +/** + * Generated by erpcgen {$erpcVersion} on {$todaysDate}. + * + * AUTOGENERATED - DO NOT EDIT + */ + {% set iface = interface %} +package {$groupPackage}.client; + +import {$groupPackage}.interfaces.I{$iface.name}; +{% if not empty(group.symbolsMap.structs) %}import {$groupPackage}.common.structs.*;{% elif not empty(structs)%}import {$groupPackage}.common.structs.*;{% endif %} +{% if not empty(enums)%}import {$groupPackage}.common.enums.*;{% endif %} + +{% for inc in includes %} +import {$inc}; +{% endfor -- includes %} + +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.RequestContext; +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import io.github.embeddedrpc.erpc.client.ClientManager; +import io.github.embeddedrpc.erpc.codec.Codec; + +import java.util.ArrayList; +import java.util.List; + +public class {$iface.name}Client implements I{$iface.name} { + private final ClientManager clientManager; + + public {$iface.name}Client(ClientManager clientManager) { + this.clientManager = clientManager; + } +{% for fn in iface.functions %} +{$loop.addNewLineIfNotLast} + @Override + public {$fn.prototype} { + // Create request + RequestContext request = clientManager.createRequest({% if fn.isOneway %}true{% else %}false{% endif %}); + Codec codec = request.codec(); + + // Write message info + codec.startWriteMessage(new MessageInfo( + MessageType.{% if fn.isReturnValue %}kInvocationMessage{% else %}kOnewayMessage{% endif %}, + this.SERVICE_ID, + this.{$upper(fn.name)}_ID, + request.sequence())); + + // Write message data +{% for p in fn.inParameters if not p.serializedViaMember %} +{% if p.isNullable %} + if({$p.name} == null) { + codec.writeNullFlag(1); + } else { + codec.writeNullFlag(0); +{$ addIndent(" ", p.call.encode(p.call))} + } +{% else %} + Utils.checkNotNull({$p.name}, "{$p.name} is null"); + {% if p.call.isReference%}Utils.checkNotNull({$p.name}.get(), "{$p.name}.value is null");{% endif %} +{$ addIndent(" ", p.call.encode(p.call))} +{% endif -- isNullable %} +{% endfor -- inParams %} + + // Perform request + clientManager.performRequest(request); + +{% if not fn.isOneway %} + // Read out parameters +{% for p in fn.outParameters if not p.serializedViaMember %} +{% if p.isNullable %} + if(!codec.readNullFlag()) { +{$ addIndent(" ", p.call.decode(p.call))} + } +{% else %} +{$ addIndent(" ", p.call.decode(p.call))} +{% endif -- isNullable %} +{% endfor -- outParams %} +{% if fn.isReturnValue && fn.returnValue.type.type != "void" %} + + // Read return value +{$ addIndent(" ", fn.returnValue.call.decode(fn.returnValue.call))} + return {$fn.returnValue.call.name}; +{% endif -- returnValue %} +{% endif -- oneway %} + } +{% endfor -- fn %} +} diff --git a/erpcgen/src/templates/java_coders.template b/erpcgen/src/templates/java_coders.template new file mode 100644 index 00000000..660f502c --- /dev/null +++ b/erpcgen/src/templates/java_coders.template @@ -0,0 +1,236 @@ +{##################################################################################} +{################################### DECODING #####################################} +{##################################################################################} + +{############################### decodeBuiltinType ###############################} +{% def decodeBuiltinType(info) --------------- BuiltinType %} +{% if info.isReference%} +{$info.name}.set(codec.read{$info.type.codecTypeName}()); +{% else %} +{% if info.needTypeDeclaration %}{$info.type.typeName} {% endif %}{$info.name} = codec.read{$info.type.codecTypeName}(); +{% endif -- isReference%} +{% enddef %} + +{############################### decodeStructType ###############################} +{% def decodeStructType(info) --------------- StructType %} +{% if info.isReference%} +{$info.name}.set({$info.type.name}.read(codec)); +{% else %} +{% if info.needTypeDeclaration %}{$info.type.typeName} {% endif %}{$info.name} = {$info.type.name}.read(codec); +{% endif -- isReference%} +{% enddef -------------------------- StructType %} + +{############################### decodeArrayType ###############################} +{% def decodeArrayType(info) -------------- ArrayType %} +{% if info.isReference%} +{$info.name}.set({$info.initialization}); +{% else %} +{% if info.needTypeDeclaration %}{$info.type.typeName} {% endif %}{$info.name} = {$info.initialization}; +{% endif -- isReference%} +for (int {$info.counter} = 0; {$info.counter} < {$info.size}; ++{$info.counter}) +{ +{$ addIndent(" ", info.protoNext.decode(info.protoNext))} + {$info.name}{% if info.isReference%}.get(){% endif %}[{$info.counter}] = {$info.protoNext.name}; +} +{% enddef ----------------------------------- ArrayType %} + +{############################### decodeUnionType ###############################} +{% def decodeUnionType(info) ---------------- %} +{#var _{$name} = {$commonPrefix}{$info.name}().read({$codec}){%>%}; +var {$name} = _{$name}.getFirst(); +var {$type.discriminatorName} = {$info.name}.get(_{$name}.getSecond());#} +{% enddef -------------------------- UnionType %} + +{############################### decodeEnumType ###############################} +{% def decodeEnumType(info) ---------------- EnumType %} +{% if info.isReference%} +{$info.name}.set({$info.type.name}.read(codec)); +{% else %} +{% if info.needTypeDeclaration %}{$info.type.typeName} {% endif %}{$info.name} = {$info.type.name}.read(codec); +{% endif -- isReference%} +{% enddef ---------------------------------- EnumType %} + +{############################### decodeBinaryType ###############################} +{% def decodeBinaryType(info) ------------------- BinaryType %} +{% if info.needTypeDeclaration %}{$info.type.typeName} {% endif %}{$info.name} = codec.readBinary();{%>%} +{% enddef ------------------------------------- BinaryType %} + +{############################### decodeListType ###############################} +{% def decodeListType(info) ------------------- ListType %} +long {$info.sizeVariable} = {% if info.hasLengthVariable %}{$info.size}{% else %}codec.startReadList(){% endif %}; +{% if info.isReference%} +{$info.name}.set(new ArrayList<>()); +{% else %} +{% if info.needTypeDeclaration %}{$info.type.typeName} {% endif %}{$info.name} = new ArrayList<>(); +{% endif -- isReference%} +for (long {$info.counter} = 0L; {$info.counter} < {$info.sizeVariable}; ++{$info.counter}) { +{$addIndent(" ", info.protoNext.decode(info.protoNext))} + {$info.name}{% if info.isReference%}.get(){% endif %}.add({$info.protoNext.name}); +} +{% enddef ------------------------------------- ListType %} + + +{##################################################################################} +{################################### ENCODING #####################################} +{##################################################################################} + +{############################### encodeBuiltinType ###############################} +{% def encodeBuiltinType(info) --------------- BuiltinType %} +codec.write{$info.type.codecTypeName}({$info.name}{% if info.isReference%}.get(){% endif %}); +{% enddef %} + +{############################### encodeArrayType ###############################} +{% def encodeArrayType(info) -------------- ArrayType %} +for (int {$info.counter} = 0; {$info.counter} < {$info.size}; ++{$info.counter}) +{ + {$info.protoNext.type.typeName} {$info.protoNext.name} = {%if info.isStructMember %}this.{% endif %}{$info.name}{% if info.isReference%}.get(){% endif %}[{$info.counter}]; +{$addIndent(" ", info.protoNext.encode(info.protoNext))} +} +{% enddef ----------------------------------- ArrayType %} + +{############################### encodeStructType ###############################} +{% def encodeStructType(info) --------------- StructType %} +{%if info.isStructMember %}this.{% endif %}{$info.name}{% if info.isReference%}.get(){% endif %}.write(codec); +{% enddef -------------------------- StructType %} + +{############################### encodeUnionType ###############################} +{% def encodeUnionType(info) ---------------- %} + +{% enddef -------------------------- UnionType %} + +{############################### encodeEnumType ###############################} +{% def encodeEnumType(info) ---------------- EnumType %} +{%if info.isStructMember %}this.{% endif %}{$info.name}{% if info.isReference%}.get(){% endif %}.write(codec); +{% enddef ---------------------------------- EnumType %} + +{############################### encodeBinaryType ###############################} +{% def encodeBinaryType(info) ------------------- BinaryType %} +codec.writeBinary({%if info.isStructMember %}this.{% endif %}{$info.name}{% if info.isReference%}.get(){% endif %});{%>%} +{% enddef ------------------------------------- BinaryType %} + +{############################### encodeListType ###############################} +{% def encodeListType(info) ------------------- ListType %} +codec.startWriteList({$info.name}{% if info.isReference%}.get(){% endif %}.size()); +for ({$info.protoNext.type.typeName} {$info.protoNext.name} : {%if info.isStructMember %}this.{% endif %}{$info.name}{% if info.isReference%}.get(){% endif %}) { +{$ addIndent(" ", info.protoNext.encode(info.protoNext))} +} +{% enddef ------------------------------------- ListType %} + +{############################### union encode/decode ###############################} +{% def encodeValueUnion(info, name, codec, indent, depth) %} +{% if info.isNonEncapsulatedUnion %} +{% set self = "" %} +{% else %} +{% set self = "self." %} +{% endif %} +codec.start_write_union({$self}{$info.discriminatorName}) +{# unions are always within structs, so we have self available #} +{% set isFirst = true %} +{% set hasNonVoidCase = false %} +{% set defaultCase = false %} +{% for c in info.cases %} +{% if c.name == "default" %} +{% set defaultCase = c %} +{% elif not c.isVoid %} +{% set hasNonVoidCase = true %} +{$indent}{$"if" if isFirst else "elif"} {$self}{$info.discriminatorName} == {% if c.name != "" && (c.type.type == "enum" || c.type.type == "const") %}{% if c.type.name != "" %}{$c.type.name}.{% endif %}{$c.name}{% else %}{$c.value}{% endif %}: +{% for cm in c.members %} +{% if cm.isNullable %} +{$indent} if {$name}.{$cm.name} is None: +{$indent} {$codec}.write_null_flag(True) +{$indent} else: +{$indent} {$codec}.write_null_flag(False) +{$indent} {$encodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{% else -- isNullable %} +{$indent} if {$name}.{$cm.name} is None: +{$indent} raise ValueError("{$name}.{$cm.name} is None") +{$indent} {$encodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{% endif -- isNullable %} +{% endfor -- union case members %} +{% set isFirst = false %} +{% endif -- default case/not void %} +{% endfor -- union cases %} +{% if defaultCase %} +{% if not isFirst %} +{$indent}else: # default case +{% endif %} +{% if defaultCase.isVoid && not isFirst %} +{$indent} pass +{% else %} +{% for cm in defaultCase.members %} +{% if cm.isNullable %} +{$indent} if {$name}.{$cm.name} is None: +{$indent} {$codec}.write_null_flag(True) +{$indent} else: +{$indent} {$codec}.write_null_flag(False) +{$indent} {% if not isFirst %} {% endif %}{$encodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{% else -- isNullable %} +{$indent}{% if not isFirst %} {% endif %}{$encodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{% endif -- isNullable %} +{% endfor -- union case members %} +{% endif -- defaultCase.isVoid %} +{% elif hasNonVoidCase %} +{$indent}else: +{$indent} raise ValueError("invalid union discriminator value %s" % repr({$self}{$info.discriminatorName})) +{% endif -- defaultCase/hasNonVoidCase %} +{% enddef %} + +{% def decodeValueUnion(info, name, codec, indent, depth) %} +{% if info.isNonEncapsulatedUnion %} +{% set self = "" %} +{% else %} +{% set self = "self." %} +{% endif %} +{$self}{$info.discriminatorName} = codec.start_read_union() +{% if self == "self." %} +{$indent}{$name} = {$name}_union() +{% endif %} +{% set isFirst = true %} +{% set hasNonVoidCase = false %} +{% set defaultCase = false %} +{% for c in info.cases %} +{% if c.name == "default" %} +{% set defaultCase = c %} +{% elif not c.isVoid %} +{% set hasNonVoidCase = true %} +{$indent}{$"if" if isFirst else "elif"} {$self}{$info.discriminatorName} == {% if c.name != "" && (c.type.type == "enum" || c.type.type == "const") %}{% if c.type.name != "" %}{$c.type.name}.{% endif %}{$c.name}{% else %}{$c.value}{% endif %}: +{% for cm in c.members %} +{% if cm.isNullable %} +{$indent} if not {$codec}.read_null_flag() +{$indent} {$decodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{$indent} else: +{$indent} {$name}.{$cm.name} = None +{% else -- isNullable %} +{$indent} {$decodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{% endif -- isNullable %} +{% endfor -- union case members %} +{% set isFirst = false %} +{% endif -- default/not void %} +{% endfor -- union cases %} +{% if defaultCase %} +{% if not isFirst %} +{$indent}else: # default case +{% endif %} +{% if defaultCase.isVoid && not isFirst %} +{$indent} pass +{% else %} +{% for cm in defaultCase.members %} +{% if cm.isNullable %} +{$indent} if not {$codec}.read_null_flag() +{$indent} {% if not isFirst %} {% endif %}{$decodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{$indent} else: +{$indent} {$name}.{$cm.name} = None +{% else -- isNullable %} +{$indent}{% if not isFirst %} {% endif %}{$decodeValue(cm.type, name & "." & cm.name, codec, indent & " ", depth + 1)} +{% endif -- isNullable %} +{% endfor -- union case members %} +{% endif -- defaultCase.isVoid %} +{% elif hasNonVoidCase %} +{$indent}else: +{$indent} raise ValueError("invalid union discriminator value %s" % repr({$self}{$info.discriminatorName})) +{% endif -- default/hasNonVoidCase %} +{% enddef %} + +{% def getTypeValuePosfix(type) %} +{% if type.type == "float" %}F{% elif type.type == "long" %}L{% elif type.type == "double" %}D{% endif %}{%>%} +{% enddef%} \ No newline at end of file diff --git a/erpcgen/src/templates/java_const.template b/erpcgen/src/templates/java_const.template new file mode 100644 index 00000000..8b44ee3d --- /dev/null +++ b/erpcgen/src/templates/java_const.template @@ -0,0 +1,27 @@ +/** + * Generated by erpcgen {$erpcVersion} on {$todaysDate}. + * + * AUTOGENERATED - DO NOT EDIT + */ + package {$groupPackage}.common; + +{% if not empty(group.symbolsMap.structs) %}import {$groupPackage}.common.structs.*;{% elif not empty(structs)%}import {$groupPackage}.common.structs.*;{% endif %} +{% if not empty(enums)%}import {$groupPackage}.common.enums.*;{% endif %} + +{% for inc in includes %} +import {$inc}; +{% endfor -- includes %} + +import java.util.ArrayList; +import java.util.List; + +public final class Constants { +{% for c in consts %} + {$>c.mlComment} + public static final {$c.type.typeName} {$c.name} = {$c.value}{$getTypeValuePosfix(c.type)};{% if c.ilComment %} {$c.ilComment}{% endif %} +{% endfor %} + + private Constants() { + } +} + diff --git a/erpcgen/src/templates/java_enum.template b/erpcgen/src/templates/java_enum.template new file mode 100644 index 00000000..bc0f2a4d --- /dev/null +++ b/erpcgen/src/templates/java_enum.template @@ -0,0 +1,51 @@ +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +/** + * Generated by erpcgen {$erpcVersion} on {$todaysDate}. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package {$groupPackage}.common.enums; + +import io.github.embeddedrpc.erpc.codec.Codec; + +{$>(enum.mlComment or enum.ilComment)} +public enum {$enum.name}{ +{% for member in enum.members %} +{% if member.mlComment %} + {$member.mlComment} +{% endif %} + {$member.name}({$member.value}){% if !loop.last %},{% else %};{% endif %} {% if member.ilComment %}{$member.ilComment}{% endif %} +{% endfor -- member %} + + private final Integer value; + + {$enum.name}(Integer value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static {$enum.name} get(int value) { +{% for member in enum.members %} + if (value == {$member.value}) { + return {$member.name}; + } + +{% endfor %} + return null; + } + + public static {$enum.name} read(Codec codec) { + return get(codec.readInt32()); + } + + public void write(Codec codec) { + codec.writeInt32(this.getValue()); + } +} \ No newline at end of file diff --git a/erpcgen/src/templates/java_interface.template b/erpcgen/src/templates/java_interface.template new file mode 100644 index 00000000..69267d52 --- /dev/null +++ b/erpcgen/src/templates/java_interface.template @@ -0,0 +1,42 @@ +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +/** + * Generated by erpcgen {$erpcVersion} on {$todaysDate}. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package {$groupPackage}.interfaces; +{% if not empty(group.symbolsMap.structs) %}import {$groupPackage}.common.structs.*;{% elif not empty(structs)%}import {$groupPackage}.common.structs.*;{% endif %} +{% if not empty(enums)%}import {$groupPackage}.common.enums.*;{% endif %} + +{% for inc in includes %} +import {$inc}; +{% endfor -- includes %} + +import io.github.embeddedrpc.erpc.auxiliary.Reference; + +import java.util.List; + +{% if interface.mlComment %} +{$interface.mlComment} +{% else %} +{% endif %} +public interface I{$interface.name} { + int SERVICE_ID = {$interface.id}; +{% for fn in interface.functions %} + int {$upper(fn.name)}_ID = {$fn.id}; +{% endfor -- fn %} + +{% for fn in interface.functions %} +{% if fn.mlComment %} +{$fn.mlComment} +{% endif %} + {$fn.prototype}; +{% endfor -- fn %} +} + + + diff --git a/erpcgen/src/templates/java_server.template b/erpcgen/src/templates/java_server.template new file mode 100644 index 00000000..fd2ad1ce --- /dev/null +++ b/erpcgen/src/templates/java_server.template @@ -0,0 +1,87 @@ +/** + * Generated by erpcgen {$erpcVersion} on {$todaysDate}. + * + * AUTOGENERATED - DO NOT EDIT + */ +{% set iface = interface %} +package {$groupPackage}.server; + +import {$groupPackage}.interfaces.I{$iface.name}; +{% if not empty(group.symbolsMap.structs) %}import {$groupPackage}.common.structs.*;{% elif not empty(structs)%}import {$groupPackage}.common.structs.*;{% endif %} +{% if not empty(enums)%}import {$groupPackage}.common.enums.*;{% endif %} + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.auxiliary.Reference; + +{% for inc in includes %} +import {$inc}; +{% endfor -- includes %} + +import java.util.ArrayList; +import java.util.List; + +/** + * Testing abstract service class for simple eRPC interface. + */ +public abstract class Abstract{$iface.name}Service + extends Service + implements I{$iface.name} { + + /** + * Default constructor. + */ + public Abstract{$iface.name}Service() { + super(I{$iface.name}.SERVICE_ID); +{% for fn in iface.functions %} + addMethodHandler(I{$iface.name}.{$upper(fn.name)}_ID, this::{$fn.name}Handler); +{% endfor -- fn %} + } + +{% for fn in iface.functions %} + private void {$fn.name}Handler(int sequence, Codec codec) { +{% for p in fn.parameters if not p.serializedViaMember %} + {$p.call.type.typeName} {$p.name}{% if p.call.isReference %} = new Reference<>(){% endif%}; +{% endfor %} + +{% for p in fn.inParameters if not p.serializedViaMember %} +{% set tmp = p.call.needTypeDeclaration%} +{% set p.call.needTypeDeclaration = false %} +{$ addIndent(" ", p.call.decode(p.call))} +{% set p.call.needTypeDeclaration = tmp %} +{% endfor %} + + {% if not fn.isOneway %}{% if fn.isReturnValue && fn.returnValue.type.type != "void" %}{$fn.returnValue.call.type.typeName} _result = {% endif %}{% endif %}{$fn.name}({% for p in fn.parameters if not p.serializedViaMember %}{$p.name}{% if !loop.last%}, {% endif %}{% endfor %}); + + codec.reset(); + +{% if not fn.isOneway %} + codec.startWriteMessage(new MessageInfo( + MessageType.kReplyMessage, + getServiceId(), + I{$iface.name}.{$upper(fn.name)}_ID, + sequence) + ); + + // Read out parameters +{% for p in fn.outParameters if not p.serializedViaMember %} +{% if p.isNullable %} + if(!codec.readNullFlag()) { +{$ addIndent(" ", p.call.encode(p.call))} + } +{% else %} +{$ addIndent(" ", p.call.encode(p.call))} +{% endif -- isNullable %} +{% endfor -- outParams %} +{% if fn.isReturnValue && fn.returnValue.type.type != "void" %} + // Read return value +{$ addIndent(" ", fn.returnValue.call.encode(fn.returnValue.call))} +{% endif -- returnValue %} +{% endif -- oneway %} + } +{% endfor -- fn %} + +} + diff --git a/erpcgen/src/templates/java_struct.template b/erpcgen/src/templates/java_struct.template new file mode 100644 index 00000000..0a376017 --- /dev/null +++ b/erpcgen/src/templates/java_struct.template @@ -0,0 +1,95 @@ +{% if mlComment != "" %} +{$mlComment} + +{% endif %} +/** + * Generated by erpcgen {$erpcVersion} on {$todaysDate}. + * + * AUTOGENERATED - DO NOT EDIT + */ +package {$groupPackage}.common.structs; + +{% if not empty(group.symbolsMap.structs) %}import {$groupPackage}.common.structs.*;{% elif not empty(structs)%}import {$groupPackage}.common.structs.*;{% endif %} +{% if not empty(enums)%}import {$groupPackage}.common.enums.*;{% endif %} +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import io.github.embeddedrpc.erpc.codec.Codec; + +{% for inc in includes %} +import {$inc}; +{% endfor -- includes %} + +import java.util.ArrayList; +import java.util.List; + +{% set s = struct %} +{$>(s.mlComment or s.ilComment)} +public class {$s.name}{ +{% for m in s.members if not m.lengthForMember %} +{% if m.mlComment or m.ilComment %} + {$m.mlComment or m.ilComment} +{% endif %} + private {$m.call.type.typeName} {$m.call.name}; +{% endfor -- members %} + + public {$s.name} ({% for m in s.members if ((not m.lengthForMember) && (m.call.type.type != 'union' or m.call.type.isNonEncapsulatedUnion)) %}{$m.call.type.typeName} {$m.call.name}{% if !loop.last %}, {% endif %}{% endfor %}) { +{% for m in s.members if not m.lengthForMember %} + this.{$m.call.name} = {$m.call.name}; +{% endfor -- members %} + } + + public {$s.name}() { + } + + public void write(Codec codec) { +{% for m in s.members if not m.serializedViaMember %} +{% if m.isNullable %} + if(this.{$m.name} == null) { + codec.writeNullFlag(1); + } else { + codec.writeNullFlag(0); +{$ addIndent(" ", m.call.encode(m.call))} + } +{% else %} + Utils.checkNotNull({$m.name}, "{$m.name} is null"); + {% if m.call.isReference%}Utils.checkNotNull({$m.name}.get(), "{$m.name}.value is null");{% endif %} +{$ addIndent(" ", m.call.encode(m.call))} +{% endif -- isNullable %} +{% endfor -- members %} + } + + public static {$s.name} read(Codec codec) { + {$s.name} _struct = new {$s.name}(); +{% for m in s.members if not m.serializedViaMember %} +{% set name = m.call.name%} +{% set m.call.name = "_struct." & m.call.name %} +{% if m.isNullable %} + if(!codec.readNullFlag()) { +{$ addIndent(" ", m.call.decode(m.call))} + } +{% else %} +{$ addIndent(" ", m.call.decode(m.call))} +{% endif -- isNullable %} +{% set m.call.name = name %} +{% endfor -- members %} + return _struct; + } + +{% for m in s.members if ((not m.lengthForMember) && (m.call.type.type != 'union' or m.call.type.isNonEncapsulatedUnion)) %} + public {$m.call.type.typeName} get_{$m.name}() { + return {$m.name}; + } + + public void set_{$m.name}({$m.call.type.typeName} {$m.name}) { + this.{$m.name} = {$m.name}; + } +{% endfor %} + +{# create read-only properties for @length counts #} +{% for m in s.members if m.lengthForMember %} + public int {$m.name}() { + return {$m.lengthForMember}.size(); + } + +{% endfor -- s.members %} +} diff --git a/erpcgen/src/types/AliasType.hpp b/erpcgen/src/types/AliasType.hpp index 6fc99285..7c912772 100644 --- a/erpcgen/src/types/AliasType.hpp +++ b/erpcgen/src/types/AliasType.hpp @@ -34,9 +34,8 @@ class AliasType : public DataType * @param[in] name Name. * @param[in] elementType Given data type. */ - AliasType(const std::string &name, DataType *elementType) - : DataType(name, kAliasType) - , m_elementType(elementType) + AliasType(const std::string &name, DataType *elementType) : + DataType(name, data_type_t::kAliasType), m_elementType(elementType) { } @@ -48,9 +47,8 @@ class AliasType : public DataType * @param[in] tok Token, which contains name and location. * @param[in] elementType Given data type. */ - AliasType(const Token &tok, DataType *elementType) - : DataType(tok, kAliasType) - , m_elementType(elementType) + AliasType(const Token &tok, DataType *elementType) : + DataType(tok, data_type_t::kAliasType), m_elementType(elementType) { } diff --git a/erpcgen/src/types/Annotation.hpp b/erpcgen/src/types/Annotation.hpp index 029b232f..e10d92b5 100644 --- a/erpcgen/src/types/Annotation.hpp +++ b/erpcgen/src/types/Annotation.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016-2023 NXP * All rights reserved. * * @@ -28,11 +28,12 @@ namespace erpcgen { class Annotation { public: - enum program_lang_t + enum class program_lang_t { kAll, kC, - kPython + kPython, + kJava }; /*! @@ -44,11 +45,8 @@ class Annotation * @param[in] val Pointer to value. * @param[in] lang Programming language for which is annotation intended. */ - Annotation(const Token &token, Value *val, program_lang_t lang) - : m_name(token.getStringValue()) - , m_value(val) - , m_location(token.getLocation()) - , m_lang(lang) + Annotation(const Token &token, Value *val, program_lang_t lang) : + m_name(token.getStringValue()), m_value(val), m_location(token.getLocation()), m_lang(lang) { } @@ -59,11 +57,8 @@ class Annotation * * @param[in] token Token contains annotation name and location in parsed file. */ - explicit Annotation(const Token &token) - : m_name(token.getStringValue()) - , m_value(nullptr) - , m_location(token.getLocation()) - , m_lang(kAll) + explicit Annotation(const Token &token) : + m_name(token.getStringValue()), m_value(nullptr), m_location(token.getLocation()), m_lang(program_lang_t::kAll) { } @@ -74,11 +69,8 @@ class Annotation * * @param[in] a Source annotation. */ - explicit Annotation(const Annotation &a) - : m_name(a.m_name) - , m_value(a.m_value) - , m_location(a.m_location) - , m_lang(a.m_lang) + explicit Annotation(const Annotation &a) : + m_name(a.m_name), m_value(a.m_value), m_location(a.m_location), m_lang(a.m_lang) { } diff --git a/erpcgen/src/types/ArrayType.hpp b/erpcgen/src/types/ArrayType.hpp index 13d105c4..16a6014c 100644 --- a/erpcgen/src/types/ArrayType.hpp +++ b/erpcgen/src/types/ArrayType.hpp @@ -34,10 +34,8 @@ class ArrayType : public DataType * @param[in] elementType Given data type. * @param[in] elementCount Given count. */ - ArrayType(DataType *elementType, uint32_t elementCount) - : DataType("(array)", kArrayType) - , m_elementType(elementType) - , m_elementCount(elementCount) + ArrayType(DataType *elementType, uint32_t elementCount) : + DataType("(array)", data_type_t::kArrayType), m_elementType(elementType), m_elementCount(elementCount) { } diff --git a/erpcgen/src/types/BuiltinType.hpp b/erpcgen/src/types/BuiltinType.hpp index 003c04ce..4cb45aa0 100644 --- a/erpcgen/src/types/BuiltinType.hpp +++ b/erpcgen/src/types/BuiltinType.hpp @@ -29,7 +29,7 @@ class BuiltinType : public DataType /*! * @brief Atomic builtin types. */ - enum _builtin_type + enum class builtin_type_t { kBoolType, kInt8Type, @@ -55,9 +55,8 @@ class BuiltinType : public DataType * @param[in] name Given name. * @param[in] builtinType Given builtin type. */ - BuiltinType(const std::string &name, _builtin_type builtinType) - : DataType(name, kBuiltinType) - , m_builtinType(builtinType) + BuiltinType(const std::string &name, builtin_type_t builtinType) : + DataType(name, data_type_t::kBuiltinType), m_builtinType(builtinType) { } @@ -66,7 +65,7 @@ class BuiltinType : public DataType * * @return Builtin type of current object. */ - _builtin_type getBuiltinType() const { return m_builtinType; } + builtin_type_t getBuiltinType() const { return m_builtinType; } /*! * @brief This function return "true" value for identify scalar type. @@ -82,7 +81,10 @@ class BuiltinType : public DataType * @retval true When builtin type is int. * @retval false When builtin type isn't int. */ - virtual bool isInt() const override { return ((kInt8Type <= m_builtinType) && (m_builtinType <= kUInt64Type)); } + virtual bool isInt() const override + { + return ((builtin_type_t::kInt8Type <= m_builtinType) && (m_builtinType <= builtin_type_t::kUInt64Type)); + } /*! * @brief This function return "true" value for identify float type. @@ -90,7 +92,10 @@ class BuiltinType : public DataType * @retval true When builtin type is float. * @retval false When builtin type isn't float. */ - virtual bool isFloat() const override { return ((m_builtinType == kFloatType) || (m_builtinType == kDoubleType)); } + virtual bool isFloat() const override + { + return ((m_builtinType == builtin_type_t::kFloatType) || (m_builtinType == builtin_type_t::kDoubleType)); + } /*! * @brief This function return "true" value for identify bool type. @@ -98,7 +103,7 @@ class BuiltinType : public DataType * @retval true When builtin type is bool. * @retval false When builtin type isn't bool. */ - virtual bool isBool() const override { return m_builtinType == kBoolType; } + virtual bool isBool() const override { return m_builtinType == builtin_type_t::kBoolType; } /*! * @brief This function return true/false value for identify string type. @@ -108,7 +113,7 @@ class BuiltinType : public DataType */ virtual bool isString() const override { - return ((m_builtinType == kStringType) || (m_builtinType == kUStringType)); + return ((m_builtinType == builtin_type_t::kStringType) || (m_builtinType == builtin_type_t::kUStringType)); } /*! @@ -117,7 +122,7 @@ class BuiltinType : public DataType * @retval true When builtin type is ustring. * @retval false When builtin type isn't ustring. */ - virtual bool isUString() const override { return m_builtinType == kUStringType; } + virtual bool isUString() const override { return m_builtinType == builtin_type_t::kUStringType; } /*! * @brief This function return true/false value for identify binary type. @@ -125,10 +130,10 @@ class BuiltinType : public DataType * @retval true When builtin type is binary. * @retval false When builtin type isn't binary. */ - virtual bool isBinary() const override { return m_builtinType == kBinaryType; } + virtual bool isBinary() const override { return m_builtinType == builtin_type_t::kBinaryType; } protected: - _builtin_type m_builtinType; /*!< Builtin type of current object. */ + builtin_type_t m_builtinType; /*!< Builtin type of current object. */ }; } // namespace erpcgen diff --git a/erpcgen/src/types/ConstType.hpp b/erpcgen/src/types/ConstType.hpp index 7b1988fa..4c523aaf 100644 --- a/erpcgen/src/types/ConstType.hpp +++ b/erpcgen/src/types/ConstType.hpp @@ -36,10 +36,8 @@ class ConstType : public Symbol * @param[in] dataType Given data type.. * @param[in] value Given value. */ - ConstType(const Token &tok, DataType *dataType, Value *value) - : Symbol(kConstSymbol, tok) - , m_dataType(dataType) - , m_value(value) + ConstType(const Token &tok, DataType *dataType, Value *value) : + Symbol(symbol_type_t::kConstSymbol, tok), m_dataType(dataType), m_value(value) { } diff --git a/erpcgen/src/types/DataType.hpp b/erpcgen/src/types/DataType.hpp index 9cdfd55b..bc646fee 100644 --- a/erpcgen/src/types/DataType.hpp +++ b/erpcgen/src/types/DataType.hpp @@ -29,7 +29,7 @@ class DataType : public Symbol /*! * @brief Supported data types. */ - enum data_type_t + enum class data_type_t { kAliasType, kArrayType, @@ -49,11 +49,7 @@ class DataType : public Symbol * * @param[in] dataType Given data type. */ - explicit DataType(data_type_t dataType) - : Symbol(kTypenameSymbol) - , m_dataType(dataType) - { - } + explicit DataType(data_type_t dataType) : Symbol(symbol_type_t::kTypenameSymbol), m_dataType(dataType) {} /*! * @brief Constructor. @@ -63,9 +59,8 @@ class DataType : public Symbol * @param[in] dataType Given data type. * @param[in] name Given name for symbol. */ - DataType(const std::string &name, data_type_t dataType) - : Symbol(kTypenameSymbol, name) - , m_dataType(dataType) + DataType(const std::string &name, data_type_t dataType) : + Symbol(symbol_type_t::kTypenameSymbol, name), m_dataType(dataType) { } /*! @@ -77,9 +72,7 @@ class DataType : public Symbol * @param[in] dataType Given data type. * @param[in] symbolType Given symbol type for symbol. */ - DataType(const Token &tok, data_type_t dataType) - : Symbol(kTypenameSymbol, tok) - , m_dataType(dataType) + DataType(const Token &tok, data_type_t dataType) : Symbol(symbol_type_t::kTypenameSymbol, tok), m_dataType(dataType) { } @@ -115,7 +108,7 @@ class DataType : public Symbol * @retval true When data type is AliasType. * @retval false When data type isn't AliasType. */ - bool isAlias() const { return (m_dataType == kAliasType); } + bool isAlias() const { return (m_dataType == data_type_t::kAliasType); } /*! * @brief This function is testing data type. @@ -123,7 +116,7 @@ class DataType : public Symbol * @retval true When data type is ArrayType. * @retval false When data type isn't ArrayType. */ - bool isArray() const { return (m_dataType == kArrayType); } + bool isArray() const { return (m_dataType == data_type_t::kArrayType); } /*! * @brief This function return "false" value as default for identify binary type. @@ -145,7 +138,7 @@ class DataType : public Symbol * @retval true When data type is BuiltinType. * @retval false When data type isn't BuiltinType. */ - bool isBuiltin() const { return (m_dataType == kBuiltinType); } + bool isBuiltin() const { return (m_dataType == data_type_t::kBuiltinType); } /*! * @brief This function is testing data type. @@ -153,7 +146,7 @@ class DataType : public Symbol * @retval true When data type is EnumTyp. * @retval false When data type isn't EnumTyp. */ - bool isEnum() const { return (m_dataType == kEnumType); } + bool isEnum() const { return (m_dataType == data_type_t::kEnumType); } /*! * @brief This function is testing data type. @@ -161,7 +154,7 @@ class DataType : public Symbol * @retval true When data type is FunctionType. * @retval false When data type isn't FunctionType. */ - bool isFunction() const { return (m_dataType == kFunctionType); } + bool isFunction() const { return (m_dataType == data_type_t::kFunctionType); } /*! * @brief This function is testing data type. @@ -169,7 +162,7 @@ class DataType : public Symbol * @retval true When data type is ListType. * @retval false When data type isn't ListType. */ - bool isList() const { return (m_dataType == kListType); } + bool isList() const { return (m_dataType == data_type_t::kListType); } /*! * @brief This function return "false" value as default for identify scalar builtin type. @@ -212,7 +205,7 @@ class DataType : public Symbol * @retval true When data type is StructType. * @retval false When data type isn't StructType. */ - bool isStruct() const { return (m_dataType == kStructType); } + bool isStruct() const { return (m_dataType == data_type_t::kStructType); } /*! * @brief This function is testing data type. @@ -220,7 +213,7 @@ class DataType : public Symbol * @retval true When data type is UnionType. * @retval false When data type isn't UnionType. */ - bool isUnion() const { return (m_dataType == kUnionType); } + bool isUnion() const { return (m_dataType == data_type_t::kUnionType); } /*! * @brief This function is testing data type. @@ -228,7 +221,7 @@ class DataType : public Symbol * @retval true When data type is VoidType. * @retval false When data type isn't VoidType. */ - bool isVoid() const { return (m_dataType == kVoidType); } + bool isVoid() const { return (m_dataType == data_type_t::kVoidType); } protected: data_type_t m_dataType; /*!< Data type of current object */ diff --git a/erpcgen/src/types/EnumMember.hpp b/erpcgen/src/types/EnumMember.hpp index ea8b0715..730f5e4d 100644 --- a/erpcgen/src/types/EnumMember.hpp +++ b/erpcgen/src/types/EnumMember.hpp @@ -34,10 +34,8 @@ class EnumMember : public Symbol * @param[in] tok Token, which contains name and location. * @param[in] value Given value. */ - EnumMember(const Token &tok, uint32_t value) - : Symbol(kEnumMemberSymbol, tok) - , m_value(value) - , m_valueSet(true) + EnumMember(const Token &tok, uint32_t value) : + Symbol(symbol_type_t::kEnumMemberSymbol, tok), m_value(value), m_valueSet(true) { } @@ -48,10 +46,8 @@ class EnumMember : public Symbol * * @param[in] tok Token, which contains name and location. */ - explicit EnumMember(const Token &tok) - : Symbol(kEnumMemberSymbol, tok) - , m_value(-1) - , m_valueSet(false) + explicit EnumMember(const Token &tok) : + Symbol(symbol_type_t::kEnumMemberSymbol, tok), m_value(-1), m_valueSet(false) { } diff --git a/erpcgen/src/types/EnumType.hpp b/erpcgen/src/types/EnumType.hpp index 91d0c932..2f35de26 100644 --- a/erpcgen/src/types/EnumType.hpp +++ b/erpcgen/src/types/EnumType.hpp @@ -37,20 +37,14 @@ class EnumType : public DataType * * @param[in] tok Given token. */ - explicit EnumType(const Token &tok) - : DataType(tok, kEnumType) - { - } + explicit EnumType(const Token &tok) : DataType(tok, data_type_t::kEnumType) {} /*! * @brief Constructor. * * This function set DataType with default name. */ - EnumType() - : DataType("", kEnumType) - { - } + EnumType() : DataType("", data_type_t::kEnumType) {} /*! * @brief This function will add enum member to the enum. diff --git a/erpcgen/src/types/Function.hpp b/erpcgen/src/types/Function.hpp index 20262352..11fda0c7 100644 --- a/erpcgen/src/types/Function.hpp +++ b/erpcgen/src/types/Function.hpp @@ -21,6 +21,7 @@ //////////////////////////////////////////////////////////////////////////////// namespace erpcgen { +class Interface; /*! * @brief Function base declaration. @@ -33,15 +34,20 @@ class FunctionBase /*! * @brief Constructor. */ - FunctionBase() - : m_parameters("(fn)") - , m_returnType(nullptr) - , m_isOneway(false) + FunctionBase(Interface *interface) : + m_parameters("(fn)"), m_returnType(nullptr), m_isOneway(false), m_interface(interface) { } virtual ~FunctionBase(){}; + /*! + * @brief This function returns parent Interface. + * + * @return parent Interface. + */ + Interface *getInterface() const { return m_interface; } + /*! * @brief This function returns function parameters. * @@ -105,9 +111,9 @@ class FunctionBase StructType m_parameters; /*!< Function parameters are saved as structure members. */ StructMember *m_returnType; /*!< Function return data type. */ bool m_isOneway; /*!< If false then communication is bidirectional. */ + Interface *m_interface; /*!< Parent interface. */ }; -class Interface; class FunctionType; /*! * @brief Function declaration. @@ -123,14 +129,11 @@ class Function : public FunctionBase, public Symbol * This function set symbol token to given token. * * @param[in] tok Given token. - * @param[in] m_interface Parent interface. - */ - Function(const Token &tok, Interface *interface) - : FunctionBase() - , Symbol(kFunctionSymbol, tok) - , m_uniqueId(++s_idCounter) - , m_interface(interface) - , m_functionType(nullptr) + * @param[in] interface Parent interface. + */ + Function(const Token &tok, Interface *interface) : + FunctionBase(interface), Symbol(symbol_type_t::kFunctionSymbol, tok), m_uniqueId(++s_idCounter), + m_functionType(nullptr) { } @@ -140,15 +143,11 @@ class Function : public FunctionBase, public Symbol * This function set symbol token to given token, uniqueId and idCounter to given uniqueId. * * @param[in] tok Given token. - * @param[in] m_interface Parent interface. + * @param[in] interface Parent interface. * @param[in] uniqueId Given unique function id. */ - Function(const Token &tok, Interface *interface, uint32_t uniqueId) - : FunctionBase() - , Symbol(kFunctionSymbol, tok) - , m_uniqueId(uniqueId) - , m_interface(interface) - , m_functionType(nullptr) + Function(const Token &tok, Interface *interface, uint32_t uniqueId) : + FunctionBase(interface), Symbol(symbol_type_t::kFunctionSymbol, tok), m_uniqueId(uniqueId), m_functionType(nullptr) { s_idCounter = uniqueId; } @@ -167,13 +166,6 @@ class Function : public FunctionBase, public Symbol */ void setUniqueId(uint32_t newId) { m_uniqueId = newId; } - /*! - * @brief This function returns parent Interface. - * - * @return parent Interface. - */ - Interface *getInterface() const { return m_interface; } - /*! * @brief This function returns description about the interface function. * @@ -206,8 +198,7 @@ class Function : public FunctionBase, public Symbol protected: uint32_t m_uniqueId; /*!< Function unique id. */ - Interface *m_interface; /*!< Parent interface. */ - FunctionType *m_functionType; /*!< Parent interface. */ + FunctionType *m_functionType; /*!< Function type. */ static uint32_t s_idCounter; /*!< Function id counter. Each function will increase this. */ }; diff --git a/erpcgen/src/types/FunctionType.hpp b/erpcgen/src/types/FunctionType.hpp index cbe0697d..923cbac4 100644 --- a/erpcgen/src/types/FunctionType.hpp +++ b/erpcgen/src/types/FunctionType.hpp @@ -39,11 +39,10 @@ class FunctionType : public FunctionBase, public DataType * This function set symbol token to given token. * * @param[in] tok Given token. + * @param[in] m_interface Parent interface. */ - explicit FunctionType(const Token &tok) - : FunctionBase() - , DataType(tok, kFunctionType) - , m_callbackFuns() + FunctionType(const Token &tok, Interface *interface) : + FunctionBase(interface), DataType(tok, data_type_t::kFunctionType), m_callbackFuns() { } diff --git a/erpcgen/src/types/Group.hpp b/erpcgen/src/types/Group.hpp index ff7f51f0..a9399d15 100644 --- a/erpcgen/src/types/Group.hpp +++ b/erpcgen/src/types/Group.hpp @@ -30,7 +30,7 @@ class Group public: typedef std::vector interface_list_t; /*!< Vector of interfaces belongs to group. */ typedef std::vector symbols_list_t; /*!< Vector of symbols belongs to group. */ - typedef std::map > + typedef std::map> symbol_directions_map_t; /*!< Map symbol with direction in which is used in current group. */ /*! @@ -38,10 +38,7 @@ class Group * * @param[in] name Group name. */ - explicit Group(const std::string &name) - : m_name(name) - { - } + explicit Group(const std::string &name) : m_name(name) { m_template["name"] = name; } /*! * @brief This function returns the group name. @@ -70,7 +67,7 @@ class Group * @param[in] symbol Symbol for which direction should be added. * @param[in] dir Direction of the symbol. */ - void addDirToSymbolsMap(Symbol *symbol, _param_direction dir); + void addDirToSymbolsMap(Symbol *symbol, param_direction_t dir); /*! * @brief This function returns set with symbol directions. @@ -79,7 +76,7 @@ class Group * * @return Set with symbol directions. */ - const std::set<_param_direction> getSymbolDirections(Symbol *symbol) const; + const std::set getSymbolDirections(Symbol *symbol) const; /*! * @brief This function returns vector with symbols. diff --git a/erpcgen/src/types/Interface.hpp b/erpcgen/src/types/Interface.hpp index 1dea8b36..0bbe61b0 100644 --- a/erpcgen/src/types/Interface.hpp +++ b/erpcgen/src/types/Interface.hpp @@ -29,7 +29,8 @@ namespace erpcgen { class Interface : public Symbol { public: - typedef std::vector function_vector_t; /*!< Vector of Interface functions. */ + typedef std::vector function_vector_t; /*!< Vector of Interface functions. */ + typedef std::vector function_types_vector_t; /*!< Vector of Interface function types. */ /*! * @brief Constructor. @@ -38,10 +39,8 @@ class Interface : public Symbol * * @param[in] tok Given token. */ - explicit Interface(const Token &tok) - : Symbol(kInterfaceSymbol, tok) - , m_scope() - , m_uniqueId(s_idCounter++) + explicit Interface(const Token &tok) : + Symbol(symbol_type_t::kInterfaceSymbol, tok), m_scope(), m_uniqueId(s_idCounter++) { } @@ -55,6 +54,16 @@ class Interface : public Symbol */ void addFunction(Function *func); + /*! + * @brief This function will add function type to the interface. + * + * The function will add function type given by pointer func to the interface members vector m_functionTypes. + * Also this member will be added as symbol to interface symbol scope m_scope. + * + * @param[in] func Function pointer, which is added to interface members vector. + */ + void addFunctionType(FunctionType *func); + /*! * @brief This function return symbol scope. * @@ -67,7 +76,14 @@ class Interface : public Symbol * * @return Interface functions vector. */ - function_vector_t &getFunctions() { return m_functions; } + const function_vector_t &getFunctions() const { return m_functions; } + + /*! + * @brief This function return interface function types vector. + * + * @return Interface function types vector. + */ + const function_types_vector_t &getFunctionTypes() const { return m_functionTypes; } /*! * @brief This function get unique id of interface. @@ -101,9 +117,10 @@ class Interface : public Symbol virtual std::string getDescription() const override; protected: - SymbolScope m_scope; /*!< Scope which interface belongs to. */ - function_vector_t m_functions; /*!< Vector of interface functions. */ - uint32_t m_uniqueId; /*!< Interface unique id. */ + SymbolScope m_scope; /*!< Scope which interface belongs to. */ + function_vector_t m_functions; /*!< Vector of interface functions. */ + function_types_vector_t m_functionTypes; /*!< Vector of interface function types. */ + uint32_t m_uniqueId; /*!< Interface unique id. */ static uint32_t s_idCounter; /*!< Interface id counter. Each interface will increase this. */ }; diff --git a/erpcgen/src/types/ListType.hpp b/erpcgen/src/types/ListType.hpp index f564d7cd..e9b76cc0 100644 --- a/erpcgen/src/types/ListType.hpp +++ b/erpcgen/src/types/ListType.hpp @@ -33,10 +33,8 @@ class ListType : public DataType * * @param[in] elementType Given data type. */ - explicit ListType(DataType *elementType) - : DataType("(list)", kListType) - , m_elementType(elementType) - , m_lengthVariableName("") + explicit ListType(DataType *elementType) : + DataType("(list)", data_type_t::kListType), m_elementType(elementType), m_lengthVariableName("") { } diff --git a/erpcgen/src/types/Program.hpp b/erpcgen/src/types/Program.hpp index 990aed65..77179016 100644 --- a/erpcgen/src/types/Program.hpp +++ b/erpcgen/src/types/Program.hpp @@ -35,10 +35,7 @@ class Program : public Symbol * * @param[in] tok Given token. */ - explicit Program(const Token &tok) - : Symbol(kProgramSymbol, tok) - { - } + explicit Program(const Token &tok) : Symbol(symbol_type_t::kProgramSymbol, tok) {} }; } // namespace erpcgen diff --git a/erpcgen/src/types/StructMember.hpp b/erpcgen/src/types/StructMember.hpp index 576e74bd..6c0fb055 100644 --- a/erpcgen/src/types/StructMember.hpp +++ b/erpcgen/src/types/StructMember.hpp @@ -24,7 +24,7 @@ namespace erpcgen { /*! * @brief Supported directions types. */ -enum _param_direction +enum class param_direction_t { kInDirection, kOutDirection, @@ -46,13 +46,9 @@ class StructMember : public Symbol * @param[in] name Given name. * @param[in] dataType Given data type. */ - StructMember(const std::string &name, DataType *dataType) - : Symbol(kStructMemberSymbol, name) - , m_dataType(dataType) - , m_paramDirection() - , m_containList() - , m_containString() - , m_byref(false) + StructMember(const std::string &name, DataType *dataType) : + Symbol(symbol_type_t::kStructMemberSymbol, name), m_dataType(dataType), m_paramDirection(), m_containList(), + m_containString(), m_byref(false) { } @@ -64,13 +60,9 @@ class StructMember : public Symbol * @param[in] tok Given token. * @param[in] dataType Given data type. */ - StructMember(const Token &tok, DataType *dataType) - : Symbol(kStructMemberSymbol, tok) - , m_dataType(dataType) - , m_paramDirection() - , m_containList() - , m_containString() - , m_byref(false) + StructMember(const Token &tok, DataType *dataType) : + Symbol(symbol_type_t::kStructMemberSymbol, tok), m_dataType(dataType), m_paramDirection(), m_containList(), + m_containString(), m_byref(false) { } @@ -111,7 +103,7 @@ class StructMember : public Symbol * * @param[in] paramDirection Define direction type for parameter in functions. */ - void setDirection(_param_direction paramDirection) { m_paramDirection = paramDirection; } + void setDirection(param_direction_t paramDirection) { m_paramDirection = paramDirection; } /*! * @brief This function returns routing for parameter. @@ -120,7 +112,7 @@ class StructMember : public Symbol * * @return Returns routing type for parameter in functions. */ - _param_direction getDirection() const { return m_paramDirection; } + param_direction_t getDirection() const { return m_paramDirection; } /*! * @brief This function set information about if member contains list data type. @@ -165,11 +157,11 @@ class StructMember : public Symbol void setByref(bool byref) { m_byref = byref; } protected: - DataType *m_dataType; /*!< Struct member data type. */ - _param_direction m_paramDirection; /*!< Direction in which is member used. */ - bool m_containList; /*!< True when member contains list type */ - bool m_containString; /*!< True when member contains string type */ - bool m_byref; /*!< True when member is byref type */ + DataType *m_dataType; /*!< Struct member data type. */ + param_direction_t m_paramDirection; /*!< Direction in which is member used. */ + bool m_containList; /*!< True when member contains list type */ + bool m_containString; /*!< True when member contains string type */ + bool m_byref; /*!< True when member is byref type */ }; } // namespace erpcgen diff --git a/erpcgen/src/types/StructType.hpp b/erpcgen/src/types/StructType.hpp index 76b8d36e..d02d3caf 100644 --- a/erpcgen/src/types/StructType.hpp +++ b/erpcgen/src/types/StructType.hpp @@ -38,10 +38,7 @@ class StructType : public DataType * * @param[in] name Given name. */ - explicit StructType(const std::string &name) - : DataType(name, kStructType) - { - } + explicit StructType(const std::string &name) : DataType(name, data_type_t::kStructType) {} /*! * @brief Constructor. @@ -50,10 +47,7 @@ class StructType : public DataType * * @param[in] tok Given token. */ - explicit StructType(const Token &tok) - : DataType(tok, kStructType) - { - } + explicit StructType(const Token &tok) : DataType(tok, data_type_t::kStructType) {} /*! * @brief This function will add struct member to the struct. diff --git a/erpcgen/src/types/Symbol.hpp b/erpcgen/src/types/Symbol.hpp index 6f854713..666a4b3b 100644 --- a/erpcgen/src/types/Symbol.hpp +++ b/erpcgen/src/types/Symbol.hpp @@ -31,7 +31,7 @@ class Symbol /*! * @brief Supported symbol types. */ - enum symbol_type_t + enum class symbol_type_t { kConstSymbol, kEnumMemberSymbol, @@ -50,13 +50,8 @@ class Symbol * * @param[in] symType Enum symbol type. */ - explicit Symbol(symbol_type_t symType) - : m_symbolType(symType) - , m_name() - , m_location() - , m_annotations() - , m_mlComment("") - , m_ilComment("") + explicit Symbol(symbol_type_t symType) : + m_symbolType(symType), m_name(), m_location(), m_annotations(), m_mlComment(""), m_ilComment("") { } @@ -68,13 +63,8 @@ class Symbol * @param[in] symType Enum symbol type. * @param[in] name Name for symbol. */ - Symbol(symbol_type_t symType, const std::string &name) - : m_symbolType(symType) - , m_name(name) - , m_location() - , m_annotations() - , m_mlComment("") - , m_ilComment("") + Symbol(symbol_type_t symType, const std::string &name) : + m_symbolType(symType), m_name(name), m_location(), m_annotations(), m_mlComment(""), m_ilComment("") { } @@ -86,13 +76,9 @@ class Symbol * @param[in] symType Enum symbol type. * @param[in] tok Token for symbol, which contains name and location. */ - Symbol(symbol_type_t symType, const Token &tok) - : m_symbolType(symType) - , m_name(tok.getStringValue()) - , m_location(tok.getLocation()) - , m_annotations() - , m_mlComment("") - , m_ilComment("") + Symbol(symbol_type_t symType, const Token &tok) : + m_symbolType(symType), m_name(tok.getStringValue()), m_location(tok.getLocation()), m_annotations(), + m_mlComment(""), m_ilComment("") { } @@ -128,7 +114,7 @@ class Symbol * @retval true When symbol is ConstSymbol. * @retval false When symbol isn't ConstSymbol. */ - bool isConstSymbol() const { return (m_symbolType == kConstSymbol); } + bool isConstSymbol() const { return (m_symbolType == symbol_type_t::kConstSymbol); } /*! * @brief This function is testing symbol type. @@ -136,7 +122,7 @@ class Symbol * @retval true When symbol is EnumMemberSymbol. * @retval false When symbol isn't EnumMemberSymbol. */ - bool isEnumMemberSymbol() const { return (m_symbolType == kEnumMemberSymbol); } + bool isEnumMemberSymbol() const { return (m_symbolType == symbol_type_t::kEnumMemberSymbol); } /*! * @brief This function is testing symbol type. @@ -144,7 +130,7 @@ class Symbol * @retval true When symbol is FunctionSymbol. * @retval false When symbol isn't FunctionSymbol. */ - bool isFunctionSymbol() const { return (m_symbolType == kFunctionSymbol); } + bool isFunctionSymbol() const { return (m_symbolType == symbol_type_t::kFunctionSymbol); } /*! * @brief This function is testing symbol type. @@ -152,7 +138,7 @@ class Symbol * @retval true When symbol is InterfaceSymbol. * @retval false When symbol isn't InterfaceSymbol. */ - bool isInterfaceSymbol() const { return (m_symbolType == kInterfaceSymbol); } + bool isInterfaceSymbol() const { return (m_symbolType == symbol_type_t::kInterfaceSymbol); } /*! * @brief This function is testing symbol type. @@ -160,7 +146,7 @@ class Symbol * @retval true When symbol is ProgramSymbol. * @retval false When symbol isn't ProgramSymbol. */ - bool isProgramSymbol() const { return (m_symbolType == kProgramSymbol); } + bool isProgramSymbol() const { return (m_symbolType == symbol_type_t::kProgramSymbol); } /*! * @brief This function is testing symbol type. @@ -168,7 +154,7 @@ class Symbol * @retval true When symbol is StructMemberSymbol. * @retval false When symbol isn't StructMemberSymbol. */ - bool isStructMemberSymbol() const { return (m_symbolType == kStructMemberSymbol); } + bool isStructMemberSymbol() const { return (m_symbolType == symbol_type_t::kStructMemberSymbol); } /*! * @brief This function is testing symbol type. @@ -176,7 +162,7 @@ class Symbol * @retval true When symbol is TypenameSymbol. * @retval false When symbol isn't TypenameSymbol. */ - bool isDatatypeSymbol() const { return (m_symbolType == kTypenameSymbol); } + bool isDatatypeSymbol() const { return (m_symbolType == symbol_type_t::kTypenameSymbol); } /*! * @brief This function is testing symbol type. @@ -184,7 +170,7 @@ class Symbol * @retval true When symbol is UnionCaseMemberSymbol. * @retval false When symbol isn't UnionCaseMemberSymbol. */ - bool isUnionCaseSymbol() const { return (m_symbolType == kUnionCaseMemberSymbol); } + bool isUnionCaseSymbol() const { return (m_symbolType == symbol_type_t::kUnionCaseMemberSymbol); } /*! * @brief This function returns location for symbol. diff --git a/erpcgen/src/types/SymbolScope.hpp b/erpcgen/src/types/SymbolScope.hpp index 93b3a145..617d1985 100644 --- a/erpcgen/src/types/SymbolScope.hpp +++ b/erpcgen/src/types/SymbolScope.hpp @@ -69,12 +69,7 @@ class SymbolScope /*! * @brief Constructor. */ - SymbolScope() - : m_symbolMap() - , m_symbolVector() - , m_parent(nullptr) - { - } + SymbolScope() : m_symbolMap(), m_symbolVector(), m_parent(nullptr) {} /*! * @brief Destructor. diff --git a/erpcgen/src/types/Type.cpp b/erpcgen/src/types/Type.cpp index cceb07f7..78ba49f7 100644 --- a/erpcgen/src/types/Type.cpp +++ b/erpcgen/src/types/Type.cpp @@ -99,7 +99,7 @@ vector Symbol::getAnnotations(const string &name, Annotation::prog for (unsigned int i = 0; i < m_annotations.size(); ++i) { if (m_annotations[i].getName() == name && - (m_annotations[i].getLang() == lang || m_annotations[i].getLang() == Annotation::kAll)) + (m_annotations[i].getLang() == lang || m_annotations[i].getLang() == Annotation::program_lang_t::kAll)) { anList.push_back(&m_annotations[i]); } @@ -119,10 +119,8 @@ string Symbol::getAnnStringValue(const string &annName, Annotation::program_lang return (annVallue) ? annVallue->toString() : ""; } -SymbolScope::typed_iterator::typed_iterator(const vit &bv, const vit &ev, Symbol::symbol_type_t predicateType) -: m_vec(bv) -, m_endvec(ev) -, m_predicateType(predicateType) +SymbolScope::typed_iterator::typed_iterator(const vit &bv, const vit &ev, Symbol::symbol_type_t predicateType) : +m_vec(bv), m_endvec(ev), m_predicateType(predicateType) { // Advance to the first matching symbol. while (m_vec != m_endvec && (*m_vec)->getSymbolType() != m_predicateType) @@ -398,13 +396,13 @@ void Group::addInterface(Interface *iface) m_interfaces.push_back(iface); } -void Group::addDirToSymbolsMap(Symbol *symbol, _param_direction dir) +void Group::addDirToSymbolsMap(Symbol *symbol, param_direction_t dir) { Log::info("Adding direction %d for symbol \"%s\"\n", dir, symbol->getName().c_str()); auto it = m_symbolDirections.find(symbol); if (it == m_symbolDirections.end()) { - set<_param_direction> directions; + set directions; directions.insert(dir); m_symbolDirections[symbol] = directions; @@ -424,9 +422,9 @@ void Group::setTemplate(cpptempl::data_map groupTemplate) m_template = groupTemplate; } -const set<_param_direction> Group::getSymbolDirections(Symbol *symbol) const +const set Group::getSymbolDirections(Symbol *symbol) const { - set<_param_direction> directions; + set directions; auto it = m_symbolDirections.find(symbol); if (it != m_symbolDirections.end()) { @@ -477,12 +475,14 @@ DataType *DataType::getTrueContainerDataType() DataType *trueDataType = this->getTrueDataType(); switch (trueDataType->getDataType()) { - case DataType::kListType: { + case DataType::data_type_t::kListType: + { ListType *l = dynamic_cast(trueDataType); assert(l); return l->getElementType()->getTrueContainerDataType(); } - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { ArrayType *a = dynamic_cast(trueDataType); assert(a); return a->getElementType()->getTrueContainerDataType(); @@ -514,6 +514,14 @@ void Interface::addFunction(Function *func) m_functions.push_back(func); } +void Interface::addFunctionType(FunctionType *func) +{ + assert(func); + + m_scope.addSymbol(func); + m_functionTypes.push_back(func); +} + string Interface::getDescription() const { string fns; diff --git a/erpcgen/src/types/UnionCase.hpp b/erpcgen/src/types/UnionCase.hpp index dd924c8b..ea5c010a 100644 --- a/erpcgen/src/types/UnionCase.hpp +++ b/erpcgen/src/types/UnionCase.hpp @@ -35,11 +35,9 @@ class UnionCase : public Symbol * @param[in] caseName Given case name. * @param[in] caseValue Given case value. */ - UnionCase(const std::string &caseName, int32_t caseValue) - : Symbol(kUnionCaseMemberSymbol, caseName) - , m_caseName(caseName) - , m_caseValue(caseValue) - , m_containingUnion(nullptr) + UnionCase(const std::string &caseName, int32_t caseValue) : + Symbol(symbol_type_t::kUnionCaseMemberSymbol, caseName), m_caseName(caseName), m_caseValue(caseValue), + m_containingUnion(nullptr) { } @@ -51,11 +49,8 @@ class UnionCase : public Symbol * * @param[in] caseValue Given case value. */ - explicit UnionCase(int32_t caseValue) - : Symbol(kUnionCaseMemberSymbol) - , m_caseName("") - , m_caseValue(caseValue) - , m_containingUnion(nullptr) + explicit UnionCase(int32_t caseValue) : + Symbol(symbol_type_t::kUnionCaseMemberSymbol), m_caseName(""), m_caseValue(caseValue), m_containingUnion(nullptr) { } @@ -67,11 +62,8 @@ class UnionCase : public Symbol * * @param[in] caseName Given case name. */ - explicit UnionCase(const std::string &caseName) - : Symbol(kUnionCaseMemberSymbol) - , m_caseName(caseName) - , m_caseValue(-1) - , m_containingUnion(nullptr) + explicit UnionCase(const std::string &caseName) : + Symbol(symbol_type_t::kUnionCaseMemberSymbol), m_caseName(caseName), m_caseValue(-1), m_containingUnion(nullptr) { } diff --git a/erpcgen/src/types/UnionType.hpp b/erpcgen/src/types/UnionType.hpp index e04d99de..20950b75 100644 --- a/erpcgen/src/types/UnionType.hpp +++ b/erpcgen/src/types/UnionType.hpp @@ -39,11 +39,9 @@ class UnionType : public DataType * @param[in] name Given name. * @param[in] discriminatorName Discriminator name. */ - UnionType(const std::string &name, const std::string &discriminatorName) - : DataType(name, kUnionType) - , m_discriminator(discriminatorName) - , m_members("(union)") - , m_parentStruct(nullptr) + UnionType(const std::string &name, const std::string &discriminatorName) : + DataType(name, data_type_t::kUnionType), m_discriminator(discriminatorName), m_members("(union)"), + m_parentStruct(nullptr) { } @@ -56,11 +54,9 @@ class UnionType : public DataType * @param[in] tok Given token.. * @param[in] discriminatorName Discriminator name. */ - UnionType(const Token &tok, const std::string &discriminatorName) - : DataType(tok, kUnionType) - , m_discriminator(discriminatorName) - , m_members("(union)") - , m_parentStruct(nullptr) + UnionType(const Token &tok, const std::string &discriminatorName) : + DataType(tok, data_type_t::kUnionType), m_discriminator(discriminatorName), m_members("(union)"), + m_parentStruct(nullptr) { } diff --git a/erpcgen/src/types/VoidType.hpp b/erpcgen/src/types/VoidType.hpp index 2ab9e5c6..2621dd92 100644 --- a/erpcgen/src/types/VoidType.hpp +++ b/erpcgen/src/types/VoidType.hpp @@ -31,10 +31,7 @@ class VoidType : public DataType * * This function set name to "(void)". */ - VoidType() - : DataType("(void)", kVoidType) - { - } + VoidType() : DataType("(void)", data_type_t::kVoidType) {} /*! * @brief This function returns description about the void. diff --git a/erpcgen/test/conftest.py b/erpcgen/test/conftest.py index 324dd9bf..759c3157 100644 --- a/erpcgen/test/conftest.py +++ b/erpcgen/test/conftest.py @@ -284,8 +284,8 @@ def _run(cwd, captureOutput, pytestConfig, args, compilerType): # Enable all warnings except for unused functions. defaultArgs = ["-c", "-Wall", "-Werror", "-Wno-unused-function"] defaultArgs += self._args - argsCC = [self._pathCC, "-std=gnu11"] + defaultArgs - argsCXX = [self._pathCXX, "-std=gnu++11"] + defaultArgs + argsCC = [self._pathCC, "-std=gnu17"] + defaultArgs + argsCXX = [self._pathCXX, "-std=gnu++17"] + defaultArgs incl = [] for i in self._includes: @@ -294,15 +294,24 @@ def _run(cwd, captureOutput, pytestConfig, args, compilerType): argsCXX += incl argsCC += incl + hasCSource = False + hasCppSource = False for s in self._sources: if str(s).split(".")[-1] == "cpp": argsCXX.append(str(s)) + hasCppSource = True else: argsCC.append(str(s)) + hasCSource = True - output = [_run(self._cwd, captureOutput, pytestConfig, argsCC, "C")] - output.append(_run(self._cwd, captureOutput, - pytestConfig, argsCXX, "CXX")) + output = [] + + if hasCSource: + output.append(_run(self._cwd, captureOutput, + pytestConfig, argsCC, "C")) + if hasCppSource: + output.append(_run(self._cwd, captureOutput, + pytestConfig, argsCXX, "CXX")) return output @@ -481,29 +490,58 @@ def run(self): pass -class ErpcgenCCompileTest(ErpcgenCompileTest): - # @brief Tests that generated C code will compile successfully. - # - # An objects directory is created under the test case directory. It is used to hold the - # .o files written by the compiler. A .c file with the main() function is also written to - # the objects directory. +class ErpcgenCCppCompileTest(ErpcgenCompileTest): + # @brief Compile with C and CPP main. + def __init__(self, spec: ErpcgenTestSpec, name: str, caseDir: str, outDir: str): + super(ErpcgenCCppCompileTest, self).__init__( + spec, name, caseDir, outDir) + self._caseDir = caseDir + self._out_dir = outDir + + def run(self): + ErpcgenCCompileTest(self._caseDir, self._out_dir).run() + ErpcgenCppCompileTest(self._caseDir, self._out_dir).run() + + +class ErpcgenCCppCompileTestCommon(object): MAIN_CODE = textwrap.dedent(""" int main(void) { return 0; } """) - def __init__(self, spec: ErpcgenTestSpec, name: str, caseDir: str, outDir: str): - super(ErpcgenCCompileTest, self).__init__(spec, name, caseDir, outDir) - self._objs_dir = caseDir.mkdir(OBJECTS_DIR_NAME) - self._compiler = CCompiler(self._objs_dir) + def __init__(self, outDir: str): + self._out_dir = outDir + self._objs_dir = None + self._compiler = None + + def getMainSourceCode(self): + raise ErpcgenTestException( + "Missing implementation for getting main source code") + + def getMainFilename(self): + raise ErpcgenTestException( + "Missing implementation for getting main filename") + + def getObjectsDir(self): + raise ErpcgenTestException( + "Missing implementation for getting objects dir") + + def getCompiler(self): + raise ErpcgenTestException( + "Missing implementation for getting compiler") + def run(self): # TODO run compiler tests on Windows if sys.platform == 'win32': return + self._compiler = self.getCompiler() + + self._objs_dir = self.getObjectsDir() + # Add include directories. self._compiler.add_include(erpc_dir.join("erpc_c", "port")) self._compiler.add_include(erpc_dir.join("erpc_c", "config")) @@ -515,21 +553,70 @@ def run(self): if '.cpp' in file: self._compiler.add_source(self._out_dir.join(file)) - # Add all header includes into main code - headers = ['#include "'+f + - '"' for f in os.listdir(str(self._out_dir)) if '.h' in f] - self.MAIN_CODE = '\n'.join(headers) + self.MAIN_CODE - - # Add both .c and .cpp copies of the main file. - for main_filename in ("main_c.c", "main_cxx.cpp"): - main = self._objs_dir.join(main_filename) - main.write(self.MAIN_CODE) - self._compiler.add_source(main) + mainCode = self.getMainSourceCode() + mainFilename = self.getMainFilename() + main = self._objs_dir.join(mainFilename) + main.write(mainCode) + self._compiler.add_source(main) # Run the compiler. self._compiler.run() +class ErpcgenCCompileTest(ErpcgenCCppCompileTestCommon): + # @brief Tests that generated C code will compile successfully. + # + # An objects directory is created under the test case directory. It is used to hold the + # .o files written by the compiler. A .c file with the main() function is also written to + # the objects directory. + + def __init__(self, caseDir: str, outDir: str): + super(ErpcgenCCompileTest, self).__init__(outDir) + self._objs_dir = caseDir.mkdir(OBJECTS_DIR_NAME + "_c") + self._compiler = CCompiler(self._objs_dir) + + def getMainSourceCode(self): + headers = ['#include "'+f + + '"' for f in os.listdir(str(self._out_dir)) if f[-2:] == '.h'] + return '\n'.join(headers) + self.MAIN_CODE + + def getMainFilename(self): + return "main.c" + + def getObjectsDir(self): + return self._objs_dir + + def getCompiler(self): + return self._compiler + + +class ErpcgenCppCompileTest(ErpcgenCCppCompileTestCommon): + # @brief Tests that generated Cpp code will compile successfully. + # + # An objects directory is created under the test case directory. It is used to hold the + # .o files written by the compiler. A .cpp file with the main() function is also written to + # the objects directory. + + def __init__(self, caseDir: str, outDir: str): + super(ErpcgenCppCompileTest, self).__init__(outDir) + self._objs_dir = caseDir.mkdir(OBJECTS_DIR_NAME + "_cpp") + self._compiler = CCompiler(self._objs_dir) + + def getMainSourceCode(self): + headers = ['#include "'+f + + '"' for f in os.listdir(str(self._out_dir)) if f[-4:] == '.hpp'] + return '\n'.join(headers) + self.MAIN_CODE + + def getMainFilename(self): + return "main.cpp" + + def getObjectsDir(self): + return self._objs_dir + + def getCompiler(self): + return self._compiler + + class ErpcgenPythonCompileTest(ErpcgenCompileTest): # @brief Tests that generated Python code can be successfully compiled. # @@ -572,7 +659,7 @@ class ErpcgenTestCase(object): # Map of language names to compilation test classes. COMPILE_TEST_CLASSES = { - 'c': ErpcgenCCompileTest, + 'c': ErpcgenCCppCompileTest, 'py': ErpcgenPythonCompileTest, } diff --git a/erpcgen/test/test_builtin_types.yml b/erpcgen/test/test_builtin_types.yml index a1abf140..5b53c484 100644 --- a/erpcgen/test/test_builtin_types.yml +++ b/erpcgen/test/test_builtin_types.yml @@ -21,7 +21,7 @@ idl: | interface myintf { {fns[fore]} somefunc({type} i) {fns[after]} } -test.h: +c_test_client.h: - if: not type in ('bool', 'float', 'double') then: - void somefunc({type}_t i); @@ -46,7 +46,7 @@ idl: | interface myintf { somefunc() -> {type} } -test.h: +c_test_client.h: - if: not type in ('bool', 'float', 'double') then: - '{type}_t somefunc(void);' @@ -71,7 +71,7 @@ idl: | struct structwithint { {type} i } -test.h: +test_common.h: - 'struct structwithint {' - if: not type in ('bool', 'float', 'double') then: diff --git a/erpcgen/test/test_comments.yml b/erpcgen/test/test_comments.yml index 0db04396..ea322664 100644 --- a/erpcgen/test/test_comments.yml +++ b/erpcgen/test/test_comments.yml @@ -73,7 +73,7 @@ idl: | sendReceiveStruct(A a) -> A ///< 33 comment; } /*!<30 comment */ -test.h: +test_common.h: - "/*" - not: "!" - "* Comment" @@ -127,6 +127,8 @@ test.h: - //! 10 comment - //!11 comment - //!< 12 comment + +c_test_client.h: - /*! @brief DoxygenComments identifiers */ - //! 28 comment - //!29 comment @@ -136,7 +138,7 @@ test.h: - ///< 33 comment; - - //@} /*!<30 comment */ - - // _test_h_ + - // _c_test_client_h_ test_client.cpp: - "/*" @@ -158,7 +160,7 @@ test_client.cpp: - // DoxygenComments interface sendReceiveList function client shim. - // DoxygenComments interface sendReceiveStruct function client shim. -test_server.h: +test_server.hpp: - "/*" - not: "!" - "* Comment" @@ -173,7 +175,7 @@ test_server.h: - "*/" - /*! @brief Call the correct server shim based on method unique ID. */ - /*! @brief Server shim for sendReceiveList of DoxygenComments interface. */ - - // _test_server_h_ + - // _test_server_hpp_ test_server.cpp: - "/*" diff --git a/erpcgen/test/test_enum.yml b/erpcgen/test/test_enum.yml index a0a294ea..76e6611b 100644 --- a/erpcgen/test/test_enum.yml +++ b/erpcgen/test/test_enum.yml @@ -11,7 +11,7 @@ idl: | B, C } -test.h: +test_common.h: # named enums get a typedef - if: name then: @@ -38,7 +38,7 @@ idl: | B, C } -test.h: +test_common.h: # named enums get a typedef - if: name then: @@ -68,7 +68,7 @@ idl: | B = 30, C = {c_val} } -test.h: +test_common.h: # named enums get a typedef - if: name then: @@ -99,7 +99,7 @@ idl: | enum {name} { A{a_val}{opt_comma} } -test.h: +test_common.h: # named enums get a typedef - if: name then: @@ -123,7 +123,7 @@ idl: | A = 0, B = -1 } -test.h: +test_common.h: # named enums get a typedef - if: name then: @@ -148,7 +148,7 @@ idl: | D= 1*five, E = 2*five, } -test.h: +test_common.h: # named enums get a typedef - A = 0 - B = 5 diff --git a/erpcgen/test/test_error_checks_c.yml b/erpcgen/test/test_error_checks_c.yml index ad1c0d66..28e751bd 100644 --- a/erpcgen/test/test_error_checks_c.yml +++ b/erpcgen/test/test_error_checks_c.yml @@ -25,9 +25,9 @@ test_client.cpp: - if (codec == NULL) - err = kErpcStatus_MemoryError; - codec->startWriteMessage - - g_client->performRequest + - m_clientManager->performRequest - err = codec->getStatus(); - - g_client->callErrorHandler(err, + - m_clientManager->callErrorHandler(err, - if: type[1] != 'NULL' then: - if (err != kErpcStatus_Success) @@ -115,9 +115,9 @@ test_client.cpp: - not: if (result == NULL) - not: codec->updateStatus; - codec->startWriteMessage - - g_client->performRequest + - m_clientManager->performRequest - err = codec->getStatus(); - - g_client->callErrorHandler(err, kErrorTest_f_id) + - m_clientManager->callErrorHandler(err, m_fId) - if: type[1] != 'NULL' then: - if (err != kErpcStatus_Success) @@ -164,9 +164,9 @@ test_client.cpp: - if (codec == NULL) - err = kErpcStatus_MemoryError; - codec->startWriteMessage - - g_client->performRequest + - m_clientManager->performRequest - err = codec->getStatus(); - - g_client->callErrorHandler(err, + - m_clientManager->callErrorHandler(err, - if: type[1] != 'NULL' then: - if (err != kErpcStatus_Success) @@ -214,7 +214,7 @@ test_client.cpp: - if (codec == NULL) - err = kErpcStatus_MemoryError; - codec->startWriteMessage - - g_client->performRequest + - m_clientManager->performRequest - err = codec->getStatus(); test_server.cpp: @@ -261,9 +261,9 @@ test_client.cpp: - not: if (codec == NULL) - not: err = kErpcStatus_MemoryError; - codec->startWriteMessage - - g_client->performRequest + - m_clientManager->performRequest - err = codec->getStatus(); - - g_client->callErrorHandler(err, + - m_clientManager->callErrorHandler(err, test_server.cpp: - erpc_status_t err = kErpcStatus_Success; @@ -312,10 +312,10 @@ test_client.cpp: - err = kErpcStatus_MemoryError; - else - codec->startWriteMessage - - g_client->performRequest(request); + - m_clientManager->performRequest(request); - err = codec->getStatus(); - - g_client->releaseRequest(request); - - g_client->callErrorHandler(err, kErrorTest_f_id); + - m_clientManager->releaseRequest(request); + - m_clientManager->callErrorHandler(err, m_fId); test_server.cpp: - erpc_status_t err = kErpcStatus_Success; diff --git a/erpcgen/test/test_error_return_c.yml b/erpcgen/test/test_error_return_c.yml index 73ba7041..8c2571c3 100644 --- a/erpcgen/test/test_error_return_c.yml +++ b/erpcgen/test/test_error_return_c.yml @@ -28,7 +28,7 @@ idl: | f() -> {type[0]} } test_client.cpp: - - g_client->releaseRequest(request); + - m_clientManager->releaseRequest(request); - if: type[1] != 'NULL' then: - if (err != kErpcStatus_Success) @@ -71,7 +71,7 @@ idl: | f() -> {type[0]} } test_client.cpp: - - g_client->releaseRequest(request); + - m_clientManager->releaseRequest(request); - if: type[0] != 'A' and type[0] != 'string' then: - if (err != kErpcStatus_Success) diff --git a/erpcgen/test/test_expressions.yml b/erpcgen/test/test_expressions.yml index 6b3f5dcf..1d3ee2f6 100644 --- a/erpcgen/test/test_expressions.yml +++ b/erpcgen/test/test_expressions.yml @@ -15,7 +15,7 @@ idl: | const int32 a = 2 const int32 b = a * two + three -1 -test.h: +test_common.h: # named enums get a typedef - if: name then: diff --git a/erpcgen/test/test_extern_c.yml b/erpcgen/test/test_extern_c.yml index 6e778483..0b9d9575 100644 --- a/erpcgen/test/test_extern_c.yml +++ b/erpcgen/test/test_extern_c.yml @@ -2,7 +2,7 @@ name: extern c empty desc: do the extern "C" blocks get produced for empty input idl: "" -test.h: +test_common.h: - | #if defined(__cplusplus) extern "C" { @@ -19,7 +19,7 @@ idl: | interface Foo { foofn() -> void } -test.h: +test_common.h: - | #if defined(__cplusplus) extern "C" { diff --git a/erpcgen/test/test_forward_declaration_c.yml b/erpcgen/test/test_forward_declaration_c.yml index c39f0594..79b01021 100644 --- a/erpcgen/test/test_forward_declaration_c.yml +++ b/erpcgen/test/test_forward_declaration_c.yml @@ -1,42 +1,3 @@ ---- -name: struct before function -desc: forward declaration of structure before function which is using type. -params: - dir: - - "in" - - "out" -idl: - struct forwardStruct; - - oneway forwardCallback_t(forwardStruct s); - - struct forwardStruct - { - forwardCallback_t pCallback; /*!< Pointer to callback function */ - } - - interface foo - { - myFun({dir} forwardCallback_t pCallback1_t) -> void - - forwardCallback_t forwardCallback; - } - -test.h: - - typedef struct forwardStruct forwardStruct; - - typedef void (*forwardCallback_t)(const forwardStruct * s); - - - struct forwardStruct - - "{" - - forwardCallback_t pCallback; - - "};" -test_server.cpp: - - if: dir == 'in' - then: - - not: erpc_free(pCallback1_t); - else: - - erpc_free(pCallback1_t); - --- name: struct before struct desc: forward declaration of structure before structure which is using type. @@ -58,7 +19,7 @@ idl: myFun(in forwardStruct s) -> void } -test.h: +test_common.h: - typedef struct struct2 struct2; - typedef struct forwardStruct forwardStruct; @@ -102,7 +63,7 @@ idl: | { myFun(in forwardUnion u @discriminator(discriminator), unionCases discriminator) -> void } -test.h: +test_common.h: - typedef struct structure structure; - typedef union forwardUnion forwardUnion; diff --git a/erpcgen/test/test_import.yml b/erpcgen/test/test_import.yml index 03c4095c..ab41d3b9 100644 --- a/erpcgen/test/test_import.yml +++ b/erpcgen/test/test_import.yml @@ -4,10 +4,16 @@ desc: C/Py import test is the same. idl: | import "imports/test2.erpc" -test.h: +c_test_client.h: - void hello1(int32_t a); - void hello2(int32_t a); - void hello3(int32_t a); - void hello4(int32_t a); - void hello5(int32_t a); +c_test_server.h: + - void hello1(int32_t a); + - void hello2(int32_t a); + - void hello3(int32_t a); + - void hello4(int32_t a); + - void hello5(int32_t a); diff --git a/erpcgen/test/test_include.yml b/erpcgen/test/test_include.yml index c1d886b4..8bc3ece5 100644 --- a/erpcgen/test/test_include.yml +++ b/erpcgen/test/test_include.yml @@ -21,24 +21,5 @@ idl: | interface foo { bar(in string x) -> void } -test.h: +test_common.h: - '#include "stdio.h"' ---- -name: C include two interfaces -desc: -idl: | - program test; - - @include("stdio.h") - @include("stdio.h") - interface fooA { - barA(in string xA) -> void - } - - @include("stdio.h") - interface fooB { - barB(in string xB) -> void - } -test_server.cpp: - - '#include "stdio.h"' - - not: '#include "stdio.h"' \ No newline at end of file diff --git a/erpcgen/test/test_includes/test_includes_union.h b/erpcgen/test/test_includes/test_includes_union.h index 97cef1a0..01e78bea 100644 --- a/erpcgen/test/test_includes/test_includes_union.h +++ b/erpcgen/test/test_includes/test_includes_union.h @@ -6,10 +6,15 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include +#ifndef TEST_INCLUDES_UNION +#define TEST_INCLUDES_UNION + +#include typedef union unionType { int32_t x; float y; }unionType; + +#endif diff --git a/erpcgen/test/test_name_c.yml b/erpcgen/test/test_name_c.yml index 0354379c..4d4196bb 100644 --- a/erpcgen/test/test_name_c.yml +++ b/erpcgen/test/test_name_c.yml @@ -31,22 +31,27 @@ idl: | oneway functionName2(S a @name(m)) } -test.h: +test_common.h: - enum EnumName - D - struct StructName StructName - StructName type - struct StructName - int32_t d + +c_test_client.h: - function(const StructName * m) test_client.cpp: - write_StructName_struct - write_StructName_struct - data->d - - void function(const StructName * m) + - void I_client::function(const StructName * m) - write_StructName_struct(codec, m) - - void functionName2(const StructName * m) + - void I_client::functionName2(const StructName * m) + +c_test_server.h: + - function(const StructName * m) test_server.cpp: - read_StructName_struct @@ -58,5 +63,7 @@ test_server.cpp: - function(m); - erpc_free(m); - functionName2(m); + +c_test_server.cpp: + - ERPC_MANUALLY_CONSTRUCTED_STATIC(I_service, s_I_service); - create_I_service - - s_I_service diff --git a/erpcgen/test/test_nullable_c.yml b/erpcgen/test/test_nullable_c.yml index c60c69cc..1ee80060 100644 --- a/erpcgen/test/test_nullable_c.yml +++ b/erpcgen/test/test_nullable_c.yml @@ -11,7 +11,7 @@ idl: | bar({dir} string a @nullable @max_length(8)) -> void } test_client.cpp: - - re: void bar\(\w*\s*char \* a\) + - re: void foo_client::bar\(\w*\s*char \* a\) - if (a == NULL) - codec->writeNullFlag(true) - if: dir in ('in', 'inout') @@ -58,7 +58,7 @@ idl: | bar({dir} ustring a @nullable @max_length(8)) -> void } test_client.cpp: - - re: void bar\(\w*\s*unsigned\s*char\s*\* a\) + - re: void foo_client::bar\(\w*\s*unsigned\s*char\s*\* a\) - if (a == NULL) - codec->writeNullFlag(true) - if: dir in ('in', 'inout') @@ -113,11 +113,12 @@ idl: | interface foo { bar(Vector v @nullable) -> void } -test.h: +test_common.h: - '{type[1]} v[3]' +c_test_client.h: - void bar(const Vector * v); test_client.cpp: - - re: void bar\(const Vector \* v\) + - re: void foo_client::bar\(const Vector \* v\) - if (v == NULL) - writeNullFlag(true) - "{" @@ -152,7 +153,7 @@ test_client.cpp: - writeNullFlag(false) - write_list_bool_1_t_struct - '}' - - void bar(const erpc_pair * s) + - void foo_client::bar(const erpc_pair * s) - write_erpc_pair_struct test_server.cpp: - void read_erpc_pair_struct @@ -182,7 +183,7 @@ test_client.cpp: - writeNullFlag(false) - write_binary_t_struct - '}' - - void bar(const erpc_pair * s) + - void foo_client::bar(const erpc_pair * s) - write_erpc_pair_struct test_server.cpp: - void read_erpc_pair_struct @@ -339,9 +340,9 @@ idl: | test_client.cpp: - if: dir == 'inout' then: - - void bar(const bool * l, uint32_t * c) + - void foo_client::bar(const bool * l, uint32_t * c) else: - - void bar(const bool * l, uint32_t c) + - void foo_client::bar(const bool * l, uint32_t c) - if: dir == 'inout' and ann == '@nullable' then: - if ((l == NULL) || (c == NULL)) @@ -404,7 +405,7 @@ idl: | } test_client.cpp: - - void bar(bool * l, uint32_t * c) + - void foo_client::bar(bool * l, uint32_t * c) - if: ann == '@nullable' then: - if ((l == NULL) || (c == NULL)) diff --git a/erpcgen/test/test_redundant_definitions.yml b/erpcgen/test/test_redundant_definitions.yml index ea947b13..230f77dd 100644 --- a/erpcgen/test/test_redundant_definitions.yml +++ b/erpcgen/test/test_redundant_definitions.yml @@ -40,7 +40,7 @@ idl: | interface foo { bar(in Vector vector_x, out Wector vector_y) -> void } -test.h: +test_common.h: - typedef struct Vector Vector - typedef struct Wector Wector - struct Vector @@ -50,7 +50,7 @@ test_server.cpp: - read_Vector_struct - not: read_Wector_struct - write_Wector_struct -test_client.cpp: +test_client.cpp: - write_Vector_struct - not: read_Vector_struct - read_Wector_struct @@ -124,44 +124,52 @@ idl: | interface fooA { barA(out Vector vector_x, in Wector vector_y) -> void } -test.h: +test_common.h: - typedef struct Vector Vector - typedef struct Wector Wector - typedef struct NoGroup NoGroup; - struct Vector - struct Wector - struct NoGroup +c_test_server.h: - enum _foo_ids - void bar(const NoGroup * noGroup_z) test_server.cpp: - read_NoGroup_struct - not: write_NoGroup_struct - - not: Vector_struct + - not: Vector_struct - not: Wector_struct - foo_service::bar_shim -test_client.cpp: +c_test_client.h: + - enum _foo_ids + - void bar(const NoGroup * noGroup_z) +test_client.cpp: - not: read_NoGroup_struct - write_NoGroup_struct - - not: Vector_struct + - not: Vector_struct - not: Wector_struct - bar(const NoGroup * noGroup_z) -test_A.h: +test_A_common.h: - typedef struct Vector Vector - typedef struct Wector Wector - typedef struct NoGroup NoGroup; - struct Vector - struct Wector - struct NoGroup +c_test_A_server.h: - enum _fooA_ids - void barA(Vector * vector_x, const Wector * vector_y) -test_A_server.cpp: +test_A_server.cpp: - read_Wector_struct - not: write_Wector_struct - write_Vector_struct - not: read_Vector_struct - not: NoGroup_struct - fooA_service::barA_shim -test_A_client.cpp: +c_test_A_client.h: + - enum _fooA_ids + - void barA(Vector * vector_x, const Wector * vector_y) +test_A_client.cpp: - write_Wector_struct - not: read_Wector_struct - read_Vector_struct @@ -200,14 +208,14 @@ idl: | interface foo_B { bar_B(out VectorB b) -> void } -test.h: +test_A_common.h: - typedef struct VectorA VectorA - typedef struct VectorB VectorB - struct VectorA - struct VectorB - not: bar_A(const VectorA * a) - not: bar_AA(const VectorA * aa, VectorB * bb) -test_A.h: +c_test_A_client.h: - not: typedef - bar_A(const VectorA * a) - bar_AA(const VectorA * aa, VectorB * bb) @@ -216,10 +224,10 @@ test_A_server.cpp: - write_VectorB_struct - not: write_VectorA_struct - not: read_VectorB_struct -test_B.h: +c_test_B_client.h: - not: typedef - bar_B(VectorB * b) -test_B_server.cpp: +test_B_server.cpp: - write_VectorB_struct - not: read_VectorB_struct - not: VectorA_struct @@ -235,4 +243,4 @@ test_B_server.cpp: # interface foo { # bar(zz discriminator, Scalar scalar_y @discriminator(discriminator)) -> void -# } \ No newline at end of file +# } diff --git a/erpcgen/test/test_scope_c.yml b/erpcgen/test/test_scope_c.yml index e9775256..b0d20a20 100644 --- a/erpcgen/test/test_scope_c.yml +++ b/erpcgen/test/test_scope_c.yml @@ -5,7 +5,7 @@ idl: | interface test { bar(int32 x) -> void } -test.h: +test_common.h: - | #if !defined(ERPC_TYPE_DEFINITIONS_ERPCSHIM) #define ERPC_TYPE_DEFINITIONS_ERPCSHIM @@ -21,7 +21,7 @@ idl: | interface test { bar(int32 x) -> void } -test.h: +test_common.h: - | #if !defined(ERPC_TYPE_DEFINITIONS_TEST) #define ERPC_TYPE_DEFINITIONS_TEST @@ -38,7 +38,7 @@ idl: | interface test { bar(int32 x) -> void } -test.h: +test_common.h: - | #if !defined(ERPC_TYPE_DEFINITIONS_MYSCOPE) #define ERPC_TYPE_DEFINITIONS_MYSCOPE @@ -55,7 +55,7 @@ idl: | interface test { bar(int32 x) -> void } -test.h: +test_common.h: - | #if !defined(ERPC_TYPE_DEFINITIONS) #define ERPC_TYPE_DEFINITIONS diff --git a/erpcgen/test/test_service_c.yml b/erpcgen/test/test_service_c.yml index 5865cfac..5446b86f 100644 --- a/erpcgen/test/test_service_c.yml +++ b/erpcgen/test/test_service_c.yml @@ -8,17 +8,18 @@ idl: | oneway f() } -test_server.h: +c_test_server.h: - erpc_service_t create_ErrorTest_service(void); - void destroy_ErrorTest_service(erpc_service_t service); -test_server.cpp: +c_test_server.cpp: - ERPC_MANUALLY_CONSTRUCTED_STATIC(ErrorTest_service, s_ErrorTest_service); + - ERPC_MANUALLY_CONSTRUCTED_STATIC(ErrorTest_server, s_ErrorTest_server); - erpc_service_t create_ErrorTest_service(void) - "{" - erpc_service_t service; - "#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC" - - service = new (nothrow) ErrorTest_service(); + - service = new (nothrow) ErrorTest_service(new (nothrow)ErrorTest_server()); - "#else" - if (s_ErrorTest_service.isUsed()) - "{" @@ -26,7 +27,8 @@ test_server.cpp: - "}" - else - "{" - - s_ErrorTest_service.construct(); + - s_ErrorTest_server.construct(); + - s_ErrorTest_service.construct(s_ErrorTest_server.get()); - service = s_ErrorTest_service.get(); - "}" - "#endif" @@ -35,11 +37,15 @@ test_server.cpp: - void destroy_ErrorTest_service(erpc_service_t service) - "{" - "#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC" - - erpc_assert(service != NULL); + - if (service) + - "{" + - delete (ErrorTest_server *)(((ErrorTest_service *)service)->getHandler()); - delete (ErrorTest_service *)service; + - "}" - "#else" - (void)service; - erpc_assert(service == s_ErrorTest_service.get()); - s_ErrorTest_service.destroy(); + - s_ErrorTest_server.destroy(); - "#endif" - "}" diff --git a/erpcgen/test/test_struct.yml b/erpcgen/test/test_struct.yml index afb5f5ce..b376b48f 100644 --- a/erpcgen/test/test_struct.yml +++ b/erpcgen/test/test_struct.yml @@ -20,7 +20,7 @@ idl: | interface B { testF(inout A b) ->void } -test.h: +test_common.h: - typedef struct A A; - struct A - if: type in ('bool', 'float', 'double') @@ -41,7 +41,7 @@ idl: | interface foo { bar(ListType x) -> ListType } -test.h: +test_common.h: - typedef struct list_int32_1_t list_int32_1_t; - typedef list_int32_1_t ListType; - struct list_int32_1_t @@ -52,7 +52,7 @@ test_client.cpp: - read_list_int32_1_t_struct - if(NULL == data) - return; - - ListType * bar(const ListType * x) + - ListType * foo_client::bar(const ListType * x) test_server.cpp: - read_list_int32_1_t_struct - if(NULL == data) @@ -72,7 +72,7 @@ idl: | interface foo { bar(Vector x, binary y) -> void } -test.h: +test_common.h: - typedef struct binary_t binary_t; - typedef struct Vector Vector; - struct binary_t @@ -97,7 +97,7 @@ idl: | foo(Vector a) -> void bar() -> Vector } -test.h: +test_common.h: - typedef struct binary_t binary_t; - typedef struct Vector Vector; - struct binary_t diff --git a/erpcgen/test/test_types_header.yml b/erpcgen/test/test_types_header.yml deleted file mode 100644 index 97b461b9..00000000 --- a/erpcgen/test/test_types_header.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: types header file -desc: places all type definitions into separate header file "test_types.h" -idl: | - @types_header("test_types.h") - program test - - struct Vector { - int8 a - int16 b - int32 c - } - - interface test { - bar(Vector x) -> void - } -test.h: - - '#include "test_types.h"' - - not: // Aliases data types declarations - - not: typedef struct Vector Vector; - - not: // Structures data types declarations - - not: struct Vector - - void bar(const Vector * x); -test_types.h: - - '#if !defined(_test_types_h_)' - - '#include ' - - '#include ' - - '#include ' - - // Aliases data types declarations - - typedef struct Vector Vector; - - // Structures/unions data types declarations - - struct Vector - - not: void bar(const Vector * x); diff --git a/erpcgen/test/test_union_c.yml b/erpcgen/test/test_union_c.yml index 2673fa9f..04b04e78 100644 --- a/erpcgen/test/test_union_c.yml +++ b/erpcgen/test/test_union_c.yml @@ -21,7 +21,7 @@ idl: | myUnion(fruitType discriminator, unionType unionVariable @discriminator(discriminator)) -> void } -test.h: +test_common.h: - not: typedef union unionType unionType; - not: union unionType - not: int32 x; @@ -72,7 +72,7 @@ idl: | myUnion(fruitType discriminator, unionType unionVariable @discriminator(discriminator)) -> void } -test.h: +test_common.h: - typedef union unionType unionType; - union unionType - "{" @@ -95,6 +95,8 @@ test.h: - int32_t blah; - "};" - "};" + +c_test_client.h: - void myUnion(fruitType discriminator, const unionType * unionVariable); test_client.cpp: @@ -146,10 +148,12 @@ test_client.cpp: - break; - "}" - "}" - - void myUnion(fruitType discriminator, const unionType * unionVariable) + - void foo_client::myUnion(fruitType discriminator, const unionType * unionVariable) - not: codec->read(static_cast(discriminator)); - write_unionType_union(codec, static_cast(discriminator), unionVariable) +c_test_server.h: + - void myUnion(fruitType discriminator, const unionType * unionVariable); test_server.cpp: - static void read_unionType_union(erpc::Codec * codec, int32_t & discriminator, unionType * data); @@ -268,15 +272,20 @@ idl: | myUnion(structType structVariable) -> void } -test.h: +test_common.h: - struct structType - fruitType discriminator - unionType unionVariable + +c_test_client.h: - void myUnion(const structType * structVariable); test_client.cpp: - write_unionType_union(codec, static_cast(data->discriminator), &data->unionVariable); +c_test_server.h: + - void myUnion(const structType * structVariable); + test_server.cpp: - int32_t _tmp_local_i32; - read_unionType_union(codec, _tmp_local_i32, &data->unionVariable); diff --git a/erpcsniffer/src/Sniffer.cpp b/erpcsniffer/src/Sniffer.cpp index 6f4f7834..fd363a92 100644 --- a/erpcsniffer/src/Sniffer.cpp +++ b/erpcsniffer/src/Sniffer.cpp @@ -17,9 +17,9 @@ #include #include #include +#include #include #include -#include using namespace erpcgen; using namespace erpcsniffer; @@ -64,7 +64,7 @@ erpc_status_t Sniffer::run() } Log::info("message received\n"); - m_codec->setBuffer(message); + m_codec->setBuffer(message, m_transport->reserveHeaderSize()); // Save time when message was received. time_t now = chrono::system_clock::to_time_t(currentTime); @@ -139,7 +139,7 @@ void Sniffer::openFile(ofstream &outputFileStream) erpc_status_t Sniffer::readNullFlag(StructMember *structMember, string &nullFlag) { - if (structMember && structMember->findAnnotation(NULLABLE_ANNOTATION, Annotation::kC) != nullptr) + if (structMember && structMember->findAnnotation(NULLABLE_ANNOTATION, Annotation::program_lang_t::kC) != nullptr) { bool nullF; m_codec->readNullFlag(nullF); @@ -154,7 +154,7 @@ erpc_status_t Sniffer::readNullFlag(StructMember *structMember, string &nullFlag erpc_status_t Sniffer::readSharedAddress(StructMember *structMember, string &address) { erpc_status_t err = kErpcStatus_Success; - if (structMember->findAnnotation(SHARED_ANNOTATION, Annotation::kC) != nullptr) + if (structMember->findAnnotation(SHARED_ANNOTATION, Annotation::program_lang_t::kC) != nullptr) { uintptr_t ptr; m_codec->readPtr(ptr); @@ -184,7 +184,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) erpc_status_t err; switch (dataType->getDataType()) { - case DataType::data_type_t::kAliasType: { + case DataType::data_type_t::kAliasType: + { AliasType *aliasType = dynamic_cast(dataType); assert(aliasType); string parseDataInfo; @@ -198,7 +199,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) addSpaces(parsedDataInfo, 2); break; } - case DataType::data_type_t::kArrayType: { + case DataType::data_type_t::kArrayType: + { ArrayType *arrayType = dynamic_cast(dataType); assert(arrayType); uint32_t arraySize = arrayType->getElementCount(); @@ -221,13 +223,15 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) } break; } - case DataType::data_type_t::kBuiltinType: { + case DataType::data_type_t::kBuiltinType: + { parsedDataInfo = " value: "; BuiltinType *builtinType = dynamic_cast(dataType); assert(builtinType); switch (builtinType->getBuiltinType()) { - case BuiltinType::_builtin_type::kBoolType: { + case BuiltinType::builtin_type_t::kBoolType: + { bool value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -237,7 +241,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "bool" + parsedDataInfo + ((value) ? "true" : "false"); break; } - case BuiltinType::_builtin_type::kInt8Type: { + case BuiltinType::builtin_type_t::kInt8Type: + { int8_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -247,7 +252,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "int8_t" + parsedDataInfo + format_string("%d", value); break; } - case BuiltinType::_builtin_type::kInt16Type: { + case BuiltinType::builtin_type_t::kInt16Type: + { int16_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -257,7 +263,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "int16_t" + parsedDataInfo + format_string("%d", value); break; } - case BuiltinType::_builtin_type::kInt32Type: { + case BuiltinType::builtin_type_t::kInt32Type: + { int32_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -267,7 +274,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "int32_t" + parsedDataInfo + format_string("%d", value); break; } - case BuiltinType::_builtin_type::kInt64Type: { + case BuiltinType::builtin_type_t::kInt64Type: + { int64_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -277,7 +285,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "int64_t" + parsedDataInfo + format_string("%ld", value); break; } - case BuiltinType::_builtin_type::kUInt8Type: { + case BuiltinType::builtin_type_t::kUInt8Type: + { uint8_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -287,7 +296,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "uint8_t" + parsedDataInfo + format_string("%u", value); break; } - case BuiltinType::_builtin_type::kUInt16Type: { + case BuiltinType::builtin_type_t::kUInt16Type: + { uint16_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -297,7 +307,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "uint16_t" + parsedDataInfo + format_string("%u", value); break; } - case BuiltinType::_builtin_type::kUInt32Type: { + case BuiltinType::builtin_type_t::kUInt32Type: + { uint32_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -307,7 +318,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "uint32_t" + parsedDataInfo + format_string("%u", value); break; } - case BuiltinType::_builtin_type::kUInt64Type: { + case BuiltinType::builtin_type_t::kUInt64Type: + { uint64_t value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -317,7 +329,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "uint64_t" + parsedDataInfo + format_string("%lu", value); break; } - case BuiltinType::_builtin_type::kFloatType: { + case BuiltinType::builtin_type_t::kFloatType: + { float value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -327,7 +340,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "float" + parsedDataInfo + format_string("%f", value); break; } - case BuiltinType::_builtin_type::kDoubleType: { + case BuiltinType::builtin_type_t::kDoubleType: + { double value; m_codec->read(value); if ((err = m_codec->getStatus())) @@ -337,7 +351,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "double" + parsedDataInfo + format_string("%f", value); break; } - case BuiltinType::_builtin_type::kStringType: { + case BuiltinType::builtin_type_t::kStringType: + { char *value; uint32_t length; m_codec->readString(length, &value); @@ -348,7 +363,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "string" + parsedDataInfo + format_string("%.*s", length, value); break; } - case BuiltinType::_builtin_type::kBinaryType: { + case BuiltinType::builtin_type_t::kBinaryType: + { uint8_t *value; uint32_t length; m_codec->readBinary(length, &value); @@ -364,13 +380,15 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = "binary" + parsedDataInfo + binaryValue; break; } - default: { + default: + { throw runtime_error("Unrecognized builtin type.\n"); } } break; } - case DataType::data_type_t::kEnumType: { + case DataType::data_type_t::kEnumType: + { EnumType *e = dynamic_cast(dataType); assert(e); uint32_t value; @@ -395,7 +413,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) parsedDataInfo = format_string("%s value: %s", e->getName().c_str(), enumMemberName.c_str()); break; } - case DataType::data_type_t::kFunctionType: { + case DataType::data_type_t::kFunctionType: + { FunctionType *f = dynamic_cast(dataType); assert(f); int32_t value; @@ -415,7 +434,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) } break; } - case DataType::data_type_t::kListType: { + case DataType::data_type_t::kListType: + { ListType *listType = dynamic_cast(dataType); assert(listType); uint32_t listSize; @@ -445,7 +465,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) } break; } - case DataType::data_type_t::kStructType: { + case DataType::data_type_t::kStructType: + { StructType *structType = dynamic_cast(dataType); assert(structType); parsedDataInfo = "struct " + structType->getName() + ":\n"; @@ -470,7 +491,8 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) addSpaces(parsedDataInfo, 2); break; } - case DataType::data_type_t::kUnionType: { + case DataType::data_type_t::kUnionType: + { UnionType *unionType = dynamic_cast(dataType); assert(unionType); int32_t discriminator; @@ -520,11 +542,13 @@ erpc_status_t Sniffer::parseDataType(DataType *dataType, string &parsedDataInfo) addSpaces(parsedDataInfo, 2); break; } - case DataType::data_type_t::kVoidType: { + case DataType::data_type_t::kVoidType: + { parsedDataInfo = "void"; break; } - default: { + default: + { throw runtime_error("Unrecognized data type.\n"); } } @@ -544,8 +568,8 @@ erpc_status_t Sniffer::parseMemberType(StructType *structType, StructMember *str { Annotation *ann; string referencedName; - if ((ann = referenced->findAnnotation(LENGTH_ANNOTATION, Annotation::kC)) || - (ann = referenced->findAnnotation(DISCRIMINATOR_ANNOTATION, Annotation::kC))) + if ((ann = referenced->findAnnotation(LENGTH_ANNOTATION, Annotation::program_lang_t::kC)) || + (ann = referenced->findAnnotation(DISCRIMINATOR_ANNOTATION, Annotation::program_lang_t::kC))) { if (Value *val = ann->getValueObject()) { @@ -568,8 +592,8 @@ erpc_status_t Sniffer::parseMemberType(StructType *structType, StructMember *str // check if reference is null-able Annotation *ann; - if ((ann = structMember->findAnnotation(LENGTH_ANNOTATION, Annotation::kC)) || - (ann = structMember->findAnnotation(DISCRIMINATOR_ANNOTATION, Annotation::kC))) + if ((ann = structMember->findAnnotation(LENGTH_ANNOTATION, Annotation::program_lang_t::kC)) || + (ann = structMember->findAnnotation(DISCRIMINATOR_ANNOTATION, Annotation::program_lang_t::kC))) { if (Value *val = ann->getValueObject()) { @@ -643,12 +667,14 @@ string Sniffer::getDataTypeName(DataType *dataType) { switch (dataType->getDataType()) { - case DataType::kListType: { + case DataType::data_type_t::kListType: + { ListType *listType = dynamic_cast(dataType); assert(listType); return "list<" + getDataTypeName(listType->getElementType()) + ">"; } - case DataType::kArrayType: { + case DataType::data_type_t::kArrayType: + { string returnVal; while (dataType->isArray()) { @@ -659,7 +685,8 @@ string Sniffer::getDataTypeName(DataType *dataType) } return getDataTypeName(dataType) + returnVal; } - case DataType::kVoidType: { + case DataType::data_type_t::kVoidType: + { return "void"; } default: @@ -667,7 +694,7 @@ string Sniffer::getDataTypeName(DataType *dataType) } } -string Sniffer::getPrototype(erpcgen::Function *function) +string Sniffer::getPrototype(Function *function) { string prototype = getDataTypeName(function->getReturnType()); if (function->isOneway()) @@ -705,7 +732,7 @@ erpc_status_t Sniffer::analyzeMessage(string &message, const char *timeDiffernce return err; } - enum msg_t + enum class msg_t { msg_request, // client serialization/server deserialization msg_answer // client deserialization/server serialization @@ -713,14 +740,14 @@ erpc_status_t Sniffer::analyzeMessage(string &message, const char *timeDiffernce // Set message type. msg_t msgType; - if (messageType == message_type_t::kInvocationMessage || messageType == message_type_t::kOnewayMessage) + if ((messageType == message_type_t::kInvocationMessage) || (messageType == message_type_t::kOnewayMessage)) { - msgType = msg_request; + msgType = msg_t::msg_request; message += "'Request'"; } else { - msgType = msg_answer; + msgType = msg_t::msg_answer; message += "'Answer'"; } @@ -731,7 +758,7 @@ erpc_status_t Sniffer::analyzeMessage(string &message, const char *timeDiffernce // Find and record interface information. if (Interface *interface = getInterface(serviceId)) { - string groupName = interface->getAnnStringValue(GROUP_ANNOTATION, Annotation::kC); + string groupName = interface->getAnnStringValue(GROUP_ANNOTATION, Annotation::program_lang_t::kC); message += format_string("Group name:%s\nInterface name:%s id:%d\n", groupName.c_str(), interface->getName().c_str(), serviceId); @@ -745,10 +772,10 @@ erpc_status_t Sniffer::analyzeMessage(string &message, const char *timeDiffernce StructType params = function->getParameters(); for (StructMember *param : params.getMembers()) { - if ((msgType == msg_request && (param->getDirection() == _param_direction::kInDirection || - param->getDirection() == _param_direction::kInoutDirection)) || - (msgType == msg_answer && (param->getDirection() == _param_direction::kOutDirection || - param->getDirection() == _param_direction::kInoutDirection))) + if ((msgType == msg_t::msg_request && (param->getDirection() == param_direction_t::kInDirection || + param->getDirection() == param_direction_t::kInoutDirection)) || + (msgType == msg_t::msg_answer && (param->getDirection() == param_direction_t::kOutDirection || + param->getDirection() == param_direction_t::kInoutDirection))) { string output; err = parseMemberType(¶ms, param, output); @@ -763,7 +790,7 @@ erpc_status_t Sniffer::analyzeMessage(string &message, const char *timeDiffernce } // Record function's return data information. - if (msgType == msg_answer) + if (msgType == msg_t::msg_answer) { StructMember *returnDataType = function->getReturnStructMemberType(); if (returnDataType) diff --git a/erpcsniffer/src/Sniffer.hpp b/erpcsniffer/src/Sniffer.hpp index b61177d9..0697ad3a 100644 --- a/erpcsniffer/src/Sniffer.hpp +++ b/erpcsniffer/src/Sniffer.hpp @@ -37,12 +37,10 @@ class Sniffer * @param[in] quantity How much messages record. */ Sniffer(erpc::Transport *transport, erpcgen::InterfaceDefinition *def, const char *outputFilePath, - uint64_t quantity) - : m_transport(transport) - , m_interfaces(def->getGlobals().getSymbolsOfType(erpcgen::Symbol::kInterfaceSymbol)) - , m_outputFilePath(outputFilePath) - , m_quantity(quantity) - , m_codec(new erpc::BasicCodec()){}; + uint64_t quantity) : + m_transport(transport), + m_interfaces(def->getGlobals().getSymbolsOfType(erpcgen::Symbol::symbol_type_t::kInterfaceSymbol)), + m_outputFilePath(outputFilePath), m_quantity(quantity), m_codec(new erpc::BasicCodec()){}; /*! * @brief This function is destructor of Sniffer class. diff --git a/erpcsniffer/src/erpc_config.h b/erpcsniffer/src/erpc_config.h index f1a68c01..bf256c30 100644 --- a/erpcsniffer/src/erpc_config.h +++ b/erpcsniffer/src/erpc_config.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2020 NXP + * Copyright 2020-2021 ACRIOS Systems s.r.o. * All rights reserved. * * @@ -10,6 +11,12 @@ #ifndef _ERPC_CONFIG_H_ #define _ERPC_CONFIG_H_ +/*! + * @addtogroup config + * @{ + * @file + */ + //////////////////////////////////////////////////////////////////////////////// // Declarations //////////////////////////////////////////////////////////////////////////////// @@ -176,10 +183,27 @@ //! @name Assert function definition //@{ -//! User custom asser defition. Include header file if needed before bellow line. If assert is not enabled, default will be used. +//! User custom asser defition. Include header file if needed before bellow line. If assert is not enabled, default will +//! be used. // #define erpc_assert(condition) //@} +//! @def ENDIANES_HEADER +//! +//! Include header file that controls the communication endianness +//! +//! Uncomment for example behaviour for endianness agnostic with: +//! 1. communication in little endian. +//! 2. current processor is big endian. +//! 3. pointer size is 32 bit. +//! 4. float+double scheme not defined, so throws assert if passes. +//! #define ERPC_PROCESSOR_ENDIANNESS_LITTLE 0 +//! #define ERPC_COMMUNICATION_LITTLE 1 +//! #define ERPC_POINTER_SIZE_16 0 +//! #define ERPC_POINTER_SIZE_32 1 +//! #define ERPC_POINTER_SIZE_64 0 +//! #define ENDIANNESS_HEADER "erpc_endianness_agnostic_example.h" + /*! @} */ #endif // _ERPC_CONFIG_H_ //////////////////////////////////////////////////////////////////////////////// diff --git a/erpcsniffer/src/erpcsniffer.cpp b/erpcsniffer/src/erpcsniffer.cpp index 043c328b..80b94735 100644 --- a/erpcsniffer/src/erpcsniffer.cpp +++ b/erpcsniffer/src/erpcsniffer.cpp @@ -94,7 +94,7 @@ Available transports (use with -t option):\n\ class erpcsnifferTool { protected: - enum verbose_type_t + enum class verbose_type_t { kWarning, kInfo, @@ -102,7 +102,7 @@ class erpcsnifferTool kExtraDebug }; /*!< Types of verbose outputs from erpcsniffer application. */ - enum transports_t + enum class transports_t { kNoneTransport, kTcpTransport, @@ -133,22 +133,14 @@ class erpcsnifferTool * * Creates the singleton logger instance. */ - erpcsnifferTool(int argc, char *argv[]) - : m_argc(argc) - , m_argv(argv) - , m_logger(0) - , m_verboseType(kWarning) - , m_outputFilePath(NULL) - , m_ErpcFile(NULL) - , m_transport(kNoneTransport) - , m_quantity(10) - , m_baudrate(115200) - , m_port(NULL) - , m_host(NULL) + erpcsnifferTool(int argc, char *argv[]) : + m_argc(argc), m_argv(argv), m_logger(0), m_verboseType(verbose_type_t::kWarning), m_outputFilePath(NULL), + m_ErpcFile(NULL), m_transport(transports_t::kNoneTransport), m_quantity(10), m_baudrate(115200), m_port(NULL), + m_host(NULL) { // create logger instance m_logger = new StdoutLogger(); - m_logger->setFilterLevel(Logger::kWarning); + m_logger->setFilterLevel(Logger::log_level_t::kWarning); Log::setLogger(m_logger); } @@ -185,73 +177,84 @@ class erpcsnifferTool { switch (optchar) { - case '?': { + case '?': + { printUsage(options); return 0; } - case 'V': { + case 'V': + { printf("%s %s\n%s\n", k_toolName, k_version, k_copyright); return 0; } - case 'o': { + case 'o': + { m_outputFilePath = optarg; break; } - case 'v': { - if (m_verboseType != kExtraDebug) + case 'v': + { + if (m_verboseType != verbose_type_t::kExtraDebug) { m_verboseType = (verbose_type_t)(((int)m_verboseType) + 1); } break; } - case 'I': { + case 'I': + { PathSearcher::getGlobalSearcher().addSearchPath(optarg); break; } - case 't': { + case 't': + { string transport = optarg; if (transport == "tcp") { - m_transport = kTcpTransport; + m_transport = transports_t::kTcpTransport; } else if (transport == "serial") { - m_transport = kSerialTransport; + m_transport = transports_t::kSerialTransport; } else { - Log::error(format_string("error: unknown transport type %s", transport.c_str()).c_str()); + Log::error("error: unknown transport type %s", transport.c_str()); return 1; } break; } - case 'q': { + case 'q': + { m_quantity = strtoul(optarg, NULL, 10); break; } - case 'b': { + case 'b': + { m_baudrate = strtoul(optarg, NULL, 10); break; } - case 'p': { + case 'p': + { m_port = optarg; break; } - case 'h': { + case 'h': + { m_host = optarg; break; } - default: { + default: + { Log::error("error: unrecognized option\n\n"); printUsage(options); return 0; @@ -336,7 +339,8 @@ class erpcsnifferTool Transport *_transport; switch (m_transport) { - case kTcpTransport: { + case transports_t::kTcpTransport: + { uint16_t portNumber = strtoul(m_port, NULL, 10); TCPTransport *tcpTransport = new TCPTransport(m_host, portNumber, true); if (erpc_status_t err = tcpTransport->open()) @@ -347,14 +351,16 @@ class erpcsnifferTool break; } - case kSerialTransport: { + case transports_t::kSerialTransport: + { erpc_transport_t transport = erpc_transport_serial_init(m_port, m_baudrate); _transport = reinterpret_cast(transport); assert(_transport); break; } - default: { + default: + { break; } } @@ -363,7 +369,7 @@ class erpcsnifferTool if (def.hasProgramSymbol()) { Program *program = def.getProgramSymbol(); - if (program->findAnnotation(CRC_ANNOTATION, Annotation::kC) != nullptr) + if (program->findAnnotation(CRC_ANNOTATION, Annotation::program_lang_t::kC) != nullptr) { crc.setCrcStart(def.getIdlCrc16()); } @@ -408,17 +414,17 @@ class erpcsnifferTool // if the user has selected quiet mode, it overrides verbose switch (m_verboseType) { - case kWarning: - Log::getLogger()->setFilterLevel(Logger::kWarning); + case verbose_type_t::kWarning: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kWarning); break; - case kInfo: - Log::getLogger()->setFilterLevel(Logger::kInfo); + case verbose_type_t::kInfo: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kInfo); break; - case kDebug: - Log::getLogger()->setFilterLevel(Logger::kDebug); + case verbose_type_t::kDebug: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kDebug); break; - case kExtraDebug: - Log::getLogger()->setFilterLevel(Logger::kDebug2); + case verbose_type_t::kExtraDebug: + Log::getLogger()->setFilterLevel(Logger::log_level_t::kDebug2); break; } } diff --git a/examples/matrix_multiply_java/.gitignore b/examples/matrix_multiply_java/.gitignore new file mode 100644 index 00000000..5ff6309b --- /dev/null +++ b/examples/matrix_multiply_java/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/examples/matrix_multiply_java/pom.xml b/examples/matrix_multiply_java/pom.xml new file mode 100644 index 00000000..d5710d77 --- /dev/null +++ b/examples/matrix_multiply_java/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + io.github.embeddedrpc.erpc.example + matrix_multiply_java + 1.0 + + + 21 + 21 + UTF-8 + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + + ${project.build.directory}/libs + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + libs/ + + io.github.embeddedrpc.erpc.example.Main + + + + + + + + + + + io.github.embeddedrpc.erpc + erpc + 0.1.0 + + + commons-cli + commons-cli + 1.6.0 + + + + \ No newline at end of file diff --git a/examples/matrix_multiply_java/readme.md b/examples/matrix_multiply_java/readme.md new file mode 100644 index 00000000..11cfae60 --- /dev/null +++ b/examples/matrix_multiply_java/readme.md @@ -0,0 +1,81 @@ +# Matrix Multiply Java Example + +This example demonstrates the use of Java eRPC. It could be used with as a server or client. This example is +compatible with the Python and C versions of this example. + +When the client is started, it generates two random matrices and sends them to the server. The server then performs +matrix multiplication and sends the resulting matrix back to the client. The client then prints out the resulting +matrix. + +## eRPC documentation + +- eRPC is open-source project stored on github: https://github.com/EmbeddedRPC/erpc +- eRPC documentation can be also found on github: https://github.com/EmbeddedRPC/erpc/wiki + +## Prerequisites + +- [Java 21 SDK](https://jdk.java.net/21/) +- [Maven 3.9.5](https://maven.apache.org/download.cgi) + +To check that all the prerequisites are correctly installed, run `mvn -v`. You should get something like this: + +``` +Apache Maven 3.9.5 (***) +Maven home: c:\Program Files\maven\apache-maven-3.9.5 +Java version: 21, vendor: Oracle Corporation, runtime: c:\Program Files\Java\jdk-21 +Default locale: en_US, platform encoding: UTF-8 +OS name: "***", version: "***", arch: "***", family: "***" +``` + +- If `mvn -v` fails, check that you have added maven to the `PATH` variable. +- If you do not see the correct Java version, check that you have set the `JAVA_HOME` and `PATH` variables correctly. + +## Example's files + +- `Main.java`: Main file +- `MatrixMultiplyService.java`: Custom service for MatrixMultiplyService interface +- `pom.xml`: Maven configuration file, with Java eRPC dependency +- `resource/erpc_matrix_multiply.erpc`: eRPC IDL file for example +- `erpc_matrix_multiply/`: eRPC output shim code generated from IDL file + +## eRPC installation + +1. Run `mvn -f ..\..\erpc_java\pom.xml install`. This command install the Java eRPC to the local repository. + +## Building the example + +To build and run this example, we create executable jar with copied dependencies using Maven. + +1. Run `mvn package` to download all dependencies and create executable jar in `target/` (all Maven configuration is + stored in `pom.xml`). + +## Running the example + +### Parameters + +- `-c,--client ` Run client +- `-s,--server ` Run server +- `-S,--serial ` Serial device (default value is None) +- `-B,--baud ` Baud (default value is 115200) +- `-t,--host ` Host IP address (default value is localhost) +- `-p,--port ` Port (default value is 40) + +### Running + +To execute the example use `java` with parameter `-jar` and the jar file we created. The pass the arguments to example. + +```shell +java -jar .\target\matrix_multiply_java-1.0.jar -s # Server on port 40 +java -jar .\target\matrix_multiply_java-1.0.jar -s -p 12345 # Server on port 12345 +java -jar .\target\matrix_multiply_java-1.0.jar -c # Client connected to `localhost:40` +java -jar .\target\matrix_multiply_java-1.0.jar -c -S COM6 # Client connected serial port COM6 +``` + +You can also try this example with a Python or C implementation. For Python server, execute: +```shell +python ..\matrix_multiply_tcp_python\matrix_multiply.py --server --host localhost --port 40 +``` +and then: +```shell +java -jar .\target\matrix_multiply_java-1.0.jar -c +``` \ No newline at end of file diff --git a/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/Main.java b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/Main.java new file mode 100644 index 00000000..12f4ac63 --- /dev/null +++ b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/Main.java @@ -0,0 +1,180 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.example; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.client.ClientManager; +import io.github.embeddedrpc.erpc.codec.BasicCodecFactory; +import io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.client.MatrixMultiplyServiceClient; +import io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.common.Constants; +import io.github.embeddedrpc.erpc.server.Server; +import io.github.embeddedrpc.erpc.server.SimpleServer; +import io.github.embeddedrpc.erpc.transport.SerialTransport; +import io.github.embeddedrpc.erpc.transport.TCPTransport; +import io.github.embeddedrpc.erpc.transport.Transport; +import org.apache.commons.cli.*; + +import java.io.IOException; +import java.util.Random; + +public class Main { + public static final String HOST = "localhost"; + public static final int PORT = 40; + public static final int BAUDRATE = 115200; + + public static void main(String[] args) throws IOException { + // parsing objects + Options options = new Options(); + HelpFormatter formatter = new HelpFormatter(); + CommandLine cmd; + + // configuration + String host = HOST; + int port = PORT; + String serial = null; + int baudrate = BAUDRATE; + Transport transport; + + // parsing options + options.addOption("c", "client", false, "Run client"); + options.addOption("s", "server", false, "Run server"); + options.addOption("t", "host", true, "Host IP address (default value is localhost)"); + options.addOption("p", "port", true, "Port (default value is 40)"); + options.addOption("S", "serial", true, "Serial device (default value is None)"); + options.addOption("B", "baud", true, "Baud (default value is 115200)"); + + CommandLineParser parser = new DefaultParser(); + + // parsing cmd arguments + try { + cmd = parser.parse(options, args); + } catch (ParseException e) { + System.err.println("Parsing failed. Reason: " + e.getMessage()); + System.exit(1); + return; + } + + if (!cmd.hasOption('c') && !cmd.hasOption('s')) { + formatter.printHelp("ant", options); + System.err.println("Either server or client has to be selected to run"); + System.exit(1); + } + + if (cmd.hasOption('t') && !cmd.getOptionValue('t').isEmpty()) { + host = cmd.getOptionValue('t'); + } + + if (cmd.hasOption('p') && !cmd.getOptionValue('p').isEmpty()) { + port = Integer.parseInt(cmd.getOptionValue('p')); + } + + if (cmd.hasOption("S")) { + if (cmd.getOptionValue('S').isEmpty()) { + System.err.println("Select serial port with: '-S COM_PORT'"); + System.exit(1); + } + serial = cmd.getOptionValue('S'); + } + + if (cmd.hasOption('B') && !cmd.getOptionValue('B').isEmpty()) { + baudrate = Integer.parseInt(System.getProperty("baudrate")); + } + + System.out.println("eRPC Matrix Multiply TCP example"); + + // transport initialization + if (serial != null) { + // initialize Serial transport layer + System.out.println("Transport: serial=" + serial + " baudrate=" + baudrate); + transport = new SerialTransport(serial, baudrate); + } else { + // initialize TCP transport layer + if (cmd.hasOption('c')) { + // client + System.out.println("Transport: tcp client - host=" + host + " port=" + port); + transport = new TCPTransport(host, port); + } else { + // server + System.out.println("Transport: tcp server - port = " + port); + transport = new TCPTransport(port); + } + } + + // running example + if (cmd.hasOption('c')) { + client(transport); + } else if (cmd.hasOption('s')) { + server(transport); + } else { + // Should not happen + assert false; + } + } + + public static void fillMatrix(int[][] matrix) { + Random rand = new Random(); + for (int y = 0; y < matrix.length; y++) { + for (int x = 0; x < matrix[y].length; x++) { + matrix[y][x] = Math.abs(rand.nextInt() % 10); + } + } + } + + public static void printMatrix(int[][] matrix) { + for (int[] y : matrix) { + for (int x : y) { + System.out.print(x); + System.out.print(" "); + } + System.out.println(); + } + } + + public static void server(Transport transport) { + Server server = new SimpleServer(transport, new BasicCodecFactory()); + + server.addService(new MatrixMultiplyService()); + + server.run(); + } + + public static void client(Transport transport) throws IOException { + ClientManager clientManager = new ClientManager(transport, new BasicCodecFactory()); + MatrixMultiplyServiceClient client = new MatrixMultiplyServiceClient(clientManager); + + try { + while (true) { + int[][] matrix1 = new int[Constants.matrix_size][5]; + int[][] matrix2 = new int[5][5]; + Reference matrixResult = new Reference<>(); + + fillMatrix(matrix1); + fillMatrix(matrix2); + + System.out.println("Matrix #1\r\n========="); + printMatrix(matrix1); + System.out.println("\r\nMatrix #1\r\n========="); + printMatrix(matrix2); + + System.out.println("\r\neRPC request is sent to the server"); + client.erpcMatrixMultiply(matrix1, matrix2, matrixResult); + + System.out.println("\r\nMatrix result\r\n========="); + printMatrix(matrixResult.get()); + + System.out.println("\r\nPress Enter to initiate the next matrix multiplication or 'q' to quit"); + if (System.in.read() == 'q') { + break; + } + } + } finally { + transport.close(); + } + + System.out.println("eRPC Matrix Multiply TCP example finished."); + } +} \ No newline at end of file diff --git a/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/MatrixMultiplyService.java b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/MatrixMultiplyService.java new file mode 100644 index 00000000..e6506783 --- /dev/null +++ b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/MatrixMultiplyService.java @@ -0,0 +1,35 @@ +package io.github.embeddedrpc.erpc.example; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.example.Main; +import io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.common.Constants; +import io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.server.AbstractMatrixMultiplyServiceService; + +public class MatrixMultiplyService extends AbstractMatrixMultiplyServiceService { + + @Override + public void erpcMatrixMultiply(int[][] matrix1, int[][] matrix2, Reference result_matrix) { + System.out.println("Server received these matrices:"); + System.out.println("\r\nMatrix #1"); + System.out.println("========="); + Main.printMatrix(matrix1); + + System.out.println("\r\nMatrix #2"); + System.out.println("========="); + Main.printMatrix(matrix2); + + result_matrix.set(new int[Constants.matrix_size][Constants.matrix_size]); + + for (int i = 0; i < Constants.matrix_size; i++) { + for (int j = 0; j < Constants.matrix_size; j++) { + for (int k = 0; k < Constants.matrix_size; k++) { + result_matrix.get()[i][j] += matrix1[i][k] * matrix2[k][j]; + } + } + } + + System.out.println("\r\nResult matrix"); + System.out.println("========="); + Main.printMatrix(result_matrix.get()); + } +} diff --git a/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/client/MatrixMultiplyServiceClient.java b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/client/MatrixMultiplyServiceClient.java new file mode 100644 index 00000000..15b4d35f --- /dev/null +++ b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/client/MatrixMultiplyServiceClient.java @@ -0,0 +1,86 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 09:33:04 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.client; + +import io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.interfaces.IMatrixMultiplyService; + + + + +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.RequestContext; +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import io.github.embeddedrpc.erpc.client.ClientManager; +import io.github.embeddedrpc.erpc.codec.Codec; + +import java.util.ArrayList; +import java.util.List; + +public class MatrixMultiplyServiceClient implements IMatrixMultiplyService { + private final ClientManager clientManager; + + public MatrixMultiplyServiceClient(ClientManager clientManager) { + this.clientManager = clientManager; + } + + @Override + public void erpcMatrixMultiply(int[][] matrix1, int[][] matrix2, Reference result_matrix) { + // Create request + RequestContext request = clientManager.createRequest(false); + Codec codec = request.codec(); + + // Write message info + codec.startWriteMessage(new MessageInfo( + MessageType.kInvocationMessage, + this.SERVICE_ID, + this.ERPCMATRIXMULTIPLY_ID, + request.sequence())); + + // Write message data + Utils.checkNotNull(matrix1, "matrix1 is null"); + + for (int genLoopVariable1 = 0; genLoopVariable1 < 5; ++genLoopVariable1) + { + int[] genValueVariable1 = matrix1[genLoopVariable1]; + for (int genLoopVariable2 = 0; genLoopVariable2 < 5; ++genLoopVariable2) + { + int genValueVariable2 = genValueVariable1[genLoopVariable2]; + codec.writeInt32(genValueVariable2); + } + } + Utils.checkNotNull(matrix2, "matrix2 is null"); + + for (int genLoopVariable1 = 0; genLoopVariable1 < 5; ++genLoopVariable1) + { + int[] genValueVariable1 = matrix2[genLoopVariable1]; + for (int genLoopVariable2 = 0; genLoopVariable2 < 5; ++genLoopVariable2) + { + int genValueVariable2 = genValueVariable1[genLoopVariable2]; + codec.writeInt32(genValueVariable2); + } + } + + // Perform request + clientManager.performRequest(request); + + // Read out parameters + + result_matrix.set(new int[5][5]); + for (int genLoopVariable1 = 0; genLoopVariable1 < 5; ++genLoopVariable1) + { + int[] genValueVariable1 = new int[5]; + for (int genLoopVariable2 = 0; genLoopVariable2 < 5; ++genLoopVariable2) + { + int genValueVariable2 = codec.readInt32(); + genValueVariable1[genLoopVariable2] = genValueVariable2; + } + result_matrix.get()[genLoopVariable1] = genValueVariable1; + } + } +} diff --git a/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/common/Constants.java b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/common/Constants.java new file mode 100644 index 00000000..6543b0f8 --- /dev/null +++ b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/common/Constants.java @@ -0,0 +1,24 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 09:33:04 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + package io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.common; + + + + + +import java.util.ArrayList; +import java.util.List; + +public final class Constants { + /*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ + public static final int matrix_size = 5; + + private Constants() { + } +} + diff --git a/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/interfaces/IMatrixMultiplyService.java b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/interfaces/IMatrixMultiplyService.java new file mode 100644 index 00000000..3599a81a --- /dev/null +++ b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/interfaces/IMatrixMultiplyService.java @@ -0,0 +1,24 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 09:33:04 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.interfaces; + + + + +import io.github.embeddedrpc.erpc.auxiliary.Reference; + +import java.util.List; + +public interface IMatrixMultiplyService { + int SERVICE_ID = 1; + int ERPCMATRIXMULTIPLY_ID = 1; + + void erpcMatrixMultiply(int[][] matrix1, int[][] matrix2, Reference result_matrix); +} + + + diff --git a/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/server/AbstractMatrixMultiplyServiceService.java b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/server/AbstractMatrixMultiplyServiceService.java new file mode 100644 index 00000000..2312c609 --- /dev/null +++ b/examples/matrix_multiply_java/src/main/java/io/github/embeddedrpc/erpc/example/erpc_matrix_multiply/server/AbstractMatrixMultiplyServiceService.java @@ -0,0 +1,89 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 09:33:04 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ +package io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.server; + +import io.github.embeddedrpc.erpc.example.erpc_matrix_multiply.interfaces.IMatrixMultiplyService; + + + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.auxiliary.Reference; + + +import java.util.ArrayList; +import java.util.List; + +/** + * Testing abstract service class for simple eRPC interface. + */ +public abstract class AbstractMatrixMultiplyServiceService + extends Service + implements IMatrixMultiplyService { + + /** + * Default constructor. + */ + public AbstractMatrixMultiplyServiceService() { + super(IMatrixMultiplyService.SERVICE_ID); + addMethodHandler(IMatrixMultiplyService.ERPCMATRIXMULTIPLY_ID, this::erpcMatrixMultiplyHandler); + } + + private void erpcMatrixMultiplyHandler(int sequence, Codec codec) { + int[][] matrix1; + int[][] matrix2; + Reference result_matrix = new Reference<>(); + + matrix1 = new int[5][5]; + for (int genLoopVariable1 = 0; genLoopVariable1 < 5; ++genLoopVariable1) + { + int[] genValueVariable1 = new int[5]; + for (int genLoopVariable2 = 0; genLoopVariable2 < 5; ++genLoopVariable2) + { + int genValueVariable2 = codec.readInt32(); + genValueVariable1[genLoopVariable2] = genValueVariable2; + } + matrix1[genLoopVariable1] = genValueVariable1; + } + matrix2 = new int[5][5]; + for (int genLoopVariable1 = 0; genLoopVariable1 < 5; ++genLoopVariable1) + { + int[] genValueVariable1 = new int[5]; + for (int genLoopVariable2 = 0; genLoopVariable2 < 5; ++genLoopVariable2) + { + int genValueVariable2 = codec.readInt32(); + genValueVariable1[genLoopVariable2] = genValueVariable2; + } + matrix2[genLoopVariable1] = genValueVariable1; + } + + erpcMatrixMultiply(matrix1, matrix2, result_matrix); + + codec.reset(); + + codec.startWriteMessage(new MessageInfo( + MessageType.kReplyMessage, + getServiceId(), + IMatrixMultiplyService.ERPCMATRIXMULTIPLY_ID, + sequence) + ); + + // Read out parameters + for (int genLoopVariable1 = 0; genLoopVariable1 < 5; ++genLoopVariable1) + { + int[] genValueVariable1 = result_matrix.get()[genLoopVariable1]; + for (int genLoopVariable2 = 0; genLoopVariable2 < 5; ++genLoopVariable2) + { + int genValueVariable2 = genValueVariable1[genLoopVariable2]; + codec.writeInt32(genValueVariable2); + } + } + } + +} + diff --git a/examples/matrix_multiply_java/src/main/resources/erpc_matrix_multiply.erpc b/examples/matrix_multiply_java/src/main/resources/erpc_matrix_multiply.erpc new file mode 100644 index 00000000..8099a835 --- /dev/null +++ b/examples/matrix_multiply_java/src/main/resources/erpc_matrix_multiply.erpc @@ -0,0 +1,21 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +program erpc_matrix_multiply + +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +const int32 matrix_size = 5; + +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +type Matrix = int32[matrix_size][matrix_size]; + +interface MatrixMultiplyService { + erpcMatrixMultiply(in Matrix matrix1, in Matrix matrix2, out Matrix result_matrix) -> void +} diff --git a/examples/matrix_multiply_tcp_python/service/__init__.py b/examples/matrix_multiply_tcp_python/service/__init__.py index 7f501191..b3fea60e 100644 --- a/examples/matrix_multiply_tcp_python/service/__init__.py +++ b/examples/matrix_multiply_tcp_python/service/__init__.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# Generated by erpcgen 1.10.0 on Thu Oct 13 21:22:10 2022. +# Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. # # AUTOGENERATED - DO NOT EDIT # diff --git a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/__init__.py b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/__init__.py index 7a0ca3b5..360de229 100644 --- a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/__init__.py +++ b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/__init__.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# Generated by erpcgen 1.10.0 on Thu Oct 13 21:22:10 2022. +# Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. # # AUTOGENERATED - DO NOT EDIT # @@ -15,8 +15,8 @@ version = erpc_version.ERPC_VERSION except ImportError: version = "unknown" -if version != "1.10.0": - raise ValueError("The generated shim code version (1.10.0) is different to the rest of eRPC code (%s). \ +if version != "1.12.0": + raise ValueError("The generated shim code version (1.12.0) is different to the rest of eRPC code (%s). \ Install newer version by running \"python setup.py install\" in folder erpc/erpc_python/." % repr(version)) from . import common diff --git a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/client.py b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/client.py index 4a05460a..098618db 100644 --- a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/client.py +++ b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/client.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# Generated by erpcgen 1.10.0 on Thu Oct 13 21:22:10 2022. +# Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. # # AUTOGENERATED - DO NOT EDIT # diff --git a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/common.py b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/common.py index 511c4033..a4ede601 100644 --- a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/common.py +++ b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/common.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# Generated by erpcgen 1.10.0 on Thu Oct 13 21:22:10 2022. +# Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. # # AUTOGENERATED - DO NOT EDIT # diff --git a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/interface.py b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/interface.py index 8137fcc0..b0d25311 100644 --- a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/interface.py +++ b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/interface.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# Generated by erpcgen 1.10.0 on Thu Oct 13 21:22:10 2022. +# Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. # # AUTOGENERATED - DO NOT EDIT # diff --git a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/server.py b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/server.py index ccb2daa4..7fa1adc6 100644 --- a/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/server.py +++ b/examples/matrix_multiply_tcp_python/service/erpc_matrix_multiply/server.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# Generated by erpcgen 1.10.0 on Thu Oct 13 21:22:10 2022. +# Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. # # AUTOGENERATED - DO NOT EDIT # diff --git a/examples/zephyr/matrix_multiply_rpmsglite/CMakeLists.txt b/examples/zephyr/matrix_multiply_rpmsglite/CMakeLists.txt new file mode 100644 index 00000000..ef3edcef --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/CMakeLists.txt @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/../remote_server/zephyr) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(matrix_multiply_rpmsglite) + +if(CONFIG_INCLUDE_REMOTE_DIR) + target_include_directories(zephyr_interface + INTERFACE ${REMOTE_ZEPHYR_DIR}/include/public) +endif() + +enable_language(C CXX) + +target_include_directories(app PRIVATE + ${PROJECT_SOURCE_DIR}/ + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/src/service +) + +target_sources(app PRIVATE + ${PROJECT_SOURCE_DIR}/src/main.cpp + ${PROJECT_SOURCE_DIR}/src/erpc_error_handler.cpp + + # Generated shim code + ${PROJECT_SOURCE_DIR}/src/service/c_erpc_matrix_multiply_client.cpp + ${PROJECT_SOURCE_DIR}/src/service/erpc_matrix_multiply_client.cpp + ${PROJECT_SOURCE_DIR}/src/service/erpc_matrix_multiply_interface.cpp +) + +# Also include this directory into rpmsg_lite library because of project specific include rpsmg_config.h +target_include_directories(rpmsg_lite PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +# Same for erpc library and erpc_config.h +target_include_directories(erpc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/examples/zephyr/matrix_multiply_rpmsglite/Kconfig b/examples/zephyr/matrix_multiply_rpmsglite/Kconfig new file mode 100644 index 00000000..3837c49b --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/Kconfig @@ -0,0 +1,11 @@ +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +source "Kconfig.zephyr" + +config INCLUDE_REMOTE_DIR + bool "Include remote core header directory" + help + Include remote build header files. Can be used if primary image + needs to be aware of size or base address of secondary image diff --git a/examples/zephyr/matrix_multiply_rpmsglite/Kconfig.sysbuild b/examples/zephyr/matrix_multiply_rpmsglite/Kconfig.sysbuild new file mode 100644 index 00000000..0ff689dd --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config RPMSG_LITE_REMOTE_BOARD +string + default "lpcxpresso54114_m0" if $(BOARD) = "lpcxpresso54114_m4" + default "lpcxpresso55s69_cpu1" if $(BOARD) = "lpcxpresso55s69_cpu0" + default "mps2_an521_remote" if $(BOARD) = "mps2_an521" + default "v2m_musca_b1_ns" if $(BOARD) = "v2m_musca_b1" + default "mimxrt1170_evk_cm4" if $(BOARD) = "mimxrt1170_evk_cm7" + default "mimxrt1160_evk_cm4" if $(BOARD) = "mimxrt1160_evk_cm7" + default "mimxrt1170_evkb_cm4" if $(BOARD) = "mimxrt1170_evkb_cm7" diff --git a/examples/zephyr/matrix_multiply_rpmsglite/README.rst b/examples/zephyr/matrix_multiply_rpmsglite/README.rst new file mode 100644 index 00000000..80ee9cef --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/README.rst @@ -0,0 +1,118 @@ +.. _matrix_multiply_rpmsglite: + +Matrix multiply RPMSG-Lite +########### + +The eRPC Matrix multiply RPMSG-Lite sample that can be used with: :ref:`supported board `. + + +The Multicore eRPC Matrix Multiply project is a simple demonstration program that uses Zephyr OS and +the Multicore SDK to show how to implement the Remote Procedure Call between cores of the multicore +system. The primary core (eRPC client) releases the secondary core (eRPC server) from the reset and +then the erpcMatrixMultiply() eRPC call is issued to let the secondary core to perform the +multiplication of two randomly generated matrices. The original matrices and the result matrix is +printed out to the serial console by the primary core. RPMsg-Lite erpctransport layer is used in +this example application. + +Shared memory usage +This multicore example uses the shared memory for data exchange. The shared memory region is +defined and the size can be adjustable in the `board/.overlay`. The shared memory region +start address and the size have to be defined for each core equally. + +eRPC documentation +eRPC specific files are stored in: middleware\multicore\erpc +eRPC documentation is stored in: middleware\multicore\erpc\doc +eRPC is open-source project stored on github: https://github.com/EmbeddedRPC/erpc +eRPC documentation can be also found in: http://embeddedrpc.github.io + +Building and Running +******************** + +This application can be built and executed on Supported Multi Core boards as follows: + + +Building the application for lpcxpresso54114_m4 +*********************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/matrix_multiply_rpmsglite + :board: lpcxpresso54114_m4 + :goals: debug + :west-args: --sysbuild + +Building the application for lpcxpresso55s69_cpu0 +************************************************* + +.. zephyr-app-commands:: + :zephyr-app: samples/matrix_multiply_rpmsglite + :board: lpcxpresso55s69_cpu0 + :goals: debug + :west-args: --sysbuild + +Building the application for mimxrt1160_evk_cm7 +*********************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/matrix_multiply_rpmsglite + :board: mimxrt1160_evk_cm7 + :goals: debug + :west-args: --sysbuild + +Building the application for mimxrt1170_evk_cm7 +*********************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/matrix_multiply_rpmsglite + :board: mimxrt1170_evk_cm7 + :goals: debug + :west-args: --sysbuild + +Building the application for mimxrt1170_evkb_cm7 +*********************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/matrix_multiply_rpmsglite + :board: mimxrt1170_evkb_cm7 + :goals: debug + :west-args: --sysbuild + +Sample Output +============= + +Open a serial terminal (minicom, putty, etc.) and connect the board with the +following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and the following message will appear on the corresponding +serial port: + +.. code-block:: console + + Matrix #1 + 21 33 37 37 9 + 23 45 43 0 32 + 38 44 8 15 36 + 18 18 38 44 16 + 22 23 0 38 7 + + Matrix #2 + 11 23 27 45 11 + 7 19 23 24 6 + 32 26 49 43 16 + 22 48 36 34 41 + 27 20 32 31 11 + + eRPC request is sent to the server + + Result matrix + 2703 4028 4759 4865 2637 + 2808 3142 4787 4956 1563 + 2284 3358 4122 4736 1821 + 2940 4176 4858 4868 2894 + 1428 2907 2715 3051 2015 + + ... \ No newline at end of file diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.conf b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.conf new file mode 100644 index 00000000..60eead5a --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.conf @@ -0,0 +1,2 @@ +CONFIG_SECOND_CORE_MCUX=y +CONFIG_INCLUDE_REMOTE_DIR=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.overlay b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.overlay new file mode 100644 index 00000000..e061dcc4 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso54114_m4.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019 Linaro Limited + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /* + * shared memory reserved for the inter-processor communication + */ + zephyr,ipc_shm = &sramx1; + zephyr,ipc = &mailbox0; + }; + + sramx1:memory@4000000{ + compatible = "mmio-sram"; + reg = <0x4000000 0x8000>; + }; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.conf b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.conf new file mode 100644 index 00000000..7e6904d5 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.conf @@ -0,0 +1 @@ +CONFIG_SECOND_CORE_MCUX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.overlay b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.overlay new file mode 100644 index 00000000..270eb0e7 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/lpcxpresso55s69_cpu0.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Linaro Limited + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /* + * shared memory reserved for the inter-processor communication + */ + + zephyr,ipc_shm = &sram4duplicate; + zephyr,ipc = &mailbox0; + }; + + /* This is a duplication of sram4, workaround */ + sram4duplicate: memory@20040000 { + compatible = "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(16)>; + }; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.conf b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.conf new file mode 100644 index 00000000..630a1933 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.conf @@ -0,0 +1,2 @@ +CONFIG_INCLUDE_REMOTE_DIR=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.overlay b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.overlay new file mode 100644 index 00000000..584538a1 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1160_evk_cm7.overlay @@ -0,0 +1,24 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + chosen { + zephyr,ipc_shm = &ocram2_overlay; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set. + */ + ocram2_overlay: memory@202c0000{ + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.conf b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.conf new file mode 100644 index 00000000..630a1933 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.conf @@ -0,0 +1,2 @@ +CONFIG_INCLUDE_REMOTE_DIR=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.overlay b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.overlay new file mode 100644 index 00000000..584538a1 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evk_cm7.overlay @@ -0,0 +1,24 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + chosen { + zephyr,ipc_shm = &ocram2_overlay; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set. + */ + ocram2_overlay: memory@202c0000{ + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.conf b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.conf new file mode 100644 index 00000000..ae8dba8c --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.conf @@ -0,0 +1,7 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_INCLUDE_REMOTE_DIR=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.overlay b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.overlay new file mode 100644 index 00000000..584538a1 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/boards/mimxrt1170_evkb_cm7.overlay @@ -0,0 +1,24 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + chosen { + zephyr,ipc_shm = &ocram2_overlay; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set. + */ + ocram2_overlay: memory@202c0000{ + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/erpc_config.h b/examples/zephyr/matrix_multiply_rpmsglite/erpc_config.h new file mode 100644 index 00000000..6076fd48 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/erpc_config.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2021 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _ERPC_CONFIG_H_ +#define _ERPC_CONFIG_H_ + +/*! + * @addtogroup config + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// Declarations +//////////////////////////////////////////////////////////////////////////////// + +//! @name Threading model options +//@{ +#define ERPC_ALLOCATION_POLICY_DYNAMIC (0U) //!< Dynamic allocation policy +#define ERPC_ALLOCATION_POLICY_STATIC (1U) //!< Static allocation policy + +#define ERPC_THREADS_NONE (0U) //!< No threads. +#define ERPC_THREADS_PTHREADS (1U) //!< POSIX pthreads. +#define ERPC_THREADS_FREERTOS (2U) //!< FreeRTOS. +#define ERPC_THREADS_ZEPHYR (3U) //!< ZEPHYR. +#define ERPC_THREADS_MBED (4U) //!< Mbed OS +#define ERPC_THREADS_WIN32 (5U) //!< WIN32 +#define ERPC_THREADS_THREADX (6U) //!< THREADX + +#define ERPC_NOEXCEPT_DISABLED (0U) //!< Disabling noexcept feature. +#define ERPC_NOEXCEPT_ENABLED (1U) //!< Enabling noexcept feature. + +#define ERPC_NESTED_CALLS_DISABLED (0U) //!< No nested calls support. +#define ERPC_NESTED_CALLS_ENABLED (1U) //!< Nested calls support. + +#define ERPC_NESTED_CALLS_DETECTION_DISABLED (0U) //!< Nested calls detection disabled. +#define ERPC_NESTED_CALLS_DETECTION_ENABLED (1U) //!< Nested calls detection enabled. + +#define ERPC_MESSAGE_LOGGING_DISABLED (0U) //!< Trace functions disabled. +#define ERPC_MESSAGE_LOGGING_ENABLED (1U) //!< Trace functions enabled. + +#define ERPC_TRANSPORT_MU_USE_MCMGR_DISABLED (0U) //!< Do not use MCMGR for MU ISR management. +#define ERPC_TRANSPORT_MU_USE_MCMGR_ENABLED (1U) //!< Use MCMGR for MU ISR management. + +#define ERPC_PRE_POST_ACTION_DISABLED (0U) //!< Pre post shim callbacks functions disabled. +#define ERPC_PRE_POST_ACTION_ENABLED (1U) //!< Pre post shim callback functions enabled. + +#define ERPC_PRE_POST_ACTION_DEFAULT_DISABLED (0U) //!< Pre post shim default callbacks functions disabled. +#define ERPC_PRE_POST_ACTION_DEFAULT_ENABLED (1U) //!< Pre post shim default callback functions enabled. +//@} + +//! @name Configuration options +//@{ + +//! @def ERPC_ALLOCATION_POLICY +//! +//! @brief Choose which allocation policy should be used. +//! +//! Set ERPC_ALLOCATION_POLICY_DYNAMIC if dynamic allocations should be used. +//! Set ERPC_ALLOCATION_POLICY_STATIC if static allocations should be used. +//! +//! Default value is ERPC_ALLOCATION_POLICY_DYNAMIC or in case of FreeRTOS it can be auto-detected if __has_include() is +//! supported by compiler. Uncomment comment bellow to use static allocation policy. In case of static implementation +//! user need consider another values to set (ERPC_CODEC_COUNT, ERPC_MESSAGE_LOGGERS_COUNT, +//! ERPC_CLIENTS_THREADS_AMOUNT). +// #define ERPC_ALLOCATION_POLICY (ERPC_ALLOCATION_POLICY_STATIC) + +//! @def ERPC_CODEC_COUNT +//! +//! @brief Set amount of codecs objects used simultaneously in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. For example if client or server is used in one thread then 1. If both are used in one +//! thread per each then 2, ... Default value 2. +// #define ERPC_CODEC_COUNT (2U) + +//! @def ERPC_MESSAGE_LOGGERS_COUNT +//! +//! @brief Set amount of message loggers objects used simultaneously in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. +//! For example if client or server is used in one thread then 1. If both are used in one thread per each then 2, ... +//! For arbitrated client 1 is enough. +//! Default value 0 (May not be used). +// #define ERPC_MESSAGE_LOGGERS_COUNT (0U) + +//! @def ERPC_CLIENTS_THREADS_AMOUNT +//! +//! @brief Set amount of client threads objects used in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. Default value 1 (Most of current cases). +// #define ERPC_CLIENTS_THREADS_AMOUNT (1U) + +//! @def ERPC_THREADS +//! +//! @brief Select threading model. +//! +//! Set to one of the @c ERPC_THREADS_x macros to specify the threading model used by eRPC. +//! +//! Leave commented out to attempt to auto-detect. Auto-detection works well for pthreads. +//! FreeRTOS can be detected when building with compilers that support __has_include(). +//! Otherwise, the default is no threading. +#define ERPC_THREADS (ERPC_THREADS_NONE) + +//! @def ERPC_DEFAULT_BUFFER_SIZE +//! +//! Uncomment to change the size of buffers allocated by one of MessageBufferFactory. +//! (@ref client_setup and @ref server_setup). The default size is set to 256. +//! For RPMsg transport layer, ERPC_DEFAULT_BUFFER_SIZE must be 2^n - 16. +#define ERPC_DEFAULT_BUFFER_SIZE (4096U) + +//! @def ERPC_DEFAULT_BUFFERS_COUNT +//! +//! Uncomment to change the count of buffers allocated by one of statically allocated messages. +//! Default value is set to 2. +//#define ERPC_DEFAULT_BUFFERS_COUNT (2U) + +//! @def ERPC_NOEXCEPT +//! +//! @brief Disable/enable noexcept support. +//! +//! Uncomment for using noexcept feature. +//#define ERPC_NOEXCEPT (ERPC_NOEXCEPT_ENABLED) + +//! @def ERPC_NESTED_CALLS +//! +//! Default set to ERPC_NESTED_CALLS_DISABLED. Uncomment when callbacks, or other eRPC +//! functions are called from server implementation of another eRPC call. Nested functions +//! need to be marked as @nested in IDL. +//#define ERPC_NESTED_CALLS (ERPC_NESTED_CALLS_ENABLED) + +//! @def ERPC_NESTED_CALLS_DETECTION +//! +//! Default set to ERPC_NESTED_CALLS_DETECTION_ENABLED when NDEBUG macro is presented. +//! This serve for locating nested calls in code. Nested calls are calls where inside eRPC function +//! on server side is called another eRPC function (like callbacks). Code need be a bit changed +//! to support nested calls. See ERPC_NESTED_CALLS macro. +//#define ERPC_NESTED_CALLS_DETECTION (ERPC_NESTED_CALLS_DETECTION_DISABLED) + +//! @def ERPC_MESSAGE_LOGGING +//! +//! Enable eRPC message logging code through the eRPC. Take look into "erpc_message_loggers.h". Can be used for base +//! printing messages, or sending data to another system for data analysis. Default set to +//! ERPC_MESSAGE_LOGGING_DISABLED. +//! +//! Uncomment for using logging feature. +//#define ERPC_MESSAGE_LOGGING (ERPC_MESSAGE_LOGGING_ENABLED) + +//! @def ERPC_TRANSPORT_MU_USE_MCMGR +//! +//! @brief MU transport layer configuration. +//! +//! Set to one of the @c ERPC_TRANSPORT_MU_USE_MCMGR_x macros to configure the MCMGR usage in MU transport layer. +//! +//! MU transport layer could leverage the Multicore Manager (MCMGR) component for Inter-Core +//! interrupts / MU interrupts management or the Inter-Core interrupts can be managed by itself (MUX_IRQHandler +//! overloading). By default, ERPC_TRANSPORT_MU_USE_MCMGR is set to ERPC_TRANSPORT_MU_USE_MCMGR_ENABLED when mcmgr.h +//! is part of the project, otherwise the ERPC_TRANSPORT_MU_USE_MCMGR_DISABLED option is used. This settings can be +//! overwritten from the erpc_config.h by uncommenting the ERPC_TRANSPORT_MU_USE_MCMGR macro definition. Do not forget +//! to add the MCMGR library into your project when ERPC_TRANSPORT_MU_USE_MCMGR_ENABLED option is used! See the +//! erpc_mu_transport.h for additional MU settings. +//#define ERPC_TRANSPORT_MU_USE_MCMGR ERPC_TRANSPORT_MU_USE_MCMGR_DISABLED +//@} + +//! @def ERPC_PRE_POST_ACTION +//! +//! Enable eRPC pre and post callback functions shim code. Take look into "erpc_pre_post_action.h". Can be used for +//! detection of eRPC call freeze, ... Default set to ERPC_PRE_POST_ACTION_DISABLED. +//! +//! Uncomment for using pre post callback feature. +//#define ERPC_PRE_POST_ACTION (ERPC_PRE_POST_ACTION_ENABLED) + +//! @def ERPC_PRE_POST_ACTION_DEFAULT +//! +//! Enable eRPC pre and post default callback functions. Take look into "erpc_setup_extensions.h". Can be used for +//! detection of eRPC call freeze, ... Default set to ERPC_PRE_POST_ACTION_DEFAULT_DISABLED. +//! +//! Uncomment for using pre post default callback feature. +//#define ERPC_PRE_POST_ACTION_DEFAULT (ERPC_PRE_POST_ACTION_DEFAULT_ENABLED) + +/*! @} */ +#endif // _ERPC_CONFIG_H_ +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/examples/zephyr/matrix_multiply_rpmsglite/prj.conf b/examples/zephyr/matrix_multiply_rpmsglite/prj.conf new file mode 100644 index 00000000..0dfa548a --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/prj.conf @@ -0,0 +1,22 @@ +# C++ Language Support +CONFIG_CPP=y +CONFIG_STD_CPP20=y +CONFIG_NEWLIB_LIBC=y +CONFIG_GLIBCXX_LIBCPP=y + +# Compiler +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +# eRPC +CONFIG_ERPC=y +CONFIG_ERPC_TRANSPORT_RPMSG_LITE=y + +# RPMSG Lite +CONFIG_IPM=y +CONFIG_EVENTS=y +CONFIG_PRINTK=y +CONFIG_RPMSGLITE=y +CONFIG_RPMSGLITE_QUEUE=y +CONFIG_RPMSGLITE_NS=y +CONFIG_TIMESLICE_SIZE=1 \ No newline at end of file diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/CMakeLists.txt b/examples/zephyr/matrix_multiply_rpmsglite/remote/CMakeLists.txt new file mode 100644 index 00000000..16ed61d7 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/CMakeLists.txt @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(remote_server) + +message(STATUS "${BOARD} compiles as remote in this sample") + +target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..) + +enable_language(C CXX) + +target_include_directories(app PRIVATE + ${PROJECT_SOURCE_DIR}/.. + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/src/service +) + +target_sources(app PRIVATE + # Main files + ${PROJECT_SOURCE_DIR}/src/main.cpp + ${PROJECT_SOURCE_DIR}/src/erpc_error_handler.cpp + + # Generated shim code + ${PROJECT_SOURCE_DIR}/src/service/c_erpc_matrix_multiply_server.cpp + ${PROJECT_SOURCE_DIR}/src/service/erpc_matrix_multiply_server.cpp + ${PROJECT_SOURCE_DIR}/src/service/erpc_matrix_multiply_interface.cpp +) + +# Also include this directory into rpmsg_lite library because of project specific include rpsmg_config.h +target_include_directories(rpmsg_lite PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..) +# Same for erpc library and erpc_config.h +target_include_directories(erpc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..) \ No newline at end of file diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.conf b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.conf new file mode 100644 index 00000000..b9e2b072 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.conf @@ -0,0 +1,2 @@ +CONFIG_SECOND_CORE_MCUX=y +CONFIG_BUILD_OUTPUT_HEX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.overlay b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.overlay new file mode 100644 index 00000000..e061dcc4 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso54114_m0.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019 Linaro Limited + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /* + * shared memory reserved for the inter-processor communication + */ + zephyr,ipc_shm = &sramx1; + zephyr,ipc = &mailbox0; + }; + + sramx1:memory@4000000{ + compatible = "mmio-sram"; + reg = <0x4000000 0x8000>; + }; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.conf b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.conf new file mode 100644 index 00000000..b9e2b072 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.conf @@ -0,0 +1,2 @@ +CONFIG_SECOND_CORE_MCUX=y +CONFIG_BUILD_OUTPUT_HEX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.overlay b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.overlay new file mode 100644 index 00000000..270eb0e7 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/lpcxpresso55s69_cpu1.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Linaro Limited + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /* + * shared memory reserved for the inter-processor communication + */ + + zephyr,ipc_shm = &sram4duplicate; + zephyr,ipc = &mailbox0; + }; + + /* This is a duplication of sram4, workaround */ + sram4duplicate: memory@20040000 { + compatible = "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(16)>; + }; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.conf b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.conf new file mode 100644 index 00000000..4dfc4a60 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.conf @@ -0,0 +1,3 @@ +CONFIG_BUILD_OUTPUT_INFO_HEADER=y +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.overlay b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.overlay new file mode 100644 index 00000000..83589d7e --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1160_evk_cm4.overlay @@ -0,0 +1,51 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + /* Switch to lpuart2, since primary core uses lpuart1 */ + chosen { + zephyr,flash = &ocram; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; + zephyr,ipc_shm = &ocram2_overlay; + }; + + soc { + /delete-node/ gpt@400f0000; + + /* Replace GPT2 with another GPT kernel timer */ + gpt2_hw_timer:gpt@400f0000 { + compatible = "nxp,gpt-hw-timer"; + reg = <0x400f0000 0x4000>; + interrupts = <120 0>; + status = "okay"; + }; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set + */ + ocram2_overlay: memory@202c0000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; +}; + +/* Enable secondary LPUART */ +&lpuart2 { + status = "okay"; + current-speed = <115200>; +}; + +/* Disable primary GPT timer */ +&gpt_hw_timer { + status = "disabled"; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.conf b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.conf new file mode 100644 index 00000000..4dfc4a60 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.conf @@ -0,0 +1,3 @@ +CONFIG_BUILD_OUTPUT_INFO_HEADER=y +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.overlay b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.overlay new file mode 100644 index 00000000..83589d7e --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evk_cm4.overlay @@ -0,0 +1,51 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + /* Switch to lpuart2, since primary core uses lpuart1 */ + chosen { + zephyr,flash = &ocram; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; + zephyr,ipc_shm = &ocram2_overlay; + }; + + soc { + /delete-node/ gpt@400f0000; + + /* Replace GPT2 with another GPT kernel timer */ + gpt2_hw_timer:gpt@400f0000 { + compatible = "nxp,gpt-hw-timer"; + reg = <0x400f0000 0x4000>; + interrupts = <120 0>; + status = "okay"; + }; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set + */ + ocram2_overlay: memory@202c0000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; +}; + +/* Enable secondary LPUART */ +&lpuart2 { + status = "okay"; + current-speed = <115200>; +}; + +/* Disable primary GPT timer */ +&gpt_hw_timer { + status = "disabled"; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.conf b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.conf new file mode 100644 index 00000000..7b43b448 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.conf @@ -0,0 +1,8 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BUILD_OUTPUT_INFO_HEADER=y +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.overlay b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.overlay new file mode 100644 index 00000000..b9c0439c --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/boards/mimxrt1170_evkb_cm4.overlay @@ -0,0 +1,51 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + /* Switch to lpuart2, since primary core uses lpuart1 */ + chosen { + zephyr,flash = &ocram; + zephyr,console = &lpuart1; + zephyr,shell-uart = &lpuart1; + zephyr,ipc_shm = &ocram2_overlay; + }; + + soc { + /delete-node/ gpt@400f0000; + + /* Replace GPT2 with another GPT kernel timer */ + gpt2_hw_timer:gpt@400f0000 { + compatible = "nxp,gpt-hw-timer"; + reg = <0x400f0000 0x4000>; + interrupts = <120 0>; + status = "okay"; + }; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set + */ + ocram2_overlay: memory@202c0000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; +}; + +/* Enable secondary LPUART */ +&lpuart2 { + status = "okay"; + current-speed = <115200>; +}; + +/* Disable primary GPT timer */ +&gpt_hw_timer { + status = "disabled"; +}; diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/prj.conf b/examples/zephyr/matrix_multiply_rpmsglite/remote/prj.conf new file mode 100644 index 00000000..53365095 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/prj.conf @@ -0,0 +1,24 @@ +# C++ Language Support +CONFIG_CPP=y +CONFIG_STD_CPP20=y +CONFIG_NEWLIB_LIBC=y +CONFIG_GLIBCXX_LIBCPP=y + +# Compiler +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +# eRPC +CONFIG_ERPC=y +CONFIG_ERPC_TRANSPORT_RPMSG_LITE=y + +# RPMSG Lite +CONFIG_IPM=y +CONFIG_EVENTS=y +CONFIG_PRINTK=y +CONFIG_RPMSGLITE=y +CONFIG_RPMSGLITE_QUEUE=y +CONFIG_RPMSGLITE_NS=y +CONFIG_TIMESLICE_SIZE=1 + +CONFIG_STDOUT_CONSOLE=n diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.cpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.cpp new file mode 100644 index 00000000..8be36267 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "erpc_error_handler.h" +#include + +//////////////////////////////////////////////////////////////////////////////// +// Variables +//////////////////////////////////////////////////////////////////////////////// + +extern bool g_erpc_error_occurred; +bool g_erpc_error_occurred = false; + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +void erpc_error_handler(erpc_status_t err, uint32_t functionID) +{ + switch (err) + { + case kErpcStatus_Fail: + printk("\r\nGeneric failure."); + break; + + case kErpcStatus_InvalidArgument: + printk("\r\nArgument is an invalid value."); + break; + + case kErpcStatus_Timeout: + printk("\r\nOperated timed out."); + break; + + case kErpcStatus_InvalidMessageVersion: + printk("\r\nMessage header contains an unknown version."); + break; + + case kErpcStatus_ExpectedReply: + printk("\r\nExpected a reply message but got another message type."); + break; + + case kErpcStatus_CrcCheckFailed: + printk("\r\nMessage is corrupted."); + break; + + case kErpcStatus_BufferOverrun: + printk("\r\nAttempt to read or write past the end of a buffer."); + break; + + case kErpcStatus_UnknownName: + printk("\r\nCould not find host with given name."); + break; + + case kErpcStatus_ConnectionFailure: + printk("\r\nFailed to connect to host."); + break; + + case kErpcStatus_ConnectionClosed: + printk("\r\nConnected closed by peer."); + break; + + case kErpcStatus_MemoryError: + printk("\r\nMemory allocation error."); + break; + + case kErpcStatus_ServerIsDown: + printk("\r\nServer is stopped."); + break; + + case kErpcStatus_InitFailed: + printk("\r\nTransport layer initialization failed."); + break; + + case kErpcStatus_ReceiveFailed: + printk("\r\nFailed to receive data."); + break; + + case kErpcStatus_SendFailed: + printk("\r\nFailed to send data."); + break; + + /* no error occurred */ + case kErpcStatus_Success: + return; + + /* unhandled error */ + default: + printk("\r\nUnhandled error occurred."); + break; + } + + /* When error occurred on client side. */ + if (functionID != 0) + { + printk("Function id '%u'.", (unsigned int)functionID); + } + printk("\r\n"); + + /* error occurred */ + g_erpc_error_occurred = true; +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.h b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.h new file mode 100644 index 00000000..faf32559 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/erpc_error_handler.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _EMBEDDED_RPC__ERROR_HANDLER_H_ +#define _EMBEDDED_RPC__ERROR_HANDLER_H_ + +#include "erpc_common.h" +#include + +/*! + * @addtogroup error_handler + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// API +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +//! @name Error handler +//@{ + +/*! + * @brief This function handles eRPC errors. + * + * This function prints a description of occurred error and sets bool variable g_erpc_error_occurred which is used for + * determining if error occurred in user application on client side. + */ +void erpc_error_handler(erpc_status_t err, uint32_t functionID); + +//@} + +#ifdef __cplusplus +} +#endif + +/*! @} */ +#endif // _EMBEDDED_RPC__ERROR_HANDLER_H_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/main.cpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/main.cpp new file mode 100644 index 00000000..1b88ab8d --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/main.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "rpmsg_lite.h" +#include "erpc_server_setup.h" +#include "erpc_matrix_multiply_common.h" +#include "c_erpc_matrix_multiply_server.h" +#include "erpc_error_handler.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define ERPC_TRANSPORT_RPMSG_LITE_LINK_ID (RL_PLATFORM_IMXRT1160_M7_M4_LINK_ID) + +#define SHM_MEM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) +#define SHM_MEM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +/*! + * @brief erpcMatrixMultiply function implementation. + * + * This is the implementation of the erpcMatrixMultiply function called by the primary core. + * + * @param matrix1 First matrix + * @param matrix2 Second matrix + * @param result_matrix Result matrix + */ +void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) +{ + int32_t i, j, k; + + /* Clear the result matrix */ + for (i = 0; i < matrix_size; ++i) + { + for (j = 0; j < matrix_size; ++j) + { + result_matrix[i][j] = 0; + } + } + + /* Multiply two matrices */ + for (i = 0; i < matrix_size; ++i) + { + for (j = 0; j < matrix_size; ++j) + { + for (k = 0; k < matrix_size; ++k) + { + result_matrix[i][j] += matrix1[i][k] * matrix2[k][j]; + } + } + } +} + +static void SignalReady(void) {} + +/*! + * @brief Main function + */ +int main(void) +{ + uint32_t *shared_memory = (uint32_t *)SHM_MEM_ADDR; + + /* RPMsg-Lite transport layer initialization */ + erpc_transport_t transport; + erpc_server_t server; + + transport = erpc_transport_rpmsg_lite_rtos_remote_init(101U, 100U, (void *)(char *)shared_memory, + ERPC_TRANSPORT_RPMSG_LITE_LINK_ID, SignalReady, NULL); + + /* MessageBufferFactory initialization */ + erpc_mbf_t message_buffer_factory; + message_buffer_factory = erpc_mbf_rpmsg_init(transport); + + /* eRPC server side initialization */ + server = erpc_server_init(transport, message_buffer_factory); + + /* adding the service to the server */ + erpc_service_t service = create_MatrixMultiplyService_service(); + erpc_add_service_to_server(server, service); + + for (;;) + { + /* process message */ + erpc_status_t status = erpc_server_poll(server); + + /* handle error status */ + if (status != (erpc_status_t)kErpcStatus_Success) + { + /* print error description */ + erpc_error_handler(status, 0); + + /* removing the service from the server */ + erpc_remove_service_from_server(server, service); + destroy_MatrixMultiplyService_service(service); + + /* stop erpc server */ + erpc_server_stop(server); + + /* print error description */ + erpc_server_deinit(server); + + /* exit program loop */ + break; + } + + /* do other tasks */ + int32_t i; + for (i = 0; i < 10000; i++) + { + } + } + for (;;) + { + } +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.cpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.cpp new file mode 100644 index 00000000..afb98cb3 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include +#include "c_erpc_matrix_multiply_server.h" +#include "erpc_matrix_multiply_server.hpp" +#include "erpc_manually_constructed.hpp" + +using namespace erpc; +using namespace std; +using namespace erpcShim; + + +class MatrixMultiplyService_server: public MatrixMultiplyService_interface +{ + public: + virtual ~MatrixMultiplyService_server() {}; + + + void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) + { + ::erpcMatrixMultiply(matrix1, matrix2, result_matrix); + } +}; + +ERPC_MANUALLY_CONSTRUCTED_STATIC(MatrixMultiplyService_service, s_MatrixMultiplyService_service); +ERPC_MANUALLY_CONSTRUCTED_STATIC(MatrixMultiplyService_server, s_MatrixMultiplyService_server); + +erpc_service_t create_MatrixMultiplyService_service(void) +{ + erpc_service_t service; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + service = new (nothrow) MatrixMultiplyService_service(new (nothrow)MatrixMultiplyService_server()); +#else + if (s_MatrixMultiplyService_service.isUsed()) + { + service = NULL; + } + else + { + s_MatrixMultiplyService_server.construct(); + s_MatrixMultiplyService_service.construct(s_MatrixMultiplyService_server.get()); + service = s_MatrixMultiplyService_service.get(); + } +#endif + + return service; +} + +void destroy_MatrixMultiplyService_service(erpc_service_t service) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + if (service) + { + delete (MatrixMultiplyService_server *)(((MatrixMultiplyService_service *)service)->getHandler()); + delete (MatrixMultiplyService_service *)service; + } +#else + (void)service; + erpc_assert(service == s_MatrixMultiplyService_service.get()); + s_MatrixMultiplyService_service.destroy(); + s_MatrixMultiplyService_server.destroy(); +#endif +} + diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.h b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.h new file mode 100644 index 00000000..d312e8d3 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/c_erpc_matrix_multiply_server.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_c_erpc_matrix_multiply_server_h_) +#define _c_erpc_matrix_multiply_server_h_ + +#include "erpc_matrix_multiply_common.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef void * erpc_service_t; + +#if !defined(ERPC_FUNCTIONS_DEFINITIONS) +#define ERPC_FUNCTIONS_DEFINITIONS + + +/*! @brief MatrixMultiplyService identifiers */ +enum _MatrixMultiplyService_ids +{ + kMatrixMultiplyService_service_id = 1, + kMatrixMultiplyService_erpcMatrixMultiply_id = 1, +}; + +//! @name MatrixMultiplyService +//@{ +void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix); +//@} + + +#endif // ERPC_FUNCTIONS_DEFINITIONS + +/*! @brief Return MatrixMultiplyService_service service object. */ +erpc_service_t create_MatrixMultiplyService_service(void); + +/*! @brief Destroy MatrixMultiplyService_service service object. */ +void destroy_MatrixMultiplyService_service(erpc_service_t service); + + +#if defined(__cplusplus) +} +#endif + +#endif // _c_erpc_matrix_multiply_server_h_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply.erpc b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply.erpc new file mode 100644 index 00000000..bfcece34 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply.erpc @@ -0,0 +1,24 @@ +//Copyright below will be added into all generated files. +/*! + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +program erpc_matrix_multiply + +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +const int32 matrix_size = 5; + +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +type Matrix = int32[matrix_size][matrix_size]; + +interface MatrixMultiplyService { + erpcMatrixMultiply(in Matrix matrix1, in Matrix matrix2, out Matrix result_matrix) -> void +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.h b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.h new file mode 100644 index 00000000..fdbd0c7a --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_common_h_) +#define _erpc_matrix_multiply_common_h_ + + +#if defined(__cplusplus) +extern "C" +{ +#endif +#include +#include +#include + +#include "erpc_version.h" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +#if !defined(ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY) +#define ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +// Aliases data types declarations +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +typedef int32_t Matrix[5][5]; + +// Constant variable declarations +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +extern const int32_t matrix_size; + +#endif // ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +#if defined(__cplusplus) +} +#endif + +#endif // _erpc_matrix_multiply_common_h_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.hpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.hpp new file mode 100644 index 00000000..d1b16374 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_common.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_common_hpp_) +#define _erpc_matrix_multiply_common_hpp_ + + +#include +#include +#include + +#include "erpc_version.h" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +#if !defined(ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY) +#define ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +// Aliases data types declarations +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +typedef int32_t Matrix[5][5]; + +// Constant variable declarations +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +extern const int32_t matrix_size; + +#endif // ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + + +#endif // _erpc_matrix_multiply_common_hpp_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.cpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.cpp new file mode 100644 index 00000000..e50f033c --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include "erpc_matrix_multiply_interface.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +using namespace std; +using namespace erpcShim; + +MatrixMultiplyService_interface::~MatrixMultiplyService_interface(void) +{ +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.hpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.hpp new file mode 100644 index 00000000..b2be5a90 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_interface.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_interface_hpp_) +#define _erpc_matrix_multiply_interface_hpp_ + +#include "erpc_matrix_multiply_common.hpp" + +namespace erpcShim +{ + + +// Abstract base class for MatrixMultiplyService +class MatrixMultiplyService_interface +{ + public: + static const uint8_t m_serviceId = 1; + static const uint8_t m_erpcMatrixMultiplyId = 1; + + virtual ~MatrixMultiplyService_interface(void); + + virtual void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) = 0; +private: +}; +} // erpcShim + + +#endif // _erpc_matrix_multiply_interface_hpp_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.cpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.cpp new file mode 100644 index 00000000..d6c97a33 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include "erpc_matrix_multiply_server.hpp" +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC +#include +#include "erpc_port.h" +#endif +#include "erpc_manually_constructed.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + +using namespace erpc; +using namespace std; +using namespace erpcShim; + +#if ERPC_NESTED_CALLS_DETECTION +extern bool nestingDetection; +#endif + + + +// Constant variable definitions +#if defined(__MINGW32__) +__declspec( selectany ) +#else +#pragma weak matrix_size +#endif +extern const int32_t matrix_size = 5; + + +MatrixMultiplyService_service::MatrixMultiplyService_service(MatrixMultiplyService_interface *_MatrixMultiplyService_interface) + : erpc::Service(MatrixMultiplyService_interface::m_serviceId) + , m_handler(_MatrixMultiplyService_interface) +{ +} + +MatrixMultiplyService_service::~MatrixMultiplyService_service() +{ +} + +// return service interface handler. +MatrixMultiplyService_interface* MatrixMultiplyService_service::getHandler(void) +{ + return m_handler; +} + +// Call the correct server shim based on method unique ID. +erpc_status_t MatrixMultiplyService_service::handleInvocation(uint32_t methodId, uint32_t sequence, Codec * codec, MessageBufferFactory *messageFactory, Transport * transport) +{ + erpc_status_t erpcStatus; + switch (methodId) + { + case MatrixMultiplyService_interface::m_erpcMatrixMultiplyId: + { + erpcStatus = erpcMatrixMultiply_shim(codec, messageFactory, transport, sequence); + break; + } + + default: + { + erpcStatus = kErpcStatus_InvalidArgument; + break; + } + } + + return erpcStatus; +} + +// Server shim for erpcMatrixMultiply of MatrixMultiplyService interface. +erpc_status_t MatrixMultiplyService_service::erpcMatrixMultiply_shim(Codec * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence) +{ + erpc_status_t err = kErpcStatus_Success; + + Matrix matrix1; + Matrix matrix2; + Matrix result_matrix; + + // startReadMessage() was already called before this shim was invoked. + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->read(matrix1[arrayCount0][arrayCount1]); + } + } + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->read(matrix2[arrayCount0][arrayCount1]); + } + } + + err = codec->getStatus(); + if (err == kErpcStatus_Success) + { + // Invoke the actual served function. +#if ERPC_NESTED_CALLS_DETECTION + nestingDetection = true; +#endif + m_handler->erpcMatrixMultiply(matrix1, matrix2, result_matrix); +#if ERPC_NESTED_CALLS_DETECTION + nestingDetection = false; +#endif + + // preparing MessageBuffer for serializing data + err = messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize()); + } + + if (err == kErpcStatus_Success) + { + // preparing codec for serializing data + codec->reset(transport->reserveHeaderSize()); + + // Build response message. + codec->startWriteMessage(message_type_t::kReplyMessage, MatrixMultiplyService_interface::m_serviceId, MatrixMultiplyService_interface::m_erpcMatrixMultiplyId, sequence); + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->write(result_matrix[arrayCount0][arrayCount1]); + } + } + + err = codec->getStatus(); + } + + return err; +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.hpp b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.hpp new file mode 100644 index 00000000..ad1f17f2 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/remote/src/service/erpc_matrix_multiply_server.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_server_hpp_) +#define _erpc_matrix_multiply_server_hpp_ + +#include "erpc_matrix_multiply_interface.hpp" + +#include "erpc_server.hpp" +#include "erpc_codec.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +namespace erpcShim +{ + +/*! + * @brief Service subclass for MatrixMultiplyService. + */ +class MatrixMultiplyService_service : public erpc::Service +{ +public: + MatrixMultiplyService_service(MatrixMultiplyService_interface *_MatrixMultiplyService_interface); + + virtual ~MatrixMultiplyService_service(); + + /*! @brief return service interface handler. */ + MatrixMultiplyService_interface* getHandler(void); + + /*! @brief Call the correct server shim based on method unique ID. */ + virtual erpc_status_t handleInvocation(uint32_t methodId, uint32_t sequence, erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport); + +private: + MatrixMultiplyService_interface *m_handler; + /*! @brief Server shim for erpcMatrixMultiply of MatrixMultiplyService interface. */ + erpc_status_t erpcMatrixMultiply_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence); +}; + +} // erpcShim + + +#endif // _erpc_matrix_multiply_server_hpp_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/rpmsg_config.h b/examples/zephyr/matrix_multiply_rpmsglite/rpmsg_config.h new file mode 100644 index 00000000..17095866 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/rpmsg_config.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * Copyright (c) 2015 Xilinx, Inc. + * Copyright (c) 2016 Freescale Semiconductor, Inc. + * Copyright 2016-2021 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPMSG_CONFIG_H_ +#define RPMSG_CONFIG_H_ + +/*! + * @addtogroup config + * @{ + * @file + */ + +//! @name Configuration options +//@{ + +//! @def RL_MS_PER_INTERVAL +//! +//! Delay in milliseconds used in non-blocking API functions for polling. +//! The default value is 1. +#define RL_MS_PER_INTERVAL (1) + +//! @def RL_BUFFER_PAYLOAD_SIZE +//! +//! Size of the buffer payload, it must be equal to (240, 496, 1008, ...) +//! [2^n - 16]. Ensure the same value is defined on both sides of rpmsg +//! communication. The default value is 496U. +#define RL_BUFFER_PAYLOAD_SIZE (496U) + +//! @def RL_BUFFER_COUNT +//! +//! Number of the buffers, it must be power of two (2, 4, ...). +//! The default value is 2U. +//! Note this value defines the buffer count for one direction of the rpmsg +//! communication only, i.e. if the default value of 2 is used +//! in rpmsg_config.h files for the master and the remote side, 4 buffers +//! in total are created in the shared memory. +#define RL_BUFFER_COUNT (2U) + +//! @def RL_API_HAS_ZEROCOPY +//! +//! Zero-copy API functions enabled/disabled. +//! The default value is 1 (enabled). +#define RL_API_HAS_ZEROCOPY (1) + +//! @def RL_USE_STATIC_API +//! +//! Static API functions (no dynamic allocation) enabled/disabled. +//! The default value is 0 (static API disabled). +#define RL_USE_STATIC_API (1) + +//! @def RL_CLEAR_USED_BUFFERS +//! +//! Clearing used buffers before returning back to the pool of free buffers +//! enabled/disabled. +//! The default value is 0 (disabled). +#define RL_CLEAR_USED_BUFFERS (0) + +//! @def RL_USE_MCMGR_IPC_ISR_HANDLER +//! +//! When enabled IPC interrupts are managed by the Multicore Manager (IPC +//! interrupts router), when disabled RPMsg-Lite manages IPC interrupts +//! by itself. +//! The default value is 0 (no MCMGR IPC ISR handler used). +#define RL_USE_MCMGR_IPC_ISR_HANDLER (0) + +//! @def RL_USE_ENVIRONMENT_CONTEXT +//! +//! When enabled the environment layer uses its own context. +//! Added for QNX port mainly, but can be used if required. +//! The default value is 0 (no context, saves some RAM). +#define RL_USE_ENVIRONMENT_CONTEXT (0) + +//! @def RL_DEBUG_CHECK_BUFFERS +//! +//! Do not use in RPMsg-Lite to Linux configuration +#define RL_DEBUG_CHECK_BUFFERS (0) +//@} + +#endif /* RPMSG_CONFIG_H_ */ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/sample.yaml b/examples/zephyr/matrix_multiply_rpmsglite/sample.yaml new file mode 100644 index 00000000..5af04190 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/sample.yaml @@ -0,0 +1,3 @@ +sample: + description: eRPC Matrix multiplication + name: eRPC Matrix multiplication diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.cpp b/examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.cpp new file mode 100644 index 00000000..8be36267 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "erpc_error_handler.h" +#include + +//////////////////////////////////////////////////////////////////////////////// +// Variables +//////////////////////////////////////////////////////////////////////////////// + +extern bool g_erpc_error_occurred; +bool g_erpc_error_occurred = false; + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +void erpc_error_handler(erpc_status_t err, uint32_t functionID) +{ + switch (err) + { + case kErpcStatus_Fail: + printk("\r\nGeneric failure."); + break; + + case kErpcStatus_InvalidArgument: + printk("\r\nArgument is an invalid value."); + break; + + case kErpcStatus_Timeout: + printk("\r\nOperated timed out."); + break; + + case kErpcStatus_InvalidMessageVersion: + printk("\r\nMessage header contains an unknown version."); + break; + + case kErpcStatus_ExpectedReply: + printk("\r\nExpected a reply message but got another message type."); + break; + + case kErpcStatus_CrcCheckFailed: + printk("\r\nMessage is corrupted."); + break; + + case kErpcStatus_BufferOverrun: + printk("\r\nAttempt to read or write past the end of a buffer."); + break; + + case kErpcStatus_UnknownName: + printk("\r\nCould not find host with given name."); + break; + + case kErpcStatus_ConnectionFailure: + printk("\r\nFailed to connect to host."); + break; + + case kErpcStatus_ConnectionClosed: + printk("\r\nConnected closed by peer."); + break; + + case kErpcStatus_MemoryError: + printk("\r\nMemory allocation error."); + break; + + case kErpcStatus_ServerIsDown: + printk("\r\nServer is stopped."); + break; + + case kErpcStatus_InitFailed: + printk("\r\nTransport layer initialization failed."); + break; + + case kErpcStatus_ReceiveFailed: + printk("\r\nFailed to receive data."); + break; + + case kErpcStatus_SendFailed: + printk("\r\nFailed to send data."); + break; + + /* no error occurred */ + case kErpcStatus_Success: + return; + + /* unhandled error */ + default: + printk("\r\nUnhandled error occurred."); + break; + } + + /* When error occurred on client side. */ + if (functionID != 0) + { + printk("Function id '%u'.", (unsigned int)functionID); + } + printk("\r\n"); + + /* error occurred */ + g_erpc_error_occurred = true; +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.h b/examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.h new file mode 100644 index 00000000..faf32559 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/erpc_error_handler.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _EMBEDDED_RPC__ERROR_HANDLER_H_ +#define _EMBEDDED_RPC__ERROR_HANDLER_H_ + +#include "erpc_common.h" +#include + +/*! + * @addtogroup error_handler + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// API +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +//! @name Error handler +//@{ + +/*! + * @brief This function handles eRPC errors. + * + * This function prints a description of occurred error and sets bool variable g_erpc_error_occurred which is used for + * determining if error occurred in user application on client side. + */ +void erpc_error_handler(erpc_status_t err, uint32_t functionID); + +//@} + +#ifdef __cplusplus +} +#endif + +/*! @} */ +#endif // _EMBEDDED_RPC__ERROR_HANDLER_H_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/main.cpp b/examples/zephyr/matrix_multiply_rpmsglite/src/main.cpp new file mode 100644 index 00000000..d67d72af --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/main.cpp @@ -0,0 +1,143 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "rpmsg_lite.h" +#include "erpc_client_setup.h" +#include "erpc_matrix_multiply_common.h" +#include "c_erpc_matrix_multiply_client.h" +#include "erpc_error_handler.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define ERPC_TRANSPORT_RPMSG_LITE_LINK_ID (RL_PLATFORM_IMXRT1160_M7_M4_LINK_ID) + +extern char rpmsg_lite_base[]; + +#define MATRIX_ITEM_MAX_VALUE (50) +#define APP_ERPC_READY_EVENT_DATA (1U) + +/******************************************************************************* + * Variables + ******************************************************************************/ +extern bool g_erpc_error_occurred; + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +/*! + * @brief Fill matrices by random values + */ +static void fill_matrices(Matrix matrix1_ptr, Matrix matrix2_ptr) +{ + int32_t a, b; + + /* Fill both matrices by random values */ + for (a = 0; a < matrix_size; ++a) + { + for (b = 0; b < matrix_size; ++b) + { + matrix1_ptr[a][b] = rand() % MATRIX_ITEM_MAX_VALUE; + matrix2_ptr[a][b] = rand() % MATRIX_ITEM_MAX_VALUE; + } + } +} + +/*! + * @brief Printing a matrix to the console + */ +static void print_matrix(Matrix matrix_ptr) +{ + int32_t a, b; + + for (a = 0; a < matrix_size; ++a) + { + for (b = 0; b < matrix_size; ++b) + { + printk("%4i ", matrix_ptr[a][b]); + } + printk("\r\n"); + } +} + +int main(void) +{ + Matrix matrix1 = { 0 }, matrix2 = { 0 }, result_matrix = { 0 }; + + /* RPMsg-Lite transport layer initialization */ + erpc_transport_t transport; + erpc_client_t client; + + transport = erpc_transport_rpmsg_lite_rtos_master_init(100, 101, ERPC_TRANSPORT_RPMSG_LITE_LINK_ID); + + /* MessageBufferFactory initialization */ + erpc_mbf_t message_buffer_factory; + message_buffer_factory = erpc_mbf_rpmsg_init(transport); + + /* eRPC client side initialization */ + client = erpc_client_init(transport, message_buffer_factory); + initMatrixMultiplyService_client(client); + + /* Set default error handler */ + erpc_client_set_error_handler(client, erpc_error_handler); + + /* Fill both matrices by random values */ + fill_matrices(matrix1, matrix2); + + /* Print both matrices on the console */ + printk("\r\nMatrix #1"); + printk("\r\n=========\r\n"); + print_matrix(matrix1); + + printk("\r\nMatrix #2"); + printk("\r\n=========\r\n"); + print_matrix(matrix2); + + for (;;) + { + printk("\r\neRPC request is sent to the server\r\n"); + + erpcMatrixMultiply(matrix1, matrix2, result_matrix); + + /* Check if some error occurred in eRPC */ + if (g_erpc_error_occurred) + { + /* Exit program loop */ + break; + } + + printk("\r\nResult matrix"); + printk("\r\n=============\r\n"); + print_matrix(result_matrix); + + env_sleep_msec(1000); + + /* Wait for 200ms to eliminate the button glitch */ + env_sleep_msec(200); + + /* Fill both matrices by random values */ + fill_matrices(matrix1, matrix2); + + /* Print both matrices on the console */ + printk("\r\nMatrix #1"); + printk("\r\n=========\r\n"); + print_matrix(matrix1); + + printk("\r\nMatrix #2"); + printk("\r\n=========\r\n"); + print_matrix(matrix2); + } + for (;;) + { + } +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.cpp b/examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.cpp new file mode 100644 index 00000000..af77c961 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include "c_erpc_matrix_multiply_client.h" +#include "erpc_matrix_multiply_client.hpp" +#include "erpc_manually_constructed.hpp" + +using namespace erpc; +using namespace std; +using namespace erpcShim; + + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC +MatrixMultiplyService_client *s_MatrixMultiplyService_client = nullptr; +#else +ERPC_MANUALLY_CONSTRUCTED_STATIC(MatrixMultiplyService_client, s_MatrixMultiplyService_client); +#endif + +void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) +{ + s_MatrixMultiplyService_client->erpcMatrixMultiply(matrix1, matrix2, result_matrix); +} + +void initMatrixMultiplyService_client(erpc_client_t client) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + erpc_assert(s_MatrixMultiplyService_client == nullptr); + s_MatrixMultiplyService_client = new MatrixMultiplyService_client(reinterpret_cast(client)); +#else + erpc_assert(!s_MatrixMultiplyService_client.isUsed()); + s_MatrixMultiplyService_client.construct(reinterpret_cast(client)); +#endif +} + +void deinitMatrixMultiplyService_client(void) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + if (s_MatrixMultiplyService_client != nullptr) + { + delete s_MatrixMultiplyService_client; + s_MatrixMultiplyService_client = nullptr; + } +#else + s_MatrixMultiplyService_client.destroy(); +#endif +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.h b/examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.h new file mode 100644 index 00000000..8966a5c4 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/c_erpc_matrix_multiply_client.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_c_erpc_matrix_multiply_client_h_) +#define _c_erpc_matrix_multiply_client_h_ + +#include "erpc_matrix_multiply_common.h" +#include "erpc_client_manager.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if !defined(ERPC_FUNCTIONS_DEFINITIONS) +#define ERPC_FUNCTIONS_DEFINITIONS + + +/*! @brief MatrixMultiplyService identifiers */ +enum _MatrixMultiplyService_ids +{ + kMatrixMultiplyService_service_id = 1, + kMatrixMultiplyService_erpcMatrixMultiply_id = 1, +}; + +//! @name MatrixMultiplyService +//@{ +void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix); +//@} + +#endif // ERPC_FUNCTIONS_DEFINITIONS + +void initMatrixMultiplyService_client(erpc_client_t client); + +void deinitMatrixMultiplyService_client(void); + +#if defined(__cplusplus) +} +#endif + +#endif // _c_erpc_matrix_multiply_client_h_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply.erpc b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply.erpc new file mode 100644 index 00000000..bfcece34 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply.erpc @@ -0,0 +1,24 @@ +//Copyright below will be added into all generated files. +/*! + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +program erpc_matrix_multiply + +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +const int32 matrix_size = 5; + +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +type Matrix = int32[matrix_size][matrix_size]; + +interface MatrixMultiplyService { + erpcMatrixMultiply(in Matrix matrix1, in Matrix matrix2, out Matrix result_matrix) -> void +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.cpp b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.cpp new file mode 100644 index 00000000..329c4b43 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC +#include "erpc_port.h" +#endif +#include "erpc_codec.hpp" +#include "erpc_matrix_multiply_client.hpp" +#include "erpc_manually_constructed.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + +using namespace erpc; +using namespace std; +using namespace erpcShim; + + +// Constant variable definitions +#if defined(__MINGW32__) +__declspec( selectany ) +#else +#pragma weak matrix_size +#endif +extern const int32_t matrix_size = 5; + + + +MatrixMultiplyService_client::MatrixMultiplyService_client(ClientManager *manager) +:m_clientManager(manager) +{ +} + +MatrixMultiplyService_client::~MatrixMultiplyService_client() +{ +} + +// MatrixMultiplyService interface erpcMatrixMultiply function client shim. +void MatrixMultiplyService_client::erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) +{ + erpc_status_t err = kErpcStatus_Success; + + +#if ERPC_PRE_POST_ACTION + pre_post_action_cb preCB = m_clientManager->getPreCB(); + if (preCB) + { + preCB(); + } +#endif + + // Get a new request. + RequestContext request = m_clientManager->createRequest(false); + + // Encode the request. + Codec * codec = request.getCodec(); + + if (codec == NULL) + { + err = kErpcStatus_MemoryError; + } + else + { + codec->startWriteMessage(message_type_t::kInvocationMessage, m_serviceId, m_erpcMatrixMultiplyId, request.getSequence()); + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->write(matrix1[arrayCount0][arrayCount1]); + } + } + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->write(matrix2[arrayCount0][arrayCount1]); + } + } + + // Send message to server + // Codec status is checked inside this function. + m_clientManager->performRequest(request); + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->read(result_matrix[arrayCount0][arrayCount1]); + } + } + + err = codec->getStatus(); + } + + // Dispose of the request. + m_clientManager->releaseRequest(request); + + // Invoke error handler callback function + m_clientManager->callErrorHandler(err, m_erpcMatrixMultiplyId); + +#if ERPC_PRE_POST_ACTION + pre_post_action_cb postCB = m_clientManager->getPostCB(); + if (postCB) + { + postCB(); + } +#endif + + + return; +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.hpp b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.hpp new file mode 100644 index 00000000..b8b81101 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_client.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_client_hpp_) +#define _erpc_matrix_multiply_client_hpp_ + +#include "erpc_matrix_multiply_interface.hpp" + +#include "erpc_client_manager.h" + +namespace erpcShim +{ + +class MatrixMultiplyService_client: public MatrixMultiplyService_interface +{ + public: + MatrixMultiplyService_client(erpc::ClientManager *manager); + + virtual ~MatrixMultiplyService_client(); + + virtual void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix); + + protected: + erpc::ClientManager *m_clientManager; +}; + +} // erpcShim + + +#endif // _erpc_matrix_multiply_client_hpp_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.h b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.h new file mode 100644 index 00000000..fdbd0c7a --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_common_h_) +#define _erpc_matrix_multiply_common_h_ + + +#if defined(__cplusplus) +extern "C" +{ +#endif +#include +#include +#include + +#include "erpc_version.h" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +#if !defined(ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY) +#define ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +// Aliases data types declarations +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +typedef int32_t Matrix[5][5]; + +// Constant variable declarations +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +extern const int32_t matrix_size; + +#endif // ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +#if defined(__cplusplus) +} +#endif + +#endif // _erpc_matrix_multiply_common_h_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.hpp b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.hpp new file mode 100644 index 00000000..d1b16374 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_common.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_common_hpp_) +#define _erpc_matrix_multiply_common_hpp_ + + +#include +#include +#include + +#include "erpc_version.h" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +#if !defined(ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY) +#define ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +// Aliases data types declarations +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +typedef int32_t Matrix[5][5]; + +// Constant variable declarations +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +extern const int32_t matrix_size; + +#endif // ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + + +#endif // _erpc_matrix_multiply_common_hpp_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.cpp b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.cpp new file mode 100644 index 00000000..e50f033c --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include "erpc_matrix_multiply_interface.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +using namespace std; +using namespace erpcShim; + +MatrixMultiplyService_interface::~MatrixMultiplyService_interface(void) +{ +} diff --git a/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.hpp b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.hpp new file mode 100644 index 00000000..b2be5a90 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/src/service/erpc_matrix_multiply_interface.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_interface_hpp_) +#define _erpc_matrix_multiply_interface_hpp_ + +#include "erpc_matrix_multiply_common.hpp" + +namespace erpcShim +{ + + +// Abstract base class for MatrixMultiplyService +class MatrixMultiplyService_interface +{ + public: + static const uint8_t m_serviceId = 1; + static const uint8_t m_erpcMatrixMultiplyId = 1; + + virtual ~MatrixMultiplyService_interface(void); + + virtual void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) = 0; +private: +}; +} // erpcShim + + +#endif // _erpc_matrix_multiply_interface_hpp_ diff --git a/examples/zephyr/matrix_multiply_rpmsglite/sysbuild.cmake b/examples/zephyr/matrix_multiply_rpmsglite/sysbuild.cmake new file mode 100644 index 00000000..255b8358 --- /dev/null +++ b/examples/zephyr/matrix_multiply_rpmsglite/sysbuild.cmake @@ -0,0 +1,21 @@ +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +# Add external project +ExternalZephyrProject_Add( + APPLICATION remote_server + SOURCE_DIR ${APP_DIR}/remote + BOARD ${SB_CONFIG_RPMSG_LITE_REMOTE_BOARD} + ) + +# Add dependencies so that the remote sample will be built first +# This is required because some primary cores need information from the +# remote core's build, such as the output image's LMA +add_dependencies(matrix_multiply_rpmsglite remote_server) +sysbuild_add_dependencies(CONFIGURE matrix_multiply_rpmsglite remote_server) + +if(SB_CONFIG_BOOTLOADER_MCUBOOT) + # Make sure MCUboot is flashed first + sysbuild_add_dependencies(FLASH matrix_multiply_rpmsglite mcuboot) +endif() diff --git a/examples/zephyr/matrix_multiply_uart/CMakeLists.txt b/examples/zephyr/matrix_multiply_uart/CMakeLists.txt new file mode 100644 index 00000000..eef5200e --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/CMakeLists.txt @@ -0,0 +1,24 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(erpc_matrix_multiply_example C CXX) + +target_sources(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/erpc_error_handler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/service/c_erpc_matrix_multiply_server.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/service/erpc_matrix_multiply_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/service/erpc_matrix_multiply_server.cpp + ) + +target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/service) + +target_include_directories(erpc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) diff --git a/examples/zephyr/matrix_multiply_uart/README.rst b/examples/zephyr/matrix_multiply_uart/README.rst new file mode 100644 index 00000000..33a99787 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/README.rst @@ -0,0 +1,106 @@ +.. _matrix_multiply_uart: + +Matrix multiply UART +########### + +This example demonstrates usage of eRPC between PC and board using the Zephyr OS and the UART +transport layer. Board acts like a server and the PC as client. When client starts, it generates +two random matrixes and sends them to server. Server then performs matrix multiplication and sends +result data back to client. Result matrix is then printed on the PC side. + +eRPC documentation +eRPC specific files are stored in: middleware\multicore\erpc +eRPC documentation is stored in: middleware\multicore\erpc\doc +eRPC is open-source project stored on github: https://github.com/EmbeddedRPC/erpc +eRPC documentation can be also found in: http://embeddedrpc.github.io + +PC Side Setup (Python) +1. Make sure you have Python installed on your PC +2. Install serial module by executing following command in command line: "python -m pip install pyserial" +3. Install eRPC module to Python by executing setup.py located in: middleware\multicore\erpc\erpc_python - "python setup.py install" + +Usage of run_uart.py +usage: run_uart.py [-h] [-c] [-s] [-p PORT] [-b BD] + +eRPC Matrix Multiply example + +optional arguments: + -h, --help show this help message and exit + -c, --client Run client + -s, --server Run server + -p PORT, --port PORT Serial port + -b BD, --bd BD Baud rate (default value is 115200) + +Either server or client has to be selected to run + +Example: +To run PC side as a client with a board connected as a server to COM3 execute: +"run_uart.py --client --port COM3" + + +Building and Running +******************** + +This application can be built and executed as follows: + + +Building the application for mimxrt1060_evk +*********************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/matrix_multiply_uart + :board: mimxrt1060_evk + :goals: debug + +Building the application for mimxrt1170_evkb_cm7 +*********************************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/matrix_multiply_uart + :board: mimxrt1170_evkb_cm7 + :goals: debug + +Sample Output +============= + +Open a serial terminal (minicom, putty, etc.) and connect the board with the +following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and the following message will appear on the corresponding +serial port: + +.. code-block:: console + eRPC Matrix Multiply TCP example + Transport: serial=COM14 baudrate=115200 + Matrix #1 + ========= + 8 2 1 3 1 + 9 4 7 6 0 + 3 8 5 9 8 + 2 8 7 3 7 + 7 8 3 6 3 + + Matrix #1 + ========= + 1 9 5 7 8 + 2 4 8 3 9 + 9 1 8 3 0 + 7 6 3 4 2 + 4 4 8 7 8 + + eRPC request is sent to the server + + Matrix result + ========= + 46 103 81 84 96 + 122 140 151 120 120 + 159 150 210 152 178 + 130 103 195 120 150 + 104 146 165 127 164 + + Press Enter to initiate the next matrix multiplication or 'q' to quit diff --git a/examples/zephyr/matrix_multiply_uart/prj.conf b/examples/zephyr/matrix_multiply_uart/prj.conf new file mode 100644 index 00000000..69998ba5 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/prj.conf @@ -0,0 +1,17 @@ +# C++ Language Support +CONFIG_CPP=y +CONFIG_STD_CPP20=y +CONFIG_GLIBCXX_LIBCPP=y +CONFIG_NEWLIB_LIBC=y + +# eRPC +CONFIG_ERPC=y +CONFIG_ERPC_TRANSPORT_UART=y + +# UART +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n + +# Compiler +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_HEAP_MEM_POOL_SIZE=8192 diff --git a/examples/zephyr/matrix_multiply_uart/sample.yaml b/examples/zephyr/matrix_multiply_uart/sample.yaml new file mode 100644 index 00000000..5af04190 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/sample.yaml @@ -0,0 +1,3 @@ +sample: + description: eRPC Matrix multiplication + name: eRPC Matrix multiplication diff --git a/examples/zephyr/matrix_multiply_uart/src/erpc_config.h b/examples/zephyr/matrix_multiply_uart/src/erpc_config.h new file mode 100644 index 00000000..6076fd48 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/erpc_config.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2021 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _ERPC_CONFIG_H_ +#define _ERPC_CONFIG_H_ + +/*! + * @addtogroup config + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// Declarations +//////////////////////////////////////////////////////////////////////////////// + +//! @name Threading model options +//@{ +#define ERPC_ALLOCATION_POLICY_DYNAMIC (0U) //!< Dynamic allocation policy +#define ERPC_ALLOCATION_POLICY_STATIC (1U) //!< Static allocation policy + +#define ERPC_THREADS_NONE (0U) //!< No threads. +#define ERPC_THREADS_PTHREADS (1U) //!< POSIX pthreads. +#define ERPC_THREADS_FREERTOS (2U) //!< FreeRTOS. +#define ERPC_THREADS_ZEPHYR (3U) //!< ZEPHYR. +#define ERPC_THREADS_MBED (4U) //!< Mbed OS +#define ERPC_THREADS_WIN32 (5U) //!< WIN32 +#define ERPC_THREADS_THREADX (6U) //!< THREADX + +#define ERPC_NOEXCEPT_DISABLED (0U) //!< Disabling noexcept feature. +#define ERPC_NOEXCEPT_ENABLED (1U) //!< Enabling noexcept feature. + +#define ERPC_NESTED_CALLS_DISABLED (0U) //!< No nested calls support. +#define ERPC_NESTED_CALLS_ENABLED (1U) //!< Nested calls support. + +#define ERPC_NESTED_CALLS_DETECTION_DISABLED (0U) //!< Nested calls detection disabled. +#define ERPC_NESTED_CALLS_DETECTION_ENABLED (1U) //!< Nested calls detection enabled. + +#define ERPC_MESSAGE_LOGGING_DISABLED (0U) //!< Trace functions disabled. +#define ERPC_MESSAGE_LOGGING_ENABLED (1U) //!< Trace functions enabled. + +#define ERPC_TRANSPORT_MU_USE_MCMGR_DISABLED (0U) //!< Do not use MCMGR for MU ISR management. +#define ERPC_TRANSPORT_MU_USE_MCMGR_ENABLED (1U) //!< Use MCMGR for MU ISR management. + +#define ERPC_PRE_POST_ACTION_DISABLED (0U) //!< Pre post shim callbacks functions disabled. +#define ERPC_PRE_POST_ACTION_ENABLED (1U) //!< Pre post shim callback functions enabled. + +#define ERPC_PRE_POST_ACTION_DEFAULT_DISABLED (0U) //!< Pre post shim default callbacks functions disabled. +#define ERPC_PRE_POST_ACTION_DEFAULT_ENABLED (1U) //!< Pre post shim default callback functions enabled. +//@} + +//! @name Configuration options +//@{ + +//! @def ERPC_ALLOCATION_POLICY +//! +//! @brief Choose which allocation policy should be used. +//! +//! Set ERPC_ALLOCATION_POLICY_DYNAMIC if dynamic allocations should be used. +//! Set ERPC_ALLOCATION_POLICY_STATIC if static allocations should be used. +//! +//! Default value is ERPC_ALLOCATION_POLICY_DYNAMIC or in case of FreeRTOS it can be auto-detected if __has_include() is +//! supported by compiler. Uncomment comment bellow to use static allocation policy. In case of static implementation +//! user need consider another values to set (ERPC_CODEC_COUNT, ERPC_MESSAGE_LOGGERS_COUNT, +//! ERPC_CLIENTS_THREADS_AMOUNT). +// #define ERPC_ALLOCATION_POLICY (ERPC_ALLOCATION_POLICY_STATIC) + +//! @def ERPC_CODEC_COUNT +//! +//! @brief Set amount of codecs objects used simultaneously in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. For example if client or server is used in one thread then 1. If both are used in one +//! thread per each then 2, ... Default value 2. +// #define ERPC_CODEC_COUNT (2U) + +//! @def ERPC_MESSAGE_LOGGERS_COUNT +//! +//! @brief Set amount of message loggers objects used simultaneously in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. +//! For example if client or server is used in one thread then 1. If both are used in one thread per each then 2, ... +//! For arbitrated client 1 is enough. +//! Default value 0 (May not be used). +// #define ERPC_MESSAGE_LOGGERS_COUNT (0U) + +//! @def ERPC_CLIENTS_THREADS_AMOUNT +//! +//! @brief Set amount of client threads objects used in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. Default value 1 (Most of current cases). +// #define ERPC_CLIENTS_THREADS_AMOUNT (1U) + +//! @def ERPC_THREADS +//! +//! @brief Select threading model. +//! +//! Set to one of the @c ERPC_THREADS_x macros to specify the threading model used by eRPC. +//! +//! Leave commented out to attempt to auto-detect. Auto-detection works well for pthreads. +//! FreeRTOS can be detected when building with compilers that support __has_include(). +//! Otherwise, the default is no threading. +#define ERPC_THREADS (ERPC_THREADS_NONE) + +//! @def ERPC_DEFAULT_BUFFER_SIZE +//! +//! Uncomment to change the size of buffers allocated by one of MessageBufferFactory. +//! (@ref client_setup and @ref server_setup). The default size is set to 256. +//! For RPMsg transport layer, ERPC_DEFAULT_BUFFER_SIZE must be 2^n - 16. +#define ERPC_DEFAULT_BUFFER_SIZE (4096U) + +//! @def ERPC_DEFAULT_BUFFERS_COUNT +//! +//! Uncomment to change the count of buffers allocated by one of statically allocated messages. +//! Default value is set to 2. +//#define ERPC_DEFAULT_BUFFERS_COUNT (2U) + +//! @def ERPC_NOEXCEPT +//! +//! @brief Disable/enable noexcept support. +//! +//! Uncomment for using noexcept feature. +//#define ERPC_NOEXCEPT (ERPC_NOEXCEPT_ENABLED) + +//! @def ERPC_NESTED_CALLS +//! +//! Default set to ERPC_NESTED_CALLS_DISABLED. Uncomment when callbacks, or other eRPC +//! functions are called from server implementation of another eRPC call. Nested functions +//! need to be marked as @nested in IDL. +//#define ERPC_NESTED_CALLS (ERPC_NESTED_CALLS_ENABLED) + +//! @def ERPC_NESTED_CALLS_DETECTION +//! +//! Default set to ERPC_NESTED_CALLS_DETECTION_ENABLED when NDEBUG macro is presented. +//! This serve for locating nested calls in code. Nested calls are calls where inside eRPC function +//! on server side is called another eRPC function (like callbacks). Code need be a bit changed +//! to support nested calls. See ERPC_NESTED_CALLS macro. +//#define ERPC_NESTED_CALLS_DETECTION (ERPC_NESTED_CALLS_DETECTION_DISABLED) + +//! @def ERPC_MESSAGE_LOGGING +//! +//! Enable eRPC message logging code through the eRPC. Take look into "erpc_message_loggers.h". Can be used for base +//! printing messages, or sending data to another system for data analysis. Default set to +//! ERPC_MESSAGE_LOGGING_DISABLED. +//! +//! Uncomment for using logging feature. +//#define ERPC_MESSAGE_LOGGING (ERPC_MESSAGE_LOGGING_ENABLED) + +//! @def ERPC_TRANSPORT_MU_USE_MCMGR +//! +//! @brief MU transport layer configuration. +//! +//! Set to one of the @c ERPC_TRANSPORT_MU_USE_MCMGR_x macros to configure the MCMGR usage in MU transport layer. +//! +//! MU transport layer could leverage the Multicore Manager (MCMGR) component for Inter-Core +//! interrupts / MU interrupts management or the Inter-Core interrupts can be managed by itself (MUX_IRQHandler +//! overloading). By default, ERPC_TRANSPORT_MU_USE_MCMGR is set to ERPC_TRANSPORT_MU_USE_MCMGR_ENABLED when mcmgr.h +//! is part of the project, otherwise the ERPC_TRANSPORT_MU_USE_MCMGR_DISABLED option is used. This settings can be +//! overwritten from the erpc_config.h by uncommenting the ERPC_TRANSPORT_MU_USE_MCMGR macro definition. Do not forget +//! to add the MCMGR library into your project when ERPC_TRANSPORT_MU_USE_MCMGR_ENABLED option is used! See the +//! erpc_mu_transport.h for additional MU settings. +//#define ERPC_TRANSPORT_MU_USE_MCMGR ERPC_TRANSPORT_MU_USE_MCMGR_DISABLED +//@} + +//! @def ERPC_PRE_POST_ACTION +//! +//! Enable eRPC pre and post callback functions shim code. Take look into "erpc_pre_post_action.h". Can be used for +//! detection of eRPC call freeze, ... Default set to ERPC_PRE_POST_ACTION_DISABLED. +//! +//! Uncomment for using pre post callback feature. +//#define ERPC_PRE_POST_ACTION (ERPC_PRE_POST_ACTION_ENABLED) + +//! @def ERPC_PRE_POST_ACTION_DEFAULT +//! +//! Enable eRPC pre and post default callback functions. Take look into "erpc_setup_extensions.h". Can be used for +//! detection of eRPC call freeze, ... Default set to ERPC_PRE_POST_ACTION_DEFAULT_DISABLED. +//! +//! Uncomment for using pre post default callback feature. +//#define ERPC_PRE_POST_ACTION_DEFAULT (ERPC_PRE_POST_ACTION_DEFAULT_ENABLED) + +/*! @} */ +#endif // _ERPC_CONFIG_H_ +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.cpp b/examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.cpp new file mode 100644 index 00000000..8be36267 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "erpc_error_handler.h" +#include + +//////////////////////////////////////////////////////////////////////////////// +// Variables +//////////////////////////////////////////////////////////////////////////////// + +extern bool g_erpc_error_occurred; +bool g_erpc_error_occurred = false; + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +void erpc_error_handler(erpc_status_t err, uint32_t functionID) +{ + switch (err) + { + case kErpcStatus_Fail: + printk("\r\nGeneric failure."); + break; + + case kErpcStatus_InvalidArgument: + printk("\r\nArgument is an invalid value."); + break; + + case kErpcStatus_Timeout: + printk("\r\nOperated timed out."); + break; + + case kErpcStatus_InvalidMessageVersion: + printk("\r\nMessage header contains an unknown version."); + break; + + case kErpcStatus_ExpectedReply: + printk("\r\nExpected a reply message but got another message type."); + break; + + case kErpcStatus_CrcCheckFailed: + printk("\r\nMessage is corrupted."); + break; + + case kErpcStatus_BufferOverrun: + printk("\r\nAttempt to read or write past the end of a buffer."); + break; + + case kErpcStatus_UnknownName: + printk("\r\nCould not find host with given name."); + break; + + case kErpcStatus_ConnectionFailure: + printk("\r\nFailed to connect to host."); + break; + + case kErpcStatus_ConnectionClosed: + printk("\r\nConnected closed by peer."); + break; + + case kErpcStatus_MemoryError: + printk("\r\nMemory allocation error."); + break; + + case kErpcStatus_ServerIsDown: + printk("\r\nServer is stopped."); + break; + + case kErpcStatus_InitFailed: + printk("\r\nTransport layer initialization failed."); + break; + + case kErpcStatus_ReceiveFailed: + printk("\r\nFailed to receive data."); + break; + + case kErpcStatus_SendFailed: + printk("\r\nFailed to send data."); + break; + + /* no error occurred */ + case kErpcStatus_Success: + return; + + /* unhandled error */ + default: + printk("\r\nUnhandled error occurred."); + break; + } + + /* When error occurred on client side. */ + if (functionID != 0) + { + printk("Function id '%u'.", (unsigned int)functionID); + } + printk("\r\n"); + + /* error occurred */ + g_erpc_error_occurred = true; +} diff --git a/examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.h b/examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.h new file mode 100644 index 00000000..faf32559 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/erpc_error_handler.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _EMBEDDED_RPC__ERROR_HANDLER_H_ +#define _EMBEDDED_RPC__ERROR_HANDLER_H_ + +#include "erpc_common.h" +#include + +/*! + * @addtogroup error_handler + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// API +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +//! @name Error handler +//@{ + +/*! + * @brief This function handles eRPC errors. + * + * This function prints a description of occurred error and sets bool variable g_erpc_error_occurred which is used for + * determining if error occurred in user application on client side. + */ +void erpc_error_handler(erpc_status_t err, uint32_t functionID); + +//@} + +#ifdef __cplusplus +} +#endif + +/*! @} */ +#endif // _EMBEDDED_RPC__ERROR_HANDLER_H_ diff --git a/examples/zephyr/matrix_multiply_uart/src/main.cpp b/examples/zephyr/matrix_multiply_uart/src/main.cpp new file mode 100644 index 00000000..be006b92 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/main.cpp @@ -0,0 +1,130 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "erpc_server_setup.h" +#include "c_erpc_matrix_multiply_server.h" +#include "erpc_matrix_multiply_common.h" +#include "erpc_error_handler.h" +#include "erpc_uart_zephyr_transport.hpp" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define UART_DEVICE_NODE DT_CHOSEN(zephyr_console) + +/******************************************************************************* + * Variables + ******************************************************************************/ +static const struct device *const uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE); +erpc_server_t server; + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +/*! + * @brief erpcMatrixMultiply function implementation. + * + * This is the implementation of the erpcMatrixMultiply function called by the primary core. + * + * @param matrix1 First matrix + * @param matrix2 Second matrix + * @param result_matrix Result matrix + */ +void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) +{ + int32_t i, j, k; + + /* Clear the result matrix */ + for (i = 0; i < matrix_size; ++i) + { + for (j = 0; j < matrix_size; ++j) + { + result_matrix[i][j] = 0; + } + } + + /* Multiply two matrices */ + for (i = 0; i < matrix_size; ++i) + { + for (j = 0; j < matrix_size; ++j) + { + for (k = 0; k < matrix_size; ++k) + { + result_matrix[i][j] += matrix1[i][k] * matrix2[k][j]; + } + } + } +} + +int main(void) +{ + if (!device_is_ready(uart_dev)) + { + printk("UART device not found!"); + return -1; + } + + /* UART transport layer initialization */ + erpc_transport_t transport; + + transport = erpc_transport_zephyr_uart_init((void *)uart_dev); + + /* MessageBufferFactory initialization */ + erpc_mbf_t message_buffer_factory; + message_buffer_factory = erpc_mbf_dynamic_init(); + + /* eRPC server side initialization */ + server = erpc_server_init(transport, message_buffer_factory); + + /* adding the service to the server */ + erpc_service_t service = create_MatrixMultiplyService_service(); + erpc_add_service_to_server(server, service); + + for (;;) + { + /* process message */ + erpc_status_t status = erpc_server_poll(server); + + /* handle error status */ + if (status != (erpc_status_t)kErpcStatus_Success) + { + /* print error description */ + erpc_error_handler(status, 0); + + /* removing the service from the server */ + erpc_remove_service_from_server(server, service); + destroy_MatrixMultiplyService_service(service); + + /* stop erpc server */ + erpc_server_stop(server); + + /* print error description */ + erpc_server_deinit(server); + + /* exit program loop */ + break; + } + + /* do other tasks */ + int32_t i; + for (i = 0; i < 10000; i++) + { + } + } + + for (;;) + { + } +} diff --git a/examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.cpp b/examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.cpp new file mode 100644 index 00000000..afb98cb3 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include +#include "c_erpc_matrix_multiply_server.h" +#include "erpc_matrix_multiply_server.hpp" +#include "erpc_manually_constructed.hpp" + +using namespace erpc; +using namespace std; +using namespace erpcShim; + + +class MatrixMultiplyService_server: public MatrixMultiplyService_interface +{ + public: + virtual ~MatrixMultiplyService_server() {}; + + + void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) + { + ::erpcMatrixMultiply(matrix1, matrix2, result_matrix); + } +}; + +ERPC_MANUALLY_CONSTRUCTED_STATIC(MatrixMultiplyService_service, s_MatrixMultiplyService_service); +ERPC_MANUALLY_CONSTRUCTED_STATIC(MatrixMultiplyService_server, s_MatrixMultiplyService_server); + +erpc_service_t create_MatrixMultiplyService_service(void) +{ + erpc_service_t service; + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + service = new (nothrow) MatrixMultiplyService_service(new (nothrow)MatrixMultiplyService_server()); +#else + if (s_MatrixMultiplyService_service.isUsed()) + { + service = NULL; + } + else + { + s_MatrixMultiplyService_server.construct(); + s_MatrixMultiplyService_service.construct(s_MatrixMultiplyService_server.get()); + service = s_MatrixMultiplyService_service.get(); + } +#endif + + return service; +} + +void destroy_MatrixMultiplyService_service(erpc_service_t service) +{ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC + if (service) + { + delete (MatrixMultiplyService_server *)(((MatrixMultiplyService_service *)service)->getHandler()); + delete (MatrixMultiplyService_service *)service; + } +#else + (void)service; + erpc_assert(service == s_MatrixMultiplyService_service.get()); + s_MatrixMultiplyService_service.destroy(); + s_MatrixMultiplyService_server.destroy(); +#endif +} + diff --git a/examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.h b/examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.h new file mode 100644 index 00000000..d312e8d3 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/c_erpc_matrix_multiply_server.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_c_erpc_matrix_multiply_server_h_) +#define _c_erpc_matrix_multiply_server_h_ + +#include "erpc_matrix_multiply_common.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef void * erpc_service_t; + +#if !defined(ERPC_FUNCTIONS_DEFINITIONS) +#define ERPC_FUNCTIONS_DEFINITIONS + + +/*! @brief MatrixMultiplyService identifiers */ +enum _MatrixMultiplyService_ids +{ + kMatrixMultiplyService_service_id = 1, + kMatrixMultiplyService_erpcMatrixMultiply_id = 1, +}; + +//! @name MatrixMultiplyService +//@{ +void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix); +//@} + + +#endif // ERPC_FUNCTIONS_DEFINITIONS + +/*! @brief Return MatrixMultiplyService_service service object. */ +erpc_service_t create_MatrixMultiplyService_service(void); + +/*! @brief Destroy MatrixMultiplyService_service service object. */ +void destroy_MatrixMultiplyService_service(erpc_service_t service); + + +#if defined(__cplusplus) +} +#endif + +#endif // _c_erpc_matrix_multiply_server_h_ diff --git a/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply.erpc b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply.erpc new file mode 100644 index 00000000..bfcece34 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply.erpc @@ -0,0 +1,24 @@ +//Copyright below will be added into all generated files. +/*! + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +program erpc_matrix_multiply + +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +const int32 matrix_size = 5; + +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +type Matrix = int32[matrix_size][matrix_size]; + +interface MatrixMultiplyService { + erpcMatrixMultiply(in Matrix matrix1, in Matrix matrix2, out Matrix result_matrix) -> void +} diff --git a/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.h b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.h new file mode 100644 index 00000000..fdbd0c7a --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_common_h_) +#define _erpc_matrix_multiply_common_h_ + + +#if defined(__cplusplus) +extern "C" +{ +#endif +#include +#include +#include + +#include "erpc_version.h" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +#if !defined(ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY) +#define ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +// Aliases data types declarations +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +typedef int32_t Matrix[5][5]; + +// Constant variable declarations +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +extern const int32_t matrix_size; + +#endif // ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +#if defined(__cplusplus) +} +#endif + +#endif // _erpc_matrix_multiply_common_h_ diff --git a/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.hpp b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.hpp new file mode 100644 index 00000000..d1b16374 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_common.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_common_hpp_) +#define _erpc_matrix_multiply_common_hpp_ + + +#include +#include +#include + +#include "erpc_version.h" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +#if !defined(ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY) +#define ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + +// Aliases data types declarations +/*! This is the matrix array type. The dimension has to be the same as the + matrix size const. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +typedef int32_t Matrix[5][5]; + +// Constant variable declarations +/*! This const defines the matrix size. The value has to be the same as the + Matrix array dimension. Do not forget to re-generate the erpc code once the + matrix size is changed in the erpc file */ +extern const int32_t matrix_size; + +#endif // ERPC_TYPE_DEFINITIONS_ERPC_MATRIX_MULTIPLY + + +#endif // _erpc_matrix_multiply_common_hpp_ diff --git a/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.cpp b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.cpp new file mode 100644 index 00000000..e50f033c --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include "erpc_matrix_multiply_interface.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +using namespace std; +using namespace erpcShim; + +MatrixMultiplyService_interface::~MatrixMultiplyService_interface(void) +{ +} diff --git a/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.hpp b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.hpp new file mode 100644 index 00000000..b2be5a90 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_interface.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_interface_hpp_) +#define _erpc_matrix_multiply_interface_hpp_ + +#include "erpc_matrix_multiply_common.hpp" + +namespace erpcShim +{ + + +// Abstract base class for MatrixMultiplyService +class MatrixMultiplyService_interface +{ + public: + static const uint8_t m_serviceId = 1; + static const uint8_t m_erpcMatrixMultiplyId = 1; + + virtual ~MatrixMultiplyService_interface(void); + + virtual void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix) = 0; +private: +}; +} // erpcShim + + +#endif // _erpc_matrix_multiply_interface_hpp_ diff --git a/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.cpp b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.cpp new file mode 100644 index 00000000..d6c97a33 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#include "erpc_matrix_multiply_server.hpp" +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC +#include +#include "erpc_port.h" +#endif +#include "erpc_manually_constructed.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + +using namespace erpc; +using namespace std; +using namespace erpcShim; + +#if ERPC_NESTED_CALLS_DETECTION +extern bool nestingDetection; +#endif + + + +// Constant variable definitions +#if defined(__MINGW32__) +__declspec( selectany ) +#else +#pragma weak matrix_size +#endif +extern const int32_t matrix_size = 5; + + +MatrixMultiplyService_service::MatrixMultiplyService_service(MatrixMultiplyService_interface *_MatrixMultiplyService_interface) + : erpc::Service(MatrixMultiplyService_interface::m_serviceId) + , m_handler(_MatrixMultiplyService_interface) +{ +} + +MatrixMultiplyService_service::~MatrixMultiplyService_service() +{ +} + +// return service interface handler. +MatrixMultiplyService_interface* MatrixMultiplyService_service::getHandler(void) +{ + return m_handler; +} + +// Call the correct server shim based on method unique ID. +erpc_status_t MatrixMultiplyService_service::handleInvocation(uint32_t methodId, uint32_t sequence, Codec * codec, MessageBufferFactory *messageFactory, Transport * transport) +{ + erpc_status_t erpcStatus; + switch (methodId) + { + case MatrixMultiplyService_interface::m_erpcMatrixMultiplyId: + { + erpcStatus = erpcMatrixMultiply_shim(codec, messageFactory, transport, sequence); + break; + } + + default: + { + erpcStatus = kErpcStatus_InvalidArgument; + break; + } + } + + return erpcStatus; +} + +// Server shim for erpcMatrixMultiply of MatrixMultiplyService interface. +erpc_status_t MatrixMultiplyService_service::erpcMatrixMultiply_shim(Codec * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence) +{ + erpc_status_t err = kErpcStatus_Success; + + Matrix matrix1; + Matrix matrix2; + Matrix result_matrix; + + // startReadMessage() was already called before this shim was invoked. + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->read(matrix1[arrayCount0][arrayCount1]); + } + } + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->read(matrix2[arrayCount0][arrayCount1]); + } + } + + err = codec->getStatus(); + if (err == kErpcStatus_Success) + { + // Invoke the actual served function. +#if ERPC_NESTED_CALLS_DETECTION + nestingDetection = true; +#endif + m_handler->erpcMatrixMultiply(matrix1, matrix2, result_matrix); +#if ERPC_NESTED_CALLS_DETECTION + nestingDetection = false; +#endif + + // preparing MessageBuffer for serializing data + err = messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize()); + } + + if (err == kErpcStatus_Success) + { + // preparing codec for serializing data + codec->reset(transport->reserveHeaderSize()); + + // Build response message. + codec->startWriteMessage(message_type_t::kReplyMessage, MatrixMultiplyService_interface::m_serviceId, MatrixMultiplyService_interface::m_erpcMatrixMultiplyId, sequence); + + for (uint32_t arrayCount0 = 0U; arrayCount0 < 5U; ++arrayCount0) + { + for (uint32_t arrayCount1 = 0U; arrayCount1 < 5U; ++arrayCount1) + { + codec->write(result_matrix[arrayCount0][arrayCount1]); + } + } + + err = codec->getStatus(); + } + + return err; +} diff --git a/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.hpp b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.hpp new file mode 100644 index 00000000..ad1f17f2 --- /dev/null +++ b/examples/zephyr/matrix_multiply_uart/src/service/erpc_matrix_multiply_server.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Generated by erpcgen 1.12.0 on Wed Oct 25 10:00:57 2023. + * + * AUTOGENERATED - DO NOT EDIT + */ + + +#if !defined(_erpc_matrix_multiply_server_hpp_) +#define _erpc_matrix_multiply_server_hpp_ + +#include "erpc_matrix_multiply_interface.hpp" + +#include "erpc_server.hpp" +#include "erpc_codec.hpp" + +#if 11200 != ERPC_VERSION_NUMBER +#error "The generated shim code version is different to the rest of eRPC code." +#endif + + +namespace erpcShim +{ + +/*! + * @brief Service subclass for MatrixMultiplyService. + */ +class MatrixMultiplyService_service : public erpc::Service +{ +public: + MatrixMultiplyService_service(MatrixMultiplyService_interface *_MatrixMultiplyService_interface); + + virtual ~MatrixMultiplyService_service(); + + /*! @brief return service interface handler. */ + MatrixMultiplyService_interface* getHandler(void); + + /*! @brief Call the correct server shim based on method unique ID. */ + virtual erpc_status_t handleInvocation(uint32_t methodId, uint32_t sequence, erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport); + +private: + MatrixMultiplyService_interface *m_handler; + /*! @brief Server shim for erpcMatrixMultiply of MatrixMultiplyService interface. */ + erpc_status_t erpcMatrixMultiply_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence); +}; + +} // erpcShim + + +#endif // _erpc_matrix_multiply_server_hpp_ diff --git a/mk/common.mk b/mk/common.mk index aeb20dab..91de62a0 100644 --- a/mk/common.mk +++ b/mk/common.mk @@ -54,20 +54,13 @@ space := $(empty) $(empty) #------------------------------------------------------------------------------- # Get the OS name. Known values are "Linux", "CYGWIN_NT-5.1", and "Darwin". -os_name := $(shell uname -s) - -# Set to 1 if running on mingw. -ifeq "$(os_name)" "" +ifeq "$(and $(findstring Windows,$(OS)),1)" "1" os_name := $(shell powershell [System.Environment]::OSVersion.Version) ifneq "$(os_name)" "" - is_mingw := 1 + os_name := "MINGW" endif else - # Set to 1 if running on Darwin. - is_darwin := $(and $(findstring Darwin,$(os_name)),1) - - # Set to 1 if running on cygwin. - is_cygwin := $(and $(findstring CYGWIN,$(os_name)),1) + os_name := $(shell uname -s) # Set to 1 if running on redhat. is_redhat := $(shell if [ -f /etc/redhat-release ]; then echo 1 ; fi) @@ -75,6 +68,16 @@ else # Set to 1 if running on Linux. is_linux := $(and $(findstring Linux,$(os_name)),1) + # Set to 1 if running on Darwin. + is_darwin := $(and $(findstring Darwin,$(os_name)),1) +endif + +# Set to 1 if running on cygwin. +is_cygwin := $(and $(findstring CYGWIN,$(os_name)),1) + +# Set to 1 if running on Windows under Mingw. +is_mingw := $(and $(findstring MINGW,$(os_name)),1) +ifeq "$(is_mingw)" "" is_mingw := $(and $(findstring MSYS_NT,$(os_name)),1) endif diff --git a/mk/flags.mk b/mk/flags.mk index c22d9d55..8c282c0a 100644 --- a/mk/flags.mk +++ b/mk/flags.mk @@ -68,10 +68,6 @@ else CXXFLAGS += -g3 -O0 -DDEBUG -DYYDEBUG=1 endif -ifneq "$(is_mingw)" "1" - LIBRARIES += -lc -endif - ifneq "$(is_cygwin)" "1" LIBRARIES += -lstdc++ endif @@ -81,3 +77,9 @@ ifeq "$(is_linux)" "1" endif LIBRARIES += -lm + +ifeq "$(is_mingw)" "1" + LIBRARIES += -pthread -lws2_32 +else + LIBRARIES += -lc +endif diff --git a/mk/targets.mk b/mk/targets.mk index 1c603143..41074493 100644 --- a/mk/targets.mk +++ b/mk/targets.mk @@ -122,8 +122,8 @@ $(MAKE_TARGET): $(OBJECTS_ALL) @$(call printmessage,link,Linking, $(APP_NAME)) $(at)$(LD) $(LDFLAGS) \ $(OBJECTS_ALL) \ - $(LIBRARIES) \ - -o $@ + -o $@ \ + $(LIBRARIES) @echo "Output binary:" ; echo " $(APP_NAME)" endif diff --git a/run_clang_format.py b/run_clang_format.py index 83ed7dac..b427bbc8 100755 --- a/run_clang_format.py +++ b/run_clang_format.py @@ -19,14 +19,10 @@ "erpcsniffer/src", "test"] -# Files which will be not formatted -exceptions = [ - "test/common/gtest/gtest.h", - "test/common/gtest/gtest.cpp", - "erpcgen/src/cpptemplate/cpptempl.h", - "erpcgen/src/cpptemplate/cpptempl.cpp", - "erpcgen/src/cpptemplate/cpptempl_test.cpp"] +with open(".clang-format-ignore") as f: + exceptionsTmp = f.read().split("\n") +exceptions = [exception for exception in exceptionsTmp if exception != "" and exception[0] != "#"] # For windows use "\\" instead of "/" path separators. if os.environ.get('OS', '') == 'Windows_NT': folders = [os.path.normpath(folder) for folder in folders] @@ -52,8 +48,8 @@ clang_format_stderr.decode('utf-8'))) exit(1) clang_format_stdout = clang_format_stdout.decode("utf-8") -if not clang_format_stdout.startswith("clang-format version 10.0.0"): - print("clang-format is not the required version: 10.0.0") +if "clang-format version 16.0.0" not in clang_format_stdout: + print("clang-format is not the required version: 16.0.0") exit(1) # processing formatting @@ -63,7 +59,7 @@ for path, subdirs, files in os.walk(folder): for name in files: if any(ext in name for ext in extensions): - file = os.path.join(path, name) + file = "./" + os.path.join(path, name) if file in exceptions: print("Ignored: ", file) else: diff --git a/run_tests.sh b/run_tests.sh index a98162bd..a523782c 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -7,10 +7,11 @@ make clean if [ "$1" = "clang" ]; then echo "Compiling by clang compiler." CC=clang CXX=clang++ make all + python3 test/run_unit_tests.py clang else echo "Compiling by default gnu compiler." CC=gcc CXX=g++ make all + python3 test/run_unit_tests.py gcc fi pytest erpcgen/test/ -python3 test/run_unit_tests.py diff --git a/test/common/config/erpc_config.h b/test/common/config/erpc_config.h index 4d35278c..c20f9952 100644 --- a/test/common/config/erpc_config.h +++ b/test/common/config/erpc_config.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2020 NXP + * Copyright 2020-2021 ACRIOS Systems s.r.o. * All rights reserved. * * @@ -65,17 +66,17 @@ //! Set ERPC_ALLOCATION_POLICY_DYNAMIC if dynamic allocations should be used. //! Set ERPC_ALLOCATION_POLICY_STATIC if static allocations should be used. //! -//! Default value is ERPC_ALLOCATION_POLICY_DYNAMIC or in case of FreeRTOS it can be auto-detected if __has_include() is supported -//! by compiler. Uncomment comment bellow to use static allocation policy. -//! In case of static implementation user need consider another values to set (ERPC_CODEC_COUNT, -//! ERPC_MESSAGE_LOGGERS_COUNT, ERPC_CLIENTS_THREADS_AMOUNT). +//! Default value is ERPC_ALLOCATION_POLICY_DYNAMIC or in case of FreeRTOS it can be auto-detected if __has_include() is +//! supported by compiler. Uncomment comment bellow to use static allocation policy. In case of static implementation +//! user need consider another values to set (ERPC_CODEC_COUNT, ERPC_MESSAGE_LOGGERS_COUNT, +//! ERPC_CLIENTS_THREADS_AMOUNT). #define ERPC_ALLOCATION_POLICY (ERPC_ALLOCATION_POLICY_DYNAMIC) //! @def ERPC_CODEC_COUNT //! //! @brief Set amount of codecs objects used simultaneously in case of ERPC_ALLOCATION_POLICY is set to -//! ERPC_ALLOCATION_POLICY_STATIC. For example if client or server is used in one thread then 1. If both are used in one thread per -//! each then 2, ... Default value 2. +//! ERPC_ALLOCATION_POLICY_STATIC. For example if client or server is used in one thread then 1. If both are used in one +//! thread per each then 2, ... Default value 2. #define ERPC_CODEC_COUNT (2U) //! @def ERPC_MESSAGE_LOGGERS_COUNT @@ -89,8 +90,8 @@ //! @def ERPC_CLIENTS_THREADS_AMOUNT //! -//! @brief Set amount of client threads objects used in case of ERPC_ALLOCATION_POLICY is set to ERPC_ALLOCATION_POLICY_STATIC. -//! Default value 1 (Most of current cases). +//! @brief Set amount of client threads objects used in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. Default value 1 (Most of current cases). #define ERPC_CLIENTS_THREADS_AMOUNT (1U) //! @def ERPC_THREADS @@ -146,7 +147,7 @@ //! ERPC_MESSAGE_LOGGING_DISABLED. //! //! Uncomment for using logging feature. -// #define ERPC_MESSAGE_LOGGING (ERPC_MESSAGE_LOGGING_ENABLED) +//#define ERPC_MESSAGE_LOGGING (ERPC_MESSAGE_LOGGING_ENABLED) //! @def ERPC_TRANSPORT_MU_USE_MCMGR //! @@ -182,10 +183,27 @@ //! @name Assert function definition //@{ -//! User custom asser defition. Include header file if needed before bellow line. If assert is not enabled, default will be used. +//! User custom asser defition. Include header file if needed before bellow line. If assert is not enabled, default will +//! be used. // #define erpc_assert(condition) //@} +//! @def ENDIANES_HEADER +//! +//! Include header file that controls the communication endianness +//! +//! Uncomment for example behaviour for endianness agnostic with: +//! 1. communication in little endian. +//! 2. current processor is big endian. +//! 3. pointer size is 32 bit. +//! 4. float+double scheme not defined, so throws assert if passes. +//! #define ERPC_PROCESSOR_ENDIANNESS_LITTLE 0 +//! #define ERPC_COMMUNICATION_LITTLE 1 +//! #define ERPC_POINTER_SIZE_16 0 +//! #define ERPC_POINTER_SIZE_32 1 +//! #define ERPC_POINTER_SIZE_64 0 +//! #define ENDIANNESS_HEADER "erpc_endianness_agnostic_example.h" + /*! @} */ #endif // _ERPC_CONFIG_H_ //////////////////////////////////////////////////////////////////////////////// diff --git a/test/common/gtest/gtest.cpp b/test/common/gtest/gtest.cpp index e2626e9a..4a7fc663 100644 --- a/test/common/gtest/gtest.cpp +++ b/test/common/gtest/gtest.cpp @@ -7044,9 +7044,11 @@ GTEST_DEFINE_string_( namespace internal { +# if !GTEST_OS_WINDOWS // Valid only for fast death tests. Indicates the code is running in the // child process of a fast style death test. static bool g_in_fast_death_test_child = false; +# endif // Returns a Boolean value indicating whether the caller is currently // executing in the context of the death test child process. Tools such as diff --git a/test/common/gtest/gtest.h b/test/common/gtest/gtest.h index e07c3371..ef9a6231 100644 --- a/test/common/gtest/gtest.h +++ b/test/common/gtest/gtest.h @@ -9910,6 +9910,8 @@ linked_ptr make_linked_ptr(T* ptr) { #if GTEST_OS_BARE_METAL #include +#else +#include #endif #if GTEST_HAS_STD_TUPLE_ diff --git a/test/common/gtestListener.hpp b/test/common/gtestListener.hpp index 8ceed314..1c64134f 100644 --- a/test/common/gtestListener.hpp +++ b/test/common/gtestListener.hpp @@ -10,9 +10,9 @@ #ifndef _EMBEDDED_RPC__GTESTLISTENER_H_ #define _EMBEDDED_RPC__GTESTLISTENER_H_ +#include "c_test_unit_test_common_client.h" #include "gtest.h" #include "myAlloc.hpp" -#include "test_unit_test_common.h" //////////////////////////////////////////////////////////////////////////////// // Classes @@ -26,10 +26,10 @@ class LeakChecker : public ::testing::EmptyTestEventListener { int serverAlloc = getServerAllocated(); - EXPECT_EQ(MyAlloc::allocated(), 0) - << "Leaked (on client side) : " << MyAlloc::allocated() << " unit(s) need be freed!"; + EXPECT_EQ(::MyAlloc::allocated(), 0) + << "Leaked (on client side) : " << ::MyAlloc::allocated() << " unit(s) need be freed!"; EXPECT_EQ(serverAlloc, 0) << "Leaked (on server side) : " << serverAlloc << " unit(s) need be freed!"; - MyAlloc::allocated(0); + ::MyAlloc::allocated(0); } }; diff --git a/test/common/myAlloc.hpp b/test/common/myAlloc.hpp index ad30476d..b2d11bdc 100644 --- a/test/common/myAlloc.hpp +++ b/test/common/myAlloc.hpp @@ -10,6 +10,8 @@ #ifndef _EMBEDDED_RPC__MYALLOC_H_ #define _EMBEDDED_RPC__MYALLOC_H_ +#if defined(__cplusplus) + #include "erpc_port.h" //////////////////////////////////////////////////////////////////////////////// @@ -38,15 +40,13 @@ class MyAlloc static int allocated_; }; -namespace std { -using ::MyAlloc; -} - //////////////////////////////////////////////////////////////////////////////// // Definitions //////////////////////////////////////////////////////////////////////////////// -#define erpc_malloc(X) MyAlloc::my_malloc(X) -#define erpc_free(X) MyAlloc::my_free((X)) +#define erpc_malloc(X) ::MyAlloc::my_malloc(X) +#define erpc_free(X) ::MyAlloc::my_free((X)) + +#endif // __cplusplus #endif // _EMBEDDED_RPC__MYALLOC_H_ diff --git a/test/common/retarget_cpp_streamed_io.c b/test/common/retarget_cpp_streamed_io.c index 69f24e15..757c4b2b 100644 --- a/test/common/retarget_cpp_streamed_io.c +++ b/test/common/retarget_cpp_streamed_io.c @@ -132,7 +132,7 @@ int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode) else // LOG_Push((uint8_t *)(&buf[pos - 1]), 1); // Echo normal char to terminal // DbgConsole_SendData((uint8_t *)(&buf[pos - 1]), 1); // Echo normal char to terminal - DbgConsole_Putchar(buf[pos-1]); // Echo normal char to terminal + DbgConsole_Putchar(buf[pos - 1]); // Echo normal char to terminal } while (buf[pos - 1] != '\r'); diff --git a/test/common/unit_test_arbitrator_app0.cpp b/test/common/unit_test_arbitrator_app0.cpp index a15b6ad5..e4f568ca 100644 --- a/test/common/unit_test_arbitrator_app0.cpp +++ b/test/common/unit_test_arbitrator_app0.cpp @@ -12,12 +12,14 @@ #include "erpc_transport_setup.h" #include "FreeRTOS.h" -#include "gtest.h" #include "semphr.h" #include "task.h" -#include "test_firstInterface.h" -#include "test_secondInterface_server.h" + +#include "c_test_firstInterface_client.h" +#include "c_test_secondInterface_server.h" +#include "gtest.h" #include "unit_test.h" +#include "unit_test_wrapped.h" #ifdef __cplusplus extern "C" { @@ -45,9 +47,11 @@ using namespace std; #define APP_ERPC_READY_EVENT_DATA (1) -SemaphoreHandle_t g_waitQuitMutex; -TaskHandle_t g_serverTask; -TaskHandle_t g_clientTask; +Mutex waitQuitMutex; +Thread g_initThread("runInit"); +Thread g_serverThread("runServer"); +Thread g_clientThread("runClient"); + volatile int waitQuit = 0; volatile uint16_t eRPCReadyEventData = 0; extern const uint32_t erpc_generated_crc; @@ -67,9 +71,8 @@ static void eRPCReadyEventHandler(uint16_t eventData, void *context) void increaseWaitQuit() { - xSemaphoreTake(g_waitQuitMutex, portMAX_DELAY); + Mutex::Guard lock(waitQuitMutex); waitQuit++; - xSemaphoreGive(g_waitQuitMutex); } void runServer(void *arg) @@ -100,11 +103,11 @@ void runClient(void *arg) // wait until ERPC second (server) app will announce ready to quit state. while (true) { + Mutex::Guard lock(waitQuitMutex); if (waitQuit != 0) { break; } - vTaskDelay(10); } // send to ERPC second (server) app ready to quit state @@ -165,6 +168,7 @@ void runInit(void *arg) // eRPC client side initialization client = erpc_arbitrated_client_init(transportClient, message_buffer_factory, &transportServer); + initInterfaces(client); // eRPC server side initialization server = erpc_server_init(transportServer, message_buffer_factory); @@ -173,25 +177,15 @@ void runInit(void *arg) // adding server to client for nested calls. erpc_arbitrated_client_set_server(client, server); - erpc_arbitrated_client_set_server_thread_id(client, (void *)g_serverTask); + erpc_arbitrated_client_set_server_thread_id(client, (void *)g_serverThread.getThreadId()); // adding the service to the server service = create_SecondInterface_service(); erpc_add_service_to_server(server, service); // unblock server and client task - xTaskNotifyGive(g_serverTask); - xTaskNotifyGive(g_clientTask); - - // Wait until server and client will stop. - while (true) - { - if (waitQuit >= 3) - { - break; - } - vTaskDelay(500); - } + xTaskNotifyGive((TaskHandle_t)g_serverThread.getThreadId()); + xTaskNotifyGive((TaskHandle_t)g_clientThread.getThreadId()); vTaskSuspend(NULL); } @@ -237,8 +231,8 @@ int main(void) { int fake_argc = 1; const auto fake_arg0 = "dummy"; - char* fake_argv0 = const_cast(fake_arg0); - char** fake_argv = &fake_argv0; + char *fake_argv0 = const_cast(fake_arg0); + char **fake_argv = &fake_argv0; ::testing::InitGoogleTest(&fake_argc, fake_argv); BOARD_InitHardware(); @@ -259,10 +253,13 @@ int main(void) memcpy((void *)(char *)CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, core1_image_size); #endif - g_waitQuitMutex = xSemaphoreCreateMutex(); - xTaskCreate(runInit, "runInit", 256, NULL, 1, NULL); - xTaskCreate(runServer, "runServer", 1536, NULL, 2, &g_serverTask); - xTaskCreate(runClient, "runClient", 1536, NULL, 1, &g_clientTask); + g_initThread.init(&runInit, 1, 256 * 4); + g_serverThread.init(&runServer, 2, 1536 * 4); + g_clientThread.init(&runClient, 1, 1536 * 4); + + g_initThread.start(); + g_serverThread.start(); + g_clientThread.start(); vTaskStartScheduler(); @@ -271,6 +268,7 @@ int main(void) } } +extern "C" { void quitSecondInterfaceServer() { /* removing the service from the server */ @@ -281,3 +279,4 @@ void quitSecondInterfaceServer() erpc_server_stop(server); increaseWaitQuit(); } +} diff --git a/test/common/unit_test_arbitrator_app1.cpp b/test/common/unit_test_arbitrator_app1.cpp index 5d81c78b..87043b0c 100644 --- a/test/common/unit_test_arbitrator_app1.cpp +++ b/test/common/unit_test_arbitrator_app1.cpp @@ -14,9 +14,11 @@ #include "FreeRTOS.h" #include "semphr.h" #include "task.h" -#include "test_firstInterface_server.h" -#include "test_secondInterface.h" + +#include "c_test_firstInterface_server.h" +#include "c_test_secondInterface_client.h" #include "unit_test.h" +#include "unit_test_wrapped.h" #ifdef __cplusplus extern "C" { @@ -39,9 +41,10 @@ int testClient(); #define APP_ERPC_READY_EVENT_DATA (1) -SemaphoreHandle_t g_waitQuitMutex; -TaskHandle_t g_serverTask; -TaskHandle_t g_clientTask; +Mutex waitQuitMutex; +Thread g_initThread("runInit"); +Thread g_serverThread("runServer"); +Thread g_clientThread("runClient"); volatile int waitQuit = 0; volatile int waitClient = 0; @@ -58,9 +61,8 @@ erpc_server_t server; //////////////////////////////////////////////////////////////////////////////// void increaseWaitQuit() { - xSemaphoreTake(g_waitQuitMutex, portMAX_DELAY); + Mutex::Guard lock(waitQuitMutex); waitQuit++; - xSemaphoreGive(g_waitQuitMutex); } void runServer(void *arg) @@ -88,29 +90,32 @@ void runClient(void *arg) // wait until ERPC first (client) app will announce that it is ready. while (waitClient == 0) { - vTaskDelay(10); + Thread::sleep(10); } // wait until ERPC first (client) app will announce ready to quit state while (true) { isTestPassing = testClient(); - - if (waitQuit != 0 || isTestPassing != 0 || stopTest != 0) { - enableFirstSide(); - break; + Thread::sleep(10); + Mutex::Guard lock(waitQuitMutex); + if (waitQuit != 0 || isTestPassing != 0 || stopTest != 0) + { + enableFirstSide(); + break; + } } - vTaskDelay(10); } while (true) { + Thread::sleep(10); + Mutex::Guard lock(waitQuitMutex); if (waitQuit != 0) { break; } - vTaskDelay(100); } // send to ERPC first (client) app ready to quit state @@ -155,6 +160,7 @@ void runInit(void *arg) // eRPC client side initialization client = erpc_arbitrated_client_init(transportClient, message_buffer_factory, &transportServer); + initInterfaces(client); // eRPC server side initialization server = erpc_server_init(transportServer, message_buffer_factory); @@ -163,7 +169,7 @@ void runInit(void *arg) // adding server to client for nested calls. erpc_arbitrated_client_set_server(client, server); - erpc_arbitrated_client_set_server_thread_id(client, (void *)g_serverTask); + erpc_arbitrated_client_set_server_thread_id(client, (void *)g_serverThread.getThreadId()); // adding the service to the server service = create_FirstInterface_service(); @@ -174,18 +180,8 @@ void runInit(void *arg) #endif // unblock server and client task - xTaskNotifyGive(g_serverTask); - xTaskNotifyGive(g_clientTask); - - // Wait until client side will stop. - while (true) - { - if (waitQuit >= 3) - { - break; - } - vTaskDelay(100); - } + xTaskNotifyGive((TaskHandle_t)g_serverThread.getThreadId()); + xTaskNotifyGive((TaskHandle_t)g_clientThread.getThreadId()); vTaskSuspend(NULL); } @@ -194,10 +190,13 @@ int main(void) { BOARD_InitHardware(); - g_waitQuitMutex = xSemaphoreCreateMutex(); - xTaskCreate(runInit, "runInit", 256, NULL, 1, NULL); - xTaskCreate(runServer, "runServer", 1536, NULL, 3, &g_serverTask); - xTaskCreate(runClient, "runClient", 1536, NULL, 2, &g_clientTask); + g_initThread.init(&runInit, 1, 256 * 4); + g_serverThread.init(&runServer, 3, 1536 * 4); + g_clientThread.init(&runClient, 2, 1536 * 4); + + g_initThread.start(); + g_serverThread.start(); + g_clientThread.start(); vTaskStartScheduler(); @@ -206,6 +205,7 @@ int main(void) } } +extern "C" { void stopSecondSide() { ++stopTest; @@ -235,6 +235,7 @@ void whenReady() { waitClient++; } +} int testClient() { diff --git a/test/common/unit_test_client.cpp b/test/common/unit_test_client.cpp index 09830b11..e685f6cc 100644 --- a/test/common/unit_test_client.cpp +++ b/test/common/unit_test_client.cpp @@ -26,10 +26,12 @@ int main(void); } #include "board.h" + +#include "c_test_unit_test_common_client.h" #include "gtest.h" #include "gtestListener.hpp" #include "myAlloc.hpp" -#include "test_unit_test_common.h" +#include "unit_test_wrapped.h" #ifdef UNITY_DUMP_RESULTS #include "corn_g_test.h" @@ -83,7 +85,7 @@ class MinimalistPrinter : public ::testing::EmptyTestEventListener // Definitions //////////////////////////////////////////////////////////////////////////////// -int MyAlloc::allocated_ = 0; +int ::MyAlloc::allocated_ = 0; #if defined(RPMSG) #define APP_ERPC_READY_EVENT_DATA (1) @@ -111,8 +113,8 @@ int main(void) { int fake_argc = 1; const auto fake_arg0 = "dummy"; - char* fake_argv0 = const_cast(fake_arg0); - char** fake_argv = &fake_argv0; + char *fake_argv0 = const_cast(fake_arg0); + char **fake_argv = &fake_argv0; ::testing::InitGoogleTest(&fake_argc, fake_argv); ::testing::TestEventListeners &listeners = ::testing::UnitTest::GetInstance()->listeners(); @@ -191,6 +193,8 @@ int main(void) #endif client = erpc_client_init(transport, message_buffer_factory); + initInterfaces_common(client); + initInterfaces(client); int i = RUN_ALL_TESTS(); quit(); @@ -204,3 +208,8 @@ int main(void) return i; } + +void initInterfaces_common(erpc_client_t client) +{ + initCommon_client(client); +} diff --git a/test/common/unit_test_serial_client.cpp b/test/common/unit_test_serial_client.cpp index 9fadbf77..57b31d96 100644 --- a/test/common/unit_test_serial_client.cpp +++ b/test/common/unit_test_serial_client.cpp @@ -11,10 +11,11 @@ #include "erpc_serial_transport.hpp" #include "Logging.hpp" +#include "c_test_unit_test_common_client.h" #include "gtest.h" #include "gtestListener.hpp" #include "myAlloc.hpp" -#include "test_unit_test_common.h" +#include "unit_test_wrapped.h" using namespace erpc; @@ -42,7 +43,7 @@ MyMessageBufferFactory g_msgFactory; BasicCodecFactory g_basicCodecFactory; ClientManager *g_client; -int MyAlloc::allocated_ = 0; +int ::MyAlloc::allocated_ = 0; //////////////////////////////////////////////////////////////////////////////// // Set up global fixture @@ -56,7 +57,7 @@ int main(int argc, char **argv) // create logger instance StdoutLogger *m_logger = new StdoutLogger(); - m_logger->setFilterLevel(Logger::kInfo); + m_logger->setFilterLevel(Logger::log_level_t::kInfo); Log::setLogger(m_logger); Log::info("Starting ERPC client...\n"); @@ -69,6 +70,9 @@ int main(int argc, char **argv) g_client->setMessageBufferFactory(&g_msgFactory); g_client->setTransport(&g_transport); g_client->setCodecFactory(&g_basicCodecFactory); + erpc_client_t client = reinterpret_cast(g_client); + initInterfaces_common(client); + initInterfaces(client); int ret = RUN_ALL_TESTS(); quit(); @@ -78,6 +82,11 @@ int main(int argc, char **argv) return ret; } +void initInterfaces_common(erpc_client_t client) +{ + initCommon_client(client); +} + //////////////////////////////////////////////////////////////////////////////// // EOF //////////////////////////////////////////////////////////////////////////////// diff --git a/test/common/unit_test_serial_server.cpp b/test/common/unit_test_serial_server.cpp index fc911cbd..b6969c32 100644 --- a/test/common/unit_test_serial_server.cpp +++ b/test/common/unit_test_serial_server.cpp @@ -11,13 +11,15 @@ #include "erpc_simple_server.hpp" #include "Logging.hpp" +#include "c_test_unit_test_common_server.h" #include "myAlloc.hpp" -#include "test_unit_test_common_server.h" +#include "test_unit_test_common_server.hpp" #include "unit_test.h" #include using namespace erpc; +using namespace erpcShim; class MyMessageBufferFactory : public MessageBufferFactory { @@ -43,7 +45,7 @@ MyMessageBufferFactory g_msgFactory; BasicCodecFactory g_basicCodecFactory; SimpleServer g_server; -int MyAlloc::allocated_ = 0; +int ::MyAlloc::allocated_ = 0; Common_service *svc_common; @@ -54,7 +56,7 @@ int main(int argc, const char *argv[]) { // create logger instance StdoutLogger *m_logger = new StdoutLogger(); - m_logger->setFilterLevel(Logger::kInfo); + m_logger->setFilterLevel(Logger::log_level_t::kInfo); Log::setLogger(m_logger); Log::info("Starting ERPC server...\n"); @@ -78,12 +80,43 @@ int main(int argc, const char *argv[]) return 0; } +//////////////////////////////////////////////////////////////////////////////// +// Common service implementations here +//////////////////////////////////////////////////////////////////////////////// +void quit() +{ + remove_common_service(&g_server); + remove_services(&g_server); + exit(0); +} + +int32_t getServerAllocated() +{ + int result = ::MyAlloc::allocated(); + ::MyAlloc::allocated(0); + return result; +} + +class Common_server : public Common_interface +{ +public: + void quit(void) { ::quit(); } + + int32_t getServerAllocated(void) + { + int32_t result; + result = ::getServerAllocated(); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Server helper functions //////////////////////////////////////////////////////////////////////////////// void add_common_service(SimpleServer *server) { - svc_common = new Common_service(); + svc_common = new Common_service(new Common_server()); server->addService(svc_common); } @@ -91,28 +124,13 @@ void add_common_service(SimpleServer *server) void remove_common_service(SimpleServer *server) { server->removeService(svc_common); + delete svc_common->getHandler(); delete svc_common; } extern "C" void erpc_add_service_to_server(void *service) {} extern "C" void erpc_remove_service_from_server(void *service) {} -//////////////////////////////////////////////////////////////////////////////// -// Common service implementations here -//////////////////////////////////////////////////////////////////////////////// -void quit() -{ - remove_common_service(&g_server); - remove_services(&g_server); - exit(0); -} - -int32_t getServerAllocated() -{ - int result = MyAlloc::allocated(); - MyAlloc::allocated(0); - return result; -} //////////////////////////////////////////////////////////////////////////////// // EOF //////////////////////////////////////////////////////////////////////////////// diff --git a/test/common/unit_test_server.cpp b/test/common/unit_test_server.cpp index c10dda3a..dae97b3e 100644 --- a/test/common/unit_test_server.cpp +++ b/test/common/unit_test_server.cpp @@ -14,15 +14,21 @@ #if (defined(RPMSG) || defined(UART) || defined(MU)) extern "C" { #if defined(UART) +/* clang-format off */ #include "fsl_lpuart_cmsis.h" + #include "app_core0.h" +/* clang-format on */ #else #if defined(RPMSG) #include "rpmsg_lite.h" #endif #define APP_ERPC_READY_EVENT_DATA (1) +/* clang-format off */ #include "mcmgr.h" + #include "app_core1.h" +/* clang-format on */ #endif #if defined(__CC_ARM) || defined(__ARMCC_VERSION) int main(void); @@ -31,15 +37,16 @@ int main(void); #endif #include "board.h" + +#include "c_test_unit_test_common_server.h" #include "myAlloc.hpp" -#include "test_unit_test_common_server.h" #include "unit_test_wrapped.h" //////////////////////////////////////////////////////////////////////////////// // Variables //////////////////////////////////////////////////////////////////////////////// -int MyAlloc::allocated_ = 0; +int ::MyAlloc::allocated_ = 0; erpc_service_t service_common = NULL; erpc_server_t server; @@ -117,6 +124,12 @@ void add_common_service(erpc_server_t server) erpc_add_service_to_server(server, service_common); } +void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) +{ + erpc_remove_service_from_server(server, service); + destroy_Common_service(service); +} + //////////////////////////////////////////////////////////////////////////////// // Common service implementations here //////////////////////////////////////////////////////////////////////////////// @@ -134,7 +147,7 @@ void quit() int32_t getServerAllocated() { - int result = MyAlloc::allocated(); - MyAlloc::allocated(0); + int result = ::MyAlloc::allocated(); + ::MyAlloc::allocated(0); return result; } diff --git a/test/common/unit_test_tcp_arbitrator_client.cpp b/test/common/unit_test_tcp_arbitrator_client.cpp index 549cb554..87e7dbf5 100644 --- a/test/common/unit_test_tcp_arbitrator_client.cpp +++ b/test/common/unit_test_tcp_arbitrator_client.cpp @@ -13,13 +13,13 @@ #include "erpc_transport_arbitrator.hpp" #include "Logging.hpp" +#include "c_test_firstInterface_client.h" #include "gtest.h" -#include "test_firstInterface.h" -#include "test_secondInterface.h" #include "unit_test.h" +#include "unit_test_wrapped.h" + #include #include - #include using namespace erpc; @@ -63,7 +63,6 @@ void increaseWaitQuit() { Mutex::Guard lock(waitQuitMutex); waitQuit++; - Mutex::Guard unlock(waitQuitMutex); } void runServer(void *arg) @@ -89,7 +88,6 @@ void runClient(void *arg) { break; } - Mutex::Guard unlock(waitQuitMutex); } // send to ERPC second (server) app ready to quit state @@ -108,7 +106,7 @@ int main(int argc, char **argv) // create logger instance StdoutLogger m_logger; - m_logger.setFilterLevel(Logger::kInfo); + m_logger.setFilterLevel(Logger::log_level_t::kInfo); Log::setLogger(&m_logger); Log::info("Intit ERPC first (client) app...\n"); @@ -154,6 +152,8 @@ int main(int argc, char **argv) add_services(&g_server); g_client->setServer(&g_server); + erpc_client_t client = reinterpret_cast(g_client); + initInterfaces(client); int i = -1; err = (erpc_status_t)-1; @@ -173,7 +173,6 @@ int main(int argc, char **argv) { break; } - Mutex::Guard unlock(waitQuitMutex); } // Close transport @@ -190,6 +189,7 @@ int main(int argc, char **argv) return i; } +extern "C" { void quitSecondInterfaceServer() { // removing SecondInterface service from the server @@ -198,3 +198,4 @@ void quitSecondInterfaceServer() g_server.stop(); increaseWaitQuit(); } +} diff --git a/test/common/unit_test_tcp_arbitrator_server.cpp b/test/common/unit_test_tcp_arbitrator_server.cpp index d32a1fc9..bf812acf 100644 --- a/test/common/unit_test_tcp_arbitrator_server.cpp +++ b/test/common/unit_test_tcp_arbitrator_server.cpp @@ -13,10 +13,10 @@ #include "erpc_transport_arbitrator.hpp" #include "Logging.hpp" +#include "c_test_secondInterface_server.h" #include "myAlloc.hpp" -#include "test_firstInterface.h" -#include "test_secondInterface.h" #include "unit_test.h" +#include "unit_test_wrapped.h" #include @@ -63,7 +63,6 @@ void increaseWaitQuit() { Mutex::Guard lock(waitQuitMutex); waitQuit++; - Mutex::Guard unlock(waitQuitMutex); } void runServer(void *arg) @@ -84,14 +83,14 @@ void runClient(void *arg) while (true) { isTestPassing = testClient(); - Mutex::Guard lock(waitQuitMutex); - if (waitQuit != 0 || isTestPassing != 0 || stopTest != 0) { - enableFirstSide(); - Mutex::Guard unlock(waitQuitMutex); - break; + Mutex::Guard lock(waitQuitMutex); + if (waitQuit != 0 || isTestPassing != 0 || stopTest != 0) + { + enableFirstSide(); + break; + } } - Mutex::Guard unlock(waitQuitMutex); } while (true) @@ -101,7 +100,6 @@ void runClient(void *arg) { break; } - Mutex::Guard unlock(waitQuitMutex); } // send to ERPC first (client) app ready to quit state @@ -118,7 +116,7 @@ int main(int argc, char **argv) // create logger instance StdoutLogger m_logger; - m_logger.setFilterLevel(Logger::kInfo); + m_logger.setFilterLevel(Logger::log_level_t::kInfo); Log::setLogger(&m_logger); @@ -146,6 +144,8 @@ int main(int argc, char **argv) g_server.setMessageBufferFactory(&g_msgFactory); add_services(&g_server); g_client->setServer(&g_server); + erpc_client_t client = reinterpret_cast(g_client); + initInterfaces(client); err = (erpc_status_t)-1; @@ -164,7 +164,6 @@ int main(int argc, char **argv) { break; } - Mutex::Guard unlock(waitQuitMutex); } // Close transport @@ -181,6 +180,7 @@ int main(int argc, char **argv) return isTestPassing; } +extern "C" { void stopSecondSide() { ++stopTest; @@ -208,6 +208,7 @@ void whenReady() { waitClient++; } +} int testClient() { diff --git a/test/common/unit_test_tcp_client.cpp b/test/common/unit_test_tcp_client.cpp index 132bd047..403873b4 100644 --- a/test/common/unit_test_tcp_client.cpp +++ b/test/common/unit_test_tcp_client.cpp @@ -11,10 +11,11 @@ #include "erpc_tcp_transport.hpp" #include "Logging.hpp" +#include "c_test_unit_test_common_client.h" #include "gtest.h" #include "gtestListener.hpp" #include "myAlloc.hpp" -#include "test_unit_test_common.h" +#include "unit_test_wrapped.h" using namespace erpc; @@ -47,7 +48,7 @@ ClientManager *g_client; Crc16 g_crc16; -int MyAlloc::allocated_ = 0; +int ::MyAlloc::allocated_ = 0; //////////////////////////////////////////////////////////////////////////////// // Set up global fixture @@ -61,7 +62,7 @@ int main(int argc, char **argv) // create logger instance StdoutLogger *m_logger = new StdoutLogger(); - m_logger->setFilterLevel(Logger::kInfo); + m_logger->setFilterLevel(Logger::log_level_t::kInfo); Log::setLogger(m_logger); Log::info("Starting ERPC client...\n"); @@ -90,6 +91,9 @@ int main(int argc, char **argv) #if USE_MESSAGE_LOGGING g_client->addMessageLogger(&g_messageLogger); #endif // USE_MESSAGE_LOGGING + erpc_client_t client = reinterpret_cast(g_client); + initInterfaces_common(client); + initInterfaces(client); int ret = RUN_ALL_TESTS(); quit(); @@ -100,6 +104,11 @@ int main(int argc, char **argv) return ret; } +void initInterfaces_common(erpc_client_t client) +{ + initCommon_client(client); +} + //////////////////////////////////////////////////////////////////////////////// // EOF //////////////////////////////////////////////////////////////////////////////// diff --git a/test/common/unit_test_tcp_server.cpp b/test/common/unit_test_tcp_server.cpp index 7bef7a6d..fb732ee6 100644 --- a/test/common/unit_test_tcp_server.cpp +++ b/test/common/unit_test_tcp_server.cpp @@ -11,11 +11,13 @@ #include "erpc_tcp_transport.hpp" #include "Logging.hpp" +#include "c_test_unit_test_common_server.h" #include "myAlloc.hpp" -#include "test_unit_test_common_server.h" +#include "test_unit_test_common_server.hpp" #include "unit_test.h" using namespace erpc; +using namespace erpcShim; class MyMessageBufferFactory : public MessageBufferFactory { @@ -43,7 +45,7 @@ SimpleServer g_server; Crc16 g_crc16; -int MyAlloc::allocated_ = 0; +int ::MyAlloc::allocated_ = 0; Common_service *svc_common; @@ -54,7 +56,7 @@ int main(int argc, const char *argv[]) { // create logger instance StdoutLogger *m_logger = new StdoutLogger(); - m_logger->setFilterLevel(Logger::kInfo); + m_logger->setFilterLevel(Logger::log_level_t::kInfo); Log::setLogger(m_logger); Log::info("Starting ERPC server...\n"); @@ -87,12 +89,43 @@ int main(int argc, const char *argv[]) return 0; } +//////////////////////////////////////////////////////////////////////////////// +// Common service implementations here +//////////////////////////////////////////////////////////////////////////////// +void quit() +{ + remove_common_service(&g_server); + remove_services(&g_server); + g_server.stop(); +} + +int32_t getServerAllocated() +{ + int result = ::MyAlloc::allocated(); + ::MyAlloc::allocated(0); + return result; +} + +class Common_server : public Common_interface +{ +public: + void quit(void) { ::quit(); } + + int32_t getServerAllocated(void) + { + int32_t result; + result = ::getServerAllocated(); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Server helper functions //////////////////////////////////////////////////////////////////////////////// void add_common_service(SimpleServer *server) { - svc_common = new Common_service(); + svc_common = new Common_service(new Common_server()); server->addService(svc_common); } @@ -100,28 +133,13 @@ void add_common_service(SimpleServer *server) void remove_common_service(SimpleServer *server) { server->removeService(svc_common); + delete svc_common->getHandler(); delete svc_common; } extern "C" void erpc_add_service_to_server(void *service) {} extern "C" void erpc_remove_service_from_server(void *service) {} -//////////////////////////////////////////////////////////////////////////////// -// Common service implementations here -//////////////////////////////////////////////////////////////////////////////// -void quit() -{ - remove_common_service(&g_server); - remove_services(&g_server); - g_server.stop(); -} - -int32_t getServerAllocated() -{ - int result = MyAlloc::allocated(); - MyAlloc::allocated(0); - return result; -} //////////////////////////////////////////////////////////////////////////////// // EOF //////////////////////////////////////////////////////////////////////////////// diff --git a/test/common/unit_test_wrapped.h b/test/common/unit_test_wrapped.h index 72c386ce..21f38dbf 100644 --- a/test/common/unit_test_wrapped.h +++ b/test/common/unit_test_wrapped.h @@ -9,13 +9,20 @@ #ifndef _EMBEDDED_RPC__UNIT_TEST_WRAPPED_H_ #define _EMBEDDED_RPC__UNIT_TEST_WRAPPED_H_ +#include "erpc_client_manager.h" +#include "erpc_server_setup.h" + //////////////////////////////////////////////////////////////////////////////// // Function Prototypes //////////////////////////////////////////////////////////////////////////////// +typedef void *erpc_service_t; #ifdef __cplusplus extern "C" { #endif +void initInterfaces(erpc_client_t client); +void initInterfaces_common(erpc_client_t client); + void add_services_to_server(erpc_server_t server); void remove_services_from_server(erpc_server_t server); void remove_common_services_from_server(erpc_server_t server, erpc_service_t service); diff --git a/test/java_impl_tests/.gitignore b/test/java_impl_tests/.gitignore new file mode 100644 index 00000000..c467162c --- /dev/null +++ b/test/java_impl_tests/.gitignore @@ -0,0 +1,41 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +# Allow java tests +!**/src/test/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/test/java_impl_tests/pom.xml b/test/java_impl_tests/pom.xml new file mode 100644 index 00000000..84c3c498 --- /dev/null +++ b/test/java_impl_tests/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + io.github.embeddedrpc.erpc.tests + java_impl_tests + 0.1.0 + + + 21 + 21 + UTF-8 + + + + + io.github.embeddedrpc.erpc + erpc + 0.1.0 + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + + + \ No newline at end of file diff --git a/test/java_impl_tests/readme.md b/test/java_impl_tests/readme.md new file mode 100644 index 00000000..248a3e75 --- /dev/null +++ b/test/java_impl_tests/readme.md @@ -0,0 +1,104 @@ +# Java implementation testing directory # + +This directory contains acceptance tests for Java implementation. + +Current implementation supports these tests: + +- test_arrays +- test_binary +- test_builtin +- test_const +- test_enums +- test_lists +- test_struct + +and communicate via TPC or serial port. + +## Prerequisites + +- [Java 21 SDK](https://jdk.java.net/21/) +- [Maven 3.9.5](https://maven.apache.org/download.cgi) + +To check that all the prerequisites are correctly installed, run `mvn -v`. You should get something like this: + +``` +Apache Maven 3.9.5 (***) +Maven home: c:\Program Files\Maven\apache-maven-3.9.5 +Java version: 21, vendor: Oracle Corporation, runtime: c:\Program Files\Java\jdk-21 +Default locale: en_US, platform encoding: UTF-8 +OS name: "***", version: "***", arch: "***", family: "***" +``` + +- If `mvn -v` fails, check that you have added maven to the `PATH` variable. +- If you do not see the correct Java version, check that you have set the `JAVA_HOME` and `PATH` variables correctly. + + +## Test folder structure + +* **client/** - client side tests +* **server/** - server side tests + * **servers/** - TCP and UART server for testing purpose + * **services/** - server side functions implementation + +## Generating shim code + +To generate Java shim code for tests run: + +```sh +ruby ..\..\internal\scripts\generate_erpc_java.rb [erpcgen_path] [erpc_path] +``` + +### Example + +```sh +ruby ..\..\internal\scripts\generate_erpc_java.rb "erpcgen\VisualStudio_v14\Debug\" "C:\mcu-multicore\erpc" +``` + +## Running tests + +To execute Java tests from commandline use Maven `test` lifecycle. Selecting specific test case is done with +parameter `-Dtest=TestName`. It is also possible to change transport configuration with parameters specified below. + +`TestName` is derived as PascalCase from base test name specified in IDL file. + +Example: `test_arrays -> TestArrays` + +Server tests names are create by adding `Server` to `TestName`. + +Example: `test_arrays -> TestArraysServer` + +### Client + +To run client test, execute `mvn test -Dtest=TestName` + +### Server + +To run server test, execute `mvn test -Dtest=TestNameServer -Dserver` + +### Parameters + +- `-Dtest=TEST_NAME` - Name of the test (Pascal case) +- `-Dclient` (**Default**) or `-Dserver` +- `-Dhost=HOST_NAME ` (default: localhost) - Set host name +- `-Dport=PORT` (default: 40) - Set port +- `-Dserial=COM_PORT` (default: COM6) - Enable serial communication +- `-Dbaudrate=BAUDRATE` (default: 115200) - Set serial link baudrate + +```shell +mvn test -Dtest=TestArrays # Client test casemvn +mvn test -Dtest=TestArrays -Dserial=COM6 -Dbaudrate=115200 # Specified serial transport +mvn test -Dtest=TestArraysServer -Dserver # Server test case +mvn test -Dtest=TestArraysServer -Dserver -Dport=12345 # Server test case with custom port +``` + +## Test folder structure + +- **client/** - Client tests +- **server/** - Server tests + - **services/** - Services for server tests +- **Connection.java** - Helper class for transport creation +- **TestingClient.java** - Base class for client tests +- **TestingServer.java** + - This class represent ERPC server for testing purpose. SimpleServer instance is stored as static, so it + is possible to stop the server and close connection with static function `stop()` without access to the instance of the + class. This is used in `CommonService.java` to stop currently running server. \ No newline at end of file diff --git a/test/java_impl_tests/run_tests.py b/test/java_impl_tests/run_tests.py new file mode 100644 index 00000000..fe927204 --- /dev/null +++ b/test/java_impl_tests/run_tests.py @@ -0,0 +1,136 @@ +import shlex +import sys +from time import sleep +from subprocess import Popen, PIPE, TimeoutExpired +from typing import Optional +import os +import argparse + +tests_list = [ + # "test_arbitrator", + "test_annotations", + "test_arrays", + "test_binary", + "test_builtin", + "test_const", + # "test_callbacks", + "test_enums", + "test_lists", + "test_struct", + "test_typedef", + # "test_unions" +] + +PYTHON_TESTS_PATH = r"..\python_impl_tests\scripts" + + +def to_pascal_case(text: str, separator: str = "_") -> str: + return "".join([i.capitalize() for i in text.split("_")]) + + +def python_server_test_cmd(test_name: str) -> list[str]: + return shlex.split( + f"pytest {test_name}/{test_name}.py --server" + ) + + +class Runner: + def __init__(self, server: str, client: str, port: int = 12345, mvn: str = "mvn", host="localhost"): + self.port = port + self.host = host + self.mvn = mvn + + if server == "java": + self.server = self.java_server + elif server == "py": + self.server = self.python_server + else: + raise AttributeError + + if client == "java": + self.client = self.java_client + elif client == "py": + self.client = self.python_client + else: + raise AttributeError + + def execute_test(self, test_name: str): + print("=================================") + print(f"Running test case: {test_case}") + print("=================================") + + server = self.server(test_name) + sleep(1) + client = self.client(test_name) + + try: + print("============ SERVER =============") + stdout, stderr = server.communicate(timeout=10) + except TimeoutExpired: + print("ERROR: TIMEOUT") + server.kill() + stdout, stderr = server.communicate() + + print(stdout.decode(errors="ignore")) + print(stderr.decode()) + print("=================================") + + try: + print("============ CLIENT =============") + stdout, stderr = client.communicate(timeout=10) + except TimeoutExpired: + print("ERROR: TIMEOUT") + client.kill() + stdout, stderr = client.communicate() + + print(stdout.decode(errors="ignore")) + print(stderr.decode()) + + def java_client(self, test_name: str): + return Popen( + f"{self.mvn} test -Dtest={to_pascal_case(test_name)} -Dclient " + f"-Dport={self.port} -Dhost={self.host}", + stdout=PIPE, stderr=PIPE + ) + + def java_server(self, test_name: str): + return Popen( + f"{self.mvn} test -Dtest={to_pascal_case(test_name)}Server -Dserver " + f"-Dport={self.port} -Dhost={self.host}", + stdout=PIPE, stderr=PIPE + ) + + def python_client(self, test_name: str): + return Popen( + f"pytest {test_name}/{test_name}.py --client --port {self.port} --host {self.host}", + cwd=PYTHON_TESTS_PATH, + stdout=PIPE, stderr=PIPE + ) + + def python_server(self, test_name: str): + return Popen( + f"pytest {test_name}/{test_name}.py --server --port {self.port} --host {self.host}", + cwd=PYTHON_TESTS_PATH, + stdout=PIPE, stderr=PIPE + ) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description="Run Java and Python tests.") + + # Options + parser.add_argument("-s", "--server", default="java", choices=["java", "py"], + help="Select server side implementation: java or py") + parser.add_argument("-c", "--client", default="java", choices=["java", "py"], + help="Select client side implementation: java or py") + parser.add_argument("-m", "--maven", default="mvn", help="Path to Maven executable") + parser.add_argument("-p", "--port", default=12345, type=int, help="Port") + + args = parser.parse_args() + + runner = Runner(args.server, args.client, args.port, args.maven) + + for test_case in tests_list: + runner.execute_test(test_case) diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/common/myEnum.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/common/myEnum.java new file mode 100644 index 00000000..ce46ea25 --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/common/myEnum.java @@ -0,0 +1,47 @@ +package io.github.embeddedrpc.erpc.tests.common; + +import io.github.embeddedrpc.erpc.codec.Codec; + +/** + * Custom enum implementation for testing. + */ +public enum myEnum { + one(0), + two(1), + three(2); + + private final Integer value; + + myEnum(Integer value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static myEnum get(int value) { + if (value == 0) { + return one; + } + + if (value == 1) { + return two; + } + + if (value == 2) { + return three; + } + + return null; + } + + public static myEnum read(Codec codec) { + return get(codec.readInt32()); + } + + public void write(Codec codec) { + codec.writeInt32(this.getValue()); + } + +} diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/client/CommonClient.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/client/CommonClient.java new file mode 100644 index 00000000..3511bad4 --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/client/CommonClient.java @@ -0,0 +1,78 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.tests.test_annotations.test_unit_test_common.client; + +import io.github.embeddedrpc.erpc.tests.test_annotations.test_unit_test_common.interfaces.ICommon; + + + +import io.github.embeddedrpc.erpc.tests.common.myEnum; + +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.RequestContext; +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import io.github.embeddedrpc.erpc.client.ClientManager; +import io.github.embeddedrpc.erpc.codec.Codec; + +import java.util.ArrayList; +import java.util.List; + +public class CommonClient implements ICommon { + private final ClientManager clientManager; + + public CommonClient(ClientManager clientManager) { + this.clientManager = clientManager; + } + + + @Override + public void quit() { + // Create request + RequestContext request = clientManager.createRequest(true); + Codec codec = request.codec(); + + // Write message info + codec.startWriteMessage(new MessageInfo( + MessageType.kOnewayMessage, + this.SERVICE_ID, + this.QUIT_ID, + request.sequence())); + + // Write message data + + // Perform request + clientManager.performRequest(request); + + } + + @Override + public int getServerAllocated() { + // Create request + RequestContext request = clientManager.createRequest(false); + Codec codec = request.codec(); + + // Write message info + codec.startWriteMessage(new MessageInfo( + MessageType.kInvocationMessage, + this.SERVICE_ID, + this.GETSERVERALLOCATED_ID, + request.sequence())); + + // Write message data + + // Perform request + clientManager.performRequest(request); + + // Read out parameters + + // Read return value + int _result = codec.readInt32(); + return _result; + } +} diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/common/Constants.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/common/Constants.java new file mode 100644 index 00000000..a30569c7 --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/common/Constants.java @@ -0,0 +1,21 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + package io.github.embeddedrpc.erpc.tests.test_annotations.test_unit_test_common.common; + + + + +import io.github.embeddedrpc.erpc.tests.common.myEnum; + +import java.util.ArrayList; +import java.util.List; + +public final class Constants { + + private Constants() { + } +} + diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/interfaces/ICommon.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/interfaces/ICommon.java new file mode 100644 index 00000000..be0bf2da --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/interfaces/ICommon.java @@ -0,0 +1,35 @@ +/*! + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.tests.test_annotations.test_unit_test_common.interfaces; + + + +import io.github.embeddedrpc.erpc.tests.common.myEnum; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; + +import java.util.List; + +public interface ICommon { + int SERVICE_ID = 0; + int QUIT_ID = 1; + int GETSERVERALLOCATED_ID = 2; + + void quit(); + int getServerAllocated(); +} + + + diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/server/AbstractCommonService.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/server/AbstractCommonService.java new file mode 100644 index 00000000..3c252e0a --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_annotations/test_unit_test_common/server/AbstractCommonService.java @@ -0,0 +1,67 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ +package io.github.embeddedrpc.erpc.tests.test_annotations.test_unit_test_common.server; + +import io.github.embeddedrpc.erpc.tests.test_annotations.test_unit_test_common.interfaces.ICommon; + + + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.auxiliary.Reference; + +import io.github.embeddedrpc.erpc.tests.common.myEnum; + +import java.util.ArrayList; +import java.util.List; + +/** + * Testing abstract service class for simple eRPC interface. + */ +public abstract class AbstractCommonService + extends Service + implements ICommon { + + /** + * Default constructor. + */ + public AbstractCommonService() { + super(ICommon.SERVICE_ID); + addMethodHandler(ICommon.QUIT_ID, this::quitHandler); + addMethodHandler(ICommon.GETSERVERALLOCATED_ID, this::getServerAllocatedHandler); + } + + private void quitHandler(int sequence, Codec codec) { + + + quit(); + + codec.reset(); + + } + private void getServerAllocatedHandler(int sequence, Codec codec) { + + + int _result = getServerAllocated(); + + codec.reset(); + + codec.startWriteMessage(new MessageInfo( + MessageType.kReplyMessage, + getServiceId(), + ICommon.GETSERVERALLOCATED_ID, + sequence) + ); + + // Read out parameters + // Read return value + codec.writeInt32(_result); + } + +} + diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/client/CommonClient.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/client/CommonClient.java new file mode 100644 index 00000000..a4005a6e --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/client/CommonClient.java @@ -0,0 +1,77 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client; + +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.interfaces.ICommon; + +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common.enums.*; + + +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.RequestContext; +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.auxiliary.Utils; +import io.github.embeddedrpc.erpc.client.ClientManager; +import io.github.embeddedrpc.erpc.codec.Codec; + +import java.util.ArrayList; +import java.util.List; + +public class CommonClient implements ICommon { + private final ClientManager clientManager; + + public CommonClient(ClientManager clientManager) { + this.clientManager = clientManager; + } + + + @Override + public void quit() { + // Create request + RequestContext request = clientManager.createRequest(true); + Codec codec = request.codec(); + + // Write message info + codec.startWriteMessage(new MessageInfo( + MessageType.kOnewayMessage, + this.SERVICE_ID, + this.QUIT_ID, + request.sequence())); + + // Write message data + + // Perform request + clientManager.performRequest(request); + + } + + @Override + public int getServerAllocated() { + // Create request + RequestContext request = clientManager.createRequest(false); + Codec codec = request.codec(); + + // Write message info + codec.startWriteMessage(new MessageInfo( + MessageType.kInvocationMessage, + this.SERVICE_ID, + this.GETSERVERALLOCATED_ID, + request.sequence())); + + // Write message data + + // Perform request + clientManager.performRequest(request); + + // Read out parameters + + // Read return value + int _result = codec.readInt32(); + return _result; + } +} diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/Constants.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/Constants.java new file mode 100644 index 00000000..d646d2cb --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/Constants.java @@ -0,0 +1,21 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + package io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common; + + +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common.enums.*; + + +import java.util.ArrayList; +import java.util.List; + +public final class Constants { + public static final int c_x = 5; + + private Constants() { + } +} + diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/enumColor.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/enumColor.java new file mode 100644 index 00000000..4f1a0527 --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/enumColor.java @@ -0,0 +1,57 @@ +/*! + * Copyright (c) 2014-2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common.enums; + +import io.github.embeddedrpc.erpc.codec.Codec; + +public enum enumColor{ + red(0), + green(1), + blue(2); + + private final Integer value; + + enumColor(Integer value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static enumColor get(int value) { + if (value == 0) { + return red; + } + + if (value == 1) { + return green; + } + + if (value == 2) { + return blue; + } + + return null; + } + + public static enumColor read(Codec codec) { + return get(codec.readInt32()); + } + + public void write(Codec codec) { + codec.writeInt32(this.getValue()); + } +} \ No newline at end of file diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/myEnum.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/myEnum.java new file mode 100644 index 00000000..da8677ed --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/myEnum.java @@ -0,0 +1,57 @@ +/*! + * Copyright (c) 2014-2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common.enums; + +import io.github.embeddedrpc.erpc.codec.Codec; + +public enum myEnum{ + a(0), + b(1), + c(2); + + private final Integer value; + + myEnum(Integer value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static myEnum get(int value) { + if (value == 0) { + return a; + } + + if (value == 1) { + return b; + } + + if (value == 2) { + return c; + } + + return null; + } + + public static myEnum read(Codec codec) { + return get(codec.readInt32()); + } + + public void write(Codec codec) { + codec.writeInt32(this.getValue()); + } +} \ No newline at end of file diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/numbers.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/numbers.java new file mode 100644 index 00000000..65a126d0 --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/common/enums/numbers.java @@ -0,0 +1,62 @@ +/*! + * Copyright (c) 2014-2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common.enums; + +import io.github.embeddedrpc.erpc.codec.Codec; + +public enum numbers{ + one(1), + two(2), + three(3), + four(4); + + private final Integer value; + + numbers(Integer value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static numbers get(int value) { + if (value == 1) { + return one; + } + + if (value == 2) { + return two; + } + + if (value == 3) { + return three; + } + + if (value == 4) { + return four; + } + + return null; + } + + public static numbers read(Codec codec) { + return get(codec.readInt32()); + } + + public void write(Codec codec) { + codec.writeInt32(this.getValue()); + } +} \ No newline at end of file diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/interfaces/ICommon.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/interfaces/ICommon.java new file mode 100644 index 00000000..324e09ab --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/interfaces/ICommon.java @@ -0,0 +1,34 @@ +/*! + * Copyright (c) 2014-2015, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ + +package io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.interfaces; + +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common.enums.*; + + +import io.github.embeddedrpc.erpc.auxiliary.Reference; + +import java.util.List; + +public interface ICommon { + int SERVICE_ID = 0; + int QUIT_ID = 1; + int GETSERVERALLOCATED_ID = 2; + + void quit(); + int getServerAllocated(); +} + + + diff --git a/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/server/AbstractCommonService.java b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/server/AbstractCommonService.java new file mode 100644 index 00000000..b559e939 --- /dev/null +++ b/test/java_impl_tests/src/main/java/io/github/embeddedrpc/erpc/tests/test_arrays/test_unit_test_common/server/AbstractCommonService.java @@ -0,0 +1,66 @@ +/** + * Generated by erpcgen 1.12.0 on Mon Jan 8 10:25:43 2024. + * + * AUTOGENERATED - DO NOT EDIT + */ +package io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.server; + +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.interfaces.ICommon; + +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.common.enums.*; + +import io.github.embeddedrpc.erpc.auxiliary.MessageInfo; +import io.github.embeddedrpc.erpc.auxiliary.MessageType; +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.auxiliary.Reference; + + +import java.util.ArrayList; +import java.util.List; + +/** + * Testing abstract service class for simple eRPC interface. + */ +public abstract class AbstractCommonService + extends Service + implements ICommon { + + /** + * Default constructor. + */ + public AbstractCommonService() { + super(ICommon.SERVICE_ID); + addMethodHandler(ICommon.QUIT_ID, this::quitHandler); + addMethodHandler(ICommon.GETSERVERALLOCATED_ID, this::getServerAllocatedHandler); + } + + private void quitHandler(int sequence, Codec codec) { + + + quit(); + + codec.reset(); + + } + private void getServerAllocatedHandler(int sequence, Codec codec) { + + + int _result = getServerAllocated(); + + codec.reset(); + + codec.startWriteMessage(new MessageInfo( + MessageType.kReplyMessage, + getServiceId(), + ICommon.GETSERVERALLOCATED_ID, + sequence) + ); + + // Read out parameters + // Read return value + codec.writeInt32(_result); + } + +} + diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/Connection.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/Connection.java new file mode 100644 index 00000000..20d656f2 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/Connection.java @@ -0,0 +1,70 @@ +package io.github.embeddedrpc.erpc.tests; + +import io.github.embeddedrpc.erpc.transport.SerialTransport; +import io.github.embeddedrpc.erpc.transport.TCPTransport; +import io.github.embeddedrpc.erpc.transport.Transport; + +import java.io.IOException; + +public final class Connection { + public static final String HOST = "localhost"; + public static final int PORT = 40; + public static final int BAUDRATE = 115200; + + private Connection() { + } + + /** + * Create transport based on properties: + * -Dserver or -Dclient (default: client) - Server or client + * -Dhost=HOST_NAME (default: localhost) - Host name + * -Dport=PORT (default: 40) - Port + * -Dserial=COM_PORT (default: null) - Serial communication + * -Dbaudrate=BAUDRATE (default: 115200) - Serial link baudrate + * + * @return New transport + */ + public static Transport getConnectionFromSystemProperties() { + String host = HOST; + int port = PORT; + String serial = null; + int baudrate = BAUDRATE; + boolean isServer = System.getProperty("server") != null; + + // Read parameters + if (System.getProperty("host") != null && !System.getProperty("host").isEmpty()) { + host = System.getProperty("host"); + } + + if (System.getProperty("port") != null && !System.getProperty("port").isEmpty()) { + port = Integer.parseInt(System.getProperty("port")); + } + + if (System.getProperty("serial") != null) { + if (System.getProperty("serial").isEmpty()) { + System.err.println("Select serial port with: '-Dserial=COM_PORT'"); + System.exit(-1); + } + serial = System.getProperty("serial"); + } + + if (System.getProperty("baudrate") != null && !System.getProperty("baudrate").isEmpty()) { + baudrate = Integer.parseInt(System.getProperty("baudrate")); + } + + if (serial != null) { + return new SerialTransport(serial, baudrate); + } else { + try { + if (isServer) { + return new TCPTransport(port); + } else { + // client + return new TCPTransport(host, port); + } + } catch (IOException e) { + throw new RuntimeException("Error while creating TCPTransport(" + host + ", " + port + ")", e); + } + } + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingClient.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingClient.java new file mode 100644 index 00000000..b1674f26 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingClient.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests; + +import io.github.embeddedrpc.erpc.client.ClientManager; +import io.github.embeddedrpc.erpc.codec.BasicCodecFactory; +import io.github.embeddedrpc.erpc.codec.Codec; +import io.github.embeddedrpc.erpc.tests.Connection; +import io.github.embeddedrpc.erpc.transport.SerialTransport; +import io.github.embeddedrpc.erpc.transport.TCPTransport; +import io.github.embeddedrpc.erpc.transport.Transport; + +import java.io.IOException; + +public abstract class TestingClient { + protected final ClientManager clientManager; + + public TestingClient() { + clientManager = new ClientManager( + Connection.getConnectionFromSystemProperties(), + new BasicCodecFactory() + ); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingServer.java new file mode 100644 index 00000000..3b6df4ee --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/TestingServer.java @@ -0,0 +1,38 @@ +package io.github.embeddedrpc.erpc.tests; + +import io.github.embeddedrpc.erpc.codec.BasicCodecFactory; +import io.github.embeddedrpc.erpc.server.Server; +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.server.SimpleServer; +import io.github.embeddedrpc.erpc.transport.Transport; + + +public class TestingServer { + private static Transport transport; + private static Server server; + + public TestingServer(Service[] services) { + transport = Connection.getConnectionFromSystemProperties(); + server = new SimpleServer(transport, new BasicCodecFactory()); + + for (Service service : services) { + server.addService(service); + } + } + + public void run() { + if (server != null) { + server.run(); + } + } + + public static void stop() { + if (server != null) { + server.stop(); + } + + if (transport != null) { + transport.close(); + } + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestAnnotations.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestAnnotations.java new file mode 100644 index 00000000..245d9078 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestAnnotations.java @@ -0,0 +1,31 @@ +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.tests.test_annotations.test.client.AnnotateTestClient; +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_annotations.test.interfaces.IAnnotateTest; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestAnnotations extends TestingClient { + private final AnnotateTestClient client = new AnnotateTestClient(clientManager); + + @Test + public void runTestAnnotationServiceID() { + assertEquals(5, IAnnotateTest.SERVICE_ID); + } + + @Test + public void runTesttestIfMyIntAndConstExist() { + assertEquals(1, client.testIfMyIntAndConstExist(1)); + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestArrays.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestArrays.java new file mode 100644 index 00000000..95fcff3b --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestArrays.java @@ -0,0 +1,441 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.client.PointersServiceClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.common.structs.AllTypes; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.common.structs.C; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.interfaces.IPointersService; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import org.junit.jupiter.api.*; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestArrays extends TestingClient { + private final PointersServiceClient client = new PointersServiceClient(clientManager); + + @Test + public void runTestArraysServiceID() { + assertEquals(2, IPointersService.SERVICE_ID); + } + + @Test + public void runTestsendReceivedInt32() { + int[] sendArray = new int[12]; + int[] receivedArray; + + for (int i = 0; i < 12; i++) { + sendArray[i] = i; + } + + receivedArray = client.sendReceivedInt32(sendArray); + + for (int i = 0; i < 12; i++) { + assertEquals(receivedArray[i], sendArray[i]); + } + } + + @Test + public void runTestsendReceived2Int32() { + int[][] sendArray = new int[12][10]; + int[][] receivedArray; + + for (int a = 0; a < 12; a++) { + for (int b = 0; b < 10; b++) { + sendArray[a][b] = a * b; + } + } + + receivedArray = client.sendReceived2Int32(sendArray); + + for (int a = 0; a < 12; a++) { + for (int b = 0; b < 10; b++) { + assertEquals(sendArray[a][b], receivedArray[a][b]); + } + } + } + + @Test + public void runTestsendReceivedString() { + String[] sendArray = new String[12]; + String[] receiveArray; + + for (int i = 0; i < 12; i++) { + sendArray[i] = "Hello"; + } + + receiveArray = client.sendReceivedString(sendArray); + + for (int i = 0; i < 12; i++) { + assertEquals(sendArray[i], receiveArray[i]); + } + } + + @Test + public void runTestsendReceived2String() { + String[][] sendArray = new String[3][5]; + String[][] receiveArray; + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 5; b++) { + sendArray[a][b] = "Hello"; + } + } + + receiveArray = client.sendReceived2String(sendArray); + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 5; b++) { + assertEquals(sendArray[a][b], receiveArray[a][b]); + } + } + } + + @Test + public void runTestsendReceivedEnum() { + enumColor[] sendArray = new enumColor[3]; + enumColor[] receiveArray; + + sendArray[0] = enumColor.red; + sendArray[1] = enumColor.green; + sendArray[2] = enumColor.blue; + + receiveArray = client.sendReceivedEnum(sendArray); + + for (int i = 0; i < 3; i++) { + assertEquals(sendArray[i], receiveArray[i]); + } + } + + @Test + public void runTestsendReceived2Enum() { + enumColor[][] sendArray = new enumColor[3][3]; + enumColor[][] receiveArray; + + for (int a = 0; a < 3; a++) { + sendArray[a][0] = enumColor.red; + sendArray[a][1] = enumColor.green; + sendArray[a][2] = enumColor.blue; + } + + receiveArray = client.sendReceived2Enum(sendArray); + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 3; b++) { + assertEquals(sendArray[a][b], receiveArray[a][b]); + } + } + } + + @Test + public void runTestsendReceivedList() { + List[] sendArray = new List[]{List.of(0, 1), List.of(0, 1)}; + List[] receiveArray; + + receiveArray = client.sendReceivedList(sendArray); + + assertEquals(sendArray[0], receiveArray[0]); + assertEquals(sendArray[1], receiveArray[1]); + } + + @Test + public void runTestsendReceived2List() { + List[][] sendArray = new List[][]{ + {List.of(0, 1), List.of(0, 1)}, + {List.of(0, 1), List.of(0, 1)} + }; + List[][] receiveArray; + + receiveArray = client.sendReceived2List(sendArray); + + assertEquals(sendArray[0][0], receiveArray[0][0]); + assertEquals(sendArray[0][1], receiveArray[0][1]); + assertEquals(sendArray[1][0], receiveArray[1][0]); + assertEquals(sendArray[1][1], receiveArray[1][1]); + } + + @Test + public void runTestsendReceivedInt32Type() { + int[] sendArray = new int[12]; + int[] receivedArray; + + for (int i = 0; i < 12; i++) { + sendArray[i] = i; + } + + receivedArray = client.sendReceivedInt32(sendArray); + + for (int i = 0; i < 12; i++) { + assertEquals(receivedArray[i], sendArray[i]); + } + } + + @Test + public void runTestsendReceived2Int32Type() { + int[][] sendArray = new int[12][10]; + int[][] receivedArray; + + for (int a = 0; a < 12; a++) { + for (int b = 0; b < 10; b++) { + sendArray[a][b] = a * b; + } + } + + receivedArray = client.sendReceived2Int32(sendArray); + + for (int a = 0; a < 12; a++) { + for (int b = 0; b < 10; b++) { + assertEquals(sendArray[a][b], receivedArray[a][b]); + } + } + } + + @Test + public void runTestsendReceivedStringType() { + String[] sendArray = new String[12]; + String[] receiveArray; + + for (int i = 0; i < 12; i++) { + sendArray[i] = "Hello"; + } + + receiveArray = client.sendReceivedString(sendArray); + + for (int i = 0; i < 12; i++) { + assertEquals(sendArray[i], receiveArray[i]); + } + } + + @Test + public void runTestsendReceived2StringType() { + String[][] sendArray = new String[3][5]; + String[][] receiveArray; + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 5; b++) { + sendArray[a][b] = "Hello"; + } + } + + receiveArray = client.sendReceived2String(sendArray); + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 5; b++) { + assertEquals(sendArray[a][b], receiveArray[a][b]); + } + } + } + + @Test + public void runTestsendReceivedEnumType() { + enumColor[] sendArray = new enumColor[3]; + enumColor[] receiveArray; + + sendArray[0] = enumColor.red; + sendArray[1] = enumColor.green; + sendArray[2] = enumColor.blue; + + receiveArray = client.sendReceivedEnum(sendArray); + + for (int i = 0; i < 3; i++) { + assertEquals(sendArray[i], receiveArray[i]); + } + } + + @Test + public void runTestsendReceived2EnumType() { + enumColor[][] sendArray = new enumColor[3][3]; + enumColor[][] receiveArray; + + for (int a = 0; a < 3; a++) { + sendArray[a][0] = enumColor.red; + sendArray[a][1] = enumColor.green; + sendArray[a][2] = enumColor.blue; + } + + receiveArray = client.sendReceived2Enum(sendArray); + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 3; b++) { + assertEquals(sendArray[a][b], receiveArray[a][b]); + } + } + } + + @Test + public void runTestsendReceivedStructType() { + C[] sendArray = new C[3]; + C[] receiveArray; + + for (int a = 0; a < 3; a++) { + sendArray[a] = new C(a, a + 2); + } + + receiveArray = client.sendReceivedStructType(sendArray); + + for (int x = 0; x < 3; x++) { + assertEquals(sendArray[x].get_m(), receiveArray[x].get_m()); + assertEquals(sendArray[x].get_n(), receiveArray[x].get_n()); + } + } + + @Test + public void runTestsendReceived2StructType() { + C[][] sendArray = new C[3][3]; + C[][] receiveArray; + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 3; b++) { + sendArray[a][b] = new C(a, b); + } + } + + receiveArray = client.sendReceived2StructType(sendArray); + + for (int a = 0; a < 3; a++) { + for (int b = 0; b < 3; b++) { + assertEquals(sendArray[a][b].get_m(), receiveArray[a][b].get_m()); + assertEquals(sendArray[a][b].get_n(), receiveArray[a][b].get_n()); + } + } + } + + @Test + public void runTestsendReceivedListType() { + List[] sendArray = new List[]{List.of(0, 1), List.of(0, 1)}; + List[] receiveArray; + + receiveArray = client.sendReceivedList(sendArray); + + assertEquals(sendArray[0], receiveArray[0]); + assertEquals(sendArray[1], receiveArray[1]); + } + + @Test + public void runTestsendReceived2ListType() { + List[][] sendArray = new List[][]{ + {List.of(0, 1), List.of(0, 1)}, + {List.of(0, 1), List.of(0, 1)} + }; + List[][] receiveArray; + + receiveArray = client.sendReceived2List(sendArray); + + assertEquals(sendArray[0][0], receiveArray[0][0]); + assertEquals(sendArray[0][1], receiveArray[0][1]); + assertEquals(sendArray[1][0], receiveArray[1][0]); + assertEquals(sendArray[1][1], receiveArray[1][1]); + } + + @Test + public void runTestsendReceiveStruct() { + AllTypes[] sendArray = new AllTypes[2]; + AllTypes[] receiveArray; + + for (int i = 0; i < 2; i++) { + sendArray[i] = new AllTypes( + 5, + "Hello", + new C(5, 20), + enumColor.red, + List.of(0, 1, 2, 3, 4), + List.of("Hello", "Hello", "Hello", "Hello", "Hello"), + new int[]{0, 1, 2, 3, 4}, + new String[]{"Hello", "Hello", "Hello", "Hello", "Hello"} + ); + } + + + receiveArray = client.sendReceiveStruct(sendArray); + + for (int i = 0; i < 2; i++) { + assertEquals(receiveArray[i].get_number(), sendArray[i].get_number()); + assertEquals(receiveArray[i].get_text(), sendArray[i].get_text()); + assertEquals(receiveArray[i].get_color(), sendArray[i].get_color()); + assertEquals(receiveArray[i].get_c().get_m(), sendArray[i].get_c().get_m()); + assertEquals(receiveArray[i].get_c().get_n(), sendArray[i].get_c().get_n()); + assertEquals(receiveArray[i].get_list_numbers(), sendArray[i].get_list_numbers()); + assertEquals(receiveArray[i].get_list_text(), sendArray[i].get_list_text()); + assertArrayEquals(receiveArray[i].get_array_numbers(), sendArray[i].get_array_numbers()); + assertArrayEquals(receiveArray[i].get_array_text(), sendArray[i].get_array_text()); + } + + } + + @Test + public void runTestsendReceive2Struct() { + AllTypes[][] sendArray = new AllTypes[1][1]; + AllTypes[][] receiveArray; + + sendArray[0][0] = new AllTypes( + 5, + "Hello", + new C(5, 20), + enumColor.red, + List.of(0, 1, 2, 3, 4), + List.of("Hello", "Hello", "Hello", "Hello", "Hello"), + new int[]{0, 1, 2, 3, 4}, + new String[]{"Hello", "Hello", "Hello", "Hello", "Hello"} + ); + + receiveArray = client.sendReceive2Struct(sendArray); + + assertEquals(receiveArray[0][0].get_number(), sendArray[0][0].get_number()); + assertEquals(receiveArray[0][0].get_text(), sendArray[0][0].get_text()); + assertEquals(receiveArray[0][0].get_color(), sendArray[0][0].get_color()); + assertEquals(receiveArray[0][0].get_c().get_m(), sendArray[0][0].get_c().get_m()); + assertEquals(receiveArray[0][0].get_c().get_n(), sendArray[0][0].get_c().get_n()); + assertEquals(receiveArray[0][0].get_list_numbers(), sendArray[0][0].get_list_numbers()); + assertEquals(receiveArray[0][0].get_list_text(), sendArray[0][0].get_list_text()); + assertArrayEquals(receiveArray[0][0].get_array_numbers(), sendArray[0][0].get_array_numbers()); + assertArrayEquals(receiveArray[0][0].get_array_text(), sendArray[0][0].get_array_text()); + } + + @Test + public void runTesttest_array_allDirection() { + int[] aArray = new int[5]; + int[] bArray = new int[5]; + Reference cArray = new Reference<>(new int[5]); + Reference dArray = new Reference<>(new int[5]); + + int[] pAArray = new int[5]; + int[] pBArray = new int[5]; + int[] pCArray = new int[5]; + int[] pDArray = new int[5]; + + for (int a = 0; a < 5; a++) { + aArray[a] = a; + bArray[a] = a * 2; + dArray.get()[a] = a * 4; + + pAArray[a] = aArray[a]; + pBArray[a] = bArray[a]; + pCArray[a] = a + 1; + pDArray[a] = 2 * dArray.get()[a]; + } + + client.test_array_allDirection(aArray, bArray, cArray, dArray); + + for (int a = 0; a < 5; a++) { + assertEquals(aArray[a], pAArray[a]); + assertEquals(bArray[a], pBArray[a]); + assertEquals(cArray.get()[a], pCArray[a]); + assertEquals(dArray.get()[a], pDArray[a]); + } + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBinary.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBinary.java new file mode 100644 index 00000000..a88ef74d --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBinary.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import io.github.embeddedrpc.erpc.tests.test_binary.erpc_outputs.test.client.BinaryClient; +import io.github.embeddedrpc.erpc.tests.test_binary.erpc_outputs.test.interfaces.IBinary; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestBinary extends TestingClient { + private final BinaryClient client = new BinaryClient(clientManager); + + @Test + public void runTestsendBinary() { + client.sendBinary(new byte[]{0, 1, 2, 3, 4}); + } + + @Test + public void runTestBinaryServiceID() { + assertEquals(2, IBinary.SERVICE_ID); + } + + @Test + public void runTesttest_binary_allDirection() { + byte[] a_binary = new byte[5]; + byte[] b_binary = new byte[5]; + Reference e_binary = new Reference<>(new byte[5]); + + for (byte i = 0; i < 5; i++) { + a_binary[i] = i; + b_binary[i] = (byte) (i * 2); + e_binary.get()[i] = i; + } + + client.test_binary_allDirection(a_binary, b_binary, e_binary); + + for (byte i = 0; i < 5; i++) { + assertEquals(e_binary.get()[i], (a_binary[i] * b_binary[i])); + } + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBuiltin.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBuiltin.java new file mode 100644 index 00000000..27169549 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestBuiltin.java @@ -0,0 +1,193 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import io.github.embeddedrpc.erpc.tests.test_builtin.erpc_outputs.test.client.BuiltinServicesClient; +import io.github.embeddedrpc.erpc.tests.test_builtin.erpc_outputs.test.interfaces.IBuiltinServices; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestBuiltin extends TestingClient { + private final int gInt32AClient = 2; + private final int gInt32BClient = -20; + private final String gStringAClient = "Hello"; + private final String gStringBClient = "World!"; + + private final BuiltinServicesClient client = new BuiltinServicesClient(clientManager); + + @Test + public void runTestEnumsServiceID() { + assertEquals(2, IBuiltinServices.SERVICE_ID); + } + + @Test + public void runTesttest_int32_in_out() { + Reference int32C = new Reference<>(0); + + System.out.println("RPC request is sent to the server"); + client.test_int32_in(gInt32AClient); + + System.out.println("RPC request is sent to the server"); + client.test_int32_out(int32C); + + assertEquals(gInt32AClient, int32C.get()); + } + + @Test + public void runTesttest_int32_inout() { + Reference int32E = new Reference<>(-6); + + for (int i = -5; i < 5; i++) { + System.out.println("RPC request is sent to the server"); + client.test_int32_inout(int32E); + assertEquals(i, int32E.get()); + } + } + + @Test + public void runTestest_int32_return() { + int int32R = 0; + + System.out.println("RPC request is sent to the server"); + client.test_int32_in(gInt32AClient); + + System.out.println("RPC request is sent to the server"); + client.test_int32_in2(gInt32BClient); + + System.out.println("RPC request is sent to the server"); + int32R = client.test_int32_return(); + + assertEquals((gInt32AClient * gInt32BClient), int32R); + } + + @Test + public void runTestest_int32_allDirection() { + Reference int32C = new Reference<>(0); + Reference int32E = new Reference<>(7); + int int32R = 0; + + System.out.println("RPC request is sent to the server"); + int32R = client.test_int32_allDirection(gInt32AClient, gInt32BClient, int32C, int32E); + + assertEquals(int32C.get(), gInt32AClient); + assertEquals(14, int32E.get()); + assertEquals(int32E.get(), 14); + assertEquals((gInt32AClient * gInt32BClient), int32R); + } + @Test + public void runTestest_float_inout() { + float a = 3.14F; + Reference b = new Reference<>(0.0F); + + System.out.println("RPC request is sent to the server"); + client.test_float_inout(a, b); + + assertEquals(b.get(), a); + } + + @Test + public void runTestest_double_inout() { + double a = 3.14F; + Reference b = new Reference<>(0.0D); + + System.out.println("RPC request is sent to the server"); + client.test_double_inout(a, b); + + assertEquals(b.get(), a); + } + + @Test + @Order(1) + public void runTest1test_string_in_out() { + System.out.println("1"); + Reference stringC = new Reference<>(""); + + System.out.println("RPC request is sent to the server"); + client.test_string_in(gStringAClient); + System.out.println("RPC request is sent to the server"); + client.test_string_out(stringC); + + assertEquals(gStringAClient, stringC.get()); + } + + @Test + @Order(2) + public void runTest2test_string_inout() { + System.out.println("2"); + Reference stringE = new Reference<>(gStringAClient + " "); + + System.out.println("RPC request is sent to the server"); + client.test_string_in2(gStringBClient); + System.out.println("RPC request is sent to the server"); + client.test_string_inout(stringE); + + assertEquals("Hello World!", stringE.get()); + } + + @Test + @Order(3) + public void runTest3test_string_return() { + System.out.println("3"); + String stringR = ""; + + System.out.println("RPC request is sent to the server"); + stringR = client.test_string_return(); + + assertEquals("Hello World!", stringR); + } + + @Test + public void runTestest_string_allDirection() { + Reference stringC = new Reference<>(""); + Reference stringE = new Reference<>(gStringAClient + " "); + String stringR = ""; + + System.out.println("RPC request is sent to the server"); + stringR = client.test_string_allDirection(gStringAClient, gStringBClient, stringC, stringE); + + assertEquals(stringC.get(), gStringAClient); + assertEquals(stringE.get(), "Hello World!"); + assertEquals(stringR, "Hello World!"); + } + + @Test + public void runTesStringParamTest1() { + int int32R = -1; + + System.out.println("RPC request is sent to the server"); + int32R = client.sendHello("Hello World!"); + + assertEquals(int32R, 0); + } + + @Test + public void runTesStringParamTest2() { + int int32R = -1; + + System.out.println("RPC request is sent to the server"); + int32R = client.sendTwoStrings("String one.", "String two."); + + assertEquals(int32R, 0); + } + + @Test + public void runTesStringReturnTest1() { + System.out.println("RPC request is sent to the server"); + assertEquals("Hello", client.returnHello()); + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} \ No newline at end of file diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestConst.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestConst.java new file mode 100644 index 00000000..1b119683 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestConst.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import io.github.embeddedrpc.erpc.tests.test_const.erpc_outputs.test.common.Constants; +import io.github.embeddedrpc.erpc.tests.test_const.erpc_outputs.test.interfaces.IEmptyInterface; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestConst extends TestingClient { + @Test + public void runTestConstServiceID(){ + assertEquals(2, IEmptyInterface.SERVICE_ID); + } + + @Test + public void runTestCheckConsts(){ + assertEquals(3, Constants.a); + assertEquals(3.14F, Constants.b); + assertEquals("feedbabe", Constants.c); + assertEquals(3.14F, Constants.d); + assertEquals(11, Constants.x); + assertEquals(20, Constants.y); + assertEquals(100, Constants.mass); + assertEquals(-9.8F, Constants.accel); + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestEnums.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestEnums.java new file mode 100644 index 00000000..452244c8 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestEnums.java @@ -0,0 +1,111 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.client.EnumsServiceClient; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumColor2; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumErrorCode; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.interfaces.IEnumsService; +import org.junit.jupiter.api.*; + +import static io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumErrorCode.ERROR_NONE; +import static io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumErrorCode.ERROR_UNKNOWN; +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestEnums extends TestingClient { + private final enumColor gEnumColorAClient = enumColor.green; + private final enumColor gEnumColorBClient = enumColor.red; + + private final EnumsServiceClient client = new EnumsServiceClient(clientManager); + + @Test + public void runTestEnumsServiceID() { + assertEquals(2, IEnumsService.SERVICE_ID); + } + + @Test + public void runTesttest_enumColor_in_out() { + Reference enumColorC = new Reference<>(); + + System.out.println("RPC request is sent to the server"); + client.test_enumColor_in(gEnumColorAClient); + + System.out.println("RPC request is sent to the server"); + client.test_enumColor_out(enumColorC); + + assertEquals(enumColorC.get(), gEnumColorAClient); + } + + @Test + public void runTesttest_enumColor_inout() { + Reference enumColorE = new Reference<>(gEnumColorAClient); + + client.test_enumColor_inout(enumColorE); + + assertEquals(enumColorE.get(), gEnumColorBClient); + } + + @Test + public void runTesttest_enumColor_return() { +// client.test_enumColor_in(gEnumColorBClient); +// client.test_enumColor_in(gEnumColorBClient); + + } + + @Test + public void runTesttest_enumColor_allDirection() { + Reference enumColorC = new Reference<>(); + Reference enumColorE = new Reference<>(gEnumColorAClient); + enumColor enumColorR; + + enumColorR = client.test_enumColor_allDirection(gEnumColorAClient, gEnumColorBClient, enumColorC, enumColorE); + + assertEquals(gEnumColorAClient, enumColorC.get()); + assertEquals(gEnumColorBClient, enumColorE.get()); + assertEquals(gEnumColorAClient, enumColorR); + } + + @Test + public void runTesttest_enumColor2_allDirection() { + enumColor2 enumColor2A = enumColor2.pink; + enumColor2 enumColor2B = enumColor2.yellow; + Reference enumColor2C = new Reference<>(); + Reference enumColor2E = new Reference<>(enumColor2A); + enumColor2 enumColor2R; + + enumColor2R = client.test_enumColor2_allDirection(enumColor2A, enumColor2B, enumColor2C, enumColor2E); + + assertEquals(enumColor2A, enumColor2C.get()); + assertEquals(enumColor2B, enumColor2E.get()); + assertEquals(enumColor2A, enumColor2R); + } + + @Test + public void runTesttest_enumErrorCode_allDirection() { + enumErrorCode enumErrorCodeA = ERROR_NONE; + enumErrorCode enumErrorCodeB = ERROR_UNKNOWN; + Reference enumErrorCodeC = new Reference<>(); + Reference enumErrorCodeE = new Reference<>(ERROR_NONE); + enumErrorCode enumErrorCodeR; + + enumErrorCodeR = client.test_enumErrorCode_allDirection(enumErrorCodeA, enumErrorCodeB, enumErrorCodeC, enumErrorCodeE); + + assertEquals(enumErrorCodeA, enumErrorCodeC.get()); + assertEquals(enumErrorCodeB, enumErrorCodeE.get()); + assertEquals(enumErrorCodeA, enumErrorCodeR); + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestLists.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestLists.java new file mode 100644 index 00000000..2a75602e --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestLists.java @@ -0,0 +1,274 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.client.PointersServiceClient; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.C; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.gapAdStructure_t; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.gapAdvertisingData_t; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.listStruct; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.interfaces.IPointersService; +import org.junit.jupiter.api.*; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestLists extends TestingClient { + private final PointersServiceClient client = new PointersServiceClient(clientManager); + + @Test + public void runTestListsServiceID() { + assertEquals(2, IPointersService.SERVICE_ID); + } + + @Test + public void runSendReceivedInt32() { + List sendList = new ArrayList<>(12); + List receivedList; + + for (int i = 0; i < 12; i++) { + sendList.add(i); + } + + receivedList = client.sendReceivedInt32(sendList); + + for (int i = 0; i < receivedList.size(); i++) { + assertEquals(sendList.get(i), receivedList.get(i) / 2); + } + } + + @Test + public void runSendReceiveZeroSize() { + List sendList = List.of(0); + List receivedList; + + receivedList = client.sendReceivedInt32(sendList); + + assertEquals(List.of(0), receivedList); + } + + @Test + public void runSendReceived2Int32() { + List> sendList = new ArrayList<>(); + List> receivedList; + + for (int i = 0; i < 10; i++) { + List x = new ArrayList<>(); + for (int j = 0; j < i + 1; j++) { + x.add(j); + } + sendList.add(x); + } + + receivedList = client.sendReceived2Int32(sendList); + + for (int x = 0; x < receivedList.size(); x++) { + for (int y = 0; y < receivedList.get(x).size(); y++) { + assertEquals(sendList.get(x).get(y), receivedList.get(x).get(y) / 2); + } + } + } + + @Test + public void runSendReceivedEnum() { + List sendList = List.of(enumColor.red, enumColor.green, enumColor.blue); + List receivedList; + + receivedList = client.sendReceivedEnum(sendList); + + assertEquals(sendList, receivedList); + } + + @Test + public void runSendReceived2Enum() { + List> sendList = new ArrayList<>(); + List> receivedList; + + for (int a = 0; a < 3; a++) { + List x = new ArrayList<>(); + for (int b = 0; b < a + 1; b++) { + switch (b) { + case 0 -> x.add(enumColor.red); + case 1 -> x.add(enumColor.green); + case 2 -> x.add(enumColor.blue); + } + } + sendList.add(x); + } + + receivedList = client.sendReceived2Enum(sendList); + + assertEquals(sendList, receivedList); + } + + @Test + public void runSendReceivedStruct() { + List sendList = new ArrayList<>(); + List receivedList; + + for (int a = 0; a < 10; a++) { + sendList.add(new C(a, a * 2)); + } + + receivedList = client.sendReceivedStruct(sendList); + + for (int x = 0; x < receivedList.size(); x++) { + assertEquals(sendList.get(x).get_m(), receivedList.get(x).get_m() / 2); + assertEquals(sendList.get(x).get_n(), receivedList.get(x).get_n() / 2); + } + } + + @Test + public void runSendReceived2Struct() { + List> sendList = new ArrayList<>(); + List> receivedList; + + for (int a = 0; a < 3; a++) { + List x = new ArrayList<>(); + for (int b = 0; b < a + 1; b++) { + x.add(new C(a, b)); + } + sendList.add(x); + } + + receivedList = client.sendReceived2Struct(sendList); + + for (int x = 0; x < receivedList.size(); x++) { + for (int y = 0; y < receivedList.get(x).size(); y++) { + assertEquals(sendList.get(x).get(y).get_m(), receivedList.get(x).get(y).get_m() / 2); + assertEquals(sendList.get(x).get(y).get_n(), receivedList.get(x).get(y).get_n() / 2); + } + } + } + + @Test + public void runSendReceivedString() { + List sendList = new ArrayList<>(); + List receivedList; + + for (int i = 0; i < 12; i++) { + sendList.add("Hello"); + } + + receivedList = client.sendReceivedString(sendList); + + for (String x : receivedList) { + assertEquals("Hello World!", x); + } + } + + @Test + public void runSendReceived2String() { + List> sendList = new ArrayList<>(); + List> receivedList; + + for (int a = 0; a < 12; a++) { + List x = new ArrayList<>(); + for (int b = 0; b < a + 1; b++) { + x.add("Hello"); + } + sendList.add(x); + } + + receivedList = client.sendReceived2String(sendList); + + for (List strings : receivedList) { + for (String string : strings) { + assertEquals("Hello World!", string); + } + } + } + + @Test + public void runtest_list_allDirection() { + List sendListA = new ArrayList<>(); + List sendListB = new ArrayList<>(); + Reference> sendListC = new Reference<>(new ArrayList<>()); + + for (long i = 0; i < 10; i++) { + sendListA.add(i); + sendListB.add(i * 2); + sendListC.get().add(6 * i); + } + + client.test_list_allDirection(sendListA, sendListB, sendListC); + + for (int x = 0; x < sendListA.size(); x++) { + assertEquals(12 * sendListA.get(x), sendListC.get().get(x)); + } + } + + @Test + public void runtestLengthAnnotation() { + long length = 5; + List list = new ArrayList<>(); + int result; + + for (int i = 0; i < length; i++) { + list.add(i + 1); + } + + result = client.testLengthAnnotation(list); + + assertEquals(1, result); + } + + @Test + public void runtestLengthAnnotationInStruct() { + listStruct myListStruct = new listStruct(new ArrayList<>()); + int result; + + for (int x = 0; x < 5; x++) { + myListStruct.get_myList().add(x + 1); + } + + result = client.testLengthAnnotationInStruct(myListStruct); + + assertEquals(10, result); + } + + @Test + public void runreturnSentStructLengthAnnotation() { + listStruct myListStruct = new listStruct(new ArrayList<>()); + listStruct returnStruct; + + for (int x = 0; x < 5; x++) { + myListStruct.get_myList().add(x + 1); + } + + returnStruct = client.returnSentStructLengthAnnotation(myListStruct); + + for (int x = 0; x < returnStruct.get_myList().size(); x++) { + assertEquals(myListStruct.get_myList().get(x), returnStruct.get_myList().get(x)); + } + } + + @Test + public void runsendGapAdvertisingData() { + gapAdvertisingData_t ad = new gapAdvertisingData_t(new ArrayList<>()); + int result; + + for (int x = 0; x < 2; x++) { + ad.get_aAdStructures().add(new gapAdStructure_t((short) 5, List.of((short) 5, (short) 10, (short) 15))); + } + + result = client.sendGapAdvertisingData(ad); + assertEquals(33, result); + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestStruct.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestStruct.java new file mode 100644 index 00000000..9791ad70 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestStruct.java @@ -0,0 +1,177 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package io.github.embeddedrpc.erpc.tests.client; + + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.client.ArithmeticService1Client; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.client.ArithmeticService2Client; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.enums.school_year_t; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.structs.*; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.interfaces.IArithmeticService1; +import org.junit.jupiter.api.*; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestStruct extends TestingClient { + private final ArithmeticService1Client client1 = new ArithmeticService1Client(clientManager); + private final ArithmeticService2Client client2 = new ArithmeticService2Client(clientManager); + + @Test + public void runTestArithmeticServiceID() { + assertEquals(3, IArithmeticService1.SERVICE_ID); + } + + @Test + public void runGetMember1() { + C c = new C(4, 5); + + int r = client1.getMember(c); + + assertEquals(4, r); + } + + @Test + public void runNestedStruct1() { + C c = new C(4, 5); + D d = new D(c); + + int r = client1.sendNestedStruct(d); + + assertEquals(4, r); + } + + @Test + public void runReturnStruct1() { + B b; + + b = client1.returnStruct(3.14F, 2.71828F); + + assertEquals(3.14F, b.get_x()); + assertEquals(2.71828F, b.get_y()); + } + + @Test + public void runSendIntSizes() { + F f = new F((byte) -1, (short) -1, -1, (long) -1); + + assertEquals(0, client2.sendManyInts(f)); + } + + @Test + public void runSendUnsignedIntSizes() { + // UInt64 not supported + } + + @Test + public void runGetMember2() { + C c = new C(4, 5); + B b = new B(3.14F, 2.71828F); + A a = new A(b, c); + B bb; + + bb = client1.getMemberTest2(a); + + assertEquals(4.0F, bb.get_x()); + assertEquals(3.14F, bb.get_y()); + } + + @Test + public void runTestString1() { + primate prim8 = new primate("Ape", false); + + assertEquals(0, client1.checkString(prim8)); + } + + @Test + public void runTestReturnString1() { + stringStruct result; + + result = client1.returnStrings(); + + assertEquals("One", result.get_one()); + assertEquals("Two", result.get_two()); + assertEquals("Three", result.get_three()); + } + + @Test + public void runTestStudent1() { + student stud = new student("Donnie Darko", new float[]{85.75F, 93.29F, 92.46F}, school_year_t.SENIOR, 19); + assertEquals("Donnie Darko", client2.getStudentName(stud)); + assertEquals((stud.get_test_grades()[0] + stud.get_test_grades()[1] + stud.get_test_grades()[2]) / 3, client2.getStudentTestAverage(stud)); + assertEquals(19, client2.getStudentAge(stud)); + assertEquals(school_year_t.SENIOR.getValue(), client2.getStudentYear(stud)); + } + + @Test + public void runTestStudent2() { + student stud; + + stud = client2.createStudent("George Bush", new float[]{65.32F, 69.68F, 0}, school_year_t.FRESHMAN, 68); + assertEquals("George Bush", client2.getStudentName(stud)); + assertEquals((65.32 + 69.68 + 0) / 3, client2.getStudentTestAverage(stud)); + assertEquals(68, client2.getStudentAge(stud)); + assertEquals(school_year_t.FRESHMAN.getValue(), client2.getStudentYear(stud)); + } + + @Test + public void runtest_struct_allDirection() { + + byte[] a_binary = new byte[2]; + byte[] b_binary = new byte[2]; + byte[] e_binary = new byte[2]; + + for (byte i = 0; i < 2; i++) { + a_binary[i] = i; + b_binary[i] = (byte) (i * 2); + e_binary[i] = i; + } + + AllTypes a = new AllTypes(5, "Hello", enumColor.red, new C(5, 20), List.of(0, 1), List.of("Hello", "Hello"), new int[]{0, 1}, new String[]{"Hello", "Hello"}, a_binary); + AllTypes b = new AllTypes(10, "World", enumColor.green, new C(7, 17), List.of(1, 2), List.of("World", "World"), new int[]{1, 2}, new String[]{"World", "World"}, b_binary); + Reference e = new Reference<>(new AllTypes(15, "Hello", enumColor.blue, new C(4, 14), List.of(2, 3), List.of("Hello", "Hello"), new int[]{2, 3}, new String[]{"Hello", "Hello"}, e_binary)); + client2.test_struct_allDirection(a, b, e); + + assertEquals(e.get().get_number(), a.get_number() * b.get_number()); + assertEquals(e.get().get_text(), "World"); + assertEquals(e.get().get_color(), enumColor.green); + assertEquals(e.get().get_c().get_m(), a.get_c().get_m() * b.get_c().get_m()); + assertEquals(e.get().get_c().get_n(), a.get_c().get_n() * b.get_c().get_n()); + assertEquals(2, e.get().get_list_numbers().size()); + for (int i = 0; i < a.get_list_numbers().size(); i++) { + assertEquals(e.get().get_list_numbers().get(i), a.get_list_numbers().get(i) * b.get_list_numbers().get(i)); + assertEquals("World", e.get().get_list_text().get(i)); + } + + for (int i = 0; i < 2; i++) { + assertEquals(e.get().get_array_numbers()[i], a.get_array_numbers()[i] * b.get_array_numbers()[i]); + assertEquals("World", e.get().get_list_text().get(i)); + } + + for (int i = 0; i < a.get_binary_numbers().length; i++) { + assertEquals(e.get().get_binary_numbers()[i], a.get_binary_numbers()[i] * b.get_binary_numbers()[i]); + } + } + + @Test + public void runTestSendingByrefMembers() { + StructWithByrefMembers s; + int b = 4; + // Not sure how the test work + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestTypedef.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestTypedef.java new file mode 100644 index 00000000..aef3c12d --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/client/TestTypedef.java @@ -0,0 +1,103 @@ +package io.github.embeddedrpc.erpc.tests.client; + +import io.github.embeddedrpc.erpc.tests.TestingClient; +import io.github.embeddedrpc.erpc.tests.test_arrays.test_unit_test_common.client.CommonClient; +import io.github.embeddedrpc.erpc.tests.test_typedef.erpc_outputs.test.client.TypedefServiceClient; +import io.github.embeddedrpc.erpc.tests.test_typedef.erpc_outputs.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_typedef.erpc_outputs.test.common.structs.A; +import io.github.embeddedrpc.erpc.tests.test_typedef.erpc_outputs.test.interfaces.ITypedefService; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestTypedef extends TestingClient { + private final TypedefServiceClient client = new TypedefServiceClient(clientManager); + + @Test + public void runSendReceiveInt() { + int a = 10; + int b = 2 * a + 1; + assertEquals(b, client.sendReceiveInt(a)); + } + + @Test + public void runTestTypedefServiceID() { + assertEquals(2, ITypedefService.SERVICE_ID); + } + + @Test + public void runSendReceiveEnum() { + // Java have not typedef + enumColor a = enumColor.green; + + assertEquals(enumColor.blue, client.sendReceiveEnum(a)); + } + + @Test + public void runSendReceiveStruct() { + A a = new A(1, 4); + A b = new A(2 * a.get_m(), 2 + a.get_n()); + A r; + + r = client.sendReceiveStruct(a); + + assertEquals(b.get_m(), r.get_m()); + assertEquals(b.get_n(), r.get_n()); + } + + @Test + public void runSendReceiveListType() { + List sendList = new ArrayList<>(); + + for (int i = 0; i < 12; i++) { + sendList.add(i); + } + + List receivedList = client.sendReceiveListType(sendList); + + for (int x = 0; x < receivedList.size(); x++) { + assertEquals(sendList.get(x), receivedList.get(x) / 2); + } + } + + @Test + public void runSendReceiveString() { + String send = "Hello"; + + String received = client.sendReceiveString(send); + + assertEquals("Hello World!", received); + } + + @Test + public void runSendReceive2ListType() { + List> sendList = new ArrayList<>(); + + for (int i = 0; i < 10; i++) { + List tmp = new ArrayList<>(); + for (int j = 0; j < i + 1; j++) { + tmp.add(j); + } + sendList.add(tmp); + } + + List> receivedList = client.sendReceive2ListType(sendList); + + for (int x = 0; x < receivedList.size(); x++) { + for (int y = 0; y < receivedList.get(0).size(); y++) { + assertEquals(sendList.get(x).get(y), receivedList.get(x).get(y) / 2); + } + } + } + + @AfterAll + public void quit() { + new CommonClient(clientManager).quit(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestAnnotationsServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestAnnotationsServer.java new file mode 100644 index 00000000..3c9f6211 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestAnnotationsServer.java @@ -0,0 +1,15 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestAnnotationsService; +import org.junit.jupiter.api.Test; + +public class TestAnnotationsServer { + @Test + public void testAnnotationsServer() { + TestingServer server = new TestingServer(new Service[]{new TestAnnotationsService(), new CommonService()}); + server.run(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestArraysServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestArraysServer.java new file mode 100644 index 00000000..1b82416d --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestArraysServer.java @@ -0,0 +1,16 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestArraysService; +import org.junit.jupiter.api.Test; + +public class TestArraysServer { + + @Test + public void testArraysServer() { + TestingServer server = new TestingServer(new Service[]{new TestArraysService(), new CommonService()}); + server.run(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBinaryServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBinaryServer.java new file mode 100644 index 00000000..8a48b2d8 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBinaryServer.java @@ -0,0 +1,16 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestBinaryService; +import org.junit.jupiter.api.Test; + +public class TestBinaryServer { + + @Test + public void testBinaryServer() { + TestingServer server = new TestingServer(new Service[]{new TestBinaryService(), new CommonService()}); + server.run(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBuiltinServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBuiltinServer.java new file mode 100644 index 00000000..6247ac11 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestBuiltinServer.java @@ -0,0 +1,16 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestBuiltinService; +import org.junit.jupiter.api.Test; + +public class TestBuiltinServer { + + @Test + public void testBuiltinServer() { + TestingServer server = new TestingServer(new Service[]{new TestBuiltinService(), new CommonService()}); + server.run(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestConstServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestConstServer.java new file mode 100644 index 00000000..f910e63b --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestConstServer.java @@ -0,0 +1,16 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import org.junit.jupiter.api.Test; + +public class TestConstServer { + + @Test + public void testConstServer(){ + TestingServer server = new TestingServer(new Service[]{ new CommonService()}); + server.run(); + } + +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestEnumsServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestEnumsServer.java new file mode 100644 index 00000000..f860c39b --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestEnumsServer.java @@ -0,0 +1,16 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestEnumsService; +import org.junit.jupiter.api.Test; + +public class TestEnumsServer { + + @Test + public void testEnumServer() { + TestingServer server = new TestingServer(new Service[]{new TestEnumsService(), new CommonService()}); + server.run(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestListsServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestListsServer.java new file mode 100644 index 00000000..23a7ff25 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestListsServer.java @@ -0,0 +1,16 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestListsService; +import org.junit.jupiter.api.Test; + +public class TestListsServer { + + @Test + public void testListsServer() { + TestingServer server = new TestingServer(new Service[]{new TestListsService(), new CommonService()}); + server.run(); + } +} \ No newline at end of file diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestStructServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestStructServer.java new file mode 100644 index 00000000..346d3595 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestStructServer.java @@ -0,0 +1,20 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestStructService1; +import io.github.embeddedrpc.erpc.tests.server.services.TestStructService2; +import org.junit.jupiter.api.Test; + +public class TestStructServer { + @Test + public void testListsServer() { + TestingServer server = new TestingServer(new Service[]{ + new TestStructService1(), + new TestStructService2(), + new CommonService() + }); + server.run(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestTypedefServer.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestTypedefServer.java new file mode 100644 index 00000000..d0141eea --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/TestTypedefServer.java @@ -0,0 +1,18 @@ +package io.github.embeddedrpc.erpc.tests.server; + +import io.github.embeddedrpc.erpc.server.Service; +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.server.services.CommonService; +import io.github.embeddedrpc.erpc.tests.server.services.TestTypedefService; +import org.junit.jupiter.api.Test; + +public class TestTypedefServer { + @Test + public void testTypedefServer() { + TestingServer server = new TestingServer(new Service[]{ + new TestTypedefService(), + new CommonService() + }); + server.run(); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/CommonService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/CommonService.java new file mode 100644 index 00000000..1583db19 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/CommonService.java @@ -0,0 +1,17 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.tests.TestingServer; +import io.github.embeddedrpc.erpc.tests.test_const.erpc_outputs.test_unit_test_common.server.AbstractCommonService; + +public class CommonService extends AbstractCommonService { + + @Override + public void quit() { + TestingServer.stop(); + } + + @Override + public int getServerAllocated() { + return 0; + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestAnnotationsService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestAnnotationsService.java new file mode 100644 index 00000000..74c6e68a --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestAnnotationsService.java @@ -0,0 +1,28 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.tests.common.myEnum; +import io.github.embeddedrpc.erpc.tests.test_annotations.test.common.structs.fooStruct; +import io.github.embeddedrpc.erpc.tests.test_annotations.test.server.AbstractAnnotateTestService; + + +public class TestAnnotationsService extends AbstractAnnotateTestService { + @Override + public int add(int a, int b) { + return a + b; + } + + @Override + public void testIfFooStructExist(fooStruct a) { + } + + + @Override + public void testIfMyEnumExist(myEnum a) { + + } + + @Override + public int testIfMyIntAndConstExist(int a) { + return a; + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestArraysService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestArraysService.java new file mode 100644 index 00000000..86cb7845 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestArraysService.java @@ -0,0 +1,277 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.common.structs.AllTypes; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.common.structs.C; +import io.github.embeddedrpc.erpc.tests.test_arrays.test.server.AbstractPointersServiceService; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.structs.A; + +import java.util.List; + +public class TestArraysService extends AbstractPointersServiceService { + @Override + public int[] sendReceivedInt32(int[] arrayNumbers) { + System.out.println("sendReceivedInt32 reached"); + int[] sendArray = new int[12]; + + System.arraycopy(arrayNumbers, 0, sendArray, 0, 12); + + return sendArray; + } + + @Override + public int[][] sendReceived2Int32(int[][] arrayNumbers) { + System.out.println("sendReceived2Int32 reached"); + int[][] sendArray = new int[12][10]; + + for (int y = 0; y < 12; y++) { + System.arraycopy(arrayNumbers[y], 0, sendArray[y], 0, 10); + } + + return sendArray; + } + + @Override + public String[] sendReceivedString(String[] arrayStrings) { + System.out.println("sendReceivedString reached"); + String[] sendArray = new String[12]; + + System.arraycopy(arrayStrings, 0, sendArray, 0, 12); + + return sendArray; + } + + @Override + public String[][] sendReceived2String(String[][] arrayStrings) { + System.out.println("sendReceived2String reached"); + String[][] sendArray = new String[3][5]; + + for (int y = 0; y < 3; y++) { + System.arraycopy(arrayStrings[y], 0, sendArray[y], 0, 5); + } + + return sendArray; + } + + @Override + public enumColor[] sendReceivedEnum(enumColor[] arrayEnums) { + System.out.println("sendReceivedEnum reached"); + enumColor[] sendArray = new enumColor[3]; + + System.arraycopy(arrayEnums, 0, sendArray, 0, 3); + + return sendArray; + } + + @Override + public enumColor[][] sendReceived2Enum(enumColor[][] arrayEnums) { + System.out.println("sendReceived2Enum reached"); + enumColor[][] sendArray = new enumColor[3][3]; + + for (int y = 0; y < 3; y++) { + System.arraycopy(arrayEnums[y], 0, sendArray[y], 0, 3); + } + + return sendArray; + } + + @Override + public List[] sendReceivedList(List[] arrayLists) { + System.out.println("sendReceivedList reached"); + List[] sendArray = new List[2]; + + System.arraycopy(arrayLists, 0, sendArray, 0, 2); + + return sendArray; + } + + @Override + public List[][] sendReceived2List(List[][] arrayLists) { + System.out.println("sendReceived2List reached"); + List[][] sendArray = new List[2][2]; + + for (int y = 0; y < 2; y++) { + System.arraycopy(arrayLists[y], 0, sendArray[y], 0, 2); + } + + return sendArray; + } + + @Override + public int[] sendReceivedInt32Type(int[] arrayNumbers) { + System.out.println("sendReceivedInt32Type reached"); + int[] sendArray = new int[12]; + + System.arraycopy(arrayNumbers, 0, sendArray, 0, 12); + + return sendArray; + } + + @Override + public int[][] sendReceived2Int32Type(int[][] arrayNumbers) { + System.out.println("sendReceived2Int32Type reached"); + int[][] sendArray = new int[12][10]; + + for (int i = 0; i < 12; i++) { + for (int j = 0; j < 10; j++) { + sendArray[i][j] = arrayNumbers[i][j]; + } + } + + return sendArray; + } + + @Override + public String[] sendReceivedStringType(String[] arrayStrings) { + System.out.println("sendReceivedStringType reached"); + String[] sendArray = new String[12]; + + System.arraycopy(arrayStrings, 0, sendArray, 0, 12); + + return sendArray; + } + + @Override + public String[][] sendReceived2StringType(String[][] arrayStrings) { + System.out.println("sendReceived2StringType reached"); + String[][] sendArray = new String[3][5]; + + for (int y = 0; y < 3; y++) { + System.arraycopy(arrayStrings[y], 0, sendArray[y], 0, 5); + } + + return sendArray; + } + + @Override + public enumColor[] sendReceivedEnumType(enumColor[] arrayEnums) { + System.out.println("sendReceivedEnumType reached"); + enumColor[] sendArray = new enumColor[3]; + + System.arraycopy(arrayEnums, 0, sendArray, 0, 3); + + return sendArray; + } + + @Override + public enumColor[][] sendReceived2EnumType(enumColor[][] arrayEnums) { + System.out.println("sendReceived2EnumType reached"); + enumColor[][] sendArray = new enumColor[3][3]; + + for (int y = 0; y < 3; y++) { + System.arraycopy(arrayEnums[y], 0, sendArray[y], 0, 3); + } + + return sendArray; + } + + @Override + public C[] sendReceivedStructType(C[] arrayStructs) { + System.out.println("sendReceivedStructType reached"); + C[] sendArrays = new C[]{new C(), new C(), new C()}; + + for (int i = 0; i < 3; i++) { + sendArrays[i].set_m(arrayStructs[i].get_m()); + sendArrays[i].set_n(arrayStructs[i].get_n()); + } + + return sendArrays; + } + + @Override + public C[][] sendReceived2StructType(C[][] arrayStructs) { + System.out.println("sendReceived2StructType reached"); + C[][] sendArrays = new C[][]{ + {new C(), new C(), new C()}, + {new C(), new C(), new C()}, + {new C(), new C(), new C()} + }; + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + sendArrays[i][j].set_m(arrayStructs[i][j].get_m()); + sendArrays[i][j].set_n(arrayStructs[i][j].get_n()); + } + } + + return sendArrays; + } + + @Override + public List[] sendReceivedListType(List[] arrayLists) { + System.out.println("sendReceivedListType reached"); + List[] sendArray = new List[2]; + + System.arraycopy(arrayLists, 0, sendArray, 0, 2); + + return sendArray; + } + + @Override + public List[][] sendReceived2ListType(List[][] arrayLists) { + System.out.println("sendReceived2ListType reached"); + List[][] sendArray = new List[2][2]; + + for (int y = 0; y < 2; y++) { + System.arraycopy(arrayLists[y], 0, sendArray[y], 0, 2); + } + + return sendArray; + } + + @Override + public AllTypes[] sendReceiveStruct(AllTypes[] arrayStructs) { + System.out.println("sendReceiveStruct reached"); + AllTypes[] sendArrays = new AllTypes[]{new AllTypes(), new AllTypes()}; + + for (int y = 0; y < 2; y++) { + sendArrays[y].set_c(new C()); + sendArrays[y].set_number(arrayStructs[y].get_number()); + sendArrays[y].set_text(arrayStructs[y].get_text()); + sendArrays[y].set_color(arrayStructs[y].get_color()); + sendArrays[y].set_list_numbers(arrayStructs[y].get_list_numbers()); + sendArrays[y].set_list_text(arrayStructs[y].get_list_text()); + sendArrays[y].set_array_numbers(arrayStructs[y].get_array_numbers()); + sendArrays[y].set_array_text(arrayStructs[y].get_array_text()); + sendArrays[y].get_c().set_m(arrayStructs[y].get_c().get_m()); + sendArrays[y].get_c().set_n(arrayStructs[y].get_c().get_n()); + } + + return sendArrays; + } + + @Override + public AllTypes[][] sendReceive2Struct(AllTypes[][] arrayStructs) { + System.out.println("sendReceive2Struct reached"); + AllTypes[][] sendArrays = new AllTypes[][]{{new AllTypes()}}; + + for (int y = 0; y < 1; y++) { + for (int z = 0; z < 1; z++) { + sendArrays[y][z].set_c(new C()); + sendArrays[y][z].set_number(arrayStructs[y][z].get_number()); + sendArrays[y][z].set_text(arrayStructs[y][z].get_text()); + sendArrays[y][z].set_color(arrayStructs[y][z].get_color()); + sendArrays[y][z].set_list_numbers(arrayStructs[y][z].get_list_numbers()); + sendArrays[y][z].set_list_text(arrayStructs[y][z].get_list_text()); + sendArrays[y][z].set_array_numbers(arrayStructs[y][z].get_array_numbers()); + sendArrays[y][z].set_array_text(arrayStructs[y][z].get_array_text()); + sendArrays[y][z].get_c().set_m(arrayStructs[y][z].get_c().get_m()); + sendArrays[y][z].get_c().set_n(arrayStructs[y][z].get_c().get_n()); + } + } + + return sendArrays; + } + + @Override + public void test_array_allDirection(int[] a, int[] b, Reference c, Reference d) { + System.out.println("test_array_allDirection reached"); + c.set(new int[5]); + + for (int i = 0; i < 5; i++) { + c.get()[i] = i + 1; + d.get()[i] = i * 8; + } + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBinaryService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBinaryService.java new file mode 100644 index 00000000..85b24c87 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBinaryService.java @@ -0,0 +1,26 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.test_binary.erpc_outputs.test.server.AbstractBinaryService; + +public class TestBinaryService extends AbstractBinaryService { + @Override + public void sendBinary(byte[] a) { + System.out.println("sendBinary reached"); + } + + @Override + public void test_binary_allDirection(byte[] a, byte[] b, Reference e) { + System.out.println("test_binary_allDirection reached"); + e.set(new byte[5]); + + for (int i = 0; i < 5; i++) { + e.get()[i] = (byte) (a[i] * b[i]); + } + } + + @Override + public void test_binary_allDirectionLength(byte[] a, byte[] b, Reference d) { + System.out.println("test_binary_allDirectionLength reached"); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBuiltinService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBuiltinService.java new file mode 100644 index 00000000..bba50403 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestBuiltinService.java @@ -0,0 +1,131 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.test_builtin.erpc_outputs.test.server.AbstractBuiltinServicesService; +import org.junit.jupiter.api.Test; + +public class TestBuiltinService extends AbstractBuiltinServicesService { + private int int32A = 2; + private int int32B = -20; + private String stringA = "Hello"; + private String stringB = "World!"; + + @Override + public void test_int32_in(int a) { + System.out.println("test_int32_in reached"); + int32A = a; + } + + @Override + public void test_int32_in2(int b) { + System.out.println("test_int32_in2 reached"); + int32B = b; + } + + @Override + public void test_int32_out(Reference c) { + System.out.println("test_int32_out reached"); + c.set(int32A); + } + + @Override + public void test_int32_inout(Reference e) { + System.out.println("test_int32_inout reached"); + e.set(e.get() + 1); + } + + @Override + public int test_int32_return() { + System.out.println("test_int32_return reached"); + return int32A * int32B; + } + + @Override + public int test_int32_allDirection(int a, int b, Reference c, Reference e) { + System.out.println("test_int32_allDirection reached"); + c.set(a); + e.set(2 * e.get()); + return a * b; + } + + @Override + public void test_float_inout(float a, Reference b) { + System.out.println("test_float_inout reached"); + b.set(a); + } + + @Override + public void test_double_inout(double a, Reference b) { + System.out.println("test_double_inout reached"); + b.set(a); + } + + @Override + public void test_string_in(String a) { + System.out.println("test_string_in reached"); + stringA = a; + } + + @Override + public void test_string_in2(String b) { + System.out.println("test_string_in2 reached"); + stringB = b; + } + + @Override + public void test_string_out(Reference c) { + System.out.println("test_string_out reached"); + c.set(stringA); + } + + @Override + public void test_string_inout(Reference e) { + System.out.println("test_string_inout reached"); + e.set(e.get() + stringB); + } + + @Override + public String test_string_return() { + System.out.println("test_string_return reached"); + return stringA + " " + stringB; + } + + @Override + public String test_string_allDirection(String a, String b, Reference c, Reference e) { + System.out.println("test_string_allDirection reached"); + c.set(a); + e.set(e.get() + stringB); + return e.get(); + } + + @Override + public String test_string_empty(String a, String b, Reference c, Reference e) { + System.out.println("test_string_empty reached"); + return ""; + } + + @Override + public int sendHello(String str) { + System.out.println("sendHello reached"); + if (str.equals("Hello World!")) { + return 0; + } + return -1; + } + + @Override + public int sendTwoStrings(String myStr1, String myStr2) { + System.out.println("sendTwoStrings reached"); + if (myStr1.equals("String one.") && myStr2.equals("String two.")) { + return 0; + } + return -1; + } + + @Override + public String returnHello() { + System.out.println("returnHello reached"); + return "Hello"; + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestConstService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestConstService.java new file mode 100644 index 00000000..cc0c9ac7 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestConstService.java @@ -0,0 +1,6 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.tests.test_const.erpc_outputs.test.server.AbstractEmptyInterfaceService; + +public class TestConstService extends AbstractEmptyInterfaceService { +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestEnumsService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestEnumsService.java new file mode 100644 index 00000000..c18afb46 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestEnumsService.java @@ -0,0 +1,66 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumColor2; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.common.enums.enumErrorCode; +import io.github.embeddedrpc.erpc.tests.test_enums.erpc_outputs.test.server.AbstractEnumsServiceService; + +public class TestEnumsService extends AbstractEnumsServiceService { + private enumColor gEnumColorAServer = null; + private enumColor gEnumColorBServer = null; + + @Override + public void test_enumColor_in(enumColor a) { + System.out.println("test_enumColor_in reached"); + gEnumColorAServer = a; + } + + @Override + public void test_enumColor_in2(enumColor b) { + System.out.println("test_enumColor_in2 reached"); + gEnumColorBServer = b; + } + + @Override + public void test_enumColor_out(Reference c) { + System.out.println("test_enumColor_out reached"); + c.set(gEnumColorAServer); + } + + @Override + public void test_enumColor_inout(Reference e) { + System.out.println("test_enumColor_inout reached"); + e.set(enumColor.get(e.get().getValue() - 9)); + } + + @Override + public enumColor test_enumColor_return() { + System.out.println("test_enumColor_return reached"); + return enumColor.get(gEnumColorAServer.getValue() + 9); + } + + @Override + public enumColor test_enumColor_allDirection(enumColor a, enumColor b, Reference c, Reference e) { + System.out.println("test_enumColor_allDirection reached"); + c.set(a); + e.set(b); + return a; + } + + @Override + public enumColor2 test_enumColor2_allDirection(enumColor2 a, enumColor2 b, Reference c, Reference e) { + System.out.println("test_enumColor2_allDirection reached"); + c.set(a); + e.set(b); + return a; + } + + @Override + public enumErrorCode test_enumErrorCode_allDirection(enumErrorCode a, enumErrorCode b, Reference c, Reference e) { + System.out.println("test_enumErrorCode_allDirection reached"); + c.set(a); + e.set(b); + return a; + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestListsService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestListsService.java new file mode 100644 index 00000000..73411410 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestListsService.java @@ -0,0 +1,173 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.C; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.gapAdStructure_t; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.gapAdvertisingData_t; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.common.structs.listStruct; +import io.github.embeddedrpc.erpc.tests.test_lists.erpc_outputs.test.server.AbstractPointersServiceService; + +import java.util.ArrayList; +import java.util.List; + +public class TestListsService extends AbstractPointersServiceService { + @Override + public List sendReceivedInt32(List listNumbers) { + System.out.println("sendReceivedInt32 reached"); + List sendList = new ArrayList<>(); + + for (int i = 0; i < listNumbers.size(); i++) { + sendList.add(2 * listNumbers.get(i)); + } + + return sendList; + } + + @Override + public List> sendReceived2Int32(List> listNumbers) { + System.out.println("sendReceived2Int32 reached"); + List> sendList = new ArrayList<>(); + + for (int x = 0; x < listNumbers.size(); x++) { + sendList.add(new ArrayList<>()); + for (int y = 0; y < listNumbers.get(x).size(); y++) { + sendList.get(x).add(2 * listNumbers.get(x).get(y)); + } + } + + return sendList; + } + + @Override + public List sendReceivedEnum(List listColors) { + System.out.println("sendReceivedEnum reached"); + return new ArrayList<>(listColors); + } + + @Override + public List> sendReceived2Enum(List> listColors) { + System.out.println("sendReceived2Enum reached"); + return new ArrayList<>(listColors); + } + + @Override + public List sendReceivedStruct(List listColors) { + System.out.println("sendReceivedStruct reached"); + List sendList = new ArrayList<>(); + + for (C listColor : listColors) { + sendList.add(new C(2 * listColor.get_m(), 2 * listColor.get_n())); + } + + return sendList; + } + + @Override + public List> sendReceived2Struct(List> listColors) { + System.out.println("sendReceived2Struct reached"); + List> sendList = new ArrayList<>(); + + for (List listColor : listColors) { + List tmpList = new ArrayList<>(); + for (C c : listColor) { + tmpList.add(new C(2 * c.get_m(), 2 * c.get_n())); + } + sendList.add(tmpList); + } + + return sendList; + } + + @Override + public List sendReceivedString(List listNumbers) { + System.out.println("sendReceivedString reached"); + List sendList = new ArrayList<>(); + + for (String s : listNumbers) { + sendList.add(s + " World!"); + } + + return sendList; + } + + @Override + public List> sendReceived2String(List> listNumbers) { + System.out.println("sendReceived2String reached"); + List> sendList = new ArrayList<>(); + + for (List strings : listNumbers) { + List tmpList = new ArrayList<>(); + for (String string : strings) { + tmpList.add(string + " World!"); + } + sendList.add(tmpList); + } + + return sendList; + } + + @Override + public void test_list_allDirection(List a, List b, Reference> e) { + System.out.println("test_list_allDirection reached"); + for (int i = 0; i < a.size(); i++) { + e.get().set(i, 2 * e.get().get(i)); + } + } + + @Override + public int testLengthAnnotation(List myList) { + System.out.println("testLengthAnnotation reached"); + for (int i = 0; i < myList.size(); i++) { + if (myList.get(i) != i + 1) { + return 0; + } + } + + return 1; + } + + @Override + public int testLengthAnnotationInStruct(listStruct s) { + System.out.println("testLengthAnnotationInStruct reached"); + for (int i = 0; i < s.get_myList().size(); i++) { + if (s.get_myList().get(i) != i + 1) { + return 0; + } + } + + return 10; + } + + @Override + public listStruct returnSentStructLengthAnnotation(listStruct s) { + System.out.println("returnSentStructLengthAnnotation reached"); + listStruct ret = new listStruct(new ArrayList<>()); + + for (int i = 0; i < s.get_myList().size(); i++) { + ret.get_myList().add(s.get_myList().get(i)); + } + + return ret; + } + + @Override + public int sendGapAdvertisingData(gapAdvertisingData_t ad) { + System.out.println("sendGapAdvertisingData reached"); + List gapAdStructureTs = ad.get_aAdStructures(); + + for (gapAdStructure_t gapAdStructureT : gapAdStructureTs) { + if (gapAdStructureT.get_adType() != 5) { + return 0; + } + + for (int y = 0; y < gapAdStructureT.length(); y++) { + if (gapAdStructureT.get_aData().get(y) != ((y + 1) * 5)) { + return 0; + } + } + } + + return 33; + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService1.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService1.java new file mode 100644 index 00000000..81a88735 --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService1.java @@ -0,0 +1,42 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.structs.*; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.server.AbstractArithmeticService1Service; + +public class TestStructService1 extends AbstractArithmeticService1Service { + @Override + public int getMember(C c) { + System.out.println("getMember reached"); + return c.get_m(); + } + + @Override + public B returnStruct(float a, float b) { + System.out.println("returnStruct reached"); + return new B(a, b); + } + + @Override + public B getMemberTest2(A a) { + System.out.println("getMemberTest2 reached"); + return new B(a.get_c().get_m(), a.get_b().get_x()); + } + + @Override + public int sendNestedStruct(D d) { + System.out.println("sendNestedStruct reached"); + return d.get_c().get_m(); + } + + @Override + public int checkString(primate p) { + System.out.println("checkString reached"); + return !(p.get_species().equals("Ape")) ? 1 : 0; + } + + @Override + public stringStruct returnStrings() { + System.out.println("returnStrings reached"); + return new stringStruct("One", "Two", "Three"); + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService2.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService2.java new file mode 100644 index 00000000..7e55fe8a --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestStructService2.java @@ -0,0 +1,94 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.auxiliary.Reference; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.enums.school_year_t; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.common.structs.*; +import io.github.embeddedrpc.erpc.tests.test_struct.erpc_outputs.test_ArithmeticService.server.AbstractArithmeticService2Service; + +import java.util.ArrayList; + +public class TestStructService2 extends AbstractArithmeticService2Service { + @Override + public int sendManyInts(F f) { + System.out.println("sendManyInts reached"); + if (f.get_a() == -1 && f.get_b() == -1 && f.get_c() == -1 && f.get_d() == -1) { + return 0; + } + + return -1; + } + + @Override + public int sendManyUInts(G g) { + System.out.println("sendManyUInts reached"); + return 0; + } + + @Override + public String getStudentName(student stud) { + System.out.println("getStudentName reached"); + return stud.get_name(); + } + + @Override + public float getStudentTestAverage(student stud) { + System.out.println("getStudentTestAverage reached"); + float total = 0; + + for (var testGrade : stud.get_test_grades()) { + total += testGrade; + } + + return total / stud.get_test_grades().length; + } + + @Override + public int getStudentYear(student stud) { + System.out.println("getStudentYear reached"); + return stud.get_school_year().getValue(); + } + + @Override + public int getStudentAge(student stud) { + System.out.println("getStudentAge reached"); + return stud.get_age(); + } + + @Override + public student createStudent(String name, float[] test_scores, school_year_t year, int age) { + System.out.println("createStudent reached"); + return new student(name, test_scores, year, age); + } + + @Override + public void test_struct_allDirection(AllTypes a, AllTypes b, Reference e) { + System.out.println("test_struct_allDirection reached"); + AllTypes eStruct = e.get(); + + eStruct.set_number(a.get_number() * b.get_number()); + eStruct.set_text("World"); + eStruct.set_color(enumColor.green); + eStruct.set_c(new C(a.get_c().get_m() * b.get_c().get_m(), a.get_c().get_n() * b.get_c().get_n())); + + for (int i = 0; i < a.get_list_numbers().size(); i++) { + eStruct.get_list_numbers().set(i, a.get_list_numbers().get(i) * b.get_list_numbers().get(i)); + eStruct.get_list_text().set(i, "World"); + } + + for (int i = 0; i < a.get_array_numbers().length; i++) { + eStruct.get_array_numbers()[i] = a.get_array_numbers()[i] * b.get_array_numbers()[i]; + eStruct.get_array_text()[i] = "World"; + } + + for (int i = 0; i < a.get_binary_numbers().length; i++) { + eStruct.get_binary_numbers()[i] = (byte) (a.get_binary_numbers()[i] * b.get_binary_numbers()[i]); + } + } + + @Override + public boolean testSendingByrefMembers(StructWithByrefMembers s) { + System.out.println("testSendingByrefMembers reached"); + return false; + } +} diff --git a/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestTypedefService.java b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestTypedefService.java new file mode 100644 index 00000000..5d22185a --- /dev/null +++ b/test/java_impl_tests/src/test/java/io/github/embeddedrpc/erpc/tests/server/services/TestTypedefService.java @@ -0,0 +1,56 @@ +package io.github.embeddedrpc.erpc.tests.server.services; + +import io.github.embeddedrpc.erpc.tests.test_typedef.erpc_outputs.test.common.enums.enumColor; +import io.github.embeddedrpc.erpc.tests.test_typedef.erpc_outputs.test.common.structs.A; +import io.github.embeddedrpc.erpc.tests.test_typedef.erpc_outputs.test.server.AbstractTypedefServiceService; + +import java.util.ArrayList; +import java.util.List; + +public class TestTypedefService extends AbstractTypedefServiceService { + @Override + public int sendReceiveInt(int a) { + return a * 2 + 1; + } + + @Override + public enumColor sendReceiveEnum(enumColor a) { + return enumColor.get(a.getValue() + 1); + } + + @Override + public A sendReceiveStruct(A a) { + return new A(2 * a.get_m(), 2 + a.get_n()); + } + + @Override + public List sendReceiveListType(List listNumbers) { + List sendList = new ArrayList<>(); + + for (Integer listNumber : listNumbers) { + sendList.add(2 * listNumber); + } + + return sendList; + } + + @Override + public List> sendReceive2ListType(List> listNumbers) { + List> sendList = new ArrayList<>(); + + for (int x = 0; x < listNumbers.size(); x++) { + List tmp = new ArrayList<>(); + for (int y = 0; y < listNumbers.get(x).size(); y++) { + tmp.add(2 * listNumbers.get(x).get(y)); + } + sendList.add(tmp); + } + + return sendList; + } + + @Override + public String sendReceiveString(String hello) { + return hello + " World!"; + } +} diff --git a/test/mk/erpc_src.mk b/test/mk/erpc_src.mk index d27e8f43..fbaa7788 100644 --- a/test/mk/erpc_src.mk +++ b/test/mk/erpc_src.mk @@ -44,8 +44,11 @@ SOURCES += $(UT_COMMON_SRC)/addOne.cpp \ $(ERPC_C_ROOT)/infra/erpc_message_buffer.cpp \ $(ERPC_C_ROOT)/infra/erpc_message_loggers.cpp \ $(ERPC_C_ROOT)/infra/erpc_transport_arbitrator.cpp \ + $(ERPC_C_ROOT)/infra/erpc_utils.cpp \ $(ERPC_C_ROOT)/port/erpc_port_stdlib.cpp \ $(ERPC_C_ROOT)/port/erpc_threading_pthreads.cpp \ - $(ERPC_C_ROOT)/port/erpc_serial.cpp \ - $(ERPC_C_ROOT)/transports/erpc_serial_transport.cpp \ $(ERPC_C_ROOT)/transports/erpc_tcp_transport.cpp +ifeq "$(is_mingw)" "" + SOURCES += $(ERPC_C_ROOT)/transports/erpc_serial_transport.cpp \ + $(ERPC_C_ROOT)/port/erpc_serial.cpp +endif diff --git a/test/mk/test.mk b/test/mk/test.mk index 4ab0ab21..028524db 100644 --- a/test/mk/test.mk +++ b/test/mk/test.mk @@ -45,7 +45,7 @@ UNIT_OUT_DIR = $(OUTPUT_ROOT)/$(DEBUG_OR_RELEASE)/$(os_name)/test/ ERPC_NAME ?= test ERPC_NAME_APP ?= $(ERPC_NAME) -TEST_DIR = $(OUTPUT_ROOT)/test/$(TEST_NAME)/$(os_name)/$(TRANSPORT)/gcc/$(TEST_NAME)_$(APP_TYPE)/$(DEBUG_OR_RELEASE) +TEST_DIR = $(OUTPUT_ROOT)/test/$(TEST_NAME)/$(os_name)/$(TRANSPORT)/$(CC)/$(TEST_NAME)_$(APP_TYPE)/$(DEBUG_OR_RELEASE) RPC_OBJS_ROOT = $(TEST_DIR) TARGET_OUTPUT_ROOT = $(RPC_OBJS_ROOT) @@ -75,12 +75,16 @@ INCLUDES += $(TARGET_OUTPUT_ROOT) \ #------------------------------- IDL_FILE = $(CUR_DIR).erpc -ifneq "$(TEST_NAME)" "test_arbitrator" +ifeq (,$(filter $(TEST_NAME),test_arbitrator test_callbacks)) INCLUDES += $(ERPC_ROOT)/test/common/config SOURCES += $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_$(APP_TYPE).cpp \ $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_interface.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME_APP)_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp \ $(CUR_DIR)_$(APP_TYPE)_impl.cpp \ $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_$(APP_TYPE).cpp @@ -91,7 +95,7 @@ all: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAM # Define dependency. $(OUTPUT_ROOT)/test/$(TEST_NAME)/$(CUR_DIR)_$(APP_TYPE)_impl.cpp: $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_$(APP_TYPE).cpp $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_$(APP_TYPE).cpp -$(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_interface.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/c_$(ERPC_NAME_APP)_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp # Run erpcgen for C. $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp: $(IDL_FILE) @@ -106,13 +110,20 @@ $(ERPC_OUT_DIR)/$(ERPC_NAME)/$(APP_TYPE).py: $(IDL_FILE) # Add libtest.a to build. LIBRARIES += -ltest LDFLAGS += -L$(OUTPUT_ROOT)/$(DEBUG_OR_RELEASE)/$(os_name)/test/lib +ifeq "$(is_mingw)" "1" + LIBRARIES += -lws2_32 +endif +else +ifeq (,$(filter $(TEST_NAME),test_arbitrator)) + INCLUDES += $(ERPC_ROOT)/test/common/config else + INCLUDES += $(OUTPUT_ROOT)/test/$(TEST_NAME)/config +endif + ERPC_C_ROOT = $(ERPC_ROOT)/erpc_c include $(ERPC_ROOT)/test/mk/erpc_src.mk - INCLUDES += $(OUTPUT_ROOT)/test/$(TEST_NAME)/config - ifeq "$(TYPE)" "CLIENT" include $(TEST_ROOT)/$(TEST_NAME)/client.mk else diff --git a/test/mk/unit_test.mk b/test/mk/unit_test.mk index 7c80b813..92a8c62c 100644 --- a/test/mk/unit_test.mk +++ b/test/mk/unit_test.mk @@ -27,9 +27,17 @@ CLIENT_NAME = $(TEST_NAME)_client SERVER_NAME = $(TEST_NAME)_server ERPCGEN_PATH = $(ERPC_ROOT)/$(BUILD_TYPE)/$(os_name)/erpcgen/erpcgen UT_OUTPUT_DIR = $(OUTPUT_ROOT)/test/$(TEST_NAME) -TCP_CLIENT_PATH = $(UT_OUTPUT_DIR)/$(os_name)/tcp/gcc/$(CLIENT_NAME)/$(DEBUG_OR_RELEASE)/$(CLIENT_NAME)_tcp_test -TCP_SERVER_PATH = $(UT_OUTPUT_DIR)/$(os_name)/tcp/gcc/$(SERVER_NAME)/$(DEBUG_OR_RELEASE)/$(SERVER_NAME)_tcp_test - +TCP_CLIENT_PATH = $(UT_OUTPUT_DIR)/$(os_name)/tcp/$(CC)/$(CLIENT_NAME)/$(DEBUG_OR_RELEASE)/$(CLIENT_NAME)_tcp_test +TCP_SERVER_PATH = $(UT_OUTPUT_DIR)/$(os_name)/tcp/$(CC)/$(SERVER_NAME)/$(DEBUG_OR_RELEASE)/$(SERVER_NAME)_tcp_test + +test_server_serial = test_server_serial +test_client_serial = test_client_serial +clean_serial = clean_serial +ifeq "$(is_mingw)" "1" + test_server_serial = + test_client_serial = + clean_serial = +endif .PHONY: all all: test_lib test_client test_server @@ -50,7 +58,7 @@ test-serial: test_lib test_client_serial test_server_serial fresh: clean all .PHONY: test_client -test_client: test_client_tcp test_client_serial +test_client: test_client_tcp $(test_client_serial) .PHONY: test_client_tcp test_client_tcp: erpcgen @@ -67,7 +75,7 @@ else endif .PHONY: test_server -test_server: test_server_tcp test_server_serial +test_server: test_server_tcp $(test_server_serial) .PHONY: test_server_tcp test_server_tcp: erpcgen @@ -105,7 +113,7 @@ run-erpcgen-common: erpcgen #cleans only output directories related to this unit test .PHONY: clean clean_serial clean_tcp -clean: clean_serial clean_tcp +clean: $(clean_serial) clean_tcp clean_tcp: @echo Cleaning $(TEST_NAME)_tcp... diff --git a/test/python_impl_tests/README.md b/test/python_impl_tests/README.md new file mode 100644 index 00000000..5c848554 --- /dev/null +++ b/test/python_impl_tests/README.md @@ -0,0 +1,7 @@ +# Python implementation testing directory # + +This directory contains acceptance tests for Python implementation. +To trigger the execution with using TCP communication run **pytest -vs --client --server** from this folder or +enter the *scripts/test_case* subfolder and run individual test using **pytest -vs --client --server** +To trigger the execution with using Serial communication run **pytest -vs --client --serial="COM_ID"** from the +*scripts/test_case* subfolder and run individual test using **pytest -vs --client --serial="COM_ID"** diff --git a/test/python_impl_tests/scripts.code-workspace b/test/python_impl_tests/scripts.code-workspace new file mode 100644 index 00000000..527ff6e3 --- /dev/null +++ b/test/python_impl_tests/scripts.code-workspace @@ -0,0 +1,162 @@ +{ "folders": [ + { + "name": "INTERNAL", + "path": "." + } + ], + "settings": { + "launch": { + "configurations": [ + { + "name": "test_annotations_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_annotations/test_annotations.py", + "args": ["-c", "-s"] + },{ + "name": "test_arrays_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_arrays/test_arrays.py", + "args": ["-c", "-s"] + },{ + "name": "test_binary_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_binary/test_binary.py", + "args": ["-c", "-s"] + },{ + "name": "test_builtin_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_builtin/test_builtin.py", + "args": ["-c", "-s"] + },{ + "name": "test_const_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_const/test_const.py", + "args": ["-c", "-s"] + },{ + "name": "test_enums_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_enums/test_enums.py", + "args": ["-c", "-s"] + },{ + "name": "test_lists_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_lists/test_lists.py", + "args": ["-c", "-s"] + },{ + "name": "test_struct_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_struct/test_struct.py", + "args": ["-c", "-s"] + },{ + "name": "test_typedef_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_typedef/test_typedef.py", + "args": ["-c", "-s"] + },{ + "name": "test_unions_tcp_client_server", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_unions/test_unions.py", + "args": ["-c", "-s"] + },{ + "name": "test_annotations_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_annotations/test_annotations.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_arrays_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_arrays/test_arrays.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_binary_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_binary/test_binary.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_builtin_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_builtin/test_builtin.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_const_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_const/test_const.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_enums_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_enums/test_enums.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_lists_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_lists/test_lists.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_struct_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_struct/test_struct.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_typedef_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_typedef/test_typedef.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_unions_uart_client", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_unions/test_unions.py", + "args": ["-c", "-S", "COM3"] + },{ + "name": "test_annotations_tcp_client_server_ip", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder:INTERNAL}/scripts", + "program": "${workspaceFolder:INTERNAL}/scripts/test_annotations/test_annotations.py", + "args": ["-s", "-c", "-t", "192.168.1.249", "-p", "54321"] + }, + ], + "compounds": [] + }, + } +} \ No newline at end of file diff --git a/test/python_impl_tests/scripts/common/common.py b/test/python_impl_tests/scripts/common/common.py new file mode 100644 index 00000000..4f781eff --- /dev/null +++ b/test/python_impl_tests/scripts/common/common.py @@ -0,0 +1,41 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +#from service import test_unit_test_common +from service.test_const.erpc_outputs import test_unit_test_common +from server.serverTCP import ServerTCP + +############################################################################### +# Variables +############################################################################### + + +############################################################################### +# Functions +############################################################################### + +def runTesttestQuit(client): + # send request to the server + print('\r\neRPC request is sent to the server') + return client.quit() + +############################################################################### +# Server +############################################################################### + +## Add service handler +class CommonTestServiceHandler(test_unit_test_common.interface.ICommon): + ## eRPC add method + # @param a First addend + # @param b Second addend + def quit(self): + print('\r\nquit service reached: \r\n=============') + sys.stdout.flush() + ServerTCP.stopServer() + return diff --git a/test/python_impl_tests/scripts/conftest.py b/test/python_impl_tests/scripts/conftest.py new file mode 100644 index 00000000..5c024662 --- /dev/null +++ b/test/python_impl_tests/scripts/conftest.py @@ -0,0 +1,23 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import pytest + + +def pytest_addoption(parser): + parser.addoption("--client", action="store_true", default=False, help="run all combinations") + parser.addoption("--server", action="store_true", default=False, help="run all combinations") + parser.addoption("--host", action="store", default='localhost', help="run all combinations") + parser.addoption("--port", action="store", default='12345', help="run all combinations") + parser.addoption("--serial", action="store", default=None, help="run all combinations") + parser.addoption("--baud", action="store", default='115200', help="run all combinations") + +#def pytest_exception_interact(node, call, report): +# excinfo = call.excinfo +# if 'script' in node.funcargs: +# excinfo.traceback = excinfo.traceback.cut(path=node.funcargs['script']) +# report.longrepr = node.repr_failure(excinfo) \ No newline at end of file diff --git a/test/python_impl_tests/scripts/server/clientTCP.py b/test/python_impl_tests/scripts/server/clientTCP.py new file mode 100644 index 00000000..e053eda8 --- /dev/null +++ b/test/python_impl_tests/scripts/server/clientTCP.py @@ -0,0 +1,40 @@ +#!/usr/bin/python + +# Copyright 2022 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import print_function +import os, sys, inspect +from .connection import ConnectionTCP, Client +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Client +############################################################################### + +class ClientTCP(ConnectionTCP, Client): + + def __init__(self, host, port): + ConnectionTCP.__init__(self, host, port) + Client.__init__(self) + self.server = False + # initialize TCP transport layer + try: + self.transport = erpc.transport.TCPTransport(host, int(port), self.server) + except ConnectionRefusedError: + print("eRPC server not found.") + sys.exit() + + ## Run client on specified transport layer + def runClient(self, constructors): + print('Client connecting to a host on \"%s:%s\".' % (self.host, self.port)) + # create test eRPC service + clientManager = erpc.client.ClientManager(self.transport, erpc.basic_codec.BasicCodec) + self.initClients(constructors, clientManager) diff --git a/test/python_impl_tests/scripts/server/clientUART.py b/test/python_impl_tests/scripts/server/clientUART.py new file mode 100644 index 00000000..05e68931 --- /dev/null +++ b/test/python_impl_tests/scripts/server/clientUART.py @@ -0,0 +1,39 @@ +#!/usr/bin/python + +# Copyright 2022 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import print_function +import os, sys, inspect +from .connection import ConnectionUART, Client +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Client +############################################################################### + +class ClientUART(ConnectionUART, Client): + + def __init__(self, port, baudrate): + ConnectionUART.__init__(self, port, baudrate) + Client.__init__(self) + # initialize TCP transport layer + try: + self.transport = erpc.transport.SerialTransport(self.port, self.baudrate) + except ConnectionRefusedError: + print("eRPC server not found.") + sys.exit() + + ## Run client on specified transport layer + def runClient(self, constructors): + print('Client connecting to a host on port %s with baudrate %s bps.' % (self.port, self.baudrate)) + # create test annotations eRPC service + clientManager = erpc.client.ClientManager(self.transport, erpc.basic_codec.BasicCodec) + self.initClients(constructors, clientManager) \ No newline at end of file diff --git a/test/python_impl_tests/scripts/server/connection.py b/test/python_impl_tests/scripts/server/connection.py new file mode 100644 index 00000000..dda5bbe5 --- /dev/null +++ b/test/python_impl_tests/scripts/server/connection.py @@ -0,0 +1,54 @@ +#!/usr/bin/python + +# Copyright 2022 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +############################################################################### +# Server +############################################################################### + +class Server: + def __init__(self): + self.serverServices = [] + +############################################################################### +# Client +############################################################################### + +class Client: + def __init__(self): + self.clientServices = [] + + def initClients(self, constructors, clientManager): + for constructor in constructors: + self.clientServices.append(constructor(clientManager)) + + def getClient(self, serviceId): + for service in self.clientServices: + if service.SERVICE_ID == serviceId: + return service + return None + +############################################################################### +# Connection +############################################################################### + +############################################################################### +# TCP +############################################################################### + +class ConnectionTCP(): + def __init__(self, host, port): + self.host = host + self.port = int(port) + +############################################################################### +# UART +############################################################################### + +class ConnectionUART(): + def __init__(self, port, baudrate): + self.port = port + self.baudrate = int(baudrate) diff --git a/test/python_impl_tests/scripts/server/runner.py b/test/python_impl_tests/scripts/server/runner.py new file mode 100644 index 00000000..b3582696 --- /dev/null +++ b/test/python_impl_tests/scripts/server/runner.py @@ -0,0 +1,67 @@ +#!/usr/bin/python + +# Copyright 2022 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import sys, argparse +from .serverTCP import ServerTCP +from .clientTCP import ClientTCP +from .clientUART import ClientUART +from .serverUART import ServerUART +from subprocess import Popen + +class Runner: + + def __init__(self, name, params, services, constructors): + self.services = services if isinstance(services, list) else [services] + self.constructors = constructors if isinstance(constructors, list) else [constructors] + self.client = None + self.proc = None + self.argParser = self.initParser() + try: + self.args = self.argParser.parse_args() + except: + args = [item for item in sys.argv if (item in ['-c', '-s', '--server', '--client']) or ('=' in item)] + self.args = self.argParser.parse_args(args) + self.initTest(name, params) + + def initParser(self): + # parse cmd parameters + argParser = argparse.ArgumentParser(description='eRPC Matrix Multiply example') + argParser.add_argument('-c', '--client', action='store_true', help='Run client') + argParser.add_argument('-s', '--server', action='store_true', help='Run server') + argParser.add_argument('-t', '--host', default='localhost', help='Host IP address (default value is localhost)') + argParser.add_argument('-p', '--port', default='12345', help='Port (default value is 12345)') + argParser.add_argument('-S', '--serial', default=None, help='Serial device (default value is None)') + argParser.add_argument('-B', '--baud', default='115200', help='Baud (default value is 115200)') + return argParser + + def initTest(self, name, params): + # check if either server or client has been selected + if not self.args.client and not self.args.server: + self.argParser.print_help() + sys.exit('\r\nEither server or client has to be selected to run') + if self.args.client and self.args.server: + print('eRPC ' + name + ' server') + cmd = ['python'] + params + ["-t", self.args.host, "-p", self.args.port] + self.proc = Popen(cmd) + if self.args.client: + print('eRPC ' + name + ' client') + #wait a while for server start + if self.args.server: + import time + time.sleep(1) + self.client = ClientUART(self.args.serial, int(self.args.baud)) if self.args.serial else ClientTCP(self.args.host, self.args.port) + self.client.runClient(self.constructors) + elif self.args.server and self.services != None and self.proc is None: + print('eRPC ' + name + ' server run') + tcp_server = ServerUART(self.args.serial, int(self.args.baud)) if self.args.serial else ServerTCP(self.args.host, self.args.port) + tcp_server.runServer(self.services) + + def runTest(self, clientIdx, *funcs): + if self.client is None: + return + for items in funcs: + items(self.client.getClient(clientIdx)) diff --git a/test/python_impl_tests/scripts/server/serverTCP.py b/test/python_impl_tests/scripts/server/serverTCP.py new file mode 100644 index 00000000..0694aca1 --- /dev/null +++ b/test/python_impl_tests/scripts/server/serverTCP.py @@ -0,0 +1,52 @@ +#!/usr/bin/python + +# Copyright 2022 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import os, sys, inspect +from .connection import ConnectionTCP +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Server +############################################################################### + +class ServerTCP(ConnectionTCP): + server=None + + def __init__(self, host, port): + ConnectionTCP.__init__(self, host, port) + self.server = True + # initialize TCP transport layer + self.transport = erpc.transport.TCPTransport(host, int(port), self.server) + + ## Run server on specified transport layer + def runServer(self, services): + # Note: TCP server is ran in daemon thread, so flush is needed to see printouts + print('Server created on \"%s:%s\"' % (self.host, self.port)) + # create eRPC service for current test + if services[0] is None: + print('\r\neRPC service not found.') + sys.exit() + # run server + ServerTCP.server = erpc.simple_server.SimpleServer(self.transport, erpc.basic_codec.BasicCodec) + for service in services: + ServerTCP.server.add_service(service) + print('\r\nWait for client to send a eRPC request') + sys.stdout.flush() + try: + ServerTCP.server.run() + except: + print("Server closed!") + ## Run server on specified transport layer + def stopServer(): + if ServerTCP.server is not None: + ServerTCP.server.stop() + diff --git a/test/python_impl_tests/scripts/server/serverUART.py b/test/python_impl_tests/scripts/server/serverUART.py new file mode 100644 index 00000000..c63d6f0f --- /dev/null +++ b/test/python_impl_tests/scripts/server/serverUART.py @@ -0,0 +1,51 @@ +#!/usr/bin/python + +# Copyright 2022 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import os, sys, inspect +from .connection import ConnectionUART +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Server +############################################################################### + +class ServerUART(ConnectionUART): + server=None + def __init__(self, port, baudrate): + ConnectionUART.__init__(self, port, baudrate) + self.server = True + # initialize TCP transport layer + self.transport = erpc.transport.SerialTransport(port, baudrate, self.server) + + ## Run server on specified transport layer + def runServer(self, services): + # Note: TCP server is ran in daemon thread, so flush is needed to see printouts + print('Server created on port %s with baudrate %s bps.' % (self.port, self.baudrate)) + # create eRPC service for current test + if services[0] is None: + print('\r\neRPC service not found.') + sys.exit() + # run server + ServerUART.server = erpc.simple_server.SimpleServer(self.transport, erpc.basic_codec.BasicCodec) + for service in services: + ServerUART.server.add_service(service) + print('\r\nWait for client to send a eRPC request') + sys.stdout.flush() + try: + ServerUART.server.run() + except: + print("Server closed!") + ## Run server on specified transport layer + def stopServer(): + if ServerUART.server is not None: + ServerUART.server.stop() + diff --git a/test/python_impl_tests/scripts/service/__init__.py b/test/python_impl_tests/scripts/service/__init__.py new file mode 100644 index 00000000..5c054291 --- /dev/null +++ b/test/python_impl_tests/scripts/service/__init__.py @@ -0,0 +1,12 @@ +# Copyright (c) 2016, Freescale Semiconductor, Inc. +# Copyright 2016 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +# +# Generated by erpcgen 1.9.1 on Tue Jun 21 11:28:31 2022. +# +# AUTOGENERATED - DO NOT EDIT +# + diff --git a/test/python_impl_tests/scripts/service/test_binary/__init__.py b/test/python_impl_tests/scripts/service/test_binary/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/service/test_builtin/__init__.py b/test/python_impl_tests/scripts/service/test_builtin/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/service/test_const/__init__.py b/test/python_impl_tests/scripts/service/test_const/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/service/test_enums/__init__.py b/test/python_impl_tests/scripts/service/test_enums/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/service/test_group/__init__.py b/test/python_impl_tests/scripts/service/test_group/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/service/test_lists/__init__.py b/test/python_impl_tests/scripts/service/test_lists/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/service/test_typedef/__init__.py b/test/python_impl_tests/scripts/service/test_typedef/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/service/test_unions/__init__.py b/test/python_impl_tests/scripts/service/test_unions/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/python_impl_tests/scripts/test_annotations/test_annotations.py b/test/python_impl_tests/scripts/test_annotations/test_annotations.py new file mode 100644 index 00000000..36013524 --- /dev/null +++ b/test/python_impl_tests/scripts/test_annotations/test_annotations.py @@ -0,0 +1,103 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_annotations import test as test_annotations +from service.test_annotations import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit + +############################################################################### +# Variables +############################################################################### + + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class AnnotateTestServiceHandler(test_annotations.interface.IAnnotateTest): + ## eRPC add method + # @param a First addend + # @param b Second addend + def add(self, a, b): + print('\r\add service reached: a=',a,'b=',b, '\r\n=============') + sys.stdout.flush() + return a + b + + def testIfFooStructExist(self, a): + return + + def testIfMyEnumExist(self, a): + return + + def testIfMyIntAndConstExist(self, a): + return a + +############################################################################### +# Client +############################################################################### + +def runTestIncludeAnnotationCheck(client): + # send request to the server + print('\r\neRPC request is sent to the server') + assert 5 == client.addOne(4) + +## Individual test cases / eRPC calls +def runTestAnnotationServiceID(client): + assert 5 == test_annotations.interface.IAnnotateTest.SERVICE_ID + +def runTesttestIfMyIntAndConstExist(client): + # send request to the server + print('\r\neRPC request is sent to the server') + assert 1 == client.testIfMyIntAndConstExist(1) + +############################################################################### +# PYTESTS +############################################################################### +class TestAnnotation: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_annotations.server.AnnotateTestService(AnnotateTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_annotations.client.AnnotateTestClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestAnnotation.runner = Runner('test_annotations', TestAnnotation.server_cmd, TestAnnotation.services, TestAnnotation.clientsConstructors) + + def test_runTestAnnotationServiceID(self): + self.runner.runTest(test_annotations.interface.IAnnotateTest.SERVICE_ID , runTestAnnotationServiceID) + + def test_runTesttestIfMyIntAndConstExist(self): + self.runner.runTest(test_annotations.interface.IAnnotateTest.SERVICE_ID , runTesttestIfMyIntAndConstExist) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestAnnotationServiceID() + self.test_runTesttestIfMyIntAndConstExist() + self.test_runTesttestQuit() + +#TBD runTestIncludeAnnotationCheck(client) + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + #sys.exit(pytest.main(["-qq"], plugins=[TestAnnotation.close()])) + tester = TestAnnotation() + tester.runTests() + diff --git a/test/python_impl_tests/scripts/test_arrays/test_arrays.py b/test/python_impl_tests/scripts/test_arrays/test_arrays.py new file mode 100644 index 00000000..944dbed5 --- /dev/null +++ b/test/python_impl_tests/scripts/test_arrays/test_arrays.py @@ -0,0 +1,620 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() +from service.test_arrays import test as test_arrays +from service.test_arrays import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit + +############################################################################### +# Variables +############################################################################### + + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class ArraysTestServiceHandler(test_arrays.interface.IPointersService): + def sendReceivedInt32(self, arrayNumbers): + print('sendReceivedInt32 service reached\r\n=============') + sys.stdout.flush() + sendArrays = [] + for y in range(12): + #sendArrays[y] = arrayNumbers[y] + sendArrays.append(arrayNumbers[y]) + return sendArrays + + def sendReceived2Int32(self, arrayNumbers): + print('sendReceived2Int32 service reached\r\n=============') + sys.stdout.flush() + sendArrays = [[0 for a in range(10)] for b in range(12)] + for y in range(12): + for z in range(10): + sendArrays[y][z] = arrayNumbers[y][z] + return sendArrays + + def sendReceivedString(self, arrayStrings): + print('sendReceivedString service reached\r\n=============') + sys.stdout.flush() + sendArrays = ["" for a in range(12)] + for y in range(12): + sendArrays[y] = arrayStrings[y] + return sendArrays + + def sendReceived2String(self, arrayStrings): + print('sendReceived2String service reached\r\n=============') + sys.stdout.flush() + sendArrays = [["" for a in range(5)] for b in range(3)] + for y in range(3): + for z in range(5): + sendArrays[y][z] = arrayStrings[y][z] + return sendArrays + + def sendReceivedEnum(self, arrayEnums): + print('sendReceivedEnum service reached\r\n=============') + sys.stdout.flush() + sendArrays = [] + for y in range(3): + sendArrays.append(arrayEnums[y]) + return sendArrays + + def sendReceived2Enum(self, arrayEnums): + print('sendReceived2Enum service reached\r\n=============') + sys.stdout.flush() + sendArrays = [[0 for a in range(3)] for b in range(3)] + for y in range(3): + for z in range(3): + sendArrays[y][z] = arrayEnums[y][z] + return sendArrays + + def sendReceivedList(self, arrayLists): + print('sendReceivedList service reached\r\n=============') + sys.stdout.flush() + sendArrays = [] + for y in range(2): + sendArrays.append(arrayLists[y]) + return sendArrays + + def sendReceived2List(self, arrayLists): + print('ssendReceived2List service reached\r\n=============') + sys.stdout.flush() + sendArrays = [[0 for a in range(2)] for b in range(2)] + for y in range(2): + for z in range(2): + sendArrays[y][z] = arrayLists[y][z] + return sendArrays + + def sendReceivedInt32Type(self, arrayNumbers): + print('sendReceivedInt32Type service reached\r\n=============') + sys.stdout.flush() + sendArrays = [] + for y in range(12): + #sendArrays[y] = arrayNumbers[y] + sendArrays.append(arrayNumbers[y]) + return sendArrays + + def sendReceived2Int32Type(self, arrayNumbers): + print('sendReceived2Int32Type service reached\r\n=============') + sys.stdout.flush() + sendArrays = [] + for y in range(12): + #sendArrays[y] = arrayNumbers[y] + sendArrays.append(arrayNumbers[y]) + return sendArrays + + def sendReceivedStringType(self, arrayStrings): + print('sendReceivedStringType service reached\r\n=============') + sys.stdout.flush() + sendArrays = ["" for a in range(12)] + for y in range(12): + sendArrays[y] = arrayStrings[y] + return sendArrays + + def sendReceived2StringType(self, arrayStrings): + print('sendReceived2StringType service reached\r\n=============') + sys.stdout.flush() + sendArrays = [["" for a in range(5)] for b in range(3)] + for y in range(3): + for z in range(5): + sendArrays[y][z] = arrayStrings[y][z] + return sendArrays + + def sendReceivedEnumType(self, arrayEnums): + print('sendReceivedEnumType service reached\r\n=============') + sys.stdout.flush() + sendArrays = [] + for y in range(3): + sendArrays.append(arrayEnums[y]) + return sendArrays + + def sendReceived2EnumType(self, arrayEnums): + print('sendReceived2EnumType service reached\r\n=============') + sys.stdout.flush() + sendArrays = [[0 for a in range(3)] for b in range(3)] + for y in range(3): + for z in range(3): + sendArrays[y][z] = arrayEnums[y][z] + return sendArrays + + def sendReceivedStructType(self, arrayStructs): + print('sendReceivedStructType service reached\r\n=============') + #print(arrayStructs) + sys.stdout.flush() + sendArrays = [test_arrays.common.C() for b in range(3)] + for y in range(3): + sendArrays[y].m = arrayStructs[y].m + sendArrays[y].n = arrayStructs[y].n + return sendArrays + + def sendReceived2StructType(self, arrayStructs): + print('sendReceived2StructType service reached\r\n=============') + #print(arrayStructs) + sys.stdout.flush() + sendArrays = [[test_arrays.common.C() for a in range(3)] for b in range(3)] + for y in range(3): + for z in range(3): + sendArrays[y][z].m = arrayStructs[y][z].m + sendArrays[y][z].n = arrayStructs[y][z].n + return sendArrays + + def sendReceivedListType(self, arrayLists): + print('sendReceivedListType service reached\r\n=============') + sys.stdout.flush() + sendArrays = [] + for y in range(2): + sendArrays.append(arrayLists[y]) + return sendArrays + + def sendReceived2ListType(self, arrayLists): + print('sendReceived2ListType service reached\r\n=============') + sys.stdout.flush() + sendArrays = [[0 for a in range(2)] for b in range(2)] + for y in range(2): + for z in range(2): + sendArrays[y][z] = arrayLists[y][z] + return sendArrays + + def sendReceiveStruct(self, all_types): + print('sendReceiveStruct service reached\r\n=============') + #print(all_types) + sys.stdout.flush() + sendArrays = [test_arrays.common.AllTypes() for b in range(2)] + for y in range(2): + sendArrays[y].c = test_arrays.common.C() + sendArrays[y].number = all_types[y].number + sendArrays[y].text = all_types[y].text + sendArrays[y].color = all_types[y].color + sendArrays[y].c.m = all_types[y].c.m + sendArrays[y].c.n = all_types[y].c.n + sendArrays[y].list_numbers = all_types[y].list_numbers + sendArrays[y].list_text = all_types[y].list_text + sendArrays[y].array_numbers = all_types[y].array_numbers + sendArrays[y].array_text = all_types[y].array_text + return sendArrays + + def sendReceive2Struct(self, all_types): + print('sendReceive2Struct service reached\r\n=============') + #print(all_types) + sys.stdout.flush() + sendArrays = [[test_arrays.common.AllTypes() for a in range(1)] for b in range(1)] + for y in range(1): + for z in range(1): + sendArrays[y][z].c = test_arrays.common.C() + sendArrays[y][z].number = all_types[y][z].number + sendArrays[y][z].text = all_types[y][z].text + sendArrays[y][z].color = all_types[y][z].color + sendArrays[y][z].c.m = all_types[y][z].c.m + sendArrays[y][z].c.n = all_types[y][z].c.n + sendArrays[y][z].list_numbers = all_types[y][z].list_numbers + sendArrays[y][z].list_text = all_types[y][z].list_text + sendArrays[y][z].array_numbers = all_types[y][z].array_numbers + sendArrays[y][z].array_text = all_types[y][z].array_text + #print(sendArrays) + return sendArrays + + def test_array_allDirection(self, a, b, c, d): + print('test_array_allDirection service reached\r\n=============') + sys.stdout.flush() + #c array is defined as an out parameter and needs to be initialized first + c.value = [0 for a in range(5)] + for y in range(5): + c.value[y] = y + 1 + d.value[y] = y * 8 + return + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls +def runTestsendReceivedInt32(client): + send_array = range(12) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedInt32(send_array) + for x in range(12): + assert received_array[x] == send_array[x] + #print(received_array[x]) + +def runTestArraysServiceID(client): + assert 2 == test_arrays.interface.IPointersService.SERVICE_ID + +def runTestsendReceived2Int32(client): + send_array = [[0 for a in range(10)] for b in range(12)] + #print(send_array) + for a in range(12): + for b in range(10): + send_array[a][b] = a*b + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2Int32(send_array) + for a in range(12): + for b in range(10): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceivedString(client): + send_array = ["Hello" for a in range(12)] + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedString(send_array) + for x in range(12): + assert received_array[x] == send_array[x] + +def runTestsendReceived2String(client): + send_array = [["Hello" for a in range(5)] for b in range(3)] + received_array = [["" for a in range(5)] for b in range(3)] + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2String(send_array) + for a in range(3): + for b in range(5): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceivedEnum(client): + send_array = [] + send_array.append(test_arrays.common.enumColor.red) + send_array.append(test_arrays.common.enumColor.green) + send_array.append(test_arrays.common.enumColor.blue) + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedEnum(send_array) + for x in range(3): + assert received_array[x] == send_array[x] + +def runTestsendReceived2Enum(client): + send_array = [[0 for a in range(3)] for b in range(3)] + for a in range(3): + send_array[a][0] = test_arrays.common.enumColor.red + send_array[a][1] = test_arrays.common.enumColor.green + send_array[a][2] = test_arrays.common.enumColor.blue + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2Enum(send_array) + for a in range(3): + for b in range(3): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceivedList(client): + send_array = [[0, 1] for a in range(2)] + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedList(send_array) + for x in range(2): + assert received_array[x] == send_array[x] + +def runTestsendReceived2List(client): + send_array = [[[0, 1] for a in range(2)] for b in range(2)] + received_array = [[0 for a in range(2)] for b in range(2)] + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2List(send_array) + for a in range(2): + for b in range(2): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceivedInt32Type(client): + send_array = range(12) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedInt32Type(send_array) + for x in range(12): + assert received_array[x] == send_array[x] + #print(received_array[x]) + +def runTestsendReceived2Int32Type(client): + send_array = [[0 for a in range(10)] for b in range(12)] + #print(send_array) + for a in range(12): + for b in range(10): + send_array[a][b] = a*b + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2Int32Type(send_array) + for a in range(12): + for b in range(10): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceivedStringType(client): + send_array = ["Hello" for a in range(12)] + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedStringType(send_array) + for x in range(12): + assert received_array[x] == send_array[x] + +def runTestsendReceived2StringType(client): + send_array = [["Hello" for a in range(5)] for b in range(3)] + received_array = [["" for a in range(5)] for b in range(3)] + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2StringType(send_array) + for a in range(3): + for b in range(5): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceivedEnumType(client): + send_array = [] + send_array.append(test_arrays.common.enumColor.red) + send_array.append(test_arrays.common.enumColor.green) + send_array.append(test_arrays.common.enumColor.blue) + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedEnumType(send_array) + for x in range(3): + assert received_array[x] == send_array[x] + +def runTestsendReceived2EnumType(client): + send_array = [[0 for a in range(3)] for b in range(3)] + for a in range(3): + send_array[a][0] = test_arrays.common.enumColor.red + send_array[a][1] = test_arrays.common.enumColor.green + send_array[a][2] = test_arrays.common.enumColor.blue + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2EnumType(send_array) + for a in range(3): + for b in range(3): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceivedStructType(client): + send_array = [0 for b in range(3)] + for a in range(3): + send_array[a] = test_arrays.common.C(a, a + 2) + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedStructType(send_array) + #print(received_array) + for x in range(3): + assert received_array[x].m == send_array[x].m + assert received_array[x].n == send_array[x].n + +def runTestsendReceived2StructType(client): + send_array = [[0 for a in range(3)] for b in range(3)] + for a in range(3): + for b in range(3): + send_array[a][b] = test_arrays.common.C(a, b) + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2StructType(send_array) + #print(received_array) + for a in range(3): + for b in range(3): + assert received_array[a][b].m == send_array[a][b].m + assert received_array[a][b].n == send_array[a][b].n + +def runTestsendReceivedListType(client): + send_array = [[0, 1] for a in range(2)] + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceivedListType(send_array) + for x in range(2): + assert received_array[x] == send_array[x] + +def runTestsendReceived2ListType(client): + send_array = [[[0, 1] for a in range(2)] for b in range(2)] + received_array = [[0 for a in range(2)] for b in range(2)] + #print(send_array) + # send request to the server + print('\r\neRPC request is sent to the server') + received_array = client.sendReceived2ListType(send_array) + for a in range(2): + for b in range(2): + assert received_array[a][b] == send_array[a][b] + +def runTestsendReceiveStruct(client): + send_array = [0 for b in range(2)] + for a in range(2): + send_array[a] = test_arrays.common.AllTypes(5, "Hello", test_arrays.common.C(5, 20), test_arrays.common.enumColor.red, [0, 1, 2, 3, 4], ["Hello" for b in range(5)], [0, 1, 2, 3, 4], ["Hello" for b in range(5)]) + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceiveStruct(send_array) + #print(received_array) + for x in range(2): + assert received_array[x].number == send_array[x].number + assert received_array[x].text == send_array[x].text + assert received_array[x].color == send_array[x].color + assert received_array[x].c.m == send_array[x].c.m + assert received_array[x].c.n == send_array[x].c.n + assert received_array[x].list_numbers == send_array[x].list_numbers + assert received_array[x].list_text == send_array[x].list_text + assert received_array[x].array_numbers == send_array[x].array_numbers + assert received_array[x].array_text == send_array[x].array_text + +def runTestsendReceive2Struct(client): + send_array = [[(test_arrays.common.AllTypes(5, "Hello", test_arrays.common.C(5, 20), test_arrays.common.enumColor.red, [0, 1, 2, 3, 4], ["Hello" for b in range(5)], [0, 1, 2, 3, 4], ["Hello" for b in range(5)])) for x in range(1)] for y in range(1)] + received_array = [[0 for a in range(1)] for b in range(1)] + #print(send_array) + print('\r\neRPC request is sent to the server') + received_array = client.sendReceive2Struct(send_array) + #print(received_array) + for x in range(1): + for y in range(1): + assert received_array[x][y].number == send_array[x][y].number + assert received_array[x][y].text == send_array[x][y].text + assert received_array[x][y].color == send_array[x][y].color + assert received_array[x][y].c.m == send_array[x][y].c.m + assert received_array[x][y].c.n == send_array[x][y].c.n + assert received_array[x][y].list_numbers == send_array[x][y].list_numbers + assert received_array[x][y].list_text == send_array[x][y].list_text + assert received_array[x][y].array_numbers == send_array[x][y].array_numbers + assert received_array[x][y].array_text == send_array[x][y].array_text + +def runTesttest_array_allDirection(client): + a_array = [0 for a in range(5)] + b_array = [0 for a in range(5)] + c_array = erpc.Reference() + d_array = erpc.Reference() + c_array.value = [0 for a in range(5)] + d_array.value = [0 for a in range(5)] + pA_array = [0 for a in range(5)] + pB_array = [0 for a in range(5)] + pC_array = [0 for a in range(5)] + pD_array = [0 for a in range(5)] + for a in range(5): + a_array[a] = a + b_array[a] = a * 2 + d_array.value[a] = a * 4 + pA_array[a] = a_array[a] + pB_array[a] = b_array[a] + pC_array[a] = a + 1 + pD_array[a] = 2 * d_array.value[a] + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_array_allDirection(a_array, b_array, c_array, d_array) + for a in range(5): + assert a_array[a] == pA_array[a] + assert b_array[a] == pB_array[a] + assert c_array.value[a] == pC_array[a] + assert d_array.value[a] == pD_array[a] + +############################################################################### +# PYTESTS +############################################################################### +class TestArrays: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_arrays.server.PointersServiceService(ArraysTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_arrays.client.PointersServiceClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestArrays.runner = Runner('test_arrays', TestArrays.server_cmd, TestArrays.services, TestArrays.clientsConstructors) + + def test_runTestArraysServiceID(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestArraysServiceID) + + def test_runTestsendReceivedInt32(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedInt32) + + def test_runTestsendReceived2Int32(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2Int32) + + def test_runTestsendReceivedString(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedString) + + def test_runTestsendReceived2String(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2String) + + def test_runTestsendReceivedEnum(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedEnum) + + def test_runTestsendReceived2Enum(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2Enum) + + def test_runTestsendReceivedList(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedList) + + def test_runTestsendReceived2List(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2List) + + def test_runTestsendReceivedInt32Type(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedInt32Type) + + def test_runTestsendReceived2Int32Type(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2Int32Type) + + def test_runTestsendReceivedStringType(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedStringType) + + def test_runTestsendReceived2StringType(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2StringType) + + def test_runTestsendReceivedStructType(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedStructType) + + def test_runTestsendReceived2StructType(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2StructType) + + def test_runTestsendReceivedListType(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceivedListType) + + def test_runTestsendReceived2ListType(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceived2ListType) + + def test_runTestsendReceiveStruct(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceiveStruct) + + def test_runTestsendReceive2Struct(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTestsendReceive2Struct) + + def test_runTesttest_array_allDirection(self): + self.runner.runTest(test_arrays.interface.IPointersService.SERVICE_ID, runTesttest_array_allDirection) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestArraysServiceID() + self.test_runTestsendReceivedInt32() + self.test_runTestsendReceived2Int32() + self.test_runTestsendReceivedString() + self.test_runTestsendReceived2String() + self.test_runTestsendReceivedEnum() + self.test_runTestsendReceived2Enum() + self.test_runTestsendReceivedList() + self.test_runTestsendReceived2List() + self.test_runTestsendReceivedInt32Type() + self.test_runTestsendReceived2Int32Type() + self.test_runTestsendReceivedStringType() + self.test_runTestsendReceived2StringType() + self.test_runTestsendReceivedStructType() + self.test_runTestsendReceived2StructType() + self.test_runTestsendReceivedListType() + self.test_runTestsendReceived2ListType() + self.test_runTestsendReceiveStruct() + self.test_runTestsendReceive2Struct() + self.test_runTesttest_array_allDirection() + self.test_runTesttestQuit() + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestArrays() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_binary/test_binary.py b/test/python_impl_tests/scripts/test_binary/test_binary.py new file mode 100644 index 00000000..288bfe59 --- /dev/null +++ b/test/python_impl_tests/scripts/test_binary/test_binary.py @@ -0,0 +1,116 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_binary.erpc_outputs import test as test_binary +from service.test_binary.erpc_outputs import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Variables +############################################################################### + + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class BinaryTestServiceHandler(test_binary.interface.IBinary): + def sendBinary(self, a): + #print(a) + return + + def test_binary_allDirection(self, a, b, e): + e.value = bytearray(b'') + for x in range(5): + e.value.append(a[x] * b[x]) + return + + def test_binary_allDirectionLength(self, a, b, d, p1): + return + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls +def runTestsendBinary(client): + send_binary = b'01234' + # send request to the server + print('\r\neRPC request is sent to the server') + client.sendBinary(send_binary) + +def runTestBinaryServiceID(client): + assert 2 == test_binary.interface.IBinary.SERVICE_ID + +def runTesttest_binary_allDirection(client): + a_binary = bytearray(b'') + b_binary = bytearray(b'') + e_binary = erpc.Reference() + e_binary.value = bytearray(b'') + for x in range(5): + a_binary.append(x) + b_binary.append(x * 2) + e_binary.value.append(x) + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_binary_allDirection(a_binary, b_binary, e_binary) + #print(e_binary) + for x in range(5): + assert e_binary.value[x] == (a_binary[x] * b_binary[x]) + +############################################################################### +# PYTESTS +############################################################################### +class TestBinary: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_binary.server.BinaryService(BinaryTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_binary.client.BinaryClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestBinary.runner = Runner('test_binary', TestBinary.server_cmd, TestBinary.services, TestBinary.clientsConstructors) + + def test_runTestBinaryServiceID(self): + self.runner.runTest(test_binary.interface.IBinary.SERVICE_ID, runTestBinaryServiceID) + + def test_runTestsendBinary(self): + self.runner.runTest(test_binary.interface.IBinary.SERVICE_ID, runTestsendBinary) + + def test_runTesttest_binary_allDirection(self): + self.runner.runTest(test_binary.interface.IBinary.SERVICE_ID, runTesttest_binary_allDirection) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestBinaryServiceID() + self.test_runTestsendBinary() + self.test_runTesttest_binary_allDirection() + self.test_runTesttestQuit() + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestBinary() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_builtin/test_builtin.py b/test/python_impl_tests/scripts/test_builtin/test_builtin.py new file mode 100644 index 00000000..cced8268 --- /dev/null +++ b/test/python_impl_tests/scripts/test_builtin/test_builtin.py @@ -0,0 +1,343 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_builtin.erpc_outputs import test as test_builtin +from service.test_builtin.erpc_outputs import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Variables +############################################################################### +gInt32AClient = 2 +gInt32BClient = -20 +gStringAClient = "Hello" +gStringBClient = "World!" +gSaveVariablesServer = {'int32A': 0, 'int32B': 0, 'stringA': "", 'stringB': ""} + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class BuiltinTestServiceHandler(test_builtin.interface.IBuiltinServices): + def test_int32_in(self, a): + global gSaveVariablesServer + gSaveVariablesServer['int32A'] = a + return + + def test_int32_in2(self, b): + global gSaveVariablesServer + gSaveVariablesServer['int32B'] = b + return + + def test_int32_out(self, c): + global gSaveVariablesServer + #c integer is defined as an out parameter + c.value = gSaveVariablesServer['int32A'] + return + + def test_int32_inout(self, e): + #e integer is defined as an out parameter + e.value = e.value + 1 + return + + def test_int32_return(self): + global gSaveVariablesServer + return (gSaveVariablesServer['int32A'] * gSaveVariablesServer['int32B']) + + def test_int32_allDirection(self, a, b, c, e): + c.value = a + e.value = 2 * e.value + return a * b + + def test_float_inout(self, a, b): + #b float is defined as an out parameter and needs to be initialized first + b.value = 0.0 + b.value = a + return + + def test_double_inout(self, a, b): + #b double is defined as an out parameter and needs to be initialized first + b.value = 0.0 + b.value = a + return + + def test_string_in(self, a): + global gSaveVariablesServer + gSaveVariablesServer['stringA'] = a + return + + def test_string_in2(self, b): + global gSaveVariablesServer + gSaveVariablesServer['stringB'] = b + return + + def test_string_out(self, c): + global gSaveVariablesServer + #c string is defined as an out parameter + c.value = gSaveVariablesServer['stringA'] + return + + def test_string_inout(self, e): + global gSaveVariablesServer + #e string is defined as an inout parameter + e.value += gSaveVariablesServer['stringB'] + return + + def test_string_return(self): + global gSaveVariablesServer + return (gSaveVariablesServer['stringA'] + " " + gSaveVariablesServer['stringB']) + + def test_string_allDirection(self, a, b, c, e): + c.value = a + e.value += gSaveVariablesServer['stringB'] + return e.value + + def sendHello(self, myStr): + if myStr == "Hello World!": + return 0 + else: + return -1 + + def sendTwoStrings(self, myStr1, myStr2): + if (myStr1 == "String one.") and (myStr2 == "String two."): + return 0 + else: + return -1 + + def returnHello(self): + return "Hello" + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls +def runTesttest_int32_in_out(client): + global gInt32AClient + int32C = erpc.Reference() + int32C.value = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_int32_in(gInt32AClient) + print('\r\neRPC request is sent to the server') + client.test_int32_out(int32C) + assert gInt32AClient == int32C.value + +def runTestBuiltinServiceID(client): + assert 2 == test_builtin.interface.IBuiltinServices.SERVICE_ID + +def runTesttest_int32_inout(client): + int32E = erpc.Reference() + int32E.value = -6 + for a in range(-5,5): + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_int32_inout(int32E) + assert a == int32E.value + +def runTestest_int32_return(client): + global gInt32AClient + global gInt32BClient + int32R = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_int32_in(gInt32AClient) + print('\r\neRPC request is sent to the server') + client.test_int32_in2(gInt32BClient) + print('\r\neRPC request is sent to the server') + int32R = client.test_int32_return() + assert (gInt32AClient * gInt32BClient) == int32R + +def runTestest_int32_allDirection(client): + global gInt32AClient + global gInt32BClient + int32C = erpc.Reference() + int32C.value = 0 + int32E = erpc.Reference() + int32E.value = 7 + int32R = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + int32R = client.test_int32_allDirection(gInt32AClient, gInt32BClient, int32C, int32E) + assert int32C.value == gInt32AClient + assert int32E.value == 14 + assert (gInt32AClient * gInt32BClient) == int32R + +def runTestest_float_inout(client): + a = float(3.14) + b = erpc.Reference(0.00) + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_float_inout(a, b) + assert b.value == a + +def runTestest_double_inout(client): + a = float(3.14) + b = erpc.Reference(0.00) + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_double_inout(a, b) + assert b.value == a + +def runTesttest_string_in_out(client): + global gStringAClient + stringC = erpc.Reference() + stringC.value = "" + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_string_in(gStringAClient) + print('\r\neRPC request is sent to the server') + client.test_string_out(stringC) + assert gStringAClient == stringC.value + +def runTesttest_string_inout(client): + stringE = erpc.Reference() + stringE.value = gStringAClient + " " + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_string_in2(gStringBClient) + print('\r\neRPC request is sent to the server') + client.test_string_inout(stringE) + assert "Hello World!" == stringE.value + +def runTestest_string_return(client): + stringR = "" + # send request to the server + print('\r\neRPC request is sent to the server') + stringR = client.test_string_return() + assert "Hello World!" == stringR + +def runTestest_string_allDirection(client): + global gStringAClient + global gStringBClient + stringC = erpc.Reference() + stringC.value = "" + stringE = erpc.Reference() + stringE.value = gStringAClient + " " + stringR = "" + # send request to the server + print('\r\neRPC request is sent to the server') + stringR = client.test_string_allDirection(gStringAClient, gStringBClient, stringC, stringE) + assert stringC.value == gStringAClient + assert stringE.value == "Hello World!" + assert stringR == "Hello World!" + +def runTesStringParamTest1(client): + int32R = -1 + # send request to the server + print('\r\neRPC request is sent to the server') + int32R = client.sendHello("Hello World!") + assert int32R == 0 + +def runTesStringParamTest2(client): + int32R = -1 + # send request to the server + print('\r\neRPC request is sent to the server') + int32R = client.sendTwoStrings("String one.", "String two.") + assert int32R == 0 + +def runTesStringReturnTest1(client): + # send request to the server + print('\r\neRPC request is sent to the server') + assert "Hello" == client.returnHello() + +############################################################################### +# PYTESTS +############################################################################### +class TestBuiltin: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_builtin.server.BuiltinServicesService(BuiltinTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_builtin.client.BuiltinServicesClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestBuiltin.runner = Runner('test_builtin', TestBuiltin.server_cmd, TestBuiltin.services, TestBuiltin.clientsConstructors) + + def test_runTestBuiltinServiceID(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTestBuiltinServiceID) + + def test_runTesttest_int32_in_out(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTesttest_int32_in_out) + + def test_runTesttest_int32_inout(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTesttest_int32_inout) + + def test_runTestest_int32_return(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTestest_int32_return) + + def test_runTestest_int32_allDirection(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTestest_int32_allDirection) + + def test_runTestest_float_inout(self): + self.runner.runTest(runTestest_float_inout) + + def test_runTestest_double_inout(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTestest_double_inout) + + def test_runTesttest_string_in_out(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTesttest_string_in_out) + + def test_runTesttest_string_inout(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTesttest_string_inout) + + def test_runTestest_string_return(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTestest_string_return) + + def test_runTestest_string_allDirection(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTestest_string_allDirection) + + def test_runTesStringParamTest1(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTesStringParamTest1) + + def test_runTesStringParamTest2(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTesStringParamTest2) + + def test_runTesStringReturnTest1(self): + self.runner.runTest(test_builtin.interface.IBuiltinServices.SERVICE_ID, runTesStringReturnTest1) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestBuiltinServiceID() + self.test_runTesttest_int32_in_out() + self.test_runTesttest_int32_inout() + self.test_runTestest_int32_return() + self.test_runTestest_int32_allDirection() + self.test_runTestest_float_inout() + self.test_runTestest_double_inout() + self.test_runTesttest_string_in_out() + self.test_runTesttest_string_inout() + self.test_runTestest_string_return() + self.test_runTestest_string_allDirection() + self.test_runTesStringParamTest1() + self.test_runTesStringParamTest2() + self.test_runTesStringReturnTest1() + self.test_runTesttestQuit() + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestBuiltin() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_const/test_const.py b/test/python_impl_tests/scripts/test_const/test_const.py new file mode 100644 index 00000000..1a62f3bf --- /dev/null +++ b/test/python_impl_tests/scripts/test_const/test_const.py @@ -0,0 +1,82 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_const.erpc_outputs import test as test_const +from service.test_const.erpc_outputs import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit + +############################################################################### +# Variables +############################################################################### + +############################################################################### +# Functions +############################################################################### + +############################################################################### +# Server +############################################################################### + +## Add service handler +class ConstTestServiceHandler(test_const.interface.IEmptyInterface): + pass + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls +def runTestCheckConsts(client): + assert test_const.common.a == 3 + assert test_const.common.b == 3.14 + assert test_const.common.c == "feedbabe" + assert test_const.common.d == 3.14 + assert test_const.common.x == 11 + assert test_const.common.y == 20 + assert test_const.common.mass == 100 + assert test_const.common.accel == -9.8 + +def runTestConstServiceID(client): + assert 2 == test_const.interface.IEmptyInterface.SERVICE_ID + +############################################################################### +# PYTESTS +############################################################################### +class TestConst: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_const.server.EmptyInterfaceService(ConstTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_const.client.EmptyInterfaceClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestConst.runner = Runner('test_const', TestConst.server_cmd, TestConst.services, TestConst.clientsConstructors) + + def test_runTestConstServiceID(self): + self.runner.runTest(test_const.interface.IEmptyInterface.SERVICE_ID, runTestConstServiceID) + + def test_runTestCheckConsts(self): + self.runner.runTest(test_const.interface.IEmptyInterface.SERVICE_ID, runTestCheckConsts) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTesttestQuit() + self.test_runTestConstServiceID() + self.test_runTestCheckConsts() + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestConst() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_enums/test_enums.py b/test/python_impl_tests/scripts/test_enums/test_enums.py new file mode 100644 index 00000000..d78f8b7c --- /dev/null +++ b/test/python_impl_tests/scripts/test_enums/test_enums.py @@ -0,0 +1,215 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_enums.erpc_outputs import test as test_enums +from service.test_enums.erpc_outputs import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Variables +############################################################################### +gEnumColorAClient = test_enums.common.enumColor.green +gEnumColorBClient = test_enums.common.enumColor.red +gEnumColorAServer = 0 +gEnumColorBServer = 0 + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class EnumsTestServiceHandler(test_enums.interface.IEnumsService): + def test_enumColor_in(self, a): + global gEnumColorAServer + gEnumColorAServer = a + return + + def test_enumColor_in2(self, b): + global gEnumColorBServer + gEnumColorBServer = b + return + + def test_enumColor_out(self, c): + #c enum is defined as an out parameter + c.value = gEnumColorAServer + return + + def test_enumColor_inout(self, e): + #e enum is defined as an out parameter + e.value = e.value - 9 + return + + def test_enumColor_return(self): + return (gEnumColorAServer + 9) + + def test_enumColor_allDirection(self, a, b, c, e): + c.value = a + e.value = b + return a + + def test_enumColor2_allDirection(self, a, b, c, e): + c.value = a + e.value = b + return a + + def test_enumErrorCode_allDirection(self, a, b, c, e): + c.value = a + e.value = b + return a + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls +def runTesttest_enumColor_in_out(client): + global gEnumColorAClient + enumColorC = erpc.Reference() + enumColorC.value = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_enumColor_in(gEnumColorAClient) + print('\r\neRPC request is sent to the server') + client.test_enumColor_out(enumColorC) + assert enumColorC.value == gEnumColorAClient + +def runTestEnumsServiceID(client): + assert 2 == test_enums.interface.IEnumsService.SERVICE_ID + +def runTesttest_enumColor_inout(client): + global gEnumColorAClient + global gEnumColorBClient + enumColorE = erpc.Reference() + enumColorE.value = gEnumColorAClient + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_enumColor_inout(enumColorE) + assert enumColorE.value == gEnumColorBClient + +def runTesttest_enumColor_return(client): + global gEnumColorAClient + global gEnumColorBClient + enumColorR = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_enumColor_in(gEnumColorBClient) + print('\r\neRPC request is sent to the server') + enumColorR = client.test_enumColor_return() + assert gEnumColorAClient == enumColorR + +def runTesttest_enumColor_allDirection(client): + global gEnumColorAClient + global gEnumColorBClient + enumColorC = erpc.Reference() + enumColorC.value = 0 + enumColorE = erpc.Reference() + enumColorE.value = gEnumColorAClient + enumColorR = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + enumColorR = client.test_enumColor_allDirection(gEnumColorAClient, gEnumColorBClient, enumColorC, enumColorE) + assert gEnumColorAClient == enumColorC.value + assert gEnumColorBClient == enumColorE.value + assert gEnumColorAClient == enumColorR + +def runTesttest_enumColor2_allDirection(client): + enumColor2A = test_enums.common.enumColor2.pink + enumColor2B = test_enums.common.enumColor2.yellow + enumColor2C = erpc.Reference() + enumColor2C.value = 0 + enumColor2E = erpc.Reference() + enumColor2E.value = enumColor2A + enumColor2R = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + enumColor2R = client.test_enumColor2_allDirection(enumColor2A, enumColor2B, enumColor2C, enumColor2E) + assert enumColor2A == enumColor2C.value + assert enumColor2B == enumColor2E.value + assert enumColor2A == enumColor2R + +def runTesttest_enumErrorCode_allDirection(client): + enumErrorCodeA = test_enums.common.enumErrorCode.ERROR_NONE + enumErrorCodeB = test_enums.common.enumErrorCode.ERROR_UNKNOWN + enumErrorCodeC = erpc.Reference() + enumErrorCodeC.value = 0 + enumErrorCodeE = erpc.Reference() + enumErrorCodeE.value = enumErrorCodeA + enumErrorCodeR = 0 + # send request to the server + print('\r\neRPC request is sent to the server') + enumErrorCodeR = client.test_enumErrorCode_allDirection(enumErrorCodeA, enumErrorCodeB, enumErrorCodeC, enumErrorCodeE) + assert enumErrorCodeA == enumErrorCodeC.value + assert enumErrorCodeB == enumErrorCodeE.value + assert enumErrorCodeA == enumErrorCodeR + +############################################################################### +# PYTESTS +############################################################################### +class TestEnums: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_enums.server.EnumsServiceService(EnumsTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_enums.client.EnumsServiceClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestEnums.runner = Runner('test_enums', TestEnums.server_cmd, TestEnums.services, TestEnums.clientsConstructors) + + def test_runTestEnumsServiceID(self): + self.runner.runTest(test_enums.interface.IEnumsService.SERVICE_ID, runTestEnumsServiceID) + + def test_runTesttest_enumColor_in_out(self): + self.runner.runTest(test_enums.interface.IEnumsService.SERVICE_ID, runTesttest_enumColor_in_out) + + def test_runTesttest_enumColor_inout(self): + self.runner.runTest(test_enums.interface.IEnumsService.SERVICE_ID, runTesttest_enumColor_inout) + + def test_runTesttest_enumColor_return(self): + self.runner.runTest(test_enums.interface.IEnumsService.SERVICE_ID, runTesttest_enumColor_return) + + def test_runTesttest_enumColor_allDirection(self): + self.runner.runTest(test_enums.interface.IEnumsService.SERVICE_ID, runTesttest_enumColor_allDirection) + + def test_runTesttest_enumColor2_allDirection(self): + self.runner.runTest(test_enums.interface.IEnumsService.SERVICE_ID, runTesttest_enumColor2_allDirection) + + def test_runTesttest_enumErrorCode_allDirection(self): + self.runner.runTest(test_enums.interface.IEnumsService.SERVICE_ID, runTesttest_enumErrorCode_allDirection) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestEnumsServiceID() + self.test_runTesttest_enumColor_in_out() + self.test_runTesttest_enumColor_inout() + self.test_runTesttest_enumColor_return() + self.test_runTesttest_enumColor_allDirection() + self.test_runTesttest_enumColor2_allDirection() + self.test_runTesttest_enumErrorCode_allDirection() + self.test_runTesttestQuit() + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestEnums() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_lists/test_lists.py b/test/python_impl_tests/scripts/test_lists/test_lists.py new file mode 100644 index 00000000..48c99d2b --- /dev/null +++ b/test/python_impl_tests/scripts/test_lists/test_lists.py @@ -0,0 +1,396 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_lists.erpc_outputs import test as test_lists +from service.test_lists.erpc_outputs import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() +import pytest + +############################################################################### +# Variables +############################################################################### + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class ListsTestServiceHandler(test_lists.interface.IPointersService): + def sendReceivedInt32(self, received_list): + send_list = [] + for y in range(len(received_list)): + send_list.append(2 * received_list[y]) + return send_list + + def sendReceived2Int32(self, received_list): + send_list = [[] for a in range(len(received_list))] + for x in range(len(received_list)): + for y in range(len(received_list[x])): + send_list[x].append(2 * received_list[x][y]) + return send_list + + def sendReceivedEnum(self, received_list): + send_list = [] + for y in range(len(received_list)): + send_list.append(received_list[y]) + return send_list + + def sendReceived2Enum(self, received_list): + send_list = [[] for a in range(len(received_list))] + for x in range(len(received_list)): + for y in range(len(received_list[x])): + send_list[x].append(received_list[x][y]) + return send_list + + def sendReceivedStruct(self, received_list): + send_list = [test_lists.common.C() for b in range(len(received_list))] + for y in range(len(received_list)): + send_list[y].m = 2 * received_list[y].m + send_list[y].n = 2 * received_list[y].n + return send_list + + def sendReceived2Struct(self, received_list): + send_list = [[] for a in range(len(received_list))] + for x in range(len(received_list)): + send_list[x] = [test_lists.common.C() for b in range(len(received_list[x]))] + for y in range(len(received_list[x])): + send_list[x][y].m = 2 * received_list[x][y].m + send_list[x][y].n = 2 * received_list[x][y].n + return send_list + + def sendReceivedString(self, received_list): + send_list = [] + for y in range(len(received_list)): + send_list.append(received_list[y] + " World!") + return send_list + + def sendReceived2String(self, received_list): + send_list = [[] for a in range(len(received_list))] + for x in range(len(received_list)): + for y in range(len(received_list[x])): + send_list[x].append(received_list[x][y] + " World!") + return send_list + + @pytest.mark.skip(reason="They do not belong to the tests.") + def test_list_allDirection(self, a, b, e): + #e list is defined as an inout parameter + for y in range(len(a)): + e.value[y] = 2 * e.value[y] + return + + def testLengthAnnotation(self, myList): + for y in range(len(myList)): + if myList[y] != y + 1: + return 0 + return 1 + + def testLengthAnnotationInStruct(self, s): + for y in range(s.len): + if s.myList[y] != y + 1: + return 0 + return 10 + + def returnSentStructLengthAnnotation(self, s): + ret = test_lists.common.listStruct([]) + for x in range(s.len): + ret.myList.append(s.myList[x]) + return ret + + def sendGapAdvertisingData(self, ad): + for x in range(ad.cNumAdStructures): + if ad.aAdStructures[x].adType != 5: + return 0 + for y in range(ad.aAdStructures[x].length): + if ad.aAdStructures[x].aData[y] != ((y + 1) * 5): + return 0 + return 33 + +################## +## Run server on specified transport layer +def runServer(transport): + # create test lists eRPC service + handler = ListsTestServiceHandler() + service = test_lists.server.PointersServiceService(handler) + + # run server + server = erpc.simple_server.SimpleServer(transport, erpc.basic_codec.BasicCodec) + server.add_service(service) + print('\r\nWait for client to send a eRPC request') + sys.stdout.flush() + server.run() + +################## +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls + +def runTestListsServiceID(client): + assert 2 == test_lists.interface.IPointersService.SERVICE_ID + +def runSendReceivedInt32(client): + send_list = range(12) + print('\r\neRPC request is sent to the server') + received_list = client.sendReceivedInt32(send_list) + for x in range(len(received_list)): + assert (received_list[x] / 2) == send_list[x] + +def runSendReceiveZeroSize(client): + send_list = [0] + print('\r\neRPC request is sent to the server') + received_list = client.sendReceivedInt32(send_list) + assert received_list == [0] + +def runSendReceived2Int32(client): + send_list = [[0] for a in range(10)] + for a in range(10): + send_list[a] = range(a+1) + #print(send_list) + # send request to the server + print('\r\neRPC request is sent to the server') + received_list = client.sendReceived2Int32(send_list) + #print(received_list) + for x in range(len(received_list)): + for y in range(len(received_list[x])): + assert (received_list[x][y] / 2) == send_list[x][y] + +def runSendReceivedEnum(client): + send_list = [] + send_list.append(test_lists.common.enumColor.red) + send_list.append(test_lists.common.enumColor.green) + send_list.append(test_lists.common.enumColor.blue) + print('\r\neRPC request is sent to the server') + received_list = client.sendReceivedEnum(send_list) + #print(received_list) + for x in range(len(received_list)): + assert received_list[x] == send_list[x] + +def runSendReceived2Enum(client): + send_list = [[] for a in range(3)] + for a in range(3): + for b in range(a+1): + if b == 0: + send_list[a].append(test_lists.common.enumColor.red) + if b == 1: + send_list[a].append(test_lists.common.enumColor.green) + if b == 2: + send_list[a].append(test_lists.common.enumColor.blue) + # send request to the server + print('\r\neRPC request is sent to the server') + received_list = client.sendReceived2Enum(send_list) + #print(received_list) + for x in range(len(received_list)): + assert received_list[x] == send_list[x] + +def runSendReceivedStruct(client): + send_list = [] + for a in range(10): + send_list.append(test_lists.common.C(a, a * 2)) + #print(send_list) + print('\r\neRPC request is sent to the server') + received_list = client.sendReceivedStruct(send_list) + #print(received_list) + for x in range(len(received_list)): + assert (received_list[x].m) / 2 == send_list[x].m + assert (received_list[x].n) / 2 == send_list[x].n + +def runSendReceived2Struct(client): + send_list = [[] for a in range(10)] + for a in range(10): + for b in range(a+1): + send_list[a].append(test_lists.common.C(a, b)) + #print(send_list) + # send request to the server + print('\r\neRPC request is sent to the server') + received_list = client.sendReceived2Struct(send_list) + #print(received_list) + for x in range(len(received_list)): + for y in range(len(received_list[x])): + assert (received_list[x][y].m) / 2 == send_list[x][y].m + assert (received_list[x][y].n) / 2 == send_list[x][y].n + +def runSendReceivedString(client): + send_list = ["Hello" for a in range(12)] + #print(send_list) + print('\r\neRPC request is sent to the server') + received_list = client.sendReceivedString(send_list) + #print(received_list) + for x in range(len(received_list)): + assert received_list[x] == "Hello World!" + +def runSendReceived2String(client): + send_list = [[] for a in range(12)] + for a in range(12): + for b in range(a+1): + send_list[a].append("Hello") + #print(send_list) + # send request to the server + print('\r\neRPC request is sent to the server') + received_list = client.sendReceived2String(send_list) + #print(received_list) + for x in range(len(received_list)): + for y in range(len(received_list[x])): + assert received_list[x][y] == "Hello World!" + +def runtest_list_allDirection(client): + send_list_a = [] + send_list_b = [] + send_list_e = erpc.Reference() + send_list_e.value = [] + for x in range(10): + send_list_a.append(x) + send_list_b.append(2 * x) + send_list_e.value.append(6 * x) + #print(send_list_e) + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_list_allDirection(send_list_a, send_list_b, send_list_e) + #print(send_list_e) + for x in range(len(send_list_a)): + assert send_list_e.value[x] == 12 * send_list_a[x] + +def runtestLengthAnnotation(client): + length = 5 + list = [] + for x in range(length): + list.append(x + 1) + # send request to the server + print('\r\neRPC request is sent to the server') + result = client.testLengthAnnotation(list) + assert result == 1 + +def runtestLengthAnnotationInStruct(client): + myListStruct = test_lists.common.listStruct([]) + for x in range(5): + myListStruct.myList.append(x + 1) + #print(myListStruct) + # send request to the server + print('\r\neRPC request is sent to the server') + result = client.testLengthAnnotationInStruct(myListStruct) + assert result == 10 + +def runreturnSentStructLengthAnnotation(client): + myListStruct = test_lists.common.listStruct([]) + returnStruct = test_lists.common.listStruct([]) + for x in range(5): + myListStruct.myList.append(x + 1) + # send request to the server + print('\r\neRPC request is sent to the server') + returnStruct = client.returnSentStructLengthAnnotation(myListStruct) + for x in range(returnStruct.len): + assert myListStruct.myList[x] == returnStruct.myList[x] + +def runsendGapAdvertisingData(client): + ad = test_lists.common.gapAdvertisingData_t([]) + for x in range(2): + ad.aAdStructures.append(test_lists.common.gapAdStructure_t(adType=5, aData=[((a + 1) * 5) for a in range(3)])) + #print(ad) + # send request to the server + print('\r\neRPC request is sent to the server') + result = client.sendGapAdvertisingData(ad) + assert result == 33 + +############################################################################### +# PYTESTS +############################################################################### +class TestLists: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_lists.server.PointersServiceService(ListsTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_lists.client.PointersServiceClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestLists.runner = Runner('test_lists', TestLists.server_cmd, TestLists.services, TestLists.clientsConstructors) + + def test_runTestListsServiceID(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runTestListsServiceID) + + def test_runSendReceivedInt32(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceivedInt32) + + def test_runSendReceiveZeroSize(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceiveZeroSize) + + def test_runSendReceived2Int32(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceived2Int32) #TODO C failed + + def test_runSendReceivedEnum(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceivedEnum) + + def test_runSendReceived2Enum(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceived2Enum) + + def test_runSendReceivedStruct(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceivedStruct) + + def test_runSendReceived2Struct(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceived2Struct) #TODO C failed + + def test_runSendReceivedString(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceivedString) + + def test_runSendReceived2String(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runSendReceived2String) #TODO C failed + + def test_runtest_list_allDirection(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runtest_list_allDirection) + + def test_runtestLengthAnnotation(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runtestLengthAnnotation) + + def test_runtestLengthAnnotationInStruct(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runtestLengthAnnotationInStruct) + + def test_runreturnSentStructLengthAnnotation(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runreturnSentStructLengthAnnotation) + + def test_runsendGapAdvertisingData(self): + self.runner.runTest(test_lists.interface.IPointersService.SERVICE_ID, runsendGapAdvertisingData) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestListsServiceID() + self.test_runSendReceivedInt32() + self.test_runSendReceiveZeroSize() + self.test_runSendReceived2Int32() #TODO C failed + self.test_runSendReceivedEnum() + self.test_runSendReceived2Enum() + self.test_runSendReceivedStruct() + self.test_runSendReceived2Struct() #TODO C failed + self.test_runSendReceivedString() + self.test_runSendReceived2String() #TODO C failed + self.test_runtest_list_allDirection() + self.test_runtestLengthAnnotation() + self.test_runtestLengthAnnotationInStruct() + self.test_runreturnSentStructLengthAnnotation() + self.test_runsendGapAdvertisingData() + self.test_runTesttestQuit() + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestLists() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_struct/test_struct.py b/test/python_impl_tests/scripts/test_struct/test_struct.py new file mode 100644 index 00000000..7207d2ea --- /dev/null +++ b/test/python_impl_tests/scripts/test_struct/test_struct.py @@ -0,0 +1,315 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_struct.erpc_outputs import test_ArithmeticService, test_unit_test_common +#from service import test_ArithmeticService2Service +from common.common import CommonTestServiceHandler, runTesttestQuit +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Variables +############################################################################### + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class StructTestServiceHandler1(test_ArithmeticService.interface.IArithmeticService1): + def getMember(self, c): + return c.m + + def sendNestedStruct(self, d): + return d.c.m + + def returnStruct(self, x, y): + b = test_ArithmeticService.common.B() + b.x = x + b.y = y + return b + + def getMemberTest2(self, a): + result = test_ArithmeticService.common.B() + result.x = a.c.m + result.y = a.b.x + return result + + def checkString(self, p): + return not(p.species == "Ape") + + def returnStrings(self): + str_str = test_ArithmeticService.common.stringStruct(one="One", two="Two", three="Three") + return str_str + +class StructTestServiceHandler2(test_ArithmeticService.interface.IArithmeticService2): + def sendManyInts(self, f): + if (f.a == -1) and (f.b == -1) and (f.c == -1) and (f.d == -1): + return 0 + return 1 + + def sendManyUInts(self, g): + if (g.a == 0xff) and (g.b == 0xffff) and (g.c == 0xffffffff) and (g.d == 0xffffffffffffffff): + return 0 + return 1 + + def getStudentName(self, stud): + return stud.name + + def getStudentTestAverage(self, stud): + total = float(0.0) + for x in range(3): + total += stud.test_grades[x] + return float(total / 3) + + def getStudentYear(self, stud): + return stud.school_year + + def getStudentAge(self, stud): + return stud.age + + def createStudent(self, name, test_scores, year, age): + newStudent = test_ArithmeticService.common.student(name=name, test_grades=test_scores, school_year=year, age=age) + return newStudent + + def test_struct_allDirection(self, a, b, e): + e.value.number = a.number * b.number + e.value.text = "World" + e.value.color = test_ArithmeticService.common.enumColor.green + e.value.c.m = a.c.m * b.c.m + e.value.c.n = a.c.n * b.c.n + for i in range(len(a.list_numbers)): + e.value.list_numbers[i] = a.list_numbers[i] * b.list_numbers[i] + e.value.list_text[i] = "World" + for i in range(len(a.array_numbers)): + e.value.array_numbers[i] = a.array_numbers[i] * b.array_numbers[i] + e.value.array_text[i] = "World" + for i in range(len(a.binary_numbers)): + e.value.binary_numbers[i] = a.binary_numbers[i] * b.binary_numbers[i] + return + + def testSendingByrefMembers(self, s): + if (s.a == 0xED) and (s.b == 4): + return True + return False + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls +def runGetMember1(client): + c = test_ArithmeticService.common.C(m=4, n=5) + # send request to the server + print('\r\neRPC request is sent to the server') + r = client.getMember(c) + assert r == 4 + +def runTestArithmeticServiceID(client): + assert 3 == test_ArithmeticService.interface.IArithmeticService1.SERVICE_ID + +def runNestedStruct1(client): + c = test_ArithmeticService.common.C(m=4, n=5) + d = test_ArithmeticService.common.D(c) + # send request to the server + print('\r\neRPC request is sent to the server') + r = client.sendNestedStruct(d) + assert r == 4 + +def runReturnStruct1(client): + b = test_ArithmeticService.common.B() + # send request to the server + print('\r\neRPC request is sent to the server') + b = client.returnStruct(float(3.14), float(2.71828)) + print(b) + assert b.x == float(3.14) + assert b.y == float(2.71828) + +def runSendIntSizes(client): + f = test_ArithmeticService.common.F(-1, -1, -1, -1) + #print(f) + # send request to the server + print('\r\neRPC request is sent to the server') + assert 0 == client.sendManyInts(f) + +def runSendUnsignedIntSizes(client): + g = test_ArithmeticService.common.G(0xFF, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF) + #print(g) + # send request to the server + print('\r\neRPC request is sent to the server') + assert 0 == client.sendManyUInts(g) + +def runGetMember2(client): + c = test_ArithmeticService.common.C(m=4, n=5) + b = test_ArithmeticService.common.B(x=float(3.14), y=float(2.71828)) + a = test_ArithmeticService.common.A(b=b, c=c) + bb = test_ArithmeticService.common.B() + # send request to the server + print('\r\neRPC request is sent to the server') + bb = client.getMemberTest2(a) + #print(bb) + assert float(bb.x) == float(4.0) + assert float(bb.y) == float(3.14) + +def runTestString1(client): + prim8 = test_ArithmeticService.common.primate(species="Ape", is_ape=False) + # send request to the server + print('\r\neRPC request is sent to the server') + assert 0 == client.checkString(prim8) + +def runTestReturnString1(client): + result = test_ArithmeticService.common.stringStruct() + # send request to the server + print('\r\neRPC request is sent to the server') + result = client.returnStrings() + assert result.one == "One" + assert result.two == "Two" + assert result.three == "Three" + +def runTestStudent1(client): + stud = test_ArithmeticService.common.student(name="Donnie Darko", test_grades=[float(85.75), float(93.29), float(92.46)], school_year=test_ArithmeticService.common.school_year_t.SENIOR, age=19) + # send request to the server + print('\r\neRPC request is sent to the server') + assert "Donnie Darko" == client.getStudentName(stud) + assert float((stud.test_grades[0] + stud.test_grades[1] + stud.test_grades[2]) / 3) == client.getStudentTestAverage(stud) + assert 19 == client.getStudentAge(stud) + assert 12 == test_ArithmeticService.common.school_year_t.SENIOR + assert test_ArithmeticService.common.school_year_t.SENIOR == client.getStudentYear(stud) + +def runTestStudent2(client): + stud = test_ArithmeticService.common.student() + # send request to the server + print('\r\neRPC request is sent to the server') + stud = client.createStudent("George Bush", [float(65.32), float(69.68), float(0)], test_ArithmeticService.common.school_year_t.FRESHMAN, 68) + assert "George Bush" == client.getStudentName(stud) + assert float((65.32 + 69.68 + 0) / 3) == client.getStudentTestAverage(stud) + assert 68 == client.getStudentAge(stud) + assert test_ArithmeticService.common.school_year_t.FRESHMAN == client.getStudentYear(stud) + +def runtest_struct_allDirection(client): + a_binary = bytearray(b'') + b_binary = bytearray(b'') + e_binary = bytearray(b'') + for x in range(2): + a_binary.append(x) + b_binary.append(x * 2) + e_binary.append(x) + a = test_ArithmeticService.common.AllTypes(number=5, text="Hello", color=test_ArithmeticService.common.enumColor.red, c=test_ArithmeticService.common.C(m=5, n=20), list_numbers=[0, 1], list_text=["Hello", "Hello"], array_numbers=[0, 1], array_text=["Hello", "Hello"], binary_numbers=a_binary) + b = test_ArithmeticService.common.AllTypes(number=10, text="World", color=test_ArithmeticService.common.enumColor.green, c=test_ArithmeticService.common.C(m=7, n=17), list_numbers=[1, 2], list_text=["World", "World"], array_numbers=[1, 2], array_text=["World", "World"], binary_numbers=b_binary) + e = erpc.Reference(test_ArithmeticService.common.AllTypes(number=15, text="Hello", color=test_ArithmeticService.common.enumColor.blue, c=test_ArithmeticService.common.C(m=4, n=14), list_numbers=[2, 3], list_text=["Hello", "Hello"], array_numbers=[2, 3], array_text=["Hello", "Hello"], binary_numbers=e_binary)) + # send request to the server + print('\r\neRPC request is sent to the server') + client.test_struct_allDirection(a, b, e) + assert e.value.number == a.number * b.number + assert e.value.text == "World" + assert e.value.color == test_ArithmeticService.common.enumColor.green + assert e.value.c.m == a.c.m * b.c.m + assert e.value.c.n == a.c.n * b.c.n + assert len(e.value.list_numbers) == 2 + for x in range(len(a.list_numbers)): + assert e.value.list_numbers[x] == a.list_numbers[x] * b.list_numbers[x] + assert "World" == e.value.list_text[x] + for x in range(2): + assert e.value.array_numbers[x] == a.array_numbers[x] * b.array_numbers[x] + assert "World" == e.value.array_text[x] + for x in range(len(a.binary_numbers)): + assert e.value.binary_numbers[x] == a.binary_numbers[x] * b.binary_numbers[x] + +def runTestSendingByrefMembers(client): + s = test_ArithmeticService.common.StructWithByrefMembers() + b = 4 + s.a = 0xED + s.b = id(b) + # send request to the server + print('\r\neRPC request is sent to the server') + assert True == client.testSendingByrefMembers(s) + +############################################################################### +# PYTESTS +############################################################################### +class TestStruct: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_ArithmeticService.server.ArithmeticService1Service(StructTestServiceHandler1()),test_ArithmeticService.server.ArithmeticService2Service(StructTestServiceHandler2()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_ArithmeticService.client.ArithmeticService1Client, test_ArithmeticService.client.ArithmeticService2Client, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestStruct.runner = Runner('test_struct', TestStruct.server_cmd, TestStruct.services, TestStruct.clientsConstructors) + + def test_runTestArithmeticServiceID(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService1.SERVICE_ID, runTestArithmeticServiceID) + + def test_runGetMember1(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService1.SERVICE_ID, runGetMember1) + + def test_runNestedStruct1(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService1.SERVICE_ID, runNestedStruct1) + +# def test_runGetMember2(self): +# self.runner.runTest(test_ArithmeticService.interface.IArithmeticService1.SERVICE_ID, runGetMember2) + + def test_runTestString1(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService1.SERVICE_ID, runTestString1) + + def test_runTestReturnString1(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService1.SERVICE_ID, runTestReturnString1) + + def test_runSendIntSizes(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService2.SERVICE_ID, runSendIntSizes) + + def test_runSendUnsignedIntSizes(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService2.SERVICE_ID, runSendUnsignedIntSizes) + + def test_runTestStudent1(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService2.SERVICE_ID, runTestStudent1) + + def test_runTestStudent2(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService2.SERVICE_ID, runTestStudent2) + + def test_runtest_struct_allDirection(self): + self.runner.runTest(test_ArithmeticService.interface.IArithmeticService2.SERVICE_ID, + runtest_struct_allDirection) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestArithmeticServiceID() + self.test_runGetMember1() + self.test_runNestedStruct1() +# self.test_runGetMember2() + self.test_runTestString1() + self.test_runTestReturnString1() + self.test_runSendIntSizes() + self.test_runSendUnsignedIntSizes() + self.test_runTestStudent1() + self.test_runTestStudent2() + self.test_runtest_struct_allDirection() + self.test_runTesttestQuit() + +#runReturnStruct1(client1) +#runTestSendingByrefMembers(client2) + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestStruct() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_typedef/test_typedef.py b/test/python_impl_tests/scripts/test_typedef/test_typedef.py new file mode 100644 index 00000000..2aa45840 --- /dev/null +++ b/test/python_impl_tests/scripts/test_typedef/test_typedef.py @@ -0,0 +1,165 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_typedef.erpc_outputs import test as test_typedef +from service.test_typedef.erpc_outputs import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit + +############################################################################### +# Variables +############################################################################### + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class TypedefTestServiceHandler(test_typedef.interface.ITypedefService): + def sendReceiveInt(self, a): + return a * 2 + 1 + + def sendReceiveEnum(self, a): + return a + 1 + + def sendReceiveStruct(self, a): + b = test_typedef.common.B(m=(2 * a.m), n=(2 + a.n)) + return b + + def sendReceiveListType(self, received_list): + send_list = [] + for y in range(len(received_list)): + send_list.append(2 * received_list[y]) + return send_list + + def sendReceiveString(self, hello): + return hello + " World!" + + def sendReceive2ListType(self, received_list): + send_list = [[] for a in range(len(received_list))] + for x in range(len(received_list)): + for y in range(len(received_list[x])): + send_list[x].append(2 * received_list[x][y]) + return send_list + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls +def runSendReceiveInt(client): + a = 10 + b = 2 * a + 1 + # send request to the server + print('\r\neRPC request is sent to the server') + assert b == client.sendReceiveInt(a) + +def runTestTypedefServiceID(client): + assert 2 == test_typedef.interface.ITypedefService.SERVICE_ID + +def runSendReceiveEnum(client): + a = test_typedef.common.Colors.green + # send request to the server + print('\r\neRPC request is sent to the server') + assert test_typedef.common.Colors.blue == client.sendReceiveEnum(a) + +def runSendReceiveStruct(client): + a = test_typedef.common.B(m=1, n=4) + b = test_typedef.common.B(m=(2 * a.m), n=(2 + a.n)) + r = test_typedef.common.B() + # send request to the server + print('\r\neRPC request is sent to the server') + r = client.sendReceiveStruct(a) + assert r.m == b.m + assert r.n == b.n + +def runSendReceiveListType(client): + send_list = range(12) + # send request to the server + print('\r\neRPC request is sent to the server') + received_list = client.sendReceiveListType(send_list) + for x in range(len(received_list)): + assert (received_list[x] / 2) == send_list[x] + +def runSendReceiveString(client): + send = "Hello" + print('\r\neRPC request is sent to the server') + received = client.sendReceiveString(send) + assert received == "Hello World!" + +def runSendReceive2ListType(client): + send_list = [[0] for a in range(10)] + for a in range(10): + send_list[a] = range(a+1) + #print(send_list) + # send request to the server + print('\r\neRPC request is sent to the server') + received_list = client.sendReceive2ListType(send_list) + #print(received_list) + for x in range(len(received_list)): + for y in range(len(received_list[x])): + assert (received_list[x][y] / 2) == send_list[x][y] + +############################################################################### +# PYTESTS +############################################################################### +class TestTypedef: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_typedef.server.TypedefServiceService(TypedefTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_typedef.client.TypedefServiceClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestTypedef.runner = Runner('test_typedef', TestTypedef.server_cmd, TestTypedef.services, TestTypedef.clientsConstructors) + + def test_runTestTypedefServiceID(self): + self.runner.runTest(test_typedef.interface.ITypedefService.SERVICE_ID , runTestTypedefServiceID) + + def test_runSendReceiveInt(self): + self.runner.runTest(test_typedef.interface.ITypedefService.SERVICE_ID, runSendReceiveInt) + + def test_runSendReceiveEnum(self): + self.runner.runTest(test_typedef.interface.ITypedefService.SERVICE_ID, runSendReceiveEnum) + + def test_runSendReceiveStruct(self): + self.runner.runTest(test_typedef.interface.ITypedefService.SERVICE_ID, runSendReceiveStruct) + + def test_runSendReceiveListType(self): + self.runner.runTest(test_typedef.interface.ITypedefService.SERVICE_ID, runSendReceiveListType) + + def test_runSendReceiveString(self): + self.runner.runTest(test_typedef.interface.ITypedefService.SERVICE_ID, runSendReceiveString) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestTypedefServiceID() + self.test_runSendReceiveInt() + self.test_runSendReceiveEnum() + self.test_runSendReceiveStruct() + self.test_runSendReceiveListType() + self.test_runSendReceiveString() + self.test_runTesttestQuit() + +# runSendReceive2ListType) + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestTypedef() + tester.runTests() diff --git a/test/python_impl_tests/scripts/test_unions/test_unions.py b/test/python_impl_tests/scripts/test_unions/test_unions.py new file mode 100644 index 00000000..bebd7788 --- /dev/null +++ b/test/python_impl_tests/scripts/test_unions/test_unions.py @@ -0,0 +1,266 @@ +#!/usr/bin/python + +# Copyright 2021 NXP +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import inspect, os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))) +from server.runner import Runner +from service.test_unions.erpc_outputs import test as test_unions +from service.test_unions.erpc_outputs import test_unit_test_common +from common.common import CommonTestServiceHandler, runTesttestQuit +try: + import erpc +except ImportError: + print("Could not import erpc.\r\nPlease install it first by running \"python setup.py install\" in folder \"erpc/erpc_python/\".") + sys.exit() + +############################################################################### +# Variables +############################################################################### + +############################################################################### +# Functions +############################################################################### + + +############################################################################### +# Server +############################################################################### + +## Add service handler +class UnionsTestServiceHandler(test_unions.interface.IArithmeticService): + def testGenericCallback(self, event): + newEvent = test_unions.common.gapGenericEvent_t(eventType=test_unions.common.gapGenericEventType_t.gInternalError_c) + newEvent.eventData.internalError = test_unions.common.gapInternalError_t(errorCode=test_unions.common.bleResult_t.gBleSuccess_c, errorSource=test_unions.common.gapInternalErrorSource_t.gHciCommandStatus_c, hciCommandOpcode=5) + if event.eventType == test_unions.common.gapGenericEventType_t.gInternalError_c: + if (event.eventData.internalError.errorCode == test_unions.common.bleResult_t.gBleSuccess_c and + event.eventData.internalError.errorSource == test_unions.common.gapInternalErrorSource_t.gHciCommandStatus_c and + event.eventData.internalError.hciCommandOpcode == 5): + newEvent.eventType = test_unions.common.gapGenericEventType_t.gWhiteListSizeReady_c + newEvent.eventData.whiteListSize = 0 + else: + newEvent.eventType = test_unions.common.gapGenericEventType_t.gAdvertisingSetupFailed_c + newEvent.eventData.whiteListSize = 0 + elif event.eventType == test_unions.common.gapGenericEventType_t.gRandomAddressReady_c: + newEvent.eventType = test_unions.common.gapGenericEventType_t.gTestCaseReturn_c + newEvent.eventData.returnCode = 1 + for i in range(test_unions.common.gcBleDeviceAddressSize_c): + if (event.eventData.aAddress[i] != (0xAA ^ 0xFF)): + newEvent.eventData.returnCode = 0 + elif event.eventType == test_unions.common.gapGenericEventType_t.gWhiteListSizeReady_c: + newEvent.eventType = test_unions.common.gapGenericEventType_t.gTestCaseReturn_c + if (event.eventData.whiteListSize == 100): + newEvent.eventData.returnCode = 100 + else: + newEvent.eventData.returnCode = 0 + elif event.eventType == test_unions.common.gapGenericEventType_t.gPublicAddressRead_c: + pass + elif event.eventType == test_unions.common.gapGenericEventType_t.gAdvertisingSetupFailed_c: + pass + elif event.eventType == test_unions.common.gapGenericEventType_t.gAdvTxPowerLevelRead_c: + pass + return newEvent + + def sendMyFoo(self, f): + newFoo = test_unions.common.foo() + if f.discriminator == test_unions.common.fruit.apple: + newFoo.discriminator = test_unions.common.fruit.returnVal + newFoo.bing.myFoobar = test_unions.common.foobar(a=float(0), rawString=None) + newFoo.bing.ret = 0xAA + for i in range(len(f.bing.myFoobar.rawString)): + if (f.bing.myFoobar.rawString[i] != (i + 1)): + newFoo.bing.ret = 0x55 + elif f.discriminator == test_unions.common.fruit.banana: + newFoo.discriminator = test_unions.common.fruit.papaya + if (f.bing.x == 3) and (f.bing.y == float(4.0)): + newFoo.bing.x = 4 + newFoo.bing.y = 3 + else: + newFoo.bing.x = 1 + newFoo.bing.y = 1 + elif f.discriminator == test_unions.common.fruit.orange: + newFoo.discriminator = test_unions.common.fruit.returnVal + newFoo.bing.ret = 0xAA + for i in range(len(f.bing.a)): + if (f.bing.a[i] != (i + 1)): + newFoo.bing.ret = 0x55 + return newFoo + + def sendMyUnion(self, discriminator, unionVariable): + newFoo = test_unions.common.foo() + if discriminator == test_unions.common.fruit.apple: + newFoo.discriminator = test_unions.common.fruit.returnVal + newFoo.bing.myFoobar = test_unions.common.foobar(a=float(0), rawString=None) + newFoo.bing.ret = 0xAA + for i in range(len(unionVariable.myFoobar.rawString)): + if (unionVariable.myFoobar.rawString[i] != (i + 1)): + newFoo.bing.ret = 0x55 + elif discriminator == test_unions.common.fruit.banana: + newFoo.discriminator = test_unions.common.fruit.papaya + if (unionVariable.x == 3) and (unionVariable.y == float(4.0)): + newFoo.bing.x = 4 + newFoo.bing.y = 3 + else: + newFoo.bing.x = 1 + newFoo.bing.y = 1 + elif discriminator == test_unions.common.fruit.orange: + newFoo.discriminator = test_unions.common.fruit.returnVal + newFoo.bing.ret = 0xAA + for i in range(len(unionVariable.a)): + if (unionVariable.a[i] != (i + 1)): + newFoo.bing.ret = 0x55 + return newFoo + +## Run server on specified transport layer +def runServer(transport): + # create test unions eRPC service + handler = UnionsTestServiceHandler() + service = test_unions.server.ArithmeticServiceService(handler) + + # run server + server = erpc.simple_server.SimpleServer(transport, erpc.basic_codec.BasicCodec) + server.add_service(service) + print('\r\nWait for client to send a eRPC request') + sys.stdout.flush() + server.run() + +############################################################################### +# Client +############################################################################### + +## Individual test cases / eRPC calls + +def runTestUnionsServiceID(client): + assert 2 == test_unions.interface.IArithmeticService.SERVICE_ID + +def runtestGenericCallback(client): + event = test_unions.common.gapGenericEvent_t(eventType=test_unions.common.gapGenericEventType_t.gInternalError_c) + event.eventData.internalError = test_unions.common.gapInternalError_t(errorCode=test_unions.common.bleResult_t.gBleSuccess_c, errorSource=test_unions.common.gapInternalErrorSource_t.gHciCommandStatus_c, hciCommandOpcode=5) + newEvent = test_unions.common.gapGenericEvent_t() + #print(event) + # send request to the server + print('\r\neRPC request is sent to the server') + newEvent = client.testGenericCallback(event) + assert newEvent.eventType == test_unions.common.gapGenericEventType_t.gWhiteListSizeReady_c + + event.eventType = test_unions.common.gapGenericEventType_t.gRandomAddressReady_c + event.eventData.aAddress = [0 for a in range(test_unions.common.gcBleDeviceAddressSize_c)] + for x in range(test_unions.common.gcBleDeviceAddressSize_c): + event.eventData.aAddress[x] = (0xAA ^ 0xFF) + print('\r\neRPC request is sent to the server') + newEvent = client.testGenericCallback(event) + assert newEvent.eventType == test_unions.common.gapGenericEventType_t.gTestCaseReturn_c + assert newEvent.eventData.returnCode == 1 + + event.eventType = test_unions.common.gapGenericEventType_t.gWhiteListSizeReady_c + event.eventData.whiteListSize = 100 + print('\r\neRPC request is sent to the server') + newEvent = client.testGenericCallback(event) + assert newEvent.eventType == test_unions.common.gapGenericEventType_t.gTestCaseReturn_c + assert newEvent.eventData.returnCode == 100 + +def runtestUnionLists(client): + myFoo = test_unions.common.foo() + returnFoo = test_unions.common.foo() + myFoo.discriminator = test_unions.common.fruit.orange + myFoo.bing.a = [a+1 for a in range(5)] + # send request to the server + print('\r\neRPC request is sent to the server') + returnFoo = client.sendMyFoo(myFoo) + assert returnFoo.discriminator == test_unions.common.fruit.returnVal + assert returnFoo.bing.ret == 0xAA + + myFoo.discriminator = test_unions.common.fruit.banana + myFoo.bing.x = 3 + myFoo.bing.y = float(4.0) + # send request to the server + print('\r\neRPC request is sent to the server') + returnFoo = client.sendMyFoo(myFoo) + assert returnFoo.discriminator == test_unions.common.fruit.papaya + assert returnFoo.bing.x == 4 + assert returnFoo.bing.y == float(3) + +def runtestNestedStructs(client): + myFoo = test_unions.common.foo() + returnFoo = test_unions.common.foo() + myFoo.discriminator = test_unions.common.fruit.apple + myFoo.bing.a = float(2.0) + myFoo.bing.myFoobar = test_unions.common.foobar(a=float(0), rawString=None) + myFoo.bing.myFoobar.rawString = bytearray(b'') + for x in range(10): + myFoo.bing.myFoobar.rawString.append(x+1) + # send request to the server + print('\r\neRPC request is sent to the server') + returnFoo = client.sendMyFoo(myFoo) + assert returnFoo.discriminator == test_unions.common.fruit.returnVal + assert returnFoo.bing.ret == 0xAA + +def runtestUnionAnn(client): + myFoo = test_unions.common.unionType() + discriminator = test_unions.common.fruit() + discriminator = test_unions.common.fruit.orange + myFoo.a = [a+1 for a in range(5)] + returnFoo = test_unions.common.foo() + # send request to the server + print('\r\neRPC request is sent to the server') + returnFoo = client.sendMyUnion(discriminator, myFoo) + assert returnFoo.discriminator == test_unions.common.fruit.returnVal + assert returnFoo.bing.ret == 0xAA + + discriminator = test_unions.common.fruit.banana + myFoo.x = 3 + myFoo.y = float(4.0) + # send request to the server + print('\r\neRPC request is sent to the server') + returnFoo = client.sendMyUnion(discriminator, myFoo) + assert returnFoo.bing.x == 4 + assert returnFoo.bing.y == float(3) + +############################################################################### +# PYTESTS +############################################################################### +class TestUnions: + server_cmd = [(os.path.abspath(__file__)).replace(os.sep, '/'), '-s'] + services = [test_unions.server.ArithmeticServiceService(UnionsTestServiceHandler()), test_unit_test_common.server.CommonService(CommonTestServiceHandler())] + clientsConstructors = [test_unions.client.ArithmeticServiceClient, test_unit_test_common.client.CommonClient] + runner = None + + def test_runTesttestPrepareEnv(self): + TestUnions.runner = Runner('test_unions', TestUnions.server_cmd, TestUnions.services, TestUnions.clientsConstructors) + + def test_runTestUnionsServiceID(self): + self.runner.runTest(test_unions.interface.IArithmeticService.SERVICE_ID , runTestUnionsServiceID) + + def test_runtestGenericCallback(self): + self.runner.runTest(test_unions.interface.IArithmeticService.SERVICE_ID, runtestGenericCallback) + + def test_runtestUnionLists(self): + self.runner.runTest(test_unions.interface.IArithmeticService.SERVICE_ID, runtestUnionLists) + + def test_runtestNestedStructs(self): + self.runner.runTest(test_unions.interface.IArithmeticService.SERVICE_ID, runtestNestedStructs) + + def test_runtestUnionAnn(self): + self.runner.runTest(test_unions.interface.IArithmeticService.SERVICE_ID, runtestUnionAnn) + + def test_runTesttestQuit(self): + self.runner.runTest(test_unit_test_common.interface.ICommon.SERVICE_ID, runTesttestQuit) + + def runTests(self): + self.test_runTesttestPrepareEnv() + self.test_runTestUnionsServiceID() + self.test_runtestGenericCallback() + self.test_runtestUnionLists() + self.test_runtestNestedStructs() + self.test_runTesttestQuit() + +############################################################################### +# Main +############################################################################### + +if __name__ == "__main__": + tester = TestUnions() + tester.runTests() diff --git a/test/run_unit_tests.py b/test/run_unit_tests.py index 34a703a7..a65d897a 100644 --- a/test/run_unit_tests.py +++ b/test/run_unit_tests.py @@ -17,14 +17,16 @@ import os import sys -#define output text colour class + class bcolors: + # define output text colour class GREEN = '\033[36m' BLUE = '\033[38;5;097m' - ORANGE= '\033[38;5;172m' + ORANGE = '\033[38;5;172m' RED = '\033[31m' ENDC = '\033[0m' + def isTestDir(dir): regex = re.compile('test_*') if os.path.isdir(dir) and re.match(regex, dir): @@ -32,15 +34,19 @@ def isTestDir(dir): else: return False + testClientCommand = "run-tcp-client" testServerCommand = "run-tcp-server" transportLayer = "tcp" target = "release" +compilerC = "" +compilerCpp = "" +make = "make" # Process command line options # Check for 2 or more arguments because argv[0] is the script name if len(sys.argv) > 2: - print ("Too many arguments. Please specify only the transport layer to use. Options are: tcp") + print("Too many arguments. Please specify only the transport layer to use. Options are: tcp") sys.exit(1) if len(sys.argv) >= 2: for arg in sys.argv[1:]: @@ -52,10 +58,19 @@ def isTestDir(dir): target = "debug" elif arg == "-r": target = "release" + elif arg == "clang": + compilerC = "clang" + compilerCpp = "clang++" + elif arg == "gcc": + compilerC = "gcc" + compilerCpp = "gcc++" + elif "-m" in arg: + make = arg[2:] else: print("Invalid argument/s. Options are: tcp, -r, -d\n") sys.exit(1) + unitTestPath = "./test/" # enter Unit Test Directory os.chdir(unitTestPath) @@ -68,12 +83,24 @@ def isTestDir(dir): build = "build=" + target testsExitStatus = 0 +clientCmd = [make, build, testClientCommand] +serverCmd = [make, build, testServerCommand] +compilerParamC = "" +compilerParamCpp = "" +if compilerC != "": + compilerParamC = "CC="+compilerC + compilerParamCpp = "CXX="+compilerParamCpp + clientCmd.append(compilerParamC) + serverCmd.append(compilerParamC) + clientCmd.append(compilerParamCpp) + serverCmd.append(compilerParamCpp) + for dir in testDirs: - print(bcolors.BLUE + "\nRunning " + bcolors.ORANGE + dir + bcolors.BLUE +" unit tests with " - + bcolors.ORANGE + transportLayer + bcolors.BLUE + " transport layer." + bcolors.ENDC) + print(bcolors.BLUE + "\nRunning " + bcolors.ORANGE + dir + bcolors.BLUE + " unit tests with " + + bcolors.ORANGE + transportLayer + bcolors.BLUE + " transport layer." + bcolors.ENDC) os.chdir(dir) - call(["make", build, testServerCommand]) - testsExitStatus += call(["make", build, testClientCommand]) + call(serverCmd) + testsExitStatus += call(clientCmd) os.chdir('..') # For completeness, change back to erpc/ directory diff --git a/test/test_annotations/external.h b/test/test_annotations/external.h index 2ccab8a7..f6d7bef0 100644 --- a/test/test_annotations/external.h +++ b/test/test_annotations/external.h @@ -14,6 +14,8 @@ // Definitions //////////////////////////////////////////////////////////////////////////////// +#include + // Enumerators data types declarations typedef enum myEnum { diff --git a/test/test_annotations/test_annotations.erpc b/test/test_annotations/test_annotations.erpc index db981700..0a1e52cc 100644 --- a/test/test_annotations/test_annotations.erpc +++ b/test/test_annotations/test_annotations.erpc @@ -12,6 +12,7 @@ @c:output_dir("erpc_outputs/") // testing directory with slash on end @c:include("addOne.hpp") @c:include("external.h") +@java:include("io.github.embeddedrpc.erpc.tests.common.myEnum") program test; import "../common/unit_test_common.erpc" diff --git a/test/test_annotations/test_annotations_client_impl.cpp b/test/test_annotations/test_annotations_client_impl.cpp index a354d1de..3407606b 100644 --- a/test/test_annotations/test_annotations_client_impl.cpp +++ b/test/test_annotations/test_annotations_client_impl.cpp @@ -6,13 +6,19 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" //////////////////////////////////////////////////////////////////////////////// // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initAnnotateTest_client(client); +} + TEST(test_annotations, AnnotationServiceID) { EXPECT_EQ(kAnnotateTest_service_id, 5); diff --git a/test/test_annotations/test_annotations_server_impl.cpp b/test/test_annotations/test_annotations_server_impl.cpp index 66c7d202..74f4761d 100644 --- a/test/test_annotations/test_annotations_server_impl.cpp +++ b/test/test_annotations/test_annotations_server_impl.cpp @@ -8,13 +8,18 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_server.hpp" +#include "test_unit_test_common_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include +using namespace erpc; +using namespace erpcShim; + AnnotateTest_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -35,6 +40,30 @@ myInt testIfMyIntAndConstExist(myInt a) return a; } +class AnnotateTest_server : public AnnotateTest_interface +{ +public: + int32_t add(int32_t a, int32_t b) + { + int32_t result; + result = ::add(a, b); + + return result; + } + + void testIfFooStructExist(const fooStruct *a) { ::testIfFooStructExist(a); } + + void testIfMyEnumExist(myEnum a) { ::testIfMyEnumExist(a); } + + myInt testIfMyIntAndConstExist(myInt a) + { + myInt result; + result = ::testIfMyIntAndConstExist(a); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -44,7 +73,7 @@ void add_services(erpc::SimpleServer *server) /* Define services to add using dynamic memory allocation * Exapmle:ArithmeticService_service * svc = new ArithmeticService_service(); */ - svc = new AnnotateTest_service(); + svc = new AnnotateTest_service(new AnnotateTest_server()); /* Add services * Example: server->addService (svc); */ @@ -63,6 +92,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -81,12 +111,6 @@ void remove_services_from_server(erpc_server_t server) erpc_remove_service_from_server(server, service_test); destroy_AnnotateTest_service(service_test); } - -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_arbitrator/client.mk b/test/test_arbitrator/client.mk index 8c7d6f02..a9a9851d 100644 --- a/test/test_arbitrator/client.mk +++ b/test/test_arbitrator/client.mk @@ -16,7 +16,11 @@ #------------------------------------------------------------------------------- SOURCES += $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp \ - $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp\ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_interface.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_interface.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_secondInterface_server.cpp \ $(CUR_DIR)_$(APP_TYPE)_impl.cpp \ $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_arbitrator_$(APP_TYPE).cpp @@ -27,6 +31,9 @@ all: $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp $(ERPC_OUT_DIR) $(OUTPUT_ROOT)/test/$(TEST_NAME)/$(CUR_DIR)_$(APP_TYPE)_impl.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_arbitrator_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME)_secondInterface_server.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_interface.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_interface.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp # Run erpcgen for C. $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_server.cpp: $(IDL_FILE) diff --git a/test/test_arbitrator/config/erpc_config.h b/test/test_arbitrator/config/erpc_config.h index 42bced91..a5c4d552 100644 --- a/test/test_arbitrator/config/erpc_config.h +++ b/test/test_arbitrator/config/erpc_config.h @@ -1,8 +1,10 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. - * Copyright 2016-2021 NXP + * Copyright 2016-2020 NXP + * Copyright 2020-2021 ACRIOS Systems s.r.o. * All rights reserved. * + * * SPDX-License-Identifier: BSD-3-Clause */ @@ -64,17 +66,17 @@ //! Set ERPC_ALLOCATION_POLICY_DYNAMIC if dynamic allocations should be used. //! Set ERPC_ALLOCATION_POLICY_STATIC if static allocations should be used. //! -//! Default value is ERPC_ALLOCATION_POLICY_DYNAMIC or in case of FreeRTOS it can be auto-detected if __has_include() is supported -//! by compiler. Uncomment comment bellow to use static allocation policy. -//! In case of static implementation user need consider another values to set (ERPC_CODEC_COUNT, -//! ERPC_MESSAGE_LOGGERS_COUNT, ERPC_CLIENTS_THREADS_AMOUNT). +//! Default value is ERPC_ALLOCATION_POLICY_DYNAMIC or in case of FreeRTOS it can be auto-detected if __has_include() is +//! supported by compiler. Uncomment comment bellow to use static allocation policy. In case of static implementation +//! user need consider another values to set (ERPC_CODEC_COUNT, ERPC_MESSAGE_LOGGERS_COUNT, +//! ERPC_CLIENTS_THREADS_AMOUNT). #define ERPC_ALLOCATION_POLICY (ERPC_ALLOCATION_POLICY_DYNAMIC) //! @def ERPC_CODEC_COUNT //! //! @brief Set amount of codecs objects used simultaneously in case of ERPC_ALLOCATION_POLICY is set to -//! ERPC_ALLOCATION_POLICY_STATIC. For example if client or server is used in one thread then 1. If both are used in one thread per -//! each then 2, ... Default value 2. +//! ERPC_ALLOCATION_POLICY_STATIC. For example if client or server is used in one thread then 1. If both are used in one +//! thread per each then 2, ... Default value 2. #define ERPC_CODEC_COUNT (2U) //! @def ERPC_MESSAGE_LOGGERS_COUNT @@ -88,8 +90,8 @@ //! @def ERPC_CLIENTS_THREADS_AMOUNT //! -//! @brief Set amount of client threads objects used in case of ERPC_ALLOCATION_POLICY is set to ERPC_ALLOCATION_POLICY_STATIC. -//! Default value 1 (Most of current cases). +//! @brief Set amount of client threads objects used in case of ERPC_ALLOCATION_POLICY is set to +//! ERPC_ALLOCATION_POLICY_STATIC. Default value 1 (Most of current cases). #define ERPC_CLIENTS_THREADS_AMOUNT (1U) //! @def ERPC_THREADS @@ -145,7 +147,7 @@ //! ERPC_MESSAGE_LOGGING_DISABLED. //! //! Uncomment for using logging feature. -// #define ERPC_MESSAGE_LOGGING (ERPC_MESSAGE_LOGGING_ENABLED) +//#define ERPC_MESSAGE_LOGGING (ERPC_MESSAGE_LOGGING_ENABLED) //! @def ERPC_TRANSPORT_MU_USE_MCMGR //! @@ -181,10 +183,27 @@ //! @name Assert function definition //@{ -//! User custom asser defition. Include header file if needed before bellow line. If assert is not enabled, default will be used. +//! User custom asser defition. Include header file if needed before bellow line. If assert is not enabled, default will +//! be used. // #define erpc_assert(condition) //@} +//! @def ENDIANES_HEADER +//! +//! Include header file that controls the communication endianness +//! +//! Uncomment for example behaviour for endianness agnostic with: +//! 1. communication in little endian. +//! 2. current processor is big endian. +//! 3. pointer size is 32 bit. +//! 4. float+double scheme not defined, so throws assert if passes. +//! #define ERPC_PROCESSOR_ENDIANNESS_LITTLE 0 +//! #define ERPC_COMMUNICATION_LITTLE 1 +//! #define ERPC_POINTER_SIZE_16 0 +//! #define ERPC_POINTER_SIZE_32 1 +//! #define ERPC_POINTER_SIZE_64 0 +//! #define ENDIANNESS_HEADER "erpc_endianness_agnostic_example.h" + /*! @} */ #endif // _ERPC_CONFIG_H_ //////////////////////////////////////////////////////////////////////////////// diff --git a/test/test_arbitrator/server.mk b/test/test_arbitrator/server.mk index 07bca589..566799c1 100644 --- a/test/test_arbitrator/server.mk +++ b/test/test_arbitrator/server.mk @@ -16,7 +16,11 @@ #------------------------------------------------------------------------------- SOURCES += $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_interface.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_secondInterface_client.cpp \ $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_interface.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp \ $(CUR_DIR)_$(APP_TYPE)_impl.cpp \ $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_arbitrator_$(APP_TYPE).cpp @@ -27,6 +31,10 @@ all: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp $(ERPC_OUT_DIR)/$(E $(OUTPUT_ROOT)/test/$(TEST_NAME)/$(CUR_DIR)_$(APP_TYPE)_impl.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_arbitrator_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME)_secondInterface_client.cpp : $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME)_firstInterface_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_firstInterface_interface.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_interface.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp + # Run erpcgen for C. $(ERPC_OUT_DIR)/$(ERPC_NAME)_secondInterface_client.cpp: $(IDL_FILE) diff --git a/test/test_arbitrator/test_arbitrator.erpc b/test/test_arbitrator/test_arbitrator.erpc index 62202f09..a459286f 100644 --- a/test/test_arbitrator/test_arbitrator.erpc +++ b/test/test_arbitrator/test_arbitrator.erpc @@ -8,10 +8,9 @@ @crc @output_dir("erpc_outputs/") +@namespace("") program test; -import "../common/unit_test_common.erpc" - @group("firstInterface") interface FirstInterface { diff --git a/test/test_arbitrator/test_arbitrator_client_impl.cpp b/test/test_arbitrator/test_arbitrator_client_impl.cpp index ec009e76..22839f2b 100644 --- a/test/test_arbitrator/test_arbitrator_client_impl.cpp +++ b/test/test_arbitrator/test_arbitrator_client_impl.cpp @@ -8,14 +8,19 @@ #include "erpc_simple_server.hpp" +#include "c_test_firstInterface_client.h" +#include "c_test_secondInterface_server.h" #include "gtest.h" -#include "test_firstInterface.h" -#include "test_secondInterface_server.h" +#include "test_secondInterface_server.hpp" +#include "unit_test.h" +#include "unit_test_wrapped.h" //////////////////////////////////////////////////////////////////////////////// // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +using namespace erpc; + #define number 15 #define nestedCallsCount 10 volatile int j = 0; @@ -23,6 +28,11 @@ volatile int numbers[number]; volatile bool enabled = false; SecondInterface_service *svc; +void initInterfaces(erpc_client_t client) +{ + initFirstInterface_client(client); +} + TEST(test_arbitrator, FirstSendReceiveInt) { for (int i = 0; i < number; i++) @@ -99,12 +109,38 @@ void enableFirstSide() enabled = true; } +class SecondInterface_server : public SecondInterface_interface +{ +public: + void secondSendInt(int32_t a) { ::secondSendInt(a); } + + int32_t secondReceiveInt(void) + { + int32_t result; + result = ::secondReceiveInt(); + + return result; + } + + void quitSecondInterfaceServer(void) { ::quitSecondInterfaceServer(); } + + void enableFirstSide(void) { ::enableFirstSide(); } + + int32_t callFirstSide(void) + { + int32_t result; + result = ::callFirstSide(); + + return result; + } +}; + void add_services(erpc::SimpleServer *server) { /* Define services to add using dynamic memory allocation * Exapmle:ArithmeticService_service * svc = new ArithmeticService_service(); */ - svc = new SecondInterface_service(); + svc = new SecondInterface_service(new SecondInterface_server()); /* Add services * Example: server->addService(svc); @@ -124,5 +160,6 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } diff --git a/test/test_arbitrator/test_arbitrator_server_impl.cpp b/test/test_arbitrator/test_arbitrator_server_impl.cpp index f4ccc399..cb039760 100644 --- a/test/test_arbitrator/test_arbitrator_server_impl.cpp +++ b/test/test_arbitrator/test_arbitrator_server_impl.cpp @@ -8,18 +8,28 @@ #include "erpc_simple_server.hpp" -#include "test_firstInterface_server.h" -#include "test_secondInterface.h" +#include "c_test_firstInterface_server.h" +#include "c_test_secondInterface_client.h" +#include "test_firstInterface_server.hpp" +#include "unit_test_wrapped.h" //////////////////////////////////////////////////////////////////////////////// // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +using namespace erpc; + #define number 15 volatile int i = 0; volatile int numbers[number]; FirstInterface_service *svc; +extern "C" { +void initInterfaces(erpc_client_t client) +{ + initSecondInterface_client(client); +} + void firstSendInt(int32_t a) { numbers[i] = a; @@ -41,13 +51,60 @@ int32_t callSecondSide() { return callFirstSide() + 1; } +} + +class FirstInterface_server : public FirstInterface_interface +{ +public: + void whenReady(void) { ::whenReady(); } + + void firstSendInt(int32_t a) { ::firstSendInt(a); } + + int32_t firstReceiveInt(void) + { + int32_t result; + result = ::firstReceiveInt(); + + return result; + } + + void stopSecondSide(void) { ::stopSecondSide(); } + + int32_t getResultFromSecondSide(void) + { + int32_t result; + result = ::getResultFromSecondSide(); + + return result; + } + + void testCasesAreDone(void) { ::testCasesAreDone(); } + + void quitFirstInterfaceServer(void) { ::quitFirstInterfaceServer(); } + + int32_t nestedCallTest(void) + { + int32_t result; + result = ::nestedCallTest(); + + return result; + } + + int32_t callSecondSide(void) + { + int32_t result; + result = ::callSecondSide(); + + return result; + } +}; void add_services(erpc::SimpleServer *server) { /* Define services to add using dynamic memory allocation * Exapmle:ArithmeticService_service * svc = new ArithmeticService_service(); */ - svc = new FirstInterface_service(); + svc = new FirstInterface_service(new FirstInterface_server()); /* Add services * Example: server->addService(svc); @@ -67,5 +124,6 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } diff --git a/test/test_arrays/test_arrays_client_impl.cpp b/test/test_arrays/test_arrays_client_impl.cpp index 6b1ca2d7..4b80e35b 100644 --- a/test/test_arrays/test_arrays_client_impl.cpp +++ b/test/test_arrays/test_arrays_client_impl.cpp @@ -6,8 +6,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" #include @@ -15,6 +16,11 @@ // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initPointersService_client(client); +} + TEST(test_arrays, sendReceivedInt32) { uint32_t array_count = 12; diff --git a/test/test_arrays/test_arrays_server_impl.cpp b/test/test_arrays/test_arrays_server_impl.cpp index c0e70ca0..b48f66fb 100644 --- a/test/test_arrays/test_arrays_server_impl.cpp +++ b/test/test_arrays/test_arrays_server_impl.cpp @@ -8,14 +8,18 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include #include +using namespace erpc; +using namespace erpcShim; + PointersService_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -374,16 +378,185 @@ void test_array_allDirection(const int32_t a[5], const int32_t b[5], int32_t c[5 void testFunction(){}; +class PointersService_server : public PointersService_interface +{ +public: + int32_t (*sendReceivedInt32(const int32_t arrayNumbers[12]))[12] + { + int32_t(*result)[12] = NULL; + result = ::sendReceivedInt32(arrayNumbers); + + return result; + } + + int32_t (*sendReceived2Int32(int32_t arrayNumbers[12][10]))[12][10] + { + int32_t(*result)[12][10] = NULL; + result = ::sendReceived2Int32(arrayNumbers); + + return result; + } + + char *(*sendReceivedString(char *arrayStrings[12]))[12] + { + char *(*result)[12] = NULL; + result = ::sendReceivedString(arrayStrings); + + return result; + } + + char *(*sendReceived2String(char *arrayStrings[3][5]))[3][5] + { + char *(*result)[3][5] = NULL; + result = ::sendReceived2String(arrayStrings); + + return result; + } + + enumColor (*sendReceivedEnum(const enumColor arrayEnums[3]))[3] + { + enumColor(*result)[3] = NULL; + result = ::sendReceivedEnum(arrayEnums); + + return result; + } + + enumColor (*sendReceived2Enum(enumColor arrayEnums[3][3]))[3][3] + { + enumColor(*result)[3][3] = NULL; + result = ::sendReceived2Enum(arrayEnums); + + return result; + } + + list_int32_1_t (*sendReceivedList(const list_int32_1_t arrayLists[2]))[2] + { + list_int32_1_t(*result)[2] = NULL; + result = ::sendReceivedList(arrayLists); + + return result; + } + + list_int32_1_t (*sendReceived2List(list_int32_1_t arrayLists[2][2]))[2][2] + { + list_int32_1_t(*result)[2][2] = NULL; + result = ::sendReceived2List(arrayLists); + + return result; + } + + ArrayIntType *sendReceivedInt32Type(const ArrayIntType arrayNumbers) + { + ArrayIntType *result = NULL; + result = ::sendReceivedInt32Type(arrayNumbers); + + return result; + } + + Array2IntType *sendReceived2Int32Type(Array2IntType arrayNumbers) + { + Array2IntType *result = NULL; + result = ::sendReceived2Int32Type(arrayNumbers); + + return result; + } + + ArrayStringType *sendReceivedStringType(ArrayStringType arrayStrings) + { + ArrayStringType *result = NULL; + result = ::sendReceivedStringType(arrayStrings); + + return result; + } + + Array2StringType *sendReceived2StringType(Array2StringType arrayStrings) + { + Array2StringType *result = NULL; + result = ::sendReceived2StringType(arrayStrings); + + return result; + } + + ArrayEnumType *sendReceivedEnumType(const ArrayEnumType arrayEnums) + { + ArrayEnumType *result = NULL; + result = ::sendReceivedEnumType(arrayEnums); + + return result; + } + + Array2EnumType *sendReceived2EnumType(Array2EnumType arrayEnums) + { + Array2EnumType *result = NULL; + result = ::sendReceived2EnumType(arrayEnums); + + return result; + } + + ArrayStructType *sendReceivedStructType(const ArrayStructType arrayStructs) + { + ArrayStructType *result = NULL; + result = ::sendReceivedStructType(arrayStructs); + + return result; + } + + Array2StructType *sendReceived2StructType(Array2StructType arrayStructs) + { + Array2StructType *result = NULL; + result = ::sendReceived2StructType(arrayStructs); + + return result; + } + + ArrayListType *sendReceivedListType(const ArrayListType arrayLists) + { + ArrayListType *result = NULL; + result = ::sendReceivedListType(arrayLists); + + return result; + } + + Array2ListType *sendReceived2ListType(Array2ListType arrayLists) + { + Array2ListType *result = NULL; + result = ::sendReceived2ListType(arrayLists); + + return result; + } + + AllTypes (*sendReceiveStruct(const AllTypes arrayStructs[2]))[2] + { + AllTypes(*result)[2] = NULL; + result = ::sendReceiveStruct(arrayStructs); + + return result; + } + + AllTypes (*sendReceive2Struct(AllTypes arrayStructs[1][1]))[1][1] + { + AllTypes(*result)[1][1] = NULL; + result = ::sendReceive2Struct(arrayStructs); + + return result; + } + + void test_array_allDirection(const int32_t a[5], const int32_t b[5], int32_t c[5], int32_t d[5]) + { + ::test_array_allDirection(a, b, c, d); + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// void add_services(erpc::SimpleServer *server) { - // define services to add on heap - // allocate on heap so service doesn't go out of scope at end of method - svc = new PointersService_service(); - + /* Define services to add using dynamic memory allocation + * Exapmle:ArithmeticService_service * svc = new ArithmeticService_service(); + */ + svc = new PointersService_service(new PointersService_server()); // add services server->addService(svc); } @@ -400,6 +573,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -418,12 +592,6 @@ void remove_services_from_server(erpc_server_t server) erpc_remove_service_from_server(server, service_test); destroy_PointersService_service(service_test); } - -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_binary/test_binary_client_impl.cpp b/test/test_binary/test_binary_client_impl.cpp index 917a457f..58d74128 100644 --- a/test/test_binary/test_binary_client_impl.cpp +++ b/test/test_binary/test_binary_client_impl.cpp @@ -6,8 +6,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" using namespace std; @@ -15,6 +16,11 @@ using namespace std; // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initBinary_client(client); +} + /*TEST(test_binary, sendReceiveBinary) { binary *result, send; diff --git a/test/test_binary/test_binary_server_impl.cpp b/test/test_binary/test_binary_server_impl.cpp index b073d243..7e1ad36a 100644 --- a/test/test_binary/test_binary_server_impl.cpp +++ b/test/test_binary/test_binary_server_impl.cpp @@ -8,13 +8,16 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include +using namespace erpc; +using namespace erpcShim; + Binary_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -70,6 +73,21 @@ void test_binary_allDirectionLength(const uint8_t *a, const binary_t *b, binary_ free((void *)a); free((void *)b); }*/ +class Binary_server : public Binary_interface +{ +public: + void sendBinary(const binary_t *a) { ::sendBinary(a); } + + void test_binary_allDirection(const binary_t *a, const binary_t *b, binary_t *e) + { + ::test_binary_allDirection(a, b, e); + } + + void test_binary_allDirectionLength(const uint8_t *a, const binary_t *b, binary_t *d, uint32_t p1) + { + ::test_binary_allDirectionLength(a, b, d, p1); + } +}; //////////////////////////////////////////////////////////////////////////////// // Add service to server code @@ -80,7 +98,7 @@ void add_services(erpc::SimpleServer *server) /* Define services to add using dynamic memory allocation * Exapmle:ArithmeticService_service * svc = new ArithmeticService_service(); */ - svc = new Binary_service(); + svc = new Binary_service(new Binary_server()); /* Add services * Example: server->addService(svc); @@ -100,6 +118,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -119,11 +138,6 @@ void remove_services_from_server(erpc_server_t server) destroy_Binary_service(service_test); } -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_builtin/test_builtin_client_impl.cpp b/test/test_builtin/test_builtin_client_impl.cpp index a318947f..e355192c 100644 --- a/test/test_builtin/test_builtin_client_impl.cpp +++ b/test/test_builtin/test_builtin_client_impl.cpp @@ -6,8 +6,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" #include @@ -17,6 +18,11 @@ using namespace std; // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initBuiltinServices_client(client); +} + int32_t int32A = 2; int32_t int32B = -20; diff --git a/test/test_builtin/test_builtin_server_impl.cpp b/test/test_builtin/test_builtin_server_impl.cpp index 0cd2bf57..5daced06 100644 --- a/test/test_builtin/test_builtin_server_impl.cpp +++ b/test/test_builtin/test_builtin_server_impl.cpp @@ -8,14 +8,17 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include #include +using namespace erpc; +using namespace erpcShim; + BuiltinServices_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -150,6 +153,94 @@ char *returnHello() return hello; } +class BuiltinServices_server : public BuiltinServices_interface +{ +public: + void test_int32_in(int32_t a) { ::test_int32_in(a); } + + void test_int32_in2(int32_t b) { ::test_int32_in2(b); } + + void test_int32_out(int32_t *c) { ::test_int32_out(c); } + + void test_int32_inout(int32_t *e) { ::test_int32_inout(e); } + + int32_t test_int32_return(void) + { + int32_t result; + result = ::test_int32_return(); + + return result; + } + + int32_t test_int32_allDirection(int32_t a, int32_t b, int32_t *c, int32_t *e) + { + int32_t result; + result = ::test_int32_allDirection(a, b, c, e); + + return result; + } + + void test_float_inout(float a, float *b) { ::test_float_inout(a, b); } + + void test_double_inout(double a, double *b) { ::test_double_inout(a, b); } + + void test_string_in(const char *a) { ::test_string_in(a); } + + void test_string_in2(const char *b) { ::test_string_in2(b); } + + void test_string_out(char *c) { ::test_string_out(c); } + + void test_string_inout(char *e) { ::test_string_inout(e); } + + char *test_string_return(void) + { + char *result = NULL; + result = ::test_string_return(); + + return result; + } + + char *test_string_allDirection(const char *a, const char *b, char *c, char *e) + { + char *result = NULL; + result = ::test_string_allDirection(a, b, c, e); + + return result; + } + + char *test_string_empty(const char *a, const char *b, char *c, char *e) + { + char *result = NULL; + result = ::test_string_empty(a, b, c, e); + + return result; + } + + int32_t sendHello(const char *str) + { + int32_t result; + result = ::sendHello(str); + + return result; + } + + int32_t sendTwoStrings(const char *myStr1, const char *myStr2) + { + int32_t result; + result = ::sendTwoStrings(myStr1, myStr2); + + return result; + } + + char *returnHello(void) + { + char *result = NULL; + result = ::returnHello(); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -158,7 +249,7 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc = new BuiltinServices_service(); + svc = new BuiltinServices_service(new BuiltinServices_server()); // add services server->addService(svc); @@ -176,6 +267,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -194,12 +286,6 @@ void remove_services_from_server(erpc_server_t server) erpc_remove_service_from_server(server, service_test); destroy_BuiltinServices_service(service_test); } - -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_callbacks/callbacks1.h b/test/test_callbacks/callbacks1.h deleted file mode 100644 index b1d511c7..00000000 --- a/test/test_callbacks/callbacks1.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2017 NXP - * All rights reserved. - * - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -void callback1a(int32_t a, int32_t b); - -void callback1b(int32_t param1, int32_t param2); diff --git a/test/test_callbacks/callbacks2.h b/test/test_callbacks/callbacks2.h deleted file mode 100644 index f3f4120c..00000000 --- a/test/test_callbacks/callbacks2.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2017 NXP - * All rights reserved. - * - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -void callback2(int32_t param1, int32_t param2); diff --git a/test/test_callbacks/client.mk b/test/test_callbacks/client.mk new file mode 100644 index 00000000..749e4209 --- /dev/null +++ b/test/test_callbacks/client.mk @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------- +# Copyright (C) 2016 Freescale Semiconductor, Inc. +# Copyright 2016 NXP +# All Rights Reserved. +# +# THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL FREESCALE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +#------------------------------------------------------------------------------- + +SOURCES += $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME_APP)_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_core1_interface.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_interface.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp \ + $(CUR_DIR)_$(APP_TYPE)_impl.cpp \ + $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_$(APP_TYPE).cpp + +.PHONY: all +all: $(ERPC_OUT_DIR)/$(ERPC_NAME)_core0_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_core0_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_core1_interface.cpp + +# Define dependency. +$(OUTPUT_ROOT)/test/$(TEST_NAME)/$(CUR_DIR)_$(APP_TYPE)_impl.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_core0_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_core0_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_core0_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME)_core0_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_core0_$(APP_TYPE).cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_$(APP_TYPE).cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_core1_interface.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_interface.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp + +# Run erpcgen for C. +$(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp: $(IDL_FILE) + @$(call printmessage,orange,Running erpcgen-c $(TEST_NAME), $(subst $(ERPC_ROOT)/,,$<)) + $(at)$(ERPCGEN) -gc -o $(RPC_OBJS_ROOT)/ $(IDL_FILE) diff --git a/test/test_callbacks/server.mk b/test/test_callbacks/server.mk new file mode 100644 index 00000000..1d3d056d --- /dev/null +++ b/test/test_callbacks/server.mk @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------- +# Copyright (C) 2016 Freescale Semiconductor, Inc. +# Copyright 2016 NXP +# All Rights Reserved. +# +# THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL FREESCALE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +#------------------------------------------------------------------------------- + +SOURCES += $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_server.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME_APP)_server.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_core1_interface.cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp \ + $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_interface.cpp \ + $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp \ + $(CUR_DIR)_$(APP_TYPE)_impl.cpp \ + $(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_$(APP_TYPE).cpp + +.PHONY: all +all: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_server.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp $(ERPC_OUT_DIR)/$(ERPC_NAME)_core1_interface.cpp + +# Define dependency. +$(OUTPUT_ROOT)/test/$(TEST_NAME)/$(CUR_DIR)_$(APP_TYPE)_impl.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_server.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(UT_COMMON_SRC)/unit_test_$(TRANSPORT)_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_server.cpp $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_server.cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME_APP)_server.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(ERPC_OUT_DIR)/c_$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_$(APP_TYPE).cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_core1_interface.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp +$(ERPC_OUT_DIR)/$(ERPC_NAME)_unit_test_common_interface.cpp: $(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_interface.cpp + +# Run erpcgen for C. +$(ERPC_OUT_DIR)/$(ERPC_NAME_APP)_server.cpp: $(IDL_FILE) + @$(call printmessage,orange,Running erpcgen-c $(TEST_NAME), $(subst $(ERPC_ROOT)/,,$<)) + $(at)$(ERPCGEN) -gc -o $(RPC_OBJS_ROOT)/ $(IDL_FILE) diff --git a/test/test_callbacks/test_callbacks.erpc b/test/test_callbacks/test_callbacks.erpc index 0ae0aeff..9c7db83e 100644 --- a/test/test_callbacks/test_callbacks.erpc +++ b/test/test_callbacks/test_callbacks.erpc @@ -10,17 +10,17 @@ program test import "../common/unit_test_common.erpc" -oneway callback1_t(int32 a, int32 b) -oneway callback2_t(int32, int32) -callback3_t(int32 arg1, int32 arg2) -> int32 - @c:include("test_core1.h") @group("core0") interface ClientCore0Services { - myFun(in callback1_t pCallback1_in, out callback1_t pCallback1_out) -> void + type oneway callback1_t(int32 a, int32 b) + type callback3_t(int32 arg1, int32 arg2) -> int32 + type oneway callback2_t(int32, int32) + + myFun(in callback1_t pCallback1_in, out callback1_t pCallback1_out) -> int32 - myFun2(callback2_t pCallback2_in, out callback2_t pCallback2_out) -> void + myFun2(ClientCore1Services::callback2_t pCallback2_in, out ClientCore1Services::callback2_t pCallback2_out) -> void myFun3(callback3_t callback, in int32 arg1, in int32 arg2) -> int32 @@ -29,17 +29,16 @@ interface ClientCore0Services callback3_t my_mul; callback3_t my_div; - @c:include("callbacks1.h") callback1_t callback1a; - @c:include("callbacks1.h") callback1_t callback1b(param1, param2); } @group("core1") interface ClientCore1Services { - @c:include("callbacks2.h") + type oneway callback2_t(int32, int32) + callback2_t callback2(param1, param2); } diff --git a/test/test_callbacks/test_callbacks_client_impl.cpp b/test/test_callbacks/test_callbacks_client_impl.cpp index b85a6e46..76f11b94 100644 --- a/test/test_callbacks/test_callbacks_client_impl.cpp +++ b/test/test_callbacks/test_callbacks_client_impl.cpp @@ -5,9 +5,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_core0_client.h" #include "gtest.h" -#include "test_core0.h" -#include "test_core1_server.h" +#include "unit_test_wrapped.h" void callback2(int32_t param1, int32_t param2) {} @@ -15,6 +15,11 @@ void callback2(int32_t param1, int32_t param2) {} // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initClientCore0Services_client(client); +} + TEST(test_callbacks, In_Out_table_1) { callback1_t pCallback1_out = NULL; diff --git a/test/test_callbacks/test_callbacks_server_impl.cpp b/test/test_callbacks/test_callbacks_server_impl.cpp index 7f6884d2..cfb1be71 100644 --- a/test/test_callbacks/test_callbacks_server_impl.cpp +++ b/test/test_callbacks/test_callbacks_server_impl.cpp @@ -6,15 +6,19 @@ */ #include "erpc_server_setup.h" +#include "erpc_utils.hpp" -#include "test_core0_server.h" -#include "test_core1.h" -#include "test_unit_test_common_server.h" +#include "c_test_core0_server.h" +#include "c_test_core1_server.h" +#include "test_core0_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include +using namespace erpc; +using namespace erpcShim; + ClientCore0Services_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -24,18 +28,17 @@ ClientCore0Services_service *svc; callback1_t *cb1 = NULL; callback2_t *cb2 = NULL; -void myFun(const callback1_t pCallback1_in, callback1_t *pCallback1_out) +int32_t myFun(const callback1_t pCallback1_in, callback1_t *pCallback1_out) { - cb1 = NULL; pCallback1_in(1, 2); - *pCallback1_out = (callback1_t)cb1; + *pCallback1_out = pCallback1_in; + return 0; } void myFun2(const callback2_t pCallback2_in, callback2_t *pCallback2_out) { - cb2 = NULL; pCallback2_in(1, 2); - *pCallback2_out = (callback2_t)cb2; + *pCallback2_out = pCallback2_in; } void callback1a(int32_t a, int32_t b) @@ -83,6 +86,110 @@ int32_t my_div(int32_t arg1, int32_t arg2) return 0; } +static const callback1_t _callback1_t[2] = { callback1a, callback1b }; +static const callback2_t _callback2_t[1] = { callback2 }; +static const callback3_t _callback3_t[4] = { my_add, my_sub, my_mul, my_div }; + +class ClientCore0Services_server : public ClientCore0Services_interface +{ +public: + int32_t myFun(const callback1_t pCallback1_in, callback1_t *pCallback1_out) + { + uint16_t _fnIndex; + ::callback1_t _pCallback1_in = NULL; + ::callback1_t _pCallback1_out = NULL; + int32_t result; + + if (ClientCore0Services_interface::get_callbackIdx_callback1_t(&pCallback1_in, _fnIndex)) + { + _pCallback1_in = ::_callback1_t[_fnIndex]; + } + + result = ::myFun(_pCallback1_in, &_pCallback1_out); + + if (findIndexOfFunction((arrayOfFunctionPtr_t)::_callback1_t, sizeof(::_callback1_t) / sizeof(::callback1_t), + (functionPtr_t)_pCallback1_out, _fnIndex)) + { + ClientCore0Services_interface::get_callbackAddress_callback1_t(_fnIndex, pCallback1_out); + } + + return result; + } + + void myFun2(const ClientCore1Services_interface::callback2_t pCallback2_in, + ClientCore1Services_interface::callback2_t *pCallback2_out) + { + uint16_t _fnIndex; + ::callback2_t _pCallback2_in = NULL; + ::callback2_t _pCallback2_out = NULL; + + if (ClientCore1Services_interface::get_callbackIdx_callback2_t(&pCallback2_in, _fnIndex)) + { + _pCallback2_in = ::_callback2_t[_fnIndex]; + } + + ::myFun2(_pCallback2_in, &_pCallback2_out); + + if (findIndexOfFunction((arrayOfFunctionPtr_t)::_callback2_t, sizeof(::_callback2_t) / sizeof(::callback2_t), + (functionPtr_t)_pCallback2_out, _fnIndex)) + { + ClientCore1Services_interface::get_callbackAddress_callback2_t(_fnIndex, pCallback2_out); + } + } + + int32_t myFun3(const callback3_t callback, int32_t arg1, int32_t arg2) + { + uint16_t _fnIndex; + ::callback3_t _callback = NULL; + int32_t result; + + if (ClientCore0Services_interface::get_callbackIdx_callback3_t(&callback, _fnIndex)) + { + _callback = ::_callback3_t[_fnIndex]; + } + + result = ::myFun3(_callback, arg1, arg2); + + return result; + } + + int32_t my_add(int32_t arg1, int32_t arg2) + { + int32_t result; + result = ::my_add(arg1, arg2); + + return result; + } + + int32_t my_sub(int32_t arg1, int32_t arg2) + { + int32_t result; + result = ::my_sub(arg1, arg2); + + return result; + } + + int32_t my_mul(int32_t arg1, int32_t arg2) + { + int32_t result; + result = ::my_mul(arg1, arg2); + + return result; + } + + int32_t my_div(int32_t arg1, int32_t arg2) + { + int32_t result; + result = ::my_div(arg1, arg2); + + return result; + } + + void callback1a(int32_t a, int32_t b) { ::callback1a(a, b); } + + void callback1b(int32_t param1, int32_t param2) { ::callback1b(param1, param2); } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -91,7 +198,7 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc = new ClientCore0Services_service(); + svc = new ClientCore0Services_service(new ClientCore0Services_server()); // add services server->addService(svc); @@ -109,6 +216,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -127,12 +235,6 @@ void remove_services_from_server(erpc_server_t server) erpc_remove_service_from_server(server, service_test); destroy_ClientCore0Services_service(service_test); } - -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_const/test_const_client_impl.cpp b/test/test_const/test_const_client_impl.cpp index 3db9141a..cd3e6e26 100644 --- a/test/test_const/test_const_client_impl.cpp +++ b/test/test_const/test_const_client_impl.cpp @@ -7,12 +7,15 @@ */ #include "gtest.h" -#include "test.h" +#include "test_common.h" +#include "unit_test_wrapped.h" //////////////////////////////////////////////////////////////////////////////// // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) {} + TEST(test_const, CheckConsts) { EXPECT_EQ(a, 3); diff --git a/test/test_const/test_const_server_impl.cpp b/test/test_const/test_const_server_impl.cpp index 91c52740..90a83e7f 100644 --- a/test/test_const/test_const_server_impl.cpp +++ b/test/test_const/test_const_server_impl.cpp @@ -8,8 +8,8 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" #include "unit_test.h" #include "unit_test_wrapped.h" @@ -53,12 +53,6 @@ extern "C" { #endif void add_services_to_server(erpc_server_t server) {} void remove_services_from_server(erpc_server_t server) {} - -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_enums/test_enums_client_impl.cpp b/test/test_enums/test_enums_client_impl.cpp index 10530f7d..fda78c0e 100644 --- a/test/test_enums/test_enums_client_impl.cpp +++ b/test/test_enums/test_enums_client_impl.cpp @@ -6,13 +6,19 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" //////////////////////////////////////////////////////////////////////////////// // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initEnumsService_client(client); +} + enumColor enumColorA = green; enumColor enumColorB = red; diff --git a/test/test_enums/test_enums_server_impl.cpp b/test/test_enums/test_enums_server_impl.cpp index 9d437a83..7bd98846 100644 --- a/test/test_enums/test_enums_server_impl.cpp +++ b/test/test_enums/test_enums_server_impl.cpp @@ -8,13 +8,17 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include +using namespace erpc; +using namespace erpcShim; + EnumsService_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -75,6 +79,50 @@ enumErrorCode test_enumErrorCode_allDirection(enumErrorCode a, enumErrorCode b, return a; } +class EnumsService_server : public EnumsService_interface +{ +public: + void test_enumColor_in(enumColor a) { ::test_enumColor_in(a); } + + void test_enumColor_in2(enumColor b) { ::test_enumColor_in2(b); } + + void test_enumColor_out(enumColor *c) { ::test_enumColor_out(c); } + + void test_enumColor_inout(enumColor *e) { ::test_enumColor_inout(e); } + + enumColor test_enumColor_return(void) + { + enumColor result; + result = ::test_enumColor_return(); + + return result; + } + + enumColor test_enumColor_allDirection(enumColor a, enumColor b, enumColor *c, enumColor *e) + { + enumColor result; + result = ::test_enumColor_allDirection(a, b, c, e); + + return result; + } + + enumColor2 test_enumColor2_allDirection(enumColor2 a, enumColor2 b, enumColor2 *c, enumColor2 *e) + { + enumColor2 result; + result = ::test_enumColor2_allDirection(a, b, c, e); + + return result; + } + + enumErrorCode test_enumErrorCode_allDirection(enumErrorCode a, enumErrorCode b, enumErrorCode *c, enumErrorCode *e) + { + enumErrorCode result; + result = ::test_enumErrorCode_allDirection(a, b, c, e); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -83,7 +131,7 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc = new EnumsService_service(); + svc = new EnumsService_service(new EnumsService_server()); // add services server->addService(svc); @@ -101,6 +149,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -119,12 +168,6 @@ void remove_services_from_server(erpc_server_t server) erpc_remove_service_from_server(server, service_test); destroy_EnumsService_service(service_test); } - -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_lists/test_lists_client_impl.cpp b/test/test_lists/test_lists_client_impl.cpp index 4603070d..f648712a 100644 --- a/test/test_lists/test_lists_client_impl.cpp +++ b/test/test_lists/test_lists_client_impl.cpp @@ -6,8 +6,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" #include @@ -17,6 +18,11 @@ using namespace std; // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initPointersService_client(client); +} + TEST(test_list, SendReceivedInt32) { list_int32_1_t *received_list, send_list; @@ -52,7 +58,7 @@ TEST(test_list, sendReceiveZeroSize) received_list = sendReceivedInt32(&send_list); - EXPECT_EQ(received_list->elementsCount , 0); + EXPECT_EQ(received_list->elementsCount, 0); erpc_free(received_list->elements); erpc_free(received_list); @@ -88,7 +94,7 @@ TEST(test_list, SendReceived2Int32) list_r = list_int32_1_t_r->elements; for (uint32_t j = 0; j < list_int32_1_t_r->elementsCount; ++j) { - EXPECT_EQ((*list_r) / 2 , *list_s); + EXPECT_EQ((*list_r) / 2, *list_s); ++list_s; ++list_r; } diff --git a/test/test_lists/test_lists_server_impl.cpp b/test/test_lists/test_lists_server_impl.cpp index 8950ee43..7f5e517b 100644 --- a/test/test_lists/test_lists_server_impl.cpp +++ b/test/test_lists/test_lists_server_impl.cpp @@ -8,14 +8,18 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include #include +using namespace erpc; +using namespace erpcShim; + PointersService_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -309,6 +313,111 @@ int32_t sendGapAdvertisingData(const gapAdvertisingData_t *ad) return 33; } +class PointersService_server : public PointersService_interface +{ +public: + list_int32_1_t *sendReceivedInt32(const list_int32_1_t *listNumbers) + { + list_int32_1_t *result = NULL; + result = ::sendReceivedInt32(listNumbers); + + return result; + } + + list_int32_2_t *sendReceived2Int32(const list_int32_2_t *listNumbers) + { + list_int32_2_t *result = NULL; + result = ::sendReceived2Int32(listNumbers); + + return result; + } + + list_enumColor_1_t *sendReceivedEnum(const list_enumColor_1_t *listColors) + { + list_enumColor_1_t *result = NULL; + result = ::sendReceivedEnum(listColors); + + return result; + } + + list_enumColor_2_t *sendReceived2Enum(const list_enumColor_2_t *listColors) + { + list_enumColor_2_t *result = NULL; + result = ::sendReceived2Enum(listColors); + + return result; + } + + list_C_1_t *sendReceivedStruct(const list_C_1_t *listColors) + { + list_C_1_t *result = NULL; + result = ::sendReceivedStruct(listColors); + + return result; + } + + list_C_2_t *sendReceived2Struct(const list_C_2_t *listColors) + { + list_C_2_t *result = NULL; + result = ::sendReceived2Struct(listColors); + + return result; + } + + list_string_1_t *sendReceivedString(const list_string_1_t *listNumbers) + { + list_string_1_t *result = NULL; + result = ::sendReceivedString(listNumbers); + + return result; + } + + list_string_2_t *sendReceived2String(const list_string_2_t *listNumbers) + { + list_string_2_t *result = NULL; + result = ::sendReceived2String(listNumbers); + + return result; + } + + void test_list_allDirection(const list_uint32_1_t *a, const list_uint32_1_t *b, list_uint32_1_t *e) + { + ::test_list_allDirection(a, b, e); + } + + int32_t testLengthAnnotation(const int32_t *myList, uint32_t len) + { + int32_t result; + result = ::testLengthAnnotation(myList, len); + + return result; + } + + int32_t testLengthAnnotationInStruct(const listStruct *s) + { + int32_t result; + result = ::testLengthAnnotationInStruct(s); + + return result; + } + + listStruct *returnSentStructLengthAnnotation(const listStruct *s) + { + listStruct *result = NULL; + result = ::returnSentStructLengthAnnotation(s); + + return result; + } + + int32_t sendGapAdvertisingData(const gapAdvertisingData_t *ad) + { + int32_t result; + result = ::sendGapAdvertisingData(ad); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -317,7 +426,7 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc = new PointersService_service(); + svc = new PointersService_service(new PointersService_server()); // add services server->addService(svc); @@ -335,6 +444,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -354,11 +464,6 @@ void remove_services_from_server(erpc_server_t server) destroy_PointersService_service(service_test); } -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_shared/test_shared_client_impl.cpp b/test/test_shared/test_shared_client_impl.cpp index 87213bea..8fea5a99 100644 --- a/test/test_shared/test_shared_client_impl.cpp +++ b/test/test_shared/test_shared_client_impl.cpp @@ -5,19 +5,25 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" //////////////////////////////////////////////////////////////////////////////// // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initSharedService_client(client); +} + TEST(test_shared, sendReceiveBaseSharedStruct) { BaseSharedStruct sm = { 4, 5 }; BaseSharedStruct *_sm; _sm = sendReceiveBaseSharedStruct(&sm); - EXPECT_EQ(_sm , &sm); + EXPECT_EQ(_sm, &sm); } TEST(test_shared, inoutBaseSharedStruct) @@ -25,7 +31,7 @@ TEST(test_shared, inoutBaseSharedStruct) BaseSharedStruct sm = { 4, 5 }; BaseSharedStruct *_sm = &sm; inoutBaseSharedStruct(&_sm); - EXPECT_EQ(_sm , &sm); + EXPECT_EQ(_sm, &sm); } /*TEST(test_shared, inoutStruct1) diff --git a/test/test_shared/test_shared_server_impl.cpp b/test/test_shared/test_shared_server_impl.cpp index 5b3b9fb7..5890d6f8 100644 --- a/test/test_shared/test_shared_server_impl.cpp +++ b/test/test_shared/test_shared_server_impl.cpp @@ -7,13 +7,17 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include +using namespace erpc; +using namespace erpcShim; + SharedService_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -29,6 +33,20 @@ BaseSharedStruct *sendReceiveBaseSharedStruct(const BaseSharedStruct *s) void inoutBaseSharedStruct(BaseSharedStruct **s) {} /* end typedef unit tests */ +class SharedService_server : public SharedService_interface +{ +public: + BaseSharedStruct *sendReceiveBaseSharedStruct(const BaseSharedStruct *a) + { + BaseSharedStruct *result = NULL; + result = ::sendReceiveBaseSharedStruct(a); + + return result; + } + + void inoutBaseSharedStruct(BaseSharedStruct **a) { ::inoutBaseSharedStruct(a); } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -37,7 +55,7 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc = new SharedService_service(); + svc = new SharedService_service(new SharedService_server()); // add services server->addService(svc); @@ -55,6 +73,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -74,11 +93,6 @@ void remove_services_from_server(erpc_server_t server) destroy_SharedService_service(service_test); } -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_struct/test_struct_client_impl.cpp b/test/test_struct/test_struct_client_impl.cpp index bcb87b8c..7fbdd9f1 100644 --- a/test/test_struct/test_struct_client_impl.cpp +++ b/test/test_struct/test_struct_client_impl.cpp @@ -6,8 +6,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_ArithmeticService_client.h" #include "gtest.h" -#include "test_ArithmeticService.h" +#include "unit_test_wrapped.h" #include @@ -17,6 +18,12 @@ using namespace std; // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initArithmeticService1_client(client); + initArithmeticService2_client(client); +} + TEST(test_struct, GetMember1) { C c = { 4, 5 }; diff --git a/test/test_struct/test_struct_java.erpc b/test/test_struct/test_struct_java.erpc new file mode 100644 index 00000000..8c1a531e --- /dev/null +++ b/test/test_struct/test_struct_java.erpc @@ -0,0 +1,152 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +@c:include("myAlloc.hpp") +@output_dir("erpc_outputs") +//@clientOutputFormat(C) +//@serverOutputFormat(C) +program test; + +import "../common/unit_test_common.erpc" + +// Hello world! + +struct C +{ + int32 m + int32 n +} +struct B +{ + float x + float y +} +struct A +{ + B b + C c +} + +struct D +{ + C c +} + +struct F { + int8 a + int16 b + int32 c + int64 d +} + +// Java does not support uint64 + +struct G { + uint8 a + uint16 b + uint32 c + // uint64 d +} + + +struct primate { + string species + bool is_ape +} + +struct stringStruct { + string one + string two + string three +} + +enum school_year_t { + FRESHMAN = 9, + SOPHOMORE, + JUNIOR, + SENIOR +} + +struct student { + string name + float[3] test_grades + school_year_t school_year + int32 age +} + +enum enumColor{red, green, blue} + +struct AllTypes { + int32 number + string text + enumColor color + C c + list list_numbers + list list_text + int32[2] array_numbers + string[2] array_text + binary binary_numbers +} + +type Int32Type = int32 +type StringType = string +type EnumColorType = enumColor +type StructCType = C +type ListInt32Type = list +type ArrayInt32Type = int32[5] + +//type AnonymousStruct = struct { int32 a int32 b} + +//type AnonymousStruct2 = AnonymousStruct + +struct structOfAllTypes +{ + Int32Type number + StringType text + EnumColorType color + StructCType c + ListInt32Type list_numbers + ArrayInt32Type array_numbres +} + +type TypeOfAllTypes = AllTypes + +struct StructWithByrefMembers +{ + byref A a @shared; + byref int32 b; +} + +@group("group") +interface GroupService { + oneway groupFunction() +} + +@group("ArithmeticService") +interface ArithmeticService1 { + getMember(C c) -> int32 + returnStruct(float a, float b) -> B + getMemberTest2(A a) -> B + sendNestedStruct(D d) -> int32 + checkString(primate p @retain) -> int32 + returnStrings() -> stringStruct +} + +@group("ArithmeticService") +interface ArithmeticService2 { + sendManyInts(F f) -> int32 + sendManyUInts(G g) -> int32 + //student functions + getStudentName(student stud) -> string + getStudentTestAverage(student stud) -> float + getStudentYear(student stud) -> int32 + getStudentAge(student stud) -> int32 + createStudent(string name, float[3] test_scores, school_year_t year, int32 age) -> student + + test_struct_allDirection(AllTypes a, in AllTypes b, inout AllTypes e) -> void + + testSendingByrefMembers(StructWithByrefMembers s) -> bool +} diff --git a/test/test_struct/test_struct_server_impl.cpp b/test/test_struct/test_struct_server_impl.cpp index 27ebbae5..9214bcfd 100644 --- a/test/test_struct/test_struct_server_impl.cpp +++ b/test/test_struct/test_struct_server_impl.cpp @@ -8,14 +8,18 @@ #include "erpc_server_setup.h" -#include "test_ArithmeticService_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_ArithmeticService_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_ArithmeticService_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include #include +using namespace erpc; +using namespace erpcShim; + ArithmeticService1_service *svc1; ArithmeticService2_service *svc2; @@ -179,6 +183,131 @@ bool testSendingByrefMembers(const StructWithByrefMembers *s) return false; } +class ArithmeticService1_server : public ArithmeticService1_interface +{ +public: + int32_t getMember(const C *c) + { + int32_t result; + result = ::getMember(c); + + return result; + } + + B *returnStruct(float a, float b) + { + B *result = NULL; + result = ::returnStruct(a, b); + + return result; + } + + B *getMemberTest2(const A *a) + { + B *result = NULL; + result = ::getMemberTest2(a); + + return result; + } + + int32_t sendNestedStruct(const D *d) + { + int32_t result; + result = ::sendNestedStruct(d); + + return result; + } + + int32_t checkString(const primate *p) + { + int32_t result; + result = ::checkString(p); + + return result; + } + + stringStruct *returnStrings(void) + { + stringStruct *result = NULL; + result = ::returnStrings(); + + return result; + } +}; + +class ArithmeticService2_server : public ArithmeticService2_interface +{ +public: + int32_t sendManyInts(const F *f) + { + int32_t result; + result = ::sendManyInts(f); + + return result; + } + + int32_t sendManyUInts(const G *g) + { + int32_t result; + result = ::sendManyUInts(g); + + return result; + } + + char *getStudentName(const student *stud) + { + char *result = NULL; + result = ::getStudentName(stud); + + return result; + } + + float getStudentTestAverage(const student *stud) + { + float result; + result = ::getStudentTestAverage(stud); + + return result; + } + + int32_t getStudentYear(const student *stud) + { + int32_t result; + result = ::getStudentYear(stud); + + return result; + } + + int32_t getStudentAge(const student *stud) + { + int32_t result; + result = ::getStudentAge(stud); + + return result; + } + + student *createStudent(const char *name, const float test_scores[3], school_year_t year, int32_t age) + { + student *result = NULL; + result = ::createStudent(name, test_scores, year, age); + + return result; + } + + void test_struct_allDirection(const AllTypes *a, const AllTypes *b, AllTypes *e) + { + ::test_struct_allDirection(a, b, e); + } + + bool testSendingByrefMembers(const StructWithByrefMembers *s) + { + bool result; + result = ::testSendingByrefMembers(s); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -187,8 +316,8 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc1 = new ArithmeticService1_service(); - svc2 = new ArithmeticService2_service(); + svc1 = new ArithmeticService1_service(new ArithmeticService1_server()); + svc2 = new ArithmeticService2_service(new ArithmeticService2_server()); // add services server->addService(svc1); @@ -208,6 +337,8 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc2); /* Delete unused service */ + delete svc1->getHandler(); + delete svc2->getHandler(); delete svc1; delete svc2; } @@ -233,11 +364,6 @@ void remove_services_from_server(erpc_server_t server) destroy_ArithmeticService2_service(service2); } -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_typedef/test_typedef_client_impl.cpp b/test/test_typedef/test_typedef_client_impl.cpp index 7138825d..64ebeb30 100644 --- a/test/test_typedef/test_typedef_client_impl.cpp +++ b/test/test_typedef/test_typedef_client_impl.cpp @@ -6,8 +6,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" #include @@ -15,6 +16,11 @@ // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initTypedefService_client(client); +} + TEST(test_typedef, SendReceiveInt) { int32type a = 10, b = 2 * a + 1, pB; diff --git a/test/test_typedef/test_typedef_server_impl.cpp b/test/test_typedef/test_typedef_server_impl.cpp index c1e02bd6..eeeabca9 100644 --- a/test/test_typedef/test_typedef_server_impl.cpp +++ b/test/test_typedef/test_typedef_server_impl.cpp @@ -8,14 +8,18 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include #include +using namespace erpc; +using namespace erpcShim; + TypedefService_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -129,6 +133,58 @@ MultiListArray arrayNumbers, uint32_t arrayNumbers_1_count, uint32_t arrayNumber }*/ /* end typedef unit tests */ +class TypedefService_server : public TypedefService_interface +{ +public: + int32type sendReceiveInt(int32type a) + { + int32type result; + result = ::sendReceiveInt(a); + + return result; + } + + Colors sendReceiveEnum(Colors a) + { + Colors result; + result = ::sendReceiveEnum(a); + + return result; + } + + B *sendReceiveStruct(const B *a) + { + B *result = NULL; + result = ::sendReceiveStruct(a); + + return result; + } + + ListType *sendReceiveListType(const ListType *listNumbers) + { + ListType *result = NULL; + result = ::sendReceiveListType(listNumbers); + + return result; + } + + ListType2 *sendReceive2ListType(const ListType2 *listNumbers) + { + ListType2 *result = NULL; + result = ::sendReceive2ListType(listNumbers); + + return result; + } + + newString sendReceiveString(newString hello) + { + newString result = NULL; + result = ::sendReceiveString(hello); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -137,7 +193,7 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc = new TypedefService_service(); + svc = new TypedefService_service(new TypedefService_server()); // add services server->addService(svc); @@ -155,6 +211,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -174,11 +231,6 @@ void remove_services_from_server(erpc_server_t server) destroy_TypedefService_service(service_test); } -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/test/test_unions/test_unions_client_impl.cpp b/test/test_unions/test_unions_client_impl.cpp index 167374e7..17d29af3 100644 --- a/test/test_unions/test_unions_client_impl.cpp +++ b/test/test_unions/test_unions_client_impl.cpp @@ -6,8 +6,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "c_test_client.h" #include "gtest.h" -#include "test.h" +#include "unit_test_wrapped.h" #include @@ -17,6 +18,11 @@ using namespace std; // Unit test Implementation code //////////////////////////////////////////////////////////////////////////////// +void initInterfaces(erpc_client_t client) +{ + initArithmeticService_client(client); +} + TEST(test_unions, testGenericCallback) { gapGenericEvent_t event = { diff --git a/test/test_unions/test_unions_server_impl.cpp b/test/test_unions/test_unions_server_impl.cpp index 457d9957..8c2140d1 100644 --- a/test/test_unions/test_unions_server_impl.cpp +++ b/test/test_unions/test_unions_server_impl.cpp @@ -8,14 +8,18 @@ #include "erpc_server_setup.h" -#include "test_server.h" -#include "test_unit_test_common_server.h" +#include "c_test_server.h" +#include "c_test_unit_test_common_server.h" +#include "test_server.hpp" #include "unit_test.h" #include "unit_test_wrapped.h" #include #include +using namespace erpc; +using namespace erpcShim; + ArithmeticService_service *svc; //////////////////////////////////////////////////////////////////////////////// @@ -27,7 +31,8 @@ gapGenericEvent_t *testGenericCallback(const gapGenericEvent_t *event) gapGenericEvent_t *newEvent = (gapGenericEvent_t *)erpc_malloc(sizeof(gapGenericEvent_t)); switch (event->eventType) { - case gInternalError_c: { + case gInternalError_c: + { if (event->eventData.internalError.errorCode == gBleSuccess_c && event->eventData.internalError.errorSource == gHciCommandStatus_c && event->eventData.internalError.hciCommandOpcode == 5) @@ -40,7 +45,8 @@ gapGenericEvent_t *testGenericCallback(const gapGenericEvent_t *event) } break; } - case gRandomAddressReady_c: { + case gRandomAddressReady_c: + { int x = 0xAA; int success = 1; int i = 0; @@ -63,7 +69,8 @@ gapGenericEvent_t *testGenericCallback(const gapGenericEvent_t *event) } break; } - case gWhiteListSizeReady_c: { + case gWhiteListSizeReady_c: + { newEvent->eventType = gTestCaseReturn_c; if (100 == event->eventData.whiteListSize) { @@ -78,7 +85,8 @@ gapGenericEvent_t *testGenericCallback(const gapGenericEvent_t *event) case gPublicAddressRead_c: case gAdvertisingSetupFailed_c: case gAdvTxPowerLevelRead_c: - default: { + default: + { } } return newEvent; @@ -89,7 +97,8 @@ foo *sendMyFoo(const foo *f) foo *newFoo = (foo *)erpc_malloc(sizeof(foo)); switch (f->discriminator) { - case apple: { + case apple: + { for (uint32_t i = 0; i < f->bing.myFoobar.rawString.dataLength; ++i) { if ((i + 1) != f->bing.myFoobar.rawString.data[i]) @@ -104,7 +113,8 @@ foo *sendMyFoo(const foo *f) erpc_free(f->bing.myFoobar.rawString.data); break; } - case banana: { + case banana: + { if ((f->bing.x == 3) && (f->bing.y == 4.0)) { newFoo->discriminator = papaya; @@ -119,7 +129,8 @@ foo *sendMyFoo(const foo *f) } break; } - case orange: { + case orange: + { for (uint32_t i = 1; i <= f->bing.a.elementsCount; ++i) { // If data sent across is incorrect, return 0x55 @@ -136,7 +147,8 @@ foo *sendMyFoo(const foo *f) erpc_free(f->bing.a.elements); break; } - default: { + default: + { break; } } @@ -149,7 +161,8 @@ foo *sendMyUnion(fruit discriminator, const unionType *unionVariable) foo *newFoo = (foo *)erpc_malloc(sizeof(foo)); switch (discriminator) { - case apple: { + case apple: + { for (uint32_t i = 0; i < unionVariable->myFoobar.rawString.dataLength; ++i) { if ((i + 1) != unionVariable->myFoobar.rawString.data[i]) @@ -163,7 +176,8 @@ foo *sendMyUnion(fruit discriminator, const unionType *unionVariable) newFoo->bing.ret = 0xAA; break; } - case banana: { + case banana: + { if ((unionVariable->x == 3) && (unionVariable->y == 4.0)) { newFoo->discriminator = papaya; @@ -178,7 +192,8 @@ foo *sendMyUnion(fruit discriminator, const unionType *unionVariable) } break; } - case orange: { + case orange: + { for (uint32_t i = 1; i <= unionVariable->a.elementsCount; ++i) { // If data sent across is incorrect, return 0x55 @@ -194,7 +209,8 @@ foo *sendMyUnion(fruit discriminator, const unionType *unionVariable) newFoo->bing.ret = 0xAA; break; } - default: { + default: + { break; } } @@ -207,6 +223,42 @@ InnerList *testInnerList(const InnerList *il) return newList; } +class ArithmeticService_server : public ArithmeticService_interface +{ +public: + gapGenericEvent_t *testGenericCallback(const gapGenericEvent_t *event) + { + gapGenericEvent_t *result = NULL; + result = ::testGenericCallback(event); + + return result; + } + + foo *sendMyFoo(const foo *f) + { + foo *result = NULL; + result = ::sendMyFoo(f); + + return result; + } + + foo *sendMyUnion(fruit discriminator, const unionType *unionVariable) + { + foo *result = NULL; + result = ::sendMyUnion(discriminator, unionVariable); + + return result; + } + + InnerList *testInnerList(const InnerList *il) + { + InnerList *result = NULL; + result = ::testInnerList(il); + + return result; + } +}; + //////////////////////////////////////////////////////////////////////////////// // Add service to server code //////////////////////////////////////////////////////////////////////////////// @@ -215,7 +267,7 @@ void add_services(erpc::SimpleServer *server) { // define services to add on heap // allocate on heap so service doesn't go out of scope at end of method - svc = new ArithmeticService_service(); + svc = new ArithmeticService_service(new ArithmeticService_server()); // add services server->addService(svc); @@ -233,6 +285,7 @@ void remove_services(erpc::SimpleServer *server) server->removeService(svc); /* Delete unused service */ + delete svc->getHandler(); delete svc; } @@ -252,11 +305,6 @@ void remove_services_from_server(erpc_server_t server) destroy_ArithmeticService_service(service_test); } -void remove_common_services_from_server(erpc_server_t server, erpc_service_t service) -{ - erpc_remove_service_from_server(server, service); - destroy_Common_service(service); -} #ifdef __cplusplus } #endif diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt new file mode 100644 index 00000000..59d52d0e --- /dev/null +++ b/zephyr/CMakeLists.txt @@ -0,0 +1,74 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +cmake_minimum_required (VERSION 3.5) + +project (erpc C CXX) +set (ERPC_LIB erpc) + +if (CONFIG_ERPC) + set(ERPC_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/erpc_c) + + set(ERPC_INCLUDE_DIRS + ${ERPC_DIR}/infra + ${ERPC_DIR}/port + ${ERPC_DIR}/service + ${ERPC_DIR}/setup + ${ERPC_DIR}/transports + ) + + set(ERPC_SOURCES + + ${ERPC_DIR}/infra/erpc_basic_codec.cpp + ${ERPC_DIR}/infra/erpc_client_manager.cpp + ${ERPC_DIR}/infra/erpc_crc16.cpp + ${ERPC_DIR}/infra/erpc_framed_transport.cpp + ${ERPC_DIR}/infra/erpc_message_buffer.cpp + ${ERPC_DIR}/infra/erpc_message_loggers.cpp + ${ERPC_DIR}/infra/erpc_pre_post_action.cpp + ${ERPC_DIR}/infra/erpc_server.cpp + ${ERPC_DIR}/infra/erpc_simple_server.cpp + + ${ERPC_DIR}/infra/erpc_utils.cpp + ${ERPC_DIR}/port/erpc_port_zephyr.cpp + ${ERPC_DIR}/port/erpc_threading_zephyr.cpp + + ${ERPC_DIR}/setup/erpc_client_setup.cpp + ${ERPC_DIR}/setup/erpc_server_setup.cpp + ${ERPC_DIR}/setup/erpc_setup_mbf_dynamic.cpp + ${ERPC_DIR}/setup/erpc_setup_mbf_static.cpp + ) + + zephyr_library_named(${ERPC_LIB}) + zephyr_library_sources(${ERPC_SOURCES}) + zephyr_include_directories(${ERPC_INCLUDE_DIRS}) + zephyr_library_include_directories(${ERPC_INCLUDE_DIRS}) + + # Optional UART transport + zephyr_library_sources_ifdef( + CONFIG_ERPC_TRANSPORT_UART + ${ERPC_DIR}/transports/erpc_uart_zephyr_transport.cpp + ${ERPC_DIR}/setup/erpc_setup_uart_zephyr.cpp + ) + + # Optional RPMSG-LITE transport + zephyr_library_sources_ifdef( + CONFIG_ERPC_TRANSPORT_RPMSG_LITE + ${ERPC_DIR}/setup/erpc_setup_mbf_rpmsg.cpp + ${ERPC_DIR}/setup/erpc_setup_rpmsg_lite_rtos_master.cpp + ${ERPC_DIR}/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp + ${ERPC_DIR}/transports/erpc_rpmsg_lite_rtos_transport.cpp + ) + + # Optional arbitrated client + zephyr_library_sources_ifdef( + CONFIG_ERPC_ARBITRATED_CLIENT + ${ERPC_DIR}/infra/erpc_arbitrated_client_manager.cpp + ${ERPC_DIR}/infra/erpc_transport_arbitrator.cpp + ${ERPC_DIR}/setup/erpc_arbitrated_client_setup.cpp + ) + +endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig new file mode 100644 index 00000000..810bd062 --- /dev/null +++ b/zephyr/Kconfig @@ -0,0 +1,45 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +config ZEPHYR_ERPC_MODULE + bool + +config ERPC + bool "eRPC Support" + depends on ZEPHYR_ERPC_MODULE + help + This option enables the eRPC library + depends on CPP + depends on FULL_LIBCPP_SUPPORTED + +config ZEPHYR_BUILD + bool + +if ERPC + +module = ERPC +module-str = eRPC + +config ERPC_TRANSPORT_UART + bool "Enable eRPC UART transport" + help + When enabled, eRPC will include UART transport layer. + select RING_BUFFER + select SERIAL + select UART_INTERRUPT_DRIVEN + +config ERPC_TRANSPORT_RPMSG_LITE + bool "Enable eRPC rpsmg-lite transport" + help + When enabled, eRPC will include rpsmg-lite transport layer. + depends on RPMSGLITE + +config ERPC_ARBITRATED_CLIENT + bool "Enable eRPC arbitrated client" + help + When enabled, eRPC will include arbitrated client. + +endif # ERPC diff --git a/zephyr/module.yml b/zephyr/module.yml new file mode 100644 index 00000000..5322430c --- /dev/null +++ b/zephyr/module.yml @@ -0,0 +1,6 @@ +name: erpc +build: + cmake: ./zephyr + kconfig: ./zephyr/Kconfig +samples: + - ./examples/zephyr diff --git a/zephyr/readme.md b/zephyr/readme.md new file mode 100644 index 00000000..642b8efb --- /dev/null +++ b/zephyr/readme.md @@ -0,0 +1,63 @@ +# eRPC Zephyr support + +## Adding eRPC to Zephyr as module + +To include eRPC Zephyr, update Zephyr's west.yml: + +``` yml + projects: + - name: erpc + revision: + url: + path: modules/lib/erpc +``` +Then run: +``` sh +west update erpc +``` + +## eRPC module files + +- *erpc/zephyr/* - This directory holds all files required for Zephyr module +- *erpc/zephyr/module.yml* - This file defines module name and Cmake and Kconfig location +- *erpc/zephyr/CMakeList.txt* - Defines module's includes and source files base on Kconfig +- *erpc/zephyr/Kconfig* - Defines eRPC module configuration + +### Kconfig + +Kconfig options: + +- **CONFIG_ERPC** - enable eRPC support +- **CONFIG_ERPC_TRANSPORT_UART** - enable UART transport layer +- **CONFIG_ERPC_TRANSPORT_RPMSG_LITE** - enable RPMSG-Lite transport layer + - To use *RPMSG-Lite* transport layer, RPMSG-Lite module is required. + - RPMSG-Lite module has to be included in Zephyr + - Enable RPMSG-Lite module by this options: + - CONFIG_RPMSGLITE=y + - CONFIG_RPMSGLITE_QUEUE=y + - CONFIG_RPMSGLITE_NS=y +- **CONFIG_ERPC_ARBITRATED_CLIENT** - enable arbitrated client + +### CMakeList + +CMakeLists.txt defines eRPC as Zephyr library. Includes all required directories and source files for Zephyr environment. Optionaly import uart/rpmsg-lite/ns source files. + +## Samples + +Samples are located in *examples/zephyr/*. We can build the examples using west tool: + +### Matrix multiply with RPMSG-Lite transport + +```sh +cd path/to/zephyrproject +west build --sysbuild -b modules/lib/erpc/examples/zephyr/matrix_multiply_rpmsglite/ -p +west flash +``` + +### Matrix multiply with UART transport + +```sh +cd path/to/zephyrproject +west build -b modules/lib/erpc/examples/zephyr/matrix_multiply_uart/ -p +west flash +```