Skip to content

Commit e4b719e

Browse files
Kristian Klomsten Skordalgalak
Kristian Klomsten Skordal
authored andcommitted
sample: add OpenAMP sample application
This commit adds a sample application using OpenAMP for remote procedure calls on the LPCXpresso54114. It is adapted from the RPMsg-Lite sample application added in PR zephyrproject-rtos#5960, and uses the IPM driver to provide interprocessor interrupts. Instructions for how to compile the application, including OpenAMP and libmetal is provided in the README.md file in the application's toplevel directory. Signed-off-by: Kristian Klomsten Skordal <[email protected]>
1 parent 1815937 commit e4b719e

File tree

16 files changed

+666
-0
lines changed

16 files changed

+666
-0
lines changed

boards/arm/lpcxpresso54114/lpcxpresso54114_defconfig

+4
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ CONFIG_CORTEX_M_SYSTICK=y
1515
CONFIG_GPIO=y
1616
CONFIG_PINMUX=y
1717
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000
18+
19+
# Heap is needed by OpenAMP:
20+
CONFIG_HEAP_MEM_POOL_SIZE=4096
21+

boards/arm/lpcxpresso54114_m0/lpcxpresso54114_m0_defconfig

+4
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ CONFIG_SERIAL=n
1414
CONFIG_CORTEX_M_SYSTICK=y
1515
CONFIG_GPIO=n
1616
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000
17+
18+
# Heap is needed by OpenAMP:
19+
CONFIG_HEAP_MEM_POOL_SIZE=4096
20+

samples/subsys/ipc/openamp/README.rst

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
.. _openAMP_example:
2+
3+
OpenAMP Example Application
4+
###########################
5+
6+
Overview
7+
********
8+
9+
This application demostrates how to use OpenAMP with Zephyr. It is designed to
10+
be an OpenAMP counterpart to the RPMsg-Lite example for the LPCXpresso5411x
11+
chip, to be used for comparison and benchmarking of the two RPC libraries.
12+
13+
Building the application
14+
*************************
15+
16+
Building and running this application requires that libmetal and OpenAMP are
17+
compiled first. Clone the libmetal and OpenAMP repositories in an appropriate
18+
location (outside the Zephyr code tree):
19+
20+
.. code-block:: bash
21+
22+
$ git clone https://github.com/OpenAMP/libmetal.git
23+
$ git clone https://github.com/OpenAMP/open-amp.git
24+
25+
Compile and build libmetal for both cores:
26+
27+
.. code-block:: bash
28+
29+
$ cd libmetal
30+
$ mkdir build-master build-remote
31+
$ cd build-master
32+
$ cmake -DWITH_ZEPHYR=ON -DBOARD=lpcxpresso54114 ..
33+
$ make
34+
$ cd ../build-remote
35+
$ cmake -DWITH_ZEPHYR=ON -DBOARD=lpcxpresso54114_m0 ..
36+
$ make
37+
38+
Compile and build OpenAMP for both cores:
39+
40+
.. code-block:: bash
41+
42+
$ cd ../../open-amp
43+
$ mkdir build-master build-remote
44+
$ cd build-master
45+
$ cmake -DWITH_ZEPHYR=ON -DWITH_PROXY=OFF -DBOARD=lpcxpresso54114 \
46+
-DLIBMETAL_INCLUDE_DIR=<path to libmetal>/build-master/lib/include \
47+
-DLIBMETAL_LIB=<path to libmetal>/build-master/lib/libmetal.a ..
48+
$ make
49+
$ cd ../build-remote
50+
$ cmake -DWITH_ZEPHYR=ON -DWITH_PROXY=OFF -DBOARD=lpcxpresso54114_m0 \
51+
-DLIBMETAL_INCLUDE_DIR=<path to libmetal>/build-remote/lib/include \
52+
-DLIBMETAL_LIB=<path to libmetal>/build-remote/lib/libmetal.a ..
53+
$ make
54+
55+
Compile the remote application, by running the following commands:
56+
57+
.. code-block:: bash
58+
59+
$ cd $ZEPHYR_BASE/samples/subsys/ipc/openamp/remote
60+
$ mkdir build
61+
$ cmake -DBOARD=lpcxpresso54114_m0 \
62+
-DLIBMETAL_INCLUDE_DIR=<path to libmetal>/build-remote/lib/include \
63+
-DLIBMETAL_LIBRARY=<path to libmetal>/build-remote/lib/libmetal.a \
64+
-DOPENAMP_INCLUDE_DIR=<path to openamp>/lib/include \
65+
-DOPENAMP_LIBRARY=<path to openamp>/build-remote/lib/libopen_amp.a ..
66+
$ make
67+
68+
Compile the master application, by running the following commands:
69+
70+
.. code-block:: bash
71+
72+
$ cd $ZEPHYR_BASE/samples/subsys/ipc/openamp/master
73+
$ mkdir build
74+
$ cmake -DBOARD=lpcxpresso54114 \
75+
-DLIBMETAL_INCLUDE_DIR=<path to libmetal>/build-master/lib/include \
76+
-DLIBMETAL_LIBRARY=<path to libmetal>/build-master/lib/libmetal.a \
77+
-DOPENAMP_INCLUDE_DIR=<path to openamp>/lib/include \
78+
-DOPENAMP_LIBRARY=<path to openamp>/build-master/lib/libopen_amp.a ..
79+
$ make
80+
81+
Flash the project to the board from the master build directory:
82+
83+
.. code-block:: bash
84+
85+
$ make flash
86+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
set(BOARD lpcxpresso54114)
2+
3+
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
4+
project(NONE)
5+
6+
enable_language(C ASM)
7+
8+
# Location of external dependencies:
9+
set(LIBMETAL_INCLUDE_DIR "/home/kristian/libmetal/build-lpc/lib/include" CACHE PATH "Path to the libmetal header files")
10+
set(LIBMETAL_LIBRARY "/home/kristian/libmetal/build-lpc/lib/libmetal.a" CACHE FILEPATH "Path to the libmetal library")
11+
set(OPENAMP_INCLUDE_DIR "/home/kristian/openamp/lib/include" CACHE PATH "Path to the OpenAMP header files")
12+
set(OPENAMP_LIBRARY "/home/kristian/openamp/build-lpc/lib/libopen_amp.a" CACHE FILEPATH "Path to the OpenAMP library")
13+
14+
set(ZEPHYR_KERNEL_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/zephyr/kernel/libkernel.a")
15+
set(PLATFORM_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../platform")
16+
17+
target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/drivers)
18+
target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/samples/subsys/ipc/openamp/remote/build/zephyr)
19+
target_include_directories(app PRIVATE ${LIBMETAL_INCLUDE_DIR} ${OPENAMP_INCLUDE_DIR} ${PLATFORM_DIR})
20+
21+
target_sources(app PRIVATE src/main_master.c ${PLATFORM_DIR}/platform.c ${PLATFORM_DIR}/platform_ops.c ${PLATFORM_DIR}/resource_table.c)
22+
if(CONFIG_SOC_SERIES_LPC54XXX)
23+
target_sources(app PRIVATE $ENV{ZEPHYR_BASE}/ext/hal/nxp/mcux/devices/LPC54114/incbin.S)
24+
endif()
25+
26+
target_link_libraries(app
27+
${OPENAMP_LIBRARY}
28+
${LIBMETAL_LIBRARY}
29+
${ZEPHYR_KERNEL_LIBRARY})
30+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CONFIG_PRINTK=y
2+
CONFIG_IPM=y
3+
CONFIG_IPM_MCUX=y
4+
CONFIG_SLAVE_CORE_MCUX=y
5+
CONFIG_TIMESLICE_SIZE=1
6+
CONFIG_MAIN_STACK_SIZE=2048
7+
CONFIG_HEAP_MEM_POOL_SIZE=4096
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
sample:
2+
description: TBD
3+
name: TBD
4+
tests:
5+
test:
6+
build_only: true
7+
filter: CONFIG_SOC_MCUX
8+
tags: samples ipm
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright (c) 2018, NXP
3+
* Copyright (c) 2018, Nordic Semiconductor ASA
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include <zephyr.h>
9+
#include <misc/printk.h>
10+
#include <device.h>
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <string.h>
14+
15+
#include <openamp/open_amp.h>
16+
17+
#include "platform.h"
18+
#include "resource_table.h"
19+
20+
#define APP_TASK_STACK_SIZE (256)
21+
K_THREAD_STACK_DEFINE(thread_stack, APP_TASK_STACK_SIZE);
22+
static struct k_thread thread_data;
23+
24+
static struct rpmsg_channel *rp_channel;
25+
static struct rpmsg_endpoint *rp_endpoint;
26+
27+
static K_SEM_DEFINE(channel_created, 0, 1);
28+
29+
static K_SEM_DEFINE(message_received, 0, 1);
30+
static volatile unsigned int received_data;
31+
32+
static struct rsc_table_info rsc_info;
33+
static struct hil_proc *proc;
34+
35+
static void rpmsg_recv_callback(struct rpmsg_channel *channel, void *data,
36+
int data_length, void *private, unsigned long src)
37+
{
38+
received_data = *((unsigned int *) data);
39+
k_sem_give(&message_received);
40+
}
41+
42+
static void rpmsg_channel_created(struct rpmsg_channel *channel)
43+
{
44+
rp_channel = channel;
45+
rp_endpoint = rpmsg_create_ept(rp_channel, rpmsg_recv_callback, RPMSG_NULL, RPMSG_ADDR_ANY);
46+
k_sem_give(&channel_created);
47+
}
48+
49+
static void rpmsg_channel_deleted(struct rpmsg_channel *channel)
50+
{
51+
rpmsg_destroy_ept(rp_endpoint);
52+
}
53+
54+
static unsigned int receive_message(void)
55+
{
56+
while (k_sem_take(&message_received, K_NO_WAIT) != 0)
57+
hil_poll(proc, 0);
58+
return received_data;
59+
}
60+
61+
static int send_message(unsigned int message)
62+
{
63+
return rpmsg_send(rp_channel, &message, sizeof(message));
64+
}
65+
66+
void app_task(void *arg1, void *arg2, void *arg3)
67+
{
68+
ARG_UNUSED(arg1);
69+
ARG_UNUSED(arg2);
70+
ARG_UNUSED(arg3);
71+
72+
printk("\r\nOpenAMP demo started\r\n");
73+
74+
struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
75+
metal_init(&metal_params);
76+
77+
proc = platform_init(RPMSG_MASTER);
78+
if (proc == NULL) {
79+
printk("platform_init() failed\n");
80+
goto _cleanup;
81+
}
82+
83+
resource_table_init((void **) &rsc_info.rsc_tab, &rsc_info.size);
84+
85+
struct remote_proc *rproc_ptr = NULL;
86+
int status = remoteproc_resource_init(&rsc_info, proc,
87+
rpmsg_channel_created, rpmsg_channel_deleted,
88+
rpmsg_recv_callback, &rproc_ptr, RPMSG_MASTER);
89+
if (status != 0) {
90+
printk("remoteproc_resource_init() failed with status %d\n", status);
91+
goto _cleanup;
92+
}
93+
94+
while (k_sem_take(&channel_created, K_NO_WAIT) != 0)
95+
hil_poll(proc, 0);
96+
97+
unsigned int message = 0;
98+
status = send_message(message);
99+
if (status < 0) {
100+
printk("send_message(%d) failed with status %d\n", message, status);
101+
goto _cleanup;
102+
}
103+
104+
while (message <= 100) {
105+
message = receive_message();
106+
printk("Primary core received a message: %d\n", message);
107+
108+
message++;
109+
status = send_message(message);
110+
if (status < 0) {
111+
printk("send_message(%d) failed with status %d\n", message, status);
112+
goto _cleanup;
113+
}
114+
}
115+
116+
_cleanup:
117+
if (rproc_ptr) {
118+
remoteproc_resource_deinit(rproc_ptr);
119+
}
120+
metal_finish();
121+
122+
printk("OpenAMP demo ended.\n");
123+
}
124+
125+
void main(void)
126+
{
127+
printk("Starting application thread!\n");
128+
k_thread_create(&thread_data, thread_stack, APP_TASK_STACK_SIZE,
129+
(k_thread_entry_t)app_task,
130+
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
131+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2018 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr.h>
8+
9+
#include "platform.h"
10+
#include "resource_table.h"
11+
12+
extern struct hil_platform_ops platform_ops;
13+
14+
static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDRESS };
15+
static struct metal_device shm_device = {
16+
.name = SHM_DEVICE_NAME,
17+
.bus = NULL,
18+
.num_regions = 1,
19+
{
20+
{
21+
.virt = (void *) SHM_START_ADDRESS,
22+
.physmap = shm_physmap,
23+
.size = SHM_SIZE,
24+
.page_shift = 0xffffffff,
25+
.page_mask = 0xffffffff,
26+
.mem_flags = 0,
27+
.ops = { NULL },
28+
},
29+
},
30+
.node = { NULL },
31+
.irq_num = 0,
32+
.irq_info = NULL
33+
};
34+
35+
struct hil_proc *platform_init(int role)
36+
{
37+
int status;
38+
39+
status = metal_register_generic_device(&shm_device);
40+
if (status != 0) {
41+
printk("metal_register_generic_device(): could not register shared memory device: error code %d\n", status);
42+
return NULL;
43+
}
44+
45+
struct hil_proc *proc = hil_create_proc(&platform_ops, role != RPMSG_MASTER, NULL);
46+
if (proc == NULL) {
47+
printk("platform_create(): could not allocate hil_proc\n");
48+
return NULL;
49+
}
50+
51+
hil_set_shm(proc, "generic", SHM_DEVICE_NAME, SHM_START_ADDRESS, SHM_SIZE);
52+
return proc;
53+
}
54+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2018 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef PLATFORM_H__
8+
#define PLATFORM_H__
9+
10+
#include <openamp/open_amp.h>
11+
12+
#define SHM_START_ADDRESS 0x04000400
13+
#define SHM_SIZE 0x7c00
14+
#define SHM_DEVICE_NAME "sramx.shm"
15+
16+
#define VRING_COUNT 2
17+
#define VRING_RX_ADDRESS 0x04000400
18+
#define VRING_TX_ADDRESS 0x04000800
19+
#define VRING_ALIGNMENT 4
20+
#define VRING_SIZE 32
21+
22+
struct hil_proc *platform_init(int role);
23+
24+
#endif
25+

0 commit comments

Comments
 (0)