1 /* This is a sample demonstration application that showcases usage of rpmsg
2 This application is meant to run on the remote CPU running baremetal code.
3 This application echoes back data that was sent to it by the master core. */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include "openamp/open_amp.h"
10 #include "metal/alloc.h"
11 #include "rsc_table.h"
12 #include "platform_info.h"
14 #define SHUTDOWN_MSG 0xEF56A55A
15 #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
16 #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
18 struct _payload {
19 unsigned long num;
20 unsigned long size;
21 char data[];
22 };
24 static int err_cnt;
26 #define RPMSG_GET_KFIFO_SIZE 1
27 #define RPMSG_GET_AVAIL_DATA_SIZE 2
28 #define RPMSG_GET_FREE_SPACE 3
30 #define RPMSG_HEADER_LEN sizeof(struct rpmsg_hdr)
31 #define MAX_RPMSG_BUFF_SIZE (RPMSG_BUFFER_SIZE - RPMSG_HEADER_LEN)
32 #define PAYLOAD_MIN_SIZE 1
33 #define PAYLOAD_MAX_SIZE (MAX_RPMSG_BUFF_SIZE - 24)
34 #define NUM_PAYLOADS (PAYLOAD_MAX_SIZE/PAYLOAD_MIN_SIZE)
36 /* Internal functions */
37 static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl);
38 static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl);
39 static void rpmsg_read_cb(struct rpmsg_channel *, void *, int, void *,
40 unsigned long);
41 /* Globals */
42 static struct rpmsg_channel *app_rp_chnl;
43 static struct rpmsg_endpoint *rp_ept;
44 static struct remote_proc *proc = NULL;
45 static struct rsc_table_info rsc_info;
46 static struct _payload *i_payload;
47 static int rnum = 0;
48 static int err_cnt = 0;
49 extern const struct remote_resource_table resources;
50 extern struct rproc_info_plat_local proc_table;
52 /* External functions */
53 extern void init_system();
54 extern void cleanup_system();
56 /* Application entry point */
57 int main()
58 {
59 int status = 0;
60 int shutdown_msg = SHUTDOWN_MSG;
61 int i;
62 int size;
63 int expect_rnum = 0;
65 LPRINTF(" 1 - Send data to remote core, retrieve the echo");
66 LPRINTF(" and validate its integrity ..\n");
67 /* Initialize HW system components */
68 init_system();
70 rsc_info.rsc_tab = (struct resource_table *)&resources;
71 rsc_info.size = sizeof(resources);
73 i_payload =
74 (struct _payload *)metal_allocate_memory(2 * sizeof(unsigned long) +
75 PAYLOAD_MAX_SIZE);
77 if (!i_payload) {
78 LPERROR("memory allocation failed.\n");
79 return -1;
80 }
82 /* Initialize RPMSG framework */
83 status =
84 remoteproc_resource_init(&rsc_info, &proc_table,
85 rpmsg_channel_created,
86 rpmsg_channel_deleted, rpmsg_read_cb,
87 &proc, 1);
89 if (status) {
90 LPERROR("Failed to initialize remoteproc resource.\n");
91 return -1;
92 }
94 LPRINTF("Remote proc resource initialized.\n");
95 while (!app_rp_chnl) {
96 hil_poll(proc->proc, 0);
97 }
99 LPRINTF("RPMSG channel has created.\n");
100 for (i = 0, size = PAYLOAD_MIN_SIZE; i < (int)NUM_PAYLOADS; i++, size++) {
101 i_payload->num = i;
102 i_payload->size = size;
104 /* Mark the data buffer. */
105 memset(&(i_payload->data[0]), 0xA5, size);
107 LPRINTF("sending payload number %lu of size %d\n",
108 i_payload->num, (2 * sizeof(unsigned long)) + size);
110 status = rpmsg_send(app_rp_chnl, i_payload,
111 (2 * sizeof(unsigned long)) + size);
113 if (status) {
114 LPRINTF("Error sending data...\n");
115 break;
116 }
117 LPRINTF("echo test: sent : %d\n",
118 (2 * sizeof(unsigned long)) + size);
120 expect_rnum++;
121 do {
122 hil_poll(proc->proc, 0);
123 } while ((rnum < expect_rnum) && !err_cnt && app_rp_chnl);
125 }
127 LPRINTF("**********************************\n");
128 LPRINTF(" Test Results: Error count = %d \n", err_cnt);
129 LPRINTF("**********************************\n");
130 /* Send shutdown message to remote */
131 rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
132 sleep(1);
133 LPRINTF("Quitting application .. Echo test end\n");
135 remoteproc_resource_deinit(proc);
136 cleanup_system();
137 metal_free_memory(i_payload);
138 return 0;
139 }
141 static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl)
142 {
143 app_rp_chnl = rp_chnl;
144 rp_ept = rpmsg_create_ept(rp_chnl, rpmsg_read_cb, RPMSG_NULL,
145 RPMSG_ADDR_ANY);
146 }
148 static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl)
149 {
150 (void)rp_chnl;
151 rpmsg_destroy_ept(rp_ept);
152 LPRINTF("%s\n", __func__);
153 app_rp_chnl = NULL;
154 rp_ept = NULL;
155 }
157 static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
158 void *priv, unsigned long src)
159 {
160 (void)rp_chnl;
161 (void)src;
162 (void)priv;
163 int i;
164 struct _payload *r_payload = (struct _payload *)data;
166 LPRINTF(" received payload number %lu of size %d \r\n",
167 r_payload->num, len);
169 if (r_payload->size == 0) {
170 LPERROR(" Invalid size of package is received.\n");
171 err_cnt++;
172 return;
173 }
174 /* Validate data buffer integrity. */
175 for (i = 0; i < (int)r_payload->size; i++) {
176 if (r_payload->data[i] != 0xA5) {
177 LPRINTF("Data corruption at index %d \n", i);
178 err_cnt++;
179 break;
180 }
181 }
182 rnum = r_payload->num + 1;
183 }