Moving OpenAMP sources to GIT repo.
authoreanjum <etsam_anjum@mentor.com>
Fri, 10 Oct 2014 10:24:20 +0000 (15:24 +0500)
committereanjum <etsam_anjum@mentor.com>
Fri, 10 Oct 2014 10:24:20 +0000 (15:24 +0500)
218 files changed:
Makefile [new file with mode: 0644]
Makefile.commons [new file with mode: 0644]
apps/Makefile [new file with mode: 0644]
apps/samples/master/baremetal/matrix_multiply/make [new file with mode: 0644]
apps/samples/master/baremetal/matrix_multiply/matrix_multiply.c [new file with mode: 0644]
apps/samples/master/linux/kernelspace/rpmsg_mat_mul_kern_app/rpmsg_mat_mul_kern_app.c [new file with mode: 0644]
apps/samples/master/linux/kernelspace/rpmsg_user_dev_driver/rpmsg_user_dev_driver.c [new file with mode: 0644]
apps/samples/master/linux/kernelspace/zynq_remoteproc_driver/remoteproc_internal.h [new file with mode: 0644]
apps/samples/master/linux/kernelspace/zynq_remoteproc_driver/zynq_remoteproc_driver.c [new file with mode: 0644]
apps/samples/master/linux/kernelspace/zynq_rpmsg_driver/zynq_rpmsg_driver.c [new file with mode: 0644]
apps/samples/master/linux/kernelspace/zynq_rpmsg_driver/zynq_rpmsg_internals.h [new file with mode: 0644]
apps/samples/master/linux/userspace/matrix_multiply/mat_mul_demo.c [new file with mode: 0644]
apps/samples/master/nucleus/matrix_multiply/nucleus_linux/make [new file with mode: 0644]
apps/samples/master/nucleus/matrix_multiply/nucleus_linux/matrix_multiply.c [new file with mode: 0644]
apps/samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/make [new file with mode: 0644]
apps/samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/matrix_multiply.c [new file with mode: 0644]
apps/samples/remote/baremetal/matrix_multiply/make [new file with mode: 0644]
apps/samples/remote/baremetal/matrix_multiply/matrix_multiply.c [new file with mode: 0644]
apps/samples/remote/baremetal/matrix_multiply/rsc_table.c [new file with mode: 0644]
apps/samples/remote/baremetal/matrix_multiply/rsc_table.h [new file with mode: 0644]
apps/samples/remote/baremetal/rpc_demo/make [new file with mode: 0644]
apps/samples/remote/baremetal/rpc_demo/rpc_demo.c [new file with mode: 0644]
apps/samples/remote/baremetal/rpc_demo/rsc_table.c [new file with mode: 0644]
apps/samples/remote/baremetal/rpc_demo/rsc_table.h [new file with mode: 0644]
apps/samples/remote/nucleus/matrix_multiply/make [new file with mode: 0644]
apps/samples/remote/nucleus/matrix_multiply/matrix_multiply.c [new file with mode: 0644]
apps/samples/remote/nucleus/matrix_multiply/rsc_table.c [new file with mode: 0644]
apps/samples/remote/nucleus/matrix_multiply/rsc_table.h [new file with mode: 0644]
apps/samples/remote/nucleus/rpc_demo/make [new file with mode: 0644]
apps/samples/remote/nucleus/rpc_demo/rpc_demo.c [new file with mode: 0644]
apps/samples/remote/nucleus/rpc_demo/rpc_demo.h [new file with mode: 0644]
apps/samples/remote/nucleus/rpc_demo/rsc_table.c [new file with mode: 0644]
apps/samples/remote/nucleus/rpc_demo/rsc_table.h [new file with mode: 0644]
apps/tests/master/baremetal/echo_test/echo_test.c [new file with mode: 0644]
apps/tests/master/baremetal/echo_test/make [new file with mode: 0644]
apps/tests/master/baremetal/func_test_suite/func_test_suite.c [new file with mode: 0644]
apps/tests/master/baremetal/func_test_suite/make [new file with mode: 0644]
apps/tests/master/baremetal/func_test_suite/test_suite.h [new file with mode: 0644]
apps/tests/master/linux/kernelspace/rpmsg_echo_test_kern_app/rpmsg_echo_test_kern_app.c [new file with mode: 0644]
apps/tests/master/linux/kernelspace/rpmsg_func_test_kern_app/rpmsg_func_test_kern_app.c [new file with mode: 0644]
apps/tests/master/linux/userspace/echo_test/echo_test.c [new file with mode: 0644]
apps/tests/master/nucleus/echo_test/nucleus_linux/echo_test.c [new file with mode: 0644]
apps/tests/master/nucleus/echo_test/nucleus_linux/make [new file with mode: 0644]
apps/tests/master/nucleus/echo_test/nucleus_nucleusbm/echo_test.c [new file with mode: 0644]
apps/tests/master/nucleus/echo_test/nucleus_nucleusbm/make [new file with mode: 0644]
apps/tests/master/nucleus/func_test_suite/nucleus_linux/func_test_suite.c [new file with mode: 0644]
apps/tests/master/nucleus/func_test_suite/nucleus_linux/make [new file with mode: 0644]
apps/tests/master/nucleus/func_test_suite/nucleus_linux/test_suite.h [new file with mode: 0644]
apps/tests/master/nucleus/func_test_suite/nucleus_nucleusbm/func_test_suite.c [new file with mode: 0644]
apps/tests/master/nucleus/func_test_suite/nucleus_nucleusbm/make [new file with mode: 0644]
apps/tests/master/nucleus/func_test_suite/nucleus_nucleusbm/test_suite.h [new file with mode: 0644]
apps/tests/master/nucleus/latency_test/nucleus_linux/latency_test.c [new file with mode: 0644]
apps/tests/master/nucleus/latency_test/nucleus_linux/make [new file with mode: 0644]
apps/tests/master/nucleus/latency_test/nucleus_nucleusbm/latency_test.c [new file with mode: 0644]
apps/tests/master/nucleus/latency_test/nucleus_nucleusbm/make [new file with mode: 0644]
apps/tests/remote/baremetal/echo_test/echo_test.c [new file with mode: 0644]
apps/tests/remote/baremetal/echo_test/make [new file with mode: 0644]
apps/tests/remote/baremetal/echo_test/rsc_table.c [new file with mode: 0644]
apps/tests/remote/baremetal/echo_test/rsc_table.h [new file with mode: 0644]
apps/tests/remote/baremetal/func_test_suite/func_test_suite.c [new file with mode: 0644]
apps/tests/remote/baremetal/func_test_suite/make [new file with mode: 0644]
apps/tests/remote/baremetal/func_test_suite/rsc_table.c [new file with mode: 0644]
apps/tests/remote/baremetal/func_test_suite/rsc_table.h [new file with mode: 0644]
apps/tests/remote/baremetal/func_test_suite/test_suite.h [new file with mode: 0644]
apps/tests/remote/nucleus/echo_test/echo_test.c [new file with mode: 0644]
apps/tests/remote/nucleus/echo_test/make [new file with mode: 0644]
apps/tests/remote/nucleus/echo_test/rsc_table.c [new file with mode: 0644]
apps/tests/remote/nucleus/echo_test/rsc_table.h [new file with mode: 0644]
apps/tests/remote/nucleus/func_test_suite/func_test_suite.c [new file with mode: 0644]
apps/tests/remote/nucleus/func_test_suite/make [new file with mode: 0644]
apps/tests/remote/nucleus/func_test_suite/rsc_table.c [new file with mode: 0644]
apps/tests/remote/nucleus/func_test_suite/rsc_table.h [new file with mode: 0644]
apps/tests/remote/nucleus/func_test_suite/test_suite.h [new file with mode: 0644]
common/hil/hil.c [new file with mode: 0644]
common/hil/hil.h [new file with mode: 0644]
common/llist/llist.c [new file with mode: 0644]
common/llist/llist.h [new file with mode: 0644]
common/shm/sh_mem.c [new file with mode: 0644]
common/shm/sh_mem.h [new file with mode: 0644]
docs/openamp_gs.pdf [new file with mode: 0644]
docs/openamp_perf_meas_gd.pdf [new file with mode: 0644]
docs/openamp_ref.pdf [new file with mode: 0644]
include/open_amp.h [new file with mode: 0644]
libs/system/zc702evk/baremetal/Makefile [new file with mode: 0644]
libs/system/zc702evk/baremetal/Makefile.commons [new file with mode: 0644]
libs/system/zc702evk/baremetal/baremetal.c [new file with mode: 0644]
libs/system/zc702evk/baremetal/baremetal.h [new file with mode: 0644]
libs/system/zc702evk/baremetal/libbaremetal_master.a [new file with mode: 0644]
libs/system/zc702evk/baremetal/libbaremetal_remote.a [new file with mode: 0644]
libs/system/zc702evk/baremetal/libbaremetal_remote_rpc.a [new file with mode: 0644]
libs/system/zc702evk/baremetal/linker_master.ld [new file with mode: 0644]
libs/system/zc702evk/baremetal/linker_remote.ld [new file with mode: 0644]
libs/system/zc702evk/baremetal/make_master [new file with mode: 0644]
libs/system/zc702evk/baremetal/make_remote [new file with mode: 0644]
libs/system/zc702evk/baremetal/make_remote_rpc [new file with mode: 0644]
libs/system/zc702evk/linux/boot.c [new file with mode: 0644]
libs/system/zc702evk/linux/boot_wrapper.S [new file with mode: 0644]
libs/system/zc702evk/linux/image.ub [new file with mode: 0644]
libs/system/zc702evk/linux/lib/arm-none-eabi-/libfdt.a [new file with mode: 0644]
libs/system/zc702evk/linux/lib/arm-none-eabi-/libzlib.a [new file with mode: 0644]
libs/system/zc702evk/linux/lib/arm-xilinx-eabi-/libfdt.a [new file with mode: 0644]
libs/system/zc702evk/linux/lib/arm-xilinx-eabi-/libzlib.a [new file with mode: 0644]
libs/system/zc702evk/linux/libfdt/fdt.h [new file with mode: 0644]
libs/system/zc702evk/linux/libfdt/libfdt.h [new file with mode: 0644]
libs/system/zc702evk/linux/libfdt/libfdt_internal.h [new file with mode: 0644]
libs/system/zc702evk/linux/libfdt/types.h [new file with mode: 0644]
libs/system/zc702evk/linux/link_remote.ld [new file with mode: 0644]
libs/system/zc702evk/linux/make [new file with mode: 0644]
libs/system/zc702evk/linux/patches/linux/petalinux2013.10/devtree.patch [new file with mode: 0644]
libs/system/zc702evk/linux/patches/linux/petalinux2013.10/gic.patch [new file with mode: 0644]
libs/system/zc702evk/linux/patches/linux/petalinux2013.10/readme.txt [new file with mode: 0644]
libs/system/zc702evk/linux/patches/linux/petalinux2013.10/system.dts [new file with mode: 0644]
libs/system/zc702evk/linux/rsc_table.c [new file with mode: 0644]
libs/system/zc702evk/linux/rsc_table.h [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/echo_test_baremetal_fw/Makefile [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/echo_test_nucleus_fw/Makefile [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/mat_mul_baremetal_fw/Makefile [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/mat_mul_demo/Makefile [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/mat_mul_nucleus_fw/Makefile [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/readme [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/rpc_demo_baremetal_fw/Makefile [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/makefiles/rpc_demo_nucleus_fw/Makefile [new file with mode: 0644]
libs/system/zc702evk/linux/scripts/open_amp_create_projects.sh [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/crc32.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/deflate.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/inffast.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/inffixed.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/inflate.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/inftrees.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/trees.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/zconf.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/zlib.h [new file with mode: 0644]
libs/system/zc702evk/linux/zlib/zutil.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/arch/arm/arch.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/arch/arm/arm_debug_defs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/arch/arm/arm_defs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/arch/arm/arm_mmu_defs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/arch/arm/tool-csgnu_arm/csgnu_arm_defs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/arch/arm/tool-csgnu_arm/toolset.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/bsp/arch/plat-zynq7000/platform.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/bsp/arch/plat-zynq7000/zynq7000_defs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/bsp/zc702evk_defs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/dev_mgr.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/eh_defs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/eh_extr.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/eqm.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/esal_extr.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/nu_kernel.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/plus_cfg.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/plus_core.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/plus_supplement.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/proc_extern.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/rtl.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/kernel/rtl_extr.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-none-eabi-/master/libnucleus_master.a [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-none-eabi-/master/nucleus_gen_cfg.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-none-eabi-/remote/libnucleus_remote.a [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-none-eabi-/remote/nucleus_gen_cfg.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-none-eabi-/remote_proxy/libnucleus_remote.a [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-none-eabi-/remote_proxy/nucleus_gen_cfg.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-xilinx-eabi-/master/libnucleus_master.a [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-xilinx-eabi-/master/nucleus_gen_cfg.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-xilinx-eabi-/remote/libnucleus_remote.a [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-xilinx-eabi-/remote/nucleus_gen_cfg.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-xilinx-eabi-/remote_proxy/libnucleus_remote.a [new file with mode: 0644]
libs/system/zc702evk/nucleus/lib/arm-xilinx-eabi-/remote_proxy/nucleus_gen_cfg.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/linker_master.ld [new file with mode: 0644]
libs/system/zc702evk/nucleus/linker_remote.ld [new file with mode: 0644]
libs/system/zc702evk/nucleus/nucleus.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/os/kernel/plus/core/inc/thread_control.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/cpu_dvfs.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/cpu_idle.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/cpu_selfrefresh.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/nu_services.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/nu_trace.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/nu_trace_os_mark.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/reg_api.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/reg_impl.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/reg_impl_mem_node.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/reg_status.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/runlevel_init.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/semaphore.h [new file with mode: 0644]
libs/system/zc702evk/nucleus/services/syslog_extern.h [new file with mode: 0644]
open_amp_build.sh [new file with mode: 0644]
porting/config/config.c [new file with mode: 0644]
porting/config/config.h [new file with mode: 0644]
porting/env/bm_env.c [new file with mode: 0644]
porting/env/env.h [new file with mode: 0644]
porting/env/nu_env.c [new file with mode: 0644]
porting/zc702evk/platform.c [new file with mode: 0644]
porting/zc702evk/platform.h [new file with mode: 0644]
porting/zc702evk/platform_info.c [new file with mode: 0644]
porting/zc702evk/zynq_trampoline.S [new file with mode: 0644]
proxy/master/linux/kernelspace/rpmsg_proxy_dev_driver.c [new file with mode: 0644]
proxy/master/linux/userspace/proxy_app.c [new file with mode: 0644]
proxy/master/linux/userspace/proxy_app.h [new file with mode: 0644]
proxy/remote/rpmsg_retarget/rpmsg_retarget.c [new file with mode: 0644]
proxy/remote/rpmsg_retarget/rpmsg_retarget.h [new file with mode: 0644]
remoteproc/elf_loader.c [new file with mode: 0644]
remoteproc/elf_loader.h [new file with mode: 0644]
remoteproc/remoteproc.c [new file with mode: 0644]
remoteproc/remoteproc.h [new file with mode: 0644]
remoteproc/remoteproc_loader.c [new file with mode: 0644]
remoteproc/remoteproc_loader.h [new file with mode: 0644]
remoteproc/rsc_table_parser.c [new file with mode: 0644]
remoteproc/rsc_table_parser.h [new file with mode: 0644]
rpmsg/Makefile [new file with mode: 0644]
rpmsg/remote_device.c [new file with mode: 0644]
rpmsg/rpmsg.c [new file with mode: 0644]
rpmsg/rpmsg.h [new file with mode: 0644]
rpmsg/rpmsg_core.c [new file with mode: 0644]
rpmsg/rpmsg_core.h [new file with mode: 0644]
virtio/Makefile [new file with mode: 0644]
virtio/virtio.c [new file with mode: 0644]
virtio/virtio.h [new file with mode: 0644]
virtio/virtio_ring.h [new file with mode: 0644]
virtio/virtqueue.c [new file with mode: 0644]
virtio/virtqueue.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..9703385
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,45 @@
+# Make file to create ipc stack library.\r
+\r
+# Include commons make file to get platform and tool chain specific variables.\r
+include Makefile.commons\r
+\r
+LIB := libs/open_amp/libopen_amp.a\r
+\r
+HEADERS += \\r
+$(wildcard */*.h) \\r
+$(wildcard *.h)\r
+\r
+C_SRCFILES += \\r
+$(wildcard *.c) \\r
+$(wildcard */*.c) \\r
+$(wildcard */*/*/*.c) \\r
+$(wildcard */*/*.c)\r
+\r
+AS_SRCFILES += \\r
+$(wildcard *.S) \\r
+$(wildcard */*.S) \\r
+$(wildcard */*/*/*.S) \\r
+$(wildcard */*/*.S)\r
+\r
+OBJFILES := $(patsubst %.c, %.o, $(C_SRCFILES)) $(patsubst %.S, %.o, $(AS_SRCFILES))\r
+\r
+DEPFILES := $(patsubst %.c, %.d, $(C_SRCFILES)) $(patsubst %.S, %.d, $(AS_SRCFILES))\r
+\r
+all: $(LIB)\r
+\r
+$(LIB): $(OBJFILES)\r
+       @echo AR $@\r
+       @$(AR) -r $@ $(OBJFILES)\r
+\r
+%.o:%.c $(HEADERS)\r
+       @echo CC $(<:.c=.o)\r
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@\r
+\r
+%.o:%.S\r
+       @echo AS $(<:.S=.o)\r
+       @$(AS) $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@\r
+\r
+clean:\r
+       -$(RM) $(LIB) $(OBJFILES) $(DEPFILES)\r
+\r
+PHONY: all clean\r
diff --git a/Makefile.commons b/Makefile.commons
new file mode 100644 (file)
index 0000000..0190e45
--- /dev/null
@@ -0,0 +1,85 @@
+\r
+TOOLSET          := csgnu\r
+CROSS            := arm-xilinx-eabi-\r
+CFLAGS           := -Wall -ffunction-sections -fdata-sections -O0 -g3 -MMD \r
+CXXFLAGS         := -Wall -fno-enforce-eh-specs -MMD\r
+ASFLAGS          := -gdwarf2 -meabi=4 -mcpu=cortex-a9 -mfpu=neon\r
+ARFLAGS          := \r
+ARCH_CFLAGS      := -gdwarf-2 -mthumb-interwork -mcpu=cortex-a9\r
+ARCH_CXXFLAGS    := -gdwarf-2 -mthumb-interwork -mcpu=cortex-a9\r
+ARCH_ASFLAGS     := -gdwarf-2 -mthumb-interwork -mcpu=cortex-a9\r
+ARCH_ARFLAGS     := \r
+CC               = $(CROSS)gcc\r
+CXX              = $(CROSS)g++\r
+AS               = $(CROSS)as\r
+AR               = $(CROSS)ar\r
+LD               = $(CROSS)gcc\r
+OBJCPY           = $(CROSS)objcopy\r
+INCLUDE          := \r
+RM               := rm -f\r
+CP               := cp\r
+OHOME            := $(OPENAMP)\r
+\r
+ifeq ($(PLAT),)\r
+export PLAT := zc702evk\r
+endif\r
+\r
+ifeq ($(OS),)\r
+export OS := nucleus\r
+endif\r
+\r
+BAREMETAL_INCLUDES := -I"$(OHOME)/libs/system/$(PLAT)/baremetal"\r
+NUCLEUS_INCLUDES := -I"$(OHOME)/libs/system/$(PLAT)/nucleus/arch/arm/tool-csgnu_arm" -I"$(OHOME)/libs/system/$(PLAT)/nucleus/bsp/arch/plat-zynq7000" -I"$(OHOME)/libs/system/$(PLAT)/nucleus" -I"$(OHOME)/libs/system/$(PLAT)/nucleus/arch/arm" \r
+GENERAL_INCLUDES := -I"$(OHOME)/include"\r
+\r
+ifeq ($(OS),nucleus)\r
+CFLAGS += $(NUCLEUS_INCLUDES)\r
+CFLAGS +=-D"ENV=0"\r
+ifeq ($(ROLE),master)\r
+CFLAGS +=-I"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/master"\r
+CFLAGS+=-D"MASTER=1"\r
+else\r
+CFLAGS +=-I"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/remote"\r
+CFLAGS+=-D"MASTER=0"\r
+endif\r
+endif\r
+\r
+ifeq ($(OS),baremetal)\r
+CFLAGS += $(BAREMETAL_INCLUDES)\r
+CFLAGS +=-D"ENV=1"\r
+\r
+ifeq ($(ROLE),master)\r
+CFLAGS+=-D"MASTER=1"\r
+else\r
+CFLAGS+=-D"MASTER=0"\r
+endif\r
+endif\r
+\r
+ifeq ($(BENCHMARK),1)\r
+CFLAGS+=-D"OPENAMP_BENCHMARK_ENABLE"\r
+endif\r
+\r
+ifeq ($(LINUXREMOTE),1)\r
+CFLAGS+=-D"OPENAMP_REMOTE_LINUX_ENABLE"\r
+endif\r
+\r
+CFLAGS += $(GENERAL_INCLUDES)\r
+\r
+#The example make file for csgnu and zynq platform would look like below\r
+\r
+#TOOLSET          := csgnu\r
+#CROSS            := arm-none-eabi-\r
+#CFLAGS           := -Wall -ffunction-sections -fdata-sections -O0 -g3\r
+#CXXFLAGS         := -Wall -fno-enforce-eh-specs\r
+#ASFLAGS          := -gdwarf2 -meabi=4 -mcpu=cortex-a9 -mfpu=neon\r
+#ARFLAGS          := \r
+#ARCH_CFLAGS      := -gdwarf-2 -mthumb-interwork -mcpu=cortex-a9\r
+#ARCH_CXXFLAGS    := -gdwarf-2 -mthumb-interwork -mcpu=cortex-a9\r
+#ARCH_ASFLAGS     := -gdwarf-2 -mthumb-interwork -mcpu=cortex-a9\r
+#ARCH_ARFLAGS     := \r
+#CC               = $(CROSS)gcc\r
+#CXX              = $(CROSS)g++\r
+#AS               = $(CROSS)as\r
+#AR               = $(CROSS)ar\r
+#INCLUDE          := \r
+#RM               := rm -f\r
diff --git a/apps/Makefile b/apps/Makefile
new file mode 100644 (file)
index 0000000..52dd627
--- /dev/null
@@ -0,0 +1,95 @@
+
+# Include commons make file to get platform and tool chain specific variables.
+
+
+include ../Makefile.commons
+
+all:
+ifeq ($(OS),nucleus)
+ifeq ($(ROLE),master)
+       make  -f samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/make
+       make  -f tests/master/nucleus/echo_test/nucleus_nucleusbm/make
+       make  -f tests/master/nucleus/func_test_suite/nucleus_nucleusbm/make
+else
+       make  -f samples/remote/nucleus/matrix_multiply/make
+       make  -f tests/remote/nucleus/echo_test/make
+       make  -f tests/remote/nucleus/func_test_suite/make
+       make  -f samples/remote/nucleus/rpc_demo/make
+endif
+endif                  
+ifeq ($(OS),baremetal) 
+ifeq ($(ROLE),remote)
+       make  -f samples/remote/baremetal/matrix_multiply/make
+       make  -f tests/remote/baremetal/echo_test/make
+       make  -f tests/remote/baremetal/func_test_suite/make
+       make  -f samples/remote/baremetal/rpc_demo/make
+endif
+endif
+
+benchmark:
+       make  -f tests/master/nucleus/latency_test/nucleus_nucleusbm/make
+
+linux_remote:
+ifeq ($(OS),nucleus)
+       make  -f samples/master/nucleus/matrix_multiply/nucleus_linux/make
+       make  -f tests/master/nucleus/echo_test/nucleus_linux/make
+       make  -f tests/master/nucleus/func_test_suite/nucleus_linux/make
+else
+       make  -f samples/master/baremetal/matrix_multiply/make
+       make  -f tests/master/baremetal/echo_test/make
+       make  -f tests/master/baremetal/func_test_suite/make
+endif
+
+linux_remote_benchmark:
+ifeq ($(OS),nucleus)
+       make  -f tests/master/nucleus/latency_test/nucleus_linux/make
+endif
+
+clean:
+ifeq ($(OS),nucleus)
+ifeq ($(ROLE),master)
+       make  -f samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/make clean
+       make  -f tests/master/nucleus/echo_test/nucleus_nucleusbm/make clean
+       make  -f tests/master/nucleus/func_test_suite/nucleus_nucleusbm/make clean
+else
+       make  -f samples/remote/nucleus/matrix_multiply/make clean
+       make  -f tests/remote/nucleus/echo_test/make clean
+       make  -f tests/remote/nucleus/func_test_suite/make clean
+       make  -f samples/remote/nucleus/rpc_demo/make clean
+endif
+endif                  
+ifeq ($(OS),baremetal)
+ifeq ($(ROLE),remote)
+       make  -f samples/remote/baremetal/matrix_multiply/make clean
+       make  -f tests/remote/baremetal/echo_test/make clean
+       make  -f tests/remote/baremetal/func_test_suite/make clean
+       make  -f samples/remote/baremetal/rpc_demo/make clean
+endif
+endif
+
+cleanbenchmark:
+       make  -f tests/master/nucleus/latency_test/nucleus_nucleusbm/make clean
+
+clean_linux_remote:
+ifeq ($(OS),nucleus)
+       make  -f samples/master/nucleus/matrix_multiply/nucleus_linux/make clean
+       make  -f tests/master/nucleus/echo_test/nucleus_linux/make clean
+       make  -f tests/master/nucleus/func_test_suite/nucleus_linux/make clean
+else
+       make  -f samples/master/baremetal/matrix_multiply/make clean
+       make  -f tests/master/baremetal/echo_test/make clean
+       make  -f tests/master/baremetal/func_test_suite/make clean
+endif
+
+clean_linux_remote_benchmark:
+ifeq ($(OS),nucleus)
+       make  -f tests/master/nucleus/latency_test/nucleus_linux/make clean
+endif
+
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/master/baremetal/matrix_multiply/make b/apps/samples/master/baremetal/matrix_multiply/make
new file mode 100644 (file)
index 0000000..4b53a17
--- /dev/null
@@ -0,0 +1,52 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := samples/master/baremetal/matrix_multiply/matrix_multiply.out
+SAMPLE_C_SRC := samples/master/baremetal/matrix_multiply/matrix_multiply.c
+
+
+REMOTE_OUT   := matrix_multiply.out
+DST_DIR := samples/master/baremetal/matrix_multiply
+LINUX_SRC_DIR := firmware/$(PLAT)/linux
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_C_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_C_SRC))
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+
+$(SAMPLE_OUT): $(REMOTE_OUT) $(SAMPLEOBJFILES)
+
+       @echo 'Building master core matrix multiply sample for baremetal : $@'
+
+       $(LD)  -Wl,-Map=samples/master/baremetal/matrix_multiply/matrix_multiply.map -Wl,--gc-sections -T"$(OHOME)/libs/system/$(PLAT)/baremetal/linker_master.ld" -L"$(OHOME)/libs/system/$(PLAT)/baremetal" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lbaremetal_master -lopen_amp -lc -lm -lstdc++ -lcs3 -lcs3arm -lcs3unhosted -Wl,--end-group       
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+       
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+       
+%.o:%.S
+       @$(AS) -c -mcpu=cortex-a9 $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@
+
+$(REMOTE_OUT):
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(LINUX_SRC_DIR)/firmware1.o $(DST_DIR)/firmware1.o
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(LINUX_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(LINUX_SRC_DIR)/; rm firmware1; rm firmware2;
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP) $(SAMPLE_BIN) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/master/baremetal/matrix_multiply/matrix_multiply.c b/apps/samples/master/baremetal/matrix_multiply/matrix_multiply.c
new file mode 100644 (file)
index 0000000..7eea207
--- /dev/null
@@ -0,0 +1,194 @@
+/* This is a sample demonstration application that showcases usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running baremetal
+and showcases booting of linux remote firmware using remoteproc and 
+IPC with remote firmware using rpmsg; Baremetal on master core acts as a remoteproc master
+but as an rpmsg remote;It brings up a remote Linux based 
+firmware which acts as an rpmsg master and offloads matrix multiplication to the baremetal context.
+Linux app generates two random matrices and transmits them to baremetal env which computes 
+the product and transmits results back to Linux. Once Linux application is complete, it
+requests a shutdown from baremetal env. Baremetal env acknowledges with a shutdown message which results
+in Linux starting a system halt. Baremetal env shutsdown the remot core after a reasonable delay which allows
+Linux to gracefully shutdown. */
+
+
+/* Including required headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "open_amp.h"
+
+#define BAREMETAL_MASTER 1
+
+#include "baremetal.h"
+
+#define MAX_SIZE        6
+#define NUM_MATRIX      2
+
+#define SHUTDOWN_MSG   0xEF56A55A
+
+
+typedef struct _matrix
+{
+    unsigned long size;
+    unsigned long elements[MAX_SIZE][MAX_SIZE];
+} matrix;
+
+
+static  matrix  matrix_array[NUM_MATRIX];
+
+static  matrix matrix_result;
+
+/* Prototypes */
+static void init_system();
+
+void sleep();
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric , unsigned long src );
+
+/* Globals */
+struct rpmsg_endpoint *rp_ept;
+struct rpmsg_channel *app_rp_chnl;
+char fw_name []= "firmware1";
+
+int int_flag;
+
+static int shutdown_called = 0;
+
+static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r)
+{
+    int i, j, k;
+
+    r->size = m->size;
+
+    for (i = 0; i < m->size; ++i) {
+        for (j = 0; j < n->size; ++j) {
+            r->elements[i][j] = 0;
+        }
+    }
+
+    for (i = 0; i < m->size; ++i) {
+        for (j = 0; j < n->size; ++j) {
+            for (k = 0; k < r->size; ++k) {
+                r->elements[i][j] += m->elements[i][k] * n->elements[k][j];
+            }
+        }
+    }
+}
+
+
+/* Application entry point */
+int main() {
+
+    int status;
+    struct remote_proc *proc;
+    int i;
+       int shutdown_msg = SHUTDOWN_MSG;
+    
+    /* Switch to System Mode */
+    SWITCH_TO_SYS_MODE();
+
+    /* Initialize HW system components */
+    init_system();
+    
+    status = remoteproc_init((void *) fw_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+    
+    if(!status)
+    {
+        status = remoteproc_boot(proc);
+    }
+    
+    if(status)
+    {
+           return -1;  
+       }
+    while (1) {
+               
+        if (int_flag) {
+                       
+                       if(shutdown_called == 1)
+                       {
+                           break;      
+                       }
+
+                        /* Process received data and multiple matrices. */
+                       Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);
+
+                       /* Send the result of matrix multiplication back to master. */
+                       rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix));
+                       
+                       int_flag = 0;
+                       
+                       sleep();
+        }
+        
+        sleep();
+    }
+    
+    /* Send shutdown message to remote */
+       rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
+
+    for (i = 0; i < 100000; i++)
+    {
+           sleep();
+    }
+    
+    remoteproc_shutdown(proc);
+        
+    remoteproc_deinit(proc);
+
+    return 0;
+}
+
+/* This callback gets invoked when the remote chanl is created */
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
+
+    app_rp_chnl = rp_chnl;
+    rp_ept = rpmsg_create_ept(rp_chnl , rpmsg_read_cb ,RPMSG_NULL , RPMSG_ADDR_ANY);
+
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
+    rpmsg_destroy_ept(rp_ept);
+}
+
+/* This is the read callback, note we are in a task context when this callback
+is invoked, so kernel primitives can be used freely */
+void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
+                void * priv, unsigned long src) {
+    
+    if ((*(int *) data) == SHUTDOWN_MSG)
+    {
+               shutdown_called  = 1;
+    }
+    else
+    {
+        memcpy(matrix_array, data, len);
+    }
+        
+    int_flag = 1;
+}
+
+void sleep() {
+    volatile int i;
+    for (i = 0; i < 10000000; i++);
+}
+
+static void init_system() {
+
+    /* Place the vector table at the image entry point */
+    arm_arch_install_isr_vector_table(RAM_VECTOR_TABLE_ADDR);
+
+    /* Enable MMU */
+    arm_ar_mem_enable_mmu();
+
+    /* Initialize ARM stacks */
+    init_arm_stacks();
+
+    /* Initialize GIC */
+    zc702evk_gic_initialize();
+}
+
diff --git a/apps/samples/master/linux/kernelspace/rpmsg_mat_mul_kern_app/rpmsg_mat_mul_kern_app.c b/apps/samples/master/linux/kernelspace/rpmsg_mat_mul_kern_app/rpmsg_mat_mul_kern_app.c
new file mode 100644 (file)
index 0000000..13cda8d
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * RPMSG Matrix Multiplication Kernel Driver
+ *
+ * Copyright (C) 2014 Mentor Graphics Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+/* Application */
+#define        MAX_SIZE                        6
+#define NUM_MATRIX                     2
+/* Shutdown message ID */
+#define SHUTDOWN_MSG                   0xEF56A55A
+
+struct rpmsg_endpoint *ept;
+static const char init_msg[] = "init_msg";
+
+static const char *const shutdown_argv[]
+               = { "/sbin/shutdown", "-h", "-P", "now", NULL };
+
+struct _matrix {
+       unsigned long size;
+       unsigned long elements[MAX_SIZE][MAX_SIZE];
+};
+
+static struct  _matrix *p_matrix;
+
+static void matrix_print(struct _matrix *m)
+{
+       int i, j;
+
+       /* Generate two random matrices */
+       pr_err(" \r\n Master : Linux : Printing results \r\n");
+
+       for (i = 0; i < m->size; ++i) {
+               for (j = 0; j < m->size; ++j)
+                       pr_cont(" %d ", (unsigned int)m->elements[i][j]);
+               pr_info("\r\n");
+       }
+}
+
+static void generate_matrices(int num_matrices, unsigned int matrix_size,
+                               void *p_data)
+{
+       int     i, j, k, val;
+       struct _matrix *p_matrix = p_data;
+
+       /* Generate two random matrices */
+       pr_err(" \r\n Master : Linux : Generating random matrices \r\n");
+
+       for (i = 0; i < num_matrices; i++) {
+
+               /* Initialize workload */
+               p_matrix[i].size = matrix_size;
+
+               pr_err(" \r\n Master : Linux : Input matrix %d \r\n", i);
+               for (j = 0; j < matrix_size; j++) {
+
+                       pr_info("\r\n");
+                       for (k = 0; k < matrix_size; k++) {
+                               get_random_bytes(&val, sizeof(val));
+                               p_matrix[i].elements[j][k] =
+                                               ((val & 0x7F) % 10);
+                               pr_cont(" %d ",
+                               (unsigned int)p_matrix[i].elements[j][k]);
+                       }
+               }
+               pr_err("\r\n");
+       }
+
+}
+
+static void rpmsg_mat_mul_kern_app_rx_cb(struct rpmsg_channel *rpdev,
+                       void *data, int len, void *priv, u32 src)
+{
+       int err;
+       int shutdown_msg = SHUTDOWN_MSG;
+
+       pr_err(" \r\n Master : Linux : Received %d bytes of data", len);
+       pr_err(" over rpmsg channel from remote \r\n");
+
+       /* Shutdown Linux if such a message is received. Only applicable
+               when Linux is a remoteproc remote. */
+       if ((*(int *) data) == SHUTDOWN_MSG) {
+               call_usermodehelper(shutdown_argv[0], shutdown_argv,
+                                       NULL, UMH_NO_WAIT);
+       } else {
+               /* print results */
+               matrix_print((struct _matrix *)data);
+
+               /* Send payload to remote. */
+               err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                                       &shutdown_msg, sizeof(int));
+
+               if (err)
+                       pr_err(" Shutdown send failed!\r\n");
+
+               kzfree(p_matrix);
+       }
+}
+
+static int rpmsg_mat_mul_kern_app_probe(struct rpmsg_channel *rpdev)
+{
+       int     err;
+
+       pr_err("\r\n Demo Start - Demo rpmsg driver got probed \r\n");
+       pr_err("since the rpmsg device associated with driver was found !\r\n");
+
+       pr_err("\r\n Create endpoint and register rx callback \r\n");
+       /* Create endpoint for remote channel and register rx callabck */
+       ept = rpmsg_create_ept(rpdev, rpmsg_mat_mul_kern_app_rx_cb, 0,
+                               RPMSG_ADDR_ANY);
+
+       if (!ept) {
+               pr_err(" Endpoint creation for failed!\r\n");
+               return -ENOMEM;
+       }
+
+       /* Send init message to complete the connection loop */
+       err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                               init_msg, sizeof(init_msg));
+
+       if (err) {
+               pr_err(" Init messages send failed!\r\n");
+               return err;
+       }
+
+       /* Allocate memory for random matrices */
+       p_matrix = kzalloc(sizeof(struct _matrix)*2, GFP_KERNEL);
+
+       /* Generate random matrices */
+       generate_matrices(NUM_MATRIX, MAX_SIZE, p_matrix);
+
+       /* Send matrices to remote for computation */
+       err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                               p_matrix, sizeof(struct _matrix) * 2);
+
+       pr_err("\r\n Master : Linux : Sent %d bytes of data over rpmsg channel to remote \r\n",
+               sizeof(struct _matrix) * 2);
+
+       if (err) {
+               pr_err(" send failed!\r\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static void rpmsg_mat_mul_kern_app_remove(struct rpmsg_channel *rpdev)
+{
+       rpmsg_destroy_ept(ept);
+}
+
+static void rpmsg_cb(struct rpmsg_channel *rpdev, void *data,
+                                       int len, void *priv, u32 src)
+{
+
+}
+
+static struct rpmsg_device_id rpmsg_mat_mul_kern_app_id_table[] = {
+       { .name = "rpmsg-openamp-demo-channel" },
+       { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_mat_mul_kern_app_id_table);
+
+static struct rpmsg_driver rpmsg_mat_mul_kern_app = {
+       .drv.name       = KBUILD_MODNAME,
+       .drv.owner      = THIS_MODULE,
+       .id_table       = rpmsg_mat_mul_kern_app_id_table,
+       .probe          = rpmsg_mat_mul_kern_app_probe,
+       .callback       = rpmsg_cb,
+       .remove = rpmsg_mat_mul_kern_app_remove,
+};
+
+static int __init init(void)
+{
+       return register_rpmsg_driver(&rpmsg_mat_mul_kern_app);
+}
+
+static void __exit fini(void)
+{
+       unregister_rpmsg_driver(&rpmsg_mat_mul_kern_app);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_DESCRIPTION("Sample rpmsg matrix multiplication kernel application");
+MODULE_LICENSE("GPL v2");
diff --git a/apps/samples/master/linux/kernelspace/rpmsg_user_dev_driver/rpmsg_user_dev_driver.c b/apps/samples/master/linux/kernelspace/rpmsg_user_dev_driver/rpmsg_user_dev_driver.c
new file mode 100644 (file)
index 0000000..97f48ae
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * RPMSG User Device Kernel Driver
+ *
+ * Copyright (C) 2014 Mentor Graphics Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/kfifo.h>
+#include <linux/uaccess.h>
+#include <linux/kthread.h>
+#include <linux/ioctl.h>
+#include <linux/errno.h>
+
+static struct class *rpmsg_class;
+static dev_t rpmsg_dev;
+
+struct _rpmsg_dev_params {
+       int rpmsg_major;
+       int rpmsg_minor;
+       struct device *rpmsg_dev;
+       struct cdev cdev;
+       struct rpmsg_channel *rpmsg_chnl;
+};
+
+struct _rpmsg_dev_instance {
+       struct rpmsg_endpoint *ept;
+       struct _rpmsg_dev_params *dev_params;
+       wait_queue_head_t usr_wait_q;
+       struct mutex sync_lock;
+};
+
+#define MAX_RPMSG_BUFF_SIZE            512
+#define RPMSG_KFIFO_SIZE               (MAX_RPMSG_BUFF_SIZE * 4)
+
+#define IOCTL_CMD_GET_KFIFO_SIZE       1
+#define IOCTL_CMD_GET_AVAIL_DATA_SIZE  2
+#define IOCTL_CMD_GET_FREE_BUFF_SIZE   3
+
+/* Shutdown message ID */
+#define SHUTDOWN_MSG                   0xEF56A55A
+
+static struct kfifo rpmsg_kfifo;
+static int block_flag ;
+static const char init_msg[] = "init_msg";
+
+static const char *const shutdown_argv[]
+               = { "/sbin/shutdown", "-h", "-P", "now", NULL };
+
+/* This callback gets invoked when we received data from the remote node */
+static void rpmsg_user_dev_drv_rx_cb(struct rpmsg_channel *rpdev,
+                       void *data, int len, void *priv, u32 src)
+{
+       struct _rpmsg_dev_instance *rpmsg_dev_instance = priv;
+
+       /* Shutdown Linux if such a message is received. Only applicable
+       when Linux is a remoteproc remote. */
+       if ((*(int *) data) == SHUTDOWN_MSG) {
+               call_usermodehelper(shutdown_argv[0], shutdown_argv,
+                                       NULL, UMH_NO_WAIT);
+       } else {
+               /* Push data received into rpmsg kfifo */
+               mutex_lock_interruptible(&rpmsg_dev_instance->sync_lock);
+               kfifo_in(&rpmsg_kfifo, data, (unsigned int)len);
+               mutex_unlock(&rpmsg_dev_instance->sync_lock);
+
+               /* Wake up any blocking contexts waiting for data */
+               block_flag = 1;
+               wake_up_interruptible(&rpmsg_dev_instance->usr_wait_q);
+       }
+}
+
+
+static int rpmsg_dev_open(struct inode *inode, struct file *p_file)
+{
+       struct _rpmsg_dev_instance *rpmsg_dev_instance;
+       struct _rpmsg_dev_params *rpmsg_dev_params;
+       int retval;
+
+       /* Create and initialize rpmsg device instance */
+       rpmsg_dev_instance = kzalloc(sizeof(struct _rpmsg_dev_instance),
+                                       GFP_KERNEL);
+
+       if (!rpmsg_dev_instance) {
+               pr_err("\r\n cannot allocate memory for rpmsg device instance \r\n");
+               return -ENOMEM;
+       }
+
+       /* Initialize rpmsg instance with device params from inode */
+       rpmsg_dev_instance->dev_params = container_of(inode->i_cdev,
+                                       struct _rpmsg_dev_params, cdev);
+
+       rpmsg_dev_params = rpmsg_dev_instance->dev_params;
+
+       /* Allocate kfifo for rpmsg */
+       retval = kfifo_alloc(&rpmsg_kfifo, RPMSG_KFIFO_SIZE, GFP_KERNEL);
+       kfifo_reset(&rpmsg_kfifo);
+
+       if (retval) {
+               pr_err("\r\n error in kfifo_alloc for rpmsg \r\n");
+
+               return retval;
+       }
+
+       /* Initialize mutex */
+       mutex_init(&rpmsg_dev_instance->sync_lock);
+
+       /* Initialize wait queue head that provides blocking rx for userspace */
+       init_waitqueue_head(&rpmsg_dev_instance->usr_wait_q);
+
+       p_file->private_data = rpmsg_dev_instance;
+
+       /* Create endpoint for remote channel and register rx callabck */
+       rpmsg_dev_instance->ept = rpmsg_create_ept(rpmsg_dev_params->rpmsg_chnl,
+                                               rpmsg_user_dev_drv_rx_cb,
+                                               rpmsg_dev_instance,
+                                               RPMSG_ADDR_ANY);
+
+
+       if (!rpmsg_dev_instance->ept) {
+               pr_err(" Endpoint creation for failed!\r\n");
+               return -ENOMEM;
+       }
+
+       /* Send init message to remote to complete the connection stage.
+       The message carries the address of new endpoint so that the
+       further messages from remote are received in its call back */
+       retval = rpmsg_send_offchannel(rpmsg_dev_params->rpmsg_chnl,
+                                       rpmsg_dev_instance->ept->addr,
+                                       rpmsg_dev_params->rpmsg_chnl->dst,
+                                       init_msg, sizeof(init_msg));
+
+       if (retval) {
+               pr_err(" Init message send failed!\r\n");
+               return retval;
+       }
+
+       return 0;
+}
+
+static ssize_t rpmsg_dev_write(struct file *p_file,
+                               const char __user *ubuff, size_t len,
+                               loff_t *p_off)
+{
+       struct _rpmsg_dev_instance *rpmsg_dev_instance = p_file->private_data;
+       struct _rpmsg_dev_params *rpmsg_dev_params
+                                       = rpmsg_dev_instance->dev_params;
+       int err;
+       unsigned int size;
+       char *tmp_buff;
+
+       if (len < MAX_RPMSG_BUFF_SIZE)
+               size = len;
+       else
+               size = MAX_RPMSG_BUFF_SIZE;
+
+       tmp_buff = kzalloc(size, GFP_KERNEL);
+
+       if (copy_from_user(tmp_buff, ubuff, size)) {
+               pr_err("\r\n user to kernel buff copy error \r\n");
+               return -1;
+       }
+
+       err = rpmsg_send_offchannel(rpmsg_dev_params->rpmsg_chnl,
+                                       rpmsg_dev_instance->ept->addr,
+                                       rpmsg_dev_params->rpmsg_chnl->dst,
+                                       tmp_buff, size);
+
+       if (err) {
+               size = 0;
+               pr_err("\r\n rpmsg_send_off_channel error \r\n");
+       }
+
+       return size;
+}
+
+static ssize_t rpmsg_dev_read(struct file *p_file, char __user *ubuff,
+                               size_t len, loff_t *p_off)
+{
+       struct _rpmsg_dev_instance *rpmsg_dev_instance = p_file->private_data;
+       int retval;
+       unsigned int data_available, data_used, bytes_copied;
+
+       /* Acquire lock to access rpmsg kfifo */
+       if (mutex_lock_interruptible(&rpmsg_dev_instance->sync_lock))
+               return -ERESTARTSYS;
+
+       data_available = kfifo_len(&rpmsg_kfifo);
+
+       if (data_available ==  0) {
+               /* Release lock */
+               mutex_unlock(&rpmsg_dev_instance->sync_lock);
+
+               /* if non-blocking read is requested return error */
+               if (p_file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+
+               /* Block the calling context till data becomes available */
+               wait_event_interruptible(rpmsg_dev_instance->usr_wait_q,
+                                       block_flag != 0);
+       }
+
+       /* reset block flag */
+       block_flag = 0;
+
+       /* Provide requested data size to user space */
+       data_available = kfifo_len(&rpmsg_kfifo);
+       data_used = (data_available > len) ? len : data_available;
+       retval = kfifo_to_user(&rpmsg_kfifo, ubuff, data_used, &bytes_copied);
+
+       /* Release lock on rpmsg kfifo */
+       mutex_unlock(&rpmsg_dev_instance->sync_lock);
+
+       return retval ? retval : bytes_copied;
+}
+
+static long rpmsg_dev_ioctl(struct file *p_file, unsigned int cmd,
+                               unsigned long arg)
+{
+       unsigned int tmp;
+
+       switch (cmd) {
+       case IOCTL_CMD_GET_KFIFO_SIZE:
+               tmp = kfifo_size(&rpmsg_kfifo);
+               if (copy_to_user((unsigned int *)arg, &tmp, sizeof(int)))
+                       return -EACCES;
+               break;
+
+       case IOCTL_CMD_GET_AVAIL_DATA_SIZE:
+               tmp = kfifo_len(&rpmsg_kfifo);
+               pr_err("kfifo len ioctl = %d ", kfifo_len(&rpmsg_kfifo));
+               if (copy_to_user((unsigned int *)arg, &tmp, sizeof(int)))
+                       return -EACCES;
+               break;
+       case IOCTL_CMD_GET_FREE_BUFF_SIZE:
+               tmp = kfifo_avail(&rpmsg_kfifo);
+               if (copy_to_user((unsigned int *)arg, &tmp, sizeof(int)))
+                       return -EACCES;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rpmsg_dev_release(struct inode *inode, struct file *p_file)
+{
+       struct _rpmsg_dev_instance *rpmsg_dev_instance = p_file->private_data;
+
+       rpmsg_destroy_ept(rpmsg_dev_instance->ept);
+       kfree(rpmsg_dev_instance);
+
+       return 0;
+}
+
+static const struct file_operations rpmsg_dev_fops = {
+       .owner = THIS_MODULE,
+       .read = rpmsg_dev_read,
+       .write = rpmsg_dev_write,
+       .open = rpmsg_dev_open,
+       .unlocked_ioctl = rpmsg_dev_ioctl,
+       .release = rpmsg_dev_release,
+};
+
+static int rpmsg_user_dev_drv_probe(struct rpmsg_channel *rpdev)
+{
+       struct _rpmsg_dev_params *rpmsg_dev_params;
+
+       /* Allocate memory for the rpmsg device parameters data structure */
+       rpmsg_dev_params = kzalloc(sizeof(struct _rpmsg_dev_params),
+                                       GFP_KERNEL);
+
+       if (!rpmsg_dev_params) {
+               pr_err("\r\n cannot allocate memory for rpmsg device params \r\n");
+               return -ENOMEM;
+       }
+
+       /* Initialize rpmsg device parameters data structure */
+       rpmsg_dev_params->rpmsg_major = MAJOR(rpmsg_dev);
+       rpmsg_dev_params->rpmsg_minor = 0;
+       /* Create device */
+       rpmsg_dev_params->rpmsg_dev = device_create(rpmsg_class, &rpdev->dev,
+                                               rpmsg_dev, NULL, "rpmsg");
+       if (rpmsg_dev_params->rpmsg_dev == NULL) {
+               class_destroy(rpmsg_class);
+               unregister_chrdev_region(rpmsg_dev, 1);
+               return -1;
+       }
+       /* Initialize character device */
+       cdev_init(&rpmsg_dev_params->cdev, &rpmsg_dev_fops);
+       rpmsg_dev_params->cdev.owner = THIS_MODULE;
+       if (cdev_add(&rpmsg_dev_params->cdev, rpmsg_dev, 1) == -1) {
+               device_destroy(rpmsg_class, rpmsg_dev);
+               class_destroy(rpmsg_class);
+               unregister_chrdev_region(rpmsg_dev, 1);
+               return -1;
+       }
+       rpmsg_dev_params->rpmsg_chnl = rpdev;
+
+       dev_set_drvdata(&rpdev->dev, rpmsg_dev_params);
+
+       dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+                       rpdev->src, rpdev->dst);
+
+       return 0;
+}
+
+static void rpmsg_user_dev_drv_remove(struct rpmsg_channel *rpdev)
+{
+       struct _rpmsg_dev_params *rpmsg_dev_params
+                                       = dev_get_drvdata(&rpdev->dev);
+
+       device_destroy(rpmsg_class, rpmsg_dev);
+       cdev_del(&rpmsg_dev_params->cdev);
+       kfree(rpmsg_dev_params);
+}
+
+static void rpmsg_cb(struct rpmsg_channel *rpdev, void *data,
+                                       int len, void *priv, u32 src)
+{
+
+}
+
+static struct rpmsg_device_id rpmsg_user_dev_drv_id_table[] = {
+       { .name = "rpmsg-openamp-demo-channel" },
+       { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_user_dev_drv_id_table);
+
+static struct rpmsg_driver rpmsg_user_dev_drv = {
+       .drv.name       = KBUILD_MODNAME,
+       .drv.owner      = THIS_MODULE,
+       .id_table       = rpmsg_user_dev_drv_id_table,
+       .probe          = rpmsg_user_dev_drv_probe,
+       .callback       = rpmsg_cb,
+       .remove = rpmsg_user_dev_drv_remove,
+};
+
+static int __init init(void)
+{
+       /* Allocate char device for this rpmsg driver */
+       if (alloc_chrdev_region(&rpmsg_dev, 0, 1, KBUILD_MODNAME) < 0) {
+               pr_err("\r\n Error allocating char device \r\n");
+               return -1;
+       }
+
+       /* Create device class for this device */
+       rpmsg_class = class_create(THIS_MODULE, KBUILD_MODNAME);
+
+       if (rpmsg_class == NULL) {
+               unregister_chrdev_region(rpmsg_dev, 1);
+               pr_err("\r\n Error allocating char device \r\n");
+               return -1;
+       }
+
+       /* Register this rpmsg driver with the rpmsg bus layer */
+       return register_rpmsg_driver(&rpmsg_user_dev_drv);
+}
+
+static void __exit fini(void)
+{
+       unregister_rpmsg_driver(&rpmsg_user_dev_drv);
+       class_destroy(rpmsg_class);
+       unregister_chrdev_region(rpmsg_dev, 1);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_DESCRIPTION("Sample driver to exposes rpmsg svcs to userspace via a char device");
+MODULE_LICENSE("GPL v2");
diff --git a/apps/samples/master/linux/kernelspace/zynq_remoteproc_driver/remoteproc_internal.h b/apps/samples/master/linux/kernelspace/zynq_remoteproc_driver/remoteproc_internal.h
new file mode 100644 (file)
index 0000000..94e3dcc
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Remote processor framework
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef REMOTEPROC_INTERNAL_H
+#define REMOTEPROC_INTERNAL_H
+
+#include <linux/irqreturn.h>
+#include <linux/firmware.h>
+
+struct rproc;
+
+/**
+ * struct rproc_fw_ops - firmware format specific operations.
+ * @find_rsc_table:    finds the resource table inside the firmware image
+ * @load:              load firmeware to memory, where the remote processor
+ *                     expects to find it
+ * @sanity_check:      sanity check the fw image
+ * @get_boot_addr:     get boot address to entry point specified in firmware
+ */
+struct rproc_fw_ops {
+       struct resource_table *(*find_rsc_table) (struct rproc *rproc,
+                                               const struct firmware *fw,
+                                               int *tablesz);
+       int (*load)(struct rproc *rproc, const struct firmware *fw);
+       int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
+       u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
+};
+
+/* from remoteproc_core.c */
+void rproc_release(struct kref *kref);
+irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
+
+/* from remoteproc_virtio.c */
+int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
+void rproc_remove_virtio_dev(struct rproc_vdev *rvdev);
+
+/* from remoteproc_debugfs.c */
+void rproc_remove_trace_file(struct dentry *tfile);
+struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc,
+                                       struct rproc_mem_entry *trace);
+void rproc_delete_debug_dir(struct rproc *rproc);
+void rproc_create_debug_dir(struct rproc *rproc);
+void rproc_init_debugfs(void);
+void rproc_exit_debugfs(void);
+
+void rproc_free_vring(struct rproc_vring *rvring);
+int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
+
+void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
+int rproc_trigger_recovery(struct rproc *rproc);
+
+static inline
+int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
+{
+       if (rproc->fw_ops->sanity_check)
+               return rproc->fw_ops->sanity_check(rproc, fw);
+
+       return 0;
+}
+
+static inline
+u32 rproc_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
+{
+       if (rproc->fw_ops->get_boot_addr)
+               return rproc->fw_ops->get_boot_addr(rproc, fw);
+
+       return 0;
+}
+
+static inline
+int rproc_load_segments(struct rproc *rproc, const struct firmware *fw)
+{
+       if (rproc->fw_ops->load)
+               return rproc->fw_ops->load(rproc, fw);
+
+       return -EINVAL;
+}
+
+static inline
+struct resource_table *rproc_find_rsc_table(struct rproc *rproc,
+                               const struct firmware *fw, int *tablesz)
+{
+       if (rproc->fw_ops->find_rsc_table)
+               return rproc->fw_ops->find_rsc_table(rproc, fw, tablesz);
+
+       return NULL;
+}
+
+extern const struct rproc_fw_ops rproc_elf_fw_ops;
+
+extern int __cpuinit zynq_cpun_start(u32 address, int cpu);
+
+#endif /* REMOTEPROC_INTERNAL_H */
diff --git a/apps/samples/master/linux/kernelspace/zynq_remoteproc_driver/zynq_remoteproc_driver.c b/apps/samples/master/linux/kernelspace/zynq_remoteproc_driver/zynq_remoteproc_driver.c
new file mode 100644 (file)
index 0000000..021ff83
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Zynq Remote Processor driver
+ *
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012 PetaLogix
+ *
+ * Based on origin OMAP Remote Processor driver
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/remoteproc.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/smp.h>
+#include <asm/hardware/gic.h>
+#include <asm/outercache.h>
+#include <asm/cacheflush.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+
+#include "remoteproc_internal.h"
+
+/* Module parameter */
+static char *firmware;
+
+/* Structure for storing IRQs */
+struct irq_list {
+       int irq;
+       struct list_head list;
+};
+
+/* Private data */
+struct zynq_rproc_pdata {
+       struct irq_list mylist;
+       struct rproc *rproc;
+       u32 ipino;
+       u32 vring0;
+       u32 vring1;
+       u32 mem_start;
+       u32 mem_end;
+};
+
+/* Store rproc for IPI handler */
+static struct platform_device *remoteprocdev;
+static struct work_struct workqueue;
+
+static void handle_event(struct work_struct *work)
+{
+       struct zynq_rproc_pdata *local = platform_get_drvdata(remoteprocdev);
+
+       flush_cache_all();
+       outer_flush_range(local->mem_start, local->mem_end);
+
+       if (rproc_vq_interrupt(local->rproc, 0) == IRQ_NONE)
+               dev_dbg(&remoteprocdev->dev, "no message found in vqid 0\n");
+}
+
+static void ipi_kick(void)
+{
+       dev_dbg(&remoteprocdev->dev, "KICK Linux because of pending message\n");
+       schedule_work(&workqueue);
+}
+
+static int zynq_rproc_start(struct rproc *rproc)
+{
+       struct device *dev = rproc->dev.parent;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct zynq_rproc_pdata *local = platform_get_drvdata(pdev);
+       int ret;
+
+       dev_dbg(dev, "%s\n", __func__);
+       INIT_WORK(&workqueue, handle_event);
+
+       flush_cache_all();
+       outer_flush_range(local->mem_start, local->mem_end);
+
+       remoteprocdev = pdev;
+       ret = zynq_cpun_start(0, 1);
+
+       return ret;
+}
+
+/* kick a firmware */
+static void zynq_rproc_kick(struct rproc *rproc, int vqid)
+{
+       struct device *dev = rproc->dev.parent;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct zynq_rproc_pdata *local = platform_get_drvdata(pdev);
+
+       dev_dbg(dev, "KICK Firmware to start send messages vqid %d\n",
+                                                                       vqid);
+       /* Send swirq to firmware */
+       if (!vqid)
+               gic_raise_softirq(cpumask_of(1), local->vring0);
+       else
+               gic_raise_softirq(cpumask_of(1), local->vring1);
+}
+
+/* power off the remote processor */
+static int zynq_rproc_stop(struct rproc *rproc)
+{
+       dev_dbg(rproc->dev.parent, "%s\n", __func__);
+
+       /* FIXME missing reset option */
+       return 0;
+}
+
+static struct rproc_ops zynq_rproc_ops = {
+       .start    = zynq_rproc_start,
+       .stop      = zynq_rproc_stop,
+       .kick      = zynq_rproc_kick,
+};
+
+/* Just to detect bug if interrupt forwarding is broken */
+static irqreturn_t zynq_remoteproc_interrupt(int irq, void *dev_id)
+{
+       struct device *dev = dev_id;
+
+       dev_err(dev, "GIC IRQ %d is not forwarded correctly\n", irq);
+
+       /*
+        *  MS: Calling this function doesn't need to be BUG
+        * especially for cases where firmware doesn't disable
+        * interrupts. In next probing can be som interrupts pending.
+        * The next scenario is for cases when you want to monitor
+        * non frequent interrupt through Linux kernel. Interrupt happen
+        * and it is forwarded to Linux which update own statistic
+        * in (/proc/interrupt) and forward it to firmware.
+        *
+        * gic_set_cpu(1, irq); - setup cpu1 as destination cpu
+        * gic_raise_softirq(cpumask_of(1), irq); - forward irq to firmware
+        */
+
+       gic_set_cpu(1, irq);
+       return IRQ_HANDLED;
+}
+
+static void clear_irq(struct platform_device *pdev)
+{
+       struct list_head *pos, *q;
+       struct irq_list *tmp;
+       struct zynq_rproc_pdata *local = platform_get_drvdata(pdev);
+
+       dev_info(&pdev->dev, "Deleting the irq_list\n");
+       list_for_each_safe(pos, q, &local->mylist.list) {
+               tmp = list_entry(pos, struct irq_list, list);
+               free_irq(tmp->irq, &pdev->dev);
+               gic_set_cpu(0, tmp->irq);
+               list_del(pos);
+               kfree(tmp);
+       }
+}
+
+static int zynq_remoteproc_probe(struct platform_device *pdev)
+{
+       const unsigned char *prop;
+       const void *of_prop;
+       struct resource *res; /* IO mem resources */
+       int ret = 0;
+       struct irq_list *tmp;
+       int count;
+       struct zynq_rproc_pdata *local;
+
+       ret = cpu_down(1);
+       /* EBUSY means CPU is already released */
+       if (ret && (ret != -EBUSY)) {
+               dev_err(&pdev->dev, "Can't release cpu1\n");
+               return -ENOMEM;
+       }
+
+       local = kzalloc(sizeof(struct zynq_rproc_pdata), GFP_KERNEL);
+       if (!local) {
+               dev_err(&pdev->dev, "Unable to alloc private data\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, local);
+
+       /* Declare memory for firmware */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "invalid address\n");
+               return -ENODEV;
+       }
+
+       local->mem_start = res->start;
+       local->mem_end = res->end;
+
+       /* Alloc phys addr from 0 to max_addr for firmware */
+       ret = dma_declare_coherent_memory(&pdev->dev, local->mem_start,
+               local->mem_start, local->mem_end - local->mem_start + 1,
+               DMA_MEMORY_IO);
+       if (!ret) {
+               dev_err(&pdev->dev, "dma_declare_coherent_memory failed\n");
+               goto dma_fault;
+       }
+
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret) {
+               dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
+               goto dma_fault;
+       }
+
+       /* Init list for IRQs - it can be long list */
+       INIT_LIST_HEAD(&local->mylist.list);
+
+       count = of_irq_count(pdev->dev.of_node);
+       /* Alloc IRQ based on DTS to be sure that no other driver will use it */
+       while (count--) {
+               tmp = kzalloc(sizeof(struct irq_list), GFP_KERNEL);
+               if (!tmp) {
+                       dev_err(&pdev->dev, "Unable to alloc irq list\n");
+                       ret = -ENOMEM;
+                       goto irq_fault;
+               }
+
+               tmp->irq = irq_of_parse_and_map(pdev->dev.of_node, count);
+
+               dev_dbg(&pdev->dev, "%d: Alloc irq: %d\n", count, tmp->irq);
+
+               /* Allocating shared IRQs will ensure that any module will
+                * use these IRQs */
+               ret = request_irq(tmp->irq, zynq_remoteproc_interrupt, 0,
+                                       dev_name(&pdev->dev), &pdev->dev);
+               if (ret) {
+                       dev_err(&pdev->dev, "IRQ %d already allocated\n",
+                                                               tmp->irq);
+                       goto irq_fault;
+               }
+
+               /*
+                * MS: Here is place for detecting problem with firmware
+                * which doesn't work correctly with interrupts
+                *
+                * MS: Comment if you want to count IRQs on Linux
+                */
+               gic_set_cpu(1, tmp->irq);
+               list_add(&(tmp->list), &(local->mylist.list));
+       }
+
+       /* Allocate free IPI number */
+       of_prop = of_get_property(pdev->dev.of_node, "ipino", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify ipino node property\n");
+               goto ipi_fault;
+       }
+
+       local->ipino = be32_to_cpup(of_prop);
+       ret = set_ipi_handler(local->ipino, ipi_kick, "Firmware kick");
+       if (ret) {
+               dev_err(&pdev->dev, "IPI handler already registered\n");
+               goto ipi_fault;
+       }
+
+       /* Let the vring0 use the same ipi number. This will avoid the
+               need of having separate interrupt from remote side */
+       local->vring0 = local->ipino;
+
+       /* Read vring1 ipi number */
+       of_prop = of_get_property(pdev->dev.of_node, "vring1", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify vring1 node property\n");
+               goto ipi_fault;
+       }
+       local->vring1 = be32_to_cpup(of_prop);
+
+       /* Module param firmware first */
+       if (firmware)
+               prop = firmware;
+       else
+               prop = of_get_property(pdev->dev.of_node, "firmware", NULL);
+
+       if (prop) {
+               dev_dbg(&pdev->dev, "Using firmware: %s\n", prop);
+               local->rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev),
+                               &zynq_rproc_ops, prop, sizeof(struct rproc));
+               if (!local->rproc) {
+                       dev_err(&pdev->dev, "rproc allocation failed\n");
+                       goto rproc_fault;
+               }
+
+               ret = rproc_add(local->rproc);
+               if (ret) {
+                       dev_err(&pdev->dev, "rproc registration failed\n");
+                       goto rproc_fault;
+               }
+
+               return ret;
+       } else
+               ret = -ENODEV;
+
+rproc_fault:
+       rproc_put(local->rproc);
+ipi_fault:
+       clear_ipi_handler(local->ipino);
+
+irq_fault:
+       clear_irq(pdev);
+
+dma_fault:
+       /* Cpu can't be power on - for example in nosmp mode */
+       ret |= cpu_up(1);
+       if (ret)
+               dev_err(&pdev->dev, "Can't power on cpu1 %d\n", ret);
+
+       return ret;
+}
+
+static int zynq_remoteproc_remove(struct platform_device *pdev)
+{
+       struct zynq_rproc_pdata *local = platform_get_drvdata(pdev);
+       u32 ret;
+
+       dev_info(&pdev->dev, "%s\n", __func__);
+
+       dma_release_declared_memory(&pdev->dev);
+
+       clear_ipi_handler(local->ipino);
+       clear_irq(pdev);
+
+       rproc_del(local->rproc);
+       rproc_put(local->rproc);
+
+       /* Cpu can't be power on - for example in nosmp mode */
+       ret = cpu_up(1);
+       if (ret)
+               dev_err(&pdev->dev, "Can't power on cpu1 %d\n", ret);
+
+       return 0;
+}
+
+/* Match table for OF platform binding */
+static struct of_device_id zynq_remoteproc_match[] = {
+       { .compatible = "xlnx,zynq_remoteproc", },
+       { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, zynq_remoteproc_match);
+
+static struct platform_driver zynq_remoteproc_driver = {
+       .probe = zynq_remoteproc_probe,
+       .remove = zynq_remoteproc_remove,
+       .driver = {
+               .name = "zynq_remoteproc",
+               .owner = THIS_MODULE,
+               .of_match_table = zynq_remoteproc_match,
+       },
+};
+module_platform_driver(zynq_remoteproc_driver);
+
+module_param(firmware, charp, 0);
+MODULE_PARM_DESC(firmware, "Override the firmware image name. Default value in DTS.");
+
+MODULE_AUTHOR("Michal Simek <monstr@monstr.eu");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Zynq remote processor control driver");
diff --git a/apps/samples/master/linux/kernelspace/zynq_rpmsg_driver/zynq_rpmsg_driver.c b/apps/samples/master/linux/kernelspace/zynq_rpmsg_driver/zynq_rpmsg_driver.c
new file mode 100644 (file)
index 0000000..9ac17ca
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Zynq Remote Processor Messaging Framework driver
+ *
+ * Copyright (C) 2014 Mentor Graphics Corporation
+ *
+ * Based on Zynq Remote Processor driver
+ *
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012 PetaLogix
+ *
+ * Based on origin OMAP Remote Processor driver
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_irq.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_ring.h>
+#include <linux/virtio_config.h>
+#include <asm/outercache.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/idr.h>
+
+#include "zynq_rpmsg_internals.h"
+
+static DEFINE_IDA(rpmsg_zynq_dev_index);
+
+/* Globals. */
+struct work_struct zynq_rpmsg_work;
+
+struct platform_device *zynq_rpmsg_platform;
+struct zynq_rpmsg_instance *zynq_rpmsg_p;
+
+static void zynq_rpmsg_virtio_notify(struct virtqueue *vq)
+{
+       /* Notify the other core. */
+       if (vq == zynq_rpmsg_p->vrings[0].vq)
+               /* Raise soft IRQ on GIC. */
+               gic_raise_softirq_unicore(0, zynq_rpmsg_p->vring0);
+       else
+               gic_raise_softirq_unicore(0, zynq_rpmsg_p->vring1);
+}
+
+static void zynq_rpmsg_virtio_del_vqs(struct virtio_device *vdev)
+{
+       struct zynq_rpmsg_vring   *local_vring;
+       int i;
+
+       for (i = 0; i < ZYNQ_RPMSG_NUM_VRINGS; i++) {
+
+               local_vring = &(zynq_rpmsg_p->vrings[i]);
+
+               vring_del_virtqueue(local_vring->vq);
+
+               local_vring->vq =  NULL;
+
+               dma_free_coherent(&(zynq_rpmsg_platform->dev),
+                                       local_vring->len, local_vring->va,
+                                       local_vring->dma);
+       }
+}
+
+static int zynq_rpmsg_virtio_find_vqs(struct virtio_device *vdev,
+                                       unsigned nvqs, struct virtqueue *vqs[],
+                                       vq_callback_t *callbacks[],
+                                       const char *names[])
+{
+       int                             i;
+       struct zynq_rpmsg_vring   *local_vring;
+       void                            *vring_va;
+       int                              size;
+
+       /* Skip through the vrings. */
+       for (i = 0; i < nvqs; i++) {
+
+               local_vring = &(zynq_rpmsg_p->vrings[i]);
+
+               local_vring->len = zynq_rpmsg_p->num_descs;
+
+               size = vring_size(zynq_rpmsg_p->num_descs,
+                                       zynq_rpmsg_p->align);
+
+               /* Allocate non-cacheable memory for the vring. */
+               local_vring->va = dma_alloc_coherent
+                                       (&(zynq_rpmsg_platform->dev),
+                                       size, &(local_vring->dma), GFP_KERNEL);
+
+               vring_va = local_vring->va;
+
+               memset(vring_va, 0, size);
+
+               local_vring->vq = vring_new_virtqueue(i,
+                                               zynq_rpmsg_p->num_descs,
+                                               zynq_rpmsg_p->align, vdev,
+                                               false, vring_va,
+                                               zynq_rpmsg_virtio_notify,
+                                               callbacks[i], names[i]);
+
+               vqs[i] = local_vring->vq;
+       }
+
+       return 0;
+}
+
+static u8 zynq_rpmsg_virtio_get_status(struct virtio_device *vdev)
+{
+       return 0;
+}
+
+static void zynq_rpmsg_virtio_set_status(struct virtio_device *vdev, u8 status)
+{
+   /* */
+}
+
+static void zynq_rpmsg_virtio_reset(struct virtio_device *vdev)
+{
+       /* */
+}
+
+static u32 zynq_rpmsg_virtio_get_features(struct virtio_device *vdev)
+{
+       /* Return features. */
+       return zynq_rpmsg_p->dev_feature;
+}
+
+static void zynq_rpmsg_virtio_finalize_features(struct virtio_device *vdev)
+{
+       /* Set vring transport features. */
+       vring_transport_features(vdev);
+
+       zynq_rpmsg_p->gen_feature = vdev->features[0];
+}
+
+static void zynq_rpmsg_vdev_release(struct device *dev)
+{
+
+}
+
+static void mid_level_type_release(struct device *dev)
+{
+
+}
+
+static struct virtio_config_ops zynq_rpmsg_virtio_config_ops = {
+       .get_features   = zynq_rpmsg_virtio_get_features,
+       .finalize_features = zynq_rpmsg_virtio_finalize_features,
+       .find_vqs       = zynq_rpmsg_virtio_find_vqs,
+       .del_vqs        = zynq_rpmsg_virtio_del_vqs,
+       .reset          = zynq_rpmsg_virtio_reset,
+       .set_status     = zynq_rpmsg_virtio_set_status,
+       .get_status     = zynq_rpmsg_virtio_get_status,
+};
+
+static struct device_type mid_level_type = {
+       .name           = "rpmsg_mid",
+       .release        = mid_level_type_release,
+};
+
+static void handle_event(struct work_struct *work)
+{
+       struct virtqueue *vq;
+
+       flush_cache_all();
+
+       outer_flush_range(zynq_rpmsg_p->mem_start, zynq_rpmsg_p->mem_end);
+
+       vq = zynq_rpmsg_p->vrings[0].vq;
+
+       if (vring_interrupt(0, vq) == IRQ_NONE)
+               dev_dbg(&zynq_rpmsg_platform->dev, "no message found in vqid 0\n");
+}
+
+static void ipi_handler(void)
+{
+       schedule_work(&zynq_rpmsg_work);
+}
+
+static int zynq_rpmsg_deinitialize(struct platform_device *pdev)
+{
+       unregister_virtio_device(&(zynq_rpmsg_p->virtio_dev));
+
+       put_device(&(zynq_rpmsg_p->mid_dev));
+
+       dma_release_declared_memory(&pdev->dev);
+
+       clear_ipi_handler(zynq_rpmsg_p->vring0);
+
+       return 0;
+}
+
+static int zynq_rpmsg_initialize(struct platform_device *pdev)
+{
+       int ret = 0;
+       int index;
+       struct virtio_device *virtio_dev;
+
+       /* Register ipi handler. */
+       ret = set_ipi_handler(zynq_rpmsg_p->vring0, ipi_handler,
+                               "Firmware kick");
+
+       if (ret) {
+               dev_err(&pdev->dev, "IPI handler already registered\n");
+               return -ENODEV;
+       }
+
+       /* Initialize work. */
+       INIT_WORK(&zynq_rpmsg_work, handle_event);
+
+       /* Memory allocations for vrings. */
+       ret = dma_declare_coherent_memory(&pdev->dev,
+                                       zynq_rpmsg_p->mem_start,
+                                       zynq_rpmsg_p->mem_start,
+                                       zynq_rpmsg_p->mem_end -
+                                       zynq_rpmsg_p->mem_start + 1,
+                                       DMA_MEMORY_IO);
+
+       if (!ret) {
+               dev_err(&pdev->dev, "dma_declare_coherent_memory failed\n");
+               return -ENODEV;
+       }
+
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+       if (ret) {
+               dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
+               return -ENODEV;
+       }
+
+       /* Initialize a mid-level device. Needed because of bad data structure
+        * handling and assumptions within the virtio rpmsg bus. We are doing it
+        * to just make sure that the virtio device has a parent device which
+        * then itself has a parent in the form of the platform device. */
+       device_initialize(&(zynq_rpmsg_p->mid_dev));
+
+       zynq_rpmsg_p->mid_dev.parent = &(pdev->dev);
+       zynq_rpmsg_p->mid_dev.type = &mid_level_type;
+
+       index = ida_simple_get(&rpmsg_zynq_dev_index, 0, 0, GFP_KERNEL);
+
+       if (index < 0) {
+               put_device(&(zynq_rpmsg_p->mid_dev));
+               return -ENODEV;
+       }
+
+       dev_set_name(&(zynq_rpmsg_p->mid_dev), "rpmsg_mid%d", index);
+
+       device_add(&(zynq_rpmsg_p->mid_dev));
+
+       /* Setup the virtio device structure. */
+       virtio_dev = &(zynq_rpmsg_p->virtio_dev);
+
+       virtio_dev->id.device   = zynq_rpmsg_p->virtioid;
+       virtio_dev->config        = &zynq_rpmsg_virtio_config_ops;
+       virtio_dev->dev.parent  = &(zynq_rpmsg_p->mid_dev);
+       virtio_dev->dev.release = zynq_rpmsg_vdev_release;
+
+       /* Register the virtio device. */
+       ret = register_virtio_device(virtio_dev);
+
+       dev_info(&(zynq_rpmsg_platform->dev), "virtio device registered \r\n");
+
+       return ret;
+}
+
+static int zynq_rpmsg_retrieve_dts_info(struct platform_device *pdev)
+{
+       const void *of_prop;
+       struct resource *res;
+
+       /* Retrieve memory information. */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "invalid address\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->mem_start = res->start;
+       zynq_rpmsg_p->mem_end = res->end;
+
+       /* Allocate free IPI number */
+       of_prop = of_get_property(pdev->dev.of_node, "vring0", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify vring0 node property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->vring0 = be32_to_cpup(of_prop);
+
+
+       /* Read vring1 ipi number */
+       of_prop = of_get_property(pdev->dev.of_node, "vring1", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify vring1 node property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->vring1 = be32_to_cpup(of_prop);
+
+       of_prop = of_get_property(pdev->dev.of_node, "num-descs", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify num descs node property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->num_descs = be32_to_cpup(of_prop);
+
+       /* Read dev-feature  */
+       of_prop = of_get_property(pdev->dev.of_node, "dev-feature", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify dev features node property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->dev_feature = be32_to_cpup(of_prop);
+
+       /* Read gen-feature */
+       of_prop = of_get_property(pdev->dev.of_node, "gen-feature", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify gen features node property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->gen_feature = be32_to_cpup(of_prop);
+
+       /* Read number of vrings */
+       of_prop = of_get_property(pdev->dev.of_node, "num-vrings", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify num-vrings node property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->num_vrings = be32_to_cpup(of_prop);
+
+       if (zynq_rpmsg_p->num_vrings > 2) {
+               dev_err(&pdev->dev, "We do not currently support more than 2 vrings.\n");
+               return -ENODEV;
+       }
+
+       /* Read vring alignment */
+       of_prop = of_get_property(pdev->dev.of_node, "alignment", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify alignment node property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->align = be32_to_cpup(of_prop);
+
+       /* Read virtio ID*/
+       of_prop = of_get_property(pdev->dev.of_node, "virtioid", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify virtio id property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->virtioid = be32_to_cpup(of_prop);
+
+       /* Read Ring Tx address. */
+       of_prop = of_get_property(pdev->dev.of_node, "ringtx", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify ring tx property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->ringtx = be32_to_cpup(of_prop);
+
+       /* Read Ring Rx address. */
+       of_prop = of_get_property(pdev->dev.of_node, "ringrx", NULL);
+       if (!of_prop) {
+               dev_err(&pdev->dev, "Please specify ringrx property\n");
+               return -ENODEV;
+       }
+
+       zynq_rpmsg_p->ringrx = be32_to_cpup(of_prop);
+
+       return 0;
+}
+
+static int zynq_rpmsg_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       zynq_rpmsg_platform = pdev;
+
+       /* Allocate memory for the Zynq RPMSG instance. */
+       zynq_rpmsg_p = kzalloc(sizeof(struct zynq_rpmsg_instance), GFP_KERNEL);
+
+       if (!zynq_rpmsg_p) {
+               dev_err(&pdev->dev, "Unable to alloc memory for zynq_rpmsg instance.\n");
+               return -ENOMEM;
+       }
+
+       /* Save the instance handle. */
+       platform_set_drvdata(pdev, zynq_rpmsg_p);
+
+       /* Retrieve the rquired information from DTS. */
+       ret = zynq_rpmsg_retrieve_dts_info(pdev);
+
+       if (ret) {
+               dev_err(&pdev->dev, "Failure in retrieving info from DTS.\n");
+               kzfree(zynq_rpmsg_p);
+               return -ENOMEM;
+       }
+
+       /* Perform all the initializations. */
+       ret = zynq_rpmsg_initialize(pdev);
+
+       return ret;
+}
+
+static int zynq_rpmsg_remove(struct platform_device *pdev)
+{
+       zynq_rpmsg_deinitialize(pdev);
+
+       kfree(zynq_rpmsg_p);
+
+       return 0;
+}
+
+
+/* Match table for OF platform binding */
+static struct of_device_id zynq_rpmsg_match[] = {
+       { .compatible = "xlnx,zynq_rpmsg_driver", },
+       { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, zynq_rpmsg_match);
+
+static struct platform_driver zynq_rpmsg_driver = {
+       .probe = zynq_rpmsg_probe,
+       .remove = zynq_rpmsg_remove,
+       .driver = {
+               .name = "zynq_rpmsg_driver",
+               .owner = THIS_MODULE,
+               .of_match_table = zynq_rpmsg_match,
+       },
+};
+
+static int __init init(void)
+{
+       return platform_driver_register(&zynq_rpmsg_driver);
+}
+
+static void __exit fini(void)
+{
+       platform_driver_unregister(&zynq_rpmsg_driver);
+}
+
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Zynq RPMSG driver to use RPMSG framework without remoteproc");
diff --git a/apps/samples/master/linux/kernelspace/zynq_rpmsg_driver/zynq_rpmsg_internals.h b/apps/samples/master/linux/kernelspace/zynq_rpmsg_driver/zynq_rpmsg_internals.h
new file mode 100644 (file)
index 0000000..45b0bdf
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Zynq Remote Processor Messaging Framework driver
+ *
+ * Copyright (C) 2014 Mentor Graphics Corporation
+ *
+ * Based on Zynq Remote Processor driver
+ *
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012 PetaLogix
+ *
+ * Based on origin OMAP Remote Processor driver
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#define ZYNQ_RPMSG_NUM_VRINGS          2
+struct zynq_rpmsg_vring {
+
+       void       *va;
+       dma_addr_t dma;
+       int             len;
+       u32             da;
+       u32             align;
+       struct virtqueue *vq;
+};
+
+struct zynq_rpmsg_instance {
+
+       u32      vring0;
+       u32      vring1;
+       u32      mem_start;
+       u32      mem_end;
+       u32      num_descs;
+       u32      dev_feature;
+       u32      gen_feature;
+       u32      num_vrings;
+       u32      align;
+       u32      virtioid;
+       u32      ringtx;
+       u32      ringrx;
+
+       struct virtio_device virtio_dev;
+
+       struct zynq_rpmsg_vring vrings[ZYNQ_RPMSG_NUM_VRINGS];
+
+       struct device mid_dev;
+};
+
+#ifndef CONFIG_SMP
+extern int set_ipi_handler(int ipinr, void *handler, char *desc);
+
+extern void clear_ipi_handler(int ipinr);
+
+extern void gic_raise_softirq_unicore(unsigned long cpu, unsigned int irq);
+#endif
+
diff --git a/apps/samples/master/linux/userspace/matrix_multiply/mat_mul_demo.c b/apps/samples/master/linux/userspace/matrix_multiply/mat_mul_demo.c
new file mode 100644 (file)
index 0000000..d1621cf
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Sample demo application that showcases inter processor
+ * communication from linux userspace to a remote software
+ * context. The application generates random matrices and
+ * transmits them to the remote context over rpmsg. The
+ * remote application performs multiplication of matrices
+ * and transmits the results back to this application.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <string.h>
+
+#define MATRIX_SIZE 6
+
+/* Shutdown message ID */
+#define SHUTDOWN_MSG   0xEF56A55A
+
+struct _matrix {
+       unsigned long size;
+       unsigned long elements[MATRIX_SIZE][MATRIX_SIZE];
+};
+
+static void matrix_print(struct _matrix *m)
+{
+       int i, j;
+
+       /* Generate two random matrices */
+       printf(" \r\n Master : Linux : Printing results \r\n");
+
+       for (i = 0; i < m->size; ++i) {
+               for (j = 0; j < m->size; ++j)
+                       printf(" %d ", (unsigned int)m->elements[i][j]);
+               printf("\r\n");
+       }
+}
+
+static void generate_matrices(int num_matrices,
+                               unsigned int matrix_size, void *p_data)
+{
+       int     i, j, k;
+       struct _matrix *p_matrix = p_data;
+       time_t  t;
+       unsigned long value;
+
+       srand((unsigned) time(&t));
+
+       for (i = 0; i < num_matrices; i++) {
+               /* Initialize workload */
+               p_matrix[i].size = matrix_size;
+
+               printf(" \r\n Master : Linux : Input matrix %d \r\n", i);
+               for (j = 0; j < matrix_size; j++) {
+                       printf("\r\n");
+                       for (k = 0; k < matrix_size; k++) {
+
+                               value = (rand() & 0x7F);
+                               value = value % 10;
+                               p_matrix[i].elements[j][k] = value;
+                               printf(" %d ",
+                               (unsigned int)p_matrix[i].elements[j][k]);
+                       }
+               }
+               printf("\r\n");
+       }
+
+}
+
+static pthread_t ui_thread, compute_thread;
+static pthread_mutex_t sync_lock;
+
+static int fd, compute_flag;
+static struct _matrix *i_matrix;
+static struct _matrix *r_matrix;
+
+#define RPMSG_GET_KFIFO_SIZE 1
+#define RPMSG_GET_FREE_SPACE 3
+
+void *ui_thread_entry(void *ptr)
+{
+       int cmd, ret;
+       int flag = 1;
+
+       while (flag) {
+               printf("\r\n **************************************** \r\n");
+               printf(" Please enter command and press enter key\r\n");
+               printf(" **************************************** \r\n");
+               printf(" 1 - Generates random 6x6 matrices and transmits");
+               printf(" them to remote core over rpmsg .. \r\n");
+               printf(" 2 - Quit this application .. \r\n");
+               printf(" CMD>");
+               ret = scanf("%d", &cmd);
+               if (!ret) {
+                       while (1) {
+                               if (getchar() == '\n')
+                                       break;
+                       }
+
+                       printf("\r\n invalid command\r\n");
+                       continue;
+               }
+               if (cmd == 1) {
+                       compute_flag = 1;
+                       pthread_mutex_unlock(&sync_lock);
+
+                       printf("\r\n Compute thread unblocked .. \r\n");
+                       printf(" The compute thread is now blocking on");
+                       printf("a read() from rpmsg device \r\n");
+                       printf("\r\n Generating random matrices now ... \r\n");
+
+                       i_matrix = malloc(sizeof(*i_matrix)*2);
+
+                       generate_matrices(2, 6, i_matrix);
+
+                       printf("\r\n Writing generated matrices to rpmsg ");
+                       printf("rpmsg device, %d bytes written .. \r\n",
+                                       sizeof(*i_matrix)*2);
+
+                       write(fd, i_matrix, sizeof(*i_matrix)*2);
+
+                       free(i_matrix);
+
+                       /* adding this so the threads
+                       dont overlay the strings they print */
+                       sleep(1);
+               } else if (cmd == 2) {
+                       flag = 0;
+                       compute_flag = 0;
+                       pthread_mutex_unlock(&sync_lock);
+                       printf("\r\n Quitting application .. \r\n");
+                       printf(" Matrix multiplication demo end \r\n");
+               } else {
+                       printf("\r\n invalid command! \r\n");
+               }
+       }
+
+       return 0;
+}
+
+void *compute_thread_entry(void *ptr)
+{
+       int bytes_rcvd;
+
+       pthread_mutex_lock(&sync_lock);
+
+       while (compute_flag == 1) {
+               r_matrix = malloc(sizeof(*r_matrix));
+
+               bytes_rcvd = read(fd, r_matrix, sizeof(*r_matrix));
+
+               printf("\r\n Received results! - %d bytes from ", bytes_rcvd);
+               printf("rpmsg device (transmitted from remote context) \r\n");
+
+               matrix_print(r_matrix);
+
+               free(r_matrix);
+
+               pthread_mutex_lock(&sync_lock);
+       }
+
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int size;
+       int shutdown_msg = SHUTDOWN_MSG;
+
+       printf("\r\n Matrix multiplication demo start \r\n");
+
+       printf("\r\n Open rpmsg dev! \r\n");
+
+       fd = open("/dev/rpmsg", O_RDWR);
+
+       printf("\r\n Query internal info .. \r\n");
+
+       ioctl(fd, RPMSG_GET_KFIFO_SIZE, &size);
+
+       printf(" rpmsg kernel fifo size = %u \r\n", size);
+
+       ioctl(fd, RPMSG_GET_FREE_SPACE, &size);
+
+       printf(" rpmsg kernel fifo free space = %u \r\n", size);
+
+       if (pthread_mutex_init(&sync_lock, NULL) != 0)
+               printf("\r\n mutex initialization failure \r\n");
+
+       pthread_mutex_lock(&sync_lock);
+
+       printf("\r\n Creating ui_thread and compute_thread ... \r\n");
+
+       pthread_create(&ui_thread, NULL, &ui_thread_entry, "ui_thread");
+
+       pthread_create(&compute_thread, NULL, &compute_thread_entry,
+                               "compute_thread");
+       pthread_join(ui_thread, NULL);
+
+       pthread_join(compute_thread, NULL);
+
+       /* Send shutdown message to remote */
+       write(fd, &shutdown_msg , sizeof(int));
+       sleep(1);
+
+       printf("\r\n Quitting application .. \r\n");
+       printf(" Matrix multiply application end \r\n");
+
+       close(fd);
+
+       pthread_mutex_destroy(&sync_lock);
+
+       return 0;
+}
+
+
diff --git a/apps/samples/master/nucleus/matrix_multiply/nucleus_linux/make b/apps/samples/master/nucleus/matrix_multiply/nucleus_linux/make
new file mode 100644 (file)
index 0000000..f008ac8
--- /dev/null
@@ -0,0 +1,52 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := samples/master/nucleus/matrix_multiply/nucleus_linux/matrix_multiply.out
+SAMPLE_C_SRC := samples/master/nucleus/matrix_multiply/nucleus_linux/matrix_multiply.c
+
+REMOTE_OUT   := matrix_multiply.out
+DST_DIR := samples/master/nucleus/matrix_multiply/nucleus_linux
+LINUX_SRC_DIR := firmware/$(PLAT)/linux
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_C_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_C_SRC))
+
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+
+$(SAMPLE_OUT): $(REMOTE_OUT) $(SAMPLEOBJFILES)
+
+       @echo 'Building master core matrix multiply sample for nucleus : $@'
+
+       $(LD)  -Wl,-Map=samples/master/nucleus/matrix_multiply/nucleus_linux/matrix_multiply.map  -nostartfiles -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=free -T"$(OHOME)/libs/system/$(PLAT)/nucleus/linker_master.ld" -L"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/master" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lnucleus_master -lopen_amp -lc -lm -lstdc++ -Wl,--end-group    
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+       
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+       
+%.o:%.S
+       @$(AS) -c -mcpu=cortex-a9 $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@
+       
+$(REMOTE_OUT):
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(LINUX_SRC_DIR)/firmware1.o $(DST_DIR)/firmware1.o
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(LINUX_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(LINUX_SRC_DIR)/; rm firmware1; rm firmware2;
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP) $(SAMPLE_BIN) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/master/nucleus/matrix_multiply/nucleus_linux/matrix_multiply.c b/apps/samples/master/nucleus/matrix_multiply/nucleus_linux/matrix_multiply.c
new file mode 100644 (file)
index 0000000..4632fe0
--- /dev/null
@@ -0,0 +1,243 @@
+/* This is a sample demonstration application that showcases usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running Nucleus
+and showcases booting of linux remote firmware using remoteproc and 
+IPC with remote firmware using rpmsg; Nucleus on master core acts as a remoteproc master
+but as an rpmsg remote;It brings up a remote Linux based 
+firmware which acts as an rpmsg master and offloads matrix multiplication to Nucleus.
+Linux app generates two random matrices and transmits them to Nucleus which computes 
+the product and transmits results back to Linux. Once Linux application is complete, it
+requests a shutdown from Nucleus. Nucleus acknowledges with a shutdown message which results
+in Linux starting a system halt. Nucleus shutsdown the remote core after a reasonable delay which allows
+Linux to gracefully shutdown. */
+
+/* Including required headers */
+#include  <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "open_amp.h"
+#include "nucleus.h"
+#include "kernel/nu_kernel.h"
+
+/* Define the main task's stack size */
+#define STACK_SIZE      (NU_MIN_STACK_SIZE * 64)
+
+/* Define the main task's priority */
+#define TASK_PRIORITY   26
+
+/* Define the main task's time slice */
+#define TASK_SLICE      20
+
+#define MAX_SIZE        6
+#define NUM_MATRIX      2
+/* Shutdown message ID */
+#define SHUTDOWN_MSG                   0xEF56A55A
+
+typedef struct _matrix
+{
+    unsigned long size;
+    unsigned long elements[MAX_SIZE][MAX_SIZE];
+} matrix;
+
+
+static  matrix  matrix_array[NUM_MATRIX];
+
+static  matrix matrix_result;
+
+/* Prototypes */
+static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric , unsigned long src );
+
+/* Globals */
+NU_TASK Task_Control_Block;
+NU_SEMAPHORE App_Sem;
+struct rpmsg_endpoint *rp_ept;
+struct rpmsg_channel *app_rp_chnl;
+char fw1_name []= "firmware1";
+
+static int shutdown_received = 0;
+
+static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r)
+{
+    int i, j, k;
+
+    r->size = m->size;
+
+    for (i = 0; i < m->size; ++i) {
+        for (j = 0; j < n->size; ++j) {
+            r->elements[i][j] = 0;
+        }
+    }
+
+    for (i = 0; i < m->size; ++i) {
+        for (j = 0; j < n->size; ++j) {
+            for (k = 0; k < r->size; ++k) {
+                r->elements[i][j] += m->elements[i][k] * n->elements[k][j];
+            }
+        }
+    }
+}
+
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Application_Initialize
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Demo application entry point
+ *
+ * ***********************************************************************/
+VOID Application_Initialize(NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
+{
+    VOID *pointer;
+    STATUS status = NU_SUCCESS;
+
+    /* Reference unused parameters to avoid toolset warnings */
+    NU_UNUSED_PARAM( uncached_mem_pool );
+
+    if (status == NU_SUCCESS)
+    {
+        status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
+
+        /* Create the main task for matrix processing */
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
+            uncached_mem_pool , pointer , STACK_SIZE , TASK_PRIORITY , TASK_SLICE ,
+            NU_PREEMPT , NU_START );
+        }
+        if(status == NU_SUCCESS)
+        {
+            status = NU_Create_Semaphore(&App_Sem ,"APP_SEM", 0, NU_FIFO);
+        }
+    }
+
+    /* Check to see if previous operations were successful */
+    if ( status != NU_SUCCESS )
+    {
+        /* Loop forever */
+        while ( 1 );
+    }
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Main_Task_Entry
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Entry function for the main task. This task prints a hello world
+ * *       message.
+ * *
+ * ***********************************************************************/
+static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv ) {
+
+    struct remote_proc *proc;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+    STATUS             status;
+    int shutdown_msg = SHUTDOWN_MSG;
+
+    status = NU_System_Memory_Get(&sys_pool_ptr, NU_NULL);
+    
+    /* Start first firmware*/
+    if(status == NU_SUCCESS)
+    {   
+               printf("\n\n\r************************************");
+               printf("*******************************************\r\n");
+               printf("\r\n              Matrix Multiplication Application \r\n");
+               printf("\r\n");
+               printf("\r\nThis sample application will boot a remote Linux firmware \r\n");
+               printf("\r\nThis sample application will boot a remote Linux firmware \r\n");
+               printf("\r\nand handle offloaded matrix multiplication operations from\r\n");
+               printf("\r\nLinux RPMSG master to Nuclues RPMS Remote \r\n");
+
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+    
+    
+        printf("\r\n\nLoading remote context : %s \r\n" , fw1_name);
+        
+        printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+            
+        status = remoteproc_init((void *) fw1_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+    }
+    
+    if((!status) && (proc))
+    {
+        printf("\r\n\n********************************************\r\n");
+        printf("BOOTING LINUX REMOTE FIRMWARE");
+           printf("\r\n********************************************\r\n\n");
+        status = remoteproc_boot(proc);
+    }
+    
+    if(!status)
+    {
+        while(1)
+        {
+                       NU_Obtain_Semaphore(&App_Sem, NU_SUSPEND);
+        
+               if(shutdown_received == 1)
+               {
+                           break;      
+               }
+               
+                       /* Process received data and multiple matrices. */
+                       Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);
+
+                       /* Send the result of matrix multiplication back to master. */
+                       rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix));
+           }
+           
+               /* Send shutdown message to remote */
+               rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
+               
+               /* The remote Linux kernel requires around ~15 seconds to shutdown itself. Wait. */
+               NU_Sleep(100 * 18);
+               
+               remoteproc_shutdown(proc);
+               
+               remoteproc_deinit(proc);
+    }
+    else
+    {
+        printf("\r\n\nLoading remote context: %s failed \r\n" , fw1_name);
+    }            
+}
+
+/* This callback gets invoked when the remote chanl is created */
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
+
+    app_rp_chnl = rp_chnl;
+    rp_ept = rpmsg_create_ept(rp_chnl , rpmsg_read_cb ,RPMSG_NULL , RPMSG_ADDR_ANY);
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
+
+    rpmsg_destroy_ept(rp_ept);
+}
+
+/* This is the read callback, note we are in a task context when this callback
+is invoked, so kernel primitives can be used freely */
+void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
+                void * priv, unsigned long src) {
+
+    if ((*(int *) data) == SHUTDOWN_MSG)
+    {
+               shutdown_received  = 1;
+    }
+       
+    memcpy(matrix_array, data, len);
+
+    NU_Release_Semaphore(&App_Sem);
+}
+
diff --git a/apps/samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/make b/apps/samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/make
new file mode 100644 (file)
index 0000000..e06c6c5
--- /dev/null
@@ -0,0 +1,57 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/matrix_multiply.out
+SAMPLE_C_SRC := samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/matrix_multiply.c
+
+REMOTE_OUT   := matrix_multiply.out
+DST_DIR := samples/master/nucleus/matrix_multiply/nucleus_nucleusbm
+NU_SRC_DIR := firmware/$(PLAT)/nucleus/matrix_multiply
+BM_SRC_DIR := firmware/$(PLAT)/baremetal/matrix_multiply
+
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_C_SRC))
+
+
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_C_SRC))
+
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+
+$(SAMPLE_OUT): $(REMOTE_OUT) $(SAMPLEOBJFILES)
+
+       @echo 'Building master core matrix multiply sample for nucleus : $@'
+
+       $(LD)  -Wl,-Map=samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/matrix_multiply.map  -nostartfiles -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=free -T"$(OHOME)/libs/system/$(PLAT)/nucleus/linker_master.ld" -L"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/master" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lnucleus_master -lopen_amp -lc -lm -lstdc++ -Wl,--end-group        
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+       
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+       
+%.o:%.S
+       @$(AS) -c -mcpu=cortex-a9 $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@
+       
+$(REMOTE_OUT):
+       cd $(NU_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(NU_SRC_DIR)/firmware1.o $(DST_DIR)/
+       cd $(BM_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(BM_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(NU_SRC_DIR)/; rm firmware1
+       cd $(BM_SRC_DIR)/; rm firmware2
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP) $(SAMPLE_BIN) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/matrix_multiply.c b/apps/samples/master/nucleus/matrix_multiply/nucleus_nucleusbm/matrix_multiply.c
new file mode 100644 (file)
index 0000000..6f983f1
--- /dev/null
@@ -0,0 +1,395 @@
+/* This is a sample demonstration application that showcases usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running Nucleus
+and showcases booting of two sub-sequent remote firmware cycles using remoteproc and 
+IPC with remote firmware using rpmsg; 1. It brings up a remote Nucleus based remote 
+firmware which performs matrix multiplication, 2. It brings up a baremetal based 
+remote firmware which performs matrix multiplication. Master app generates two random 
+matrices and transmits them to remotr firmware which computes the product and transmit 
+results back to master CPU */
+
+/* Including required headers */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "nucleus.h"
+#include "kernel/nu_kernel.h"
+#include "open_amp.h"
+
+/* Define the main task's stack size */
+#define STACK_SIZE      (NU_MIN_STACK_SIZE * 64)
+
+/* Define the main task's priority */
+#define TASK_PRIORITY   26
+
+/* Define the main task's time slice */
+#define TASK_SLICE      20
+
+#define MATRIX_SIZE    6
+
+#define SHUTDOWN_MSG   0xEF56A55A
+
+typedef struct _matrix
+{
+    unsigned long size;
+    unsigned long elements[MATRIX_SIZE][MATRIX_SIZE];
+} matrix;
+
+/* Prototypes */
+static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric , unsigned long src );
+
+/* Globals */
+NU_TASK Task_Control_Block;
+NU_SEMAPHORE App_Sem;
+
+struct rpmsg_endpoint *rp_ept;
+struct rpmsg_channel *app_rp_chnl;
+
+char fw1_name []= "firmware1"; /* Nucleus based matrix multiply remote firmware */
+char fw2_name []= "firmware2"; /* Baremetal based matrix multiply remote firmware */
+
+static struct _matrix* i_matrix;
+static struct _matrix* r_matrix;
+static int bytes_received;
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Application_Initialize
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Demo application entry point
+ *
+ * ***********************************************************************/
+VOID Application_Initialize(NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
+{
+    VOID *pointer;
+    STATUS status = NU_SUCCESS;
+
+    /* Reference unused parameters to avoid toolset warnings */
+    NU_UNUSED_PARAM( uncached_mem_pool );
+
+    if (status == NU_SUCCESS)
+    {
+        status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
+
+        /* Create the main task for matrix processing */
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
+            uncached_mem_pool , pointer , STACK_SIZE , TASK_PRIORITY , TASK_SLICE ,
+            NU_PREEMPT , NU_START );
+        }
+        if(status == NU_SUCCESS)
+        {
+            status = NU_Create_Semaphore(&App_Sem ,"APP_SEM", 0, NU_FIFO);
+        }
+    }
+
+    /* Check to see if previous operations were successful */
+    if ( status != NU_SUCCESS )
+    {
+        /* Loop forever */
+        while ( 1 );
+    }
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       matrix_print
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Function to print a matrix.
+ * *
+ * ***********************************************************************/
+static void matrix_print(struct _matrix* m)
+{
+    int i, j;
+
+    /* Generate two random matrices */
+    printf( " \r\n Master : Nucleus : Printing results \r\n");
+
+    for (i = 0; i < m->size; ++i) {
+        for (j = 0; j < m->size; ++j) {
+            printf(" %d ", (unsigned int)m->elements[i][j]);
+        }
+        printf("\r\n");
+    }
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       generate_matrices
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Function to generate random matrices.
+ * *
+ * ***********************************************************************/
+static void generate_matrices(int num_matrices, 
+                unsigned int matrix_size, void* p_data)
+{
+    int    i, j, k;
+    struct _matrix* p_matrix = p_data;
+    unsigned long value;
+
+    /* Seed for random number generator */
+    srand(ESAL_GE_TMR_OS_COUNT_READ());
+
+    for(i=0; i< num_matrices; i++)
+    {
+        /* Initialize workload */
+        p_matrix[i].size = matrix_size;
+        
+        printf( " \r\n Master : Nucleus : Input matrix %d \r\n", i);
+        for(j = 0; j < matrix_size; j++)
+        {
+            printf( "\r\n");
+            for(k = 0; k < matrix_size; k++)
+            {
+                value = (rand()&0x7F);
+                value = value%10;
+                p_matrix[i].elements[j][k] = value;
+                printf( " %d ", (unsigned int)p_matrix[i].elements[j][k]);
+            }
+        }
+        printf( "\r\n");
+    }
+    
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       matrix_multiply_shell
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Simple demo shell
+ * *
+ * ***********************************************************************/
+static void matrix_multiply_shell(void)
+{
+    unsigned char cmd;
+        
+    for ( ; ; )
+    {
+        printf("\r\n **************************************** \r\n");
+        printf(" Please enter command and press enter key\r\n");
+        printf(" **************************************** \r\n");
+        printf(" 1 - Generates random 6x6 matrices and transmits them to remote core over rpmsg .. \r\n"); 
+        printf(" 2 - Quit this application .. \r\n");
+        printf(" CMD>");
+        
+        cmd = getchar();
+        
+        if(cmd == '1')
+        {
+            printf("\r\n Generating random matrices now ... \r\n");            
+
+            generate_matrices(2, 6, i_matrix); 
+
+            printf("\r\n Writing generated matrices to rpmsg device, %d bytes written .. \r\n", \
+                    sizeof(*i_matrix)*2);
+
+            rpmsg_send(app_rp_chnl, i_matrix, sizeof(*i_matrix)*2);
+
+            NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+            
+            printf("\r\n Received results! - %d bytes from rpmsg device (transmitted from remote context) \r\n", bytes_received);
+
+            matrix_print(r_matrix);
+
+        }
+        else if(cmd == '2')
+        {
+            printf("\r\n Quitting application .. \r\n");
+            printf("\r\n Matrix multiplication demo end \r\n");
+
+            break;
+        }
+        else
+        {
+            printf("\r\n invalid command! \r\n");
+        }
+    }    
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Main_Task_Entry
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Entry function for the main task. This task prints a hello world
+ * *       message.
+ * *
+ * ***********************************************************************/
+static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv ) {
+
+    struct remote_proc *proc;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+    STATUS             status;
+    int shutdown_msg = SHUTDOWN_MSG;
+
+    status = NU_System_Memory_Get(&sys_pool_ptr, NU_NULL);
+    
+       /* Allocate memory for input matrices */
+    if(status == NU_SUCCESS)
+    {
+        status = NU_Allocate_Memory (sys_pool_ptr, (VOID *)&i_matrix,sizeof(*i_matrix)*2, NU_NO_SUSPEND);
+    }
+    
+       /* Allocate memory for result matrix */
+    if(status == NU_SUCCESS)
+    {
+        status = NU_Allocate_Memory (sys_pool_ptr, (VOID *)&r_matrix,sizeof(*r_matrix), NU_NO_SUSPEND);
+    }
+    
+    /* Start first firmware*/
+    if(status == NU_SUCCESS)
+    {   
+               printf("\n\n\r************************************");
+               printf("*******************************************\r\n");
+               printf("\r\n              Matrix Multiplication Application \r\n");
+               printf("\r\n");
+               printf("\r\nThis sample application will offload matrix multiplication \r\n");
+               printf("\r\noperations from Nucleus master to remote cores\r\n");
+
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+    
+    
+        printf("\r\n\nLoading remote context : %s \r\n" , fw1_name);
+        
+        printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+            
+        status = remoteproc_init((void *) fw1_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+    }
+    
+       /* Boot first firmware */
+    if((!status) && (proc))
+    {
+        printf("\r\n\n********************************************\r\n");
+        printf("BOOTING NUCLEUS REMOTE FIRMWARE");
+           printf("\r\n********************************************\r\n\n");
+        status = remoteproc_boot(proc);
+    }
+    
+    if(!status)
+    {
+        /* Wait till communication channel is established */
+        NU_Obtain_Semaphore(&App_Sem, NU_SUSPEND);
+        printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+        printf("\r\nStarting application for first firmware  .. \r\n");
+        printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+               
+               /* Call matrix multiply application */
+        matrix_multiply_shell();
+
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+        printf("\r\nShutting down and deinitializing remote context : %s \r\n" , fw1_name);
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+
+        /* Send shutdown message to remote */
+               rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
+
+        /* Wait for channel deletion callback. */
+        NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+
+               /* Shutdown remote processor and deinitialize remoteproc */
+        remoteproc_shutdown(proc);
+        remoteproc_deinit(proc);
+    }
+    else
+    {
+        printf("\r\n\nLoading remote context: %s failed \r\n" , fw1_name);
+    }        
+    
+       /* Start second firmware */
+    status = remoteproc_init((void *) fw2_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+
+       /* Boot first firmware */
+    if((!status) && (proc))
+    {
+           printf("\r\n\n********************************************\r\n");
+        printf("BOOTING BAREMETAL  REMOTE FIRMWARE");
+           printf("\r\n********************************************\r\n\n");
+        status = remoteproc_boot(proc);
+    }
+    
+    if(!status)
+    {
+               /* Wait till communication channel is established */
+        NU_Obtain_Semaphore(&App_Sem, NU_SUSPEND);
+    
+        printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+        printf("\r\nStarting application for second firmware  .. \r\n");
+        printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+        
+               /* Call matrix multiply application */
+        matrix_multiply_shell();
+        
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+        printf("\r\nShutting down and deinitializing remote context : %s \r\n" , fw2_name);
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+
+               /* Shut down remote processor and deinitialize remoteproc */
+        remoteproc_shutdown(proc);
+        remoteproc_deinit(proc);
+    }
+    else
+    {
+        printf("\r\n\nLoading remote context: %s failed \r\n" , fw2_name);
+    }        
+    
+}
+
+/* This callback gets invoked when the remote channel is created */
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
+    app_rp_chnl = rp_chnl;
+    rp_ept = rpmsg_create_ept(rp_chnl , rpmsg_read_cb ,RPMSG_NULL , RPMSG_ADDR_ANY);
+    NU_Release_Semaphore(&App_Sem);
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
+    NU_Release_Semaphore(&App_Sem);
+}
+
+/* This is the read callback, note we are in a task context when this callback
+is invoked, so kernel primitives can be used freely */
+void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
+                void * priv, unsigned long src) {
+
+    memcpy(r_matrix,data,len);
+    
+    bytes_received = len;
+    
+    NU_Release_Semaphore(&App_Sem);
+}
+
diff --git a/apps/samples/remote/baremetal/matrix_multiply/make b/apps/samples/remote/baremetal/matrix_multiply/make
new file mode 100644 (file)
index 0000000..f4d28f6
--- /dev/null
@@ -0,0 +1,32 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := samples/remote/baremetal/matrix_multiply/matrix_multiply.out
+SAMPLE_SRC := samples/remote/baremetal/matrix_multiply/matrix_multiply.c samples/remote/baremetal/matrix_multiply/rsc_table.c
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_SRC))
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(SAMPLEOBJFILES) 
+       @echo 'Building matrix multiplication sample for baremetal environment : $@'
+       $(LD) -Wl,-Map=samples/remote/baremetal/matrix_multiply/matrix_multiply.map -Wl,--gc-sections -T"$(OHOME)/libs/system/$(PLAT)/baremetal/linker_remote.ld" -L"$(OHOME)/libs/open_amp" -L"$(OHOME)/libs/system/$(PLAT)/baremetal" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) -lopen_amp -lbaremetal_remote -lc -lm -lstdc++ -lcs3 -lcs3arm -lcs3unhosted -Wl,--end-group      
+       @echo 'Finished building target: $@'
+
+       @echo 'Copying ELF image to firmware folder'
+       $(CP) $(SAMPLE_OUT) firmware/$(PLAT)/$(OS)/matrix_multiply/firmware
+
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/remote/baremetal/matrix_multiply/matrix_multiply.c b/apps/samples/remote/baremetal/matrix_multiply/matrix_multiply.c
new file mode 100644 (file)
index 0000000..a337b9c
--- /dev/null
@@ -0,0 +1,131 @@
+/* This is a sample demonstration application that showcases usage of remoteproc\r
+and rpmsg APIs on the remote core. This application is meant to run on the remote CPU \r
+running baremetal code. This applicationr receives two matrices from the master, \r
+multiplies them and returns the result to the master core. */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "open_amp.h"\r
+#include "rsc_table.h"\r
+#include "baremetal.h"\r
+\r
+#define        MAX_SIZE                6\r
+#define NUM_MATRIX              2\r
+#define SHUTDOWN_MSG            0xEF56A55A\r
+\r
+typedef struct _matrix {\r
+    unsigned long size;\r
+    unsigned long elements[MAX_SIZE][MAX_SIZE];\r
+} matrix;\r
+\r
+/* Internal functions */\r
+static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl);\r
+static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl);\r
+static void rpmsg_read_cb(struct rpmsg_channel *, void *, int, void *, unsigned long);\r
+static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r);\r
+static void sleep();\r
+static void init_system();\r
+\r
+/* Globals */\r
+static struct rpmsg_channel *app_rp_chnl;\r
+volatile int int_flag = 0;\r
+static struct rpmsg_endpoint *rp_ept;\r
+static matrix matrix_array[NUM_MATRIX];\r
+static matrix matrix_result;\r
+static struct remote_proc *proc = NULL;\r
+static struct rsc_table_info rsc_info;\r
+extern const struct remote_resource_table resources;\r
+\r
+/* Application entry point */\r
+int main() {\r
+\r
+    /* Switch to System Mode */\r
+    SWITCH_TO_SYS_MODE();\r
+\r
+    /* Initialize HW system components */\r
+    init_system();\r
+\r
+    rsc_info.rsc_tab = (struct resource_table *)&resources;\r
+    rsc_info.size = sizeof(resources);\r
+\r
+    /* Initialize RPMSG framework */\r
+    remoteproc_resource_init(&rsc_info, rpmsg_channel_created, rpmsg_channel_deleted,\r
+               rpmsg_read_cb ,&proc);\r
+\r
+    while (1) {\r
+        if (int_flag) {\r
+\r
+            /* Process received data and multiple matrices. */\r
+            Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);\r
+\r
+            /* Send the result of matrix multiplication back to master. */\r
+            rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix));\r
+\r
+            int_flag = 0;\r
+        }\r
+        sleep();\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {\r
+    app_rp_chnl = rp_chnl;\r
+    rp_ept = rpmsg_create_ept(rp_chnl, rpmsg_read_cb, RPMSG_NULL,\r
+                    RPMSG_ADDR_ANY);\r
+}\r
+\r
+static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {\r
+    rpmsg_destroy_ept(rp_ept);\r
+}\r
+\r
+static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,\r
+                void * priv, unsigned long src) {\r
+       if ((*(int *) data) == SHUTDOWN_MSG) {\r
+               remoteproc_resource_deinit(proc);\r
+       }else{\r
+               env_memcpy(matrix_array, data, len);\r
+       int_flag = 1;\r
+       }\r
+}\r
+\r
+void sleep() {\r
+    int i;\r
+    for (i = 0; i < 1000; i++);\r
+}\r
+\r
+static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r) {\r
+    int i, j, k;\r
+\r
+    r->size = m->size;\r
+\r
+    for (i = 0; i < m->size; ++i) {\r
+        for (j = 0; j < n->size; ++j) {\r
+            r->elements[i][j] = 0;\r
+        }\r
+    }\r
+\r
+    for (i = 0; i < m->size; ++i) {\r
+        for (j = 0; j < n->size; ++j) {\r
+            for (k = 0; k < r->size; ++k) {\r
+                r->elements[i][j] += m->elements[i][k] * n->elements[k][j];\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+static void init_system() {\r
+\r
+    /* Place the vector table at the image entry point */\r
+    arm_arch_install_isr_vector_table(RAM_VECTOR_TABLE_ADDR);\r
+\r
+    /* Enable MMU */\r
+    arm_ar_mem_enable_mmu();\r
+\r
+    /* Initialize ARM stacks */\r
+    init_arm_stacks();\r
+\r
+    /* Initialize GIC */\r
+    zc702evk_gic_initialize();\r
+}\r
diff --git a/apps/samples/remote/baremetal/matrix_multiply/rsc_table.c b/apps/samples/remote/baremetal/matrix_multiply/rsc_table.c
new file mode 100644 (file)
index 0000000..a073704
--- /dev/null
@@ -0,0 +1,89 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include "open_amp.h"\r
+#include "rsc_table.h"\r
+\r
+/* Place resource table in special ELF section */\r
+#define __section(S)            __attribute__((__section__(#S)))\r
+#define __resource              __section(.resource_table)\r
+\r
+#define RPMSG_IPU_C0_FEATURES       1\r
+\r
+/* VirtIO rpmsg device id */\r
+#define VIRTIO_ID_RPMSG_             7\r
+\r
+/* Remote supports Name Service announcement */\r
+#define VIRTIO_RPMSG_F_NS           0\r
+\r
+/* Resource table entries */\r
+#define ELF_START                   0x00000000\r
+#define ELF_END                     0x08000000\r
+#define NUM_VRINGS                                     0x02\r
+#define VRING_ALIGN                                    0x1000\r
+#define RING_TX                     0x08000000\r
+#define RING_RX                     0x08004000\r
+#define VRING_SIZE                  256\r
+\r
+const struct remote_resource_table __resource resources =\r
+{\r
+    /* Version */\r
+    1,\r
+\r
+    /* NUmber of table entries */\r
+    2,\r
+    /* reserved fields */\r
+    {   0, 0,},\r
+\r
+    /* Offsets of rsc entries */\r
+    {\r
+        offsetof(struct remote_resource_table, elf_cout),\r
+        offsetof(struct remote_resource_table, rpmsg_vdev),\r
+    },\r
+\r
+    /* End of ELF file */\r
+    {\r
+        RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",\r
+    },\r
+\r
+    /* Virtio device entry */\r
+    {   RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},\r
+    },\r
+\r
+    /* Vring rsc entry - part of vdev rsc entry */\r
+    {\r
+        RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0\r
+    },\r
+    {\r
+        RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0\r
+    },\r
+};\r
diff --git a/apps/samples/remote/baremetal/matrix_multiply/rsc_table.h b/apps/samples/remote/baremetal/matrix_multiply/rsc_table.h
new file mode 100644 (file)
index 0000000..9c28005
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include <stddef.h>\r
+#include "open_amp.h"\r
+\r
+#define NO_RESOURCE_ENTRIES         8\r
+\r
+/* Resource table for the given remote */\r
+struct remote_resource_table {\r
+    unsigned int version;\r
+    unsigned int num;\r
+    unsigned int reserved[2];\r
+    unsigned int offset[NO_RESOURCE_ENTRIES];\r
+    /* text carveout entry */\r
+    struct fw_rsc_carveout elf_cout;\r
+    /* rpmsg vdev entry */\r
+    struct fw_rsc_vdev rpmsg_vdev;\r
+    struct fw_rsc_vdev_vring rpmsg_vring0;\r
+    struct fw_rsc_vdev_vring rpmsg_vring1;\r
+};\r
+\r
diff --git a/apps/samples/remote/baremetal/rpc_demo/make b/apps/samples/remote/baremetal/rpc_demo/make
new file mode 100644 (file)
index 0000000..2428e8b
--- /dev/null
@@ -0,0 +1,32 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := samples/remote/baremetal/rpc_demo/rpc_demo.out
+SAMPLE_SRC := samples/remote/baremetal/rpc_demo/rpc_demo.c samples/remote/baremetal/rpc_demo/rsc_table.c ../proxy/remote/rpmsg_retarget/rpmsg_retarget.c
+APP_INCLUDE := -I"../proxy/remote/rpmsg_retarget"
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_SRC))
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(SAMPLEOBJFILES) 
+       @echo 'Building rpc sample for baremetal environment : $@'
+       $(LD) -Wl,-Map=samples/remote/baremetal/rpc_demo/rpc_demo.map -Wl,--gc-sections -T"$(OHOME)/libs/system/$(PLAT)/baremetal/linker_remote.ld" -L"$(OHOME)/libs/open_amp" -L"$(OHOME)/libs/system/$(PLAT)/baremetal" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) -lopen_amp -lbaremetal_remote_rpc -lc -lm -lstdc++ -lcs3 -lcs3arm -lcs3unhosted -Wl,--end-group        
+       @echo 'Finished building target: $@'
+
+       @echo 'Copying ELF image to firmware folder'
+       $(CP) $(SAMPLE_OUT) firmware/$(PLAT)/$(OS)/rpc_demo/firmware
+
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) $(APP_INCLUDE) -c $< -o $@
+
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/remote/baremetal/rpc_demo/rpc_demo.c b/apps/samples/remote/baremetal/rpc_demo/rpc_demo.c
new file mode 100644 (file)
index 0000000..131c974
--- /dev/null
@@ -0,0 +1,181 @@
+/* This is a sample demonstration application that showcases usage of proxy from the remote core. \r
+ This application is meant to run on the remote CPU running baremetal.\r
+ This applicationr can print to to master console and perform file I/O using proxy mechanism. */\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <fcntl.h>\r
+#include <unistd.h>\r
+#include "open_amp.h"\r
+#include "rsc_table.h"\r
+#include "baremetal.h"\r
+#include "rpmsg_retarget.h"\r
+\r
+/* Internal functions */\r
+static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl);\r
+static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl);\r
+static void rpmsg_read_cb(struct rpmsg_channel *, void *, int, void *,\r
+                unsigned long);\r
+static void init_system();\r
+static void shutdown_cb(struct rpmsg_channel *rp_chnl);\r
+\r
+/* Globals */\r
+static struct rpmsg_channel *app_rp_chnl;\r
+volatile int chnl_cb_flag = 0;\r
+static struct remote_proc *proc = NULL;\r
+static struct rsc_table_info rsc_info;\r
+extern const struct remote_resource_table resources;\r
+\r
+#define REDEF_O_CREAT 100\r
+#define REDEF_O_EXCL 200\r
+#define REDEF_O_RDONLY 0\r
+#define REDEF_O_WRONLY 1\r
+#define REDEF_O_RDWR 2\r
+#define REDEF_O_APPEND 2000\r
+#define REDEF_O_ACCMODE 3\r
+\r
+/* Application entry point */\r
+int main() {\r
+    int fd, bytes_written, bytes_read;\r
+    char fname[] = "remote.file";\r
+    char wbuff[50];\r
+    char rbuff[1024];\r
+    char ubuff[50];\r
+    float fdata;\r
+    int idata;\r
+    int ret;\r
+\r
+    /* Switch to System Mode */\r
+    SWITCH_TO_SYS_MODE();\r
+\r
+    /* Initialize HW system components */\r
+    init_system();\r
+\r
+    rsc_info.rsc_tab = (struct resource_table *) &resources;\r
+    rsc_info.size = sizeof(resources);\r
+\r
+    /* Initialize RPMSG framework */\r
+    remoteproc_resource_init(&rsc_info, rpmsg_channel_created,\r
+                    rpmsg_channel_deleted, rpmsg_read_cb, &proc);\r
+\r
+    while (!chnl_cb_flag);\r
+\r
+    chnl_cb_flag = 0;\r
+\r
+    rpmsg_retarget_init(app_rp_chnl, shutdown_cb);\r
+\r
+    printf("\r\nRemote>***************************************************\r\n");\r
+    printf("\r\nRemote>Baremetal Remote Procedure Call (RPC) Demonstration\r\n");\r
+    printf("\r\nRemote>***************************************************\r\n");\r
+    printf("\r\nRemote>Rpmsg based retargetting to proxy initialized..\r\n");\r
+\r
+    /* Remote performing file IO on Master */\r
+    printf("\r\nRemote>FileIO demo ..\r\n");\r
+\r
+    printf("\r\nRemote>Creating a file on master and writing to it..\r\n");\r
+    fd = open(fname, REDEF_O_CREAT | REDEF_O_WRONLY | REDEF_O_APPEND,\r
+                    S_IRUSR | S_IWUSR);\r
+    printf("\r\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd);\r
+\r
+    sprintf(wbuff, "This is a test string being written to file..");\r
+    bytes_written = write(fd, wbuff, strlen(wbuff));\r
+    printf("\r\nRemote>Wrote to fd = %d, size = %d, content = %s\r\n", fd,\r
+                    bytes_written, wbuff);\r
+\r
+    close(fd);\r
+    printf("\r\nRemote>Closed fd = %d\r\n", fd);\r
+\r
+    /* Remote performing file IO on Master */\r
+    printf("\r\nRemote>Reading a file on master and displaying its contents..\r\n");\r
+    fd = open(fname, REDEF_O_RDONLY, S_IRUSR | S_IWUSR);\r
+    printf("\r\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd);\r
+    bytes_read = read(fd, rbuff, 1024);\r
+    *(char*) (&rbuff[0] + bytes_read + 1) = 0;\r
+    printf( "\r\nRemote>Read from fd = %d, size = %d, printing contents below .. %s\r\n",\r
+                    fd, bytes_read, rbuff);\r
+    close(fd);\r
+    printf("\r\nRemote>Closed fd = %d\r\n", fd);\r
+\r
+    for(;;)\r
+    {\r
+        /* Remote performing STDIO on Master */\r
+        printf("\r\nRemote>Remote firmware using scanf and printf ..\r\n");\r
+        printf("\r\nRemote>Scanning user input from master..\r\n");\r
+        printf("\r\nRemote>Enter name\r\n");\r
+        ret = scanf("%s", ubuff);\r
+        if(ret) {\r
+            printf("\r\nRemote>Enter age\r\n");\r
+            ret = scanf("%d", &idata);\r
+            if(ret) {\r
+                printf("\r\nRemote>Enter value for pi\r\n");\r
+                ret = scanf("%f", &fdata);\r
+                if(ret) {\r
+                    printf("\r\nRemote>User name = '%s'\r\n", ubuff);\r
+                    printf("\r\nRemote>User age = '%d'\r\n", idata);\r
+                    printf("\r\nRemote>User entered value of pi = '%f'\r\n", fdata);\r
+                }\r
+            }\r
+        }\r
+\r
+        if(!ret)\r
+        {\r
+            /* Consume the read buffer */\r
+            while(getchar() != '\n');\r
+            printf("Remote> Invalid value. Starting again....");\r
+        }\r
+        else\r
+        {\r
+            printf("\r\nRemote>Repeat demo ? (enter yes or no) \r\n");\r
+            scanf("%s", ubuff);\r
+\r
+            if((strcmp(ubuff,"no")) && (strcmp(ubuff,"yes")))\r
+            {\r
+                printf("\r\nRemote>Invalid option. Starting again....\r\n");\r
+            }\r
+            else if((!strcmp(ubuff,"no")))\r
+            {\r
+                printf("\r\nRemote>RPC retargetting quitting ...\r\n");\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    printf("\r\nRemote> Firmware's rpmsg-openamp-demo-channel going down! \r\n");\r
+\r
+    while (1);\r
+\r
+    return 0;\r
+}\r
+\r
+static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {\r
+    app_rp_chnl = rp_chnl;\r
+    chnl_cb_flag = 1;\r
+}\r
+\r
+static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {\r
+}\r
+\r
+static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,\r
+                void * priv, unsigned long src) {\r
+}\r
+\r
+static void shutdown_cb(struct rpmsg_channel *rp_chnl) {\r
+    rpmsg_retarget_deinit(rp_chnl);\r
+    remoteproc_resource_deinit(proc);\r
+}\r
+\r
+static void init_system() {\r
+\r
+    /* Place the vector table at the image entry point */\r
+    arm_arch_install_isr_vector_table(RAM_VECTOR_TABLE_ADDR);\r
+\r
+    /* Enable MMU */\r
+    arm_ar_mem_enable_mmu();\r
+\r
+    /* Initialize ARM stacks */\r
+    init_arm_stacks();\r
+\r
+    /* Initialize GIC */\r
+    zc702evk_gic_initialize();\r
+}\r
diff --git a/apps/samples/remote/baremetal/rpc_demo/rsc_table.c b/apps/samples/remote/baremetal/rpc_demo/rsc_table.c
new file mode 100644 (file)
index 0000000..a073704
--- /dev/null
@@ -0,0 +1,89 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include "open_amp.h"\r
+#include "rsc_table.h"\r
+\r
+/* Place resource table in special ELF section */\r
+#define __section(S)            __attribute__((__section__(#S)))\r
+#define __resource              __section(.resource_table)\r
+\r
+#define RPMSG_IPU_C0_FEATURES       1\r
+\r
+/* VirtIO rpmsg device id */\r
+#define VIRTIO_ID_RPMSG_             7\r
+\r
+/* Remote supports Name Service announcement */\r
+#define VIRTIO_RPMSG_F_NS           0\r
+\r
+/* Resource table entries */\r
+#define ELF_START                   0x00000000\r
+#define ELF_END                     0x08000000\r
+#define NUM_VRINGS                                     0x02\r
+#define VRING_ALIGN                                    0x1000\r
+#define RING_TX                     0x08000000\r
+#define RING_RX                     0x08004000\r
+#define VRING_SIZE                  256\r
+\r
+const struct remote_resource_table __resource resources =\r
+{\r
+    /* Version */\r
+    1,\r
+\r
+    /* NUmber of table entries */\r
+    2,\r
+    /* reserved fields */\r
+    {   0, 0,},\r
+\r
+    /* Offsets of rsc entries */\r
+    {\r
+        offsetof(struct remote_resource_table, elf_cout),\r
+        offsetof(struct remote_resource_table, rpmsg_vdev),\r
+    },\r
+\r
+    /* End of ELF file */\r
+    {\r
+        RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",\r
+    },\r
+\r
+    /* Virtio device entry */\r
+    {   RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},\r
+    },\r
+\r
+    /* Vring rsc entry - part of vdev rsc entry */\r
+    {\r
+        RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0\r
+    },\r
+    {\r
+        RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0\r
+    },\r
+};\r
diff --git a/apps/samples/remote/baremetal/rpc_demo/rsc_table.h b/apps/samples/remote/baremetal/rpc_demo/rsc_table.h
new file mode 100644 (file)
index 0000000..9c28005
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include <stddef.h>\r
+#include "open_amp.h"\r
+\r
+#define NO_RESOURCE_ENTRIES         8\r
+\r
+/* Resource table for the given remote */\r
+struct remote_resource_table {\r
+    unsigned int version;\r
+    unsigned int num;\r
+    unsigned int reserved[2];\r
+    unsigned int offset[NO_RESOURCE_ENTRIES];\r
+    /* text carveout entry */\r
+    struct fw_rsc_carveout elf_cout;\r
+    /* rpmsg vdev entry */\r
+    struct fw_rsc_vdev rpmsg_vdev;\r
+    struct fw_rsc_vdev_vring rpmsg_vring0;\r
+    struct fw_rsc_vdev_vring rpmsg_vring1;\r
+};\r
+\r
diff --git a/apps/samples/remote/nucleus/matrix_multiply/make b/apps/samples/remote/nucleus/matrix_multiply/make
new file mode 100644 (file)
index 0000000..401fc30
--- /dev/null
@@ -0,0 +1,38 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := samples/remote/nucleus/matrix_multiply/matrix_multiply.out
+
+SAMPLE_SRC := samples/remote/nucleus/matrix_multiply/matrix_multiply.c samples/remote/nucleus/matrix_multiply/rsc_table.c
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_SRC))
+
+SAMPLE_DEPS   := $(patsubst %.c, %.d, $(SAMPLE_SRC))
+
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(SAMPLEOBJFILES)
+
+       @echo 'Building matrix multiplication application : $@'
+
+       $(LD)  -Wl,-Map=samples/remote/nucleus/matrix_multiply/matrix_multiply.map  -nostartfiles -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=free -T"$(OHOME)/libs/system/$(PLAT)/nucleus/linker_remote.ld" -L"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/remote" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) -lnucleus_remote -lopen_amp -lc -lm -lstdc++ -Wl,--end-group        
+       
+       @echo 'Copying ELF image to firmware folder'
+       $(CP) $(SAMPLE_OUT) firmware/$(PLAT)/$(OS)/matrix_multiply/firmware
+
+    @echo 'Finished building target: $@'
+       
+%.o:%.c 
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/remote/nucleus/matrix_multiply/matrix_multiply.c b/apps/samples/remote/nucleus/matrix_multiply/matrix_multiply.c
new file mode 100644 (file)
index 0000000..4176010
--- /dev/null
@@ -0,0 +1,174 @@
+/* This is a sample demonstration application that showcases usage of remoteproc\r
+ and rpmsg APIs on the remote core. This application is meant to run on the remote CPU\r
+ running Nucleus. This applicationr receives two matrices from the master, multiplies\r
+ them and returns the result to the master core. */\r
+\r
+/* Including required headers */\r
+#include  <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "open_amp.h"\r
+#include "rsc_table.h"\r
+#include "nucleus.h"\r
+#include "kernel/nu_kernel.h"\r
+\r
+/* Define the main task's stack size */\r
+#define STACK_SIZE              (NU_MIN_STACK_SIZE * 64)\r
+\r
+/* Define the main task's priority */\r
+#define TASK_PRIORITY           26\r
+\r
+/* Define the main task's time slice */\r
+#define TASK_SLICE              20\r
+\r
+/* Application */\r
+#define MAX_SIZE                6\r
+#define NUM_MATRIX              2\r
+\r
+#define SHUTDOWN_MSG            0xEF56A55A\r
+\r
+typedef struct _matrix {\r
+    unsigned long size;\r
+    unsigned long elements[MAX_SIZE][MAX_SIZE];\r
+} matrix;\r
+\r
+/* Prototype for the main task's entry function */\r
+static void Main_Task_Entry(UNSIGNED argc, VOID *argv);\r
+\r
+static NU_TASK Task_Control_Block;\r
+static NU_SEMAPHORE Remote_Sem;\r
+static struct rpmsg_endpoint *rp_ept;\r
+static struct rpmsg_channel *app_rp_chnl;\r
+static matrix matrix_array[NUM_MATRIX];\r
+static matrix matrix_result;\r
+static struct remote_proc *proc;\r
+static struct rsc_table_info rsc_info;\r
+extern const struct remote_resource_table resources;\r
+static int shutdown_flag = 0;\r
+\r
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl);\r
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl);\r
+void rpmsg_read_default_cb(struct rpmsg_channel *rp_chnl, void *data, int len,\r
+                void * pric, unsigned long src);\r
+\r
+/***********************************************************************\r
+ * *\r
+ * *   FUNCTION\r
+ * *\r
+ * *       Application_Initialize\r
+ * *\r
+ * *   DESCRIPTION\r
+ * *\r
+ * *       Demo application entry point\r
+ *\r
+ * ***********************************************************************/\r
+VOID Application_Initialize(NU_MEMORY_POOL* mem_pool,\r
+                NU_MEMORY_POOL* uncached_mem_pool) {\r
+    VOID *pointer;\r
+    STATUS status;\r
+\r
+    /* Reference unused parameters to avoid toolset warnings */\r
+    NU_UNUSED_PARAM(uncached_mem_pool);\r
+\r
+    status = NU_Create_Semaphore(&Remote_Sem, "r_sem", 0, NU_FIFO);\r
+\r
+    if (status == NU_SUCCESS) {\r
+        status = NU_Allocate_Memory(mem_pool, &pointer,\r
+                        STACK_SIZE, NU_NO_SUSPEND);\r
+        if (status == NU_SUCCESS) {\r
+            /* Create task 0.  */\r
+            status = NU_Create_Task(&Task_Control_Block, "MAIN",\r
+                            Main_Task_Entry, 0, uncached_mem_pool, pointer,\r
+                            STACK_SIZE, TASK_PRIORITY, TASK_SLICE,\r
+                            NU_PREEMPT, NU_START);\r
+        }\r
+    }\r
+\r
+    /* Check to see if previous operations were successful */\r
+    if (status != NU_SUCCESS) {\r
+        /* Loop forever */\r
+        while (1);\r
+    }\r
+}\r
+\r
+static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r) {\r
+    int i, j, k;\r
+\r
+    r->size = m->size;\r
+\r
+    for (i = 0; i < m->size; ++i) {\r
+        for (j = 0; j < n->size; ++j) {\r
+            r->elements[i][j] = 0;\r
+        }\r
+    }\r
+\r
+    for (i = 0; i < m->size; ++i) {\r
+        for (j = 0; j < n->size; ++j) {\r
+            for (k = 0; k < r->size; ++k) {\r
+                r->elements[i][j] += m->elements[i][k] * n->elements[k][j];\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {\r
+\r
+    app_rp_chnl = rp_chnl;\r
+    rp_ept = rpmsg_create_ept(rp_chnl, rpmsg_read_default_cb, RPMSG_NULL,\r
+                    RPMSG_ADDR_ANY);\r
+}\r
+\r
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {\r
+    rpmsg_destroy_ept(rp_ept);\r
+}\r
+\r
+void rpmsg_read_default_cb(struct rpmsg_channel *rp_chnl, void *data, int len,\r
+                void * priv, unsigned long src) {\r
+\r
+    if ((*(int *) data) == SHUTDOWN_MSG) {\r
+        shutdown_flag = 1;\r
+        NU_Release_Semaphore(&Remote_Sem);\r
+    } else {\r
+        env_memcpy(matrix_array, data, len);\r
+        NU_Release_Semaphore(&Remote_Sem);\r
+    }\r
+}\r
+\r
+/***********************************************************************\r
+ * *\r
+ * *   FUNCTION\r
+ * *\r
+ * *       Main_Task_Entry\r
+ * *\r
+ * *   DESCRIPTION\r
+ * *\r
+ * *       Entry function for the main task. This task prints a hello world\r
+ * *       message.\r
+ * *\r
+ * ***********************************************************************/\r
+static VOID Main_Task_Entry(UNSIGNED argc, VOID *argv) {\r
+    rsc_info.rsc_tab = (struct resource_table *) &resources;\r
+    rsc_info.size = sizeof(resources);\r
+\r
+    remoteproc_resource_init(&rsc_info, rpmsg_channel_created,\r
+                    rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);\r
+\r
+    for (;;) {\r
+\r
+        /* Wait for incoming matrix data. */\r
+        NU_Obtain_Semaphore(&Remote_Sem, NU_SUSPEND);\r
+\r
+        if (shutdown_flag) {\r
+            remoteproc_resource_deinit(proc);\r
+            break;\r
+        }\r
+\r
+        /* Process received data and multiple matrices. */\r
+        Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);\r
+\r
+        /* Send the result of matrix multiplication back to master. */\r
+        rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix));\r
+\r
+        NU_Sleep(5);\r
+    }\r
+}\r
diff --git a/apps/samples/remote/nucleus/matrix_multiply/rsc_table.c b/apps/samples/remote/nucleus/matrix_multiply/rsc_table.c
new file mode 100644 (file)
index 0000000..d87050c
--- /dev/null
@@ -0,0 +1,90 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include "open_amp.h"\r
+#include "rsc_table.h"\r
+\r
+/* Place resource table in special ELF section */\r
+#define __section(S)            __attribute__((__section__(#S)))\r
+#define __resource              __section(.resource_table)\r
+\r
+\r
+#define RPMSG_IPU_C0_FEATURES       1\r
+\r
+/* VirtIO rpmsg device id */\r
+#define VIRTIO_ID_RPMSG_             7\r
+\r
+/* Remote supports Name Service announcement */\r
+#define VIRTIO_RPMSG_F_NS           0\r
+\r
+/* Resource table entries */\r
+#define ELF_START                   0x00000000\r
+#define ELF_END                     0x08000000\r
+#define NUM_VRINGS                                     0x02\r
+#define VRING_ALIGN                                    0x1000\r
+#define RING_TX                     0x08000000\r
+#define RING_RX                     0x08004000\r
+#define VRING_SIZE                  256\r
+\r
+const struct remote_resource_table __resource resources =\r
+{\r
+    /* Version */\r
+    1,\r
+\r
+    /* NUmber of table entries */\r
+    2,\r
+    /* reserved fields */\r
+    {   0, 0,},\r
+\r
+    /* Offsets of rsc entries */\r
+    {\r
+        offsetof(struct remote_resource_table, elf_cout),\r
+        offsetof(struct remote_resource_table, rpmsg_vdev),\r
+    },\r
+\r
+    /* End of ELF file */\r
+    {\r
+        RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",\r
+    },\r
+\r
+    /* Virtio device entry */\r
+    {   RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},\r
+    },\r
+\r
+    /* Vring rsc entry - part of vdev rsc entry */\r
+    {\r
+        RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0\r
+    },\r
+    {\r
+        RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0\r
+    },\r
+};\r
diff --git a/apps/samples/remote/nucleus/matrix_multiply/rsc_table.h b/apps/samples/remote/nucleus/matrix_multiply/rsc_table.h
new file mode 100644 (file)
index 0000000..9c28005
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include <stddef.h>\r
+#include "open_amp.h"\r
+\r
+#define NO_RESOURCE_ENTRIES         8\r
+\r
+/* Resource table for the given remote */\r
+struct remote_resource_table {\r
+    unsigned int version;\r
+    unsigned int num;\r
+    unsigned int reserved[2];\r
+    unsigned int offset[NO_RESOURCE_ENTRIES];\r
+    /* text carveout entry */\r
+    struct fw_rsc_carveout elf_cout;\r
+    /* rpmsg vdev entry */\r
+    struct fw_rsc_vdev rpmsg_vdev;\r
+    struct fw_rsc_vdev_vring rpmsg_vring0;\r
+    struct fw_rsc_vdev_vring rpmsg_vring1;\r
+};\r
+\r
diff --git a/apps/samples/remote/nucleus/rpc_demo/make b/apps/samples/remote/nucleus/rpc_demo/make
new file mode 100644 (file)
index 0000000..6b36396
--- /dev/null
@@ -0,0 +1,40 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := samples/remote/nucleus/rpc_demo/rpc_demo.out
+
+SAMPLE_SRC := samples/remote/nucleus/rpc_demo/rpc_demo.c samples/remote/nucleus/rpc_demo/rsc_table.c ../proxy/remote/rpmsg_retarget/rpmsg_retarget.c
+APP_INCLUDE := -I"../proxy/remote/rpmsg_retarget"
+
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_SRC))
+
+SAMPLE_DEPS   := $(patsubst %.c, %.d, $(SAMPLE_SRC))
+
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(SAMPLEOBJFILES)
+
+       @echo 'Building rpc demo application : $@'
+
+       $(LD)  -Wl,-Map=samples/remote/nucleus/rpc_demo/rpc_demo.map  -nostartfiles -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=free -T"$(OHOME)/libs/system/$(PLAT)/nucleus/linker_remote.ld" -L"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/remote_proxy" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) -lnucleus_remote -lopen_amp -lc -lm -lstdc++ -Wl,--end-group        
+       
+       @echo 'Copying ELF image to firmware folder'
+       $(CP) $(SAMPLE_OUT) firmware/$(PLAT)/$(OS)/rpc_demo/firmware
+
+    @echo 'Finished building target: $@'
+       
+%.o:%.c 
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) $(APP_INCLUDE)  -c $< -o $@
+
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/samples/remote/nucleus/rpc_demo/rpc_demo.c b/apps/samples/remote/nucleus/rpc_demo/rpc_demo.c
new file mode 100644 (file)
index 0000000..388b283
--- /dev/null
@@ -0,0 +1,227 @@
+
+/* This is a sample demonstration application that showcases usage of proxy from the remote core. 
+This application is meant to run on the remote CPU running Nucleus. 
+This applicationr can print to to master console and perform file I/O using proxy mechanism*/
+
+
+/* Including required headers */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "open_amp.h"
+#include "rsc_table.h"
+#include "nucleus.h"
+#include "kernel/nu_kernel.h"
+#include "rpmsg_retarget.h"
+
+/* Define the main task's stack size */
+#define STACK_SIZE      (NU_MIN_STACK_SIZE * 64)
+
+/* Define the main task's priority */
+#define TASK_PRIORITY   26
+
+/* Define the main task's time slice */
+#define TASK_SLICE      20
+
+/* Prototype for the main task's entry function */
+static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
+
+static NU_TASK Task_Control_Block;
+static NU_SEMAPHORE Remote_Sem;
+volatile int int_flag = 0;
+static struct rpmsg_channel *app_rp_chnl;
+static struct remote_proc *proc;
+static struct rsc_table_info rsc_info;
+extern const struct remote_resource_table resources;
+
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+void shutdown_cb(struct rpmsg_channel *rp_chnl);
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Application_Initialize
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Demo application entry point
+ *
+ * ***********************************************************************/
+VOID Application_Initialize(
+                NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
+{
+    VOID *pointer;
+    STATUS status;
+    /* Reference unused parameters to avoid toolset warnings */
+    NU_UNUSED_PARAM( uncached_mem_pool );
+
+    status = NU_Create_Semaphore( &Remote_Sem , "r_sem" , 0 , NU_FIFO );
+
+    if (status == NU_SUCCESS)
+    {
+          status = NU_Allocate_Memory(mem_pool, &pointer,
+                              STACK_SIZE, NU_NO_SUSPEND);
+          if ( status == NU_SUCCESS )
+          {
+               /* Create task 0.  */
+               status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
+                                   uncached_mem_pool , pointer , STACK_SIZE , TASK_PRIORITY , TASK_SLICE ,
+                                   NU_PREEMPT , NU_START );
+          }
+    }
+
+    /* Check to see if previous operations were successful */
+    if ( status != NU_SUCCESS )
+    {
+        /* Loop forever */
+        while ( 1 );
+    }
+}
+
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl)
+{
+    app_rp_chnl = rp_chnl;
+    NU_Release_Semaphore( &Remote_Sem );
+}
+
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl)
+{
+
+}
+
+void rpmsg_read_default_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
+                void * priv, unsigned long src)
+{
+
+}
+
+#define REDEF_O_CREAT 100
+#define REDEF_O_EXCL 200
+#define REDEF_O_RDONLY 0
+#define REDEF_O_WRONLY 1
+#define REDEF_O_RDWR 2
+#define REDEF_O_APPEND 2000
+#define REDEF_O_ACCMODE 3
+
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Main_Task_Entry
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Entry function for the main task. This task prints a hello world
+ * *       message.
+ * *
+ * ***********************************************************************/
+
+static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv )
+{
+    int fd, bytes_written, bytes_read;
+    char fname[]="remote.file";
+    char wbuff[50];
+    char rbuff[1024];
+    char ubuff[50];
+    float fdata;
+    int idata;
+    int ret;
+
+    rsc_info.rsc_tab = (struct resource_table *)&resources;
+    rsc_info.size = sizeof(resources);
+
+    remoteproc_resource_init(&rsc_info, rpmsg_channel_created , rpmsg_channel_deleted ,rpmsg_read_default_cb, &proc);
+
+    NU_Obtain_Semaphore( &Remote_Sem , NU_SUSPEND );
+
+    rpmsg_retarget_init(app_rp_chnl , shutdown_cb);
+
+    printf("\r\nRemote>******************************************************\r\n");
+    printf("\r\nRemote>Nucleus RTOS Remote Procedure Call (RPC) Demonstration\r\n");
+    printf("\r\nRemote>******************************************************\r\n");
+
+    printf("\r\nRemote>Rpmsg based retargetting to proxy initialized..\r\n");
+
+    /* Remote performing file IO on Master */
+    printf("\r\nRemote>FileIO demo using open, write, read, close CRTL calls ..\r\n");
+
+    printf("\r\nRemote>Creating a file on master and writing to it..\r\n");
+    fd = open(fname, REDEF_O_CREAT | REDEF_O_WRONLY | REDEF_O_APPEND, S_IRUSR | S_IWUSR);
+    printf("\r\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd);
+
+    sprintf(wbuff,"This is a test string being written to file..");
+    bytes_written = write(fd, wbuff, strlen(wbuff));
+    printf("\r\nRemote>Wrote to fd = %d, size = %d bytes \r\ncontent = %s\r\n", fd, bytes_written, wbuff);
+
+    close(fd);
+    printf("\r\nRemote>Closed fd = %d\r\n", fd);
+
+    /* Remote performing file IO on Master */
+    printf("\r\nRemote>Reading a file on master and displaying its contents..\r\n");
+    fd = open(fname, REDEF_O_RDONLY, S_IRUSR | S_IWUSR);
+    printf("\r\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd);
+    bytes_read = read(fd, rbuff, 1024);
+    *(char*)(&rbuff[0]+bytes_read+1)=0;
+    printf("\r\nRemote>Read from fd = %d, size = %d bytes \r\ncontent = %s\r\n", fd, bytes_read, rbuff);
+    close(fd);
+    printf("\r\nRemote>Closed fd = %d\r\n", fd);
+
+    for(;;)
+    {
+        /* Remote performing STDIO on Master */
+        printf("\r\nRemote>Remote firmware using scanf and printf ..\r\n");
+        printf("\r\nRemote>Scanning user input from master..\r\n");
+        printf("\r\nRemote>Enter name\r\n");
+        ret = scanf("%s", ubuff);
+        if(ret) {
+            printf("\r\nRemote>Enter age\r\n");
+            ret = scanf("%d", &idata);
+            if(ret) {
+                printf("\r\nRemote>Enter value for pi\r\n");
+                ret = scanf("%f", &fdata);
+                if(ret) {
+                    printf("\r\nRemote>User name = '%s'\r\n", ubuff);
+                    printf("\r\nRemote>User age = '%d'\r\n", idata);
+                    printf("\r\nRemote>User entered value of pi = '%f'\r\n", fdata);
+                }
+            }
+        }
+
+        if(!ret)
+        {
+            /* Consume the read buffer */
+            while(getchar() != '\n');
+            printf("Remote> Invalid value. Starting again....");
+        }
+        else
+        {
+            printf("\r\nRemote>Repeat demo ? (enter yes or no) \r\n");
+            scanf("%s", ubuff);
+
+            if((strcmp(ubuff,"no")) && (strcmp(ubuff,"yes")))
+            {
+                printf("\r\nRemote>Invalid option. Starting again....\r\n");
+            }
+            else if((!strcmp(ubuff,"no")))
+            {
+                printf("\r\nRemote>RPC retargetting quitting ...\r\n");
+                break;
+            }
+        }
+    }
+
+
+    printf("\r\nRemote> Firmware's rpmsg-openamp-demo-channel going down! \r\n");
+}
+
+void shutdown_cb(struct rpmsg_channel *rp_chnl){
+    rpmsg_retarget_deinit(rp_chnl);
+    remoteproc_resource_deinit(proc);
+}
diff --git a/apps/samples/remote/nucleus/rpc_demo/rpc_demo.h b/apps/samples/remote/nucleus/rpc_demo/rpc_demo.h
new file mode 100644 (file)
index 0000000..df38197
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * proxy_rtl.h
+ *
+ *  Created on: Mar 28, 2014
+ *      Author: etsam
+ */
+
+#ifndef PROXY_RTL_H_
+#define PROXY_RTL_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define PRINTF                  0x00000000
+#define SCANF                   0x00000001
+#define FOPEN                   0x00000002
+#define FCLOSE                  0x00000003
+#define FREAD                   0x00000004
+#define FWRITE                  0x00000005
+#define COMMAND_ID              0xEF56A55A
+#define FILE_NAME_LEN           32
+#define FILE_MOD_LEN            4
+
+struct rtl_cmd {
+
+    /* Unique identifer for command message */
+    unsigned int cmd_id;
+
+    /* Command code */
+    unsigned int cmd_cc;
+
+    /* Length of data to to transfer ins response to command */
+    unsigned int data_len;
+
+    /* Command payload */
+    char buff[0];
+
+}__attribute__((__packed__));
+
+struct rtl_cmd_ack {
+
+    /* Command code for which ACK is sent */
+    unsigned int cmd_id;
+
+    /* Any data - apart from status */
+    unsigned int data;
+
+    /* Command status */
+    unsigned int status;
+};
+
+struct fopen_data {
+    char name[FILE_NAME_LEN];
+    char mode[FILE_MOD_LEN];
+};
+
+struct proxy_rtl {
+    /* Lock to exclusively accesses RTL functions */
+    void *rtl_lock;
+    /* Command completion lock */
+    void *data_lock;
+    /* Buffer for data transfer */
+    void *buff;
+    /* Current command reference */
+    /* Command completion status */
+    struct rtl_cmd *cmd;
+    struct rtl_cmd_ack cmd_ack;
+    /* Data length yet to transfer */
+    int rem_len;
+};
+
+#endif /* PROXY_RTL_H_ */
diff --git a/apps/samples/remote/nucleus/rpc_demo/rsc_table.c b/apps/samples/remote/nucleus/rpc_demo/rsc_table.c
new file mode 100644 (file)
index 0000000..a073704
--- /dev/null
@@ -0,0 +1,89 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include "open_amp.h"\r
+#include "rsc_table.h"\r
+\r
+/* Place resource table in special ELF section */\r
+#define __section(S)            __attribute__((__section__(#S)))\r
+#define __resource              __section(.resource_table)\r
+\r
+#define RPMSG_IPU_C0_FEATURES       1\r
+\r
+/* VirtIO rpmsg device id */\r
+#define VIRTIO_ID_RPMSG_             7\r
+\r
+/* Remote supports Name Service announcement */\r
+#define VIRTIO_RPMSG_F_NS           0\r
+\r
+/* Resource table entries */\r
+#define ELF_START                   0x00000000\r
+#define ELF_END                     0x08000000\r
+#define NUM_VRINGS                                     0x02\r
+#define VRING_ALIGN                                    0x1000\r
+#define RING_TX                     0x08000000\r
+#define RING_RX                     0x08004000\r
+#define VRING_SIZE                  256\r
+\r
+const struct remote_resource_table __resource resources =\r
+{\r
+    /* Version */\r
+    1,\r
+\r
+    /* NUmber of table entries */\r
+    2,\r
+    /* reserved fields */\r
+    {   0, 0,},\r
+\r
+    /* Offsets of rsc entries */\r
+    {\r
+        offsetof(struct remote_resource_table, elf_cout),\r
+        offsetof(struct remote_resource_table, rpmsg_vdev),\r
+    },\r
+\r
+    /* End of ELF file */\r
+    {\r
+        RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",\r
+    },\r
+\r
+    /* Virtio device entry */\r
+    {   RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},\r
+    },\r
+\r
+    /* Vring rsc entry - part of vdev rsc entry */\r
+    {\r
+        RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0\r
+    },\r
+    {\r
+        RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0\r
+    },\r
+};\r
diff --git a/apps/samples/remote/nucleus/rpc_demo/rsc_table.h b/apps/samples/remote/nucleus/rpc_demo/rsc_table.h
new file mode 100644 (file)
index 0000000..9c28005
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ * Copyright (c) 2014, Mentor Graphics Corporation\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Mentor Graphics Corporation nor the names of its\r
+ *    contributors may be used to endorse or promote products derived from this\r
+ *    software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/* This file populates resource table for Nucleus and BM remotes\r
+ * for use by the Linux Master */\r
+\r
+#include <stddef.h>\r
+#include "open_amp.h"\r
+\r
+#define NO_RESOURCE_ENTRIES         8\r
+\r
+/* Resource table for the given remote */\r
+struct remote_resource_table {\r
+    unsigned int version;\r
+    unsigned int num;\r
+    unsigned int reserved[2];\r
+    unsigned int offset[NO_RESOURCE_ENTRIES];\r
+    /* text carveout entry */\r
+    struct fw_rsc_carveout elf_cout;\r
+    /* rpmsg vdev entry */\r
+    struct fw_rsc_vdev rpmsg_vdev;\r
+    struct fw_rsc_vdev_vring rpmsg_vring0;\r
+    struct fw_rsc_vdev_vring rpmsg_vring1;\r
+};\r
+\r
diff --git a/apps/tests/master/baremetal/echo_test/echo_test.c b/apps/tests/master/baremetal/echo_test/echo_test.c
new file mode 100644 (file)
index 0000000..c3dc281
--- /dev/null
@@ -0,0 +1,133 @@
+/* This is a sample demonstration application that showcases usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running baremetal env
+and showcases booting of linux remote firmware using remoteproc and 
+IPC with remote firmware using rpmsg; Baremetal env on master core acts as a remoteproc master
+but as an rpmsg remote;It brings up a remote Linux based 
+firmware which acts as an rpmsg master and transmits data payloads to bametal code.
+Linux app sends paylaods of incremental sizes to baremetal code which echoes them back to Linux. 
+Once Linux application is complete, it requests a shutdown from baremetal env. 
+Baremetal env acknowledges with a shutdown message which results in Linux starting a system halt. 
+Baremetal env shutsdown the remote core after a reasonable delay which allows
+Linux to gracefully shutdown. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "open_amp.h"
+
+#define BAREMETAL_MASTER 1
+
+#include "baremetal.h"
+
+#define SHUTDOWN_MSG   0xEF56A55A
+
+
+/* Internal functions */
+static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl);
+static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl);
+static void rpmsg_read_cb(struct rpmsg_channel *, void *, int, void *, unsigned long);
+static void sleep();
+static void init_system();
+
+/* Globals */
+static struct rpmsg_channel *app_rp_chnl;
+static struct rpmsg_endpoint *rp_ept;
+
+char fw_name []= "firmware1";
+
+static int shutdown_called = 0;
+
+/* Application entry point */
+int main() {
+       
+       int status;
+    struct remote_proc *proc;
+       int shutdown_msg = SHUTDOWN_MSG;
+       int i;
+
+    /* Switch to System Mode */
+    SWITCH_TO_SYS_MODE();
+
+    /* Initialize HW system components */
+    init_system();
+
+    status = remoteproc_init((void *) fw_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+    
+    if(!status)
+    {
+        status = remoteproc_boot(proc);
+    }
+    
+    if(status)
+    {
+           return -1;  
+       }
+
+    while (1) {
+               
+               if(shutdown_called == 1)
+               {
+                   break;
+               }
+        sleep();
+    }
+
+       /* Send shutdown message to remote */
+       rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
+
+    for (i = 0; i < 100000; i++)
+    {
+           sleep();
+    }
+    
+       remoteproc_shutdown(proc);
+               
+       remoteproc_deinit(proc);
+               
+    return 0;
+}
+
+static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
+    app_rp_chnl = rp_chnl;
+    rp_ept = rpmsg_create_ept(rp_chnl, rpmsg_read_cb, RPMSG_NULL,
+                    RPMSG_ADDR_ANY);
+}
+
+static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
+    rpmsg_destroy_ept(rp_ept);
+}
+
+static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
+                void * priv, unsigned long src) {
+    
+    if ((*(int *) data) == SHUTDOWN_MSG)
+    {
+               shutdown_called  = 1;
+    }
+    else
+    { 
+        /* Send data back to master*/  
+        rpmsg_send(rp_chnl, data, len);
+    }
+}
+
+void sleep() {
+    volatile int i;
+    for (i = 0; i < 100000; i++);
+}
+
+
+static void init_system() {
+
+    /* Place the vector table at the image entry point */
+    arm_arch_install_isr_vector_table(RAM_VECTOR_TABLE_ADDR);
+
+    /* Enable MMU */
+    arm_ar_mem_enable_mmu();
+
+    /* Initialize ARM stacks */
+    init_arm_stacks();
+
+    /* Initialize GIC */
+    zc702evk_gic_initialize();
+}
diff --git a/apps/tests/master/baremetal/echo_test/make b/apps/tests/master/baremetal/echo_test/make
new file mode 100644 (file)
index 0000000..98c50fe
--- /dev/null
@@ -0,0 +1,51 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := tests/master/baremetal/echo_test/echo_test.out
+SAMPLE_SRC := tests/master/baremetal/echo_test/echo_test.c
+
+
+REMOTE_OUT   := echo_test.out
+LINUX_SRC_DIR := firmware/$(PLAT)/linux
+DST_DIR := tests/master/baremetal/echo_test
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_SRC))
+
+SAMPLE_DEPS   := $(patsubst %.c, %.d, $(SAMPLE_SRC))
+
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(REMOTE_OUT)  $(SAMPLEOBJFILES) 
+
+       @echo 'Building echo test for baremetal : $@'
+
+       $(LD)  -Wl,-Map=tests/master/baremetal/echo_test/echo_test.map -Wl,--gc-sections -T"$(OHOME)/libs/system/$(PLAT)/baremetal/linker_master.ld" -L"$(OHOME)/libs/open_amp" -L"$(OHOME)/libs/system/$(PLAT)/baremetal" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lopen_amp -lbaremetal_master -lc -lm -lstdc++ -lcs3 -lcs3arm -lcs3unhosted -Wl,--end-group     
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+               
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+
+$(REMOTE_OUT):
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(LINUX_SRC_DIR)/firmware1.o $(DST_DIR)/firmware1.o
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(LINUX_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(LINUX_SRC_DIR)/; rm firmware1; rm firmware2;
+
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_MAP) $(SAMPLE_BIN) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/tests/master/baremetal/func_test_suite/func_test_suite.c b/apps/tests/master/baremetal/func_test_suite/func_test_suite.c
new file mode 100644 (file)
index 0000000..58dc196
--- /dev/null
@@ -0,0 +1,591 @@
+/* This is a test demonstration application that tests usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running baremetal env
+and showcases booting of two sub-sequent remote firmware cycles using remoteproc and 
+IPC with remote firmware using rpmsg. It brings up a remote Linux based remote 
+firmware which can respond to test calls. Master app executes tests to validate
+the rpmsg APIs and shutsdown the core once the test has been completed.*/
+
+/* Including required headers */
+#include  <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "open_amp.h"
+#include "test_suite.h"
+
+#define BAREMETAL_MASTER 1
+
+#include "baremetal.h"
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+
+int test_rpmsg_send(struct rpmsg_channel *rpmsg_chnl);
+int test_rpmsg_send_offchannel(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
+int test_rpmsg_create_ept(struct rpmsg_channel *rpmsg_chnl);
+int test_remoteproc_multiple_lifecycles(char * firmware_name);
+int test_rpmsg_send_offchannel_impl(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
+int test_rpmsg_send_impl(struct rpmsg_channel *rpmsg_chnl);
+int test_rpmsg_remote_channel_deletion(struct rpmsg_channel *rpmsg_chnl, char *channel_name);
+int test_execute_suite(char * firmware_name);
+static void sleep();
+static void init_system();
+
+int int_flag;
+
+struct rpmsg_endpoint *rp_ept1 , *rp_ept2;
+struct rpmsg_channel *app_rp_chnl;
+char fw_name1[] = "firmware1";
+
+struct _payload* p_payload = NULL;
+struct _payload* r_payload = NULL;
+
+
+void sleep() {
+    int i;
+    for (i = 0; i < 10000; i++);
+}
+
+static void init_system() {
+
+    /* Place the vector table at the image entry point */
+    arm_arch_install_isr_vector_table(RAM_VECTOR_TABLE_ADDR);
+
+    /* Enable MMU */
+    arm_ar_mem_enable_mmu();
+
+    /* Initialize ARM stacks */
+    init_arm_stacks();
+
+    /* Initialize GIC */
+    zc702evk_gic_initialize();
+}
+
+int main()
+{
+       /* Switch to System Mode */
+    SWITCH_TO_SYS_MODE();
+
+    /* Initialize HW system components */
+    init_system();
+    
+    test_execute_suite(fw_name1);
+    
+    return 0;
+}
+
+/* This callback gets invoked when the remote chanl is created */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl )
+{
+    app_rp_chnl = rp_chnl;
+
+    rp_ept1 = rpmsg_create_ept(rp_chnl , rpmsg_read_ept1_cb , RPMSG_NULL , RPMSG_ADDR_ANY);
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl )
+{
+    rpmsg_destroy_ept( rp_ept1 );
+
+    int_flag = 1;
+
+}
+
+/* This is the read callback, note we are in a task context when this callback
+ is invoked, so kernel primitives can be used freely */
+void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    int_flag = 1;
+}
+
+void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    int_flag = 1;
+}
+
+void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    int_flag = 1;
+}
+
+
+void wait_for_event(void)
+{
+       while (1) 
+    {
+        if (int_flag) {
+        
+                       int_flag = 0;
+                       
+                       break;
+        }
+        
+        sleep();
+    }
+}
+
+void send_test_case_report(char *result_string)
+{
+       struct command* cmd;
+    
+    cmd = malloc(sizeof(struct command) + strlen(result_string) + 1);
+    
+    cmd->comm_start=CMD_START;
+    cmd->comm_code = PRINT_RESULT;
+    
+    strcpy(cmd->data, result_string);
+        
+    (void)rpmsg_send(app_rp_chnl, cmd, sizeof(struct command) + strlen(result_string) + 1);
+    
+    free(cmd);
+       
+    wait_for_event();
+}
+
+int test_execute_suite(char * firmware_name)
+{
+    struct remote_proc *proc;
+    int status;
+    char default_channel[] = "rpmsg-openamp-demo-channel";
+    struct command* cmd;
+    int i;
+
+    status = remoteproc_init( (void *) firmware_name ,rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);
+
+    if (status)
+    {
+        printf( "\r\n CRITICAL ERROR: remoteproc_init call for remote context %s failed \r\n", firmware_name);
+
+        return -1;
+    }
+
+    status = remoteproc_boot( proc );
+
+    if (status)
+    {
+        printf( "\r\n CRITICAL ERROR: remoteproc_boot call for remote context %s failed \r\n", firmware_name);
+
+        return -1;
+    }
+
+    /* Wait for channel creation event */
+    wait_for_event();
+       
+    /* Obtain remote firmware name */
+
+    cmd =  malloc(sizeof(struct command));
+    
+    cmd->comm_start=CMD_START;
+    cmd->comm_code = QUERY_FW_NAME;
+    status = rpmsg_send(app_rp_chnl, cmd, sizeof(struct command));
+
+    free(cmd);
+       
+    /* Wait to receive firmware name */
+    wait_for_event();
+       
+    /* Test rpmsg_send API */
+    status = test_rpmsg_send(app_rp_chnl);
+
+    if(!status)
+    {
+        send_test_case_report("\r\nRPMSG Send Test: Passed\r\n");
+    }
+    else
+    {
+        send_test_case_report("\r\nRPMSG Send Test: Failed\r\n");
+    }
+
+    /* Test rpmsg_send_offchannel API. */
+    status = test_rpmsg_send_offchannel(app_rp_chnl, rp_ept1->addr, app_rp_chnl->dst);
+
+    if(!status)
+    {
+        send_test_case_report("\r\nRPMSG Send Offchannel Test: Passed\r\n");
+    }
+    else
+    {
+        send_test_case_report("\r\nRPMSG Send Offchannel: Failed\r\n");
+    }
+
+    status = test_rpmsg_create_ept(app_rp_chnl);
+
+    if(!status)
+    {
+        send_test_case_report("\r\nRPMSG Create EPT Test: Passed\r\n");
+    }
+    else
+    {
+        send_test_case_report("\r\nRPMSG Create EPT Test: Failed\r\n");
+    }
+    
+    send_test_case_report("\r\nChannel Deletion. Shutdown would be next\r\n");
+            
+    status = test_rpmsg_remote_channel_deletion(app_rp_chnl, default_channel);
+    
+    for (i = 0; i < 200000; i++)
+    {
+           sleep();
+    }
+    
+    status = remoteproc_shutdown(proc);
+    if(!status)
+    {
+        status = remoteproc_deinit(proc);
+    }
+
+    /* The multiple life-cycles test has been disabled for remote Linux configuration
+       as it would require manual user input at linux console to complete 
+       the rpmsg connection and would be cumbersome for the user. The multiple
+       lifecycles have been tested seperately. */
+    
+    
+    /*if(!status)
+    {
+        status = test_remoteproc_multiple_lifecycles(firmware_name);
+    }*/
+
+    return status;
+}
+
+int test_remoteproc_multiple_lifecycles(char * firmware_name)
+{
+    int i,j, status;
+    struct remote_proc *proc;
+
+    for(i = 0; i < 2; i++)
+    {
+        status = remoteproc_init( (void *) firmware_name ,rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);
+
+        if (status)
+        {
+            break;
+        }
+               
+        status = remoteproc_boot( proc );
+
+        if (status)
+        {
+            break;
+        }
+
+        /* Wait for channel creation event */
+        wait_for_event();
+
+        if (!status)
+        {
+            status = test_rpmsg_send_impl(app_rp_chnl);
+        }
+
+        if(!status){
+            test_rpmsg_remote_channel_deletion(app_rp_chnl , app_rp_chnl->name);
+        }
+               
+        if (!status)
+        {
+                       for (j = 0; j < 200000; j++)
+                       {
+                               sleep();
+                       }
+    
+            status = remoteproc_shutdown(proc);
+        }
+        if (status)
+        {
+            break;
+        }
+        status = remoteproc_deinit(proc);
+
+        if (status)
+        {
+            break;
+        }
+    }
+
+    return status;
+}
+
+int test_rpmsg_remote_channel_deletion(struct rpmsg_channel *rpmsg_chnl, char *channel_name)
+{
+    struct command *cmd;
+    int status;
+    struct chnl_cmd_data *chnl_data;
+
+    cmd = malloc(sizeof(struct command)+ sizeof(struct chnl_cmd_data));
+
+    cmd->comm_code = DELETE_CHNL;
+    cmd->comm_start = CMD_START;
+
+    chnl_data = (struct chnl_cmd_data *)cmd->data;
+
+    strncpy(chnl_data->name , channel_name, sizeof(struct chnl_cmd_data));
+
+    /* Let the other side that uninit its resources */
+    status = rpmsg_send( rpmsg_chnl , cmd , sizeof(struct command) + sizeof(struct chnl_cmd_data) );
+    if(status)
+    {
+        return status;
+    }
+    
+    /* Wait for echo back */
+    wait_for_event();
+    
+    free(cmd);
+
+    return status;
+}
+
+int test_rpmsg_create_ept(struct rpmsg_channel *rpmsg_chnl)
+{
+    struct command *cmd;
+    int status =-1, i;
+    struct ept_cmd_data *ept_data;
+    struct rpmsg_endpoint *test_ept[NUM_TEST_EPS];
+
+    cmd = malloc(sizeof(struct command) + sizeof(struct ept_cmd_data));
+
+    if(!cmd)
+    {
+        return status;
+    }
+
+    for(i = 0; i < NUM_TEST_EPS; i++)
+    {
+        /* Tell the remote to create a new endpoint. */
+        cmd->comm_code = CREATE_EPT;
+        cmd->comm_start = CMD_START;
+
+        /* Send create endpoint command to remote */
+        ept_data = (struct ept_cmd_data *)cmd->data;
+        ept_data->dst= EPT_TEST_ADDR + i;
+        ept_data->src= EPT_TEST_ADDR + i;
+
+        /* Let the other side know that it needs to create endpoint with the given address */
+        status = rpmsg_send(rpmsg_chnl, cmd, sizeof(struct command) + sizeof(struct ept_cmd_data));
+
+        if(!status)
+        {
+            /* Wait for ack */
+            wait_for_event();
+        }
+
+        if(!status)
+        {
+            test_ept[i] = rpmsg_create_ept(rpmsg_chnl , rpmsg_read_ept2_cb , RPMSG_NULL , EPT_TEST_ADDR + i);
+
+            if ( !test_ept[i] )
+            {
+                status = -1;
+            }
+
+        }
+        if(!status)
+        {
+            status = test_rpmsg_send_offchannel_impl(rpmsg_chnl, test_ept[i]->addr, test_ept[i]->addr);
+        }
+
+        if(!status)
+        {
+            /* Tell the remote to delete the endpoint. */
+            cmd->comm_code = DELETE_EPT;
+            cmd->comm_start = CMD_START;
+            /* Send delete endpoint command to remote */
+            ept_data = (struct ept_cmd_data *)cmd->data;
+            ept_data->dst= EPT_TEST_ADDR + i;
+            ept_data->src= EPT_TEST_ADDR + i;
+
+            /* Let the other side know that it needs to delete endpoint with the given address */
+            status = rpmsg_send(rpmsg_chnl, cmd, sizeof(struct command) + sizeof(struct ept_cmd_data));
+        }
+
+        if(!status)
+        {
+            /* Wait for ack */
+            wait_for_event();
+        }
+
+        if(!status)
+        {
+            rpmsg_destroy_ept(test_ept[i]);
+        }
+    }
+
+    free(cmd);
+    
+       if(status)
+       {
+               return -1;
+       }
+
+    return status;
+}
+
+int test_rpmsg_send_impl(struct rpmsg_channel *rpmsg_chnl)
+{
+    struct command cmd;
+    int status;
+    int i, size, idx;
+
+    /* Tell the remote to be prepared for echo payloads. */
+    cmd.comm_start = CMD_START;
+    cmd.comm_code = START_ECHO;
+
+    status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+
+    if(!status)
+    {
+        /* Wait for cmd ack. */
+        wait_for_event();
+        if(status)
+        {
+            return -1;
+        }
+        for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
+        {
+            p_payload = malloc (sizeof(struct _payload) + size );
+
+            p_payload->num = i;
+            p_payload->size = size;
+
+            /* Setup the buffer with a pattern*/
+            memset(p_payload->data, 0xA5, size);
+
+            /* Send data to remote side. */
+            status = rpmsg_send(rpmsg_chnl, p_payload, sizeof(struct _payload) + size);
+
+            if(status != 0)
+            {
+                break;
+            }
+
+            /* Wait for echo. */
+            wait_for_event();
+
+            /* Validate the data integrity. */
+            for(idx = 0; idx < r_payload->size; idx++)
+            {
+                if(p_payload->data[idx] != r_payload->data[idx])
+                {
+                    status = -1;
+                    break;
+                }
+            }
+
+            if(status != 0)
+            {
+                break;
+            }
+
+            free(p_payload);
+
+        }
+        if(status)
+        {
+            return -1;
+        }
+        cmd.comm_start = CMD_START;
+        cmd.comm_code = STOP_ECHO;
+
+        status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+        if(status)
+        if(status)
+        {
+            return -1;
+        }
+
+        /* Wait for echo. */
+        wait_for_event();
+       
+     }
+
+    return status;
+}
+int test_rpmsg_send(struct rpmsg_channel *rpmsg_chnl)
+{
+    return test_rpmsg_send_impl(rpmsg_chnl);
+}
+
+int test_rpmsg_send_offchannel_impl(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst)
+{
+    struct command cmd;
+    int status;
+    int i, size, idx;
+
+    /* Tell the remote to be prepared for echo payloads. */
+    cmd.comm_code = START_ECHO;
+    cmd.comm_start = CMD_START;
+    status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+
+    if(!status)
+    {
+        /* Wait for cmd ack. */
+        wait_for_event();
+        
+
+        for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
+        {
+            p_payload = malloc(sizeof(struct _payload) + size );
+            
+            p_payload->num = i;
+            p_payload->size = size;
+
+            /* Setup the buffer with a pattern*/
+            memset(p_payload->data, 0xA5, size);
+
+            /* Send data to remote side. */
+            status = rpmsg_send_offchannel(app_rp_chnl, src, dst, p_payload ,
+                                             sizeof(struct _payload) + size);
+
+            if(status)
+            {
+                break;
+            }
+
+            /* Wait for echo. */
+            wait_for_event();
+
+            /* Validate the data integrity. */
+            for(idx = 0; idx < r_payload->size; idx++)
+            {
+                if(p_payload->data[idx] != r_payload->data[idx])
+                {
+                    status = -1;
+                    break;
+                }
+            }
+
+            if(status)
+            {
+                break;
+            }
+
+            free(p_payload);
+        }
+        cmd.comm_start = CMD_START;
+        cmd.comm_code = STOP_ECHO;
+
+        status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+        
+        /* Wait for cmd ack. */
+         wait_for_event();
+     }
+
+     return status;
+}
+
+int test_rpmsg_send_offchannel(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst)
+{
+    return test_rpmsg_send_offchannel_impl(rpmsg_chnl, src, dst);
+}
diff --git a/apps/tests/master/baremetal/func_test_suite/make b/apps/tests/master/baremetal/func_test_suite/make
new file mode 100644 (file)
index 0000000..56b96c8
--- /dev/null
@@ -0,0 +1,49 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := tests/master/baremetal/func_test_suite/func_test_suite.out
+SAMPLE_C_SRC := tests/master/baremetal/func_test_suite/func_test_suite.c
+REMOTE_OUT   := func_test_suite.out
+DST_DIR := tests/master/baremetal/func_test_suite
+LINUX_SRC_DIR := firmware/$(PLAT)/linux
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_C_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_C_SRC))
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(REMOTE_OUT)$(SAMPLEOBJFILES)
+
+       @echo 'Building func_test_suite test for nucleus : $@'
+
+       $(LD)  -Wl,-Map=tests/master/baremetal/func_test_suite/func_test_suite.map -Wl,--gc-sections -T"$(OHOME)/libs/system/$(PLAT)/baremetal/linker_master.ld" -L"$(OHOME)/libs/open_amp" -L"$(OHOME)/libs/system/$(PLAT)/baremetal" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lopen_amp -lbaremetal_master -lc -lm -lstdc++ -lcs3 -lcs3arm -lcs3unhosted -Wl,--end-group 
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+               
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+       
+%.o:%.S
+       @$(AS) -c -mcpu=cortex-a9 $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@
+
+$(REMOTE_OUT):
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(LINUX_SRC_DIR)/firmware1.o $(DST_DIR)/firmware1.o
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(LINUX_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(LINUX_SRC_DIR)/; rm firmware1; rm firmware2;
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o $(SAMPLE_MAP) $(SAMPLE_BIN)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/tests/master/baremetal/func_test_suite/test_suite.h b/apps/tests/master/baremetal/func_test_suite/test_suite.h
new file mode 100644 (file)
index 0000000..4a0ca99
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * m_ept_func_test.h
+ *
+ *  Created on: Mar 14, 2014
+ *      Author: etsam
+ */
+
+#ifndef M_EPT_FUNC_TEST_H_
+#define M_EPT_FUNC_TEST_H_
+
+struct command
+{
+    unsigned int comm_start;
+    unsigned int comm_code;
+    char data[0];
+}__attribute__((__packed__));
+
+struct ept_cmd_data
+{
+    unsigned int src;
+    unsigned int dst;
+};
+
+struct chnl_cmd_data
+{
+    char name[32];
+};
+
+/* Command Codes */
+
+#define CREATE_EPT      0x00000000
+#define DELETE_EPT      0x00000001
+#define CREATE_CHNL     0x00000002
+#define DELETE_CHNL     0x00000003
+#define START_ECHO      0x00000004
+#define STOP_ECHO       0x00000005
+#define QUERY_FW_NAME   0x00000006
+#define PRINT_RESULT    0x00000007
+
+#define CMD_START       0xEF56A55A
+
+/* Define the main task's stack size */
+#define STACK_SIZE      (NU_MIN_STACK_SIZE * 400)
+
+/* Define the main task's priority */
+#define TASK_PRIORITY   26
+
+/* Define the main task's time slice */
+#define TASK_SLICE      20
+
+#define EPT_TEST_ADDR      59
+
+#define NUM_TEST_EPS       4
+
+#define MAX_RPMSG_BUFF_SIZE 512
+#define PAYLOAD_MIN_SIZE    1    
+#define PAYLOAD_MAX_SIZE    (MAX_RPMSG_BUFF_SIZE - 24)
+#define NUM_PAYLOADS        (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
+
+struct _payload {
+    unsigned long    num;
+    unsigned long    size;
+    char             data[0];
+}__attribute__((__packed__));
+
+
+#endif /* M_EPT_FUNC_TEST_H_ */
diff --git a/apps/tests/master/linux/kernelspace/rpmsg_echo_test_kern_app/rpmsg_echo_test_kern_app.c b/apps/tests/master/linux/kernelspace/rpmsg_echo_test_kern_app/rpmsg_echo_test_kern_app.c
new file mode 100644 (file)
index 0000000..19c99f7
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * RPMSG Echo Test Kernel Driver
+ *
+ * Copyright (C) 2014 Mentor Graphics Corporation
+ *
+ * Test application that validates data integraty of inter processor
+ * communication from linux userspace to a remote software
+ * context. The application sends chunks of data to the
+ * remote processor. The remote side echoes the data back
+ * to application which then validates the data returned.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+
+static DECLARE_WAIT_QUEUE_HEAD(wait_queue);
+static int flag;
+
+struct _payload {
+unsigned long  num;
+unsigned long  size;
+char           data[];
+};
+
+#define MAX_RPMSG_BUFF_SIZE 512
+#define PAYLOAD_MIN_SIZE       1
+#define PAYLOAD_MAX_SIZE       (MAX_RPMSG_BUFF_SIZE - 24)
+#define NUM_PAYLOADS           (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
+/* Shutdown message ID */
+#define SHUTDOWN_MSG           0xEF56A55A
+
+#define GIGA                   1000000000L
+
+static const char * const shutdown_argv[]
+                       = { "/sbin/shutdown", "-h", "-P", "now", NULL };
+
+struct rpmsg_endpoint *ept;
+
+struct _payload *p_payload;
+
+static const char init_msg[] = "init_msg";
+int err_cnt;
+
+static void rpmsg_echo_test_kern_app_rx_cb(struct rpmsg_channel *rpdev,
+                       void *data, int len, void *priv, u32 src)
+{
+       struct _payload *local_payload = data;
+       int     i;
+
+       if (p_payload) {
+
+               pr_err("\r\n Master : Linux Kernal Space : Received payload ");
+               pr_err("num %d of size %d \r\n", local_payload->num, len);
+
+               /* Shutdown Linux if such a message is received.
+               Only applicable when Linux is a remoteproc remote. */
+               if ((*(int *) data) == SHUTDOWN_MSG) {
+                       call_usermodehelper(shutdown_argv[0], shutdown_argv,
+                                               NULL, UMH_NO_WAIT);
+               } else {
+
+                       for (i = 0; i < local_payload->size; i++) {
+
+                               if (local_payload->data[i] != 0xA5) {
+                                       pr_err("\r\n Data corruption ");
+                                       pr_cont("at index %d \r\n", i);
+                                       err_cnt++;
+                                       break;
+                               }
+                       }
+
+                       /* Free memory allocated to payload buffer. */
+                       kzfree(p_payload);
+
+                       /* Wake up the application. */
+                       flag = 1;
+                       wake_up_interruptible(&wait_queue);
+               }
+       }
+}
+
+static int rpmsg_echo_test_kern_app_probe(struct rpmsg_channel *rpdev)
+{
+       int     err, i, size;
+       int shutdown_msg = SHUTDOWN_MSG;
+
+       pr_err("\r\n Echo Test Start! \r\n");
+
+       /* Create endpoint for remote channel and register rx callabck */
+       ept = rpmsg_create_ept(rpdev, rpmsg_echo_test_kern_app_rx_cb, 0,
+                               RPMSG_ADDR_ANY);
+
+       if (!ept) {
+               pr_err(" Endpoint creation for failed!\r\n");
+               return -ENOMEM;
+       }
+
+       /* Send init message to complete the connection loop */
+       err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                               init_msg, sizeof(init_msg));
+
+       if (err) {
+               pr_err(" Init message send failed!\r\n");
+               return err;
+       }
+
+       for (i = 0, size = PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++) {
+               p_payload = kzalloc(2 * sizeof(unsigned long) + size,
+                                       GFP_KERNEL);
+               p_payload->num = i;
+               p_payload->size = size;
+               memset(&(p_payload->data[0]), 0xA5, size);
+
+               pr_err("\r\n Master : Linux Kernal Space : Sending payload num %d of size %d \r\n",
+                       p_payload->num, (2 * sizeof(unsigned long)) + size);
+
+               /* Send payload to remote. */
+               err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                               p_payload, (2 * sizeof(unsigned long)) + size);
+
+               if (err) {
+                       pr_err(" send failed!\r\n");
+                       return err;
+               }
+
+               /* Wait till the data is echoed back. */
+               wait_event_interruptible(wait_queue, flag != 0);
+               flag = 0;
+       }
+
+       /* Send payload to remote. */
+       err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                               &shutdown_msg, sizeof(int));
+
+       if (err) {
+               pr_err(" Shutdown message send failed!\r\n");
+               return err;
+       }
+
+       pr_err("\r\n *******************************************\r\n");
+       pr_err("\r\n Echo Test Results: Error count = %d\r\n", err_cnt);
+       pr_err("\r\n *******************************************\r\n");
+
+       return 0;
+}
+
+static void rpmsg_echo_test_kern_app_remove(struct rpmsg_channel *rpdev)
+{
+       rpmsg_destroy_ept(ept);
+}
+
+static void rpmsg_cb(struct rpmsg_channel *rpdev, void *data,
+                                       int len, void *priv, u32 src)
+{
+
+}
+
+static struct rpmsg_device_id rpmsg_echo_test_kern_app_id_table[] = {
+       { .name = "rpmsg-openamp-demo-channel" },
+       { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_echo_test_kern_app_id_table);
+
+static struct rpmsg_driver rpmsg_echo_test_kern_app = {
+       .drv.name       = KBUILD_MODNAME,
+       .drv.owner   = THIS_MODULE,
+       .id_table       = rpmsg_echo_test_kern_app_id_table,
+       .probe     = rpmsg_echo_test_kern_app_probe,
+       .callback       = rpmsg_cb,
+       .remove   = rpmsg_echo_test_kern_app_remove,
+};
+
+static int __init init(void)
+{
+       return register_rpmsg_driver(&rpmsg_echo_test_kern_app);
+}
+
+static void __exit fini(void)
+{
+       unregister_rpmsg_driver(&rpmsg_echo_test_kern_app);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_DESCRIPTION("rpmsg echo test kernel application");
+MODULE_LICENSE("GPL v2");
diff --git a/apps/tests/master/linux/kernelspace/rpmsg_func_test_kern_app/rpmsg_func_test_kern_app.c b/apps/tests/master/linux/kernelspace/rpmsg_func_test_kern_app/rpmsg_func_test_kern_app.c
new file mode 100644 (file)
index 0000000..ca3c91d
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * RPMSG Functional Test Suite Kernel Driver
+ *
+ * Copyright (C) 2014 Mentor Graphics Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+
+static DECLARE_WAIT_QUEUE_HEAD(wait_queue);
+static int flag;
+
+struct _payload {
+       unsigned long   num;
+       unsigned long   size;
+       char                     data[];
+};
+
+struct command {
+       unsigned int comm_start;
+       unsigned int comm_code;
+       char data[0];
+} __attribute__((__packed__));
+
+struct ept_cmd_data {
+       unsigned int src;
+       unsigned int dst;
+};
+
+struct chnl_cmd_data {
+       char name[32];
+};
+
+#define MAX_RPMSG_BUFF_SIZE    512
+#define PAYLOAD_MIN_SIZE       1
+#define PAYLOAD_MAX_SIZE       (MAX_RPMSG_BUFF_SIZE - 24)
+#define NUM_PAYLOADS           (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
+
+
+/* Command Codes */
+
+#define CREATE_EPT     0x00000000
+#define DELETE_EPT     0x00000001
+#define CREATE_CHNL    0x00000002
+#define DELETE_CHNL    0x00000003
+#define START_ECHO     0x00000004
+#define STOP_ECHO      0x00000005
+#define QUERY_FW_NAME  0x00000006
+#define PRINT_RESULT   0x00000007
+
+#define CMD_START      0xEF56A55A
+
+
+struct rpmsg_endpoint *ept;
+struct rpmsg_endpoint *rp_ept;
+
+struct _payload *p_payload;
+
+char firmware_name[] = "linux-fn-test-suite-remote-firmware";
+
+u32 source_buffer;
+int data_length;
+
+char r_buffer[512];
+
+static const char init_msg[] = "init_msg";
+static const char start_test[] = "start_test";
+
+int err_cnt;
+
+static const char * const shutdown_argv[]
+       = { "/sbin/shutdown", "-h", "-P", "now", NULL };
+
+
+static void rpmsg_func_test_default_rx_cb(struct rpmsg_channel *rpdev,
+                       void *data, int len, void *priv, u32 src)
+{
+       if (data) {
+               memcpy(r_buffer, data, len);
+               source_buffer = src;
+               data_length = len;
+
+               /* Wake up the application. */
+               flag = 1;
+               wake_up_interruptible(&wait_queue);
+       }
+}
+
+static void rpmsg_func_test_ept_rx_cb(struct rpmsg_channel *rpdev,
+                       void *data, int len, void *priv, u32 src)
+{
+       rpmsg_send_offchannel(rpdev, rp_ept->addr, src, data, len);
+}
+
+static int rpmsg_func_test_kern_app_probe(struct rpmsg_channel *rpdev)
+{
+       int     err;
+       int   uninit = 0;
+       struct ept_cmd_data *ept_data;
+       struct command *cmd;
+
+       pr_err("\r\nFunc Test Suite Start! \r\n");
+
+       /* Create endpoint for remote channel and register rx callabck */
+       ept = rpmsg_create_ept(rpdev, rpmsg_func_test_default_rx_cb, 0,
+                               RPMSG_ADDR_ANY);
+
+       if (!ept) {
+               pr_err(" Endpoint creation for failed!\r\n");
+               return -ENOMEM;
+       }
+
+       /* Send init message to complete the connection loop */
+       err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                               init_msg, sizeof(init_msg));
+
+       if (err) {
+               pr_err(" Init message send failed!\r\n");
+               return err;
+       }
+
+       /* Send a message to start tests */
+       err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                               start_test, sizeof(start_test));
+
+       if (err) {
+               pr_err("Test start command failed!\r\n");
+               return err;
+       }
+
+
+       while (1) {
+               /* Wait till the data is echoed back. */
+               wait_event_interruptible(wait_queue, flag != 0);
+               flag = 0;
+
+               cmd = (struct command *)r_buffer;
+
+               if (cmd->comm_start == CMD_START) {
+                       unsigned int cm_code = cmd->comm_code;
+                       void *data = cmd->data;
+
+                       switch (cm_code) {
+                       case CREATE_EPT:
+                               ept_data = (struct ept_cmd_data *)data;
+                               rp_ept = rpmsg_create_ept(rpdev,
+                                               rpmsg_func_test_ept_rx_cb,
+                                               0, ept_data->dst);
+                               if (rp_ept)
+                                       /* Send data back to ack. */
+                                       rpmsg_send_offchannel(rpdev,
+                                                       ept->addr, rpdev->dst,
+                                                       r_buffer, data_length);
+                               break;
+                       case DELETE_EPT:
+                               rpmsg_destroy_ept(rp_ept);
+                               rpmsg_send_offchannel(rpdev, ept->addr,
+                                                       rpdev->dst,
+                                                       r_buffer, data_length);
+                               break;
+                       case CREATE_CHNL:
+                               break;
+                       case DELETE_CHNL:
+                               rpmsg_send_offchannel(rpdev, ept->addr,
+                                                       rpdev->dst,
+                                                       r_buffer, data_length);
+                               uninit = 1;
+                               break;
+                       case QUERY_FW_NAME:
+                               rpmsg_send_offchannel(rpdev, ept->addr,
+                                               rpdev->dst,
+                                               &firmware_name[0],
+                                               strlen(firmware_name)+1);
+                               break;
+                       case PRINT_RESULT:
+                               pr_err("%s", data);
+                               rpmsg_send_offchannel(rpdev, ept->addr,
+                                                       rpdev->dst,
+                                                       r_buffer, data_length);
+                               break;
+                       default:
+                               rpmsg_send_offchannel(rpdev, ept->addr,
+                                                       rpdev->dst,
+                                                       r_buffer, data_length);
+                               break;
+                       }
+               } else
+                       rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
+                                               r_buffer, data_length);
+
+               if (uninit)
+                       break;
+       }
+
+       call_usermodehelper(shutdown_argv[0], shutdown_argv, NULL, UMH_NO_WAIT);
+
+       return 0;
+}
+
+static void rpmsg_func_test_kern_app_remove(struct rpmsg_channel *rpdev)
+{
+       rpmsg_destroy_ept(ept);
+}
+
+static void rpmsg_cb(struct rpmsg_channel *rpdev, void *data,
+                                       int len, void *priv, u32 src)
+{
+
+}
+
+static struct rpmsg_device_id rpmsg_func_test_kern_app_id_table[] = {
+       { .name = "rpmsg-openamp-demo-channel" },
+       { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_func_test_kern_app_id_table);
+
+static struct rpmsg_driver rpmsg_func_test_kern_app = {
+       .drv.name       = KBUILD_MODNAME,
+       .drv.owner   = THIS_MODULE,
+       .id_table       = rpmsg_func_test_kern_app_id_table,
+       .probe     = rpmsg_func_test_kern_app_probe,
+       .callback       = rpmsg_cb,
+       .remove   = rpmsg_func_test_kern_app_remove,
+};
+
+static int __init init(void)
+{
+       return register_rpmsg_driver(&rpmsg_func_test_kern_app);
+}
+
+static void __exit fini(void)
+{
+       unregister_rpmsg_driver(&rpmsg_func_test_kern_app);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_DESCRIPTION("rpmsg functional test kernel application");
diff --git a/apps/tests/master/linux/userspace/echo_test/echo_test.c b/apps/tests/master/linux/userspace/echo_test/echo_test.c
new file mode 100644 (file)
index 0000000..e8c0e93
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * temp.c
+ *
+ *  Created on: Oct 4, 2014
+ *      Author: etsam
+ */
+
+/*
+ * Test application that data integraty of inter processor
+ * communication from linux userspace to a remote software
+ * context. The application sends chunks of data to the
+ * remote processor. The remote side echoes the data back
+ * to application which then validates the data returned.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <fcntl.h>
+#include <string.h>
+
+/* Shutdown message ID */
+#define SHUTDOWN_MSG   0xEF56A55A
+
+struct _payload {
+       unsigned long num;
+       unsigned long size;
+       char data[];
+};
+
+static int fd, err_cnt;
+
+struct _payload *i_payload;
+struct _payload *r_payload;
+
+#define RPMSG_GET_KFIFO_SIZE 1
+#define RPMSG_GET_AVAIL_DATA_SIZE 2
+#define RPMSG_GET_FREE_SPACE 3
+
+#define MAX_RPMSG_BUFF_SIZE 512
+#define PAYLOAD_MIN_SIZE       1
+#define PAYLOAD_MAX_SIZE       (MAX_RPMSG_BUFF_SIZE - 24)
+#define NUM_PAYLOADS           (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
+
+int main(int argc, char *argv[])
+{
+       int flag = 1;
+       int shutdown_msg = SHUTDOWN_MSG;
+       int cmd, ret, i;
+       unsigned int size, bytes_rcvd, bytes_sent;
+       err_cnt = 0;
+
+       printf("\r\n Echo test start \r\n");
+
+       printf("\r\n Open rpmsg dev! \r\n");
+
+       fd = open("/dev/rpmsg", O_RDWR);
+
+       printf("\r\n Query internal info .. \r\n");
+
+       ioctl(fd, RPMSG_GET_KFIFO_SIZE, &size);
+
+       printf(" rpmsg kernel fifo size = %u \r\n", size);
+
+       ioctl(fd, RPMSG_GET_FREE_SPACE, &size);
+
+       printf(" rpmsg kernel fifo free space = %u \r\n", size);
+
+       while (flag == 1) {
+               printf("\r\n **************************************** \r\n");
+               printf(" Please enter command and press enter key\r\n");
+               printf(" **************************************** \r\n");
+               printf(" 1 - Send data to remote core, retrieve the echo");
+               printf(" and validate its integrity .. \r\n");
+               printf(" 2 - Quit this application .. \r\n");
+               printf(" CMD>");
+               ret = scanf("%d", &cmd);
+               if (!ret) {
+                       while (1) {
+                               if (getchar() == '\n')
+                                       break;
+                       }
+
+                       printf("\r\n invalid command\r\n");
+                       continue;
+               }
+
+               if (cmd == 1) {
+                       for (i = 0, size = PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS;
+                       i++, size++) {
+                               i_payload = malloc(
+                               2 * sizeof(unsigned long) + size);
+                               i_payload->num = i;
+                               i_payload->size = size;
+
+                               /* Mark the data buffer. */
+                               memset(&(i_payload->data[0]), 0xA5, size);
+
+                               printf("\r\n sending payload number");
+                               printf(" %d of size %d \r\n", i_payload->num,
+                               (2 * sizeof(unsigned long)) + size);
+
+                               bytes_sent = write(fd, i_payload,
+                               (2 * sizeof(unsigned long)) + size);
+
+                               if (bytes_sent <= 0) {
+                                       printf("\r\n Error sending data");
+                                       printf(" .. \r\n");
+                                       free(i_payload);
+                                       break;
+                               }
+
+                               r_payload = malloc(
+                               (2 * sizeof(unsigned long)) + i_payload->size);
+
+                               bytes_rcvd = read(fd, r_payload,
+                               (2 * sizeof(unsigned long)) + i_payload->size);
+
+                               printf(" received payload number ");
+                               printf("%d of size %d \r\n", r_payload->num,
+                               bytes_rcvd);
+
+                               /* Validate data buffer integrity. */
+                               for (i = 0; i < r_payload->size; i++) {
+
+                                       if (r_payload->data[i] != 0xA5) {
+                                               printf(" \r\n Data corruption");
+                                               printf(" at index %d \r\n", i);
+                                               err_cnt++;
+                                               break;
+                                       }
+                               }
+
+                               free(i_payload);
+                               free(r_payload);
+                       }
+
+                       printf("\r\n **********************************");
+                       printf("****\r\n");
+                       printf("\r\n Test Results: Error count = %d\r\n",
+                       err_cnt);
+                       printf("\r\n **********************************");
+                       printf("****\r\n");
+               } else if (cmd == 2) {
+                       flag = 0;
+                       /* Send shutdown message to remote */
+                       write(fd, &shutdown_msg, sizeof(int));
+                       sleep(1);
+                       printf("\r\n Quitting application .. \r\n");
+                       printf(" Echo test end \r\n");
+               } else {
+                       printf("\r\n invalid command! \r\n");
+               }
+       }
+
+       close(fd);
+
+       return 0;
+}
+
+
diff --git a/apps/tests/master/nucleus/echo_test/nucleus_linux/echo_test.c b/apps/tests/master/nucleus/echo_test/nucleus_linux/echo_test.c
new file mode 100644 (file)
index 0000000..2f06e20
--- /dev/null
@@ -0,0 +1,196 @@
+/* This is a sample demonstration application that showcases usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running Nucleus
+and showcases booting of linux remote firmware using remoteproc and 
+IPC with remote firmware using rpmsg; Nucleus on master core acts as a remoteproc master
+but as an rpmsg remote;It brings up a remote Linux based 
+firmware which acts as an rpmsg master and transmits data payloads to Nucleus.
+Linux app sends paylaods of incremental sizes to Nucleus which echoes them back to Linux. 
+Once Linux application is complete, it requests a shutdown from Nucleus. 
+Nucleus acknowledges with a shutdown message which results in Linux starting a system halt. 
+Nucleus shutsdown the remote core after a reasonable delay which allows
+Linux to gracefully shutdown. */
+
+/* Including required headers */
+#include  <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "open_amp.h"
+#include "nucleus.h"
+#include "kernel/nu_kernel.h"
+
+/* Define the main task's stack size */
+#define STACK_SIZE      (NU_MIN_STACK_SIZE * 64)
+
+/* Define the main task's priority */
+#define TASK_PRIORITY   26
+
+/* Define the main task's time slice */
+#define TASK_SLICE      20
+
+#define MAX_RPMSG_BUFF_SIZE 512
+#define PAYLOAD_MIN_SIZE    1    
+#define PAYLOAD_MAX_SIZE    (MAX_RPMSG_BUFF_SIZE - 24)
+#define NUM_PAYLOADS        (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
+
+#define SHUTDOWN_MSG   0xEF56A55A
+
+/* Prototypes */
+static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric , unsigned long src );
+
+/* Globals */
+NU_TASK Task_Control_Block;
+NU_SEMAPHORE App_Sem;
+struct rpmsg_endpoint *rp_ept;
+struct rpmsg_channel *app_rp_chnl;
+char fw_name1 []= "firmware1";
+
+int global_count;
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Application_Initialize
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Demo application entry point
+ *
+ * ***********************************************************************/
+VOID Application_Initialize(NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
+{
+    VOID *pointer;
+    STATUS status = NU_SUCCESS;
+
+    /* Reference unused parameters to avoid toolset warnings */
+    NU_UNUSED_PARAM( uncached_mem_pool );
+
+    if (status == NU_SUCCESS)
+    {
+        status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
+
+        /* Create the main task for matrix processing */
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
+                                    uncached_mem_pool , pointer , STACK_SIZE , 
+                                    TASK_PRIORITY , TASK_SLICE , NU_PREEMPT , NU_START );
+        }
+        if(status == NU_SUCCESS)
+        {
+            status = NU_Create_Semaphore(&App_Sem ,"APP_SEM", 0, NU_FIFO);
+        }
+    }
+
+    /* Check to see if previous operations were successful */
+    if ( status != NU_SUCCESS )
+    {
+        /* Loop forever */
+        while ( 1 );
+    }
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Main_Task_Entry
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Entry function for the main task. This task prints a hello world
+ * *       message.
+ * *
+ * ***********************************************************************/
+static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv ) {
+
+    struct remote_proc *proc;
+    int                status;
+       int shutdown_msg = SHUTDOWN_MSG;
+           
+       printf("\n\n\r************************************");
+       printf("*******************************************\r\n");
+       printf("\r\n              Echo Test Application \r\n");
+       printf("\r\n");
+       printf("\r\nThis test application will start a linux kernel on remote core and will act\r\n");
+       printf("\r\nas an RPMSG remote itself to echo back any data that it receives from Linux\r\n");
+
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n");
+
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n");
+    printf("\r\nLoading remote context : %s \r\n" , fw_name1);
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n");
+    
+  
+    status = remoteproc_init((void *) fw_name1, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+    
+    if(!status && (proc))
+    {
+               printf("\r\n\n********************************************\r\n");
+        printf("BOOTING LINUX REMOTE FIRMWARE");
+           printf("\r\n********************************************\r\n\n");
+        status = remoteproc_boot(proc);
+    }
+    
+    if(!status)
+    {   
+           /* Wait for shutdown message. */
+           NU_Obtain_Semaphore(&App_Sem, NU_SUSPEND);
+                       
+               /* Send shutdown message to remote */
+               rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
+               
+               /* The remote Linux kernel requires around ~15 seconds to shutdown itself. Wait. */
+               NU_Sleep(100 * 18);
+               
+               remoteproc_shutdown(proc);
+               
+               remoteproc_deinit(proc);
+
+    }
+    else
+    {
+        printf("\r\n\nLoading remote context: %s failed \r\n" , fw_name1);
+    }       
+
+    printf("\r\nTest Completed \r\n");
+}
+
+/* This callback gets invoked when the remote chanl is created */
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
+
+    app_rp_chnl = rp_chnl;
+    
+    rp_ept = rpmsg_create_ept(rp_chnl , rpmsg_read_cb ,RPMSG_NULL , RPMSG_ADDR_ANY);
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
+    
+    rpmsg_destroy_ept(rp_ept);
+
+}
+
+/* This is the read callback, note we are in a task context when this callback
+is invoked, so kernel primitives can be used freely */
+void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
+                void * priv, unsigned long src) {
+   
+    if ((*(int *) data) == SHUTDOWN_MSG)
+    {
+        NU_Release_Semaphore(&App_Sem);
+    }
+    else
+    {
+           rpmsg_send(rp_chnl, data, len);
+    }
+}
+
diff --git a/apps/tests/master/nucleus/echo_test/nucleus_linux/make b/apps/tests/master/nucleus/echo_test/nucleus_linux/make
new file mode 100644 (file)
index 0000000..51805cf
--- /dev/null
@@ -0,0 +1,49 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := tests/master/nucleus/echo_test/nucleus_linux/echo_test.out
+SAMPLE_C_SRC := tests/master/nucleus/echo_test/nucleus_linux/echo_test.c
+REMOTE_OUT   := echo_test.out
+DST_DIR := tests/master/nucleus/echo_test/nucleus_linux
+LINUX_SRC_DIR := firmware/$(PLAT)/linux
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_C_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_C_SRC))
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(REMOTE_OUT)$(SAMPLEOBJFILES)
+
+       @echo 'Building echo_test test for nucleus : $@'
+
+       $(LD)  -Wl,-Map=tests/master/nucleus/echo_test/nucleus_linux/echo_test.map  -nostartfiles -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=free -T"$(OHOME)/libs/system/$(PLAT)/nucleus/linker_master.ld" -L"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/master" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lnucleus_master -lopen_amp -lc -lm -lstdc++ -Wl,--end-group  
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+               
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+       
+%.o:%.S
+       @$(AS) -c $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@
+
+$(REMOTE_OUT):
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(LINUX_SRC_DIR)/firmware1.o $(DST_DIR)/firmware1.o
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(LINUX_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(LINUX_SRC_DIR)/; rm firmware1; rm firmware2;
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_BIN) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o $(SAMPLE_MAP)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/tests/master/nucleus/echo_test/nucleus_nucleusbm/echo_test.c b/apps/tests/master/nucleus/echo_test/nucleus_nucleusbm/echo_test.c
new file mode 100644 (file)
index 0000000..cb865d9
--- /dev/null
@@ -0,0 +1,338 @@
+/* This is a test demonstration application that showcases usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running Nucleus
+and showcases booting of two sub-sequent remote firmware cycles using remoteproc and 
+IPC with remote firmware using rpmsg; 1. It brings up a remote Nucleus based remote 
+firmware which echoes back payload data, 2. It brings up a baremetal based 
+remote firmware which echoes back payload data. Master app transmists paylaods of
+varying sizes to the remote core which echoes them back. The master core validates
+the data integrity and shutsdown the core once the test has been completed.*/
+
+/* Including required headers */
+#include  <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "open_amp.h"
+#include "nucleus.h"
+#include "kernel/nu_kernel.h"
+
+/* Define the main task's stack size */
+#define STACK_SIZE      (NU_MIN_STACK_SIZE * 64)
+
+/* Define the main task's priority */
+#define TASK_PRIORITY   26
+
+/* Define the main task's time slice */
+#define TASK_SLICE      20
+
+#define MAX_RPMSG_BUFF_SIZE 512
+#define PAYLOAD_MIN_SIZE    1    
+#define PAYLOAD_MAX_SIZE    (MAX_RPMSG_BUFF_SIZE - 24)
+#define NUM_PAYLOADS        (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
+
+#define SHUTDOWN_MSG   0xEF56A55A
+
+struct _payload {
+    unsigned long    num;
+    unsigned long    size;
+    char             data[];
+};
+
+/* Prototypes */
+static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric , unsigned long src );
+
+/* Globals */
+NU_TASK Task_Control_Block;
+NU_SEMAPHORE App_Sem;
+struct rpmsg_endpoint *rp_ept;
+struct rpmsg_channel *app_rp_chnl;
+char fw_name1 []= "firmware1";
+char fw_name2 []= "firmware2";
+
+struct _payload* p_payload = NULL;
+struct _payload* r_payload = NULL;
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Application_Initialize
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Demo application entry point
+ *
+ * ***********************************************************************/
+VOID Application_Initialize(NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
+{
+    VOID *pointer;
+    STATUS status = NU_SUCCESS;
+
+    /* Reference unused parameters to avoid toolset warnings */
+    NU_UNUSED_PARAM( uncached_mem_pool );
+
+    if (status == NU_SUCCESS)
+    {
+        status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
+
+        /* Create the main task for matrix processing */
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
+                                    uncached_mem_pool , pointer , STACK_SIZE , 
+                                    TASK_PRIORITY , TASK_SLICE , NU_PREEMPT , NU_START );
+        }
+        if(status == NU_SUCCESS)
+        {
+            status = NU_Create_Semaphore(&App_Sem ,"APP_SEM", 0, NU_FIFO);
+        }
+    }
+
+    /* Check to see if previous operations were successful */
+    if ( status != NU_SUCCESS )
+    {
+        /* Loop forever */
+        while ( 1 );
+    }
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Main_Task_Entry
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Entry function for the main task. This task prints a hello world
+ * *       message.
+ * *
+ * ***********************************************************************/
+static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv ) {
+
+    struct remote_proc *proc;
+    int                idx ,i, size, status;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+    int shutdown_msg = SHUTDOWN_MSG;
+
+    NU_System_Memory_Get(&sys_pool_ptr, NU_NULL);
+       
+       printf("\n\n\r************************************");
+       printf("*******************************************\r\n");
+       printf("\r\n              Echo Test Application \r\n");
+       printf("\r\n");
+       printf("\r\nThis test application will send variable length data \r\n");
+       printf("\r\npackets to remote cores\r\n");
+
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n");
+
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n");
+    printf("\r\nLoading remote context : %s \r\n" , fw_name1);
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n");
+    
+    NU_Allocate_Memory(sys_pool_ptr, (VOID **)&r_payload, (2 * sizeof(unsigned long) + PAYLOAD_MAX_SIZE), NU_NO_SUSPEND);
+            
+    status = remoteproc_init((void *) fw_name1, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+    
+    if(!status && (proc))
+    {
+               printf("\r\n\n********************************************\r\n");
+        printf("BOOTING NUCLEUS REMOTE FIRMWARE");
+           printf("\r\n********************************************\r\n\n");
+        status = remoteproc_boot(proc);
+    }
+    
+    if(!status)
+    {   
+        /* Wait for channel creation complete  callback. */
+        NU_Obtain_Semaphore(&App_Sem, NU_SUSPEND);
+        
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+        printf("\r\nStarting echo test on : %s \r\n" , fw_name1);
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");
+        
+        for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
+        {     
+            NU_Allocate_Memory(sys_pool_ptr, (VOID **)&p_payload, (2 * sizeof(unsigned long) + size), NU_NO_SUSPEND);
+                    
+            p_payload->num = i;
+            
+            p_payload->size = size;
+            
+            /* Setup the buffer with a pattern*/    
+            memset(&(p_payload->data[0]), 0xA5, size);  
+         
+            printf("\r\nSending data packet of size: %d to remote firmware : %s \r\n" , size, fw_name1);
+                    
+            /* Send data to remote side. */
+            rpmsg_send(app_rp_chnl, p_payload, (2 * sizeof(unsigned long)) + size);
+            
+            /* Wait for echo. */
+            NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+            
+            /* Validate packet number*/
+            if(p_payload->num != r_payload->num)
+            {
+                printf("\r\nError Echo packet number does not match with transmitted packet number: %d \r\n", (int)p_payload->num);
+            }
+                  
+            /* Validate the data integrity. */
+            for(idx = 0; idx < r_payload->size; idx++)
+            {
+                if(p_payload->data[idx] != r_payload->data[idx])
+                {
+                    printf("\r\nError receiving data packet of size: %d at data index %d \r\n", size, idx);
+                    break;
+                }
+            }
+            
+            if(idx == size)
+            {
+                printf("\r\nReceived data packet of size: %d from remote successfully \r\n", size);
+            }
+            
+            NU_Deallocate_Memory(p_payload);
+        }
+
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");  
+        printf("\r\nRemoving remote context : %s \r\n" , fw_name1);
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n");  
+
+        /* Send termination message to remote */
+               rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
+
+        /* Wait for channel deletion callback. */
+        NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+
+        remoteproc_shutdown(proc);
+        
+        remoteproc_deinit(proc);
+
+    }
+    else
+    {
+        printf("\r\n\nLoading remote context: %s failed \r\n" , fw_name1);
+    }       
+
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n"); 
+    printf("\r\nLoading remote context : %s \r\n" , fw_name2);
+       printf("\r\n******************************************");
+       printf("*************************************\n\r\n"); 
+        
+    status = remoteproc_init((void *) fw_name2, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
+    
+    if(!status && (proc))
+    {
+               printf("\r\n\n********************************************\r\n");
+        printf("BOOTING BAREMETAL REMOTE FIRMWARE");
+           printf("\r\n********************************************\r\n\n");
+        status = remoteproc_boot(proc);
+    }
+    
+    if(!status) 
+    {
+        NU_Obtain_Semaphore(&App_Sem, NU_SUSPEND);
+
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n"); 
+        printf("\r\nStarting echo test on : %s \r\n" , fw_name2);
+               printf("\r\n******************************************");
+               printf("*************************************\n\r\n"); 
+        
+        for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
+        {     
+            NU_Allocate_Memory(sys_pool_ptr, (VOID **)&p_payload, (2 * sizeof(unsigned long) + size), NU_NO_SUSPEND);
+                                 
+            p_payload->num = i;
+            
+            p_payload->size = size;
+            
+            /* Setup the buffer with a pattern*/    
+            memset(&(p_payload->data[0]), 0xA5, size);  
+         
+            printf("\r\nSending data packet of size: %d to remote firmware : %s \r\n" , size, fw_name2);
+                    
+            /* Send data to remote side. */
+            rpmsg_send(app_rp_chnl, p_payload, (2 * sizeof(unsigned long)) + size);
+            
+            /* Wait for echo. */
+            NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+            
+            /* Validate packet number*/
+            if(p_payload->num != r_payload->num)
+            {
+                printf("\r\nError Echo packet number does not match with transmitted packet number %d \r\n", (int)p_payload->num);
+            }
+                
+            /* Validate the data integrity. */
+            for(idx = 0; idx < size; idx++)
+            {
+                if(p_payload->data[idx] != r_payload->data[idx])
+                {
+                    printf("\r\nError receiving data packet of size: %d at data index %d \r\n", size, idx);
+                    break;
+                }
+            }
+            
+            if(idx == size)
+            {
+                printf("\r\nReceived data packet of size: %d from remote successfully \r\n", size);
+            }
+            
+            NU_Deallocate_Memory(p_payload);
+        }
+        
+        printf("\r\nRemoving remote context : %s \r\n" , fw_name2);
+        
+        remoteproc_shutdown(proc);
+        
+        remoteproc_deinit(proc);
+    }
+    else
+    {
+        printf("\r\n\nLoading remote context: %s failed \r\n" , fw_name2);
+    }
+      
+    printf("\r\nTest Completed \r\n");
+}
+
+/* This callback gets invoked when the remote chanl is created */
+void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
+
+    app_rp_chnl = rp_chnl;
+    
+    rp_ept = rpmsg_create_ept(rp_chnl , rpmsg_read_cb ,RPMSG_NULL , RPMSG_ADDR_ANY);
+    
+    NU_Release_Semaphore(&App_Sem);
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
+    
+    rpmsg_destroy_ept(rp_ept);
+    NU_Release_Semaphore(&App_Sem);
+
+}
+
+/* This is the read callback, note we are in a task context when this callback
+is invoked, so kernel primitives can be used freely */
+void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
+                void * priv, unsigned long src) {
+
+    memcpy(r_payload,data,len);
+    
+    NU_Release_Semaphore(&App_Sem);
+}
+
diff --git a/apps/tests/master/nucleus/echo_test/nucleus_nucleusbm/make b/apps/tests/master/nucleus/echo_test/nucleus_nucleusbm/make
new file mode 100644 (file)
index 0000000..ba76afc
--- /dev/null
@@ -0,0 +1,51 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := tests/master/nucleus/echo_test/nucleus_nucleusbm/echo_test.out
+SAMPLE_C_SRC := tests/master/nucleus/echo_test/nucleus_nucleusbm/echo_test.c
+REMOTE_OUT   := echo_test.out
+DST_DIR := tests/master/nucleus/echo_test/nucleus_nucleusbm
+NU_SRC_DIR := firmware/$(PLAT)/nucleus/echo_test
+BM_SRC_DIR := firmware/$(PLAT)/baremetal/echo_test
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_C_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_C_SRC))
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(REMOTE_OUT)$(SAMPLEOBJFILES)
+
+       @echo 'Building echo_test test for nucleus : $@'
+
+       $(LD)  -Wl,-Map=tests/master/nucleus/echo_test/nucleus_nucleusbm/echo_test.map  -nostartfiles -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=free -T"$(OHOME)/libs/system/$(PLAT)/nucleus/linker_master.ld" -L"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/master" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lnucleus_master -lopen_amp -lc -lm -lstdc++ -Wl,--end-group      
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+               
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+       
+%.o:%.S
+       @$(AS) -c $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@
+
+$(REMOTE_OUT):
+       cd $(NU_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(NU_SRC_DIR)/firmware1.o $(DST_DIR)/
+       cd $(BM_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(BM_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(NU_SRC_DIR)/; rm firmware1
+       cd $(BM_SRC_DIR)/; rm firmware2
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(SAMPLE_BIN) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o $(SAMPLE_MAP)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/tests/master/nucleus/func_test_suite/nucleus_linux/func_test_suite.c b/apps/tests/master/nucleus/func_test_suite/nucleus_linux/func_test_suite.c
new file mode 100644 (file)
index 0000000..4fc6f47
--- /dev/null
@@ -0,0 +1,644 @@
+/* Including required headers */
+#include  <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "open_amp.h"
+#include "test_suite.h"
+#include "nucleus.h"
+#include "kernel/nu_kernel.h"
+
+
+/* Prototypes */
+static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+
+int test_rpmsg_send(struct rpmsg_channel *rpmsg_chnl);
+int test_rpmsg_send_offchannel(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
+
+int test_rpmsg_create_ept(struct rpmsg_channel *rpmsg_chnl);
+
+int test_remoteproc_multiple_lifecycles(char * firmware_name);
+
+int test_rpmsg_send_offchannel_impl(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
+
+int test_rpmsg_send_impl(struct rpmsg_channel *rpmsg_chnl);
+
+int test_rpmsg_remote_channel_deletion(struct rpmsg_channel *rpmsg_chnl, char *channel_name);
+
+int test_execute_suite(char * firmware_name);
+
+
+/* Globals */
+NU_TASK Task_Control_Block;
+NU_SEMAPHORE App_Sem, Remote_Del_Sem;
+struct rpmsg_endpoint *rp_ept1 , *rp_ept2;
+struct rpmsg_channel *app_rp_chnl;
+char fw_name1[] = "firmware1";
+
+struct _payload* p_payload = NULL;
+struct _payload* r_payload = NULL;
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Application_Initialize
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Demo application entry point
+ *
+ * ***********************************************************************/
+VOID Application_Initialize(
+                NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
+{
+    VOID *pointer;
+    STATUS status = NU_SUCCESS;
+
+    /* Reference unused parameters to avoid toolset warnings */
+    NU_UNUSED_PARAM( uncached_mem_pool );
+
+    if ( status == NU_SUCCESS )
+    {
+        status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
+
+        /* Create the main task for matrix processing */
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
+                            uncached_mem_pool , pointer , STACK_SIZE , TASK_PRIORITY , TASK_SLICE ,
+                            NU_PREEMPT , NU_START );
+        }
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Semaphore( &App_Sem , "APP_SEM" , 0 , NU_FIFO );
+        }
+
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Semaphore( &Remote_Del_Sem , "Del_SEM" , 0 , NU_FIFO );
+        }
+
+        NU_Allocate_Memory(uncached_mem_pool , (VOID **)&r_payload, 512 , NU_SUSPEND);
+    }
+
+    /* Check to see if previous operations were successful */
+    if ( status != NU_SUCCESS )
+    {
+        /* Loop forever */
+        while ( 1 );
+    }
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Main_Task_Entry
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Entry function for the main task. This task prints a hello world
+ * *       message.
+ * *
+ * ***********************************************************************/
+static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv )
+{
+    printf("\n\n\r************************************");
+    printf("*******************************************\r\n");
+    printf("\r\n              OpenAMP Test Suite \r\n");
+    printf("\r\n");
+    printf("\r\nThis test suite will execute multiple test cases for rpmsg and rempteproc \r\n");
+    printf("\r\nAPIs available within OpenAMP \r\n");
+
+    printf("\r\n******************************************");
+    printf("*************************************\n\r\n");
+
+    test_execute_suite(fw_name1);
+}
+
+/* This callback gets invoked when the remote chanl is created */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl )
+{
+    app_rp_chnl = rp_chnl;
+
+    rp_ept1 = rpmsg_create_ept(rp_chnl , rpmsg_read_ept1_cb , RPMSG_NULL , RPMSG_ADDR_ANY);
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl )
+{
+    rpmsg_destroy_ept( rp_ept1 );
+
+    NU_Release_Semaphore( &Remote_Del_Sem );
+
+}
+
+/* This is the read callback, note we are in a task context when this callback
+ is invoked, so kernel primitives can be used freely */
+void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    NU_Release_Semaphore( &App_Sem );
+}
+
+void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    NU_Release_Semaphore( &App_Sem );
+}
+
+void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    NU_Release_Semaphore( &App_Sem );
+}
+
+void send_test_case_report(char *result_string)
+{
+    struct command* cmd;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+    int status;
+
+    NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
+    
+    status = NU_Allocate_Memory(sys_pool_ptr , (void **)&(cmd), sizeof(struct command) + strlen(result_string) + 1, NU_SUSPEND);
+    
+    if(status == NU_SUCCESS)
+    {
+        cmd->comm_start=CMD_START;
+        cmd->comm_code = PRINT_RESULT;
+        
+        strcpy(cmd->data, result_string);
+            
+        status = rpmsg_send(app_rp_chnl, cmd, sizeof(struct command) + strlen(result_string) + 1);
+        
+        NU_Deallocate_Memory(cmd);
+        
+        /* Wait to receive echo*/
+        NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
+    }
+}
+
+int test_execute_suite(char * firmware_name)
+{
+    struct remote_proc *proc;
+    int status;
+    char default_channel[] = "rpmsg-openamp-demo-channel";
+    struct command* cmd;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+
+    printf("\n\n\r************************************");
+    printf("*******************************************\r\n");
+    printf( "\r\nBoot remote context : %s \r\n" , firmware_name );
+    printf("\r\n******************************************");
+    printf("*************************************\n\r\n");
+
+    status = remoteproc_init( (void *) firmware_name ,rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);
+
+    if (status)
+    {
+        printf( "\r\n CRITICAL ERROR: remoteproc_init call for remote context %s failed \r\n", firmware_name);
+
+        return -1;
+    }
+
+    status = remoteproc_boot( proc );
+
+    if (status)
+    {
+        printf( "\r\n CRITICAL ERROR: remoteproc_boot call for remote context %s failed \r\n", firmware_name);
+
+        return -1;
+    }
+
+    /* Wait for channel creation event */
+    NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
+    
+    /* Obtain remote firmware name */
+    NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
+    status = NU_Allocate_Memory(sys_pool_ptr , (void **)&(cmd), sizeof(struct command), NU_SUSPEND);
+    cmd->comm_start=CMD_START;
+    cmd->comm_code = QUERY_FW_NAME;
+    status = rpmsg_send(app_rp_chnl, cmd, sizeof(struct command));
+    NU_Deallocate_Memory(cmd);
+    
+    /* Wait to receive firmware name */
+    NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
+    
+    /* Test rpmsg_send API */
+    status = test_rpmsg_send(app_rp_chnl);
+
+    if(!status)
+    {
+        send_test_case_report("\r\nRPMSG Send Test: Passed\r\n");
+    }
+    else
+    {
+        send_test_case_report("\r\nRPMSG Send Test: Failed\r\n");
+    }
+
+    /* Test rpmsg_send_offchannel API. */
+    status = test_rpmsg_send_offchannel(app_rp_chnl, rp_ept1->addr, app_rp_chnl->dst);
+
+    if(!status)
+    {
+        send_test_case_report("\r\nRPMSG Send Offchannel Test: Passed\r\n");
+    }
+    else
+    {
+        send_test_case_report("\r\nRPMSG Send Offchannel: Failed\r\n");
+    }
+
+    status = test_rpmsg_create_ept(app_rp_chnl);
+
+    if(!status)
+    {
+        send_test_case_report("\r\nRPMSG Create EPT Test: Passed\r\n");
+    }
+    else
+    {
+        send_test_case_report("\r\nRPMSG Create EPT Test: Failed\r\n");
+    }
+    
+    send_test_case_report("\r\nChannel Deletion. Shutdown would be next\r\n");
+    
+    status = test_rpmsg_remote_channel_deletion(app_rp_chnl, default_channel);
+
+    NU_Sleep(100 * 18);
+    
+    status = remoteproc_shutdown(proc);
+    if(!status)
+    {
+        status = remoteproc_deinit(proc);
+    }
+
+    /* The multiple life-cycles test has been disabled for remote Linux configuration
+       as it would require manual user input at linux console to complete 
+       the rpmsg connection and would be cumbersome for the user. The multiple
+       lifecycles have been tested seperately. */
+    
+    
+    /*if(!status)
+    {
+        status = test_remoteproc_multiple_lifecycles(firmware_name);
+    }*/
+
+    return status;
+}
+
+int test_remoteproc_multiple_lifecycles(char * firmware_name)
+{
+    int i, status;
+    struct remote_proc *proc;
+
+    for(i = 0; i < 2; i++)
+    {
+        status = remoteproc_init( (void *) firmware_name ,rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);
+
+        if (status)
+        {
+            break;
+        }
+        
+        status = remoteproc_boot( proc );
+
+        if (status)
+        {
+            break;
+        }
+
+        /* Wait for channel creation event */
+        status = NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
+
+        if (!status)
+        {
+            status = test_rpmsg_send_impl(app_rp_chnl);
+        }
+
+        if(!status){
+            test_rpmsg_remote_channel_deletion(app_rp_chnl , app_rp_chnl->name);
+        }
+        
+        NU_Sleep(100 * 18);
+            
+        if (!status)
+        {
+            status = remoteproc_shutdown(proc);
+        }
+        if (status)
+        {
+            break;
+        }
+        status = remoteproc_deinit(proc);
+
+        if (status)
+        {
+            break;
+        }
+
+    }
+
+    return status;
+}
+
+int test_rpmsg_remote_channel_deletion(struct rpmsg_channel *rpmsg_chnl, char *channel_name)
+{
+    struct command *cmd;
+    int status;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+    struct chnl_cmd_data *chnl_data;
+
+    NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
+
+    status = NU_Allocate_Memory(sys_pool_ptr ,
+                                (void **)&(cmd), sizeof(struct command)+ sizeof(struct chnl_cmd_data), NU_SUSPEND);
+
+    cmd->comm_code = DELETE_CHNL;
+    cmd->comm_start = CMD_START;
+
+    chnl_data = (struct chnl_cmd_data *)cmd->data;
+
+    strncpy(chnl_data->name , channel_name, sizeof(struct chnl_cmd_data));
+
+    /* Let the other side that uninit its resources */
+    status = rpmsg_send( rpmsg_chnl , cmd , sizeof(struct command) + sizeof(struct chnl_cmd_data) );
+    if(status)
+    {
+        return status;
+    }
+    /* Wait for echo back */
+    status = NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND);
+
+    return status;
+}
+
+int test_rpmsg_create_ept(struct rpmsg_channel *rpmsg_chnl)
+{
+    struct command *cmd;
+    int status, i;
+    struct ept_cmd_data *ept_data;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+    struct rpmsg_endpoint *test_ept[NUM_TEST_EPS];
+
+    NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
+
+    status = NU_Allocate_Memory(sys_pool_ptr ,
+                                (void **)&(cmd), sizeof(struct command) + sizeof(struct ept_cmd_data), NU_SUSPEND);
+
+    if(status != NU_SUCCESS)
+    {
+        return status;
+    }
+
+    for(i = 0; i < NUM_TEST_EPS; i++)
+    {
+        /* Tell the remote to create a new endpoint. */
+        cmd->comm_code = CREATE_EPT;
+        cmd->comm_start = CMD_START;
+
+        /* Send create endpoint command to remote */
+        ept_data = (struct ept_cmd_data *)cmd->data;
+        ept_data->dst= EPT_TEST_ADDR + i;
+        ept_data->src= EPT_TEST_ADDR + i;
+
+        /* Let the other side know that it needs to create endpoint with the given address */
+        status = rpmsg_send(rpmsg_chnl, cmd, sizeof(struct command) + sizeof(struct ept_cmd_data));
+
+        if(!status)
+        {
+            /* Wait for ack */
+            status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+        }
+
+        if(!status)
+        {
+            test_ept[i] = rpmsg_create_ept(rpmsg_chnl , rpmsg_read_ept2_cb , RPMSG_NULL , EPT_TEST_ADDR + i);
+
+            if ( !test_ept[i] )
+            {
+                status = -1;
+            }
+
+        }
+        if(!status)
+        {
+            status = test_rpmsg_send_offchannel_impl(rpmsg_chnl, test_ept[i]->addr, test_ept[i]->addr);
+        }
+
+        if(!status)
+        {
+            /* Tell the remote to delete the endpoint. */
+            cmd->comm_code = DELETE_EPT;
+            cmd->comm_start = CMD_START;
+            /* Send delete endpoint command to remote */
+            ept_data = (struct ept_cmd_data *)cmd->data;
+            ept_data->dst= EPT_TEST_ADDR + i;
+            ept_data->src= EPT_TEST_ADDR + i;
+
+            /* Let the other side know that it needs to delete endpoint with the given address */
+            status = rpmsg_send(rpmsg_chnl, cmd, sizeof(struct command) + sizeof(struct ept_cmd_data));
+        }
+
+        if(!status)
+        {
+            /* Wait for ack */
+            status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+        }
+
+        if(!status)
+        {
+            rpmsg_destroy_ept(test_ept[i]);
+        }
+    }
+
+    NU_Deallocate_Memory(cmd);
+    if(status)
+    {
+        return -1;
+    }
+
+    return status;
+}
+
+int test_rpmsg_send_impl(struct rpmsg_channel *rpmsg_chnl)
+{
+    struct command cmd;
+    int status;
+    int i, size, idx;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+
+    NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
+    /* Tell the remote to be prepared for echo payloads. */
+    cmd.comm_start = CMD_START;
+    cmd.comm_code = START_ECHO;
+
+    status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+
+    if(!status)
+    {
+        /* Wait for cmd ack. */
+        status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+        if(status)
+        {
+            return -1;
+        }
+        for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
+        {
+            NU_Allocate_Memory(sys_pool_ptr , (void**)&p_payload, sizeof(struct _payload) + size , NU_SUSPEND );
+
+            p_payload->num = i;
+            p_payload->size = size;
+
+            /* Setup the buffer with a pattern*/
+            memset(p_payload->data, 0xA5, size);
+
+            /* Send data to remote side. */
+            status = rpmsg_send(rpmsg_chnl, p_payload, sizeof(struct _payload) + size);
+
+            if(status != 0)
+            {
+                break;
+            }
+
+            /* Wait for echo. */
+            status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+
+            /* Validate the data integrity. */
+            for(idx = 0; idx < r_payload->size; idx++)
+            {
+                if(p_payload->data[idx] != r_payload->data[idx])
+                {
+                    status = -1;
+                    break;
+                }
+            }
+
+            if(status != 0)
+            {
+                break;
+            }
+
+            NU_Deallocate_Memory(p_payload);
+
+        }
+        if(status)
+        {
+            return -1;
+        }
+        cmd.comm_start = CMD_START;
+        cmd.comm_code = STOP_ECHO;
+
+        status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+        if(status)
+        if(status)
+        {
+            return -1;
+        }
+
+        /* Wait for echo. */
+        status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+        
+        if(status)
+        {
+            return -1;
+        }
+     }
+
+    return status;
+}
+int test_rpmsg_send(struct rpmsg_channel *rpmsg_chnl)
+{
+    return test_rpmsg_send_impl(rpmsg_chnl);
+}
+
+int test_rpmsg_send_offchannel_impl(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst)
+{
+    struct command cmd;
+    int status;
+    int i, size, idx;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+    NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
+
+    /* Tell the remote to be prepared for echo payloads. */
+    cmd.comm_code = START_ECHO;
+    cmd.comm_start = CMD_START;
+    status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+
+    if(!status)
+    {
+        /* Wait for cmd ack. */
+        status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+        if(status)
+        {
+            return -1;
+        }
+
+        for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
+        {
+            NU_Allocate_Memory(sys_pool_ptr , (void**)&p_payload, sizeof(struct _payload) + size , NU_SUSPEND );
+            p_payload->num = i;
+            p_payload->size = size;
+
+            /* Setup the buffer with a pattern*/
+            memset(p_payload->data, 0xA5, size);
+
+            /* Send data to remote side. */
+            status = rpmsg_send_offchannel(app_rp_chnl, src, dst, p_payload ,
+                                             sizeof(struct _payload) + size);
+
+            if(status)
+            {
+                break;
+            }
+
+            /* Wait for echo. */
+            status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+
+            /* Validate the data integrity. */
+            for(idx = 0; idx < r_payload->size; idx++)
+            {
+                if(p_payload->data[idx] != r_payload->data[idx])
+                {
+                    status = -1;
+                    break;
+                }
+            }
+
+            if(status)
+            {
+                break;
+            }
+
+            NU_Deallocate_Memory(p_payload);
+        }
+        cmd.comm_start = CMD_START;
+        cmd.comm_code = STOP_ECHO;
+
+        status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
+        /* Wait for cmd ack. */
+        status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
+        if(status)
+        {
+            return -1;
+        }
+     }
+
+     return status;
+}
+
+int test_rpmsg_send_offchannel(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst)
+{
+    return test_rpmsg_send_offchannel_impl(rpmsg_chnl, src, dst);
+}
diff --git a/apps/tests/master/nucleus/func_test_suite/nucleus_linux/make b/apps/tests/master/nucleus/func_test_suite/nucleus_linux/make
new file mode 100644 (file)
index 0000000..7889e4d
--- /dev/null
@@ -0,0 +1,49 @@
+
+include ../Makefile.commons
+
+SAMPLE_OUT := tests/master/nucleus/func_test_suite/nucleus_linux/func_test_suite.out
+SAMPLE_C_SRC := tests/master/nucleus/func_test_suite/nucleus_linux/func_test_suite.c
+REMOTE_OUT   := func_test_suite.out
+DST_DIR := tests/master/nucleus/func_test_suite/nucleus_linux
+LINUX_SRC_DIR := firmware/$(PLAT)/linux
+
+SAMPLEOBJFILES := $(patsubst %.c, %.o, $(SAMPLE_C_SRC))
+SAMPLE_DEPS := $(patsubst %.c, %.d, $(SAMPLE_C_SRC))
+SAMPLE_MAP := $(patsubst %.out, %.map, $(SAMPLE_OUT))
+SAMPLE_BIN := $(patsubst %.out, %.bin, $(SAMPLE_OUT))
+
+$(SAMPLE_OUT): $(REMOTE_OUT)$(SAMPLEOBJFILES)
+
+       @echo 'Building func_test_suite test for nucleus : $@'
+
+       $(LD)  -Wl,-Map=tests/master/nucleus/func_test_suite/nucleus_linux/func_test_suite.map  -nostartfiles -Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=free -T"$(OHOME)/libs/system/$(PLAT)/nucleus/linker_master.ld" -L"$(OHOME)/libs/system/$(PLAT)/nucleus/lib/$(CROSS)/master" -L"$(OHOME)/libs/open_amp" -o "$(SAMPLE_OUT)" -Wl,--start-group $(SAMPLEOBJFILES) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o -lnucleus_master -lopen_amp -lc -lm -lstdc++ -Wl,--end-group      
+       
+       $(OBJCPY) -O binary $(SAMPLE_OUT) $(SAMPLE_BIN)
+               
+       @echo 'Finished building target: $@'
+       
+%.o:%.c
+       @echo CC $(<:.c=.o)
+       @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+       
+%.o:%.S
+       @$(AS) -c -mcpu=cortex-a9 $(ARCH_ASFLAGS) $(INCLUDE) $< -o $@
+
+$(REMOTE_OUT):
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware1; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware1 firmware1.o
+       mv $(LINUX_SRC_DIR)/firmware1.o $(DST_DIR)/firmware1.o
+       cd $(LINUX_SRC_DIR)/; cp firmware firmware2; \
+       $(OBJCPY) -I binary -O elf32-littlearm -B arm firmware2 firmware2.o
+       mv $(LINUX_SRC_DIR)/firmware2.o $(DST_DIR)/
+       cd $(LINUX_SRC_DIR)/; rm firmware1; rm firmware2;
+clean:
+       -$(RM) $(SAMPLEOBJFILES) $(SAMPLE_DEPS) $(SAMPLE_OUT) $(DST_DIR)/firmware1.o $(DST_DIR)/firmware2.o $(SAMPLE_MAP) $(SAMPLE_BIN)
+       
+post-build:
+       -@echo ' '
+
+secondary-outputs:
+
+PHONY: all clean dependents
+.SECONDARY: post-build
diff --git a/apps/tests/master/nucleus/func_test_suite/nucleus_linux/test_suite.h b/apps/tests/master/nucleus/func_test_suite/nucleus_linux/test_suite.h
new file mode 100644 (file)
index 0000000..4a0ca99
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * m_ept_func_test.h
+ *
+ *  Created on: Mar 14, 2014
+ *      Author: etsam
+ */
+
+#ifndef M_EPT_FUNC_TEST_H_
+#define M_EPT_FUNC_TEST_H_
+
+struct command
+{
+    unsigned int comm_start;
+    unsigned int comm_code;
+    char data[0];
+}__attribute__((__packed__));
+
+struct ept_cmd_data
+{
+    unsigned int src;
+    unsigned int dst;
+};
+
+struct chnl_cmd_data
+{
+    char name[32];
+};
+
+/* Command Codes */
+
+#define CREATE_EPT      0x00000000
+#define DELETE_EPT      0x00000001
+#define CREATE_CHNL     0x00000002
+#define DELETE_CHNL     0x00000003
+#define START_ECHO      0x00000004
+#define STOP_ECHO       0x00000005
+#define QUERY_FW_NAME   0x00000006
+#define PRINT_RESULT    0x00000007
+
+#define CMD_START       0xEF56A55A
+
+/* Define the main task's stack size */
+#define STACK_SIZE      (NU_MIN_STACK_SIZE * 400)
+
+/* Define the main task's priority */
+#define TASK_PRIORITY   26
+
+/* Define the main task's time slice */
+#define TASK_SLICE      20
+
+#define EPT_TEST_ADDR      59
+
+#define NUM_TEST_EPS       4
+
+#define MAX_RPMSG_BUFF_SIZE 512
+#define PAYLOAD_MIN_SIZE    1    
+#define PAYLOAD_MAX_SIZE    (MAX_RPMSG_BUFF_SIZE - 24)
+#define NUM_PAYLOADS        (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
+
+struct _payload {
+    unsigned long    num;
+    unsigned long    size;
+    char             data[0];
+}__attribute__((__packed__));
+
+
+#endif /* M_EPT_FUNC_TEST_H_ */
diff --git a/apps/tests/master/nucleus/func_test_suite/nucleus_nucleusbm/func_test_suite.c b/apps/tests/master/nucleus/func_test_suite/nucleus_nucleusbm/func_test_suite.c
new file mode 100644 (file)
index 0000000..33fa4b4
--- /dev/null
@@ -0,0 +1,700 @@
+/* This is a test demonstration application that tests usage of remoteproc
+and rpmsg APIs. This application is meant to run on the master CPU running Nucleus
+and showcases booting of two sub-sequent remote firmware cycles using remoteproc and 
+IPC with remote firmware using rpmsg; 1. It brings up a remote Nucleus based remote 
+firmware which can respond to test calls, 2. It brings up a baremetal based 
+remote firmware which can respond to test calls. Master app executes tests to validate
+the rpmsg APIs and shutsdown the core once the test has been completed.*/
+
+/* Including required headers */
+
+#include  <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "open_amp.h"
+#include "test_suite.h"
+#include "nucleus.h"
+#include "kernel/nu_kernel.h"
+
+
+/* Prototypes */
+static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
+
+/* Application provided callbacks */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
+void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
+                unsigned long src );
+
+int test_rpmsg_send(struct rpmsg_channel *rpmsg_chnl);
+int test_rpmsg_send_offchannel(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
+
+int test_rpmsg_create_ept(struct rpmsg_channel *rpmsg_chnl);
+
+int test_remoteproc_multiple_lifecycles(char * firmware_name);
+
+int test_rpmsg_send_offchannel_impl(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
+
+int test_rpmsg_send_impl(struct rpmsg_channel *rpmsg_chnl);
+
+int test_rpmsg_remote_channel_deletion(struct rpmsg_channel *rpmsg_chnl, char *channel_name);
+
+int test_execute_suite(char * firmware_name);
+
+
+/* Globals */
+NU_TASK Task_Control_Block;
+NU_SEMAPHORE App_Sem, Remote_Del_Sem;
+struct rpmsg_endpoint *rp_ept1 , *rp_ept2;
+struct rpmsg_channel *app_rp_chnl;
+char fw_name1[] = "firmware1";
+char fw_name2[] = "firmware2";
+
+struct _payload* p_payload = NULL;
+struct _payload* r_payload = NULL;
+static const char display_string[] = ".";
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Application_Initialize
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Demo application entry point
+ *
+ * ***********************************************************************/
+VOID Application_Initialize(
+                NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
+{
+    VOID *pointer;
+    STATUS status = NU_SUCCESS;
+
+    /* Reference unused parameters to avoid toolset warnings */
+    NU_UNUSED_PARAM( uncached_mem_pool );
+
+    if ( status == NU_SUCCESS )
+    {
+        status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
+
+        /* Create the main task for matrix processing */
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
+                            uncached_mem_pool , pointer , STACK_SIZE , TASK_PRIORITY , TASK_SLICE ,
+                            NU_PREEMPT , NU_START );
+        }
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Semaphore( &App_Sem , "APP_SEM" , 0 , NU_FIFO );
+        }
+
+        if ( status == NU_SUCCESS )
+        {
+            status = NU_Create_Semaphore( &Remote_Del_Sem , "Del_SEM" , 0 , NU_FIFO );
+        }
+
+        NU_Allocate_Memory(uncached_mem_pool , (VOID **)&r_payload, 512 , NU_SUSPEND);
+    }
+
+    /* Check to see if previous operations were successful */
+    if ( status != NU_SUCCESS )
+    {
+        /* Loop forever */
+        while ( 1 );
+    }
+}
+
+/***********************************************************************
+ * *
+ * *   FUNCTION
+ * *
+ * *       Main_Task_Entry
+ * *
+ * *   DESCRIPTION
+ * *
+ * *       Entry function for the main task. This task prints a hello world
+ * *       message.
+ * *
+ * ***********************************************************************/
+static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv )
+{
+    printf("\n\n\r************************************");
+    printf("*******************************************\r\n");
+    printf("\r\n              OpenAMP Test Suite \r\n");
+    printf("\r\n");
+    printf("\r\nThis test suite will execute multiple test cases for rpmsg and rempteproc \r\n");
+    printf("\r\nAPIs available within OpenAMP \r\n");
+
+    printf("\r\n******************************************");
+    printf("*************************************\n\r\n");
+
+    test_execute_suite(fw_name1);
+
+    test_execute_suite(fw_name2);
+
+
+}
+
+/* This callback gets invoked when the remote chanl is created */
+void rpmsg_channel_created( struct rpmsg_channel *rp_chnl )
+{
+    app_rp_chnl = rp_chnl;
+
+    rp_ept1 = rpmsg_create_ept(rp_chnl , rpmsg_read_ept1_cb , RPMSG_NULL , RPMSG_ADDR_ANY);
+
+    NU_Release_Semaphore( &App_Sem );
+}
+
+/* This callback gets invoked when the remote channel is deleted */
+void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl )
+{
+    rpmsg_destroy_ept( rp_ept1 );
+
+    NU_Release_Semaphore( &Remote_Del_Sem );
+
+}
+
+/* This is the read callback, note we are in a task context when this callback
+ is invoked, so kernel primitives can be used freely */
+void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    NU_Release_Semaphore( &App_Sem );
+}
+
+void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    NU_Release_Semaphore( &App_Sem );
+}
+
+void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
+                unsigned long src )
+{
+    memcpy( r_payload , data , len );
+    NU_Release_Semaphore( &App_Sem );
+}
+
+
+int test_execute_suite(char * firmware_name)
+{
+    struct remote_proc *proc;
+    int status;
+    char default_channel[] = "rpmsg-openamp-demo-channel";
+    struct command* cmd;
+    NU_MEMORY_POOL     *sys_pool_ptr;
+
+    printf("\n\n\r************************************");
+    printf("*******************************************\r\n");
+    printf( "\r\nBoot remote context : %s \r\n" , firmware_name );
+    printf("\r\n******************************************");
+    printf("*************************************\n\r\n");
+
+    status = remoteproc_init( (void *) firmware_name ,rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);
+
+    if (status)
+    {
+        printf( "\r\n CRITICAL ERROR: remoteproc_init call for remote context %s failed \r\n", firmware_name);
+
+        return -1;
+    }
+
+    status = remoteproc_boot( proc );
+
+    if (status)
+    {
+        printf( "\r\n CRITICAL ERROR: remoteproc_boot call for remote context %s failed \r\n", firmware_name);
+
+        return -1;
+    }
+
+    /* Wait for channel creation event */
+    NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
+       
+    /* Obtain remote firmware name */
+    NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
+    status = NU_Allocate_Memory(sys_pool_ptr , (void **)&(cmd), sizeof(struct command), NU_SUSPEND);
+    cmd->comm_start=CMD_START;
+    cmd->comm_code = QUERY_FW_NAME;
+    status = rpmsg_send(app_rp_chnl, cmd, sizeof(struct command));
+    NU_Deallocate_Memory(cmd);
+       
+    /* Wait to receive firmware name */
+    NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
+       
+    printf("\r\nREMOTE FIRMWARE NAME : %s \r\n", (char*)r_payload);
+
+    /* Test rpmsg_send API */
+    status = test_rpmsg_send(app_rp_chnl);
+
+    if(!status)
+    {
+        printf( "\r\nRESULT:   PASSED \r\n" );
+    }
+    else
+    {
+        printf( "\r\nRESULT:   FAILED \r\n" );
+    }
+
+    /* Test rpmsg_send_offchannel API. */
+    status = test_rpmsg_send_offchannel(app_rp_chnl, rp_ept1->addr, app_rp_chnl->dst);
+
+    if(!status)
+    {
+        printf( "\r\nRESULT:   PASSED \r\n" );
+    }
+    else
+    {
+        printf( "\r\nRESULT:   FAILED \r\n" );
+    }
+
+    status = test_rpmsg_create_ept(app_rp_chnl);
+
+    if(!status)
+    {
+        printf( "\r\nRESULT:   PASSED \r\n" );
+    }
+    else
+    {
+        printf( "\r\nRESULT:   FAILED \r\n" );
+    }
+
+    printf("\n\n\r************************************");
+    printf("*******************************************\r\n");
+    printf(" This test case will test channel deletion \r\n");
+    printf("******************************************");
+    printf("*************************************\r\n\n");
+
+    status = test_rpmsg_remote_channel_deletion(app_rp_chnl, default_channel);
+
+    if(!status)
+    {
+        printf( "\r\nRESULT:   PASSED \r\n" );
+    }
+    else
+    {
+        printf( "\r\nRESULT:   FAILED \r\n" );
+    }
+
+    printf("\n\n\r************************************");
+    printf("*******************************************\r\n");
+    printf( "\r\n\nShutdown remote context : %s \r\n" , firmware_name );
+    printf("******************************************");
+    printf("*************************************\r\n\n");
+
+    status = remoteproc_shutdown(proc);
+    if(!status)
+    {
+