* SPDX-License-Identifier: BSD-3-Clause
*/
* This is a sample demonstration application that showcases usage of remoteproc
* and rpmsg APIs on the remote core. This application is meant to run on the remote CPU
* running baremetal code. This applicationr receives two matrices from the host,
* multiplies them and returns the result to the host core.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openamp/open_amp.h>
#include "matrix_multiply.h"
#include "platform_info.h"
#define MAX_SIZE 6
#define NUM_MATRIX 2
#define SHUTDOWN_MSG 0xEF56A55A
#define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
typedef struct _matrix {
unsigned int size;
unsigned int elements[MAX_SIZE][MAX_SIZE];
} matrix;
static struct rpmsg_endpoint lept;
static int shutdown_req = 0;
* Calculate the Matrix
*-----------------------------------------------------------------------------*/
static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r)
{
unsigned int i, j, k;
memset(r, 0x0, sizeof(matrix));
r->size = m->size;
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];
}
}
}
}
* RPMSG callbacks setup by remoteproc_resource_init()
*-----------------------------------------------------------------------------*/
static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,
uint32_t src, void *priv)
{
matrix matrix_array[NUM_MATRIX];
matrix matrix_result;
(void)priv;
(void)src;
if ((*(unsigned int *)data) == SHUTDOWN_MSG) {
LPRINTF("shutdown message is received.\r\n");
shutdown_req = 1;
return RPMSG_SUCCESS;
}
memcpy(matrix_array, data, len);
Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);
if (rpmsg_send(ept, &matrix_result, sizeof(matrix)) < 0) {
LPERROR("rpmsg_send failed\r\n");
}
return RPMSG_SUCCESS;
}
static void rpmsg_service_unbind(struct rpmsg_endpoint *ept)
{
(void)ept;
LPERROR("Endpoint is destroyed\r\n");
shutdown_req = 1;
}
* Application
*-----------------------------------------------------------------------------*/
int app(struct rpmsg_device *rdev, void *priv)
{
int ret;
ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME,
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
rpmsg_endpoint_cb,
rpmsg_service_unbind);
if (ret) {
LPERROR("Failed to create endpoint.\r\n");
return -1;
}
LPRINTF("Waiting for events...\r\n");
while(1) {
platform_poll(priv);
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...\r\n");
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_DEVICE,
NULL, NULL);
if (!rpdev) {
LPERROR("Failed to create rpmsg virtio device.\r\n");
ret = -1;
} else {
app(rpdev, platform);
platform_release_rpmsg_vdev(rpdev, platform);
ret = 0;
}
}
LPRINTF("Stopping application...\r\n");
platform_cleanup(platform);
return ret;
}