To write an OpenAMP application, follow these steps:
- Create a firmware resource table.
The resource table defines the firmware entries that the OpenAMP application needs. It lists the system resources that the remote requires.
- Create remoteproc structure using resource table.
- Define RPMsg callback functions.
- Create an RPMsg VirtIO device.
- Create an RPMsg endpoint and associate the RPMsg device with the callback functions.
- Use
rpmsg_send()to send message to the remote processor.
After you initialize the framework, the OpenAMP application uses the RPMsg
channel to communicate between the master and remote processor. It uses
rpmsg_send() and I/O callback functions for this communication. The
following flow diagram shows this.
Figure 1. Flow Diagram

The following example shows an OpenAMP setup and flow with a resource table, remoteproc instance, and RPMsg callback functions:
struct resource_table table = {
/* Version number. If the structure changes in the future, this acts as
* reference to what the structure is.
*/
.ver = 1,
/* Number of resources; Matches number of offsets in array */
.num = 2,
/* reserved (must be zero) */
.reserved = 0,
{ /* array of offsets pointing at various resource entries */
/* This RSC_RPROC_MEM entry sets the shared memory address range. It tells the Linux kernel the shared memory range the remote can access. */
{RSC_RPROC_MEM, 0x3ed40000, 0x3ed40000, 0x100000, 0},
/* virtio device header */
{
RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0,
NUM_VRINGS, {0, 0},
}
}
};
#include <openamp/remoteproc.h>
#include <openamp/rpmsg.h>
#include <openamp/rpmsg_virtio.h>
/* User defined remoteproc operations for communication */
struct remoteproc rproc_ops = {
.init = local_rproc_init,
.mmap = local_rproc_mmap,
.notify = local_rproc_notify,
.remove = local_rproc_remove,
};
/* Remoteproc instance */
struct remoteproc rproc;
/* RPMsg VirtIO device instance */
struct rpmsg_virtio_device rpmsg_vdev;
/* RPMsg device */
struct rpmsg_device *rpmsg_dev;
/* Resource Table */
void *rsc_table = &resource_table;
/* Size of the resource table */
int rsc_size = sizeof(resource_table);
/* Shared memory metal I/O region */
struct metal_io_region *shm_io;
/* VirtIO device */
struct virtio_device *vdev;
/* RPMsg shared buffers pool */
struct rpmsg_virtio_shm_pool shpool;
/* Shared buffers */
void *shbuf;
/* RPMsg endpoint */
struct rpmsg_endpoint ept;
/* User defined RPMsg name service callback */
void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest);
/* User defined RPMsg endpoint received message callback */
void rpmsg_ept_cb(struct rpmsg_endpoint *ept, void *data, size_t len,
uint32_t src, void *priv);
/* User defined RPMsg name service unbind request callback */
void ns_unbind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest);
void main(void)
{
/* Instantiate remoteproc instance */
remoteproc_init(&rproc, &rproc_ops);
/* Mmap shared memories so that they can be used */
remoteproc_mmap(&rproc, &physical_address, NULL, size,
<memory_attributes>, &shm_io);
/* Parse resource table to remoteproc */
remoteproc_set_rsc_table(&rproc, rsc_table, rsc_size);
/* Create VirtIO device from remoteproc */
vdev = remoteproc_create_virtio(&rproc, 0, VIRTIO_DEV_MASTER, NULL);
/* Initialize the shared buffers pool (only if VirtIO master) */
shbuf = metal_io_phys_to_virt(shm_io, SHARED_BUF_PA);
rpmsg_virtio_init_shm_pool(&shpool, shbuf, SHARED_BUFF_SIZE);
/* Initialize RPMsg VirtIO device with the VirtIO device */
rpmsg_init_vdev(&rpmsg_vdev, vdev, ns_bind_cb, io, shm_io, &shpool);
/* Get RPMsg device from RPMsg VirtIO device */
rpmsg_dev = rpmsg_virtio_get_rpmsg_device(&rpmsg_vdev);
/* Create RPMsg endpoint */
rpmsg_create_ept(&ept, rdev, RPMSG_SERVICE_NAME, RPMSG_ADDR_ANY,
rpmsg_ept_cb, ns_unbind_cb);
/* Wait until endpoint is ready */
while (!is_rpmsg_ept_read(&ept)) {
rproc_virtio_notified(vdev, RSC_NOTIFY_ID_ANY);
}
/* Send RPMsg */
rpmsg_send(&ept, data, size);
do {
rproc_virtio_notified(vdev, RSC_NOTIFY_ID_ANY);
} while (!ns_unbind_cb_is_called && !user_decided_to_end_communication);
/* End of communication, destroy the endpoint and clean up */
rpmsg_destroy_ept(&ept);
rpmsg_deinit_vdev(&rpmsg_vdev);
remoteproc_remove_virtio(&rproc, vdev);
remoteproc_remove(&rproc);
}