Files
open-amp/apps/examples/rpmsg_sample_echo/rpmsg-sample-echo.c
Arnaud Pouliquen 703eba29c6 app: update to adapt on ns_unbind_cb
Rework of the endpoint management based on new ns_unbind callback.
slave core destroys its endpoint when receive rpmsg shutdown message.
Master core destroys its endpoint when receive ns unbind callback.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
2018-07-30 17:24:27 -07:00

133 lines
3.3 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 allows to check the compatibility with linux OS running on
* the master CPU. For this it echo MSG_LIMIT time message sent by the rpmsg
* sample client available in linux kernel distribution.
*/
#include <stdio.h>
#include <openamp/open_amp.h>
#include <metal/alloc.h>
#include "platform_info.h"
#define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
#define RPMSG_SERV_NAME "rpmsg-client-sample"
#define MSG_LIMIT 100
static struct rpmsg_endpoint lept;
static int shutdown_req = 0;
/* External functions */
extern int init_system(void);
extern void cleanup_system(void);
/*-----------------------------------------------------------------------------*
* 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;
static uint32_t count = 0;
char payload[RPMSG_BUFFER_SIZE];
/* Send data back MSG_LIMIT time to master */
memset(payload, 0, RPMSG_BUFFER_SIZE);
memcpy(payload, data, len);
if (++count <= MSG_LIMIT) {
LPRINTF("echo message number %u: %s\n",
(unsigned int)count, payload);
if (rpmsg_send(ept, (char *)data, len) < 0) {
LPERROR("rpmsg_send failed\n");
goto destroy_ept;
}
if (count == MSG_LIMIT) {
goto destroy_ept;
}
}
return RPMSG_SUCCESS;
destroy_ept:
shutdown_req = 1;
return RPMSG_SUCCESS;
}
static void rpmsg_service_unbind(struct rpmsg_endpoint *ept)
{
(void)ept;
LPRINTF("unexpected Remote endpoint destroy\n");
shutdown_req = 1;
}
/*-----------------------------------------------------------------------------*
* Application
*-----------------------------------------------------------------------------*/
int app(struct rpmsg_device *rdev, void *priv)
{
int ret;
/* Initialize RPMSG framework */
LPRINTF("Try to create rpmsg endpoint.\n");
ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERV_NAME, 0, RPMSG_ADDR_ANY,
rpmsg_endpoint_cb, rpmsg_service_unbind);
if (ret) {
LPERROR("Failed to create endpoint.\n");
return -1;
}
LPRINTF("Successfully created rpmsg endpoint.\n");
while (1) {
platform_poll(priv);
/* we got a shutdown request, exit */
if (shutdown_req) {
break;
}
}
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...\n");
/* 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_SLAVE,
NULL, NULL);
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;
}