├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE.md ├── MAINTAINERS.md ├── README.md ├── apps ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── echo │ │ ├── CMakeLists.txt │ │ ├── rpmsg-echo.c │ │ ├── rpmsg-echo.h │ │ └── rpmsg-ping.c │ ├── load_fw │ │ ├── CMakeLists.txt │ │ ├── common.h │ │ ├── load_fw.c │ │ ├── lscript.ld │ │ ├── mem_image_store.c │ │ ├── platform_info.c │ │ ├── platform_info.h │ │ ├── zynqmp_apu_lcm_rproc_example.c │ │ ├── zynqmp_r5_lcm_rproc_example.c │ │ └── zynqmp_rpu_lcm_rproc_example.c │ ├── matrix_multiply │ │ ├── CMakeLists.txt │ │ ├── matrix_multiply.c │ │ ├── matrix_multiply.h │ │ └── matrix_multiplyd.c │ ├── rpc_demo │ │ ├── CMakeLists.txt │ │ ├── rpc_demo.c │ │ ├── rpc_demod.c │ │ └── rpmsg-rpc-demo.h │ └── rpmsg_sample_echo │ │ ├── CMakeLists.txt │ │ ├── rpmsg-sample-echo.c │ │ └── rpmsg-sample-ping.c ├── machine │ ├── CMakeLists.txt │ ├── zynq7 │ │ ├── CMakeLists.txt │ │ ├── platform_info.c │ │ ├── platform_info.h │ │ ├── platform_info_remoteproc_master.c │ │ ├── rsc_table.c │ │ ├── rsc_table.h │ │ └── zynq_a9_rproc.c │ ├── zynqmp │ │ ├── CMakeLists.txt │ │ ├── openamp-linux-userspace.dtsi │ │ ├── platform_info.c │ │ ├── platform_info.h │ │ └── zynqmp_linux_r5_proc.c │ └── zynqmp_r5 │ │ ├── CMakeLists.txt │ │ ├── platform_info.c │ │ ├── platform_info.h │ │ ├── rsc_table.c │ │ ├── rsc_table.h │ │ └── zynqmp_r5_a53_rproc.c ├── system │ ├── CMakeLists.txt │ ├── generic │ │ ├── CMakeLists.txt │ │ └── machine │ │ │ ├── CMakeLists.txt │ │ │ ├── zynq7 │ │ │ ├── CMakeLists.txt │ │ │ ├── Xilinx.spec │ │ │ ├── helper.c │ │ │ ├── linker_master.ld │ │ │ └── linker_remote.ld │ │ │ └── zynqmp_r5 │ │ │ ├── CMakeLists.txt │ │ │ ├── helper.c │ │ │ ├── linker_large_text.ld │ │ │ └── linker_remote.ld │ └── linux │ │ ├── CMakeLists.txt │ │ └── machine │ │ ├── CMakeLists.txt │ │ ├── generic │ │ ├── CMakeLists.txt │ │ ├── helper.c │ │ ├── platform_info.c │ │ ├── platform_info.h │ │ ├── rsc_table.c │ │ └── rsc_table.h │ │ └── zynqmp │ │ ├── CMakeLists.txt │ │ └── helper.c └── tests │ ├── CMakeLists.txt │ └── msg │ ├── CMakeLists.txt │ ├── rpmsg-flood-ping.c │ ├── rpmsg-ping.c │ ├── rpmsg-ping.h │ └── rpmsg-update.c ├── cmake ├── collect.cmake ├── depends.cmake ├── modules │ └── FindLibmetal.cmake ├── options.cmake ├── platforms │ ├── cross_generic_gcc.cmake │ ├── cross_linux_gcc.cmake │ ├── zynq7_generic.cmake │ ├── zynq7_linux.cmake │ ├── zynqmp_a53_generic.cmake │ ├── zynqmp_linux.cmake │ └── zynqmp_r5_generic.cmake └── syscheck.cmake ├── docs ├── apps │ ├── echo_test │ │ └── README.md │ ├── matrix_multiply │ │ └── README.md │ └── rpc_demo │ │ └── README.md ├── data-structure.md ├── img-src │ ├── coprocessor-rpmsg-ns-dynamic.gv │ ├── coprocessor-rpmsg-ns.gv │ ├── coprocessor-rpmsg-static-ep.gv │ ├── gen-graph.py │ └── rproc-lcm-state-machine.gv ├── img │ ├── coprocessor-rpmsg-ns-dynamic.png │ ├── coprocessor-rpmsg-ns.png │ ├── coprocessor-rpmsg-static-ep.png │ └── rproc-lcm-state-machine.png ├── openamp_ref.pdf ├── remoteproc-design.md └── rpmsg-design.md └── lib ├── CMakeLists.txt ├── include └── openamp │ ├── elf_loader.h │ ├── open_amp.h │ ├── remoteproc.h │ ├── remoteproc_loader.h │ ├── remoteproc_virtio.h │ ├── rpmsg.h │ ├── rpmsg_retarget.h │ ├── rpmsg_virtio.h │ ├── rsc_table_parser.h │ ├── virtio.h │ ├── virtio_ring.h │ └── virtqueue.h ├── proxy ├── CMakeLists.txt └── rpmsg_retarget.c ├── remoteproc ├── CMakeLists.txt ├── elf_loader.c ├── remoteproc.c ├── remoteproc_virtio.c └── rsc_table_parser.c ├── rpmsg ├── CMakeLists.txt ├── rpmsg.c ├── rpmsg_internal.h └── rpmsg_virtio.c └── virtio ├── CMakeLists.txt ├── virtio.c └── virtqueue.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *~ 3 | !libs/system/zc702evk/linux/lib/*/*.a 4 | *.bin 5 | *.map 6 | *.out 7 | *.log 8 | *.d 9 | 10 | /tags 11 | /TAGS 12 | 13 | # cscope files 14 | cscope.* 15 | ncscope.* 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: minimal # setting language to C will override cross-compiler and fail 2 | 3 | compiler: 4 | - gcc 5 | 6 | sudo: required 7 | dist: trusty 8 | 9 | env: 10 | global: 11 | - ZEPHYR_TOOLCHAIN_VARIANT=zephyr 12 | - ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk 13 | - ZEPHYR_BASE=$TRAVIS_BUILD_DIR/deps/zephyr 14 | - ZEPHYR_SDK_VERSION=0.9.3 15 | - ZEPHYR_SDK_DOWNLOAD_FOLDER=https://github.com/zephyrproject-rtos/meta-zephyr-sdk/releases/download/$ZEPHYR_SDK_VERSION 16 | - ZEPHYR_SDK_SETUP_BINARY=zephyr-sdk-$ZEPHYR_SDK_VERSION-setup.run 17 | - ZEPHYR_SDK_DOWNLOAD_URL=$ZEPHYR_SDK_DOWNLOAD_FOLDER/$ZEPHYR_SDK_SETUP_BINARY 18 | 19 | matrix: 20 | fast_finish: true 21 | include: 22 | - os: linux 23 | env: TARGET="linux" 24 | # - os: linux 25 | # env: TARGET="zephyr" 26 | 27 | cache: 28 | directories: 29 | - $ZEPHYR_SDK_INSTALL_DIR 30 | - /usr/local/bin 31 | 32 | before_install: 33 | - if [[ "$TARGET" == "linux" ]]; then 34 | sudo apt-get update -qq && 35 | sudo apt-get install libsysfs-dev libhugetlbfs-dev make gcc && 36 | sudo pip install pytest pexpect; 37 | fi 38 | - if [[ "$TARGET" == "zephyr" ]]; then 39 | sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test && 40 | sudo apt-get update -qq && 41 | sudo apt-get install libc6-dev-i386 make gperf gcc g++ python3-ply python3-yaml python3-pip device-tree-compiler ncurses-dev uglifyjs -qq && 42 | sudo pip3 install pyelftools; 43 | fi 44 | 45 | install: > 46 | if [[ "$TARGET" == "zephyr" && "$(cat $ZEPHYR_SDK_INSTALL_DIR/sdk_version)" != "$ZEPHYR_SDK_VERSION" ]]; then 47 | wget $ZEPHYR_SDK_DOWNLOAD_URL && 48 | chmod +x $ZEPHYR_SDK_SETUP_BINARY && 49 | rm -rf $ZEPHYR_SDK_INSTALL_DIR && 50 | ./$ZEPHYR_SDK_SETUP_BINARY --quiet -- -y -d $ZEPHYR_SDK_INSTALL_DIR > /dev/null; 51 | fi 52 | 53 | before_script: > 54 | if [[ "$TARGET" == "linux" ]]; then 55 | cd $TRAVIS_BUILD_DIR/.. && 56 | git clone --depth=1 git://github.com/OpenAMP/openamp-test-scripts.git && 57 | git clone --depth=1 git://github.com/OpenAMP/libmetal.git; 58 | fi; 59 | if [[ "$TARGET" == "zephyr" ]]; then 60 | git clone --depth=1 git://github.com/zephyrproject-rtos/zephyr.git && 61 | cd zephyr && 62 | source zephyr-env.sh; 63 | fi 64 | 65 | script: 66 | - if [[ "$TARGET" == "linux" ]]; then 67 | cd $TRAVIS_BUILD_DIR && 68 | mkdir -p build-linux && 69 | mkdir -p ../libmetal/build-linux && 70 | cd ../libmetal/build-linux && 71 | cmake .. && 72 | make VERBOSE=1 DESTDIR=$(pwd) install && 73 | cd ../../open-amp/build-linux && 74 | cmake .. -DCMAKE_LIBRARY_PATH=${TRAVIS_BUILD_DIR}/../libmetal/build-linux/usr/local/lib -DCMAKE_INCLUDE_PATH=${TRAVIS_BUILD_DIR}/../libmetal/build-linux/usr/local/include -DWITH_APPS=on && 75 | make VERBOSE=1 DESTDIR=$(pwd) install && 76 | LD_LIBRARY_PATH=../../libmetal/build-linux/usr/local/lib:usr/local/lib PATH=usr/local/bin:${PATH} PROMPT="travis@.*:" python -m pytest -s ../../openamp-test-scripts/test-rpmsg.py; 77 | fi 78 | - if [[ "$TARGET" == "zephyr" ]]; then 79 | mkdir -p ../open-amp/build-zephyr && 80 | mkdir -p ../libmetal/build-zephyr && 81 | cd ../libmetal/build-zephyr && 82 | cmake .. -DWITH_ZEPHYR=on -DBOARD=qemu_cortex_m3 && 83 | make && 84 | cd ../../open-amp/build-zephyr && 85 | cmake .. -DWITH_ZEPHYR=ON -DWITH_PROXY=OFF -DBOARD=qemu_cortex_m3 -DLIBMETAL_INCLUDE_DIR=../../libmetal/build-zephyr/lib/include -DLIBMETAL_LIB=../../libmetal/build-zephyr/lib/libmetal.a && 86 | make VERBOSE=1; 87 | fi 88 | 89 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | if (POLICY CMP0048) 3 | cmake_policy(SET CMP0048 NEW) 4 | endif() 5 | 6 | # The version number 7 | set (OPENAMP_VERSION_MAJOR 1) 8 | set (OPENAMP_VERSION_MINOR 0) 9 | 10 | list (APPEND CMAKE_MODULE_PATH 11 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake" 12 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" 13 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/platforms") 14 | 15 | include (syscheck) 16 | project (open_amp C) 17 | 18 | include (CheckIncludeFiles) 19 | include (CheckCSourceCompiles) 20 | include (collect) 21 | include (options) 22 | include (depends) 23 | enable_testing () 24 | 25 | set (OPENAMP_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 26 | set (OPENAMP_BIN_ROOT "${CMAKE_CURRENT_BINARY_DIR}") 27 | 28 | if (WITH_OBSOLETE) 29 | add_subdirectory (obsolete) 30 | endif (WITH_OBSOLETE) 31 | 32 | add_subdirectory (lib) 33 | 34 | if (WITH_APPS) 35 | add_subdirectory (apps) 36 | endif (WITH_APPS) 37 | 38 | # vim: expandtab:ts=2:sw=2:smartindent 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD 3-Clause License) 2 | ======================================== 3 | 4 | Copyright (c) 2014, Mentor Graphics Corporation. All rights reserved. 5 | Copyright (c) 2015 - 2016 Xilinx, Inc. All rights reserved. 6 | Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 14 | 2. Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | 3. Neither the name of nor the names of its contributors 19 | may be used to endorse or promote products derived from this software 20 | without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | 34 | BSD 2-Clause License 35 | ------------------------- 36 | 37 | Copyright (c) . All rights reserved. 38 | 39 | Redistribution and use in source and binary forms, with or without 40 | modification, are permitted provided that the following conditions are met: 41 | 42 | 1. Redistributions of source code must retain the above copyright notice, this 43 | list of conditions and the following disclaimer. 44 | 45 | 2. Redistributions in binary form must reproduce the above copyright notice, 46 | this list of conditions and the following disclaimer in the documentation 47 | and/or other materials provided with the distribution. 48 | 49 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 50 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 52 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 53 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 55 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 56 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 57 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 58 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 | 60 | Notes 61 | ========================================= 62 | Use the following tag instead of the full license text in the individual files: 63 | 64 | SPDX-License-Identifier: BSD-3-Clause 65 | SPDX-License-Identifier: BSD-2-Clause 66 | 67 | This enables machine processing of license information based on the SPDX 68 | License Identifiers that are here available: http://spdx.org/licenses/ 69 | 70 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # OpenAMP Maintainers 2 | 3 | OpenAMP project is maintained by the OpenAMP open source community. Everyone 4 | is encouraged to submit issues and changes to improve OpenAMP. 5 | 6 | The intention of this file is to provide a set of names that developers can 7 | consult when they have a question about OpenAMP and to provide a a set of 8 | names to be CC'd when submitting a patch. 9 | 10 | 11 | ## Project Administration 12 | Wendy Liang 13 | 14 | ### All patches CC here 15 | open-amp@googlegroups.com 16 | 17 | ## Machines 18 | ### Xilinx Platform - Zynq-7000 19 | Wendy Liang 20 | 21 | ### Xilinx Platform - Zynq UltraScale+ MPSoC 22 | Wendy Liang 23 | -------------------------------------------------------------------------------- /apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collector_create (APP_COMMON_SOURCES "") 2 | collector_create (APP_LIB_DIRS "") 3 | collector_create (APP_INC_DIRS "") 4 | collector_create (APP_LIB_DEPS "") 5 | 6 | collector_create (APP_EXTRA_C_FLAGS "") 7 | set (APPS_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 8 | 9 | set (APPS_SHARE_DIR "${CMAKE_CURRENT_BINARY_DIR}/share") 10 | 11 | add_subdirectory (machine) 12 | add_subdirectory (system) 13 | add_subdirectory (tests) 14 | add_subdirectory (examples) 15 | -------------------------------------------------------------------------------- /apps/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | option (WITH_LOAD_FW "Include loading firmware example" OFF) 3 | 4 | add_subdirectory (echo) 5 | add_subdirectory (rpmsg_sample_echo) 6 | add_subdirectory (matrix_multiply) 7 | if (WITH_LOAD_FW) 8 | add_subdirectory (load_fw) 9 | endif (WITH_LOAD_FW) 10 | if (WITH_PROXY_APPS) 11 | add_subdirectory (rpc_demo) 12 | endif (WITH_PROXY_APPS) 13 | -------------------------------------------------------------------------------- /apps/examples/echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS} -fdata-sections -ffunction-sections") 3 | set (_fw_dir "${APPS_SHARE_DIR}") 4 | 5 | collector_list (_list PROJECT_INC_DIRS) 6 | collector_list (_app_list APP_INC_DIRS) 7 | include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR}) 8 | 9 | collector_list (_list PROJECT_LIB_DIRS) 10 | collector_list (_app_list APP_LIB_DIRS) 11 | link_directories (${_list} ${_app_list}) 12 | 13 | get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT) 14 | collector_list (_deps PROJECT_LIB_DEPS) 15 | 16 | set (OPENAMP_LIB open_amp) 17 | 18 | foreach (_app rpmsg-echo-ping rpmsg-echo) 19 | collector_list (_sources APP_COMMON_SOURCES) 20 | if (${_app} STREQUAL "rpmsg-echo-ping") 21 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-ping.c") 22 | elseif (${_app} STREQUAL "rpmsg-echo") 23 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-echo.c") 24 | endif (${_app} STREQUAL "rpmsg-echo-ping") 25 | 26 | if (WITH_SHARED_LIB) 27 | add_executable (${_app}-shared ${_sources}) 28 | target_link_libraries (${_app}-shared ${OPENAMP_LIB}-shared ${_deps}) 29 | install (TARGETS ${_app}-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 30 | endif (WITH_SHARED_LIB) 31 | 32 | if (WITH_STATIC_LIB) 33 | if (${PROJECT_SYSTEM} STREQUAL "linux") 34 | add_executable (${_app}-static ${_sources}) 35 | target_link_libraries (${_app}-static ${OPENAMP_LIB}-static ${_deps}) 36 | install (TARGETS ${_app}-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 37 | else (${PROJECT_SYSTEM}) 38 | add_executable (${_app}.out ${_sources}) 39 | set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}") 40 | 41 | target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections ${_linker_opt} -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group) 42 | 43 | install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 44 | endif (${PROJECT_SYSTEM} STREQUAL "linux" ) 45 | endif (WITH_STATIC_LIB) 46 | endforeach(_app) 47 | -------------------------------------------------------------------------------- /apps/examples/echo/rpmsg-echo.c: -------------------------------------------------------------------------------- 1 | /* This is a sample demonstration application that showcases usage of rpmsg 2 | This application is meant to run on the remote CPU running baremetal code. 3 | This application echoes back data that was sent to it by the master core. */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "platform_info.h" 9 | #include "rpmsg-echo.h" 10 | 11 | #define SHUTDOWN_MSG 0xEF56A55A 12 | 13 | #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) 14 | //#define LPRINTF(format, ...) 15 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 16 | 17 | static struct rpmsg_endpoint lept; 18 | static int shutdown_req = 0; 19 | 20 | /*-----------------------------------------------------------------------------* 21 | * RPMSG endpoint callbacks 22 | *-----------------------------------------------------------------------------*/ 23 | static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, 24 | uint32_t src, void *priv) 25 | { 26 | (void)priv; 27 | (void)src; 28 | 29 | /* On reception of a shutdown we signal the application to terminate */ 30 | if ((*(unsigned int *)data) == SHUTDOWN_MSG) { 31 | LPRINTF("shutdown message is received.\r\n"); 32 | shutdown_req = 1; 33 | return RPMSG_SUCCESS; 34 | } 35 | 36 | /* Send data back to master */ 37 | if (rpmsg_send(ept, data, len) < 0) { 38 | LPERROR("rpmsg_send failed\r\n"); 39 | } 40 | return RPMSG_SUCCESS; 41 | } 42 | 43 | static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) 44 | { 45 | (void)ept; 46 | LPRINTF("unexpected Remote endpoint destroy\r\n"); 47 | shutdown_req = 1; 48 | } 49 | 50 | /*-----------------------------------------------------------------------------* 51 | * Application 52 | *-----------------------------------------------------------------------------*/ 53 | int app(struct rpmsg_device *rdev, void *priv) 54 | { 55 | int ret; 56 | 57 | /* Initialize RPMSG framework */ 58 | LPRINTF("Try to create rpmsg endpoint.\r\n"); 59 | 60 | ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, 61 | 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, 62 | rpmsg_service_unbind); 63 | if (ret) { 64 | LPERROR("Failed to create endpoint.\r\n"); 65 | return -1; 66 | } 67 | 68 | LPRINTF("Successfully created rpmsg endpoint.\r\n"); 69 | while(1) { 70 | platform_poll(priv); 71 | /* we got a shutdown request, exit */ 72 | if (shutdown_req) { 73 | break; 74 | } 75 | } 76 | rpmsg_destroy_ept(&lept); 77 | 78 | return 0; 79 | } 80 | 81 | /*-----------------------------------------------------------------------------* 82 | * Application entry point 83 | *-----------------------------------------------------------------------------*/ 84 | int main(int argc, char *argv[]) 85 | { 86 | void *platform; 87 | struct rpmsg_device *rpdev; 88 | int ret; 89 | 90 | LPRINTF("Starting application...\r\n"); 91 | 92 | /* Initialize platform */ 93 | ret = platform_init(argc, argv, &platform); 94 | if (ret) { 95 | LPERROR("Failed to initialize platform.\r\n"); 96 | ret = -1; 97 | } else { 98 | rpdev = platform_create_rpmsg_vdev(platform, 0, 99 | VIRTIO_DEV_SLAVE, 100 | NULL, NULL); 101 | if (!rpdev) { 102 | LPERROR("Failed to create rpmsg virtio device.\r\n"); 103 | ret = -1; 104 | } else { 105 | app(rpdev, platform); 106 | platform_release_rpmsg_vdev(rpdev); 107 | ret = 0; 108 | } 109 | } 110 | 111 | LPRINTF("Stopping application...\r\n"); 112 | platform_cleanup(platform); 113 | 114 | return ret; 115 | } 116 | -------------------------------------------------------------------------------- /apps/examples/echo/rpmsg-echo.h: -------------------------------------------------------------------------------- 1 | #ifndef RPMSG_ECHO_H 2 | #define RPMSG_ECHO_H 3 | 4 | #define RPMSG_SERVICE_NAME "rpmsg-openamp-demo-channel" 5 | 6 | #endif /* RPMSG_ECHO_H */ 7 | -------------------------------------------------------------------------------- /apps/examples/echo/rpmsg-ping.c: -------------------------------------------------------------------------------- 1 | /* This is a sample demonstration application that showcases usage of rpmsg 2 | This application is meant to run on the remote CPU running baremetal code. 3 | This application echoes back data that was sent to it by the master core. */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "platform_info.h" 12 | #include "rpmsg-echo.h" 13 | 14 | #define APP_EPT_ADDR 0 15 | #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) 16 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 17 | 18 | struct _payload { 19 | unsigned long num; 20 | unsigned long size; 21 | unsigned char data[]; 22 | }; 23 | 24 | static int err_cnt; 25 | 26 | #define PAYLOAD_MIN_SIZE 1 27 | 28 | /* Globals */ 29 | static struct rpmsg_endpoint lept; 30 | static struct _payload *i_payload; 31 | static int rnum = 0; 32 | static int err_cnt = 0; 33 | static int ept_deleted = 0; 34 | 35 | /*-----------------------------------------------------------------------------* 36 | * RPMSG endpoint callbacks 37 | *-----------------------------------------------------------------------------*/ 38 | static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, 39 | uint32_t src, void *priv) 40 | { 41 | int i; 42 | struct _payload *r_payload = (struct _payload *)data; 43 | 44 | (void)ept; 45 | (void)src; 46 | (void)priv; 47 | LPRINTF(" received payload number %lu of size %lu \r\n", 48 | r_payload->num, (unsigned long)len); 49 | 50 | if (r_payload->size == 0) { 51 | LPERROR(" Invalid size of package is received.\r\n"); 52 | err_cnt++; 53 | return RPMSG_SUCCESS; 54 | } 55 | /* Validate data buffer integrity. */ 56 | for (i = 0; i < (int)r_payload->size; i++) { 57 | if (r_payload->data[i] != 0xA5) { 58 | LPRINTF("Data corruption at index %d\r\n", i); 59 | err_cnt++; 60 | break; 61 | } 62 | } 63 | rnum = r_payload->num + 1; 64 | return RPMSG_SUCCESS; 65 | } 66 | 67 | static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) 68 | { 69 | (void)ept; 70 | rpmsg_destroy_ept(&lept); 71 | LPRINTF("echo test: service is destroyed\r\n"); 72 | ept_deleted = 1; 73 | } 74 | 75 | static void rpmsg_name_service_bind_cb(struct rpmsg_device *rdev, 76 | const char *name, uint32_t dest) 77 | { 78 | LPRINTF("new endpoint notification is received.\r\n"); 79 | if (strcmp(name, RPMSG_SERVICE_NAME)) 80 | LPERROR("Unexpected name service %s.\r\n", name); 81 | else 82 | (void)rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, 83 | APP_EPT_ADDR, dest, 84 | rpmsg_endpoint_cb, 85 | rpmsg_service_unbind); 86 | 87 | } 88 | 89 | /*-----------------------------------------------------------------------------* 90 | * Application 91 | *-----------------------------------------------------------------------------*/ 92 | int app (struct rpmsg_device *rdev, void *priv) 93 | { 94 | int ret; 95 | int i; 96 | int size, max_size, num_payloads; 97 | int expect_rnum = 0; 98 | 99 | LPRINTF(" 1 - Send data to remote core, retrieve the echo"); 100 | LPRINTF(" and validate its integrity ..\r\n"); 101 | 102 | max_size = rpmsg_virtio_get_buffer_size(rdev); 103 | if (max_size < 0) { 104 | LPERROR("No avaiable buffer size.\r\n"); 105 | return -1; 106 | } 107 | max_size -= sizeof(struct _payload); 108 | num_payloads = max_size - PAYLOAD_MIN_SIZE + 1; 109 | i_payload = 110 | (struct _payload *)metal_allocate_memory(2 * sizeof(unsigned long) + 111 | max_size); 112 | 113 | if (!i_payload) { 114 | LPERROR("memory allocation failed.\r\n"); 115 | return -1; 116 | } 117 | 118 | /* Create RPMsg endpoint */ 119 | ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, APP_EPT_ADDR, 120 | RPMSG_ADDR_ANY, 121 | rpmsg_endpoint_cb, rpmsg_service_unbind); 122 | 123 | if (ret) { 124 | LPERROR("Failed to create RPMsg endpoint.\r\n"); 125 | return ret; 126 | } 127 | 128 | while (!is_rpmsg_ept_ready(&lept)) 129 | platform_poll(priv); 130 | 131 | LPRINTF("RPMSG endpoint is binded with remote.\r\n"); 132 | for (i = 0, size = PAYLOAD_MIN_SIZE; i < num_payloads; i++, size++) { 133 | i_payload->num = i; 134 | i_payload->size = size; 135 | 136 | /* Mark the data buffer. */ 137 | memset(&(i_payload->data[0]), 0xA5, size); 138 | 139 | LPRINTF("sending payload number %lu of size %lu\r\n", 140 | i_payload->num, 141 | (unsigned long)(2 * sizeof(unsigned long)) + size); 142 | 143 | ret = rpmsg_send(&lept, i_payload, 144 | (2 * sizeof(unsigned long)) + size); 145 | 146 | if (ret < 0) { 147 | LPERROR("Failed to send data...\r\n"); 148 | break; 149 | } 150 | LPRINTF("echo test: sent : %lu\r\n", 151 | (unsigned long)(2 * sizeof(unsigned long)) + size); 152 | 153 | expect_rnum++; 154 | do { 155 | platform_poll(priv); 156 | } while ((rnum < expect_rnum) && !err_cnt && !ept_deleted); 157 | 158 | } 159 | 160 | LPRINTF("**********************************\r\n"); 161 | LPRINTF(" Test Results: Error count = %d \r\n", err_cnt); 162 | LPRINTF("**********************************\r\n"); 163 | /* Destroy the RPMsg endpoint */ 164 | rpmsg_destroy_ept(&lept); 165 | LPRINTF("Quitting application .. Echo test end\r\n"); 166 | 167 | metal_free_memory(i_payload); 168 | return 0; 169 | } 170 | 171 | int main(int argc, char *argv[]) 172 | { 173 | void *platform; 174 | struct rpmsg_device *rpdev; 175 | int ret; 176 | 177 | /* Initialize platform */ 178 | ret = platform_init(argc, argv, &platform); 179 | if (ret) { 180 | LPERROR("Failed to initialize platform.\r\n"); 181 | ret = -1; 182 | } else { 183 | rpdev = platform_create_rpmsg_vdev(platform, 0, 184 | VIRTIO_DEV_MASTER, 185 | NULL, 186 | rpmsg_name_service_bind_cb); 187 | if (!rpdev) { 188 | LPERROR("Failed to create rpmsg virtio device.\r\n"); 189 | ret = -1; 190 | } else { 191 | app(rpdev, platform); 192 | platform_release_rpmsg_vdev(rpdev); 193 | ret = 0; 194 | } 195 | } 196 | 197 | LPRINTF("Stopping application...\r\n"); 198 | platform_cleanup(platform); 199 | 200 | return ret; 201 | } 202 | 203 | -------------------------------------------------------------------------------- /apps/examples/load_fw/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collector_list (_app_extra_c_flags APP_EXTRA_C_FLAGS) 2 | set (_cflags "${CMAKE_C_FLAGS} ${_app_extra_c_flags}") 3 | set (_fw_dir "${APPS_SHARE_DIR}") 4 | 5 | collector_list (_list PROJECT_INC_DIRS) 6 | collector_list (_app_list APP_INC_DIRS) 7 | include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR}) 8 | 9 | collector_list (_list PROJECT_LIB_DIRS) 10 | collector_list (_app_list APP_LIB_DIRS) 11 | link_directories (${_list} ${_app_list}) 12 | 13 | get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT) 14 | collector_list (_deps PROJECT_LIB_DEPS) 15 | 16 | set (OPENAMP_LIB open_amp) 17 | # set default value to LOAD_FW_TARGET if not provided. 18 | if(NOT LOAD_FW_TARGET) 19 | if(VERSION_2_PM_CLIENT) 20 | set(LOAD_FW_TARGET "XPM_NODEIDX_DEV_ACPU_0") 21 | elseif(VERSION_1_PM_CLIENT) 22 | set(LOAD_FW_TARGET "NODE_APU_1") 23 | endif(VERSION_2_PM_CLIENT) 24 | endif(NOT LOAD_FW_TARGET) 25 | add_definitions( -DLOAD_FW_TARGET=${LOAD_FW_TARGET} ) 26 | 27 | foreach (_app load_fw) 28 | collector_list (_sources APP_COMMON_SOURCES) 29 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c") 30 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/mem_image_store.c") 31 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/zynqmp_apu_lcm_rproc_example.c") 32 | if(VERSION_1_PM_CLIENT) 33 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/zynqmp_rpu_lcm_rproc_example.c") 34 | endif(VERSION_1_PM_CLIENT) 35 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/platform_info.c") 36 | 37 | if (WITH_STATIC_LIB) 38 | add_executable (${_app}.out ${_sources}) 39 | set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}") 40 | 41 | target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections -T"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld" -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group) 42 | 43 | install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 44 | endif (WITH_STATIC_LIB) 45 | endforeach(_app) 46 | -------------------------------------------------------------------------------- /apps/examples/load_fw/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019 Xilinx Ltd. 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | #ifndef COMMON_H_ 9 | #define COMMON_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | /* Xilinx headers */ 20 | #ifdef VERSION_2_PM_CLIENT 21 | #include 22 | #include 23 | #define NODEID_DDR0 NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_MEM, XPM_NODETYPE_DEV_DDR, XPM_NODEIDX_DEV_DDR_0) 24 | #define NODEID_DDR1 NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_MEM, XPM_NODETYPE_DEV_DDR, XPM_NODEIDX_DEV_DDR_1) 25 | #define APU_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, \ 26 | XPM_NODESUBCL_DEV_CORE, \ 27 | XPM_NODETYPE_DEV_CORE_APU, (IDX)) 28 | #define APU_NODE_0 XPM_NODEIDX_DEV_ACPU_0 29 | #define APU_NODE_1 XPM_NODEIDX_DEV_ACPU_1 30 | #define APU_POWER_CYCLE_NODE_ID(IDX) APU_DEVID(IDX) 31 | #elif VERSION_1_PM_CLIENT 32 | #include 33 | #include 34 | #define APU_NODE_0 NODE_APU_0 35 | #define APU_NODE_1 NODE_APU_3 36 | #define APU_POWER_CYCLE_NODE_ID(IDX) (IDX) 37 | #endif /* VERSION_2_PM_CLIENT */ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #define LPRINTF(format, ...) xil_printf(format, ##__VA_ARGS__) 44 | //#define LPRINTF(format, ...) 45 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 46 | 47 | struct rproc_priv { 48 | struct remoteproc *rproc; 49 | int cpu_id; 50 | }; 51 | 52 | #endif /* COMMON_H_ */ 53 | -------------------------------------------------------------------------------- /apps/examples/load_fw/load_fw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Load firmware example 3 | * 4 | * Copyright(c) 2018 Xilinx Ltd. 5 | * All rights reserved. 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | extern struct image_store_ops mem_image_store_ops; 14 | 15 | struct mem_file { 16 | const void *base; 17 | }; 18 | 19 | static struct mem_file image = { 20 | .base = (void *)0x3ED00000, 21 | }; 22 | 23 | int load_exectuable_block(struct remoteproc *rproc, 24 | struct image_store_ops *store_ops, void *store, 25 | const char *img_path) 26 | { 27 | int ret; 28 | 29 | (void)img_path; 30 | if (rproc == NULL) 31 | return -EINVAL; 32 | /* Configure remoteproc to get ready to load executable */ 33 | remoteproc_config(rproc, NULL); 34 | 35 | /* Load remoteproc executable */ 36 | LPRINTF("Start to load executable with remoteproc_load() \r\n"); 37 | ret = remoteproc_load(rproc, NULL, store, store_ops, NULL); 38 | if (ret) { 39 | LPRINTF("failed to load firmware\r\n"); 40 | return ret; 41 | } 42 | /* Start the processor */ 43 | ret = remoteproc_start(rproc); 44 | if (ret) { 45 | LPRINTF("failed to start processor\r\n"); 46 | return ret; 47 | } 48 | LPRINTF("successfully started the processor\r\n"); 49 | /* ... */ 50 | asm volatile("wfi"); 51 | LPRINTF("going to stop the processor\r\n"); 52 | remoteproc_stop(rproc); 53 | /* application may want to do some cleanup before shutdown */ 54 | LPRINTF("going to shutdown the processor\r\n"); 55 | remoteproc_shutdown(rproc); 56 | return 0; 57 | } 58 | 59 | int load_exectuable_noblock(struct remoteproc *rproc, 60 | struct image_store_ops *store_ops, void *store, 61 | const char *img_path) 62 | { 63 | int ret; 64 | const void *img_data; 65 | void *img_info = NULL; 66 | metal_phys_addr_t pa; 67 | struct metal_io_region *io; 68 | size_t offset, noffset; 69 | size_t len, nlen, nmlen; 70 | unsigned char padding; 71 | 72 | if (rproc == NULL) 73 | return -EINVAL; 74 | /* Configure remoteproc to get ready to load executable */ 75 | remoteproc_config(rproc, NULL); 76 | /* Load remoteproc executable */ 77 | LPRINTF("Start to load executable with remoteproc_load() \r\n"); 78 | ret = store_ops->open(store, img_path, &img_data); 79 | if (ret <= 0) 80 | return -EINVAL; 81 | offset = 0; 82 | len = (size_t)ret; 83 | do { 84 | nlen = 0; 85 | pa = METAL_BAD_PHYS; 86 | io = NULL; 87 | nmlen = 0; 88 | LPRINTF("%s, loading 0x%lx,0x%lx\r\n", 89 | __func__, offset, len); 90 | ret = remoteproc_load_noblock(rproc, img_data, offset, len, 91 | &img_info, &pa, &io, &noffset, 92 | &nlen, &nmlen, &padding); 93 | if (ret) { 94 | LPERROR("failed to load executable, 0x%lx,0x%lx\r\n", 95 | offset, len); 96 | return ret; 97 | } 98 | if (nlen == 0) 99 | break; 100 | offset = noffset; 101 | len = nlen; 102 | ret = store_ops->load(store, noffset, nlen, &img_data, pa, 103 | io, 1); 104 | if (ret != (int)nlen) { 105 | LPERROR("failed to load data to memory, 0x%lx,0x%lx\r\n", 106 | noffset, nlen); 107 | return ret; 108 | } 109 | if (nmlen > nlen && io != NULL) { 110 | /* pad the rest of the memory with 0 */ 111 | size_t tmpoffset; 112 | 113 | tmpoffset = metal_io_phys_to_offset(io, pa + nlen); 114 | metal_io_block_set(io, tmpoffset, padding, 115 | (nmlen - nlen)); 116 | 117 | } 118 | } while(1); 119 | 120 | /* Start the processor */ 121 | ret = remoteproc_start(rproc); 122 | if (ret) { 123 | LPRINTF("failed to start processor\r\n"); 124 | return ret; 125 | } 126 | LPRINTF("successfully started the processor\r\n"); 127 | /* ... */ 128 | asm volatile("wfi"); 129 | LPRINTF("going to stop the processor\r\n"); 130 | remoteproc_stop(rproc); 131 | /* application may want to do some cleanup before shutdown */ 132 | LPRINTF("going to shutdown the processor\r\n"); 133 | remoteproc_shutdown(rproc); 134 | return 0; 135 | } 136 | 137 | 138 | int main(void) 139 | { 140 | struct remoteproc *rproc = NULL; 141 | void *store = ℑ 142 | unsigned int cpu_id = LOAD_FW_TARGET; 143 | int ret; 144 | 145 | LPRINTF("Loading Exectuable Demo\n"); 146 | rproc = app_init(cpu_id); 147 | if (!rproc) { 148 | LPERROR("app_init failed\r\n"); 149 | return -1; 150 | } 151 | ret = load_exectuable_block(rproc, &mem_image_store_ops, store, NULL); 152 | if (ret < 0) { 153 | LPERROR("load_exectuable_block failed\r\n"); 154 | /* Make sure the remote is shut down */ 155 | remoteproc_shutdown(rproc); 156 | return -1; 157 | } 158 | 159 | ret = load_exectuable_noblock(rproc, &mem_image_store_ops, store, 160 | NULL); 161 | if (ret < 0) { 162 | LPERROR("load_exectuable_noblock failed\r\n"); 163 | /* Make sure the remote is shut down */ 164 | remoteproc_shutdown(rproc); 165 | return -1; 166 | } 167 | remoteproc_remove(rproc); 168 | return ret; 169 | } 170 | -------------------------------------------------------------------------------- /apps/examples/load_fw/mem_image_store.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory based image store Operation 3 | * 4 | * Copyright(c) 2018 Xilinx Ltd. 5 | * All rights reserved. 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | #include 11 | 12 | struct mem_file { 13 | const void *base; 14 | }; 15 | 16 | int mem_image_open(void *store, const char *path, const void **image_data) 17 | { 18 | struct mem_file *image = store; 19 | const void *fw_base = image->base; 20 | 21 | (void)(path); 22 | if (image_data == NULL) { 23 | LPERROR("%s: input image_data is NULL\r\n", __func__); 24 | return -EINVAL; 25 | } 26 | *image_data = fw_base; 27 | /* return an abitrary length, as the whole firmware is in memory */ 28 | return 0x100; 29 | } 30 | 31 | void mem_image_close(void *store) 32 | { 33 | /* The image is in memory, does nothing */ 34 | (void)store; 35 | } 36 | 37 | int mem_image_load(void *store, size_t offset, size_t size, 38 | const void **data, metal_phys_addr_t pa, 39 | struct metal_io_region *io, 40 | char is_blocking) 41 | { 42 | struct mem_file *image = store; 43 | const void *fw_base = image->base; 44 | 45 | (void)is_blocking; 46 | 47 | LPRINTF("%s: offset=0x%x, size=0x%x\n\r", 48 | __func__, offset, size); 49 | if (pa == METAL_BAD_PHYS) { 50 | if (data == NULL) { 51 | LPERROR("%s: data is NULL while pa is ANY\r\n", 52 | __func__); 53 | return -EINVAL; 54 | } 55 | *data = (const void *)((const char *)fw_base + offset); 56 | } else { 57 | void *va; 58 | 59 | if (io == NULL) { 60 | LPERROR("%s, io is NULL while pa is not ANY\r\n", 61 | __func__); 62 | return -EINVAL; 63 | } 64 | va = metal_io_phys_to_virt(io, pa); 65 | if (va == NULL) { 66 | LPERROR("%s: no va is found\r\n", __func__); 67 | return -EINVAL; 68 | } 69 | memcpy(va, (const void *)((const char *)fw_base + offset), size); 70 | } 71 | 72 | return (int)size; 73 | } 74 | 75 | struct image_store_ops mem_image_store_ops = { 76 | .open = mem_image_open, 77 | .close = mem_image_close, 78 | .load = mem_image_load, 79 | .features = SUPPORT_SEEK, 80 | }; 81 | 82 | -------------------------------------------------------------------------------- /apps/examples/load_fw/platform_info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019 Xilinx Ltd. 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #ifdef VERSION_2_PM_CLIENT 12 | #include 13 | #include 14 | #elif VERSION_1_PM_CLIENT 15 | #include 16 | #endif /* VERSION_2_PM_CLIENT */ 17 | #if !defined(VERSION_1_PM_CLIENT) && !defined(VERSION_2_PM_CLIENT) 18 | #error ("missing PM version.") 19 | #endif 20 | 21 | extern struct remoteproc_ops zynqmp_apu_rproc_ops; 22 | extern struct remoteproc_ops zynqmp_rpu_rproc_ops; 23 | 24 | static struct remoteproc rproc_inst; 25 | static struct remoteproc_ops ops; 26 | 27 | static struct remoteproc * platform_create_proc(unsigned int cpu_id){ 28 | struct remoteproc * rproc; 29 | #ifdef VERSION_2_PM_CLIENT 30 | if (XPM_NODEIDX_DEV_ACPU_0 <= LOAD_FW_TARGET && LOAD_FW_TARGET <= XPM_NODEIDX_DEV_ACPU_1) 31 | ops = zynqmp_apu_rproc_ops; 32 | #elif VERSION_1_PM_CLIENT 33 | if (NODE_RPU_0 <= LOAD_FW_TARGET && LOAD_FW_TARGET <= NODE_RPU_1) 34 | ops = zynqmp_rpu_rproc_ops; 35 | else if (NODE_APU_0 <= LOAD_FW_TARGET && LOAD_FW_TARGET <= NODE_APU_3) 36 | ops = zynqmp_apu_rproc_ops; 37 | #endif /* VERSION_2_PM_CLIENT */ 38 | 39 | else 40 | return NULL; 41 | 42 | rproc = remoteproc_init(&rproc_inst, &ops, &cpu_id); 43 | if (!rproc) 44 | return NULL; 45 | return &rproc_inst; 46 | } 47 | 48 | 49 | static void app_log_handler(enum metal_log_level level, 50 | const char *format, ...) 51 | { 52 | char msg[1024]; 53 | va_list args; 54 | static const char *level_strs[] = { 55 | "metal: emergency: ", 56 | "metal: alert: ", 57 | "metal: critical: ", 58 | "metal: error: ", 59 | "metal: warning: ", 60 | "metal: notice: ", 61 | "metal: info: ", 62 | "metal: debug: ", 63 | }; 64 | 65 | va_start(args, format); 66 | vsnprintf(msg, sizeof(msg), format, args); 67 | va_end(args); 68 | 69 | if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG) 70 | level = METAL_LOG_EMERGENCY; 71 | 72 | xil_printf("%s%s", level_strs[level], msg); 73 | } 74 | 75 | static XIpiPsu IpiInst; 76 | 77 | static XStatus IpiConfigure(XIpiPsu *const IpiInstPtr) 78 | { 79 | XStatus Status; 80 | XIpiPsu_Config *IpiCfgPtr; 81 | 82 | /* Look Up the config data */ 83 | IpiCfgPtr = XIpiPsu_LookupConfig(XPAR_XIPIPSU_0_DEVICE_ID); 84 | if (NULL == IpiCfgPtr) { 85 | Status = XST_FAILURE; 86 | LPERROR("%s ERROR in getting CfgPtr\n", __func__); 87 | return Status; 88 | } 89 | 90 | /* Init with the Cfg Data */ 91 | Status = XIpiPsu_CfgInitialize(IpiInstPtr, IpiCfgPtr, 92 | IpiCfgPtr->BaseAddress); 93 | if (XST_SUCCESS != Status) { 94 | LPERROR("%s ERROR #%d in configuring IPI\n", __func__, Status); 95 | return Status; 96 | } 97 | return Status; 98 | } 99 | 100 | 101 | struct remoteproc * app_init(unsigned int cpu_id){ 102 | struct metal_init_params metal_param = { 103 | .log_handler = app_log_handler, 104 | .log_level = METAL_LOG_DEBUG, 105 | }; 106 | metal_init(&metal_param); 107 | 108 | if (XST_SUCCESS != IpiConfigure(&IpiInst)) { 109 | LPERROR("Failed to config IPI instance\r\n"); 110 | return NULL; 111 | } 112 | 113 | if (XST_SUCCESS != XPm_InitXilpm(&IpiInst)) { 114 | LPERROR("Failed to initialize PM\r\n"); 115 | return NULL; 116 | } 117 | 118 | 119 | return platform_create_proc(cpu_id); 120 | } 121 | -------------------------------------------------------------------------------- /apps/examples/load_fw/platform_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2019 Xilinx Ltd. 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | #ifndef PLATFORM_INFO_H_ 8 | #define PLATFORM_INFO_H_ 9 | 10 | struct remoteproc * app_init(unsigned int cpu_id); 11 | #endif /* PLATFORM_INFO_H_ */ 12 | -------------------------------------------------------------------------------- /apps/examples/load_fw/zynqmp_apu_lcm_rproc_example.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ZynqMP APU life cycle management remoteproc example implementation 3 | * 4 | * Copyright(c) 2019 Xilinx Ltd. 5 | * All rights reserved. 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | #include 11 | 12 | 13 | static struct remoteproc *apu_rproc_init(struct remoteproc *rproc, 14 | struct remoteproc_ops *ops, void *arg) 15 | { 16 | struct rproc_priv *priv; 17 | unsigned int cpu_id = *((unsigned int *)arg); 18 | if(cpu_id < APU_NODE_0 || cpu_id > APU_NODE_1){ 19 | xil_printf("%s: invalide node id: %d \n\r",__func__, cpu_id); 20 | return NULL; 21 | } 22 | 23 | xil_printf("%s: node id: %d\n\r", __func__, cpu_id); 24 | priv = metal_allocate_memory(sizeof(*priv)); 25 | if (!priv) 26 | return NULL; 27 | memset(priv, 0, sizeof(*priv)); 28 | priv->rproc = rproc; 29 | priv->cpu_id = cpu_id; 30 | priv->rproc->ops = ops; 31 | metal_list_init(&priv->rproc->mems); 32 | priv->rproc->priv = priv; 33 | rproc->state = RPROC_READY; 34 | return priv->rproc; 35 | } 36 | 37 | static void apu_rproc_remove(struct remoteproc *rproc) 38 | { 39 | if (rproc) { 40 | struct rproc_priv *priv; 41 | 42 | priv = (struct rproc_priv *)rproc->priv; 43 | metal_free_memory(priv); 44 | } 45 | } 46 | 47 | static void *apu_rproc_mmap(struct remoteproc *rproc, 48 | metal_phys_addr_t *pa, metal_phys_addr_t *da, 49 | size_t size, unsigned int attribute, 50 | struct metal_io_region **io) 51 | { 52 | struct remoteproc_mem *mem; 53 | metal_phys_addr_t lpa, lda; 54 | 55 | if (!da || !pa) 56 | return NULL; 57 | 58 | LPRINTF("%s: pa=0x%x, da=0x%x, size=0x%x, atrribute=0x%x\n\r", 59 | __func__, *pa, *da, size, attribute); 60 | lda = *da; 61 | lpa = *pa; 62 | if (!attribute) 63 | attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW; 64 | 65 | metal_phys_addr_t lda_end; 66 | 67 | lda_end = lda + size; 68 | if (lda_end <= 0x7FFFFFFF){ 69 | #ifdef VERSION_2_PM_CLIENT 70 | XPm_RequestNode(NODEID_DDR0, XPM_DEF_CAPABILITY, XPM_DEF_QOS, 0); 71 | XPm_RequestNode(NODEID_DDR1, XPM_DEF_CAPABILITY, XPM_DEF_QOS, 0); 72 | } 73 | #elif VERSION_1_PM_CLIENT 74 | XPm_RequestNode( NODE_DDR, 75 | PM_CAP_ACCESS, 0, 76 | REQUEST_ACK_BLOCKING); 77 | } 78 | if (lda >= 0xFFFC0000 && lda < 0xFFFD0000) 79 | XPm_RequestNode(NODE_OCM_BANK_0, 80 | PM_CAP_ACCESS, 0, 81 | REQUEST_ACK_BLOCKING); 82 | if (lda <= 0xFFFDFFFF && lda_end >= 0xFFFD0000) 83 | XPm_RequestNode(NODE_OCM_BANK_1, 84 | PM_CAP_ACCESS, 0, 85 | REQUEST_ACK_BLOCKING); 86 | if (lda <= 0xFFFEFFFF && lda_end >= 0xFFFE0000) 87 | XPm_RequestNode(NODE_OCM_BANK_2, 88 | PM_CAP_ACCESS, 0, 89 | REQUEST_ACK_BLOCKING); 90 | if (lda_end >= 0xFFFF0000) 91 | XPm_RequestNode(NODE_OCM_BANK_3, 92 | PM_CAP_ACCESS, 0, 93 | REQUEST_ACK_BLOCKING); 94 | #endif /* VERSION_2_PM_CLIENT */ 95 | 96 | if (lpa == METAL_BAD_PHYS) 97 | lpa = lda; 98 | if (lpa == METAL_BAD_PHYS) 99 | return NULL; 100 | mem = metal_allocate_memory(sizeof(*mem)); 101 | if (!mem) 102 | return NULL; 103 | mem->pa = lpa; 104 | mem->da = lda; 105 | 106 | *io = metal_allocate_memory(sizeof(struct metal_io_region)); 107 | if (!*io) { 108 | metal_free_memory(mem); 109 | return NULL; 110 | } 111 | metal_io_init(*io, (void *)mem->pa, &mem->pa, size, 112 | sizeof(metal_phys_addr_t)<<3, attribute, NULL); 113 | mem->io = *io; 114 | metal_list_add_tail(&rproc->mems, &mem->node); 115 | *pa = lpa; 116 | *da = lda; 117 | mem->size = size; 118 | return metal_io_phys_to_virt(*io, mem->pa); 119 | } 120 | 121 | static int apu_rproc_start(struct remoteproc *rproc) 122 | { 123 | struct rproc_priv *priv; 124 | int ret; 125 | 126 | priv = rproc->priv; 127 | ret = XPm_RequestWakeUp(APU_POWER_CYCLE_NODE_ID(priv->cpu_id), 1, 128 | rproc->bootaddr, 1); 129 | if (ret != XST_SUCCESS) { 130 | LPRINTF("%s: Failed to start APU 0x%x, ret=0x%x\n\r", 131 | __func__, priv->cpu_id, ret); 132 | return -1; 133 | } else { 134 | return 0; 135 | } 136 | } 137 | 138 | static int apu_rproc_stop(struct remoteproc *rproc) 139 | { 140 | /* It is lacking a stop operation in the libPM */ 141 | (void)rproc; 142 | return 0; 143 | } 144 | 145 | static int apu_rproc_shutdown(struct remoteproc *rproc) 146 | { 147 | struct rproc_priv *priv; 148 | int ret; 149 | struct remoteproc_mem *mem; 150 | struct metal_list *node; 151 | 152 | priv = rproc->priv; 153 | /* Delete all the registered remoteproc memories */ 154 | metal_list_for_each(&rproc->mems, node) { 155 | struct metal_list *tmpnode; 156 | metal_phys_addr_t pa, pa_end; 157 | mem = metal_container_of(node, struct remoteproc_mem, node); 158 | tmpnode = node; 159 | /* Release TCM resource */ 160 | pa = mem->pa; 161 | pa_end = metal_io_phys(mem->io, metal_io_region_size(mem->io)); 162 | if (pa_end <= 0x7FFFFFFF){ 163 | #ifdef VERSION_2_PM_CLIENT 164 | XPm_ReleaseNode(NODEID_DDR0); 165 | XPm_ReleaseNode(NODEID_DDR1); 166 | } 167 | #else 168 | XPm_ReleaseNode(NODE_DDR); 169 | } 170 | if (pa >= 0xFFFC0000 && pa < 0xFFFD0000) 171 | XPm_ReleaseNode(NODE_OCM_BANK_0); 172 | if (pa <= 0xFFFDFFFF && pa_end >= 0xFFFD0000) 173 | XPm_ReleaseNode(NODE_OCM_BANK_1); 174 | if (pa <= 0xFFFEFFFF && pa_end >= 0xFFFE0000) 175 | XPm_ReleaseNode(NODE_OCM_BANK_2); 176 | if (pa_end >= 0xFFFF0000) 177 | XPm_ReleaseNode(NODE_OCM_BANK_3); 178 | #endif /* VERSION_2_PM_CLIENT */ 179 | 180 | node = tmpnode->prev; 181 | metal_list_del(tmpnode); 182 | metal_free_memory(mem->io); 183 | metal_free_memory(mem); 184 | } 185 | ret = XPm_ForcePowerDown(APU_POWER_CYCLE_NODE_ID(priv->cpu_id), 0); 186 | if (ret != XST_SUCCESS) 187 | return -1; 188 | else 189 | return 0; 190 | } 191 | 192 | struct remoteproc_ops zynqmp_apu_rproc_ops = { 193 | .init = apu_rproc_init, 194 | .remove = apu_rproc_remove, 195 | .start = apu_rproc_start, 196 | .stop = apu_rproc_stop, 197 | .shutdown = apu_rproc_shutdown, 198 | .mmap = apu_rproc_mmap, 199 | }; 200 | -------------------------------------------------------------------------------- /apps/examples/load_fw/zynqmp_rpu_lcm_rproc_example.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ZynqMP RPU life cycle management remoteproc example implementation 3 | * 4 | * Copyright(c) 2019 Xilinx Ltd. 5 | * All rights reserved. 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | #include 10 | 11 | 12 | static struct remoteproc *rpu_rproc_init(struct remoteproc *rproc, 13 | struct remoteproc_ops *ops, void *arg) 14 | { 15 | struct rproc_priv *priv; 16 | unsigned int cpu_id = *((unsigned int *)arg); 17 | 18 | if (cpu_id < NODE_RPU_0 || cpu_id > NODE_RPU_1) { 19 | xil_printf("%s: invalide node id: %d\n\r", __func__, cpu_id); 20 | return NULL; 21 | } 22 | 23 | xil_printf("%s: node id: %d\n\r", __func__, cpu_id); 24 | priv = metal_allocate_memory(sizeof(*priv)); 25 | if (!priv) 26 | return NULL; 27 | memset(priv, 0, sizeof(*priv)); 28 | priv->rproc = rproc; 29 | priv->cpu_id = cpu_id; 30 | priv->rproc->ops = ops; 31 | metal_list_init(&priv->rproc->mems); 32 | priv->rproc->priv = priv; 33 | rproc->state = RPROC_READY; 34 | return priv->rproc; 35 | } 36 | 37 | static void rpu_rproc_remove(struct remoteproc *rproc) 38 | { 39 | if (rproc) { 40 | struct rproc_priv *priv; 41 | 42 | priv = (struct rproc_priv *)rproc->priv; 43 | metal_free_memory(priv); 44 | } 45 | } 46 | 47 | static void *rpu_rproc_mmap(struct remoteproc *rproc, 48 | metal_phys_addr_t *pa, metal_phys_addr_t *da, 49 | size_t size, unsigned int attribute, 50 | struct metal_io_region **io) 51 | { 52 | struct remoteproc_mem *mem; 53 | struct rproc_priv *priv; 54 | metal_phys_addr_t lpa, lda; 55 | 56 | priv = rproc->priv; 57 | 58 | if (!da || !pa) 59 | return NULL; 60 | LPRINTF("%s: pa=0x%x, da=0x%x, size=0x%x, atrribute=0x%x\n\r", 61 | __func__, *pa, *da, size, attribute); 62 | lda = *da; 63 | lpa = *pa; 64 | if (!attribute) 65 | attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW; 66 | metal_phys_addr_t lda_end; 67 | 68 | lda_end = lda + size; 69 | if (priv->cpu_id == NODE_RPU_0) { 70 | if (lda < 0x10000) 71 | XPm_RequestNode(NODE_TCM_0_A, 72 | PM_CAP_ACCESS, 0, 73 | REQUEST_ACK_BLOCKING); 74 | if (lda <= 0x20000 && lda_end >= 0x10000) 75 | XPm_RequestNode(NODE_TCM_1_A, 76 | PM_CAP_ACCESS, 0, 77 | REQUEST_ACK_BLOCKING); 78 | if (lda <= 0x30000 && lda_end >= 0x20000) 79 | XPm_RequestNode(NODE_TCM_0_B, 80 | PM_CAP_ACCESS, 0, 81 | REQUEST_ACK_BLOCKING); 82 | if (lda <= 0x40000 && lda_end >= 0x30000) 83 | XPm_RequestNode(NODE_TCM_1_B, 84 | PM_CAP_ACCESS, 0, 85 | REQUEST_ACK_BLOCKING); 86 | } else if (priv->cpu_id == NODE_RPU_1) { 87 | lpa = 0xFFE90000 + lda; 88 | if (lda < 0x10000) 89 | XPm_RequestNode(NODE_TCM_1_A, 90 | PM_CAP_ACCESS, 0, 91 | REQUEST_ACK_BLOCKING); 92 | if (lda <= 0x30000 && lda_end >= 0x20000) 93 | XPm_RequestNode(NODE_TCM_1_B, 94 | PM_CAP_ACCESS, 0, 95 | REQUEST_ACK_BLOCKING); 96 | } else { 97 | LPERROR("mmap failed: invalid cpu node: %d\n", 98 | priv->cpu_id); 99 | return NULL; 100 | } 101 | if (lpa == METAL_BAD_PHYS) 102 | lpa = lda; 103 | if (lpa == METAL_BAD_PHYS) 104 | return NULL; 105 | mem = metal_allocate_memory(sizeof(*mem)); 106 | if (!mem) 107 | return NULL; 108 | mem->pa = lpa; 109 | mem->da = lda; 110 | 111 | *io = metal_allocate_memory(sizeof(struct metal_io_region)); 112 | if (!*io) { 113 | metal_free_memory(mem); 114 | return NULL; 115 | } 116 | metal_io_init(*io, (void *)mem->pa, &mem->pa, size, 117 | sizeof(metal_phys_addr_t)<<3, attribute, NULL); 118 | mem->io = *io; 119 | metal_list_add_tail(&rproc->mems, &mem->node); 120 | *pa = lpa; 121 | *da = lda; 122 | mem->size = size; 123 | return metal_io_phys_to_virt(*io, mem->pa); 124 | } 125 | 126 | static int rpu_rproc_start(struct remoteproc *rproc) 127 | { 128 | struct rproc_priv *priv; 129 | int ret; 130 | 131 | priv = rproc->priv; 132 | ret = XPm_RequestWakeUp(priv->cpu_id, true, rproc->bootaddr, 133 | REQUEST_ACK_BLOCKING); 134 | if (ret != XST_SUCCESS) { 135 | LPRINTF("%s: Failed to start RPU 0x%x, ret=0x%x\n\r", 136 | __func__, priv->cpu_id, ret); 137 | return -1; 138 | } else { 139 | return 0; 140 | } 141 | } 142 | 143 | static int rpu_rproc_stop(struct remoteproc *rproc) 144 | { 145 | /* It is lacking a stop operation in the libPM */ 146 | (void)rproc; 147 | return 0; 148 | } 149 | 150 | static int rpu_rproc_shutdown(struct remoteproc *rproc) 151 | { 152 | struct rproc_priv *priv; 153 | int ret; 154 | struct remoteproc_mem *mem; 155 | struct metal_list *node; 156 | 157 | priv = rproc->priv; 158 | /* Delete all the registered remoteproc memories */ 159 | metal_list_for_each(&rproc->mems, node) { 160 | struct metal_list *tmpnode; 161 | metal_phys_addr_t pa, pa_end; 162 | 163 | mem = metal_container_of(node, struct remoteproc_mem, node); 164 | tmpnode = node; 165 | /* Release TCM resource */ 166 | pa = mem->pa; 167 | pa_end = metal_io_phys(mem->io, metal_io_region_size(mem->io)); 168 | if (pa >= 0XFFE00000 && pa < 0xFFE10000) 169 | XPm_ReleaseNode(NODE_TCM_0_A); 170 | if (pa < 0xFFE20000 && pa_end >= 0xFFE10000) 171 | XPm_ReleaseNode(NODE_TCM_1_A); 172 | if (pa <= 0xFFE30000 && pa_end >= 0xFFE20000) 173 | XPm_ReleaseNode(NODE_TCM_0_B); 174 | if (pa <= 0xFFE40000 && pa_end >= 0xFFE30000) 175 | XPm_ReleaseNode(NODE_TCM_1_B); 176 | if (pa < 0xFFEA0000) 177 | XPm_ReleaseNode(NODE_TCM_1_A); 178 | if (pa <= 0xFFC0000 && pa_end >= 0xFFEB0000) 179 | XPm_ReleaseNode(NODE_TCM_1_B); 180 | node = tmpnode->prev; 181 | metal_list_del(tmpnode); 182 | metal_free_memory(mem->io); 183 | metal_free_memory(mem); 184 | } 185 | 186 | ret = XPm_ForcePowerDown(priv->cpu_id, REQUEST_ACK_BLOCKING); 187 | if (ret != XST_SUCCESS) 188 | return -1; 189 | else 190 | return 0; 191 | } 192 | 193 | struct remoteproc_ops zynqmp_rpu_rproc_ops = { 194 | .init = rpu_rproc_init, 195 | .remove = rpu_rproc_remove, 196 | .start = rpu_rproc_start, 197 | .stop = rpu_rproc_stop, 198 | .shutdown = rpu_rproc_shutdown, 199 | .mmap = rpu_rproc_mmap, 200 | }; 201 | -------------------------------------------------------------------------------- /apps/examples/matrix_multiply/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS} -fdata-sections -ffunction-sections") 2 | set (_fw_dir "${APPS_SHARE_DIR}") 3 | 4 | collector_list (_list PROJECT_INC_DIRS) 5 | collector_list (_app_list APP_INC_DIRS) 6 | include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR}) 7 | 8 | collector_list (_list PROJECT_LIB_DIRS) 9 | collector_list (_app_list APP_LIB_DIRS) 10 | link_directories (${_list} ${_app_list}) 11 | 12 | get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT) 13 | collector_list (_deps PROJECT_LIB_DEPS) 14 | 15 | set (OPENAMP_LIB open_amp) 16 | foreach (_app matrix_multiply matrix_multiplyd) 17 | collector_list (_sources APP_COMMON_SOURCES) 18 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c") 19 | 20 | if (WITH_SHARED_LIB) 21 | add_executable (${_app}-shared ${_sources}) 22 | target_link_libraries (${_app}-shared ${OPENAMP_LIB}-shared ${_deps}) 23 | install (TARGETS ${_app}-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 24 | endif (WITH_SHARED_LIB) 25 | 26 | if (WITH_STATIC_LIB) 27 | if (${PROJECT_SYSTEM} STREQUAL "linux") 28 | add_executable (${_app}-static ${_sources}) 29 | target_link_libraries (${_app}-static ${OPENAMP_LIB}-static ${_deps}) 30 | install (TARGETS ${_app}-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 31 | else (${PROJECT_SYSTEM}) 32 | add_executable (${_app}.out ${_sources}) 33 | set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}") 34 | 35 | target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections ${_linker_opt} -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group) 36 | 37 | install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 38 | endif (${PROJECT_SYSTEM} STREQUAL "linux" ) 39 | endif (WITH_STATIC_LIB) 40 | endforeach(_app) 41 | 42 | -------------------------------------------------------------------------------- /apps/examples/matrix_multiply/matrix_multiply.h: -------------------------------------------------------------------------------- 1 | #ifndef MATRIX_MULTIPLY_H 2 | #define MATRIX_MULTIPLY_H 3 | 4 | #define RPMSG_SERVICE_NAME "rpmsg-openamp-demo-channel" 5 | 6 | #endif /* MATRIX_MULTIPLY_H */ 7 | -------------------------------------------------------------------------------- /apps/examples/matrix_multiply/matrix_multiplyd.c: -------------------------------------------------------------------------------- 1 | /* This is a sample demonstration application that showcases usage of remoteproc 2 | and rpmsg APIs on the remote core. This application is meant to run on the remote CPU 3 | running baremetal code. This applicationr receives two matrices from the master, 4 | multiplies them and returns the result to the master core. */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "matrix_multiply.h" 11 | #include "platform_info.h" 12 | 13 | #define MAX_SIZE 6 14 | #define NUM_MATRIX 2 15 | 16 | #define SHUTDOWN_MSG 0xEF56A55A 17 | 18 | #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) 19 | //#define LPRINTF(format, ...) 20 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 21 | 22 | typedef struct _matrix { 23 | unsigned int size; 24 | unsigned int elements[MAX_SIZE][MAX_SIZE]; 25 | } matrix; 26 | 27 | /* Local variables */ 28 | static struct rpmsg_endpoint lept; 29 | static int shutdown_req = 0; 30 | 31 | /*-----------------------------------------------------------------------------* 32 | * Calculate the Matrix 33 | *-----------------------------------------------------------------------------*/ 34 | static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r) 35 | { 36 | unsigned int i, j, k; 37 | 38 | memset(r, 0x0, sizeof(matrix)); 39 | r->size = m->size; 40 | 41 | for (i = 0; i < m->size; ++i) { 42 | for (j = 0; j < n->size; ++j) { 43 | for (k = 0; k < r->size; ++k) { 44 | r->elements[i][j] += 45 | m->elements[i][k] * n->elements[k][j]; 46 | } 47 | } 48 | } 49 | } 50 | 51 | /*-----------------------------------------------------------------------------* 52 | * RPMSG callbacks setup by remoteproc_resource_init() 53 | *-----------------------------------------------------------------------------*/ 54 | static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, 55 | uint32_t src, void *priv) 56 | { 57 | matrix matrix_array[NUM_MATRIX]; 58 | matrix matrix_result; 59 | 60 | (void)priv; 61 | (void)src; 62 | 63 | if ((*(unsigned int *)data) == SHUTDOWN_MSG) { 64 | LPRINTF("shutdown message is received.\r\n"); 65 | shutdown_req = 1; 66 | return RPMSG_SUCCESS; 67 | } 68 | 69 | memcpy(matrix_array, data, len); 70 | /* Process received data and multiple matrices. */ 71 | Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result); 72 | 73 | /* Send the result of matrix multiplication back to master. */ 74 | if (rpmsg_send(ept, &matrix_result, sizeof(matrix)) < 0) { 75 | LPERROR("rpmsg_send failed\r\n"); 76 | } 77 | return RPMSG_SUCCESS; 78 | } 79 | 80 | static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) 81 | { 82 | (void)ept; 83 | LPERROR("Endpoint is destroyed\r\n"); 84 | shutdown_req = 1; 85 | } 86 | 87 | /*-----------------------------------------------------------------------------* 88 | * Application 89 | *-----------------------------------------------------------------------------*/ 90 | int app(struct rpmsg_device *rdev, void *priv) 91 | { 92 | int ret; 93 | 94 | ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, 95 | 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, 96 | rpmsg_service_unbind); 97 | if (ret) { 98 | LPERROR("Failed to create endpoint.\r\n"); 99 | return -1; 100 | } 101 | 102 | LPRINTF("Waiting for events...\r\n"); 103 | while(1) { 104 | platform_poll(priv); 105 | /* we got a shutdown request, exit */ 106 | if (shutdown_req) { 107 | break; 108 | } 109 | } 110 | rpmsg_destroy_ept(&lept); 111 | 112 | return 0; 113 | } 114 | 115 | /*-----------------------------------------------------------------------------* 116 | * Application entry point 117 | *-----------------------------------------------------------------------------*/ 118 | int main(int argc, char *argv[]) 119 | { 120 | void *platform; 121 | struct rpmsg_device *rpdev; 122 | int ret; 123 | 124 | LPRINTF("Starting application...\r\n"); 125 | 126 | /* Initialize platform */ 127 | ret = platform_init(argc, argv, &platform); 128 | if (ret) { 129 | LPERROR("Failed to initialize platform.\r\n"); 130 | ret = -1; 131 | } else { 132 | rpdev = platform_create_rpmsg_vdev(platform, 0, 133 | VIRTIO_DEV_SLAVE, 134 | NULL, NULL); 135 | if (!rpdev) { 136 | LPERROR("Failed to create rpmsg virtio device.\r\n"); 137 | ret = -1; 138 | } else { 139 | app(rpdev, platform); 140 | platform_release_rpmsg_vdev(rpdev); 141 | ret = 0; 142 | } 143 | } 144 | 145 | LPRINTF("Stopping application...\r\n"); 146 | platform_cleanup(platform); 147 | 148 | return ret; 149 | } 150 | -------------------------------------------------------------------------------- /apps/examples/rpc_demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS}") 2 | set (_fw_dir "${APPS_SHARE_DIR}") 3 | 4 | collector_list (_list PROJECT_INC_DIRS) 5 | collector_list (_app_list APP_INC_DIRS) 6 | include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR}) 7 | 8 | collector_list (_list PROJECT_LIB_DIRS) 9 | collector_list (_app_list APP_LIB_DIRS) 10 | link_directories (${_list} ${_app_list}) 11 | 12 | get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_LARGE_TEXT_OPT) 13 | if (NOT _linker_opt) 14 | get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT) 15 | endif (NOT _linker_opt) 16 | collector_list (_deps PROJECT_LIB_DEPS) 17 | 18 | set (OPENAMP_LIB open_amp) 19 | 20 | if (${PROJECT_SYSTEM} STREQUAL "linux") 21 | set (app_list rpc_demod) 22 | else (${PROJECT_SYSTEM}) 23 | set (app_list rpc_demo) 24 | endif (${PROJECT_SYSTEM} STREQUAL "linux") 25 | 26 | foreach (_app ${app_list}) 27 | collector_list (_sources APP_COMMON_SOURCES) 28 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c") 29 | 30 | if (WITH_SHARED_LIB) 31 | add_executable (${_app}-shared ${_sources}) 32 | target_link_libraries (${_app}-shared ${OPENAMP_LIB}-shared ${_deps}) 33 | install (TARGETS ${_app}-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 34 | endif (WITH_SHARED_LIB) 35 | 36 | if (WITH_STATIC_LIB) 37 | if (${PROJECT_SYSTEM} STREQUAL "linux") 38 | add_executable (${_app}-static ${_sources}) 39 | target_link_libraries (${_app}-static ${OPENAMP_LIB}-static ${_deps}) 40 | install (TARGETS ${_app}-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 41 | else (${PROJECT_SYSTEM}) 42 | add_executable (${_app}.out ${_sources}) 43 | set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}") 44 | 45 | target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections ${_linker_opt} -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group) 46 | install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 47 | endif (${PROJECT_SYSTEM} STREQUAL "linux" ) 48 | endif (WITH_STATIC_LIB) 49 | endforeach(_app) 50 | -------------------------------------------------------------------------------- /apps/examples/rpc_demo/rpc_demo.c: -------------------------------------------------------------------------------- 1 | /* This is a sample demonstration application that showcases usage of proxy from the remote core. 2 | This application is meant to run on the remote CPU running baremetal. 3 | This applicationr can print to to master console and perform file I/O using proxy mechanism. */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "rsc_table.h" 13 | #include "platform_info.h" 14 | #include "rpmsg-rpc-demo.h" 15 | 16 | #define REDEF_O_CREAT 0000100 17 | #define REDEF_O_EXCL 0000200 18 | #define REDEF_O_RDONLY 0000000 19 | #define REDEF_O_WRONLY 0000001 20 | #define REDEF_O_RDWR 0000002 21 | #define REDEF_O_APPEND 0002000 22 | #define REDEF_O_ACCMODE 0000003 23 | 24 | #define LPRINTF(format, ...) xil_printf(format, ##__VA_ARGS__) 25 | //#define LPRINTF(format, ...) 26 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 27 | 28 | static void rpmsg_rpc_shutdown(struct rpmsg_rpc_data *rpc) 29 | { 30 | (void)rpc; 31 | LPRINTF("RPMSG RPC is shutting down.\r\n"); 32 | } 33 | 34 | /*-----------------------------------------------------------------------------* 35 | * Application specific 36 | *-----------------------------------------------------------------------------*/ 37 | int app(struct rpmsg_device *rdev, void *priv) 38 | { 39 | struct rpmsg_rpc_data rpc; 40 | struct rpmsg_rpc_syscall rpccall; 41 | int fd, bytes_written, bytes_read; 42 | char fname[] = "remote.file"; 43 | char wbuff[50]; 44 | char rbuff[1024]; 45 | char ubuff[50]; 46 | float fdata; 47 | int idata; 48 | int ret; 49 | 50 | /* redirect I/Os */ 51 | LPRINTF("Initializating I/Os redirection...\r\n"); 52 | ret = rpmsg_rpc_init(&rpc, rdev, RPMSG_SERVICE_NAME, 53 | RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, 54 | priv, platform_poll, rpmsg_rpc_shutdown); 55 | rpmsg_set_default_rpc(&rpc); 56 | if (ret) { 57 | LPRINTF("Failed to intialize rpmsg rpc\r\n"); 58 | return -1; 59 | } 60 | 61 | printf("\nRemote>Baremetal Remote Procedure Call (RPC) Demonstration\r\n"); 62 | printf("\nRemote>***************************************************\r\n"); 63 | 64 | printf("\nRemote>Rpmsg based retargetting to proxy initialized..\r\n"); 65 | 66 | /* Remote performing file IO on Master */ 67 | printf("\nRemote>FileIO demo ..\r\n"); 68 | 69 | printf("\nRemote>Creating a file on master and writing to it..\r\n"); 70 | fd = open(fname, REDEF_O_CREAT | REDEF_O_WRONLY | REDEF_O_APPEND, 71 | S_IRUSR | S_IWUSR); 72 | printf("\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd); 73 | 74 | sprintf(wbuff, "This is a test string being written to file.."); 75 | bytes_written = write(fd, wbuff, strlen(wbuff)); 76 | printf("\nRemote>Wrote to fd = %d, size = %d, content = %s\r\n", fd, 77 | bytes_written, wbuff); 78 | close(fd); 79 | printf("\nRemote>Closed fd = %d\r\n", fd); 80 | 81 | /* Remote performing file IO on Master */ 82 | printf("\nRemote>Reading a file on master and displaying its contents..\r\n"); 83 | fd = open(fname, REDEF_O_RDONLY, S_IRUSR | S_IWUSR); 84 | printf("\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd); 85 | bytes_read = read(fd, rbuff, 1024); 86 | *(char *)(&rbuff[0] + bytes_read + 1) = 0; 87 | printf("\nRemote>Read from fd = %d, size = %d, printing contents below .. %s\r\n", 88 | fd, bytes_read, rbuff); 89 | close(fd); 90 | printf("\nRemote>Closed fd = %d\r\n", fd); 91 | 92 | while (1) { 93 | /* Remote performing STDIO on Master */ 94 | printf("\nRemote>Remote firmware using scanf and printf ..\r\n"); 95 | printf("\nRemote>Scanning user input from master..\r\n"); 96 | printf("\nRemote>Enter name\r\n"); 97 | ret = scanf("%s", ubuff); 98 | if (ret) { 99 | printf("\nRemote>Enter age\r\n"); 100 | ret = scanf("%d", &idata); 101 | if (ret) { 102 | printf("\nRemote>Enter value for pi\r\n"); 103 | ret = scanf("%f", &fdata); 104 | if (ret) { 105 | printf("\nRemote>User name = '%s'\r\n", ubuff); 106 | printf("\nRemote>User age = '%d'\r\n", idata); 107 | printf("\nRemote>User entered value of pi = '%f'\r\n", fdata); 108 | } 109 | } 110 | } 111 | if (!ret) { 112 | scanf("%s", ubuff); 113 | printf("Remote> Invalid value. Starting again...."); 114 | } else { 115 | printf("\nRemote>Repeat demo ? (enter yes or no) \r\n"); 116 | scanf("%s", ubuff); 117 | if ((strcmp(ubuff, "no")) && (strcmp(ubuff, "yes"))) { 118 | printf("\nRemote>Invalid option. Starting again....\r\n"); 119 | } else if ((!strcmp(ubuff, "no"))) { 120 | printf("\nRemote>RPC retargetting quitting ...\r\n"); 121 | break; 122 | } 123 | } 124 | } 125 | 126 | printf("\nRemote> Firmware's rpmsg-rpc-channel going down! \r\n"); 127 | rpccall.id = TERM_SYSCALL_ID; 128 | (void)rpmsg_rpc_send(&rpc, &rpccall, sizeof(rpccall), NULL, 0); 129 | 130 | LPRINTF("Release remoteproc procedure call\r\n"); 131 | rpmsg_rpc_release(&rpc); 132 | return 0; 133 | } 134 | 135 | /*-----------------------------------------------------------------------------* 136 | * Application entry point 137 | *-----------------------------------------------------------------------------*/ 138 | int main(int argc, char *argv[]) 139 | { 140 | void *platform; 141 | struct rpmsg_device *rpdev; 142 | int ret; 143 | 144 | LPRINTF("Starting application...\r\n"); 145 | 146 | /* Initialize platform */ 147 | ret = platform_init(argc, argv, &platform); 148 | if (ret) { 149 | LPERROR("Failed to initialize platform.\r\n"); 150 | ret = -1; 151 | } else { 152 | rpdev = platform_create_rpmsg_vdev(platform, 0, 153 | VIRTIO_DEV_SLAVE, 154 | NULL, NULL); 155 | if (!rpdev) { 156 | LPERROR("Failed to create rpmsg virtio device.\r\n"); 157 | ret = -1; 158 | } else { 159 | app(rpdev, platform); 160 | platform_release_rpmsg_vdev(rpdev); 161 | ret = 0; 162 | } 163 | } 164 | 165 | LPRINTF("Stopping application...\r\n"); 166 | platform_cleanup(platform); 167 | 168 | return ret; 169 | } 170 | -------------------------------------------------------------------------------- /apps/examples/rpc_demo/rpmsg-rpc-demo.h: -------------------------------------------------------------------------------- 1 | #ifndef RPMSG_RPC_DEMO_H 2 | #define RPMSG_RPC_DEMO_H 3 | 4 | #define RPMSG_SERVICE_NAME "rpmsg-openamp-demo-channel" 5 | 6 | #endif /* RPMSG_RPC_DEMO_H */ 7 | -------------------------------------------------------------------------------- /apps/examples/rpmsg_sample_echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS} -fdata-sections -ffunction-sections") 3 | set (_fw_dir "${APPS_SHARE_DIR}") 4 | 5 | collector_list (_list PROJECT_INC_DIRS) 6 | collector_list (_app_list APP_INC_DIRS) 7 | include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR}) 8 | 9 | collector_list (_list PROJECT_LIB_DIRS) 10 | collector_list (_app_list APP_LIB_DIRS) 11 | link_directories (${_list} ${_app_list}) 12 | 13 | get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT) 14 | collector_list (_deps PROJECT_LIB_DEPS) 15 | 16 | set (OPENAMP_LIB open_amp) 17 | 18 | foreach (_app rpmsg-sample-echo rpmsg-sample-ping) 19 | collector_list (_sources APP_COMMON_SOURCES) 20 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c") 21 | 22 | if (WITH_SHARED_LIB) 23 | add_executable (${_app}-shared ${_sources}) 24 | target_link_libraries (${_app}-shared ${OPENAMP_LIB}-shared ${_deps}) 25 | install (TARGETS ${_app}-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 26 | endif (WITH_SHARED_LIB) 27 | 28 | if (WITH_STATIC_LIB) 29 | if (${PROJECT_SYSTEM} STREQUAL "linux") 30 | add_executable (${_app}-static ${_sources}) 31 | target_link_libraries (${_app}-static ${OPENAMP_LIB}-static ${_deps}) 32 | install (TARGETS ${_app}-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 33 | else (${PROJECT_SYSTEM}) 34 | add_executable (${_app}.out ${_sources}) 35 | set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}") 36 | 37 | target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections ${_linker_opt} -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group) 38 | 39 | install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 40 | endif (${PROJECT_SYSTEM} STREQUAL "linux" ) 41 | endif (WITH_STATIC_LIB) 42 | endforeach(_app) 43 | -------------------------------------------------------------------------------- /apps/examples/rpmsg_sample_echo/rpmsg-sample-echo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a sample demonstration application that showcases usage of rpmsg 3 | * This application is meant to run on the remote CPU running baremetal code. 4 | * This application allows to check the compatibility with linux OS running on 5 | * the master CPU. For this it echo MSG_LIMIT time message sent by the rpmsg 6 | * sample client available in linux kernel distribution. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "platform_info.h" 13 | 14 | #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) 15 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 16 | 17 | 18 | #define RPMSG_SERV_NAME "rpmsg-client-sample" 19 | #define MSG_LIMIT 100 20 | 21 | static struct rpmsg_endpoint lept; 22 | static int shutdown_req = 0; 23 | 24 | /*-----------------------------------------------------------------------------* 25 | * RPMSG endpoint callbacks 26 | *-----------------------------------------------------------------------------*/ 27 | static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, 28 | uint32_t src, void *priv) 29 | { 30 | (void)priv; 31 | (void)src; 32 | static uint32_t count = 0; 33 | char payload[RPMSG_BUFFER_SIZE]; 34 | 35 | /* Send data back MSG_LIMIT time to master */ 36 | memset(payload, 0, RPMSG_BUFFER_SIZE); 37 | memcpy(payload, data, len); 38 | if (++count <= MSG_LIMIT) { 39 | LPRINTF("echo message number %u: %s\r\n", 40 | (unsigned int)count, payload); 41 | if (rpmsg_send(ept, (char *)data, len) < 0) { 42 | LPERROR("rpmsg_send failed\r\n"); 43 | goto destroy_ept; 44 | } 45 | 46 | if (count == MSG_LIMIT) { 47 | goto destroy_ept; 48 | } 49 | } 50 | return RPMSG_SUCCESS; 51 | 52 | destroy_ept: 53 | shutdown_req = 1; 54 | return RPMSG_SUCCESS; 55 | } 56 | 57 | static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) 58 | { 59 | (void)ept; 60 | LPRINTF("unexpected Remote endpoint destroy\r\n"); 61 | shutdown_req = 1; 62 | } 63 | 64 | /*-----------------------------------------------------------------------------* 65 | * Application 66 | *-----------------------------------------------------------------------------*/ 67 | int app(struct rpmsg_device *rdev, void *priv) 68 | { 69 | int ret; 70 | 71 | /* Initialize RPMSG framework */ 72 | LPRINTF("Try to create rpmsg endpoint.\r\n"); 73 | 74 | ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERV_NAME, 0, RPMSG_ADDR_ANY, 75 | rpmsg_endpoint_cb, rpmsg_service_unbind); 76 | if (ret) { 77 | LPERROR("Failed to create endpoint.\r\n"); 78 | return -1; 79 | } 80 | 81 | LPRINTF("Successfully created rpmsg endpoint.\r\n"); 82 | while (1) { 83 | platform_poll(priv); 84 | /* we got a shutdown request, exit */ 85 | if (shutdown_req) { 86 | break; 87 | } 88 | } 89 | rpmsg_destroy_ept(&lept); 90 | 91 | return 0; 92 | } 93 | 94 | /*-----------------------------------------------------------------------------* 95 | * Application entry point 96 | *-----------------------------------------------------------------------------*/ 97 | int main(int argc, char *argv[]) 98 | { 99 | void *platform; 100 | struct rpmsg_device *rpdev; 101 | int ret; 102 | 103 | LPRINTF("Starting application...\r\n"); 104 | 105 | /* Initialize platform */ 106 | ret = platform_init(argc, argv, &platform); 107 | if (ret) { 108 | LPERROR("Failed to initialize platform.\r\n"); 109 | ret = -1; 110 | } else { 111 | rpdev = platform_create_rpmsg_vdev(platform, 0, 112 | VIRTIO_DEV_SLAVE, 113 | NULL, NULL); 114 | if (!rpdev) { 115 | LPERROR("Failed to create rpmsg virtio device.\r\n"); 116 | ret = -1; 117 | } else { 118 | app(rpdev, platform); 119 | platform_release_rpmsg_vdev(rpdev); 120 | ret = 0; 121 | } 122 | } 123 | 124 | LPRINTF("Stopping application...\r\n"); 125 | platform_cleanup(platform); 126 | 127 | return ret; 128 | } 129 | -------------------------------------------------------------------------------- /apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a sample demonstration application that showcases usage of rpmsg 3 | * This application is meant to run on the remote CPU running baremetal code. 4 | * This application simulate linux sample rpmsg driver. For this it echo 100 5 | * time message sent by the rpmsg sample client available in linux kernel 6 | * distribution. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "platform_info.h" 16 | 17 | #define RPMSG_SERV_NAME "rpmsg-client-sample" 18 | 19 | #define HELLO_MSG "hello world!" 20 | #define BYE_MSG "goodbye!" 21 | #define MSG_LIMIT 100 22 | 23 | #define APP_EPT_ADDR 0 24 | #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) 25 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 26 | 27 | static int err_cnt; 28 | 29 | 30 | /* Globals */ 31 | static struct rpmsg_endpoint lept; 32 | static int rnum = 0; 33 | static int err_cnt = 0; 34 | static int ept_deleted = 0; 35 | 36 | /*-----------------------------------------------------------------------------* 37 | * RPMSG endpoint callbacks 38 | *-----------------------------------------------------------------------------*/ 39 | static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, 40 | uint32_t src, void *priv) 41 | { 42 | char payload[RPMSG_BUFFER_SIZE]; 43 | char seed[20]; 44 | 45 | (void)ept; 46 | (void)src; 47 | (void)priv; 48 | 49 | memset(payload, 0, RPMSG_BUFFER_SIZE); 50 | memcpy(payload, data, len); 51 | LPRINTF("received message %d: %s of size %lu \r\n", 52 | rnum + 1, payload, (unsigned long)len); 53 | 54 | if (rnum == (MSG_LIMIT - 1)) 55 | sprintf (seed, "%s", BYE_MSG); 56 | else 57 | sprintf (seed, "%s", HELLO_MSG); 58 | 59 | LPRINTF(" seed %s: \r\n", seed); 60 | 61 | if (strncmp(payload, seed, len)) { 62 | LPERROR(" Invalid message is received.\r\n"); 63 | err_cnt++; 64 | return RPMSG_SUCCESS; 65 | } 66 | LPRINTF(" rnum %d: \r\n", rnum); 67 | rnum++; 68 | 69 | return RPMSG_SUCCESS; 70 | } 71 | 72 | static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) 73 | { 74 | (void)ept; 75 | rpmsg_destroy_ept(&lept); 76 | LPRINTF("echo test: service is destroyed\r\n"); 77 | ept_deleted = 1; 78 | } 79 | 80 | static void rpmsg_name_service_bind_cb(struct rpmsg_device *rdev, 81 | const char *name, uint32_t dest) 82 | { 83 | LPRINTF("new endpoint notification is received.\r\n"); 84 | if (strcmp(name, RPMSG_SERV_NAME)) 85 | LPERROR("Unexpected name service %s.\r\n", name); 86 | else 87 | (void)rpmsg_create_ept(&lept, rdev, RPMSG_SERV_NAME, 88 | APP_EPT_ADDR, dest, 89 | rpmsg_endpoint_cb, 90 | rpmsg_service_unbind); 91 | 92 | } 93 | 94 | /*-----------------------------------------------------------------------------* 95 | * Application 96 | *-----------------------------------------------------------------------------*/ 97 | int app(struct rpmsg_device *rdev, void *priv) 98 | { 99 | int ret; 100 | int i; 101 | 102 | LPRINTF(" 1 - Send data to remote core, retrieve the echo"); 103 | LPRINTF(" and validate its integrity ..\r\n"); 104 | 105 | /* Create RPMsg endpoint */ 106 | ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERV_NAME, APP_EPT_ADDR, 107 | RPMSG_ADDR_ANY, 108 | rpmsg_endpoint_cb, rpmsg_service_unbind); 109 | 110 | if (ret) { 111 | LPERROR("Failed to create RPMsg endpoint.\r\n"); 112 | return ret; 113 | } 114 | 115 | while (!is_rpmsg_ept_ready(&lept)) 116 | platform_poll(priv); 117 | 118 | LPRINTF("RPMSG endpoint is binded with remote.\r\n"); 119 | for (i = 1; i <= MSG_LIMIT; i++) { 120 | 121 | 122 | if (i < MSG_LIMIT) 123 | ret = rpmsg_send(&lept, HELLO_MSG, strlen(HELLO_MSG)); 124 | else 125 | ret = rpmsg_send(&lept, BYE_MSG, strlen(BYE_MSG)); 126 | 127 | if (ret < 0) { 128 | LPERROR("Failed to send data...\r\n"); 129 | break; 130 | } 131 | LPRINTF("rpmsg sample test: message %d sent\r\n", i); 132 | 133 | do { 134 | platform_poll(priv); 135 | } while ((rnum < i) && !err_cnt); 136 | 137 | } 138 | 139 | LPRINTF("**********************************\r\n"); 140 | LPRINTF(" Test Results: Error count = %d\r\n", err_cnt); 141 | LPRINTF("**********************************\r\n"); 142 | while (!ept_deleted) 143 | platform_poll(priv); 144 | LPRINTF("Quitting application .. rpmsg sample test end\r\n"); 145 | 146 | return 0; 147 | } 148 | 149 | int main(int argc, char *argv[]) 150 | { 151 | void *platform; 152 | struct rpmsg_device *rpdev; 153 | int ret; 154 | 155 | /* Initialize platform */ 156 | ret = platform_init(argc, argv, &platform); 157 | if (ret) { 158 | LPERROR("Failed to initialize platform.\r\n"); 159 | ret = -1; 160 | } else { 161 | rpdev = platform_create_rpmsg_vdev(platform, 0, 162 | VIRTIO_DEV_MASTER, 163 | NULL, 164 | rpmsg_name_service_bind_cb); 165 | if (!rpdev) { 166 | LPERROR("Failed to create rpmsg virtio device.\r\n"); 167 | ret = -1; 168 | } else { 169 | app(rpdev, platform); 170 | platform_release_rpmsg_vdev(rpdev); 171 | ret = 0; 172 | } 173 | } 174 | 175 | LPRINTF("Stopping application...\r\n"); 176 | platform_cleanup(platform); 177 | 178 | return ret; 179 | } 180 | 181 | -------------------------------------------------------------------------------- /apps/machine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE}/CMakeLists.txt") 2 | add_subdirectory (${PROJECT_MACHINE}) 3 | endif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE}/CMakeLists.txt") 4 | -------------------------------------------------------------------------------- /apps/machine/zynq7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (APP_INC_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | collect (APP_COMMON_SOURCES platform_info.c) 4 | collect (APP_COMMON_SOURCES rsc_table.c) 5 | collect (APP_COMMON_SOURCES zynq_a9_rproc.c) 6 | 7 | -------------------------------------------------------------------------------- /apps/machine/zynq7/platform_info.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_INFO_H_ 2 | #define PLATFORM_INFO_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* SGIs */ 13 | #define SGI_TO_NOTIFY 15 /* SGI to notify the remote */ 14 | #define SGI_NOTIFICATION 14 /* SGI from the remote */ 15 | 16 | /* Memory attributes */ 17 | #define NORM_NONCACHE 0x11DE2 /* Normal Non-cacheable */ 18 | #define STRONG_ORDERED 0xC02 /* Strongly ordered */ 19 | #define DEVICE_MEMORY 0xC06 /* Device memory */ 20 | #define RESERVED 0x0 /* reserved memory */ 21 | 22 | /* Shared memory */ 23 | #define SHARED_MEM_PA 0x3e800000UL 24 | #define SHARED_MEM_SIZE 0x80000UL 25 | #define SHARED_BUF_OFFSET 0x80000UL 26 | 27 | /* Zynq CPU ID mask */ 28 | #define ZYNQ_CPU_ID_MASK 0x1UL 29 | 30 | /* Remoteproc private data struct */ 31 | struct remoteproc_priv { 32 | const char *gic_name; /* SCUGIC device name */ 33 | const char *gic_bus_name; /* SCUGIC bus name */ 34 | struct metal_device *gic_dev; /* pointer to SCUGIC device */ 35 | struct metal_io_region *gic_io; /* pointer to SCUGIC i/o region */ 36 | unsigned int irq_to_notify; /* SCUGIC IRQ vector to notify the 37 | * other end. 38 | */ 39 | unsigned int irq_notification; /* SCUGIC IRQ vector received from 40 | * other end. 41 | */ 42 | unsigned int cpu_id; /* CPU ID */ 43 | atomic_int nokick; /* 0 for kick from other side */ 44 | }; 45 | 46 | /** 47 | * platform_init - initialize the platform 48 | * 49 | * It will initialize the platform. 50 | * 51 | * @argc: number of arguments 52 | * @argv: array of the input arguements 53 | * @platform: pointer to store the platform data pointer 54 | * 55 | * return 0 for success or negative value for failure 56 | */ 57 | int platform_init(int argc, char *argv[], void **platform); 58 | 59 | /** 60 | * platform_create_rpmsg_vdev - create rpmsg vdev 61 | * 62 | * It will create rpmsg virtio device, and returns the rpmsg virtio 63 | * device pointer. 64 | * 65 | * @platform: pointer to the private data 66 | * @vdev_index: index of the virtio device, there can more than one vdev 67 | * on the platform. 68 | * @role: virtio master or virtio slave of the vdev 69 | * @rst_cb: virtio device reset callback 70 | * @ns_bind_cb: rpmsg name service bind callback 71 | * 72 | * return pointer to the rpmsg virtio device 73 | */ 74 | struct rpmsg_device * 75 | platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, 76 | unsigned int role, 77 | void (*rst_cb)(struct virtio_device *vdev), 78 | rpmsg_ns_bind_cb ns_bind_cb); 79 | 80 | /** 81 | * platform_poll - platform poll function 82 | * 83 | * @platform: pointer to the platform 84 | * 85 | * return negative value for errors, otherwise 0. 86 | */ 87 | int platform_poll(void *platform); 88 | 89 | /** 90 | * platform_release_rpmsg_vdev - release rpmsg virtio device 91 | * 92 | * @rpdev: pointer to the rpmsg device 93 | */ 94 | void platform_release_rpmsg_vdev(struct rpmsg_device *rpdev); 95 | 96 | /** 97 | * platform_cleanup - clean up the platform resource 98 | * 99 | * @platform: pointer to the platform 100 | */ 101 | void platform_cleanup(void *platform); 102 | 103 | #if defined __cplusplus 104 | } 105 | #endif 106 | 107 | #endif /* PLATFORM_INFO_H_ */ 108 | -------------------------------------------------------------------------------- /apps/machine/zynq7/platform_info_remoteproc_master.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | /************************************************************************** 9 | * FILE NAME 10 | * 11 | * platform_info.c 12 | * 13 | * DESCRIPTION 14 | * 15 | * This file implements APIs to get platform specific 16 | * information for OpenAMP. 17 | * 18 | **************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | /* Reference implementation that show cases platform_get_cpu_info and 25 | platform_get_for_firmware API implementation for Bare metal environment */ 26 | 27 | extern struct hil_platform_ops zynq_a9_proc_ops; 28 | 29 | /* IPC Device parameters */ 30 | #define SHM_ADDR (void *)0x08008000 31 | #define SHM_SIZE 0x00200000 32 | #define VRING0_IPI_VECT 6 33 | #define VRING1_IPI_VECT 3 34 | #define MASTER_CPU_ID 0 35 | #define REMOTE_CPU_ID 1 36 | 37 | /** 38 | * This array provdes defnition of CPU nodes for master and remote 39 | * context. It contains two nodes beacuse the same file is intended 40 | * to use with both master and remote configurations. On zynq platform 41 | * only one node defintion is required for master/remote as there 42 | * are only two cores present in the platform. 43 | * 44 | * Only platform specific info is populated here. Rest of information 45 | * is obtained during resource table parsing.The platform specific 46 | * information includes; 47 | * 48 | * -CPU ID 49 | * -Shared Memory 50 | * -Interrupts 51 | * -Channel info. 52 | * 53 | * Although the channel info is not platform specific information 54 | * but it is conveneient to keep it in HIL so that user can easily 55 | * provide it without modifying the generic part. 56 | * 57 | * It is good idea to define hil_proc structure with platform 58 | * specific fields populated as this can be easily copied to hil_proc 59 | * structure passed as parameter in platform_get_processor_info. The 60 | * other option is to populate the required structures individually 61 | * and copy them one by one to hil_proc structure in platform_get_processor_info 62 | * function. The first option is adopted here. 63 | * 64 | * 65 | * 1) First node in the array is intended for the remote contexts and it 66 | * defines Master CPU ID, shared memory, interrupts info, number of channels 67 | * and there names. This node defines only one channel 68 | * "rpmsg-openamp-demo-channel". 69 | * 70 | * 2)Second node is required by the master and it defines remote CPU ID, 71 | * shared memory and interrupts info. In general no channel info is required by the 72 | * Master node, however in baremetal master and linux remote case the linux 73 | * rpmsg bus driver behaves as master so the rpmsg driver on linux side still needs 74 | * channel info. This information is not required by the masters for baremetal 75 | * remotes. 76 | * 77 | */ 78 | struct hil_proc proc_table []= 79 | { 80 | { 81 | /* CPU ID of remote */ 82 | REMOTE_CPU_ID, 83 | 84 | /* Shared memory info - Last field is not used currently */ 85 | { 86 | SHM_ADDR, SHM_SIZE, 0x00 87 | }, 88 | 89 | /* VirtIO device info */ 90 | { 91 | 0, 0, 0, 92 | { 93 | { 94 | /* Provide vring interrupts info here. Other fields are obtained 95 | * from the rsc table so leave them empty. 96 | */ 97 | NULL, NULL, 0, 0, 98 | { 99 | VRING0_IPI_VECT,0x1006,1 100 | } 101 | }, 102 | { 103 | NULL, NULL, 0, 0, 104 | { 105 | VRING1_IPI_VECT,0x1006,1 106 | } 107 | } 108 | } 109 | }, 110 | 111 | /* Number of RPMSG channels */ 112 | 1, 113 | 114 | /* RPMSG channel info - Only channel name is expected currently */ 115 | { 116 | {"rpmsg-openamp-demo-channel"} 117 | }, 118 | 119 | /* HIL platform ops table. */ 120 | &zynq_a9_proc_ops, 121 | 122 | /* Next three fields are for future use only */ 123 | 0, 124 | 0, 125 | NULL 126 | } 127 | }; 128 | 129 | /* Start and end addresses of firmware image for remotes. These are defined in the 130 | * object files that are obtained by converting the remote ELF Image into object 131 | * files. These symbols are not used for remotes. 132 | */ 133 | extern unsigned char _binary_firmware1_start; 134 | extern unsigned char _binary_firmware1_end; 135 | 136 | extern unsigned char _binary_firmware2_start; 137 | extern unsigned char _binary_firmware2_end; 138 | 139 | #define FIRMWARE1_START (void *)&_binary_firmware1_start 140 | #define FIRMWARE1_END (void *)&_binary_firmware1_end 141 | 142 | #define FIRMWARE2_START (void *)&_binary_firmware2_start 143 | #define FIRMWARE2_END (void *)&_binary_firmware2_end 144 | 145 | /* Init firmware table */ 146 | 147 | const struct firmware_info fw_table[] = 148 | { 149 | {"firmware1", 150 | (unsigned int)FIRMWARE1_START, 151 | (unsigned int)FIRMWARE1_END}, 152 | {"firmware2", 153 | (unsigned int)FIRMWARE2_START, 154 | (unsigned int)FIRMWARE2_END} 155 | }; 156 | 157 | int fw_table_size = sizeof(fw_table)/sizeof(struct firmware_info); 158 | -------------------------------------------------------------------------------- /apps/machine/zynq7/rsc_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * Copyright (c) 2015 Xilinx, Inc. All rights reserved. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | /* This file populates resource table for BM remote 10 | * for use by the Linux Master */ 11 | 12 | #include 13 | #include "rsc_table.h" 14 | #include "platform_info.h" 15 | 16 | /* Place resource table in special ELF section */ 17 | /* Redefine __section for section name with token */ 18 | #define __section_t(S) __attribute__((__section__(#S))) 19 | #define __resource __section_t(.resource_table) 20 | 21 | #define RPMSG_IPU_C0_FEATURES 1 22 | 23 | /* VirtIO rpmsg device id */ 24 | #define VIRTIO_ID_RPMSG_ 7 25 | 26 | /* Remote supports Name Service announcement */ 27 | #define VIRTIO_RPMSG_F_NS 0 28 | 29 | /* Resource table entries */ 30 | #define NUM_VRINGS 0x02 31 | #define VRING_ALIGN 0x1000 32 | #define RING_TX FW_RSC_U32_ADDR_ANY 33 | #define RING_RX FW_RSC_U32_ADDR_ANY 34 | #define VRING_SIZE 256 35 | 36 | #define NUM_TABLE_ENTRIES 1 37 | 38 | 39 | struct remote_resource_table __resource resources = { 40 | /* Version */ 41 | 1, 42 | 43 | /* NUmber of table entries */ 44 | NUM_TABLE_ENTRIES, 45 | /* reserved fields */ 46 | {0, 0,}, 47 | 48 | /* Offsets of rsc entries */ 49 | { 50 | offsetof(struct remote_resource_table, rpmsg_vdev), 51 | }, 52 | 53 | /* Virtio device entry */ 54 | { 55 | RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, 56 | NUM_VRINGS, {0, 0}, 57 | }, 58 | 59 | /* Vring rsc entry - part of vdev rsc entry */ 60 | {RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0}, 61 | {RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0}, 62 | }; 63 | 64 | void *get_resource_table (int rsc_id, int *len) 65 | { 66 | (void) rsc_id; 67 | *len = sizeof(resources); 68 | return &resources; 69 | } 70 | -------------------------------------------------------------------------------- /apps/machine/zynq7/rsc_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * Copyright (c) 2015 Xilinx, Inc. All rights reserved. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | /* This file populates resource table for BM remote 10 | * for use by the Linux Master */ 11 | 12 | #ifndef RSC_TABLE_H_ 13 | #define RSC_TABLE_H_ 14 | 15 | #include 16 | #include 17 | 18 | #if defined __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | #define NO_RESOURCE_ENTRIES 8 23 | 24 | /* Resource table for the given remote */ 25 | struct remote_resource_table { 26 | unsigned int version; 27 | unsigned int num; 28 | unsigned int reserved[2]; 29 | unsigned int offset[NO_RESOURCE_ENTRIES]; 30 | /* rpmsg vdev entry */ 31 | struct fw_rsc_vdev rpmsg_vdev; 32 | struct fw_rsc_vdev_vring rpmsg_vring0; 33 | struct fw_rsc_vdev_vring rpmsg_vring1; 34 | }__attribute__((packed, aligned(0x100000))); 35 | 36 | void *get_resource_table (int rsc_id, int *len); 37 | 38 | #if defined __cplusplus 39 | } 40 | #endif 41 | 42 | #endif /* RSC_TABLE_H_ */ 43 | -------------------------------------------------------------------------------- /apps/machine/zynq7/zynq_a9_rproc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Xilinx, Inc. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | /************************************************************************** 8 | * FILE NAME 9 | * 10 | * zynq_a9_rproc.c 11 | * 12 | * DESCRIPTION 13 | * 14 | * This file define Xilinx Zynq A9 platform specific remoteproc 15 | * implementation. 16 | * 17 | **************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | /* SCUGIC macros */ 27 | #define GIC_DIST_SOFTINT 0xF00 28 | #define GIC_SFI_TRIG_CPU_MASK 0x00FF0000 29 | #define GIC_SFI_TRIG_SATT_MASK 0x00008000 30 | #define GIC_SFI_TRIG_INTID_MASK 0x0000000F 31 | #define GIC_CPU_ID_BASE (1 << 4) 32 | 33 | static int zynq_a9_proc_irq_handler(int vect_id, void *data) 34 | { 35 | struct remoteproc *rproc = data; 36 | struct remoteproc_priv *prproc; 37 | 38 | (void)vect_id; 39 | if (!rproc) 40 | return METAL_IRQ_NOT_HANDLED; 41 | prproc = rproc->priv; 42 | atomic_flag_clear(&prproc->nokick); 43 | return METAL_IRQ_HANDLED; 44 | } 45 | 46 | static struct remoteproc * 47 | zynq_a9_proc_init(struct remoteproc *rproc, 48 | struct remoteproc_ops *ops, void *arg) 49 | { 50 | struct remoteproc_priv *prproc = arg; 51 | struct metal_device *dev; 52 | unsigned int irq_vect; 53 | int ret; 54 | 55 | if (!rproc || !prproc || !ops) 56 | return NULL; 57 | ret = metal_device_open(prproc->gic_bus_name, prproc->gic_name, 58 | &dev); 59 | if (ret) { 60 | xil_printf("failed to open GIC device: %d.\r\n", ret); 61 | return NULL; 62 | } 63 | rproc->priv = prproc; 64 | prproc->gic_dev = dev; 65 | prproc->gic_io = metal_device_io_region(dev, 0); 66 | if (!prproc->gic_io) 67 | goto err1; 68 | rproc->ops = ops; 69 | atomic_flag_test_and_set(&prproc->nokick); 70 | 71 | /* Register interrupt handler and enable interrupt */ 72 | irq_vect = prproc->irq_notification; 73 | metal_irq_register(irq_vect, zynq_a9_proc_irq_handler, rproc); 74 | metal_irq_enable(irq_vect); 75 | xil_printf("Successfully intialize remoteproc.\r\n"); 76 | return rproc; 77 | err1: 78 | metal_device_close(dev); 79 | return NULL; 80 | } 81 | 82 | static void zynq_a9_proc_remove(struct remoteproc *rproc) 83 | { 84 | struct remoteproc_priv *prproc; 85 | struct metal_device *dev; 86 | 87 | if (!rproc) 88 | return; 89 | prproc = rproc->priv; 90 | metal_irq_disable(prproc->irq_to_notify); 91 | metal_irq_unregister(prproc->irq_to_notify); 92 | dev = prproc->gic_dev; 93 | if (dev) 94 | metal_device_close(dev); 95 | } 96 | 97 | static void * 98 | zynq_a9_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa, 99 | metal_phys_addr_t *da, size_t size, 100 | unsigned int attribute, struct metal_io_region **io) 101 | { 102 | struct remoteproc_mem *mem; 103 | metal_phys_addr_t lpa, lda; 104 | struct metal_io_region *tmpio; 105 | 106 | lpa = *pa; 107 | lda = *da; 108 | 109 | if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS) 110 | return NULL; 111 | if (lpa == METAL_BAD_PHYS) 112 | lpa = lda; 113 | if (lda == METAL_BAD_PHYS) 114 | lda = lpa; 115 | 116 | if (!attribute) 117 | attribute = NORM_NONCACHE | STRONG_ORDERED; 118 | mem = metal_allocate_memory(sizeof(*mem)); 119 | if (!mem) 120 | return NULL; 121 | tmpio = metal_allocate_memory(sizeof(*tmpio)); 122 | if (!tmpio) { 123 | metal_free_memory(mem); 124 | return NULL; 125 | } 126 | remoteproc_init_mem(mem, NULL, lpa, lda, size, tmpio); 127 | /* va is the same as pa in this platform */ 128 | metal_io_init(tmpio, (void *)lpa, &mem->pa, size, 129 | sizeof(metal_phys_addr_t)<<3, attribute, NULL); 130 | remoteproc_add_mem(rproc, mem); 131 | *pa = lpa; 132 | *da = lda; 133 | if (io) 134 | *io = tmpio; 135 | return metal_io_phys_to_virt(tmpio, mem->pa); 136 | } 137 | 138 | static int zynq_a9_proc_notify(struct remoteproc *rproc, uint32_t id) 139 | { 140 | struct remoteproc_priv *prproc; 141 | unsigned long mask = 0; 142 | 143 | (void)id; 144 | if (!rproc) 145 | return -1; 146 | prproc = rproc->priv; 147 | if (!prproc->gic_io) 148 | return -1; 149 | 150 | mask = ((1 << (GIC_CPU_ID_BASE + prproc->cpu_id)) | 151 | (prproc->irq_to_notify)) 152 | & (GIC_SFI_TRIG_CPU_MASK | GIC_SFI_TRIG_INTID_MASK); 153 | /* Trigger IPI */ 154 | metal_io_write32(prproc->gic_io, GIC_DIST_SOFTINT, mask); 155 | return 0; 156 | } 157 | 158 | /* processor operations from r5 to a53. It defines 159 | * notification operation and remote processor managementi operations. */ 160 | struct remoteproc_ops zynq_a9_proc_ops = { 161 | .init = zynq_a9_proc_init, 162 | .remove = zynq_a9_proc_remove, 163 | .mmap = zynq_a9_proc_mmap, 164 | .notify = zynq_a9_proc_notify, 165 | .start = NULL, 166 | .stop = NULL, 167 | .shutdown = NULL, 168 | }; 169 | -------------------------------------------------------------------------------- /apps/machine/zynqmp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (APP_COMMON_SOURCES platform_info.c) 2 | collect (APP_COMMON_SOURCES zynqmp_linux_r5_proc.c) 3 | collect (APP_INC_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") 4 | 5 | -------------------------------------------------------------------------------- /apps/machine/zynqmp/openamp-linux-userspace.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | reserved-memory { 3 | #address-cells = <2>; 4 | #size-cells = <2>; 5 | ranges; 6 | rproc_0_reserved: rproc@3ed000000 { 7 | no-map; 8 | reg = <0x0 0x3ed00000 0x0 0x1000000>; 9 | }; 10 | }; 11 | 12 | amba { 13 | vring: vring@0 { 14 | compatible = "vring_uio"; 15 | reg = <0x0 0x3ed40000 0x0 0x40000>; 16 | }; 17 | shm0: shm@0 { 18 | compatible = "shm_uio"; 19 | reg = <0x0 0x3ed80000 0x0 0x80000>; 20 | }; 21 | ipi0: ipi@0 { 22 | compatible = "ipi_uio"; 23 | reg = <0x0 0xff340000 0x0 0x1000>; 24 | interrupt-parent = <&gic>; 25 | interrupts = <0 29 4>; 26 | }; 27 | }; 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /apps/machine/zynqmp/platform_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Xilinx, Inc. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | /* This file populates resource table for BM remote 8 | * for use by the Linux Master */ 9 | 10 | #ifndef PLATFORM_INFO_H_ 11 | #define PLATFORM_INFO_H_ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | struct remoteproc_priv { 22 | const char *ipi_name; /**< IPI device name */ 23 | const char *ipi_bus_name; /**< IPI bus name */ 24 | const char *rsc_name; /**< rsc device name */ 25 | const char *rsc_bus_name; /**< rsc bus name */ 26 | const char *shm_name; /**< shared memory device name */ 27 | const char *shm_bus_name; /**< shared memory bus name */ 28 | struct metal_device *ipi_dev; /**< pointer to IPI device */ 29 | struct metal_io_region *ipi_io; /**< pointer to IPI i/o region */ 30 | struct metal_device *shm_dev; /**< pointer to shared memory device */ 31 | struct metal_io_region *shm_io; /**< pointer to shared memory i/o 32 | region */ 33 | struct remoteproc_mem shm_mem; /**< shared memory */ 34 | unsigned int ipi_chn_mask; /**< IPI channel mask */ 35 | atomic_int ipi_nokick; 36 | }; 37 | 38 | 39 | /** 40 | * platform_init - initialize the platform 41 | * 42 | * It will initialize the platform. 43 | * 44 | * @argc: number of arguments 45 | * @argv: array of the input arguements 46 | * @platform: pointer to store the platform data pointer 47 | * 48 | * return 0 for success or negative value for failure 49 | */ 50 | int platform_init(int argc, char *argv[], void **platform); 51 | 52 | /** 53 | * platform_create_rpmsg_vdev - create rpmsg vdev 54 | * 55 | * It will create rpmsg virtio device, and returns the rpmsg virtio 56 | * device pointer. 57 | * 58 | * @platform: pointer to the private data 59 | * @vdev_index: index of the virtio device, there can more than one vdev 60 | * on the platform. 61 | * @role: virtio master or virtio slave of the vdev 62 | * @rst_cb: virtio device reset callback 63 | * @ns_bind_cb: rpmsg name service bind callback 64 | * 65 | * return pointer to the rpmsg virtio device 66 | */ 67 | struct rpmsg_device * 68 | platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, 69 | unsigned int role, 70 | void (*rst_cb)(struct virtio_device *vdev), 71 | rpmsg_ns_bind_cb ns_bind_cb); 72 | 73 | /** 74 | * platform_poll - platform poll function 75 | * 76 | * @platform: pointer to the platform 77 | * 78 | * return negative value for errors, otherwise 0. 79 | */ 80 | int platform_poll(void *platform); 81 | 82 | /** 83 | * platform_release_rpmsg_vdev - release rpmsg virtio device 84 | * 85 | * @rpdev: pointer to the rpmsg device 86 | */ 87 | void platform_release_rpmsg_vdev(struct rpmsg_device *rpdev); 88 | 89 | /** 90 | * platform_cleanup - clean up the platform resource 91 | * 92 | * @platform: pointer to the platform 93 | */ 94 | void platform_cleanup(void *platform); 95 | 96 | #if defined __cplusplus 97 | } 98 | #endif 99 | 100 | #endif /* PLATFORM_INFO_H_ */ 101 | 102 | -------------------------------------------------------------------------------- /apps/machine/zynqmp_r5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (APP_COMMON_SOURCES platform_info.c) 2 | collect (APP_COMMON_SOURCES rsc_table.c) 3 | collect (APP_COMMON_SOURCES zynqmp_r5_a53_rproc.c) 4 | collect (APP_INC_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") 5 | 6 | -------------------------------------------------------------------------------- /apps/machine/zynqmp_r5/platform_info.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_INFO_H_ 2 | #define PLATFORM_INFO_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* Cortex R5 memory attributes */ 13 | #define DEVICE_SHARED 0x00000001U /* device, shareable */ 14 | #define DEVICE_NONSHARED 0x00000010U /* device, non shareable */ 15 | #define NORM_NSHARED_NCACHE 0x00000008U /* Non cacheable non shareable */ 16 | #define NORM_SHARED_NCACHE 0x0000000CU /* Non cacheable shareable */ 17 | #define PRIV_RW_USER_RW (0x00000003U<<8U) /* Full Access */ 18 | 19 | /* Interrupt vectors */ 20 | #define IPI_IRQ_VECT_ID XPAR_XIPIPSU_0_INT_ID 21 | 22 | struct remoteproc_priv { 23 | const char *ipi_name; /**< IPI device name */ 24 | const char *ipi_bus_name; /**< IPI bus name */ 25 | struct metal_device *ipi_dev; /**< pointer to IPI device */ 26 | struct metal_io_region *ipi_io; /**< pointer to IPI i/o region */ 27 | unsigned int ipi_chn_mask; /**< IPI channel mask */ 28 | atomic_int ipi_nokick; 29 | }; 30 | 31 | /** 32 | * platform_init - initialize the platform 33 | * 34 | * It will initialize the platform. 35 | * 36 | * @argc: number of arguments 37 | * @argv: array of the input arguements 38 | * @platform: pointer to store the platform data pointer 39 | * 40 | * return 0 for success or negative value for failure 41 | */ 42 | int platform_init(int argc, char *argv[], void **platform); 43 | 44 | /** 45 | * platform_create_rpmsg_vdev - create rpmsg vdev 46 | * 47 | * It will create rpmsg virtio device, and returns the rpmsg virtio 48 | * device pointer. 49 | * 50 | * @platform: pointer to the private data 51 | * @vdev_index: index of the virtio device, there can more than one vdev 52 | * on the platform. 53 | * @role: virtio master or virtio slave of the vdev 54 | * @rst_cb: virtio device reset callback 55 | * @ns_bind_cb: rpmsg name service bind callback 56 | * 57 | * return pointer to the rpmsg virtio device 58 | */ 59 | struct rpmsg_device * 60 | platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, 61 | unsigned int role, 62 | void (*rst_cb)(struct virtio_device *vdev), 63 | rpmsg_ns_bind_cb ns_bind_cb); 64 | 65 | /** 66 | * platform_poll - platform poll function 67 | * 68 | * @platform: pointer to the platform 69 | * 70 | * return negative value for errors, otherwise 0. 71 | */ 72 | int platform_poll(void *platform); 73 | 74 | /** 75 | * platform_release_rpmsg_vdev - release rpmsg virtio device 76 | * 77 | * @rpdev: pointer to the rpmsg device 78 | */ 79 | void platform_release_rpmsg_vdev(struct rpmsg_device *rpdev); 80 | 81 | /** 82 | * platform_cleanup - clean up the platform resource 83 | * 84 | * @platform: pointer to the platform 85 | */ 86 | void platform_cleanup(void *platform); 87 | 88 | #if defined __cplusplus 89 | } 90 | #endif 91 | 92 | #endif /* PLATFORM_INFO_H_ */ 93 | -------------------------------------------------------------------------------- /apps/machine/zynqmp_r5/rsc_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * Copyright (c) 2015 Xilinx, Inc. All rights reserved. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | /* This file populates resource table for BM remote 10 | * for use by the Linux Master */ 11 | 12 | #include 13 | #include "rsc_table.h" 14 | 15 | /* Place resource table in special ELF section */ 16 | #define __section_t(S) __attribute__((__section__(#S))) 17 | #define __resource __section_t(.resource_table) 18 | 19 | #define RPMSG_IPU_C0_FEATURES 1 20 | 21 | /* VirtIO rpmsg device id */ 22 | #define VIRTIO_ID_RPMSG_ 7 23 | 24 | /* Remote supports Name Service announcement */ 25 | #define VIRTIO_RPMSG_F_NS 0 26 | 27 | #define NUM_VRINGS 0x02 28 | #define VRING_ALIGN 0x1000 29 | #define RING_TX FW_RSC_U32_ADDR_ANY 30 | #define RING_RX FW_RSC_U32_ADDR_ANY 31 | #define VRING_SIZE 256 32 | 33 | #define NUM_TABLE_ENTRIES 1 34 | 35 | struct remote_resource_table __resource resources = { 36 | /* Version */ 37 | 1, 38 | 39 | /* NUmber of table entries */ 40 | NUM_TABLE_ENTRIES, 41 | /* reserved fields */ 42 | {0, 0,}, 43 | 44 | /* Offsets of rsc entries */ 45 | { 46 | offsetof(struct remote_resource_table, rpmsg_vdev), 47 | }, 48 | 49 | /* Virtio device entry */ 50 | { 51 | RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, 52 | NUM_VRINGS, {0, 0}, 53 | }, 54 | 55 | /* Vring rsc entry - part of vdev rsc entry */ 56 | {RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0}, 57 | {RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0}, 58 | }; 59 | 60 | void *get_resource_table (int rsc_id, int *len) 61 | { 62 | (void) rsc_id; 63 | *len = sizeof(resources); 64 | return &resources; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /apps/machine/zynqmp_r5/rsc_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * 5 | * Copyright (C) 2015 Xilinx, Inc. All rights reserved. 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | /* This file populates resource table for BM remote 11 | * for use by the Linux Master */ 12 | 13 | #ifndef RSC_TABLE_H_ 14 | #define RSC_TABLE_H_ 15 | 16 | #include 17 | #include 18 | 19 | #if defined __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define NO_RESOURCE_ENTRIES 8 24 | 25 | /* Resource table for the given remote */ 26 | struct remote_resource_table { 27 | unsigned int version; 28 | unsigned int num; 29 | unsigned int reserved[2]; 30 | unsigned int offset[NO_RESOURCE_ENTRIES]; 31 | /* rpmsg vdev entry */ 32 | struct fw_rsc_vdev rpmsg_vdev; 33 | struct fw_rsc_vdev_vring rpmsg_vring0; 34 | struct fw_rsc_vdev_vring rpmsg_vring1; 35 | }__attribute__((packed, aligned(0x100))); 36 | 37 | void *get_resource_table (int rsc_id, int *len); 38 | 39 | #if defined __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* RSC_TABLE_H_ */ 44 | -------------------------------------------------------------------------------- /apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * Copyright (c) 2017 Xilinx, Inc. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | /************************************************************************** 10 | * FILE NAME 11 | * 12 | * zynqmp_r5_a53_rproc.c 13 | * 14 | * DESCRIPTION 15 | * 16 | * This file define Xilinx ZynqMP R5 to A53 platform specific 17 | * remoteproc implementation. 18 | * 19 | **************************************************************************/ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "platform_info.h" 28 | 29 | /* IPI REGs OFFSET */ 30 | #define IPI_TRIG_OFFSET 0x00000000 /* IPI trigger register offset */ 31 | #define IPI_OBS_OFFSET 0x00000004 /* IPI observation register offset */ 32 | #define IPI_ISR_OFFSET 0x00000010 /* IPI interrupt status register offset */ 33 | #define IPI_IMR_OFFSET 0x00000014 /* IPI interrupt mask register offset */ 34 | #define IPI_IER_OFFSET 0x00000018 /* IPI interrupt enable register offset */ 35 | #define IPI_IDR_OFFSET 0x0000001C /* IPI interrupt disable register offset */ 36 | 37 | static int zynqmp_r5_a53_proc_irq_handler(int vect_id, void *data) 38 | { 39 | struct remoteproc *rproc = data; 40 | struct remoteproc_priv *prproc; 41 | unsigned int ipi_intr_status; 42 | 43 | (void)vect_id; 44 | if (!rproc) 45 | return METAL_IRQ_NOT_HANDLED; 46 | prproc = rproc->priv; 47 | ipi_intr_status = (unsigned int)metal_io_read32(prproc->ipi_io, 48 | IPI_ISR_OFFSET); 49 | if (ipi_intr_status & prproc->ipi_chn_mask) { 50 | atomic_flag_clear(&prproc->ipi_nokick); 51 | metal_io_write32(prproc->ipi_io, IPI_ISR_OFFSET, 52 | prproc->ipi_chn_mask); 53 | return METAL_IRQ_HANDLED; 54 | } 55 | return METAL_IRQ_NOT_HANDLED; 56 | } 57 | 58 | static struct remoteproc * 59 | zynqmp_r5_a53_proc_init(struct remoteproc *rproc, 60 | struct remoteproc_ops *ops, void *arg) 61 | { 62 | struct remoteproc_priv *prproc = arg; 63 | struct metal_device *ipi_dev; 64 | unsigned int irq_vect; 65 | int ret; 66 | 67 | if (!rproc || !prproc || !ops) 68 | return NULL; 69 | ret = metal_device_open(prproc->ipi_bus_name, prproc->ipi_name, 70 | &ipi_dev); 71 | if (ret) { 72 | xil_printf("failed to open ipi device: %d.\r\n", ret); 73 | return NULL; 74 | } 75 | rproc->priv = prproc; 76 | prproc->ipi_dev = ipi_dev; 77 | prproc->ipi_io = metal_device_io_region(ipi_dev, 0); 78 | if (!prproc->ipi_io) 79 | goto err1; 80 | atomic_store(&prproc->ipi_nokick, 1); 81 | rproc->ops = ops; 82 | 83 | /* Register interrupt handler and enable interrupt */ 84 | irq_vect = (uintptr_t)ipi_dev->irq_info; 85 | metal_irq_register(irq_vect, zynqmp_r5_a53_proc_irq_handler, rproc); 86 | metal_irq_enable(irq_vect); 87 | metal_io_write32(prproc->ipi_io, IPI_IER_OFFSET, 88 | prproc->ipi_chn_mask); 89 | return rproc; 90 | err1: 91 | metal_device_close(ipi_dev); 92 | return NULL; 93 | } 94 | 95 | static void zynqmp_r5_a53_proc_remove(struct remoteproc *rproc) 96 | { 97 | struct remoteproc_priv *prproc; 98 | struct metal_device *dev; 99 | 100 | if (!rproc) 101 | return; 102 | prproc = rproc->priv; 103 | metal_io_write32(prproc->ipi_io, IPI_IDR_OFFSET, prproc->ipi_chn_mask); 104 | dev = prproc->ipi_dev; 105 | if (dev) { 106 | metal_irq_disable((uintptr_t)dev->irq_info); 107 | metal_irq_unregister((uintptr_t)dev->irq_info); 108 | metal_device_close(dev); 109 | } 110 | } 111 | 112 | static void * 113 | zynqmp_r5_a53_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa, 114 | metal_phys_addr_t *da, size_t size, 115 | unsigned int attribute, struct metal_io_region **io) 116 | { 117 | struct remoteproc_mem *mem; 118 | metal_phys_addr_t lpa, lda; 119 | struct metal_io_region *tmpio; 120 | 121 | lpa = *pa; 122 | lda = *da; 123 | 124 | if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS) 125 | return NULL; 126 | if (lpa == METAL_BAD_PHYS) 127 | lpa = lda; 128 | if (lda == METAL_BAD_PHYS) 129 | lda = lpa; 130 | 131 | if (!attribute) 132 | attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW; 133 | mem = metal_allocate_memory(sizeof(*mem)); 134 | if (!mem) 135 | return NULL; 136 | tmpio = metal_allocate_memory(sizeof(*tmpio)); 137 | if (!tmpio) { 138 | metal_free_memory(mem); 139 | return NULL; 140 | } 141 | remoteproc_init_mem(mem, NULL, lpa, lda, size, tmpio); 142 | /* va is the same as pa in this platform */ 143 | metal_io_init(tmpio, (void *)lpa, &mem->pa, size, 144 | sizeof(metal_phys_addr_t)<<3, attribute, NULL); 145 | remoteproc_add_mem(rproc, mem); 146 | *pa = lpa; 147 | *da = lda; 148 | if (io) 149 | *io = tmpio; 150 | return metal_io_phys_to_virt(tmpio, mem->pa); 151 | } 152 | 153 | static int zynqmp_r5_a53_proc_notify(struct remoteproc *rproc, uint32_t id) 154 | { 155 | struct remoteproc_priv *prproc; 156 | 157 | (void)id; 158 | if (!rproc) 159 | return -1; 160 | prproc = rproc->priv; 161 | 162 | /* TODO: use IPI driver instead and pass ID */ 163 | metal_io_write32(prproc->ipi_io, IPI_TRIG_OFFSET, 164 | prproc->ipi_chn_mask); 165 | return 0; 166 | } 167 | 168 | /* processor operations from r5 to a53. It defines 169 | * notification operation and remote processor managementi operations. */ 170 | struct remoteproc_ops zynqmp_r5_a53_proc_ops = { 171 | .init = zynqmp_r5_a53_proc_init, 172 | .remove = zynqmp_r5_a53_proc_remove, 173 | .mmap = zynqmp_r5_a53_proc_mmap, 174 | .notify = zynqmp_r5_a53_proc_notify, 175 | .start = NULL, 176 | .stop = NULL, 177 | .shutdown = NULL, 178 | }; 179 | -------------------------------------------------------------------------------- /apps/system/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_SYSTEM}/CMakeLists.txt") 2 | add_subdirectory (${PROJECT_SYSTEM}) 3 | endif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_SYSTEM}/CMakeLists.txt") 4 | -------------------------------------------------------------------------------- /apps/system/generic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory (machine) 2 | -------------------------------------------------------------------------------- /apps/system/generic/machine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE}/CMakeLists.txt") 2 | add_subdirectory (${PROJECT_MACHINE}) 3 | endif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE}/CMakeLists.txt") 4 | -------------------------------------------------------------------------------- /apps/system/generic/machine/zynq7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (APP_COMMON_SOURCES helper.c) 2 | 3 | set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_remote.ld") 4 | 5 | set_property (GLOBAL PROPERTY APP_LINKER_OPT "-Wl,-build-id=none -specs=${CMAKE_CURRENT_SOURCE_DIR}/Xilinx.spec -T\"${_linker_script}\"") 6 | 7 | find_path(XIL_INCLUDE_DIR NAMES xparameters.h PATHS ${CMAKE_FIND_ROOT_PATH}) 8 | collect (PROJECT_INC_DIRS "${XIL_INCLUDE_DIR}") 9 | 10 | find_library(LIBXIL_LIB NAMES xil PATHS ${CMAKE_FIND_ROOT_PATH}) 11 | get_filename_component(LIBXIL_LIB_DIR ${LIBXIL_LIB} DIRECTORY) 12 | collect(PROJECT_LIB_DIRS ${LIBXIL_LIB_DIR}) 13 | 14 | collect(PROJECT_LIB_DEPS xil) 15 | collect(PROJECT_LIB_DEPS c) 16 | collect(PROJECT_LIB_DEPS m) 17 | -------------------------------------------------------------------------------- /apps/system/generic/machine/zynq7/Xilinx.spec: -------------------------------------------------------------------------------- 1 | *startfile: 2 | crti%O%s crtbegin%O%s 3 | -------------------------------------------------------------------------------- /apps/system/generic/machine/zynq7/helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2015 Xilinx, Inc. All rights reserved. 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | #include "xparameters.h" 11 | #include "xil_exception.h" 12 | #include "xil_printf.h" 13 | #include "xscugic.h" 14 | #include "xil_cache.h" 15 | #include 16 | #include 17 | #include "platform_info.h" 18 | 19 | 20 | #define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID 21 | 22 | static XScuGic xInterruptController; 23 | 24 | /* Interrupt Controller setup */ 25 | static int app_gic_initialize(void) 26 | { 27 | u32 Status; 28 | XScuGic_Config *IntcConfig; /* The configuration parameters of the interrupt controller */ 29 | 30 | Xil_ExceptionDisable(); 31 | 32 | /* 33 | * Initialize the interrupt controller driver 34 | */ 35 | IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); 36 | if (NULL == IntcConfig) { 37 | return XST_FAILURE; 38 | } 39 | 40 | Status = XScuGic_CfgInitialize(&xInterruptController, IntcConfig, 41 | IntcConfig->CpuBaseAddress); 42 | if (Status != XST_SUCCESS) { 43 | return XST_FAILURE; 44 | } 45 | 46 | /* 47 | * Register the interrupt handler to the hardware interrupt handling 48 | * logic in the ARM processor. 49 | */ 50 | Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, 51 | (Xil_ExceptionHandler)XScuGic_InterruptHandler, 52 | &xInterruptController); 53 | 54 | /* Disable the interrupt before enabling exception to avoid interrupts 55 | * received before exception is enabled. 56 | */ 57 | XScuGic_Disable(&xInterruptController, SGI_NOTIFICATION); 58 | 59 | Xil_ExceptionEnable(); 60 | 61 | /* Connect notificaiton interrupt ID with ISR */ 62 | XScuGic_Connect(&xInterruptController, SGI_NOTIFICATION, 63 | (Xil_ExceptionHandler)metal_xlnx_irq_isr, 64 | (void *)SGI_NOTIFICATION); 65 | 66 | return 0; 67 | } 68 | 69 | /* Main hw machinery initialization entry point, called from main()*/ 70 | /* return 0 on success */ 71 | int init_system(void) 72 | { 73 | int ret; 74 | struct metal_init_params metal_param = METAL_INIT_DEFAULTS; 75 | 76 | /* Low level abstraction layer for openamp initialization */ 77 | metal_init(&metal_param); 78 | 79 | /* configure the global interrupt controller */ 80 | app_gic_initialize(); 81 | 82 | /* Initialize metal Xilinx IRQ controller */ 83 | ret = metal_xlnx_irq_init(); 84 | if (ret) { 85 | xil_printf("%s: Xilinx metal IRQ controller init failed.\r\n", 86 | __func__); 87 | } 88 | 89 | return ret; 90 | } 91 | 92 | void cleanup_system() 93 | { 94 | metal_finish(); 95 | 96 | Xil_DCacheDisable(); 97 | Xil_ICacheDisable(); 98 | Xil_DCacheInvalidate(); 99 | Xil_ICacheInvalidate(); 100 | } 101 | -------------------------------------------------------------------------------- /apps/system/generic/machine/zynqmp_r5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (APP_COMMON_SOURCES helper.c) 2 | 3 | set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_remote.ld") 4 | set_property (GLOBAL PROPERTY APP_LINKER_OPT "-T\"${_linker_script}\"") 5 | set (_linker_large_text_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_large_text.ld") 6 | set_property (GLOBAL PROPERTY APP_LINKER_LARGE_TEXT_OPT "-T\"${_linker_large_text_script}\"") 7 | 8 | find_path(XIL_INCLUDE_DIR NAMES xparameters.h PATHS ${CMAKE_FIND_ROOT_PATH}) 9 | collect (PROJECT_INC_DIRS "${XIL_INCLUDE_DIR}") 10 | 11 | find_library(LIBXIL_LIB NAMES xil PATHS ${CMAKE_FIND_ROOT_PATH}) 12 | get_filename_component(LIBXIL_LIB_DIR ${LIBXIL_LIB} DIRECTORY) 13 | collect(PROJECT_LIB_DIRS ${LIBXIL_LIB_DIR}) 14 | 15 | # check PM API for certain headers and set client version based 16 | # on which functions are found 17 | find_path(VERSION_1_PM_CLIENT "pm_api_sys.h") 18 | if (NOT VERSION_1_PM_CLIENT) 19 | # check for version 2 20 | find_path(VERSION_2_PM_CLIENT "xpm_client_api.h") 21 | if (NOT VERSION_2_PM_CLIENT) 22 | message(FATAL_ERROR "PM Client not found") 23 | else() 24 | collect (APP_EXTRA_C_FLAGS " -DVERSION_2_PM_CLIENT ") 25 | endif() 26 | else() 27 | collect (APP_EXTRA_C_FLAGS " -DVERSION_1_PM_CLIENT ") 28 | endif() 29 | 30 | collect(PROJECT_LIB_DEPS xil) 31 | collect(PROJECT_LIB_DEPS c) 32 | collect(PROJECT_LIB_DEPS m) 33 | find_library(XILMEM_LIB NAMES xilmem PATHS ${CMAKE_FIND_ROOT_PATH}) 34 | if(XILMEM_LIB) 35 | collect (PROJECT_LIB_DEPS xilmem) 36 | endif(XILMEM_LIB) 37 | 38 | if (VERSION_2_PM_CLIENT) 39 | find_library(HAS_PM_LIB NAMES xillibpm PATHS ${CMAKE_FIND_ROOT_PATH}) 40 | collect (PROJECT_LIB_DEPS xillibpm) 41 | else() 42 | find_library(HAS_PM_LIB NAMES xilpm PATHS ${CMAKE_FIND_ROOT_PATH}) 43 | collect (PROJECT_LIB_DEPS xilpm) 44 | endif(VERSION_2_PM_CLIENT) 45 | -------------------------------------------------------------------------------- /apps/system/generic/machine/zynqmp_r5/helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2015 Xilinx, Inc. All rights reserved. 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | #include "xparameters.h" 11 | #include "xil_exception.h" 12 | #include "xil_printf.h" 13 | #include "xscugic.h" 14 | #include "xil_cache.h" 15 | #include 16 | #include 17 | #include "platform_info.h" 18 | 19 | #define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID 20 | 21 | static XScuGic xInterruptController; 22 | 23 | /* Interrupt Controller setup */ 24 | static int app_gic_initialize(void) 25 | { 26 | uint32_t status; 27 | XScuGic_Config *int_ctrl_config; /* interrupt controller configuration params */ 28 | uint32_t int_id; 29 | uint32_t mask_cpu_id = ((u32)0x1 << XPAR_CPU_ID); 30 | uint32_t target_cpu; 31 | 32 | mask_cpu_id |= mask_cpu_id << 8U; 33 | mask_cpu_id |= mask_cpu_id << 16U; 34 | 35 | Xil_ExceptionDisable(); 36 | 37 | /* 38 | * Initialize the interrupt controller driver 39 | */ 40 | int_ctrl_config = XScuGic_LookupConfig(INTC_DEVICE_ID); 41 | if (NULL == int_ctrl_config) { 42 | return XST_FAILURE; 43 | } 44 | 45 | status = XScuGic_CfgInitialize(&xInterruptController, int_ctrl_config, 46 | int_ctrl_config->CpuBaseAddress); 47 | if (status != XST_SUCCESS) { 48 | return XST_FAILURE; 49 | } 50 | 51 | /* Only associate interrupt needed to this CPU */ 52 | for (int_id = 32U; int_id 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | int init_system() 19 | { 20 | struct metal_init_params metal_param = METAL_INIT_DEFAULTS; 21 | 22 | metal_param.log_level = LOG_DEBUG; 23 | metal_init(&metal_param); 24 | 25 | return 0; 26 | } 27 | 28 | void cleanup_system() 29 | { 30 | metal_finish(); 31 | } 32 | -------------------------------------------------------------------------------- /apps/system/linux/machine/generic/platform_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Xilinx, Inc. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | /* This file populates resource table for BM remote 8 | * for use by the Linux Master */ 9 | 10 | #ifndef PLATFORM_INFO_H 11 | #define PLATFORM_INFO_H 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /** 22 | * platform_init - initialize the platform 23 | * 24 | * It will initialize the platform. 25 | * 26 | * @argc: number of arguments 27 | * @argv: array of the input arguements 28 | * @platform: pointer to store the platform data pointer 29 | * 30 | * return 0 for success or negative value for failure 31 | */ 32 | int platform_init(int argc, char *argv[], void **platform); 33 | 34 | /** 35 | * platform_create_rpmsg_vdev - create rpmsg vdev 36 | * 37 | * It will create rpmsg virtio device, and returns the rpmsg virtio 38 | * device pointer. 39 | * 40 | * @platform: pointer to the private data 41 | * @vdev_index: index of the virtio device, there can more than one vdev 42 | * on the platform. 43 | * @role: virtio master or virtio slave of the vdev 44 | * @rst_cb: virtio device reset callback 45 | * @ns_bind_cb: rpmsg name service bind callback 46 | * 47 | * return pointer to the rpmsg virtio device 48 | */ 49 | struct rpmsg_device * 50 | platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, 51 | unsigned int role, 52 | void (*rst_cb)(struct virtio_device *vdev), 53 | rpmsg_ns_bind_cb ns_bind_cb); 54 | 55 | /** 56 | * platform_poll - platform poll function 57 | * 58 | * @platform: pointer to the platform 59 | * 60 | * return negative value for errors, otherwise 0. 61 | */ 62 | int platform_poll(void *platform); 63 | 64 | /** 65 | * platform_release_rpmsg_vdev - release rpmsg virtio device 66 | * 67 | * @rpdev: pointer to the rpmsg device 68 | */ 69 | void platform_release_rpmsg_vdev(struct rpmsg_device *rpdev); 70 | 71 | /** 72 | * platform_cleanup - clean up the platform resource 73 | * 74 | * @platform: pointer to the platform 75 | */ 76 | void platform_cleanup(void *platform); 77 | 78 | #if defined __cplusplus 79 | } 80 | #endif 81 | 82 | #endif /* PLATFORM_INFO_H */ 83 | -------------------------------------------------------------------------------- /apps/system/linux/machine/generic/rsc_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * Copyright (c) 2016 Xilinx, Inc. All rights reserved. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | /* This file populates resource table for BM remote 10 | * for use by the Linux Master */ 11 | 12 | #include 13 | #include "rsc_table.h" 14 | 15 | #define RPMSG_IPU_C0_FEATURES 1 16 | 17 | /* VirtIO rpmsg device id */ 18 | #define VIRTIO_ID_RPMSG_ 7 19 | 20 | /* Remote supports Name Service announcement */ 21 | #define VIRTIO_RPMSG_F_NS 0 22 | 23 | #define NUM_VRINGS 0x02 24 | #define VRING_ALIGN 0x1000 25 | #define RING_TX 0x00004000 26 | #define RING_RX 0x00008000 27 | #define VRING_SIZE 256 28 | 29 | #define NUM_TABLE_ENTRIES 1 30 | 31 | struct remote_resource_table resources = { 32 | /* Version */ 33 | 1, 34 | 35 | /* NUmber of table entries */ 36 | NUM_TABLE_ENTRIES, 37 | /* reserved fields */ 38 | {0, 0,}, 39 | 40 | /* Offsets of rsc entries */ 41 | { 42 | offsetof(struct remote_resource_table, rpmsg_vdev), 43 | }, 44 | 45 | /* Virtio device entry */ 46 | { 47 | RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, 48 | NUM_VRINGS, {0, 0}, 49 | }, 50 | 51 | /* Vring rsc entry - part of vdev rsc entry */ 52 | {RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0}, 53 | {RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0}, 54 | }; 55 | 56 | void *get_resource_table (int rsc_id, int *len) 57 | { 58 | (void) rsc_id; 59 | *len = sizeof(resources); 60 | return &resources; 61 | } 62 | -------------------------------------------------------------------------------- /apps/system/linux/machine/generic/rsc_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * Copyright (c) 2016 Xilinx, Inc. All rights reserved. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | /* This file populates resource table for BM remote 10 | * for use by the Linux Master */ 11 | 12 | #ifndef RSC_TABLE_H_ 13 | #define RSC_TABLE_H_ 14 | 15 | #include 16 | #include 17 | 18 | #if defined __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | #define NO_RESOURCE_ENTRIES 1 23 | 24 | /* Resource table for the given remote */ 25 | struct remote_resource_table { 26 | unsigned int version; 27 | unsigned int num; 28 | unsigned int reserved[2]; 29 | unsigned int offset[NO_RESOURCE_ENTRIES]; 30 | /* rpmsg vdev entry */ 31 | struct fw_rsc_vdev rpmsg_vdev; 32 | struct fw_rsc_vdev_vring rpmsg_vring0; 33 | struct fw_rsc_vdev_vring rpmsg_vring1; 34 | }; 35 | 36 | void *get_resource_table (int rsc_id, int *len); 37 | 38 | #if defined __cplusplus 39 | } 40 | #endif 41 | 42 | #endif /* RSC_TABLE_H_ */ 43 | -------------------------------------------------------------------------------- /apps/system/linux/machine/zynqmp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (APP_COMMON_SOURCES helper.c) 2 | 3 | -------------------------------------------------------------------------------- /apps/system/linux/machine/zynqmp/helper.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (c) 2014, Mentor Graphics Corporation 4 | * All rights reserved. 5 | * 6 | * Copyright (c) 2015 Xilinx, Inc. All rights reserved. 7 | * 8 | * SPDX-License-Identifier: BSD-3-Clause 9 | */ 10 | #include 11 | #include 12 | #include 13 | 14 | int init_system() 15 | { 16 | struct metal_init_params metal_param = METAL_INIT_DEFAULTS; 17 | 18 | metal_init(&metal_param); 19 | 20 | return 0; 21 | } 22 | 23 | void cleanup_system() 24 | { 25 | metal_finish(); 26 | } 27 | -------------------------------------------------------------------------------- /apps/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory (msg) 3 | -------------------------------------------------------------------------------- /apps/tests/msg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS} -fdata-sections -ffunction-sections") 3 | set (_fw_dir "${APPS_SHARE_DIR}") 4 | 5 | collector_list (_list PROJECT_INC_DIRS) 6 | collector_list (_app_list APP_INC_DIRS) 7 | include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR}) 8 | 9 | collector_list (_list PROJECT_LIB_DIRS) 10 | collector_list (_app_list APP_LIB_DIRS) 11 | link_directories (${_list} ${_app_list}) 12 | 13 | get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT) 14 | collector_list (_deps PROJECT_LIB_DEPS) 15 | 16 | set (OPENAMP_LIB open_amp) 17 | 18 | foreach (_app msg-test-rpmsg-ping msg-test-rpmsg-update msg-test-rpmsg-flood-ping) 19 | collector_list (_sources APP_COMMON_SOURCES) 20 | if (${_app} STREQUAL "msg-test-rpmsg-ping") 21 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-ping.c") 22 | elseif (${_app} STREQUAL "msg-test-rpmsg-update") 23 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-update.c") 24 | elseif (${_app} STREQUAL "msg-test-rpmsg-flood-ping") 25 | list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-flood-ping.c") 26 | endif (${_app} STREQUAL "msg-test-rpmsg-ping") 27 | 28 | if (WITH_SHARED_LIB) 29 | add_executable (${_app}-shared ${_sources}) 30 | target_link_libraries (${_app}-shared ${OPENAMP_LIB}-shared ${_deps}) 31 | install (TARGETS ${_app}-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 32 | endif (WITH_SHARED_LIB) 33 | 34 | if (WITH_STATIC_LIB) 35 | if (${PROJECT_SYSTEM} STREQUAL "linux") 36 | add_executable (${_app}-static ${_sources}) 37 | target_link_libraries (${_app}-static ${OPENAMP_LIB}-static ${_deps}) 38 | install (TARGETS ${_app}-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 39 | else (${PROJECT_SYSTEM}) 40 | add_executable (${_app}.out ${_sources}) 41 | set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}") 42 | 43 | target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections ${_linker_opt} -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group) 44 | 45 | install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 46 | endif (${PROJECT_SYSTEM} STREQUAL "linux" ) 47 | endif (WITH_STATIC_LIB) 48 | endforeach(_app) 49 | -------------------------------------------------------------------------------- /apps/tests/msg/rpmsg-ping.h: -------------------------------------------------------------------------------- 1 | #ifndef RPMSG_PING_H 2 | #define RPMSG_PING_H 3 | 4 | #define RPMSG_SERVICE_NAME "rpmsg-openamp-demo-channel" 5 | 6 | #endif /* RPMSG_PING_H */ 7 | -------------------------------------------------------------------------------- /apps/tests/msg/rpmsg-update.c: -------------------------------------------------------------------------------- 1 | /* This is a sample demonstration application that showcases usage of rpmsg 2 | This application is meant to run on the remote CPU running baremetal code. 3 | This application echoes back data that was sent to it by the master core. */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "platform_info.h" 9 | #include "rpmsg-ping.h" 10 | 11 | #define SHUTDOWN_MSG 0xEF56A55A 12 | 13 | #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) 14 | //#define LPRINTF(format, ...) 15 | #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) 16 | 17 | static struct rpmsg_endpoint lept; 18 | static int shutdown_req = 0; 19 | 20 | /* External functions */ 21 | extern int init_system(void); 22 | extern void cleanup_system(void); 23 | 24 | /*-----------------------------------------------------------------------------* 25 | * RPMSG endpoint callbacks 26 | *-----------------------------------------------------------------------------*/ 27 | static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, 28 | uint32_t src, void *priv) 29 | { 30 | (void)priv; 31 | (void)src; 32 | 33 | /* On reception of a shutdown we signal the application to terminate */ 34 | if ((*(unsigned int *)data) == SHUTDOWN_MSG) { 35 | LPRINTF("shutdown message is received.\r\n"); 36 | shutdown_req = 1; 37 | return RPMSG_SUCCESS; 38 | } 39 | 40 | /* Send data back to master */ 41 | while (1) { 42 | int ret; 43 | 44 | ret = rpmsg_send(ept, data, len); 45 | if (ret == RPMSG_ERR_NO_BUFF) { 46 | LPRINTF("%s, wait for buffer\r\n", __func__); 47 | continue; 48 | } else { 49 | if (ret < 0) 50 | LPERROR("rpmsg_send, size %lu failed %d\r\n", 51 | (unsigned long)len, ret); 52 | break; 53 | } 54 | } 55 | return RPMSG_SUCCESS; 56 | } 57 | 58 | static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) 59 | { 60 | (void)ept; 61 | LPRINTF("unexpected Remote endpoint destroy\r\n"); 62 | shutdown_req = 1; 63 | } 64 | 65 | /*-----------------------------------------------------------------------------* 66 | * Application 67 | *-----------------------------------------------------------------------------*/ 68 | int app(struct rpmsg_device *rdev, void *priv) 69 | { 70 | int ret; 71 | 72 | /* Initialize RPMSG framework */ 73 | LPRINTF("Try to create rpmsg endpoint.\r\n"); 74 | 75 | ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, 76 | 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, 77 | rpmsg_service_unbind); 78 | if (ret) { 79 | LPERROR("Failed to create endpoint.\r\n"); 80 | return -1; 81 | } 82 | 83 | LPRINTF("Successfully created rpmsg endpoint.\r\n"); 84 | while(1) { 85 | platform_poll(priv); 86 | /* we got a shutdown request, exit */ 87 | if (shutdown_req) { 88 | break; 89 | } 90 | } 91 | rpmsg_destroy_ept(&lept); 92 | 93 | return 0; 94 | } 95 | 96 | /*-----------------------------------------------------------------------------* 97 | * Application entry point 98 | *-----------------------------------------------------------------------------*/ 99 | int main(int argc, char *argv[]) 100 | { 101 | void *platform; 102 | struct rpmsg_device *rpdev; 103 | int ret; 104 | 105 | LPRINTF("Starting application...\r\n"); 106 | 107 | /* Initialize platform */ 108 | ret = platform_init(argc, argv, &platform); 109 | if (ret) { 110 | LPERROR("Failed to initialize platform.\r\n"); 111 | ret = -1; 112 | } else { 113 | rpdev = platform_create_rpmsg_vdev(platform, 0, 114 | VIRTIO_DEV_SLAVE, 115 | NULL, NULL); 116 | if (!rpdev) { 117 | LPERROR("Failed to create rpmsg virtio device.\r\n"); 118 | ret = -1; 119 | } else { 120 | app(rpdev, platform); 121 | platform_release_rpmsg_vdev(rpdev); 122 | ret = 0; 123 | } 124 | } 125 | 126 | LPRINTF("Stopping application...\r\n"); 127 | platform_cleanup(platform); 128 | 129 | return ret; 130 | } 131 | -------------------------------------------------------------------------------- /cmake/collect.cmake: -------------------------------------------------------------------------------- 1 | function (collector_create name base) 2 | set_property (GLOBAL PROPERTY "COLLECT_${name}_LIST") 3 | set_property (GLOBAL PROPERTY "COLLECT_${name}_BASE" "${base}") 4 | endfunction (collector_create) 5 | 6 | function (collector_list var name) 7 | get_property (_list GLOBAL PROPERTY "COLLECT_${name}_LIST") 8 | set (${var} "${_list}" PARENT_SCOPE) 9 | endfunction (collector_list) 10 | 11 | function (collector_base var name) 12 | get_property (_base GLOBAL PROPERTY "COLLECT_${name}_BASE") 13 | set (${var} "${_base}" PARENT_SCOPE) 14 | endfunction (collector_base) 15 | 16 | function (collect name) 17 | collector_base (_base ${name}) 18 | string(COMPARE NOTEQUAL "${_base}" "" _is_rel) 19 | set (_list) 20 | foreach (s IN LISTS ARGN) 21 | if (_is_rel) 22 | get_filename_component (s "${s}" ABSOLUTE) 23 | file (RELATIVE_PATH s "${_base}" "${s}") 24 | else (_is_rel) 25 | get_filename_component (ts "${s}" ABSOLUTE) 26 | if (EXISTS "${ts}") 27 | set (s "${ts}") 28 | endif (EXISTS "${ts}") 29 | endif (_is_rel) 30 | list (APPEND _list "${s}") 31 | endforeach () 32 | set_property (GLOBAL APPEND PROPERTY "COLLECT_${name}_LIST" "${_list}") 33 | endfunction (collect) 34 | 35 | # Create global collectors 36 | collector_create (PROJECT_INC_DIRS "") 37 | collector_create (PROJECT_LIB_DIRS "") 38 | collector_create (PROJECT_LIB_DEPS "") 39 | 40 | # vim: expandtab:ts=2:sw=2:smartindent 41 | -------------------------------------------------------------------------------- /cmake/depends.cmake: -------------------------------------------------------------------------------- 1 | if (WITH_LIBMETAL_FIND) 2 | find_package (Libmetal REQUIRED) 3 | collect (PROJECT_INC_DIRS "${LIBMETAL_INCLUDE_DIR}") 4 | collect (PROJECT_LIB_DIRS "${LIBMETAL_LIB_DIR}") 5 | collect (PROJECT_LIB_DEPS "${LIBMETAL_LIB}") 6 | endif (WITH_LIBMETAL_FIND) 7 | 8 | if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") 9 | check_include_files (stdatomic.h HAVE_STDATOMIC_H) 10 | check_include_files (fcntl.h HAVE_FCNTL_H) 11 | else ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") 12 | set (_saved_cmake_required_flags ${CMAKE_REQUIRED_FLAGS}) 13 | set (CMAKE_REQUIRED_FLAGS "-c") 14 | check_include_files (stdatomic.h HAVE_STDATOMIC_H) 15 | check_include_files (fcntl.h HAVE_FCNTL_H) 16 | set (CMAKE_REQUIRED_FLAGS ${_saved_cmake_required_flags}) 17 | endif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") 18 | 19 | if (NOT HAVE_FCNTL_H) 20 | unset (WITH_PROXY CACHE) 21 | endif (NOT HAVE_FCNTL_H) 22 | 23 | # vim: expandtab:ts=2:sw=2:smartindent 24 | -------------------------------------------------------------------------------- /cmake/modules/FindLibmetal.cmake: -------------------------------------------------------------------------------- 1 | # FindLibmetal 2 | # -------- 3 | # 4 | # Find Libmetal 5 | # 6 | # Find the native Libmetal includes and library this module defines 7 | # 8 | # :: 9 | # 10 | # LIBMETAL_INCLUDE_DIR, where to find metal/sysfs.h, etc. 11 | # LIBSYSFS_LIB_DIR, where to find libmetal library. 12 | 13 | # FIX ME, CMAKE_FIND_ROOT_PATH doesn't work 14 | # even use the following 15 | # set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) 16 | # set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) 17 | # set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) 18 | find_path(LIBMETAL_INCLUDE_DIR NAMES metal/sys.h PATHS ${CMAKE_FIND_ROOT_PATH}) 19 | find_library(LIBMETAL_LIB NAMES metal PATHS ${CMAKE_FIND_ROOT_PATH}) 20 | get_filename_component(LIBMETAL_LIB_DIR ${LIBMETAL_LIB} DIRECTORY) 21 | 22 | # handle the QUIETLY and REQUIRED arguments and set HUGETLBFS_FOUND to TRUE if 23 | # all listed variables are TRUE 24 | include (FindPackageHandleStandardArgs) 25 | FIND_PACKAGE_HANDLE_STANDARD_ARGS (LIBMETAL DEFAULT_MSG LIBMETAL_LIB LIBMETAL_INCLUDE_DIR) 26 | 27 | if (LIBMETAL_FOUND) 28 | set (LIBMETAL_LIBS ${LIBMETAL_LIB}) 29 | endif (LIBMETAL_FOUND) 30 | 31 | mark_as_advanced (LIBMETAL_LIB LIBMETAL_INCLUDE_DIR LIBMETAL_LIB_DIR) 32 | -------------------------------------------------------------------------------- /cmake/options.cmake: -------------------------------------------------------------------------------- 1 | set (PROJECT_VER_MAJOR 0) 2 | set (PROJECT_VER_MINOR 1) 3 | set (PROJECT_VER_PATCH 0) 4 | set (PROJECT_VER 0.1.0) 5 | 6 | if (NOT CMAKE_BUILD_TYPE) 7 | set (CMAKE_BUILD_TYPE Debug) 8 | endif (NOT CMAKE_BUILD_TYPE) 9 | 10 | if (NOT CMAKE_INSTALL_LIBDIR) 11 | set (CMAKE_INSTALL_LIBDIR "lib") 12 | endif (NOT CMAKE_INSTALL_LIBDIR) 13 | 14 | if (NOT CMAKE_INSTALL_BINDIR) 15 | set (CMAKE_INSTALL_BINDIR "bin") 16 | endif (NOT CMAKE_INSTALL_BINDIR) 17 | 18 | set (_host "${CMAKE_HOST_SYSTEM_NAME}/${CMAKE_HOST_SYSTEM_PROCESSOR}") 19 | message ("-- Host: ${_host}") 20 | 21 | set (_target "${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}") 22 | message ("-- Target: ${_target}") 23 | 24 | if (NOT DEFINED MACHINE) 25 | set (MACHINE "Generic") 26 | endif (NOT DEFINED MACHINE) 27 | message ("-- Machine: ${MACHINE}") 28 | 29 | string (TOLOWER ${CMAKE_SYSTEM_NAME} PROJECT_SYSTEM) 30 | string (TOUPPER ${CMAKE_SYSTEM_NAME} PROJECT_SYSTEM_UPPER) 31 | string (TOLOWER ${CMAKE_SYSTEM_PROCESSOR} PROJECT_PROCESSOR) 32 | string (TOUPPER ${CMAKE_SYSTEM_PROCESSOR} PROJECT_PROCESSOR_UPPER) 33 | string (TOLOWER ${MACHINE} PROJECT_MACHINE) 34 | string (TOUPPER ${MACHINE} PROJECT_MACHINE_UPPER) 35 | 36 | # Select which components are in the openamp lib 37 | option (WITH_PROXY "Build with proxy(access device controlled by other processor)" ON) 38 | option (WITH_APPS "Build with sample applicaitons" OFF) 39 | option (WITH_PROXY_APPS "Build with proxy sample applicaitons" OFF) 40 | if (WITH_APPS) 41 | if (WITH_PROXY) 42 | set (WITH_PROXY_APPS ON) 43 | endif (WITH_PROXY) 44 | endif (WITH_APPS) 45 | 46 | # LOAD_FW only allowed for R5, otherwise turn off 47 | if (NOT ${MACHINE} STREQUAL "zynqmp_r5") 48 | set (WITH_LOAD_FW OFF) 49 | endif(NOT ${MACHINE} STREQUAL "zynqmp_r5") 50 | 51 | option (WITH_VIRTIO_MASTER "Build with virtio master enabled" ON) 52 | option (WITH_VIRTIO_SLAVE "Build with virtio slave enabled" ON) 53 | 54 | if (NOT WITH_VIRTIO_MASTER) 55 | add_definitions(-DVIRTIO_SLAVE_ONLY) 56 | endif (NOT WITH_VIRTIO_MASTER) 57 | 58 | if (NOT WITH_VIRTIO_SLAVE) 59 | add_definitions(-DVIRTIO_MASTER_ONLY) 60 | endif (NOT WITH_VIRTIO_SLAVE) 61 | 62 | # Set the complication flags 63 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") 64 | 65 | option (WITH_STATIC_LIB "Build with a static library" ON) 66 | 67 | if ("${PROJECT_SYSTEM}" STREQUAL "linux") 68 | option (WITH_SHARED_LIB "Build with a shared library" ON) 69 | endif ("${PROJECT_SYSTEM}" STREQUAL "linux") 70 | 71 | if (WITH_ZEPHYR) 72 | option (WITH_ZEPHYR_LIB "Build open-amp as a zephyr library" OFF) 73 | endif (WITH_ZEPHYR) 74 | 75 | option (WITH_LIBMETAL_FIND "Check Libmetal library can be found" ON) 76 | 77 | message ("-- C_FLAGS : ${CMAKE_C_FLAGS}") 78 | # vim: expandtab:ts=2:sw=2:smartindent 79 | -------------------------------------------------------------------------------- /cmake/platforms/cross_generic_gcc.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_NAME "Generic" CACHE STRING "") 2 | 3 | include (CMakeForceCompiler) 4 | 5 | CMAKE_FORCE_C_COMPILER ("${CROSS_PREFIX}gcc" GNU) 6 | CMAKE_FORCE_CXX_COMPILER ("${CROSS_PREFIX}g++" GNU) 7 | 8 | set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "") 9 | set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "") 10 | set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "") 11 | 12 | # vim: expandtab:ts=2:sw=2:smartindent 13 | -------------------------------------------------------------------------------- /cmake/platforms/cross_linux_gcc.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_NAME "Linux") 2 | set (CMAKE_C_COMPILER "${CROSS_PREFIX}gcc") 3 | set (CMAKE_CXX_COMPILER "${CROSS_PREFIX}g++") 4 | 5 | set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 6 | set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) 7 | set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) 8 | 9 | # vim: expandtab:ts=2:sw=2:smartindent 10 | -------------------------------------------------------------------------------- /cmake/platforms/zynq7_generic.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "") 2 | set (MACHINE "zynq7" CACHE STRING "") 3 | set (CROSS_PREFIX "arm-none-eabi-" CACHE STRING "") 4 | set (CMAKE_C_FLAGS "-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard" CACHE STRING "") 5 | 6 | include (cross_generic_gcc) 7 | 8 | # vim: expandtab:ts=2:sw=2:smartindent 9 | -------------------------------------------------------------------------------- /cmake/platforms/zynq7_linux.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_PROCESSOR "arm") 2 | set (CROSS_PREFIX "arm-xilinx-linux-gnueabi-") 3 | 4 | include (cross-linux-gcc) 5 | 6 | # vim: expandtab:ts=2:sw=2:smartindent 7 | -------------------------------------------------------------------------------- /cmake/platforms/zynqmp_a53_generic.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_PROCESSOR "arm64") 2 | set (CROSS_PREFIX "aarch64-none-elf-") 3 | 4 | include (cross_generic_gcc) 5 | 6 | # vim: expandtab:ts=2:sw=2:smartindent 7 | -------------------------------------------------------------------------------- /cmake/platforms/zynqmp_linux.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_PROCESSOR "arm64") 2 | set (CROSS_PREFIX "aarch64-linux-gnu-") 3 | set (MACHINE "zynqmp" CACHE STRING "") 4 | 5 | include (cross_linux_gcc) 6 | 7 | # vim: expandtab:ts=2:sw=2:smartindent 8 | -------------------------------------------------------------------------------- /cmake/platforms/zynqmp_r5_generic.cmake: -------------------------------------------------------------------------------- 1 | set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "") 2 | set (MACHINE "zynqmp_r5" CACHE STRING "") 3 | set (CROSS_PREFIX "armr5-none-eabi-" CACHE STRING "") 4 | 5 | # Xilinx SDK version earlier than 2017.2 use mfloat-abi=soft by default to generat libxil 6 | set (CMAKE_C_FLAGS "-mfloat-abi=hard -mfpu=vfpv3-d16 -mcpu=cortex-r5" CACHE STRING "") 7 | 8 | include (cross_generic_gcc) 9 | 10 | # vim: expandtab:ts=2:sw=2:smartindent 11 | -------------------------------------------------------------------------------- /cmake/syscheck.cmake: -------------------------------------------------------------------------------- 1 | # use "Generic" as CMAKE_SYSTEM_NAME 2 | 3 | if (WITH_ZEPHYR) 4 | set (CMAKE_SYSTEM_NAME "Generic" CACHE STRING "") 5 | string (TOLOWER "Zephyr" PROJECT_SYSTEM) 6 | string (TOUPPER "Zephyr" PROJECT_SYSTEM_UPPER) 7 | if (NOT WITH_ZEPHYR_LIB) 8 | include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) 9 | endif () 10 | if (CONFIG_CPU_CORTEX_M) 11 | set (MACHINE "cortexm" CACHE STRING "") 12 | endif (CONFIG_CPU_CORTEX_M) 13 | endif (WITH_ZEPHYR) 14 | -------------------------------------------------------------------------------- /docs/apps/echo_test/README.md: -------------------------------------------------------------------------------- 1 | 2 | # echo_test 3 | This readme is about the OpenAMP echo_test demo. 4 | The echo_test is about one processor sends message to the other one, and the other one echo back the message. The processor which sends the message will verify the echo message. 5 | 6 | For now, it implements Linux sends the message, and the baremetal echos back. 7 | 8 | ## Compilation 9 | 10 | ### Baremetal Compilation 11 | Option `WITH_ECHO_TEST` is to control if the application will be built. 12 | By default this option is `ON` when `WITH_APPS` is on. 13 | 14 | Here is an example: 15 | 16 | ``` 17 | $ cmake ../open-amp -DCMAKE_TOOLCHAIN_FILE=zynq7_generic -DWITH_OBSOLETE=on -DWITH_APPS=ON 18 | ``` 19 | 20 | ### Linux Compilation 21 | 22 | #### Linux Kernel Compilation 23 | You will need to manually compile the following kernel modules with your Linux kernel (Please refer to Linux kernel documents for how to add kernel module): 24 | 25 | * Your machine's remoteproc kernel driver 26 | * `obsolete/apps/echo_test/system/linux/kernelspace/rpmsg_user_dev_driver` if you want to run the echo_test app in Linux user space. 27 | * `obsolete/system/linux/kernelspace/rpmsg_echo_test_kern_app` if you want to run the echo_test app in Linux kernel space. 28 | 29 | #### Linux Userspace Compliation 30 | * Compile `obsolete/apps/echo_test/system/linux/userspace/echo_test` into your Linux OS. 31 | * If you are running generic(baremetal) system as remoteproc slave, and Linux as remoteproc master, please also add the built generic `echo_test` executable to the firmware of your Linux OS. 32 | 33 | ## Run the Demo 34 | 35 | ### Load the Demo 36 | After Linux boots, 37 | * Load the machine remoteproc. If Linux runs as remoteproc master, you will need to pass the other processor's echo_test binary as firmware arguement to the remoteproc module. 38 | * If you run the Linux kernel application demo, load the `rpmsg_echo_test_kern_app` module. You will see the kernel application send the message to remote and the remote reply back and the kernel application will verify the result. 39 | * If you run the userspace application demo, load the `rpmsg_user_dev_driver` module. 40 | * If you run the userspace application demo, you will see the similar output on the console: 41 | ``` 42 | **************************************** 43 | Please enter command and press enter key 44 | **************************************** 45 | 1 - Send data to remote core, retrieve the echo and validate its integrity .. 46 | 2 - Quit this application .. 47 | CMD> 48 | ``` 49 | * Input `1` to send packages. 50 | * Input `2` to exit the application. 51 | 52 | After you run the demo, you will need to unload the kernel modules. 53 | 54 | ### Unload the Demo 55 | * If you run the userspace application demo, unload the `rpmsg_user_dev_driver` module. 56 | * If you run the kernelspace application demo, unload the `rpmsg_echo_test_kern_app` module. 57 | * Unload the machine remoteproc driver. 58 | 59 | -------------------------------------------------------------------------------- /docs/apps/matrix_multiply/README.md: -------------------------------------------------------------------------------- 1 | 2 | # matrix_multiply 3 | This readme is about the OpenAMP matrix_multiply demo. 4 | The matrix_multiply is about one processor generates two matrices, and send them to the one, and the other one calcuate the matrix multiplicaiton and return the result matrix. 5 | 6 | For now, it implements Linux generates the matrices, and the baremetal calculate the matrix mulitplication and send back the result. 7 | 8 | ## Compilation 9 | 10 | ### Baremetal Compilation 11 | Option `WITH_MATRIX_MULTIPLY` is to control if the application will be built. 12 | By default this option is `ON` when `WITH_APPS` is on. 13 | 14 | Here is an example: 15 | 16 | ``` 17 | $ cmake ../open-amp -DCMAKE_TOOLCHAIN_FILE=zynq7_generic -DWITH_OBSOLETE=on -DWITH_APPS=ON 18 | ``` 19 | 20 | ### Linux Compilation 21 | 22 | #### Linux Kernel Compilation 23 | You will need to manually compile the following kernel modules with your Linux kernel (Please refer to Linux kernel documents for how to add kernel module): 24 | 25 | * Your machine's remoteproc kernel driver 26 | * `obsolete/system/linux/kernelspace/rpmsg_user_dev_driver` if you want to run the matrix_multiply app in Linux user space. 27 | * `obsolete/apps/matrix_multiply/system/linux/kernelspace/rpmsg_mat_mul_kern_app` if you want to run the matrix_multiply app in Linux kernel space. 28 | 29 | #### Linux Userspace Compliation 30 | * Compile `obsolete/apps/matrix_multiply/system/linux/userspace/mat_mul_demo` into your Linux OS. 31 | * If you are running generic(baremetal) system as remoteproc slave, and Linux as remoteproc master, please also add the built generic `matrix_multiply` executable to the firmware of your Linux OS. 32 | 33 | ## Run the Demo 34 | 35 | ### Load the Demo 36 | After Linux boots, 37 | * Load the machine remoteproc. If Linux runs as remoteproc master, you will need to pass the other processor's matrix_multiply binary as firmware arguement to the remoteproc module. 38 | * If you run the Linux kernel application demo, load the `rpmsg_mat_mul_kern_app` module, you will see the kernel app will generate two matrices to the other processor, and output the result matrix returned by the other processor. 39 | * If you run the userspace application demo, load the `rpmsg_user_dev_driver` module. 40 | * If you run the userspace application demo `mat_mul_demo`, you will see the similar output on the console: 41 | ``` 42 | **************************************** 43 | Please enter command and press enter key 44 | **************************************** 45 | 1 - Generates random 6x6 matrices and transmits them to remote core over rpmsg 46 | .. 47 | 2 - Quit this application .. 48 | CMD> 49 | ``` 50 | * Input `1` to run the matrix multiplication. 51 | * Input `2` to exit the application. 52 | 53 | After you run the demo, you will need to unload the kernel modules. 54 | 55 | ### Unload the Demo 56 | * If you run the userspace application demo, unload the `rpmsg_user_dev_driver` module. 57 | * If you run the kernelspace application demo, unload the `rpmsg_mat_mul_kern_app` module. 58 | * Unload the machine remoteproc driver. 59 | 60 | -------------------------------------------------------------------------------- /docs/apps/rpc_demo/README.md: -------------------------------------------------------------------------------- 1 | 2 | # rpc_demo 3 | This readme is about the OpenAMP rpc_demo demo. 4 | The rpc_demo is about one processor uses the UART on the other processor and create file on the other processor's filesystem with file operations. 5 | 6 | For now, It implements the processor running generic(baremetal) applicaiton access the devices on the Linux. 7 | 8 | ## Compilation 9 | 10 | ### Baremetal Compilation 11 | Option `WITH_RPC_DEMO` is to control if the application will be built. 12 | By default this option is `ON` when `WITH_APPS` is on. 13 | 14 | Here is an example: 15 | 16 | ``` 17 | $ cmake ../open-amp -DCMAKE_TOOLCHAIN_FILE=zynq7_generic -DWITH_OBSOLETE=on -DWITH_APPS=ON 18 | ``` 19 | 20 | ### Linux Compilation 21 | 22 | #### Linux Kernel Compilation 23 | You will need to manually compile the following kernel modules with your Linux kernel (Please refer to Linux kernel documents for how to add kernel module): 24 | 25 | * Your machine's remoteproc kernel driver 26 | * `obsolete/apps/rpc_demo/system/linux/kernelspace/rpmsg_proxy_dev_driver` 27 | 28 | #### Linux Userspace Compliation 29 | * Compile `obsolete/apps/rpc_demo/system/linux/userspace/proxy_app` into your Linux OS. 30 | * Add the built generic `rpc_demo` executable to the firmware of your Linux OS. 31 | 32 | ## Run the Demo 33 | After Linux boots, run `proxy_app` as follows: 34 | ``` 35 | # proxy_app [-m REMOTEPROC_MODULE] [-f PATH_OF_THE_RPC_DEMO_FIRMWARE] 36 | ``` 37 | 38 | The demo application will load the remoteproc module, then the proxy rpmsg module, will output message sent from the other processor, send the console input back to the other processor. When the demo application exits, it will unload the kernel modules. 39 | -------------------------------------------------------------------------------- /docs/img-src/coprocessor-rpmsg-ns-dynamic.gv: -------------------------------------------------------------------------------- 1 | // RPMsg dynamic endpoint creation 2 | 3 | digraph G { 4 | rankdir="LR"; 5 | 6 | subgraph roles { 7 | node [style="filled", fillcolor="lightblue"]; 8 | master [label="Master"]; 9 | slave [label="Slave"]; 10 | } 11 | 12 | subgraph m_comment_nodes { 13 | node [group=m_comment, shape="note", style="filled", fillcolor="yellow"]; 14 | rank="same"; 15 | m_remoteproc_init_comment [label="this is initialize rproc call"]; 16 | m_remoteproc_boot_comment [label="it will setup vdev before booting the remote"]; 17 | m_rpmsg_vdev_init_comment [label="\l* It will initialize vrings with the shared memory\l* If vdev supports name service, it will create name service endpoint;\l* it sets vdev status to DRVIER_READY, And will notify remote.\l"]; 18 | m_rpmsg_create_ep_comment [label="\if vdev supports name service,\lit will send out name service.\l"]; 19 | m_rpmsg_send_comment [label="\lIf endpoint hasn't binded, it fail\lreturn failure to indicate ep hasn't been binded.\l"]; 20 | 21 | } 22 | 23 | subgraph m_flow_nodes { 24 | node [shape="box"]; 25 | rank="same"; 26 | m_remoteproc_init [label="rproc = remoteproc_init(&remoteproc_ops, &arg);"] 27 | m_remoteproc_load [label="calls remoteproc_load() to load applicaiton"]; 28 | m_remoteproc_boot [shape="box", label="ret=remoteproc_boot(&rproc)"]; 29 | m_remoteproc_get_vdev [label="vdev=remoteproc_create_virtio(rproc, rpmsg_vdev_id, MASTER, NULL);"]; 30 | m_rpmsg_shmpool_init[label="rpmsg_virtio_init_shm_pool(shpool, shbuf, shbuf_pool_size);"]; 31 | m_rpmsg_vdev_init [label="rpdev=rpmsg_init_vdev(rpvdev, vdev, ns_bind_cb, &shm_io, shpool);"]; 32 | m_rpmsg_ns_cb [label="\lrpmsg_ns_callback() will see if there is a local ep registered.\lIf yes, bind the ep; otherwise, call ns_bind_cb.\l"]; 33 | m_rpmsg_create_ep [label="\lept=rpmsg_create_ept(ept, rdev, ept_name, ept_addr, dest_addr, \lendpoint_cb, ns_unbind_cb);\l"]; 34 | m_rpmsg_send [label="rpmsg_send(ept,data)"]; 35 | m_rpmsg_rx_cb [label="rpmsg_rx_callback()"]; 36 | m_ep_cb [label="endpoint_cb(ept, data, size, src_addr)"]; 37 | m_rpmsg_destroy_ep [label="rpmsg_destroy_endpoint(ept)"]; 38 | 39 | m_remoteproc_init -> m_remoteproc_load -> m_remoteproc_boot -> m_remoteproc_get_vdev -> 40 | m_rpmsg_shmpool_init -> m_rpmsg_vdev_init -> m_rpmsg_create_ep -> m_rpmsg_ns_cb -> m_rpmsg_send; 41 | m_rpmsg_send -> m_rpmsg_rx_cb -> m_ep_cb -> 42 | m_rpmsg_destroy_ep [dir="none", style="dashed"]; 43 | } 44 | 45 | subgraph s_flow_nodes { 46 | rank="same"; 47 | node [shape="box"]; 48 | s_remoteproc_init [label="rproc = remoteproc_init(&remoteproc_ops, &arg);"]; 49 | 50 | s_remoteproc_parse_rsc [label="ret = remoteproc_set_rsc_table(rproc, &rsc_table, rsc_size)"]; 51 | s_remoteproc_get_vdev [label="vdev=remoteproc_create_virtio(rproc, rpmsg_vdev_id, SLAVE, rst_cb);"]; 52 | s_rpmsg_vdev_init [label="rpdev=rpmsg_init_vdev(rpvdev, vdev, ns_bind_cb, &shm_io, NULL);"]; 53 | s_rpmsg_ns_cb [label="\lrpmsg_ns_callback() will see if there is a local ep registered.\lIf yes, bind the ep; otherwise, it will call ns_bind_cb()."]; 54 | s_rpmsg_ns_bind_cb [label="s_rpsmg_ns_bind_cb(ept_name, remote_addr)"]; 55 | s_rpmsg_create_ep [label="\lept=rpmsg_create_endpoint(ept, rdev, ept_name, ept_addr, remote_addr,\lendpoint_cb, ns_unbind_cb);\l"]; 56 | s_rpmsg_send [label="rpmsg_send(ept,data)"]; 57 | s_rpmsg_rx_cb [label="rpmsg_rx_callback()"]; 58 | s_ep_cb [label="endpoint_cb(ept, data, size, src_addr)"]; 59 | s_rpmsg_ns_unbind_cb [label="\lrpmsg_ns_callback() will call the previous\lregistered endpoint unbind callback\l"]; 60 | 61 | s_remoteproc_init -> s_remoteproc_parse_rsc -> s_remoteproc_get_vdev -> 62 | s_rpmsg_vdev_init -> s_rpmsg_ns_cb -> s_rpmsg_ns_bind_cb -> 63 | s_rpmsg_create_ep; 64 | s_rpmsg_create_ep-> s_rpmsg_rx_cb -> s_ep_cb -> s_rpmsg_send -> 65 | s_rpmsg_ns_unbind_cb [dir="none", style="dash"]; 66 | 67 | } 68 | 69 | subgraph s_comment_nodes { 70 | node [group=s_comment, shape="note", style="filled", fillcolor="yellow"]; 71 | rank="same"; 72 | s_rpmsg_vdev_init_comment [label="\l* If vdev supports name service, it will create name service endpoint;\l* It will not return until the master set status to DRIVER READY\l"]; 73 | s_rpmsg_rx_cb_comment [label="\l* It will look for the endpoint which matches the destination address.\lIf the two endpoints hasn't binded yet,\lit will set the local endpoint's destination address with the source address in the message\l"]; 74 | } 75 | 76 | master -> m_remoteproc_init [dir="none"]; 77 | slave -> s_remoteproc_init [dir="none"]; 78 | s_rpmsg_create_ep -> m_rpmsg_ns_cb [label="NS annoucement"]; 79 | m_rpmsg_create_ep -> s_rpmsg_ns_cb [label="NS annoucement"]; 80 | m_rpmsg_send -> s_rpmsg_rx_cb [label="RPMsg data"]; 81 | s_rpmsg_send -> m_rpmsg_rx_cb [label="RPMsg data"]; 82 | m_rpmsg_destroy_ep -> s_rpmsg_ns_unbind_cb [label="Endpoint destroy NS"]; 83 | 84 | m_remoteproc_init_comment -> m_remoteproc_init [dir="none"]; 85 | m_remoteproc_boot_comment -> m_remoteproc_boot [dir="none"]; 86 | m_rpmsg_vdev_init_comment -> m_rpmsg_vdev_init [dir="none"]; 87 | m_rpmsg_create_ep_comment -> m_rpmsg_create_ep [dir="none"]; 88 | m_rpmsg_send_comment -> m_rpmsg_send [dir="none"]; 89 | 90 | s_rpmsg_vdev_init -> s_rpmsg_vdev_init_comment [dir="none"]; 91 | s_rpmsg_rx_cb -> s_rpmsg_rx_cb_comment [dir="none"]; 92 | 93 | {rank=same; master; m_remoteproc_init} 94 | {rank=same; slave; s_remoteproc_init} 95 | 96 | } 97 | 98 | -------------------------------------------------------------------------------- /docs/img-src/coprocessor-rpmsg-ns.gv: -------------------------------------------------------------------------------- 1 | // RPMsg dynamic endpoints binding 2 | 3 | digraph G { 4 | rankdir="LR"; 5 | 6 | subgraph roles { 7 | node [style="filled", fillcolor="lightblue"]; 8 | master [label="Master"]; 9 | slave [label="Slave"]; 10 | } 11 | 12 | subgraph m_comment_nodes { 13 | node [group=m_comment, shape="note", style="filled", fillcolor="yellow"]; 14 | rank="same"; 15 | m_remoteproc_init_comment [label="this is initialize rproc call"]; 16 | m_remoteproc_boot_comment [label="it will setup vdev before booting the remote"]; 17 | m_rpmsg_vdev_init_comment [label="\l* It will initialize vrings with the shared memory\l* As vdev doesn't support name service, it will not create name service endpoint;\l* it sets vdev status to DRVIER_READY, And will notify remote.\l"]; 18 | m_rpmsg_create_ep_comment [label="\lIf vdev supports name service,\lit will send out name service.\l"]; 19 | m_rpmsg_send_comment [label="\lIf endpoint hasn't binded, it fail\lreturn failure to indicate ep hasn't been binded.\l"]; 20 | 21 | } 22 | 23 | subgraph m_flow_nodes { 24 | node [shape="box"]; 25 | rank="same"; 26 | m_remoteproc_init [label="rproc = remoteproc_init(&remoteproc_ops, &arg);"] 27 | m_remoteproc_load [label="calls remoteproc_load() to load applicaiton"]; 28 | m_remoteproc_boot [shape="box", label="ret=remoteproc_boot(&rproc)"]; 29 | m_remoteproc_get_vdev [label="vdev=remoteproc_create_virtio(rproc, rpmsg_vdev_id, MASTER, NULL);"]; 30 | m_rpmsg_shmpool_init[label="rpmsg_virtio_init_shm_pool(shpool, shbuf, shbuf_pool_size);"]; 31 | m_rpmsg_vdev_init [label="rpdev=rpmsg_init_vdev(rpvdev, vdev, ns_bind_cb, &shm_io, shpool);"]; 32 | m_rpmsg_ns_cb [label="\lrpmsg_ns_callback() will see if there is a local ep registered.\lIf yes, bind the ep; otherwise, call ns_bind_cb.\l"]; 33 | m_rpmsg_create_ep [label="\lept=rpmsg_create_ept(ept, rdev, ept_name, ept_addr, dest_addr, \lendpoint_cb, ns_unbind_cb);\l"]; 34 | m_rpmsg_send [label="rpmsg_send(ept,data)"]; 35 | m_rpmsg_rx_cb [label="rpmsg_rx_callback()"]; 36 | m_ep_cb [label="endpoint_cb(ept, data, size, src_addr)"]; 37 | m_rpmsg_destroy_ep [label="rpmsg_destroy_endpoint(ept)"]; 38 | 39 | m_remoteproc_init -> m_remoteproc_load -> m_remoteproc_boot -> m_remoteproc_get_vdev -> 40 | m_rpmsg_shmpool_init -> m_rpmsg_vdev_init -> m_rpmsg_ns_cb -> m_rpmsg_create_ep -> m_rpmsg_send; 41 | m_rpmsg_send -> m_rpmsg_rx_cb -> m_ep_cb -> 42 | m_rpmsg_destroy_ep [dir="none", style="dashed"]; 43 | } 44 | 45 | subgraph s_flow_nodes { 46 | rank="same"; 47 | node [shape="box"]; 48 | s_remoteproc_init [label="rproc = remoteproc_init(&remoteproc_ops, &arg);"]; 49 | 50 | s_remoteproc_parse_rsc [label="ret = remoteproc_set_rsc_table(rproc, &rsc_table, rsc_size)"]; 51 | s_remoteproc_get_vdev [label="vdev=remoteproc_create_virtio(rproc, rpmsg_vdev_id, SLAVE, rst_cb);"]; 52 | s_rpmsg_vdev_init [label="rpdev=rpmsg_init_vdev(rpvdev, vdev, ns_bind_cb, &shm_io, NULL);"]; 53 | s_rpmsg_create_ep [label="\lept=rpmsg_create_ept(ept, rdev, ept_name, ept_addr, dest_addr, \lendpoint_cb, ns_unbind_cb);\l"]; 54 | s_rpmsg_ns_cb [label="\lrpmsg_ns_callback() will see if there is a local ep registered.\lIf yes, bind the ep; otherwise, call ns_binc_cb.\l"]; 55 | s_rpmsg_send [label="rpmsg_send(ept,data)"]; 56 | s_rpmsg_rx_cb [label="rpmsg_rx_callback()"]; 57 | s_ep_cb [label="endpoint_cb(ept, data, size, src_addr)"]; 58 | s_rpmsg_ns_unbind_cb [label="\lrpmsg_ns_callback() will call the previous\lregistered endpoint unbind callback\l"]; 59 | 60 | s_remoteproc_init -> s_remoteproc_parse_rsc -> s_remoteproc_get_vdev -> 61 | s_rpmsg_vdev_init -> s_rpmsg_create_ep; 62 | s_rpmsg_create_ep -> s_rpmsg_ns_cb -> s_rpmsg_rx_cb -> 63 | s_ep_cb -> s_rpmsg_send -> s_rpmsg_ns_unbind_cb [dir="none", style="dash"]; 64 | 65 | } 66 | 67 | subgraph s_comment_nodes { 68 | node [group=s_comment, shape="note", style="filled", fillcolor="yellow"]; 69 | rank="same"; 70 | s_rpmsg_vdev_init_comment [label="\l* If vdev supports name service, it will create name service endpoint;\l* It will not return until the master set status to DRIVER READY\l"]; 71 | s_rpmsg_rx_cb_comment [label="\l* It will look for the endpoint which matches the destination address.\lIf the two endpoints hasn't binded yet,\lit will set the local endpoint's destination address with the source address in the message\l"]; 72 | } 73 | 74 | master -> m_remoteproc_init [dir="none"]; 75 | slave -> s_remoteproc_init [dir="none"]; 76 | s_rpmsg_create_ep -> m_rpmsg_ns_cb [label="NS annoucement"]; 77 | m_rpmsg_create_ep -> s_rpmsg_ns_cb [label="NS annoucement"]; 78 | m_rpmsg_send -> s_rpmsg_rx_cb [label="RPMsg data"]; 79 | s_rpmsg_send -> m_rpmsg_rx_cb [label="RPMsg data"]; 80 | m_rpmsg_destroy_ep -> s_rpmsg_ns_unbind_cb [label="Endpoint destroy NS"]; 81 | 82 | m_remoteproc_init_comment -> m_remoteproc_init [dir="none"]; 83 | m_remoteproc_boot_comment -> m_remoteproc_boot [dir="none"]; 84 | m_rpmsg_vdev_init_comment -> m_rpmsg_vdev_init [dir="none"]; 85 | m_rpmsg_create_ep_comment -> m_rpmsg_create_ep [dir="none"]; 86 | m_rpmsg_send_comment -> m_rpmsg_send [dir="none"]; 87 | 88 | s_rpmsg_vdev_init -> s_rpmsg_vdev_init_comment [dir="none"]; 89 | s_rpmsg_rx_cb -> s_rpmsg_rx_cb_comment [dir="none"]; 90 | 91 | {rank=same; master; m_remoteproc_init} 92 | {rank=same; slave; s_remoteproc_init} 93 | 94 | } 95 | 96 | -------------------------------------------------------------------------------- /docs/img-src/coprocessor-rpmsg-static-ep.gv: -------------------------------------------------------------------------------- 1 | // RPMsg static endpoints 2 | 3 | digraph G { 4 | rankdir="LR"; 5 | 6 | subgraph roles { 7 | node [style="filled", fillcolor="lightblue"]; 8 | master [label="Master"]; 9 | slave [label="Slave"]; 10 | } 11 | 12 | subgraph m_comment_nodes { 13 | node [group=m_comment, shape="note", style="filled", fillcolor="yellow"]; 14 | rank="same"; 15 | m_remoteproc_init_comment [label="this is initialize rproc call"]; 16 | m_remoteproc_boot_comment [label="it will setup vdev before booting the remote"]; 17 | m_rpmsg_vdev_init_comment [label="\l* It will initialize vrings with the shared memory\l* As vdev doesn't support name service, it will not create name service endpoint;\l* it sets vdev status to DRVIER_READY, And will notify remote.\l"]; 18 | m_rpmsg_create_ep_comment [label="\lAs vdev doesn't supports name service,\lit will not send out name service.\l"]; 19 | } 20 | 21 | subgraph m_flow_nodes { 22 | node [shape="box"]; 23 | rank="same"; 24 | m_remoteproc_init [label="rproc = remoteproc_init(&remoteproc_ops, &arg);"]; 25 | m_remoteproc_load [label="calls remoteproc_load() to load applicaiton"]; 26 | m_remoteproc_boot [shape="box", label="ret=remoteproc_boot(&rproc)"]; 27 | m_remoteproc_get_vdev [label="vdev=remoteproc_create_virtio(rproc, rpmsg_vdev_id, MASTER, NULL);"]; 28 | m_rpmsg_shmpool_init[label="rpmsg_virtio_init_shm_pool(shpool, shbuf, shbuf_pool_size);"]; 29 | m_rpmsg_vdev_init [label="rpdev=rpmsg_init_vdev(rpvdev, vdev, ns_bind_cb, &shm_io, shpool);"]; 30 | m_rpmsg_create_ep [label="\lept=rpmsg_create_ept(ept, rdev, ept_name, ept_addr, dest_addr, \lendpoint_cb, ns_unbind_cb);\l"]; 31 | m_rpmsg_send [label="rpmsg_send(ept,data)"]; 32 | m_rpmsg_rx_cb [label="rpmsg_rx_callback()"]; 33 | m_ep_cb [label="endpoint_cb(ept, data, size, src_addr)"]; 34 | m_rpmsg_destroy_ep [label="rpmsg_destroy_endpoint(ept)"]; 35 | 36 | m_remoteproc_init -> m_remoteproc_load -> m_remoteproc_boot -> m_remoteproc_get_vdev -> 37 | m_rpmsg_shmpool_init -> m_rpmsg_vdev_init -> m_rpmsg_create_ep -> m_rpmsg_send; 38 | m_rpmsg_send -> m_rpmsg_rx_cb -> m_ep_cb -> 39 | m_rpmsg_destroy_ep [dir="none", style="dashed"]; 40 | } 41 | 42 | subgraph s_flow_nodes { 43 | rank="same"; 44 | node [shape="box"]; 45 | s_remoteproc_init [label="rproc = remoteproc_init(&remoteproc_ops, &arg);"]; 46 | 47 | s_remoteproc_parse_rsc [label="ret = remoteproc_set_rsc_table(rproc, &rsc_table, rsc_size)"]; 48 | s_remoteproc_get_vdev [label="vdev=remoteproc_create_virtio(rproc, rpmsg_vdev_id, SLAVE, rst_cb);"]; 49 | s_rpmsg_vdev_init [label="rpdev=rpmsg_init_vdev(rpvdev, vdev, ns_bind_cb, &shm_io, NULL);"]; 50 | s_rpmsg_create_ep [label="\lept=rpmsg_create_ept(ept, rdev, ept_name, ept_addr, dest_addr, \lendpoint_cb, ns_unbind_cb);\l"]; 51 | s_rpmsg_send [label="rpmsg_send(ept,data)"]; 52 | s_rpmsg_rx_cb [label="rpmsg_rx_callback()"]; 53 | s_ep_cb [label="endpoint_cb(ept, data, size, src_addr)"]; 54 | s_rpmsg_destroy_ep [label="rpmsg_destroy_endpoint(ept)"]; 55 | 56 | s_remoteproc_init -> s_remoteproc_parse_rsc -> s_remoteproc_get_vdev -> 57 | s_rpmsg_vdev_init -> s_rpmsg_create_ep; 58 | s_rpmsg_create_ep -> s_rpmsg_rx_cb -> 59 | s_ep_cb -> s_rpmsg_send -> s_rpmsg_destroy_ep [dir="none", style="dash"]; 60 | 61 | } 62 | 63 | subgraph s_comment_nodes { 64 | node [group=s_comment, shape="note", style="filled", fillcolor="yellow"]; 65 | rank="same"; 66 | s_rpmsg_vdev_init_comment [label="\l* As vdev doesn't support name service, it will not create name service endpoint;\l* It will not return until the master set status to DRIVER READY\l"]; 67 | s_rpmsg_rx_cb_comment [label="\l* It will look for the endpoint which matches the destination address.\lIf no endpoint has found, it will drop the message.\l"]; 68 | } 69 | 70 | master -> m_remoteproc_init [dir="none"]; 71 | slave -> s_remoteproc_init [dir="none"]; 72 | m_rpmsg_send -> s_rpmsg_rx_cb [label="RPMsg data"]; 73 | s_rpmsg_send -> m_rpmsg_rx_cb [label="RPMsg data"]; 74 | 75 | m_remoteproc_init_comment -> m_remoteproc_init [dir="none"]; 76 | m_remoteproc_boot_comment -> m_remoteproc_boot [dir="none"]; 77 | m_rpmsg_vdev_init_comment -> m_rpmsg_vdev_init [dir="none"]; 78 | m_rpmsg_create_ep_comment -> m_rpmsg_create_ep [dir="none"]; 79 | 80 | s_rpmsg_vdev_init -> s_rpmsg_vdev_init_comment [dir="none"]; 81 | s_rpmsg_rx_cb -> s_rpmsg_rx_cb_comment [dir="none"]; 82 | 83 | {rank=same; master; m_remoteproc_init} 84 | {rank=same; slave; s_remoteproc_init} 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /docs/img-src/gen-graph.py: -------------------------------------------------------------------------------- 1 | from graphviz import Digraph 2 | import argparse 3 | import os 4 | import pydot 5 | import sys 6 | import warnings 7 | 8 | def gen_graph_from_gv(ifile, odir, oformat="png"): 9 | (graph,) = pydot.graph_from_dot_file(ifile) 10 | gen_graph_func = getattr(graph, "write_" + oformat) 11 | filename = os.path.basename(ifile) 12 | ofile = odir + "/" + os.path.splitext(filename)[0] + "." + oformat 13 | gen_graph_func(ofile) 14 | 15 | parser = argparse.ArgumentParser(description='Process some integers.') 16 | parser.add_argument('-i', "--infile", action="append", 17 | help="graphviz file path") 18 | parser.add_argument('-o', '--outdir', 19 | help='sum the integers (default: find the max)') 20 | parser.add_argument('-f', '--outformat', default="png", 21 | help='output image format (default: png)') 22 | 23 | args = parser.parse_args() 24 | 25 | # Image source directory 26 | img_src_dir = os.path.dirname(os.path.realpath(sys.argv[0])) 27 | 28 | img_files = [] 29 | if args.infile: 30 | for f in args.infile: 31 | if not os.path.isfile(f): 32 | f = img_src_dir + "/" + f 33 | if not os.path.isfile(f): 34 | warnings.warn("Input file: " + f + " doesn't exist.") 35 | else: 36 | img_files.append(f) 37 | else: 38 | for f in os.listdir(img_src_dir): 39 | if f.endswith(".gv"): 40 | img_files.append(img_src_dir + "/" + f) 41 | 42 | if not img_files: 43 | sys.exist("ERROR: no found image files.") 44 | 45 | oformat = args.outformat 46 | 47 | if args.outdir: 48 | odir = args.outdir 49 | if not os.path.isdir(odir): 50 | sys.exit("--outdir " + odir + "doesn't exist") 51 | else: 52 | odir = os.path.dirname(img_src_dir) + "/img" 53 | 54 | for f in img_files: 55 | print("Generating " + oformat + " for " + f + " ...") 56 | gen_graph_from_gv(f, odir, oformat) 57 | -------------------------------------------------------------------------------- /docs/img-src/rproc-lcm-state-machine.gv: -------------------------------------------------------------------------------- 1 | // Remoteproc Life Cycle Management State Machine 2 | 3 | digraph G { 4 | rankdir="LR" 5 | st_offline [label="Offline"] 6 | st_configured [label="Configured"] 7 | st_ready [label="Ready"] 8 | st_running [label="Running"] 9 | st_stopped [label="Stopped"] 10 | 11 | st_offline -> st_configured 12 | st_configured -> st_ready 13 | st_ready -> st_running 14 | st_ready -> st_stopped 15 | st_stopped -> st_offline 16 | st_running -> st_stopped 17 | 18 | {rank=same; st_configured; st_ready; st_running} 19 | } 20 | -------------------------------------------------------------------------------- /docs/img/coprocessor-rpmsg-ns-dynamic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xilinx/open-amp/f9039c27a00caa7f1548ffd53d863776edc6f223/docs/img/coprocessor-rpmsg-ns-dynamic.png -------------------------------------------------------------------------------- /docs/img/coprocessor-rpmsg-ns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xilinx/open-amp/f9039c27a00caa7f1548ffd53d863776edc6f223/docs/img/coprocessor-rpmsg-ns.png -------------------------------------------------------------------------------- /docs/img/coprocessor-rpmsg-static-ep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xilinx/open-amp/f9039c27a00caa7f1548ffd53d863776edc6f223/docs/img/coprocessor-rpmsg-static-ep.png -------------------------------------------------------------------------------- /docs/img/rproc-lcm-state-machine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xilinx/open-amp/f9039c27a00caa7f1548ffd53d863776edc6f223/docs/img/rproc-lcm-state-machine.png -------------------------------------------------------------------------------- /docs/openamp_ref.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xilinx/open-amp/f9039c27a00caa7f1548ffd53d863776edc6f223/docs/openamp_ref.pdf -------------------------------------------------------------------------------- /docs/remoteproc-design.md: -------------------------------------------------------------------------------- 1 | # Remoteproc Design Document 2 | Remoteproc provides abstraction to manage the life cycle of a remote 3 | application. For now, it only provides APIs on bringing up and 4 | tearing down the remote application, and parsing resource table. 5 | It will extend to crash detection, suspend and resume. 6 | 7 | ## Remoteproc LCM States 8 | | State | State Description | 9 | |:------|:------------------| 10 | | Offline | Initial state of a remoteproc instance. The remote presented by the remoteproc instance and its resource has been powered off. | 11 | | Configured | The remote presented by the remoteproc instance has been configured. And ready to load applicaiton. | 12 | | Ready | The remote presented by the remoteproc instance has applicaiton loaded, and ready to run. | 13 | | Stopped | The remote presented by the remoteproc instance has stopped from running. But the remote is still powered on. And the remote's resource hasn't been released. | 14 | 15 | ![Rproc LCM States](img/rproc-lcm-state-machine.png) 16 | 17 | ### State Transition 18 | | State Transition | Transition Trigger | 19 | |:-----------------|:-------------------| 20 | | Offline -> Configured | Configure the remote to make it able to load application;
`remoteproc_configure(&rproc, &config_data)`| 21 | | Configured -> Ready | load firmware ;
`remoteproc_load(&rproc, &path, &image_store, &image_store_ops, &image_info)` | 22 | | Ready -> Running | start the processor;
`remoteproc_start(&rproc)` | 23 | | Ready -> Stopped | stop the processor;
`remoteproc_stop(&rproc)`;
`remoteproc_shutdown(&rproc)`(Stopped is the intermediate state of shutdown operation) | 24 | | Running -> Stopped | stop the processor;
`remoteproc_stop(&rproc)`;
`remoteproc_shutdown(&rproc)` | 25 | | Stopped -> Offline | shutdown the processor;
`remoteproc_shutdown(&rproc)` | 26 | 27 | ## Remote User APIs 28 | * Initialize remoteproc instance: 29 | ``` 30 | struct remoteproc *remoteproc_init(struct remoteproc *rproc, 31 | struct remoteproc_ops *ops, void *priv) 32 | ``` 33 | * Release remoteproc instance: 34 | ``` 35 | int remoteproc_remove(struct remoteproc *rproc) 36 | ``` 37 | * Add memory to remoteproc: 38 | ``` 39 | void remoteproc_add_mem(struct remoteproc *rproc, struct remoteproc_mem *mem) 40 | ``` 41 | * Get memory libmetal I/O region from remoteproc specifying memory name: 42 | ``` 43 | struct metal_io_region *remoteproc_get_io_with_name(struct remoteproc *rproc, const char *name) 44 | ``` 45 | * Get memory libmetal I/O region from remoteproc specifying physical address: 46 | ``` 47 | struct metal_io_region *remoteproc_get_io_with_pa(struct remoteproc *rproc, metal_phys_addr_t pa); 48 | ``` 49 | * Get memory libmetal I/O region from remoteproc specifying virtual address: 50 | ``` 51 | struct metal_io_region *remoteproc_get_io_with_va(struct remoteproc *rproc, void *va); 52 | ``` 53 | * Map memory and add the memory to the remoteproc instance: 54 | ``` 55 | void *remoteproc_mmap(struct remoteproc *rproc, 56 | metal_phys_addr_t *pa, metal_phys_addr_t *da, 57 | size_t size, unsigned int attribute, 58 | struct metal_io_region **io); 59 | ``` 60 | * Set resource table to remoteproc: 61 | ``` 62 | int remoteproc_set_rsc_table(struct remoteproc *rproc, 63 | struct resource_table *rsc_table, 64 | size_t rsc_size) 65 | ``` 66 | * Configure the remote presented by the remoteproc instance to make it able 67 | to load applicaiton: 68 | ``` 69 | int remoteproc_config(struct remoteproc *rproc, void *data) 70 | ``` 71 | * Load application to the remote presented by the remoteproc instance to make 72 | it ready to run: 73 | ``` 74 | int remoteproc_load(struct remoteproc *rproc, const char *path, 75 | void *store, struct image_store_ops *store_ops, 76 | void **img_info) 77 | ``` 78 | * Run application on the remote presented by the remoteproc instance: 79 | ``` 80 | int remoteproc_start(struct remoteproc *rproc) 81 | ``` 82 | * Stop application on remote presented by the remoteproc instance: 83 | ``` 84 | int remoteproc_stop(struct remoteproc *rproc) 85 | ``` 86 | * Shutdown the remote presented by the remoteproc instance: 87 | ``` 88 | int remoteproc_shutdown(struct remoteproc *rproc) 89 | ``` 90 | * Create virtio device from the resource table vdev resource, and add it to the 91 | remoteproc instance: 92 | ``` 93 | struct virtio_device *remoteproc_create_virtio(struct remoteproc *rproc, 94 | int vdev_id, unsigned int role, 95 | void (*rst_cb)(struct virtio_device *vdev)) 96 | ``` 97 | * Remove virtio device from the remoteproc instance: 98 | ``` 99 | void remoteproc_remove_virtio(struct remoteproc *rproc, 100 | struct virtio_device *vdev) 101 | ``` 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/rpmsg-design.md: -------------------------------------------------------------------------------- 1 | # RPMsg Design Document 2 | RPMsg is a framework to allow communication between two processors. 3 | RPMsg implementation in OpenAMP library is based on virtio. It complies 4 | the RPMsg Linux kernel implementation. It defines the handshaking on 5 | setting up and tearing down the communication between applicaitons 6 | running on two processors. 7 | 8 | ## RPMsg User API Flow Chats 9 | ### RPMsg Static Endpoint 10 | ![Static Endpoint](img/coprocessor-rpmsg-static-ep.png) 11 | ### Binding Endpoint Dynamically with Name Service 12 | ![Binding Endpoint Dynamically with Name Service](img/coprocessor-rpmsg-ns.png) 13 | ### Creating Endpoint Dynamically with Name Service 14 | ![Creating Endpoint Dynamically with Name Service](img/coprocessor-rpmsg-ns-dynamic.png) 15 | 16 | ## RPMsg User APIs 17 | * RPMsg virtio master to initialize the shared buffers pool(RPMsg virtio slave 18 | doesn't need to use this API): 19 | ``` 20 | void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool, 21 | void *shbuf, size_t size) 22 | ``` 23 | * Initialize RPMsg virtio device: 24 | ``` 25 | int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, 26 | struct virtio_device *vdev, 27 | rpmsg_ns_bind_cb ns_bind_cb, 28 | struct metal_io_region *shm_io, 29 | struct rpmsg_virtio_shm_pool *shpool) 30 | ``` 31 | * Deinitialize RPMsg virtio device: 32 | ``` 33 | void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev)` 34 | ``` 35 | * Get RPMsg device from RPMsg virtio device: 36 | ``` 37 | struct rpmsg_device *rpmsg_virtio_get_rpmsg_device(struct rpmsg_virtio_device *rvdev) 38 | ``` 39 | * Create RPMsg endpoint: 40 | ``` 41 | int rpmsg_create_ept(struct rpmsg_endpoint *ept, 42 | struct rpmsg_device *rdev, 43 | const char *name, uint32_t src, uint32_t dest, 44 | rpmsg_ept_cb cb, rpmsg_ns_unbind_cb ns_unbind_cb) 45 | ``` 46 | * Destroy RPMsg endpoint: 47 | ``` 48 | void rpmsg_destroy_ept(struct rpsmg_endpoint *ept) 49 | ``` 50 | * Check if the local RPMsg endpoint is binded to the remote, and ready to send 51 | message: 52 | ``` 53 | int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept) 54 | ``` 55 | * Send message with RPMsg endpoint default binding: 56 | ``` 57 | int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, int len) 58 | ``` 59 | * Send message with RPMsg endpoint, specify destination address: 60 | ``` 61 | int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, 62 | uint32_t dst) 63 | ``` 64 | * Send message with RPMsg endpoint using explicit source and destination 65 | addresses: 66 | ``` 67 | int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, 68 | uint32_t src, uint32_t dst, 69 | const void *data, int len) 70 | ``` 71 | * Try to send message with RPMsg endpoint default binding, if no buffer 72 | available, returns: 73 | ``` 74 | int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data, 75 | int len) 76 | ``` 77 | * Try to send message with RPMsg endpoint, specify destination address, 78 | if no buffer available, returns: 79 | ``` 80 | int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, 81 | uint32_t dst) 82 | ``` 83 | * Try to send message with RPMsg endpoint using explicit source and destination 84 | addresses, if no buffer available, returns: 85 | ``` 86 | int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, 87 | uint32_t src, uint32_t dst, 88 | const void *data, int len)` 89 | ``` 90 | ## RPMsg User Defined Callbacks 91 | * RPMsg endpoint message received callback: 92 | ``` 93 | int (*rpmsg_ept_cb)(struct rpmsg_endpoint *ept, void *data, 94 | size_t len, uint32_t src, void *priv) 95 | ``` 96 | * RPMsg name service binding callback. If user defines such callback, when 97 | there is a name service announcement arrives, if there is no registered 98 | endpoint found to bind to this name service, it will call this callback. 99 | If this callback is not defined, it will drop this name service.: 100 | ``` 101 | void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev, 102 | const char *name, uint32_t dest) 103 | ``` 104 | * RPMsg endpoint name service unbind callback. If user defines such callback, 105 | when there is name service destroy arrives, it will call this callback to 106 | notify the user application about the remote has destroyed the service.: 107 | ``` 108 | void (*rpmsg_ns_unbind_cb)(struct rpmsg_endpoint *ept) 109 | ``` 110 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set_property (GLOBAL PROPERTY "PROJECT_LIB_EXTRA_CFLAGS") 3 | 4 | collector_create (PROJECT_LIB_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}") 5 | collect (PROJECT_LIB_DIRS "${CMAKE_CURRENT_BINARY_DIR}") 6 | collect (PROJECT_INC_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include") 7 | 8 | 9 | add_subdirectory (virtio) 10 | add_subdirectory (rpmsg) 11 | add_subdirectory (remoteproc) 12 | 13 | if (WITH_PROXY) 14 | add_subdirectory (proxy) 15 | endif (WITH_PROXY) 16 | 17 | set (OPENAMP_LIB open_amp) 18 | 19 | if (NOT CMAKE_INSTALL_LIBDIR) 20 | set (CMAKE_INSTALL_LIBDIR "lib") 21 | endif (NOT CMAKE_INSTALL_LIBDIR) 22 | 23 | collector_list (_include PROJECT_INC_DIRS) 24 | include_directories (${_include}) 25 | 26 | collector_list (_deps PROJECT_LIB_DEPS) 27 | 28 | get_property (_ecflags GLOBAL PROPERTY "PROJECT_LIB_EXTRA_CFLAGS") 29 | 30 | collector_list (_sources PROJECT_LIB_SOURCES) 31 | set_property (SOURCE ${_sources} 32 | APPEND_STRING PROPERTY COMPILE_FLAGS " ${_ecflags}") 33 | 34 | # Build a shared library if so configured. 35 | if (WITH_ZEPHYR) 36 | zephyr_library_named(${OPENAMP_LIB}) 37 | add_dependencies(${OPENAMP_LIB} offsets_h) 38 | target_sources (${OPENAMP_LIB} PRIVATE ${_sources}) 39 | zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) 40 | else (WITH_ZEPHYR) 41 | if (WITH_SHARED_LIB) 42 | set (_lib ${OPENAMP_LIB}-shared) 43 | add_library (${_lib} SHARED ${_sources}) 44 | target_link_libraries (${_lib} ${_deps}) 45 | install (TARGETS ${_lib} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 46 | set_target_properties (${_lib} PROPERTIES 47 | OUTPUT_NAME "${OPENAMP_LIB}" 48 | VERSION "${PROJECT_VER}" 49 | SOVERSION "${PROJECT_VER_MAJOR}" 50 | ) 51 | endif (WITH_SHARED_LIB) 52 | 53 | if (WITH_STATIC_LIB) 54 | set (_lib ${OPENAMP_LIB}-static) 55 | add_library (${_lib} STATIC ${_sources}) 56 | install (TARGETS ${_lib} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) 57 | set_target_properties (${_lib} PROPERTIES 58 | OUTPUT_NAME "${OPENAMP_LIB}" 59 | ) 60 | endif (WITH_STATIC_LIB) 61 | endif (WITH_ZEPHYR) 62 | 63 | install (DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/openamp" DESTINATION include) 64 | 65 | # vim: expandtab:ts=2:sw=2:smartindent 66 | -------------------------------------------------------------------------------- /lib/include/openamp/open_amp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | #ifndef OPEN_AMP_H_ 9 | #define OPEN_AMP_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | #endif /* OPEN_AMP_H_ */ 18 | -------------------------------------------------------------------------------- /lib/include/openamp/remoteproc_loader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | /************************************************************************** 9 | * FILE NAME 10 | * 11 | * remoteproc_loader.h 12 | * 13 | * COMPONENT 14 | * 15 | * OpenAMP stack. 16 | * 17 | * DESCRIPTION 18 | * 19 | * This file provides definitions for remoteproc loader 20 | * 21 | * 22 | **************************************************************************/ 23 | #ifndef REMOTEPROC_LOADER_H_ 24 | #define REMOTEPROC_LOADER_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #if defined __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* Loader feature macros */ 36 | #define SUPPORT_SEEK 1UL 37 | 38 | /* Remoteproc loader any address */ 39 | #define RPROC_LOAD_ANYADDR ((metal_phys_addr_t)-1) 40 | 41 | /* Remoteproc loader Executable Image Parsing States */ 42 | /* Remoteproc loader parser initial state */ 43 | #define RPROC_LOADER_NOT_READY 0x0UL 44 | /* Remoteproc loader ready to load, even it can be not finish parsing */ 45 | #define RPROC_LOADER_READY_TO_LOAD 0x10000UL 46 | /* Remoteproc loader post data load */ 47 | #define RPROC_LOADER_POST_DATA_LOAD 0x20000UL 48 | /* Remoteproc loader finished loading */ 49 | #define RPROC_LOADER_LOAD_COMPLETE 0x40000UL 50 | /* Remoteproc loader state mask */ 51 | #define RPROC_LOADER_MASK 0x00FF0000UL 52 | /* Remoteproc loader private mask */ 53 | #define RPROC_LOADER_PRIVATE_MASK 0x0000FFFFUL 54 | /* Remoteproc loader reserved mask */ 55 | #define RPROC_LOADER_RESERVED_MASK 0x0F000000UL 56 | 57 | /** 58 | * struct image_store_ops - user defined image store operations 59 | * @open: user defined callback to open the "firmware" to prepare loading 60 | * @close: user defined callback to close the "firmware" to clean up 61 | * after loading 62 | * @load: user defined callback to load the firmware contents to target 63 | * memory or local memory 64 | * @features: loader supported features. e.g. seek 65 | */ 66 | struct image_store_ops { 67 | int (*open)(void *store, const char *path, const void **img_data); 68 | void (*close)(void *store); 69 | int (*load)(void *store, size_t offset, size_t size, 70 | const void **data, 71 | metal_phys_addr_t pa, 72 | struct metal_io_region *io, char is_blocking); 73 | unsigned int features; 74 | }; 75 | 76 | /** 77 | * struct loader_ops - loader operations 78 | * @load_header: define how to get the executable headers 79 | * @load_data: define how to load the target data 80 | * @locate_rsc_table: define how to get the resource table target address, 81 | * offset to the ELF image file and size of the resource 82 | * table. 83 | * @release: define how to release the loader 84 | * @get_entry: get entry address 85 | * @get_load_state: get load state from the image information 86 | */ 87 | struct loader_ops { 88 | int (*load_header)(const void *img_data, size_t offset, size_t len, 89 | void **img_info, int last_state, 90 | size_t *noffset, size_t *nlen); 91 | int (*load_data)(struct remoteproc *rproc, 92 | const void *img_data, size_t offset, size_t len, 93 | void **img_info, int last_load_state, 94 | metal_phys_addr_t *da, 95 | size_t *noffset, size_t *nlen, 96 | unsigned char *padding, size_t *nmemsize); 97 | int (*locate_rsc_table)(void *img_info, metal_phys_addr_t *da, 98 | size_t *offset, size_t *size); 99 | void (*release)(void *img_info); 100 | metal_phys_addr_t (*get_entry)(void *img_info); 101 | int (*get_load_state)(void *img_info); 102 | }; 103 | 104 | #if defined __cplusplus 105 | } 106 | #endif 107 | 108 | #endif /* REMOTEPROC_LOADER_H_ */ 109 | -------------------------------------------------------------------------------- /lib/include/openamp/remoteproc_virtio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Remoteproc Virtio Framework 3 | * 4 | * Copyright(c) 2018 Xilinx Ltd. 5 | * Copyright(c) 2011 Texas Instruments, Inc. 6 | * Copyright(c) 2011 Google, Inc. 7 | * All rights reserved. 8 | * 9 | * SPDX-License-Identifier: BSD-3-Clause 10 | */ 11 | 12 | #ifndef REMOTEPROC_VIRTIO_H 13 | #define REMOTEPROC_VIRTIO_H 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #if defined __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* define vdev notification funciton user should implement */ 24 | typedef int (*rpvdev_notify_func)(void *priv, uint32_t id); 25 | 26 | /** 27 | * struct remoteproc_virtio 28 | * @priv pointer to private data 29 | * @vdev_rsc address of vdev resource 30 | * @vdev_rsc_io metal I/O region of vdev_info, can be NULL 31 | * @notify notification function 32 | * @vdev virtio device 33 | * @node list node 34 | */ 35 | struct remoteproc_virtio { 36 | void *priv; 37 | void *vdev_rsc; 38 | struct metal_io_region *vdev_rsc_io; 39 | rpvdev_notify_func notify; 40 | struct virtio_device vdev; 41 | struct metal_list node; 42 | }; 43 | 44 | /** 45 | * rproc_virtio_create_vdev 46 | * 47 | * Create rproc virtio vdev 48 | * 49 | * @role: 0 - virtio master, 1 - virtio slave 50 | * @notifyid: virtio device notification id 51 | * @rsc: pointer to the virtio device resource 52 | * @rsc_io: pointer to the virtio device resource I/O region 53 | * @priv: pointer to the private data 54 | * @notify: vdev and virtqueue notification function 55 | * @rst_cb: reset virtio device callback 56 | * 57 | * return pointer to the created virtio device for success, 58 | * NULL for failure. 59 | */ 60 | struct virtio_device * 61 | rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, 62 | void *rsc, struct metal_io_region *rsc_io, 63 | void *priv, 64 | rpvdev_notify_func notify, 65 | virtio_dev_reset_cb rst_cb); 66 | 67 | /** 68 | * rproc_virtio_remove_vdev 69 | * 70 | * Remove rproc virtio vdev 71 | * 72 | * @vdev - pointer to the virtio device 73 | */ 74 | void rproc_virtio_remove_vdev(struct virtio_device *vdev); 75 | 76 | /** 77 | * rproc_virtio_init_vring 78 | * 79 | * Initialize rproc virtio vring 80 | * 81 | * @vdev: pointer to the virtio device 82 | * @index: vring index in the virtio device 83 | * @notifyid: remoteproc vring notification id 84 | * @va: vring virtual address 85 | * @io: pointer to vring I/O region 86 | * @num_desc: number of descriptors 87 | * @align: vring alignment 88 | * 89 | * return 0 for success, negative value for failure. 90 | */ 91 | int rproc_virtio_init_vring(struct virtio_device *vdev, unsigned int index, 92 | unsigned int notifyid, void *va, 93 | struct metal_io_region *io, 94 | unsigned int num_descs, unsigned int align); 95 | 96 | /** 97 | * rproc_virtio_notified 98 | * 99 | * remoteproc virtio is got notified 100 | * 101 | * @vdev - pointer to the virtio device 102 | * @notifyid - notify id 103 | * 104 | * return 0 for successful, negative value for failure 105 | */ 106 | int rproc_virtio_notified(struct virtio_device *vdev, uint32_t notifyid); 107 | 108 | /** 109 | * rproc_virtio_wait_remote_ready 110 | * 111 | * Blocking function, waiting for the remote core is ready to start 112 | * communications. 113 | * 114 | * @vdev - pointer to the virtio device 115 | * 116 | * return true when remote processor is ready. 117 | */ 118 | void rproc_virtio_wait_remote_ready(struct virtio_device *vdev); 119 | 120 | #if defined __cplusplus 121 | } 122 | #endif 123 | 124 | #endif /* REMOTEPROC_VIRTIO_H */ 125 | -------------------------------------------------------------------------------- /lib/include/openamp/rpmsg_retarget.h: -------------------------------------------------------------------------------- 1 | #ifndef RPMSG_RETARGET_H 2 | #define RPMSG_RETARGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* File Operations System call definitions */ 13 | #define OPEN_SYSCALL_ID 0x1UL 14 | #define CLOSE_SYSCALL_ID 0x2UL 15 | #define WRITE_SYSCALL_ID 0x3UL 16 | #define READ_SYSCALL_ID 0x4UL 17 | #define ACK_STATUS_ID 0x5UL 18 | 19 | #define TERM_SYSCALL_ID 0x6UL 20 | 21 | #define DEFAULT_PROXY_ENDPOINT 0xFFUL 22 | 23 | struct rpmsg_rpc_data; 24 | 25 | typedef int (*rpmsg_rpc_poll)(void *arg); 26 | typedef void (*rpmsg_rpc_shutdown_cb)(struct rpmsg_rpc_data *rpc); 27 | 28 | struct rpmsg_rpc_syscall_header { 29 | int32_t int_field1; 30 | int32_t int_field2; 31 | uint32_t data_len; 32 | }; 33 | 34 | struct rpmsg_rpc_syscall { 35 | uint32_t id; 36 | struct rpmsg_rpc_syscall_header args; 37 | }; 38 | 39 | struct rpmsg_rpc_data { 40 | struct rpmsg_endpoint ept; 41 | int ept_destroyed; 42 | atomic_int nacked; 43 | void *respbuf; 44 | size_t respbuf_len; 45 | rpmsg_rpc_poll poll; 46 | void *poll_arg; 47 | rpmsg_rpc_shutdown_cb shutdown_cb; 48 | metal_mutex_t lock; 49 | struct metal_spinlock buflock; 50 | }; 51 | 52 | /** 53 | * rpmsg_rpc_init - initialize RPMsg remote procedure call 54 | * 55 | * This function is to intialize the remote procedure call 56 | * global data. RPMsg RPC will send request to remote and 57 | * wait for callback. 58 | * 59 | * @rpc: pointer to the global remote procedure call data 60 | * @rdev: pointer to the rpmsg device 61 | * @ept_name: name of the endpoint used by RPC 62 | * @ept_addr: address of the endpoint used by RPC 63 | * @ept_raddr: remote address of the endpoint used by RPC 64 | * @poll_arg: pointer to poll function argument 65 | * @poll: poll function 66 | * @shutdown_cb: shutdown callback function 67 | * 68 | * return 0 for success, and negative value for failure. 69 | */ 70 | int rpmsg_rpc_init(struct rpmsg_rpc_data *rpc, 71 | struct rpmsg_device *rdev, 72 | const char *ept_name, uint32_t ept_addr, 73 | uint32_t ept_raddr, 74 | void *poll_arg, rpmsg_rpc_poll poll, 75 | rpmsg_rpc_shutdown_cb shutdown_cb); 76 | 77 | /** 78 | * rpmsg_rpc_release - release RPMsg remote procedure call 79 | * 80 | * This function is to release remoteproc procedure call 81 | * global data. 82 | * 83 | * @rpc: pointer to the globacl remote procedure call 84 | */ 85 | void rpmsg_rpc_release(struct rpmsg_rpc_data *rpc); 86 | 87 | /** 88 | * rpmsg_rpc_send - Request RPMsg RPC call 89 | * 90 | * This function sends RPC request it will return with the length 91 | * of data and the response buffer. 92 | * 93 | * @rpc: pointer to remoteproc procedure call data struct 94 | * @req: pointer to request buffer 95 | * @len: length of the request data 96 | * @resp: pointer to where store the response buffer 97 | * @resp_len: length of the response buffer 98 | * 99 | * return length of the received response, negative value for failure. 100 | */ 101 | int rpmsg_rpc_send(struct rpmsg_rpc_data *rpc, 102 | void *req, size_t len, 103 | void *resp, size_t resp_len); 104 | 105 | /** 106 | * rpmsg_set_default_rpc - set default RPMsg RPC data 107 | * 108 | * The default RPC data is used to redirect standard C file operations 109 | * to RPMsg channels. 110 | * 111 | * @rpc: pointer to remoteproc procedure call data struct 112 | */ 113 | void rpmsg_set_default_rpc(struct rpmsg_rpc_data *rpc); 114 | 115 | #if defined __cplusplus 116 | } 117 | #endif 118 | 119 | #endif /* RPMSG_RETARGET_H */ 120 | -------------------------------------------------------------------------------- /lib/include/openamp/rsc_table_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | */ 7 | 8 | #ifndef RSC_TABLE_PARSER_H 9 | #define RSC_TABLE_PARSER_H 10 | 11 | #include 12 | 13 | #if defined __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #define RSC_TAB_SUPPORTED_VERSION 1 18 | 19 | /* Standard control request handling. */ 20 | typedef int (*rsc_handler)(struct remoteproc *rproc, void *rsc); 21 | 22 | /** 23 | * handle_rsc_table 24 | * 25 | * This function parses resource table. 26 | * 27 | * @param rproc - pointer to remote remoteproc 28 | * @param rsc_table - resource table to parse 29 | * @param len - size of rsc table 30 | * @param io - pointer to the resource table I/O region 31 | * It can be NULL if the resource table 32 | * is in the local memory. 33 | * 34 | * @returns - execution status 35 | * 36 | */ 37 | int handle_rsc_table(struct remoteproc *rproc, 38 | struct resource_table *rsc_table, size_t len, 39 | struct metal_io_region *io); 40 | int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc); 41 | int handle_trace_rsc(struct remoteproc *rproc, void *rsc); 42 | int handle_vdev_rsc(struct remoteproc *rproc, void *rsc); 43 | int handle_vendor_rsc(struct remoteproc *rproc, void *rsc); 44 | 45 | /** 46 | * find_rsc 47 | * 48 | * find out location of a resource type in the resource table. 49 | * 50 | * @rsc_table - pointer to the resource table 51 | * @rsc_type - type of the resource 52 | * @index - index of the resource of the specified type 53 | * 54 | * return the offset to the resource on success, or 0 on failure 55 | */ 56 | size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index); 57 | 58 | #if defined __cplusplus 59 | } 60 | #endif 61 | 62 | #endif /* RSC_TABLE_PARSER_H */ 63 | -------------------------------------------------------------------------------- /lib/include/openamp/virtio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: BSD-3-Clause 3 | * 4 | * $FreeBSD$ 5 | */ 6 | 7 | #ifndef _VIRTIO_H_ 8 | #define _VIRTIO_H_ 9 | 10 | #include 11 | #include 12 | 13 | #if defined __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /* VirtIO device IDs. */ 18 | #define VIRTIO_ID_NETWORK 0x01UL 19 | #define VIRTIO_ID_BLOCK 0x02UL 20 | #define VIRTIO_ID_CONSOLE 0x03UL 21 | #define VIRTIO_ID_ENTROPY 0x04UL 22 | #define VIRTIO_ID_BALLOON 0x05UL 23 | #define VIRTIO_ID_IOMEMORY 0x06UL 24 | #define VIRTIO_ID_RPMSG 0x07UL /* remote processor messaging */ 25 | #define VIRTIO_ID_SCSI 0x08UL 26 | #define VIRTIO_ID_9P 0x09UL 27 | #define VIRTIO_DEV_ANY_ID (-1)UL 28 | 29 | /* Status byte for guest to report progress. */ 30 | #define VIRTIO_CONFIG_STATUS_ACK 0x01 31 | #define VIRTIO_CONFIG_STATUS_DRIVER 0x02 32 | #define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 33 | #define VIRTIO_CONFIG_STATUS_NEEDS_RESET 0x40 34 | #define VIRTIO_CONFIG_STATUS_FAILED 0x80 35 | 36 | /* Virtio device role */ 37 | #define VIRTIO_DEV_MASTER 0UL 38 | #define VIRTIO_DEV_SLAVE 1UL 39 | 40 | struct virtio_device_id { 41 | uint32_t device; 42 | uint32_t vendor; 43 | }; 44 | 45 | /* 46 | * Generate interrupt when the virtqueue ring is 47 | * completely used, even if we've suppressed them. 48 | */ 49 | #define VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24) 50 | 51 | /* 52 | * The guest should never negotiate this feature; it 53 | * is used to detect faulty drivers. 54 | */ 55 | #define VIRTIO_F_BAD_FEATURE (1 << 30) 56 | 57 | /* 58 | * Some VirtIO feature bits (currently bits 28 through 31) are 59 | * reserved for the transport being used (eg. virtio_ring), the 60 | * rest are per-device feature bits. 61 | */ 62 | #define VIRTIO_TRANSPORT_F_START 28 63 | #define VIRTIO_TRANSPORT_F_END 32 64 | 65 | typedef void (*virtio_dev_reset_cb)(struct virtio_device *vdev); 66 | 67 | struct virtio_dispatch; 68 | 69 | struct virtio_feature_desc { 70 | uint32_t vfd_val; 71 | const char *vfd_str; 72 | }; 73 | 74 | /** 75 | * struct virtio_vring_info 76 | * @vq virtio queue 77 | * @info vring alloc info 78 | * @notifyid vring notify id 79 | * @io metal I/O region of the vring memory, can be NULL 80 | */ 81 | struct virtio_vring_info { 82 | struct virtqueue *vq; 83 | struct vring_alloc_info info; 84 | uint32_t notifyid; 85 | struct metal_io_region *io; 86 | }; 87 | 88 | /* 89 | * Structure definition for virtio devices for use by the 90 | * applications/drivers 91 | */ 92 | 93 | struct virtio_device { 94 | uint32_t notifyid; /**< unique position on the virtio bus */ 95 | struct virtio_device_id id; /**< the device type identification 96 | * (used to match it with a driver 97 | */ 98 | uint64_t features; /**< the features supported by both ends. */ 99 | unsigned int role; /**< if it is virtio backend or front end. */ 100 | virtio_dev_reset_cb reset_cb; /**< user registered device callback */ 101 | const struct virtio_dispatch *func; /**< Virtio dispatch table */ 102 | void *priv; /**< TODO: remove pointer to virtio_device private data */ 103 | unsigned int vrings_num; /**< number of vrings */ 104 | struct virtio_vring_info *vrings_info; 105 | }; 106 | 107 | /* 108 | * Helper functions. 109 | */ 110 | const char *virtio_dev_name(uint16_t devid); 111 | void virtio_describe(struct virtio_device *dev, const char *msg, 112 | uint32_t features, 113 | struct virtio_feature_desc *feature_desc); 114 | 115 | /* 116 | * Functions for virtio device configuration as defined in Rusty Russell's 117 | * paper. 118 | * Drivers are expected to implement these functions in their respective codes. 119 | */ 120 | 121 | struct virtio_dispatch { 122 | uint8_t (*get_status)(struct virtio_device *dev); 123 | void (*set_status)(struct virtio_device *dev, uint8_t status); 124 | uint32_t (*get_features)(struct virtio_device *dev); 125 | void (*set_features)(struct virtio_device *dev, uint32_t feature); 126 | uint32_t (*negotiate_features)(struct virtio_device *dev, 127 | uint32_t features); 128 | 129 | /* 130 | * Read/write a variable amount from the device specific (ie, network) 131 | * configuration region. This region is encoded in the same endian as 132 | * the guest. 133 | */ 134 | void (*read_config)(struct virtio_device *dev, uint32_t offset, 135 | void *dst, int length); 136 | void (*write_config)(struct virtio_device *dev, uint32_t offset, 137 | void *src, int length); 138 | void (*reset_device)(struct virtio_device *dev); 139 | void (*notify)(struct virtqueue *vq); 140 | }; 141 | 142 | int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, 143 | unsigned int nvqs, const char *names[], 144 | vq_callback *callbacks[]); 145 | 146 | #if defined __cplusplus 147 | } 148 | #endif 149 | 150 | #endif /* _VIRTIO_H_ */ 151 | -------------------------------------------------------------------------------- /lib/include/openamp/virtio_ring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Rusty Russell IBM Corporation 2007. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | * 6 | * $FreeBSD$ 7 | */ 8 | 9 | #ifndef VIRTIO_RING_H 10 | #define VIRTIO_RING_H 11 | 12 | #if defined __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /* This marks a buffer as continuing via the next field. */ 17 | #define VRING_DESC_F_NEXT 1 18 | /* This marks a buffer as write-only (otherwise read-only). */ 19 | #define VRING_DESC_F_WRITE 2 20 | /* This means the buffer contains a list of buffer descriptors. */ 21 | #define VRING_DESC_F_INDIRECT 4 22 | 23 | /* The Host uses this in used->flags to advise the Guest: don't kick me 24 | * when you add a buffer. It's unreliable, so it's simply an 25 | * optimization. Guest will still kick if it's out of buffers. 26 | */ 27 | #define VRING_USED_F_NO_NOTIFY 1 28 | /* The Guest uses this in avail->flags to advise the Host: don't 29 | * interrupt me when you consume a buffer. It's unreliable, so it's 30 | * simply an optimization. 31 | */ 32 | #define VRING_AVAIL_F_NO_INTERRUPT 1 33 | 34 | /* VirtIO ring descriptors: 16 bytes. 35 | * These can chain together via "next". 36 | */ 37 | struct vring_desc { 38 | /* Address (guest-physical). */ 39 | uint64_t addr; 40 | /* Length. */ 41 | uint32_t len; 42 | /* The flags as indicated above. */ 43 | uint16_t flags; 44 | /* We chain unused descriptors via this, too. */ 45 | uint16_t next; 46 | }; 47 | 48 | struct vring_avail { 49 | uint16_t flags; 50 | uint16_t idx; 51 | uint16_t ring[0]; 52 | }; 53 | 54 | /* uint32_t is used here for ids for padding reasons. */ 55 | struct vring_used_elem { 56 | union { 57 | uint16_t event; 58 | /* Index of start of used descriptor chain. */ 59 | uint32_t id; 60 | }; 61 | /* Total length of the descriptor chain which was written to. */ 62 | uint32_t len; 63 | }; 64 | 65 | struct vring_used { 66 | uint16_t flags; 67 | uint16_t idx; 68 | struct vring_used_elem ring[0]; 69 | }; 70 | 71 | struct vring { 72 | unsigned int num; 73 | 74 | struct vring_desc *desc; 75 | struct vring_avail *avail; 76 | struct vring_used *used; 77 | }; 78 | 79 | /* The standard layout for the ring is a continuous chunk of memory which 80 | * looks like this. We assume num is a power of 2. 81 | * 82 | * struct vring { 83 | * // The actual descriptors (16 bytes each) 84 | * struct vring_desc desc[num]; 85 | * 86 | * // A ring of available descriptor heads with free-running index. 87 | * __u16 avail_flags; 88 | * __u16 avail_idx; 89 | * __u16 available[num]; 90 | * __u16 used_event_idx; 91 | * 92 | * // Padding to the next align boundary. 93 | * char pad[]; 94 | * 95 | * // A ring of used descriptor heads with free-running index. 96 | * __u16 used_flags; 97 | * __u16 used_idx; 98 | * struct vring_used_elem used[num]; 99 | * __u16 avail_event_idx; 100 | * }; 101 | * 102 | * NOTE: for VirtIO PCI, align is 4096. 103 | */ 104 | 105 | /* 106 | * We publish the used event index at the end of the available ring, and vice 107 | * versa. They are at the end for backwards compatibility. 108 | */ 109 | #define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) 110 | #define vring_avail_event(vr) ((vr)->used->ring[(vr)->num].event) 111 | 112 | static inline int vring_size(unsigned int num, unsigned long align) 113 | { 114 | int size; 115 | 116 | size = num * sizeof(struct vring_desc); 117 | size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) + 118 | sizeof(uint16_t); 119 | size = (size + align - 1) & ~(align - 1); 120 | size += sizeof(struct vring_used) + 121 | (num * sizeof(struct vring_used_elem)) + sizeof(uint16_t); 122 | 123 | return size; 124 | } 125 | 126 | static inline void 127 | vring_init(struct vring *vr, unsigned int num, uint8_t *p, unsigned long align) 128 | { 129 | vr->num = num; 130 | vr->desc = (struct vring_desc *)p; 131 | vr->avail = (struct vring_avail *)(p + num * sizeof(struct vring_desc)); 132 | vr->used = (struct vring_used *) 133 | (((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t) + 134 | align - 1) & ~(align - 1)); 135 | } 136 | 137 | /* 138 | * The following is used with VIRTIO_RING_F_EVENT_IDX. 139 | * 140 | * Assuming a given event_idx value from the other size, if we have 141 | * just incremented index from old to new_idx, should we trigger an 142 | * event? 143 | */ 144 | static inline int 145 | vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) 146 | { 147 | return (uint16_t)(new_idx - event_idx - 1) < 148 | (uint16_t)(new_idx - old); 149 | } 150 | 151 | #if defined __cplusplus 152 | } 153 | #endif 154 | 155 | #endif /* VIRTIO_RING_H */ 156 | -------------------------------------------------------------------------------- /lib/proxy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (PROJECT_LIB_SOURCES rpmsg_retarget.c) 2 | -------------------------------------------------------------------------------- /lib/remoteproc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (PROJECT_LIB_SOURCES elf_loader.c) 2 | collect (PROJECT_LIB_SOURCES remoteproc.c) 3 | collect (PROJECT_LIB_SOURCES remoteproc_virtio.c) 4 | collect (PROJECT_LIB_SOURCES rsc_table_parser.c) 5 | -------------------------------------------------------------------------------- /lib/remoteproc/rsc_table_parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Mentor Graphics Corporation 3 | * Copyright (c) 2018, Xilinx Inc. 4 | * All rights reserved. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc); 13 | 14 | /* Resources handler */ 15 | static const rsc_handler rsc_handler_table[] = { 16 | handle_carve_out_rsc, /**< carved out resource */ 17 | handle_dummy_rsc, /**< IOMMU dev mem resource */ 18 | handle_trace_rsc, /**< trace buffer resource */ 19 | handle_vdev_rsc, /**< virtio resource */ 20 | }; 21 | 22 | int handle_rsc_table(struct remoteproc *rproc, 23 | struct resource_table *rsc_table, size_t size, 24 | struct metal_io_region *io) 25 | { 26 | char *rsc_start; 27 | unsigned int rsc_type; 28 | unsigned int idx, offset; 29 | int status = 0; 30 | 31 | /* Validate rsc table header fields */ 32 | 33 | /* Minimum rsc table size */ 34 | if (sizeof(struct resource_table) > size) { 35 | return -RPROC_ERR_RSC_TAB_TRUNC; 36 | } 37 | 38 | /* Supported version */ 39 | if (rsc_table->ver != RSC_TAB_SUPPORTED_VERSION) { 40 | return -RPROC_ERR_RSC_TAB_VER; 41 | } 42 | 43 | /* Offset array */ 44 | offset = sizeof(struct resource_table) 45 | + rsc_table->num * sizeof(rsc_table->offset[0]); 46 | 47 | if (offset > size) { 48 | return -RPROC_ERR_RSC_TAB_TRUNC; 49 | } 50 | 51 | /* Reserved fields - must be zero */ 52 | if ((rsc_table->reserved[0] != 0 || rsc_table->reserved[1]) != 0) { 53 | return -RPROC_ERR_RSC_TAB_RSVD; 54 | } 55 | 56 | /* Loop through the offset array and parse each resource entry */ 57 | for (idx = 0; idx < rsc_table->num; idx++) { 58 | rsc_start = (char *)rsc_table; 59 | rsc_start += rsc_table->offset[idx]; 60 | if (io && 61 | metal_io_virt_to_offset(io, rsc_start) == METAL_BAD_OFFSET) 62 | return -RPROC_ERR_RSC_TAB_TRUNC; 63 | rsc_type = *((uint32_t *)rsc_start); 64 | if (rsc_type < RSC_LAST) 65 | status = rsc_handler_table[rsc_type](rproc, 66 | rsc_start); 67 | else if (rsc_type >= RSC_VENDOR_START && 68 | rsc_type <= RSC_VENDOR_END) 69 | status = handle_vendor_rsc(rproc, rsc_start); 70 | if (status == -RPROC_ERR_RSC_TAB_NS) { 71 | status = 0; 72 | continue; 73 | } 74 | else if (status) 75 | break; 76 | } 77 | 78 | return status; 79 | } 80 | 81 | /** 82 | * handle_carve_out_rsc 83 | * 84 | * Carveout resource handler. 85 | * 86 | * @param rproc - pointer to remote remoteproc 87 | * @param rsc - pointer to carveout resource 88 | * 89 | * @returns - 0 for success, or negative value for failure 90 | * 91 | */ 92 | int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc) 93 | { 94 | struct fw_rsc_carveout *carve_rsc = rsc; 95 | metal_phys_addr_t da; 96 | metal_phys_addr_t pa; 97 | size_t size; 98 | unsigned int attribute; 99 | 100 | /* Validate resource fields */ 101 | if (!carve_rsc) { 102 | return -RPROC_ERR_RSC_TAB_NP; 103 | } 104 | 105 | if (carve_rsc->reserved) { 106 | return -RPROC_ERR_RSC_TAB_RSVD; 107 | } 108 | pa = carve_rsc->pa; 109 | da = carve_rsc->da; 110 | size = carve_rsc->len; 111 | attribute = carve_rsc->flags; 112 | if (remoteproc_mmap(rproc, &pa, &da, size, attribute, NULL)) 113 | return 0; 114 | else 115 | return -RPROC_EINVAL; 116 | } 117 | 118 | int handle_vendor_rsc(struct remoteproc *rproc, void *rsc) 119 | { 120 | if (rproc && rproc->ops->handle_rsc) { 121 | struct fw_rsc_vendor *vend_rsc = rsc; 122 | size_t len = vend_rsc->len; 123 | 124 | return rproc->ops->handle_rsc(rproc, rsc, len); 125 | } 126 | return -RPROC_ERR_RSC_TAB_NS; 127 | } 128 | 129 | int handle_vdev_rsc(struct remoteproc *rproc, void *rsc) 130 | { 131 | struct fw_rsc_vdev *vdev_rsc = rsc; 132 | unsigned int notifyid, i, num_vrings; 133 | 134 | /* only assign notification IDs but do not initialize vdev */ 135 | notifyid = vdev_rsc->notifyid; 136 | notifyid = remoteproc_allocate_id(rproc, 137 | notifyid, notifyid + 1); 138 | if (notifyid != RSC_NOTIFY_ID_ANY) 139 | vdev_rsc->notifyid = notifyid; 140 | 141 | num_vrings = vdev_rsc->num_of_vrings; 142 | for (i = 0; i < num_vrings; i++) { 143 | struct fw_rsc_vdev_vring *vring_rsc; 144 | 145 | vring_rsc = &vdev_rsc->vring[i]; 146 | notifyid = vring_rsc->notifyid; 147 | notifyid = remoteproc_allocate_id(rproc, 148 | notifyid, 149 | notifyid + 1); 150 | if (notifyid != RSC_NOTIFY_ID_ANY) 151 | vdev_rsc->notifyid = notifyid; 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | /** 158 | * handle_trace_rsc 159 | * 160 | * trace resource handler. 161 | * 162 | * @param rproc - pointer to remote remoteproc 163 | * @param rsc - pointer to trace resource 164 | * 165 | * @returns - no service error 166 | * 167 | */ 168 | int handle_trace_rsc(struct remoteproc *rproc, void *rsc) 169 | { 170 | struct fw_rsc_trace *vdev_rsc = rsc; 171 | (void)rproc; 172 | 173 | if (vdev_rsc->da != FW_RSC_U32_ADDR_ANY && vdev_rsc->len != 0) 174 | return 0; 175 | /* FIXME: master should allocated a memory used by slave */ 176 | 177 | return -RPROC_ERR_RSC_TAB_NS; 178 | } 179 | 180 | /** 181 | * handle_dummy_rsc 182 | * 183 | * dummy resource handler. 184 | * 185 | * @param rproc - pointer to remote remoteproc 186 | * @param rsc - pointer to trace resource 187 | * 188 | * @returns - no service error 189 | * 190 | */ 191 | static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc) 192 | { 193 | (void)rproc; 194 | (void)rsc; 195 | 196 | return -RPROC_ERR_RSC_TAB_NS; 197 | } 198 | 199 | size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index) 200 | { 201 | struct resource_table *r_table = rsc_table; 202 | unsigned int i, rsc_index; 203 | unsigned int lrsc_type; 204 | char *rsc_start; 205 | 206 | metal_assert(r_table); 207 | /* Loop through the offset array and parse each resource entry */ 208 | rsc_index = 0; 209 | for (i = 0; i < r_table->num; i++) { 210 | rsc_start = (char *)r_table; 211 | rsc_start += r_table->offset[i]; 212 | lrsc_type = *((uint32_t *)rsc_start); 213 | if (lrsc_type == rsc_type) { 214 | if (rsc_index++ == index) 215 | return r_table->offset[i]; 216 | } 217 | } 218 | return 0; 219 | } 220 | -------------------------------------------------------------------------------- /lib/rpmsg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (PROJECT_LIB_SOURCES rpmsg.c) 2 | collect (PROJECT_LIB_SOURCES rpmsg_virtio.c) 3 | -------------------------------------------------------------------------------- /lib/rpmsg/rpmsg_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: BSD-3-Clause 3 | * 4 | * $FreeBSD$ 5 | */ 6 | 7 | #ifndef _RPMSG_INTERNAL_H_ 8 | #define _RPMSG_INTERNAL_H_ 9 | 10 | #include 11 | #include 12 | 13 | #if defined __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #ifdef RPMSG_DEBUG 18 | #include 19 | 20 | #define RPMSG_ASSERT(_exp, _msg) do { \ 21 | if (!(_exp)) { \ 22 | metal_log(METAL_LOG_EMERGENCY, \ 23 | "FATAL: %s - "_msg, __func__); \ 24 | while (1) { \ 25 | ; \ 26 | } \ 27 | } \ 28 | } while (0) 29 | #else 30 | #define RPMSG_ASSERT(_exp, _msg) do { \ 31 | if (!(_exp)) \ 32 | while (1) { \ 33 | ; \ 34 | } \ 35 | } while (0) 36 | #endif 37 | 38 | #define RPMSG_LOCATE_DATA(p) ((unsigned char *)(p) + sizeof(struct rpmsg_hdr)) 39 | /** 40 | * enum rpmsg_ns_flags - dynamic name service announcement flags 41 | * 42 | * @RPMSG_NS_CREATE: a new remote service was just created 43 | * @RPMSG_NS_DESTROY: a known remote service was just destroyed 44 | * @RPMSG_NS_CREATE_WITH_ACK: a new remote service was just created waiting 45 | * acknowledgment. 46 | */ 47 | enum rpmsg_ns_flags { 48 | RPMSG_NS_CREATE = 0, 49 | RPMSG_NS_DESTROY = 1, 50 | }; 51 | 52 | /** 53 | * struct rpmsg_hdr - common header for all rpmsg messages 54 | * @src: source address 55 | * @dst: destination address 56 | * @reserved: reserved for future use 57 | * @len: length of payload (in bytes) 58 | * @flags: message flags 59 | * 60 | * Every message sent(/received) on the rpmsg bus begins with this header. 61 | */ 62 | METAL_PACKED_BEGIN 63 | struct rpmsg_hdr { 64 | uint32_t src; 65 | uint32_t dst; 66 | uint32_t reserved; 67 | uint16_t len; 68 | uint16_t flags; 69 | } METAL_PACKED_END; 70 | 71 | /** 72 | * struct rpmsg_ns_msg - dynamic name service announcement message 73 | * @name: name of remote service that is published 74 | * @addr: address of remote service that is published 75 | * @flags: indicates whether service is created or destroyed 76 | * 77 | * This message is sent across to publish a new service, or announce 78 | * about its removal. When we receive these messages, an appropriate 79 | * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() 80 | * or ->remove() handler of the appropriate rpmsg driver will be invoked 81 | * (if/as-soon-as one is registered). 82 | */ 83 | METAL_PACKED_BEGIN 84 | struct rpmsg_ns_msg { 85 | char name[RPMSG_NAME_SIZE]; 86 | uint32_t addr; 87 | uint32_t flags; 88 | } METAL_PACKED_END; 89 | 90 | int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags); 91 | 92 | struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rvdev, 93 | const char *name, uint32_t addr, 94 | uint32_t dest_addr); 95 | void rpmsg_register_endpoint(struct rpmsg_device *rdev, 96 | struct rpmsg_endpoint *ept); 97 | 98 | static inline struct rpmsg_endpoint * 99 | rpmsg_get_ept_from_addr(struct rpmsg_device *rdev, uint32_t addr) 100 | { 101 | return rpmsg_get_endpoint(rdev, NULL, addr, RPMSG_ADDR_ANY); 102 | } 103 | 104 | #if defined __cplusplus 105 | } 106 | #endif 107 | 108 | #endif /* _RPMSG_INTERNAL_H_ */ 109 | -------------------------------------------------------------------------------- /lib/virtio/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | collect (PROJECT_LIB_SOURCES virtio.c) 2 | collect (PROJECT_LIB_SOURCES virtqueue.c) 3 | -------------------------------------------------------------------------------- /lib/virtio/virtio.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2011, Bryan Venteicher 3 | * All rights reserved. 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | #include 8 | 9 | static const char *virtio_feature_name(unsigned long feature, 10 | const struct virtio_feature_desc *); 11 | 12 | //TODO : This structure may change depending on the types of devices we support. 13 | static const struct virtio_ident { 14 | unsigned short devid; 15 | const char *name; 16 | } virtio_ident_table[] = { 17 | { 18 | VIRTIO_ID_NETWORK, "Network"}, { 19 | VIRTIO_ID_BLOCK, "Block"}, { 20 | VIRTIO_ID_CONSOLE, "Console"}, { 21 | VIRTIO_ID_ENTROPY, "Entropy"}, { 22 | VIRTIO_ID_BALLOON, "Balloon"}, { 23 | VIRTIO_ID_IOMEMORY, "IOMemory"}, { 24 | VIRTIO_ID_SCSI, "SCSI"}, { 25 | VIRTIO_ID_9P, "9P Transport"}, { 26 | 0, NULL} 27 | }; 28 | 29 | /* Device independent features. */ 30 | static const struct virtio_feature_desc virtio_common_feature_desc[] = { 31 | {VIRTIO_F_NOTIFY_ON_EMPTY, "NotifyOnEmpty"}, 32 | {VIRTIO_RING_F_INDIRECT_DESC, "RingIndirect"}, 33 | {VIRTIO_RING_F_EVENT_IDX, "EventIdx"}, 34 | {VIRTIO_F_BAD_FEATURE, "BadFeature"}, 35 | 36 | {0, NULL} 37 | }; 38 | 39 | const char *virtio_dev_name(unsigned short devid) 40 | { 41 | const struct virtio_ident *ident; 42 | 43 | for (ident = virtio_ident_table; ident->name != NULL; ident++) { 44 | if (ident->devid == devid) 45 | return ident->name; 46 | } 47 | 48 | return NULL; 49 | } 50 | 51 | static const char *virtio_feature_name(unsigned long val, 52 | const struct virtio_feature_desc *desc) 53 | { 54 | int i, j; 55 | const struct virtio_feature_desc *descs[2] = { desc, 56 | virtio_common_feature_desc 57 | }; 58 | 59 | for (i = 0; i < 2; i++) { 60 | if (!descs[i]) 61 | continue; 62 | 63 | for (j = 0; descs[i][j].vfd_val != 0; j++) { 64 | if (val == descs[i][j].vfd_val) 65 | return descs[i][j].vfd_str; 66 | } 67 | } 68 | 69 | return NULL; 70 | } 71 | 72 | void virtio_describe(struct virtio_device *dev, const char *msg, 73 | uint32_t features, struct virtio_feature_desc *desc) 74 | { 75 | (void)dev; 76 | (void)msg; 77 | (void)features; 78 | 79 | // TODO: Not used currently - keeping it for future use 80 | virtio_feature_name(0, desc); 81 | } 82 | 83 | int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, 84 | unsigned int nvqs, const char *names[], 85 | vq_callback *callbacks[]) 86 | { 87 | struct virtio_vring_info *vring_info; 88 | struct vring_alloc_info *vring_alloc; 89 | unsigned int num_vrings, i; 90 | int ret; 91 | (void)flags; 92 | 93 | num_vrings = vdev->vrings_num; 94 | if (nvqs > num_vrings) 95 | return ERROR_VQUEUE_INVLD_PARAM; 96 | /* Initialize virtqueue for each vring */ 97 | for (i = 0; i < nvqs; i++) { 98 | vring_info = &vdev->vrings_info[i]; 99 | 100 | vring_alloc = &vring_info->info; 101 | #ifndef VIRTIO_SLAVE_ONLY 102 | if (vdev->role == VIRTIO_DEV_MASTER) { 103 | size_t offset; 104 | struct metal_io_region *io = vring_info->io; 105 | 106 | offset = metal_io_virt_to_offset(io, 107 | vring_alloc->vaddr); 108 | metal_io_block_set(io, offset, 0, 109 | vring_size(vring_alloc->num_descs, 110 | vring_alloc->align)); 111 | } 112 | #endif 113 | ret = virtqueue_create(vdev, i, names[i], vring_alloc, 114 | callbacks[i], vdev->func->notify, 115 | vring_info->vq); 116 | if (ret) 117 | return ret; 118 | } 119 | return 0; 120 | } 121 | 122 | --------------------------------------------------------------------------------