203 lines
5.0 KiB
C
203 lines
5.0 KiB
C
![]() |
/* 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"
|
||
|
|
||
|
#define APP_EPT_ADDR 0
|
||
|
#define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
|
||
|
#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
|
||
|
|
||
|
struct _payload {
|
||
|
unsigned long num;
|
||
|
unsigned long size;
|
||
|
unsigned char data[];
|
||
|
};
|
||
|
|
||
|
static int err_cnt;
|
||
|
|
||
|
#define PAYLOAD_MIN_SIZE 1
|
||
|
|
||
|
/* Globals */
|
||
|
static struct rpmsg_endpoint lept;
|
||
|
static struct _payload *i_payload;
|
||
|
static int rnum = 0;
|
||
|
static int err_cnt = 0;
|
||
|
static int ept_deleted = 0;
|
||
|
|
||
|
/*-----------------------------------------------------------------------------*
|
||
|
* RPMSG endpoint callbacks
|
||
|
*-----------------------------------------------------------------------------*/
|
||
|
static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,
|
||
|
uint32_t src, void *priv)
|
||
|
{
|
||
|
int i;
|
||
|
struct _payload *r_payload = (struct _payload *)data;
|
||
|
|
||
|
(void)ept;
|
||
|
(void)src;
|
||
|
(void)priv;
|
||
|
LPRINTF(" received payload number %lu of size %lu \r\n",
|
||
|
r_payload->num, (unsigned long)len);
|
||
|
|
||
|
if (r_payload->size == 0) {
|
||
|
LPERROR(" Invalid size of package is received.\n");
|
||
|
err_cnt++;
|
||
|
return RPMSG_SUCCESS;
|
||
|
}
|
||
|
/* Validate data buffer integrity. */
|
||
|
for (i = 0; i < (int)r_payload->size; i++) {
|
||
|
if (r_payload->data[i] != 0xA5) {
|
||
|
LPRINTF("Data corruption at index %d\n", i);
|
||
|
err_cnt++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
rnum = r_payload->num + 1;
|
||
|
return RPMSG_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static void rpmsg_service_unbind(struct rpmsg_endpoint *ept)
|
||
|
{
|
||
|
(void)ept;
|
||
|
rpmsg_destroy_ept(&lept);
|
||
|
LPRINTF("echo test: service is destroyed\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.\n");
|
||
|
if (strcmp(name, RPMSG_SERVICE_NAME))
|
||
|
LPERROR("Unexpected name service %s.\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;
|
||
|
int i;
|
||
|
int size, max_size, num_payloads;
|
||
|
int expect_rnum = 0;
|
||
|
|
||
|
LPRINTF(" 1 - Send data to remote core, retrieve the echo");
|
||
|
LPRINTF(" and validate its integrity ..\n");
|
||
|
|
||
|
max_size = rpmsg_virtio_get_buffer_size(rdev);
|
||
|
if (max_size < 0) {
|
||
|
LPERROR("No avaiable buffer size.\n");
|
||
|
return -1;
|
||
|
}
|
||
|
max_size -= sizeof(struct _payload);
|
||
|
num_payloads = max_size - PAYLOAD_MIN_SIZE + 1;
|
||
|
i_payload =
|
||
|
(struct _payload *)metal_allocate_memory(2 * sizeof(unsigned long) +
|
||
|
max_size);
|
||
|
|
||
|
if (!i_payload) {
|
||
|
LPERROR("memory allocation failed.\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* 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.\n");
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
while (!is_rpmsg_ept_ready(&lept))
|
||
|
platform_poll(priv);
|
||
|
|
||
|
LPRINTF("RPMSG endpoint is binded with remote.\n");
|
||
|
for (i = 0, size = PAYLOAD_MIN_SIZE; i < num_payloads; i++, size++) {
|
||
|
i_payload->num = i;
|
||
|
i_payload->size = size;
|
||
|
|
||
|
/* Mark the data buffer. */
|
||
|
memset(&(i_payload->data[0]), 0xA5, size);
|
||
|
|
||
|
LPRINTF("sending payload number %lu of size %lu\n",
|
||
|
i_payload->num,
|
||
|
(unsigned long)(2 * sizeof(unsigned long)) + size);
|
||
|
|
||
|
ret = rpmsg_send(&lept, i_payload,
|
||
|
(2 * sizeof(unsigned long)) + size);
|
||
|
|
||
|
if (ret < 0) {
|
||
|
LPERROR("Failed to send data...\n");
|
||
|
break;
|
||
|
}
|
||
|
LPRINTF("echo test: sent : %lu\n",
|
||
|
(unsigned long)(2 * sizeof(unsigned long)) + size);
|
||
|
|
||
|
expect_rnum++;
|
||
|
do {
|
||
|
platform_poll(priv);
|
||
|
} while ((rnum < expect_rnum) && !err_cnt && !ept_deleted);
|
||
|
|
||
|
}
|
||
|
|
||
|
LPRINTF("**********************************\n");
|
||
|
LPRINTF(" Test Results: Error count = %d \n", err_cnt);
|
||
|
LPRINTF("**********************************\n");
|
||
|
/* Destroy the RPMsg endpoint */
|
||
|
rpmsg_destroy_ept(&lept);
|
||
|
LPRINTF("Quitting application .. Echo test end\n");
|
||
|
|
||
|
metal_free_memory(i_payload);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
void *platform;
|
||
|
struct rpmsg_device *rpdev;
|
||
|
int ret;
|
||
|
|
||
|
/* Initialize platform */
|
||
|
ret = platform_init(argc, argv, &platform);
|
||
|
if (ret) {
|
||
|
LPERROR("Failed to initialize platform.\n");
|
||
|
ret = -1;
|
||
|
} else {
|
||
|
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.\n");
|
||
|
ret = -1;
|
||
|
} else {
|
||
|
app(rpdev, platform);
|
||
|
platform_release_rpmsg_vdev(rpdev);
|
||
|
ret = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LPRINTF("Stopping application...\n");
|
||
|
platform_cleanup(platform);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|