summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3707476)
raw | patch | inline | side by side (parent: 3707476)
author | eanjum <etsam_anjum@mentor.com> | |
Fri, 10 Oct 2014 10:24:20 +0000 (15:24 +0500) | ||
committer | eanjum <etsam_anjum@mentor.com> | |
Fri, 10 Oct 2014 10:24:20 +0000 (15:24 +0500) |
218 files changed:
diff --git a/Makefile b/Makefile
--- /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
--- /dev/null
+++ b/Makefile.commons
@@ -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
--- /dev/null
+++ b/apps/Makefile
@@ -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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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)
+ {
+