samples: openamp: Update sample to OpenAMP v2018.10 release

The v2018.10 release of OpenAMP reworks the API set and splits the
remoteproc vs rpmsg interfaces so one can use rpmsg without remoteproc.

This helps drastically reduce the code footprint utilized by OpenAMP.
The remote see around 4k reduction in code size.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
This commit is contained in:
Kumar Gala 2018-05-08 19:10:26 -05:00 committed by Kumar Gala
commit e2b62b411b
13 changed files with 578 additions and 537 deletions

View file

@ -14,13 +14,7 @@ endif()
enable_language(C ASM)
# Location of external dependencies:
set(PLATFORM_DIR "${CMAKE_CURRENT_SOURCE_DIR}/platform")
target_sources(app PRIVATE src/main_master.c
${PLATFORM_DIR}/platform.c
${PLATFORM_DIR}/platform_ops.c
${PLATFORM_DIR}/resource_table.c)
target_sources(app PRIVATE src/main.c)
include(ExternalProject)
@ -33,4 +27,4 @@ ExternalProject_Add(
)
add_dependencies(core_m0_inc_target openamp_remote)
target_include_directories(app PRIVATE ${PLATFORM_DIR})
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
* Copyright (c) 2018 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef COMMON_H__
#define COMMON_H__
#define SHM_START_ADDR 0x04000400
#define SHM_SIZE 0x7c00
#define SHM_DEVICE_NAME "sramx.shm"
#define VRING_COUNT 2
#define VRING_RX_ADDRESS 0x04007800
#define VRING_TX_ADDRESS 0x04007C00
#define VRING_ALIGNMENT 4
#define VRING_SIZE 16
#define VDEV_STATUS_ADDR 0x04000000
#endif

View file

@ -1,56 +0,0 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include "platform.h"
#include "resource_table.h"
extern struct hil_platform_ops platform_ops;
static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDRESS };
static struct metal_device shm_device = {
.name = SHM_DEVICE_NAME,
.bus = NULL,
.num_regions = 1,
{
{
.virt = (void *) SHM_START_ADDRESS,
.physmap = shm_physmap,
.size = SHM_SIZE,
.page_shift = 0xffffffff,
.page_mask = 0xffffffff,
.mem_flags = 0,
.ops = { NULL },
},
},
.node = { NULL },
.irq_num = 0,
.irq_info = NULL
};
struct hil_proc *platform_init(int role)
{
int status;
status = metal_register_generic_device(&shm_device);
if (status != 0) {
printk("metal_register_generic_device(): could not register "
"shared memory device: error code %d\n", status);
return NULL;
}
struct hil_proc *proc = hil_create_proc(&platform_ops,
role != RPMSG_MASTER, NULL);
if (proc == NULL) {
printk("platform_create(): could not allocate hil_proc\n");
return NULL;
}
hil_set_shm(proc, "generic", SHM_DEVICE_NAME, SHM_START_ADDRESS,
SHM_SIZE);
return proc;
}

View file

@ -1,25 +0,0 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef PLATFORM_H__
#define PLATFORM_H__
#include <openamp/open_amp.h>
#define SHM_START_ADDRESS 0x04000400
#define SHM_SIZE 0x7c00
#define SHM_DEVICE_NAME "sramx.shm"
#define VRING_COUNT 2
#define VRING_RX_ADDRESS 0x04007800
#define VRING_TX_ADDRESS 0x04007C00
#define VRING_ALIGNMENT 4
#define VRING_SIZE 16
struct hil_proc *platform_init(int role);
#endif

View file

@ -1,101 +0,0 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* Implement the HIL layer required by OpenAMP
*/
#include <zephyr.h>
#include <ipm.h>
#include <openamp/open_amp.h>
#include "platform.h"
static K_SEM_DEFINE(data_sem, 0, 1);
static struct device *ipm_handle;
static void platform_ipm_callback(void *context, u32_t id, volatile void *data)
{
k_sem_give(&data_sem);
}
static int enable_interrupt(struct proc_intr *intr)
{
return ipm_set_enabled(ipm_handle, 1);
}
static void notify(struct hil_proc *proc, struct proc_intr *intr_info)
{
u32_t dummy_data = 0x12345678; /* Some data must be provided */
ipm_send(ipm_handle, 0, 0, &dummy_data, sizeof(dummy_data));
}
static int boot_cpu(struct hil_proc *proc, unsigned int load_addr)
{
return -1;
}
static void shutdown_cpu(struct hil_proc *proc)
{
}
static int poll(struct hil_proc *proc, int nonblock)
{
int status = k_sem_take(&data_sem, nonblock ? K_NO_WAIT : K_FOREVER);
if (status == 0) {
hil_notified(proc, 0xffffffff);
}
return status;
}
static struct metal_io_region *alloc_shm(struct hil_proc *proc,
metal_phys_addr_t physical,
size_t size,
struct metal_device **device)
{
int status = metal_device_open("generic", SHM_DEVICE_NAME, device);
if (status != 0) {
return NULL;
}
return metal_device_io_region(*device, 0);
}
static void release_shm(struct hil_proc *proc, struct metal_device *device,
struct metal_io_region *io)
{
metal_device_close(device);
}
static int initialize(struct hil_proc *proc)
{
ipm_handle = device_get_binding("MAILBOX_0");
if (!ipm_handle) {
return -1;
}
ipm_register_callback(ipm_handle, platform_ipm_callback, NULL);
return 0;
}
static void release(struct hil_proc *proc)
{
ipm_set_enabled(ipm_handle, 0);
}
struct hil_platform_ops platform_ops = {
.enable_interrupt = enable_interrupt,
.notify = notify,
.boot_cpu = boot_cpu,
.shutdown_cpu = shutdown_cpu,
.poll = poll,
.alloc_shm = alloc_shm,
.release_shm = release_shm,
.initialize = initialize,
.release = release
};

View file

@ -1,47 +0,0 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* Implement the resource table that will get parsed by OpenAMP to convey
* the shared memory region used for message passing and ring setup.
*/
#include "platform.h"
#include "resource_table.h"
struct lpc_resource_table *rsc_table_ptr = (void *) RSC_TABLE_ADDRESS;
#if defined(CPU_LPC54114J256BD64_cm4)
static const struct lpc_resource_table rsc_table = {
.ver = 1,
.num = 2,
.offset = {
offsetof(struct lpc_resource_table, mem),
offsetof(struct lpc_resource_table, vdev),
},
.mem = {
RSC_RPROC_MEM, SHM_START_ADDRESS, SHM_START_ADDRESS, SHM_SIZE,
0,
},
.vdev = {
RSC_VDEV, VIRTIO_ID_RPMSG, 0, 1 << VIRTIO_RPMSG_F_NS, 0, 0, 0,
VRING_COUNT, { 0, 0 },
},
.vring0 = { VRING_TX_ADDRESS, VRING_ALIGNMENT, VRING_SIZE, 1, 0 },
.vring1 = { VRING_RX_ADDRESS, VRING_ALIGNMENT, VRING_SIZE, 2, 0 },
};
#endif
void resource_table_init(void **table_ptr, int *length)
{
#if defined(CPU_LPC54114J256BD64_cm4)
/* Master: copy the resource table to shared memory. */
memcpy(rsc_table_ptr, &rsc_table, sizeof(struct lpc_resource_table));
#endif
*length = sizeof(struct lpc_resource_table);
*table_ptr = rsc_table_ptr;
}

View file

@ -1,28 +0,0 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef RESOURCE_TABLE_H__
#define RESOURCE_TABLE_H__
#include <openamp/open_amp.h>
#define RSC_TABLE_ADDRESS 0x04000000
OPENAMP_PACKED_BEGIN
struct lpc_resource_table {
uint32_t ver;
uint32_t num;
uint32_t reserved[2];
uint32_t offset[2];
struct fw_rsc_rproc_mem mem;
struct fw_rsc_vdev vdev;
struct fw_rsc_vdev_vring vring0, vring1;
} OPENAMP_PACKED_END;
void resource_table_init(void **table_ptr, int *length);
#endif

View file

@ -5,8 +5,6 @@ cmake_minimum_required(VERSION 3.13.1)
#
set(BOARD lpcxpresso54114_m0)
set(PLATFORM_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../platform")
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(openamp_remote)
@ -14,9 +12,5 @@ if(NOT ("${BOARD}" STREQUAL "lpcxpresso54114_m0"))
message(FATAL_ERROR "${BOARD} was specified, but this sample only supports lpcxpresso54114_m0")
endif()
target_sources(app PRIVATE src/main_remote.c
${PLATFORM_DIR}/platform.c
${PLATFORM_DIR}/resource_table.c
${PLATFORM_DIR}/platform_ops.c)
target_include_directories(app PRIVATE ${PLATFORM_DIR})
target_sources(app PRIVATE src/main.c)
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..)

View file

@ -5,3 +5,4 @@ CONFIG_IPM_MCUX=y
CONFIG_PLATFORM_SPECIFIC_INIT=n
CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_OPENAMP=y
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096

View file

@ -0,0 +1,256 @@
/*
* Copyright (c) 2018, NXP
* Copyright (c) 2018, Nordic Semiconductor ASA
* Copyright (c) 2018, Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <ipm.h>
#include <misc/printk.h>
#include <device.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openamp/open_amp.h>
#include <metal/device.h>
#include "common.h"
#define APP_TASK_STACK_SIZE (1024)
K_THREAD_STACK_DEFINE(thread_stack, APP_TASK_STACK_SIZE);
static struct k_thread thread_data;
static struct device *ipm_handle;
static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR };
static struct metal_device shm_device = {
.name = SHM_DEVICE_NAME,
.bus = NULL,
.num_regions = 1,
{
{
.virt = (void *) SHM_START_ADDR,
.physmap = shm_physmap,
.size = SHM_SIZE,
.page_shift = 0xffffffff,
.page_mask = 0xffffffff,
.mem_flags = 0,
.ops = { NULL },
},
},
.node = { NULL },
.irq_num = 0,
.irq_info = NULL
};
static volatile unsigned int received_data;
static struct virtio_vring_info rvrings[2] = {
[0] = {
.info.align = VRING_ALIGNMENT,
},
[1] = {
.info.align = VRING_ALIGNMENT,
},
};
static struct virtio_device vdev;
static struct rpmsg_virtio_device rvdev;
static struct metal_io_region *io;
static struct virtqueue *vq[2];
static unsigned char virtio_get_status(struct virtio_device *vdev)
{
return sys_read8(VDEV_STATUS_ADDR);
}
static u32_t virtio_get_features(struct virtio_device *vdev)
{
return 1 << VIRTIO_RPMSG_F_NS;
}
static void virtio_notify(struct virtqueue *vq)
{
u32_t dummy_data = 0x00110011; /* Some data must be provided */
ipm_send(ipm_handle, 0, 0, &dummy_data, sizeof(dummy_data));
}
struct virtio_dispatch dispatch = {
.get_status = virtio_get_status,
.get_features = virtio_get_features,
.notify = virtio_notify,
};
static K_SEM_DEFINE(data_sem, 0, 1);
static K_SEM_DEFINE(data_rx_sem, 0, 1);
static void platform_ipm_callback(void *context, u32_t id, volatile void *data)
{
k_sem_give(&data_sem);
}
int endpoint_cb(struct rpmsg_endpoint *ept, void *data,
size_t len, u32_t src, void *priv)
{
received_data = *((unsigned int *) data);
k_sem_give(&data_rx_sem);
return RPMSG_SUCCESS;
}
static K_SEM_DEFINE(ept_sem, 0, 1);
struct rpmsg_endpoint my_ept;
struct rpmsg_endpoint *ep = &my_ept;
static void rpmsg_service_unbind(struct rpmsg_endpoint *ept)
{
(void)ept;
rpmsg_destroy_ept(ep);
}
static unsigned int receive_message(void)
{
while (k_sem_take(&data_rx_sem, K_NO_WAIT) != 0) {
int status = k_sem_take(&data_sem, K_FOREVER);
if (status == 0) {
virtqueue_notification(vq[1]);
}
}
return received_data;
}
static int send_message(unsigned int message)
{
return rpmsg_send(ep, &message, sizeof(message));
}
void app_task(void *arg1, void *arg2, void *arg3)
{
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
int status = 0;
unsigned int message = 0;
struct metal_device *device;
struct rpmsg_device *rdev;
struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
printk("\r\nOpenAMP[remote] demo started\r\n");
status = metal_init(&metal_params);
if (status != 0) {
printk("metal_init: failed - error code %d\n", status);
return;
}
status = metal_register_generic_device(&shm_device);
if (status != 0) {
printk("Couldn't register shared memory device: %d\n", status);
return;
}
status = metal_device_open("generic", SHM_DEVICE_NAME, &device);
if (status != 0) {
printk("metal_device_open failed: %d\n", status);
return;
}
io = metal_device_io_region(device, 0);
if (io == NULL) {
printk("metal_device_io_region failed to get region\n");
return;
}
/* setup IPM */
ipm_handle = device_get_binding("MAILBOX_0");
if (ipm_handle == NULL) {
printk("device_get_binding failed to find device\n");
return;
}
ipm_register_callback(ipm_handle, platform_ipm_callback, NULL);
status = ipm_set_enabled(ipm_handle, 1);
if (status != 0) {
printk("ipm_set_enabled failed\n");
return;
}
/* setup vdev */
vq[0] = virtqueue_allocate(VRING_SIZE);
if (vq[0] == NULL) {
printk("virtqueue_allocate failed to alloc vq[0]\n");
return;
}
vq[1] = virtqueue_allocate(VRING_SIZE);
if (vq[1] == NULL) {
printk("virtqueue_allocate failed to alloc vq[1]\n");
return;
}
vdev.role = RPMSG_REMOTE;
vdev.vrings_num = VRING_COUNT;
vdev.func = &dispatch;
rvrings[0].io = io;
rvrings[0].info.vaddr = (void *)VRING_TX_ADDRESS;
rvrings[0].info.num_descs = VRING_SIZE;
rvrings[0].info.align = VRING_ALIGNMENT;
rvrings[0].vq = vq[0];
rvrings[1].io = io;
rvrings[1].info.vaddr = (void *)VRING_RX_ADDRESS;
rvrings[1].info.num_descs = VRING_SIZE;
rvrings[1].info.align = VRING_ALIGNMENT;
rvrings[1].vq = vq[1];
vdev.vrings_info = &rvrings[0];
/* setup rvdev */
status = rpmsg_init_vdev(&rvdev, &vdev, NULL, io, NULL);
if (status != 0) {
printk("rpmsg_init_vdev failed %d\n", status);
return;
}
rdev = rpmsg_virtio_get_rpmsg_device(&rvdev);
status = rpmsg_create_ept(ep, rdev, "k", RPMSG_ADDR_ANY,
RPMSG_ADDR_ANY, endpoint_cb, rpmsg_service_unbind);
if (status != 0) {
printk("rpmsg_create_ept failed %d\n", status);
return;
}
while (message < 99) {
message = receive_message();
printk("Remote core received a message: %d\n", message);
message++;
status = send_message(message);
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);
goto _cleanup;
}
}
_cleanup:
rpmsg_deinit_vdev(&rvdev);
metal_finish();
printk("OpenAMP demo ended.\n");
}
void main(void)
{
printk("Starting application thread!\n");
k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE,
(k_thread_entry_t)app_task,
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
}

View file

@ -1,122 +0,0 @@
/*
* Copyright (c) 2018, NXP
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* This implements the remote side of an OpenAMP system.
*/
#include <zephyr.h>
#include <misc/printk.h>
#include <device.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openamp/open_amp.h>
#include "platform.h"
#include "resource_table.h"
#define APP_TASK_STACK_SIZE (512)
K_THREAD_STACK_DEFINE(thread_stack, APP_TASK_STACK_SIZE);
static struct k_thread thread_data;
static K_SEM_DEFINE(channel_created, 0, 1);
static K_SEM_DEFINE(message_received, 0, 1);
static volatile unsigned int received_data;
static struct rsc_table_info rsc_info;
static struct hil_proc *proc;
static struct rpmsg_channel *rp_channel;
static struct rpmsg_endpoint *rp_endpoint;
static void rpmsg_recv_callback(struct rpmsg_channel *channel, void *data,
int data_length, void *private,
unsigned long src)
{
received_data = *((unsigned int *) data);
k_sem_give(&message_received);
}
static void rpmsg_channel_created(struct rpmsg_channel *channel)
{
rp_channel = channel;
rp_endpoint = rpmsg_create_ept(rp_channel, rpmsg_recv_callback,
RPMSG_NULL, RPMSG_ADDR_ANY);
k_sem_give(&channel_created);
}
static void rpmsg_channel_deleted(struct rpmsg_channel *channel)
{
rpmsg_destroy_ept(rp_endpoint);
}
static unsigned int receive_message(void)
{
while (k_sem_take(&message_received, K_NO_WAIT) != 0)
hil_poll(proc, 0);
return received_data;
}
static int send_message(unsigned int message)
{
return rpmsg_send(rp_channel, &message, sizeof(message));
}
void app_task(void *arg1, void *arg2, void *arg3)
{
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
metal_init(&metal_params);
proc = platform_init(RPMSG_REMOTE);
if (proc == NULL) {
goto _cleanup;
}
resource_table_init((void **) &rsc_info.rsc_tab, &rsc_info.size);
struct remote_proc *rproc_ptr = NULL;
int status = remoteproc_resource_init(&rsc_info, proc,
rpmsg_channel_created,
rpmsg_channel_deleted,
rpmsg_recv_callback,
&rproc_ptr, RPMSG_REMOTE);
if (status != 0) {
goto _cleanup;
}
while (k_sem_take(&channel_created, K_NO_WAIT) != 0)
hil_poll(proc, 0);
unsigned int message = 0U;
while (message <= 100) {
message = receive_message();
message++;
status = send_message(message);
if (status <= 0) {
goto _cleanup;
}
}
_cleanup:
if (rproc_ptr) {
remoteproc_resource_deinit(rproc_ptr);
}
}
void main(void)
{
k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE,
(k_thread_entry_t)app_task,
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
}

View file

@ -0,0 +1,294 @@
/*
* Copyright (c) 2018, NXP
* Copyright (c) 2018, Nordic Semiconductor ASA
* Copyright (c) 2018, Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <ipm.h>
#include <misc/printk.h>
#include <device.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <init.h>
#include <openamp/open_amp.h>
#include <metal/device.h>
#include "common.h"
#define APP_TASK_STACK_SIZE (1024)
K_THREAD_STACK_DEFINE(thread_stack, APP_TASK_STACK_SIZE);
static struct k_thread thread_data;
static struct device *ipm_handle;
static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR };
static struct metal_device shm_device = {
.name = SHM_DEVICE_NAME,
.bus = NULL,
.num_regions = 1,
{
{
.virt = (void *) SHM_START_ADDR,
.physmap = shm_physmap,
.size = SHM_SIZE,
.page_shift = 0xffffffff,
.page_mask = 0xffffffff,
.mem_flags = 0,
.ops = { NULL },
},
},
.node = { NULL },
.irq_num = 0,
.irq_info = NULL
};
static volatile unsigned int received_data;
static struct virtio_vring_info rvrings[2] = {
[0] = {
.info.align = VRING_ALIGNMENT,
},
[1] = {
.info.align = VRING_ALIGNMENT,
},
};
static struct virtio_device vdev;
static struct rpmsg_virtio_device rvdev;
static struct metal_io_region *io;
static struct virtqueue *vq[2];
static unsigned char virtio_get_status(struct virtio_device *vdev)
{
return VIRTIO_CONFIG_STATUS_DRIVER_OK;
}
static void virtio_set_status(struct virtio_device *vdev, unsigned char status)
{
sys_write8(status, VDEV_STATUS_ADDR);
}
static u32_t virtio_get_features(struct virtio_device *vdev)
{
return 1 << VIRTIO_RPMSG_F_NS;
}
static void virtio_set_features(struct virtio_device *vdev,
u32_t features)
{
}
static void virtio_notify(struct virtqueue *vq)
{
u32_t dummy_data = 0x55005500; /* Some data must be provided */
ipm_send(ipm_handle, 0, 0, &dummy_data, sizeof(dummy_data));
}
struct virtio_dispatch dispatch = {
.get_status = virtio_get_status,
.set_status = virtio_set_status,
.get_features = virtio_get_features,
.set_features = virtio_set_features,
.notify = virtio_notify,
};
static K_SEM_DEFINE(data_sem, 0, 1);
static K_SEM_DEFINE(data_rx_sem, 0, 1);
static void platform_ipm_callback(void *context, u32_t id, volatile void *data)
{
k_sem_give(&data_sem);
}
int endpoint_cb(struct rpmsg_endpoint *ept, void *data,
size_t len, u32_t src, void *priv)
{
received_data = *((unsigned int *) data);
k_sem_give(&data_rx_sem);
return RPMSG_SUCCESS;
}
static K_SEM_DEFINE(ept_sem, 0, 1);
struct rpmsg_endpoint my_ept;
struct rpmsg_endpoint *ep = &my_ept;
static void rpmsg_service_unbind(struct rpmsg_endpoint *ept)
{
(void)ept;
rpmsg_destroy_ept(ep);
}
void ns_bind_cb(struct rpmsg_device *rdev, const char *name, u32_t dest)
{
(void)rpmsg_create_ept(ep, rdev, name,
RPMSG_ADDR_ANY, dest,
endpoint_cb,
rpmsg_service_unbind);
k_sem_give(&ept_sem);
}
static unsigned int receive_message(void)
{
while (k_sem_take(&data_rx_sem, K_NO_WAIT) != 0) {
int status = k_sem_take(&data_sem, K_FOREVER);
if (status == 0) {
virtqueue_notification(vq[0]);
}
}
return received_data;
}
static int send_message(unsigned int message)
{
return rpmsg_send(ep, &message, sizeof(message));
}
static struct rpmsg_virtio_shm_pool shpool;
void app_task(void *arg1, void *arg2, void *arg3)
{
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
int status = 0;
unsigned int message = 0;
struct metal_device *device;
struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
printk("\r\nOpenAMP[master] demo started\r\n");
metal_init(&metal_params);
if (status != 0) {
printk("metal_init: failed - error code %d\n", status);
return;
}
status = metal_register_generic_device(&shm_device);
if (status != 0) {
printk("Couldn't register shared memory device: %d\n", status);
return;
}
status = metal_device_open("generic", SHM_DEVICE_NAME, &device);
if (status != 0) {
printk("metal_device_open failed: %d\n", status);
return;
}
io = metal_device_io_region(device, 0);
if (io == NULL) {
printk("metal_device_io_region failed to get region\n");
return;
}
/* setup IPM */
ipm_handle = device_get_binding("MAILBOX_0");
if (ipm_handle == NULL) {
printk("device_get_binding failed to find device\n");
return;
}
ipm_register_callback(ipm_handle, platform_ipm_callback, NULL);
ipm_set_enabled(ipm_handle, 1);
if (status != 0) {
printk("ipm_set_enabled failed\n");
return;
}
/* setup vdev */
vq[0] = virtqueue_allocate(VRING_SIZE);
if (vq[0] == NULL) {
printk("virtqueue_allocate failed to alloc vq[0]\n");
return;
}
vq[1] = virtqueue_allocate(VRING_SIZE);
if (vq[1] == NULL) {
printk("virtqueue_allocate failed to alloc vq[1]\n");
return;
}
vdev.role = RPMSG_MASTER;
vdev.vrings_num = VRING_COUNT;
vdev.func = &dispatch;
rvrings[0].io = io;
rvrings[0].info.vaddr = (void *)VRING_TX_ADDRESS;
rvrings[0].info.num_descs = VRING_SIZE;
rvrings[0].info.align = VRING_ALIGNMENT;
rvrings[0].vq = vq[0];
rvrings[1].io = io;
rvrings[1].info.vaddr = (void *)VRING_RX_ADDRESS;
rvrings[1].info.num_descs = VRING_SIZE;
rvrings[1].info.align = VRING_ALIGNMENT;
rvrings[1].vq = vq[1];
vdev.vrings_info = &rvrings[0];
/* setup rvdev */
rpmsg_virtio_init_shm_pool(&shpool, (void *)SHM_START_ADDR, SHM_SIZE);
status = rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, io, &shpool);
if (status != 0) {
printk("rpmsg_init_vdev failed %d\n", status);
return;
}
/* Since we are using name service, we need to wait for a response
* from NS setup and than we need to process it
*/
k_sem_take(&data_sem, K_FOREVER);
virtqueue_notification(vq[0]);
/* Wait til nameservice ep is setup */
k_sem_take(&ept_sem, K_FOREVER);
while (message < 100) {
status = send_message(message);
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);
goto _cleanup;
}
message = receive_message();
printk("Master core received a message: %d\n", message);
message++;
}
_cleanup:
rpmsg_deinit_vdev(&rvdev);
metal_finish();
printk("OpenAMP demo ended.\n");
}
void main(void)
{
printk("Starting application thread!\n");
k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE,
(k_thread_entry_t)app_task,
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
}
/* Make sure we clear out the status flag very early (before we bringup the
* secondary core) so the secondary core see's the proper status
*/
int init_status_flag(struct device *arg)
{
virtio_set_status(NULL, 0);
return 0;
}
SYS_INIT(init_status_flag, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

View file

@ -1,142 +0,0 @@
/*
* Copyright (c) 2018, NXP
* Copyright (c) 2018, Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* This implements the master side of an OpenAMP system.
*/
#include <zephyr.h>
#include <misc/printk.h>
#include <device.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openamp/open_amp.h>
#include "platform.h"
#include "resource_table.h"
#define APP_TASK_STACK_SIZE (512)
K_THREAD_STACK_DEFINE(thread_stack, APP_TASK_STACK_SIZE);
static struct k_thread thread_data;
static struct rpmsg_channel *rp_channel;
static struct rpmsg_endpoint *rp_endpoint;
static K_SEM_DEFINE(channel_created, 0, 1);
static K_SEM_DEFINE(message_received, 0, 1);
static volatile unsigned int received_data;
static struct rsc_table_info rsc_info;
static struct hil_proc *proc;
static void rpmsg_recv_callback(struct rpmsg_channel *channel, void *data,
int data_length, void *private,
unsigned long src)
{
received_data = *((unsigned int *) data);
k_sem_give(&message_received);
}
static void rpmsg_channel_created(struct rpmsg_channel *channel)
{
rp_channel = channel;
rp_endpoint = rpmsg_create_ept(rp_channel, rpmsg_recv_callback,
RPMSG_NULL, RPMSG_ADDR_ANY);
k_sem_give(&channel_created);
}
static void rpmsg_channel_deleted(struct rpmsg_channel *channel)
{
rpmsg_destroy_ept(rp_endpoint);
}
static unsigned int receive_message(void)
{
while (k_sem_take(&message_received, K_NO_WAIT) != 0)
hil_poll(proc, 0);
return received_data;
}
static int send_message(unsigned int message)
{
return rpmsg_send(rp_channel, &message, sizeof(message));
}
void app_task(void *arg1, void *arg2, void *arg3)
{
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
printk("\r\nOpenAMP demo started\r\n");
struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
metal_init(&metal_params);
proc = platform_init(RPMSG_MASTER);
if (proc == NULL) {
printk("platform_init() failed\n");
goto _cleanup;
}
resource_table_init((void **) &rsc_info.rsc_tab, &rsc_info.size);
struct remote_proc *rproc_ptr = NULL;
int status = remoteproc_resource_init(&rsc_info, proc,
rpmsg_channel_created,
rpmsg_channel_deleted,
rpmsg_recv_callback,
&rproc_ptr, RPMSG_MASTER);
if (status != 0) {
printk("remoteproc_resource_init() failed with status %d\n",
status);
goto _cleanup;
}
while (k_sem_take(&channel_created, K_NO_WAIT) != 0)
hil_poll(proc, 0);
unsigned int message = 0U;
status = send_message(message);
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);
goto _cleanup;
}
while (message <= 100) {
message = receive_message();
printk("Primary core received a message: %d\n", message);
message++;
status = send_message(message);
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);
goto _cleanup;
}
}
_cleanup:
if (rproc_ptr) {
remoteproc_resource_deinit(rproc_ptr);
}
metal_finish();
printk("OpenAMP demo ended.\n");
}
void main(void)
{
printk("Starting application thread!\n");
k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE,
(k_thread_entry_t)app_task,
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
}