Add example for out of band rpmsg demo atop RPMsg. This demo shows a
simple proof concept for an echo-test like application. 
Instead of the default rpmsg echo-test demo, this application shows
uses a  structure within the payload that denotes whether a 
rpmsg packet holds data or a pointer.
Signed-off-by: Ben Levinsky <
ben.le...@xilinx.com>
---
 apps/examples/CMakeLists.txt            |   1 +
 apps/examples/oob_echo/CMakeLists.txt   |  47 +++++++
 apps/examples/oob_echo/rpmsg-echo.h     |   6 +
 apps/examples/oob_echo/rpmsg-oob-echo.c | 141 ++++++++++++++++++++
 apps/examples/oob_echo/rpmsg-oob-ping.c | 223 ++++++++++++++++++++++++++++++++
 5 files changed, 418 insertions(+)
 create mode 100644 apps/examples/oob_echo/CMakeLists.txt
 create mode 100644 apps/examples/oob_echo/rpmsg-echo.h
 create mode 100644 apps/examples/oob_echo/rpmsg-oob-echo.c
 create mode 100644 apps/examples/oob_echo/rpmsg-oob-ping.c
diff --git a/apps/examples/CMakeLists.txt b/apps/examples/CMakeLists.txt
index 319f01e..f0ae8cd 100644
--- a/apps/examples/CMakeLists.txt
+++ b/apps/examples/CMakeLists.txt
@@ -2,6 +2,7 @@
 option (WITH_LOAD_FW "Include loading firmware example" OFF)
 
 add_subdirectory (echo)
+add_subdirectory (oob_echo)
 add_subdirectory (rpmsg_sample_echo)
 add_subdirectory (matrix_multiply)
 if (WITH_LOAD_FW)
diff --git a/apps/examples/oob_echo/CMakeLists.txt b/apps/examples/oob_echo/CMakeLists.txt
new file mode 100644
index 0000000..eab1dbf
--- /dev/null
+++ b/apps/examples/oob_echo/CMakeLists.txt
@@ -0,0 +1,47 @@
+
+set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS} -fdata-sections -ffunction-sections")
+set (_fw_dir "${APPS_SHARE_DIR}")
+
+collector_list (_list PROJECT_INC_DIRS)
+collector_list (_app_list APP_INC_DIRS)
+include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR})
+
+collector_list (_list PROJECT_LIB_DIRS)
+collector_list (_app_list APP_LIB_DIRS)
+link_directories (${_list} ${_app_list})
+
+get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT)
+collector_list (_deps PROJECT_LIB_DEPS)
+
+set (OPENAMP_LIB open_amp)
+
+foreach (_app rpmsg-oob-echo-ping rpmsg-oob-echo)
+  collector_list (_sources APP_COMMON_SOURCES)
+  if (${_app} STREQUAL "rpmsg-oob-echo-ping")
+    list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-oob-ping.c")
+  elseif (${_app} STREQUAL "rpmsg-oob-echo")
+    list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/rpmsg-oob-echo.c")
+  endif (${_app} STREQUAL "rpmsg-oob-echo-ping")
+
+  if (WITH_SHARED_LIB)
+    add_executable (${_app}-shared ${_sources})
+    target_link_libraries (${_app}-shared ${OPENAMP_LIB}-shared ${_deps})
+    install (TARGETS ${_app}-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+  endif (WITH_SHARED_LIB)
+
+  if (WITH_STATIC_LIB)
+    if (${PROJECT_SYSTEM} STREQUAL "linux")
+      add_executable (${_app}-static ${_sources})
+      target_link_libraries (${_app}-static ${OPENAMP_LIB}-static ${_deps})
+      install (TARGETS ${_app}-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+    else (${PROJECT_SYSTEM})
+      add_executable (${_app}.out ${_sources})
+      set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}")
+
+      target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections ${_linker_opt} -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group)
+
+      install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+    endif (${PROJECT_SYSTEM} STREQUAL "linux" )
+  endif (WITH_STATIC_LIB)
+endforeach(_app)
+
diff --git a/apps/examples/oob_echo/rpmsg-echo.h b/apps/examples/oob_echo/rpmsg-echo.h
new file mode 100644
index 0000000..d15eb56
--- /dev/null
+++ b/apps/examples/oob_echo/rpmsg-echo.h
@@ -0,0 +1,6 @@
+#ifndef RPMSG_ECHO_H
+#define RPMSG_ECHO_H
+
+#define RPMSG_SERVICE_NAME         "rpmsg-openamp-demo-channel"
+
+#endif /* RPMSG_ECHO_H */
diff --git a/apps/examples/oob_echo/rpmsg-oob-echo.c b/apps/examples/oob_echo/rpmsg-oob-echo.c
new file mode 100644
index 0000000..8c92df3
--- /dev/null
+++ b/apps/examples/oob_echo/rpmsg-oob-echo.c
@@ -0,0 +1,141 @@
+/* This is a sample demonstration application that showcases usage of rpmsg
+This application is meant to run on the remote CPU running baremetal code.
+This application echoes back data that was sent to it by the master core. */
+
+#include <stdio.h>
+#include <openamp/open_amp.h>
+#include <metal/alloc.h>
+#include "platform_info.h"
+#include "rpmsg-echo.h"
+//#include "xil_printf.h"
+
+#define OUT_OF_BAND (0x1UL<<31)
+#define INIT_MSG 0x2UL
+#define ACK_MSG 0X3UL
+#define DATA_MSG 0x4UL
+#define SHUTDOWN_MSG 0x5UL
+
+#define TABLE_BASE_ADDRESS 0x3ee20000UL
+#define BUFFER_SIZE 0x10000UL //64K.. can change to 65K as needed
+#define NUM_BUFFERS 16
+#define NUM_MESSAGES_TO_SEND 32
+
+static struct packet {
+    unsigned packet_type;
+    unsigned buffer_index;
+    unsigned packet_length;
+};
+
+static int demo_status = 0;
+
+#define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
+//#define LPRINTF(format, ...)
+#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
+
+static struct rpmsg_endpoint lept;
+static int shutdown_req = 0;
+
+/*-----------------------------------------------------------------------------*
+ *  RPMSG endpoint callbacks
+ *-----------------------------------------------------------------------------*/
+static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,
+			     uint32_t src, void *priv)
+{
+
+	struct packet * p = (struct packet *)data;
+	struct packet ack_packet;
+
+	(void)priv;
+	(void)src;
+	(void)len;
+	LPRINTF("RPU message is received.\r\n" );
+	LPRINTF("RPU message contents : packet_type %x buffer_index %x packet_length %x\r\n", 
+	p->packet_type, p->buffer_index, p->packet_length );
+
+	LPRINTF("RPU: Data location at %x \r\n", (unsigned)(TABLE_BASE_ADDRESS+ (BUFFER_SIZE * p->buffer_index)));
+	LPRINTF("RPU: contents of message %x \r\n", *(char*)((TABLE_BASE_ADDRESS+ (BUFFER_SIZE * p->buffer_index))));
+	/* notify remote that message is received */
+	ack_packet.packet_type = OUT_OF_BAND | ACK_MSG;
+	if (rpmsg_send(ept, &ack_packet, sizeof(struct packet)) < 0){
+	    LPERROR("RPU rpmsg_send failed\r\n");
+		return RPMSG_ERR_PARAM;
+	}
+
+    return RPMSG_SUCCESS;
+}
+
+static void rpmsg_service_unbind(struct rpmsg_endpoint *ept)
+{
+	(void)ept;
+	LPRINTF("RPU unexpected Remote endpoint destroy\r\n");
+	shutdown_req = 1;
+}
+
+/*-----------------------------------------------------------------------------*
+ *  Application
+ *-----------------------------------------------------------------------------*/
+int app(struct rpmsg_device *rdev, void *priv)
+{
+	int ret;
+
+	/* Initialize RPMSG framework */
+	LPRINTF("Try to create rpmsg endpoint.\r\n");
+
+	ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME,
+			       0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
+			       rpmsg_service_unbind);
+	if (ret) {
+		LPERROR("Failed to create endpoint.\r\n");
+		return -1;
+	}
+
+	LPRINTF("Successfully created rpmsg endpoint.\r\n");
+	while(1) {
+		platform_poll(priv);
+		/* err or INIT */
+		if (shutdown_req ) {
+			LPRINTF("got shutdown request \r\n");
+			break;
+		}
+	}
+	LPRINTF("destroying rpmsg endpoint \r\n");
+	rpmsg_destroy_ept(&lept);
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------------------*
+ *  Application entry point
+ *-----------------------------------------------------------------------------*/
+int main(int argc, char *argv[])
+{
+	void *platform;
+	struct rpmsg_device *rpdev;
+	int ret;
+
+	LPRINTF("Starting application...\r\n");
+
+	/* Initialize platform */
+	ret = platform_init(argc, argv, &platform);
+	if (ret) {
+		LPERROR("Failed to initialize platform.\r\n");
+		ret = -1;
+	} else {
+		rpdev = platform_create_rpmsg_vdev(platform, 0,
+						   VIRTIO_DEV_SLAVE,
+						   NULL, NULL);
+		if (!rpdev) {
+			LPERROR("Failed to create rpmsg virtio device.\r\n");
+			ret = -1;
+		} else {
+			app(rpdev, platform);
+			platform_release_rpmsg_vdev(rpdev);
+			ret = 0;
+		}
+	}
+
+	LPRINTF("Stopping application...\r\n");
+	platform_cleanup(platform);
+
+	return ret;
+}
diff --git a/apps/examples/oob_echo/rpmsg-oob-ping.c b/apps/examples/oob_echo/rpmsg-oob-ping.c
new file mode 100644
index 0000000..8dc6a3b
--- /dev/null
+++ b/apps/examples/oob_echo/rpmsg-oob-ping.c
@@ -0,0 +1,223 @@
+/* This is a sample demonstration application that showcases usage of rpmsg 
+This application is meant to run on the remote CPU running baremetal code. 
+This application echoes back data that was sent to it by the master core. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <openamp/open_amp.h>
+#include <metal/alloc.h>
+#include "platform_info.h"
+#include "rpmsg-echo.h"
+#include <metal/io.h>
+#include <metal/device.h>
+
+#define APP_EPT_ADDR    0
+#define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
+#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
+
+
+#define OUT_OF_BAND (0x1UL<<31)
+#define INIT_MSG 0x2UL
+#define ACK_MSG 0X3UL
+#define DATA_MSG 0x4UL
+#define SHUTDOWN_MSG 0x5UL
+
+#define TABLE_BASE_ADDRESS 0x3ee20000UL
+#define BUFFER_SIZE 0x10000UL //64K.. can change to 65K as needed
+#define NUM_BUFFERS 16
+#define NUM_MESSAGES_TO_SEND 32
+
+#define DEV_BUS_NAME "platform"
+
+
+static struct packet {
+    unsigned packet_type;
+    unsigned buffer_index;
+    unsigned packet_length;
+};
+
+
+static void* large_buffer;
+
+static char data_to_send[BUFFER_SIZE];
+/* Globals */
+static struct rpmsg_endpoint lept;
+static int ept_deleted = 0;
+
+static struct metal_device *large_buffer_shm_device;
+static struct metal_io_region * large_buffer_io;
+
+static int setup_buffer(struct packet * p, unsigned buffer_index, unsigned packet_length, void * data){
+	int ret;
+
+    if (buffer_index > NUM_BUFFERS || packet_length > BUFFER_SIZE || !data)
+        LPERROR("send_buffer failed\r\n");
+    p->packet_type = OUT_OF_BAND | DATA_MSG;
+    p->buffer_index = buffer_index;
+    p->packet_length = packet_length;
+	ret = metal_io_block_write(large_buffer_io, (BUFFER_SIZE * buffer_index), data, packet_length);
+	if (ret < 0){
+		LPERROR("Unable to metal_io_block_write()\n");
+		return -1;
+	}
+	LPRINTF("APU copied to large buffer \r\n");
+
+    return 0;
+}
+
+
+/*-----------------------------------------------------------------------------*
+ *  RPMSG endpoint callbacks
+ *-----------------------------------------------------------------------------*/
+static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,
+			     uint32_t src, void *priv)
+{
+	(void)priv;
+    (void)src;
+    (void)len;
+	(void)ept;
+
+	struct packet * p = (struct packet *)data;
+
+    LPRINTF("APU  message is received.\r\n" );
+    LPRINTF("APU message contents : packet_type %x buffer_index %x packet_length %x\r\n", 
+        p->packet_type, p->buffer_index, p->packet_length );
+	if (p->packet_type & ACK_MSG){
+		LPRINTF("APU received ACK_MSG");
+	}
+    return RPMSG_SUCCESS;
+
+}
+
+static void rpmsg_service_unbind(struct rpmsg_endpoint *ept)
+{
+	(void)ept;
+	rpmsg_destroy_ept(&lept);
+	LPRINTF("echo test: service is destroyed\r\n");
+	ept_deleted = 1;
+}
+
+static void rpmsg_name_service_bind_cb(struct rpmsg_device *rdev,
+				       const char *name, uint32_t dest)
+{
+	LPRINTF("new endpoint notification is received.\r\n");
+	if (strcmp(name, RPMSG_SERVICE_NAME))
+		LPERROR("Unexpected name service %s.\r\n", name);
+	else
+		(void)rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME,
+				       APP_EPT_ADDR, dest,
+				       rpmsg_endpoint_cb,
+				       rpmsg_service_unbind);
+
+}
+
+/*-----------------------------------------------------------------------------*
+ *  Application
+ *-----------------------------------------------------------------------------*/
+int app (struct rpmsg_device *rdev, void *priv)
+{
+	int ret;
+	
+
+	/* Create RPMsg endpoint */
+	ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, APP_EPT_ADDR,
+			       RPMSG_ADDR_ANY,
+			       rpmsg_endpoint_cb, rpmsg_service_unbind);
+
+	if (ret) {
+		LPERROR("Failed to create RPMsg endpoint.\r\n");
+		return ret;
+	}
+	while (!is_rpmsg_ept_ready(&lept))
+		platform_poll(priv);
+	
+	struct packet * p;
+	p = (struct packet *)metal_allocate_memory(sizeof(struct packet));
+	if (!p){
+		LPERROR("memory allocation failed for packet.\r\n");
+		return -1;
+	}
+	
+	large_buffer = metal_allocate_memory(sizeof(BUFFER_SIZE*sizeof(char)));
+	if (!large_buffer){
+		LPERROR("memory allocation failed for packet.\r\n");
+		return -1;
+	}
+
+	LPRINTF("APU begin demo \r\n");
+	for(int number_messages_sent = 0; number_messages_sent < 3;  number_messages_sent++) {
+		*data_to_send = number_messages_sent;
+		LPRINTF("APU: contents of message %i \r\n", number_messages_sent);
+
+		ret = setup_buffer(p, number_messages_sent % NUM_BUFFERS, sizeof(data_to_send), data_to_send);
+		if (ret){
+			LPERROR("setup_buffer failed \r\n");
+			return RPMSG_ERR_PARAM;
+		}
+
+		if (rpmsg_send(&lept, p, sizeof(struct packet)) < 0){ 
+			LPERROR("rpmsg_send failed\r\n");
+			return RPMSG_ERR_PARAM;
+		}
+		sleep(2);
+
+	}
+	LPRINTF("APU side ending demo \r\n");
+   	metal_free_memory(p);
+
+	rpmsg_destroy_ept(&lept);
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	void *platform;
+	struct rpmsg_device *rpdev;
+	int ret;
+
+	ret = platform_init(argc, argv, &platform);
+	if (ret) {
+		LPERROR("Failed to initialize platform.\r\n");
+		ret = -1;
+	} else {
+		/* Initialize platform */
+		printf("try to open device \r\n");
+		ret = metal_device_open(DEV_BUS_NAME, "3ee20000.shm", &large_buffer_shm_device);
+		if (ret) {
+			fprintf(stderr, "ERROR: failed to open large_buffer_shm_device  device: %d.\r\n", ret);
+			return -1;
+		}
+
+		printf("able to open device. now try to get io region from device \r\n");
+		printf("large_buffer_shm_device->num_regions %u \r\n", large_buffer_shm_device->num_regions);
+		large_buffer_io = metal_device_io_region(large_buffer_shm_device, 0);
+		if (!large_buffer_io){
+			fprintf(stderr, "ERROR: failed to open large_buffer_io \r\n");
+			return -1;
+		}
+
+		printf("able to get io region from device \r\n");
+
+		rpdev = platform_create_rpmsg_vdev(platform, 0,
+						  VIRTIO_DEV_MASTER,
+						  NULL,
+						  rpmsg_name_service_bind_cb);
+		if (!rpdev) {
+			LPERROR("Failed to create rpmsg virtio device.\r\n");
+			ret = -1;
+		} else {
+			app(rpdev, platform);
+			platform_release_rpmsg_vdev(rpdev);
+			ret = 0;
+		}
+	}
+
+	LPRINTF("Stopping application...\r\n");
+	platform_cleanup(platform);
+
+	return ret;
+}
+
-- 
2.7.4