Add support for MicroBlaze in programmable logic (PL) to OpenAMP.

Add an example of a baremetal echo server running on a MicroBlaze in PL
on a ZynqMP board and using RPMSG (with NO_IPI) to reply to a Linux user
space app running in the PS APU.

Signed-off-by: Ben Levinsky <ben.levinsky@xilinx.com>
Signed-off-by: Sergei Korneichuk <sergei.korneichuk@xilinx.com>
Signed-off-by: Ed Mooring <ed.mooring@xilinx.com>
This commit is contained in:
Ben Levinsky
2020-10-01 14:48:10 -07:00
committed by Arnaud Pouliquen
parent 0b696708c0
commit 3a4fa283ec
13 changed files with 969 additions and 0 deletions

View File

@@ -251,6 +251,7 @@ For now, it supports:
* Linux host OpenAMP between Linux userspace processes
* Linux userspace OpenAMP RPMsg master
* Linux userspace OpenAMP RPMsg slave
* Linux userspace OpenAMP RPMsg and MicroBlaze bare metal remote
## Known Limitations:
1. In case of OpenAMP on Linux userspace for inter processors communication,

View File

@@ -1,6 +1,9 @@
option (WITH_LOAD_FW "Include loading firmware example" OFF)
if (MACHINE MATCHES ".*microblaze.*")
add_subdirectory (echo)
else ()
add_subdirectory (echo)
add_subdirectory (rpmsg_sample_echo)
add_subdirectory (matrix_multiply)
@@ -10,3 +13,4 @@ endif (WITH_LOAD_FW)
if (WITH_PROXY_APPS)
add_subdirectory (rpc_demo)
endif (WITH_PROXY_APPS)
endif (MACHINE MATCHES ".*microblaze.*")

View File

@@ -0,0 +1,4 @@
collect (APP_COMMON_SOURCES platform_info.c)
collect (APP_COMMON_SOURCES rsc_table.c)
collect (APP_COMMON_SOURCES zynqmp_mb_a53_rproc.c)
collect (APP_INC_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")

View File

@@ -0,0 +1,154 @@
# OpenAMP MicroBlaze example
The microblaze_generic directories in OpenAMP repository provide an
implementation of rpmsg for Xilinx MicroBlaze design
example. The design instantiates Xilinx MicroBlaze soft processor in
ZynqMP's programmable logic (PL) and uses the processing system (PS)
DDR memory for its text and data. The HP0_DDR_LOW is mapped from 0 to
0x7FFFFFFF. The Local Memory Bus (LMB) is not connected and the LMB
memory is not present. The MicroBlaze Vector Base Address is set to
0x70000000 and its reset_mode (01) will force it to enter sleep mode
without performing any bus access. The design is available in the Xilinx
Shell Archive (XSA) format at https://xilinx-wiki.atlassian.net
## How to build OpenAMP echo server for the MicroBlaze design example.
For simplicity the example is not using Inter-Processor Interrupt (IPI)
hardware at this time and the MicroBlaze OpenAMP echo server is built
with RPMSG_NO_IPI flag.
* build the libmetal library on your host as follows:
* Create your own cmake toolchain file to compile libmetal for your generic
(baremetal) platform. Here is an example toolchain file:
```
set (BSP "/path/to/your_MicroBlaze_design_BSP/dir" CACHE STRING "")
set (CMAKE_SYSTEM_PROCESSOR "microblaze" CACHE STRING "")
set (MACHINE "microblaze_generic" CACHE STRING "")
set (CROSS_PREFIX "microblaze-xilinx-elf-" CACHE STRING "")
set (CMAKE_C_FLAGS "-g -mlittle-endian -mxl-soft-mul -Wall -Werror \
"-Wextra -flto -Os -I${BSP}/include" CACHE STRING "")
link_directories( ${BSP}/lib )
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
SET(CMAKE_AR "gcc-ar" CACHE STRING "")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_FINISH true)
include (cross-generic-gcc)
```
* Compile the libmetal library:
```
$ mkdir -p build-libmetal
$ cd build-libmetal
$ BSP="/path/to/your_MicroBlaze_design_BSP/dir"
$ cmake <libmetal_source> -DCMAKE_TOOLCHAIN_FILE=<toolchain_file> \
-DCMAKE_LIBRARY_PATH=$BSP/lib
$ make VERBOSE=1 DESTDIR=<libmetal_install> install
```
* build the OpenAMP library on your host as follows:
* Create your own cmake toolchain file to compile openamp for your generic
(baremetal) platform. Here is an example toolchain file:
```
set (BSP "/path/to/your_MicroBlaze_design_BSP/dir" CACHE STRING "")
set (CMAKE_SYSTEM_PROCESSOR "microblaze" CACHE STRING "")
set (MACHINE "microblaze_generic" CACHE STRING "")
set (CROSS_PREFIX "microblaze-xilinx-elf-" CACHE STRING "")
set (CMAKE_C_FLAGS "-g -mlittle-endian -Wall -Wextra -flto -Os \
-DUNDEFINE_FILE_OPS -DRPMSG_NO_IPI -I${LIBMETAL}/include \
-I${BSP}/include" CACHE STRING "")
set (PLATFORM_LIB_DEPS "-lxil -lc -lm -lmetal " CACHE STRING "")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
SET(CMAKE_AR "gcc-ar" CACHE STRING "")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_FINISH true)
link_directories(${LIBMETAL}/include/ ${LIBMETAL}/lib/)
set (CMAKE_FIND_ROOT_PATH ${LIBMETAL}/lib ${BSP}/lib )
include (cross-generic-gcc)
```
* We use cmake `find_path` and `find_library` to check if libmetal headers
and library are in the includes and library search paths. However,
for non-linux system, it doesn't work with `CMAKE_INCLUDE_PATH` and
`CMAKE_LIBRARY_PATH` variables, and thus, we need to specify those paths
in the toolchain file with `CMAKE_C_FLAGS` and `CMAKE_FIND_ROOT_PATH`.
* Compile the OpenAMP library:
```
$ mkdir -p build-openamp
$ cd build-openamp
$ BSP="/path/to/your_MicroBlaze_design_BSP/dir"
$ cmake <openamp_source> -DCMAKE_TOOLCHAIN_FILE=<toolchain_file> \
-DCMAKE_INCLUDE_PATH="$LIBMETAL/include;$BSP/include" \
-DCMAKE_LIBRARY_PATH="$LIBMETAL/lib/;BSP/lib" -DWITH_APPS=on
$ make VERBOSE=1 DESTDIR=$(pwd) install
```
The OpenAMP library will be built in `build/usr/local/lib` directory,
headers will be built in `build/usr/local/include` directory, and the
application executable will be built in `build/usr/local/bin` directory.
## How to build OpenAMP Linux Userspace echo Client for ZynqMP MPSoC
To test the MicroBlaze echo server we use an rpmsg-echo-ping client from
Linux running on the Application Processing Unit (APU) in PS. To run both
the echo server on the MicroBlaze in PL from PS DDR and a Linux echo
client on APU in PS the kernel device tree needs reserved-memory nodes
for the MicroBlaze text and data including vrings. A Yocto overlay
device tree example: openamp-linux-u-MicroBlaze.dtsi
Build the OpenAMP Linux userspace library and application via Yocto.
The open-amp and libmetal recipes are in this Yocto layer:
https://github.com/OpenAMP/meta-openamp
* Add the `meta-openamp` layer to your layers in your Yocto build project's
`bblayers.conf` file.
* Add `libmetal` and `open-amp` to your packages list. E.g. add `libmetal`
and `open-amp` to the `IMAGE_INSTALL_append` in the `local.conf` file.
* You can also add OpenAMP demos Linux applications packages to your Yocto
packages list. OpenAMP demo examples recipes are also in `meta-openamp`:
https://github.com/OpenAMP/meta-openamp/tree/master/recipes-openamp/openamp-examples
## Sample Microblaze DTSI
/ {
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
rproc_0_reserved: rproc@3ed000000 {
no-map;
reg = <0x0 0x3ed00000 0x0 0x1000000>;
};
microblaze_text_data: microblaze:@70000000 {
no-map;
reg = <0x0 0x70000000 0x0 0x80000>;
};
};
amba {
vring: vring@0 {
compatible = "vring_uio";
reg = <0x0 0x3ed40000 0x0 0x40000>;
};
shm0: shm@0 {
compatible = "shm_uio";
reg = <0x0 0x3ed20000 0x0 0x0100000>;
};
shm1: shm@1 {
compatible = "shm_uio";
reg = <0x0 0x3ee40000 0x0 0x0100000>;
};
ipi0: ipi@0 {
compatible = "ipi_uio";
reg = <0x0 0xff340000 0x0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <0 29 4>;
};
};
};

View File

@@ -0,0 +1,209 @@
/*
* Copyright (c) 2020 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**************************************************************************
* FILE NAME
*
* platform_info.c
*
* DESCRIPTION
*
* This file define platform specific data and implements APIs to set
* platform specific information for OpenAMP.
*
**************************************************************************/
#include <metal/atomic.h>
#include <metal/assert.h>
#include <metal/device.h>
#include <metal/irq.h>
#include <metal/utilities.h>
#include <openamp/rpmsg_virtio.h>
#include "platform_info.h"
#include "rsc_table.h"
#define SHARED_MEM_PA 0x3ED40000UL
#define SHARED_MEM_SIZE 0x100000UL
#define SHARED_BUF_OFFSET 0x8000UL
/*
* IPI information used by remoteproc operations.
*/
static struct remoteproc_priv rproc_priv = {
};
static struct remoteproc rproc_inst;
/* External functions */
extern int init_system(void);
extern void cleanup_system(void);
/*
* processor operations from MicroBlaze to a53. It defines
* notification operation and remote processor management operations.
*/
extern struct remoteproc_ops zynqmp_mb_a53_proc_ops;
/* RPMsg virtio shared buffer pool */
static struct rpmsg_virtio_shm_pool shpool;
static struct remoteproc *platform_create_proc(int proc_index, int rsc_index)
{
void *rsc_table;
int rsc_size;
int ret;
metal_phys_addr_t pa;
(void)proc_index;
rsc_table = get_resource_table(rsc_index, &rsc_size);
/* Initialize remoteproc instance */
if (!remoteproc_init(&rproc_inst, &zynqmp_mb_a53_proc_ops, &rproc_priv))
return NULL;
/* mmap resource table */
pa = (metal_phys_addr_t)rsc_table;
(void *)remoteproc_mmap(&rproc_inst, &pa,
NULL, rsc_size,
NORM_NSHARED_NCACHE | PRIV_RW_USER_RW,
&rproc_inst.rsc_io);
/* mmap shared memory */
pa = SHARED_MEM_PA;
(void *)remoteproc_mmap(&rproc_inst, &pa,
NULL, SHARED_MEM_SIZE,
NORM_NSHARED_NCACHE | PRIV_RW_USER_RW,
NULL);
/* parse resource table to remoteproc */
ret = remoteproc_set_rsc_table(&rproc_inst, rsc_table, rsc_size);
if (ret) {
xil_printf("Failed to initialize remoteproc\r\n");
remoteproc_remove(&rproc_inst);
return NULL;
}
/* dbg("%d:%s rsc_table= %p\r\n", __LINE__, __func__, rsc_table); */
xil_printf("Initialize remoteproc successfully.\r\n");
return &rproc_inst;
}
int platform_init(int argc, char *argv[], void **platform)
{
unsigned long proc_id = 0;
unsigned long rsc_id = 0;
struct remoteproc *rproc;
if (!platform) {
xil_printf("Failed to initialize platform,"
"NULL pointer to store platform data.\r\n");
return -EINVAL;
}
/* Initialize HW system components */
init_system();
if (argc >= 2) {
proc_id = strtoul(argv[1], NULL, 0);
}
if (argc >= 3) {
rsc_id = strtoul(argv[2], NULL, 0);
}
rproc = platform_create_proc(proc_id, rsc_id);
if (!rproc) {
xil_printf("Failed to create remoteproc device.\r\n");
return -EINVAL;
}
*platform = rproc;
return 0;
}
struct rpmsg_device *
platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index,
unsigned int role,
void (*rst_cb)(struct virtio_device *vdev),
rpmsg_ns_bind_cb ns_bind_cb)
{
struct remoteproc *rproc = platform;
struct rpmsg_virtio_device *rpmsg_vdev;
struct virtio_device *vdev;
void *shbuf;
struct metal_io_region *shbuf_io;
int ret;
rpmsg_vdev = metal_allocate_memory(sizeof(*rpmsg_vdev));
if (!rpmsg_vdev)
return NULL;
shbuf_io = remoteproc_get_io_with_pa(rproc, SHARED_MEM_PA);
if (!shbuf_io)
goto err1;
shbuf = metal_io_phys_to_virt(shbuf_io,
SHARED_MEM_PA + SHARED_BUF_OFFSET);
xil_printf("creating remoteproc virtio\r\n");
/* TODO: can we have a wrapper for the following two functions? */
vdev = remoteproc_create_virtio(rproc, vdev_index, role, rst_cb);
if (!vdev) {
xil_printf("failed remoteproc_create_virtio\r\n");
goto err1;
}
xil_printf("initializing rpmsg shared buffer pool\r\n");
/*
* Only RPMsg virtio master needs to initialize the shared buffers
* pool
*/
rpmsg_virtio_init_shm_pool(&shpool, shbuf,
(SHARED_MEM_SIZE - SHARED_BUF_OFFSET));
xil_printf("initializing rpmsg vdev\r\n");
/* RPMsg virtio slave can set shared buffers pool argument to NULL */
ret = rpmsg_init_vdev(rpmsg_vdev, vdev, ns_bind_cb,
shbuf_io,
&shpool);
if (ret) {
xil_printf("failed rpmsg_init_vdev\r\n");
goto err2;
}
xil_printf("initializing rpmsg vdev\r\n");
return rpmsg_virtio_get_rpmsg_device(rpmsg_vdev);
err2:
remoteproc_remove_virtio(rproc, vdev);
err1:
metal_free_memory(rpmsg_vdev);
return NULL;
}
int platform_poll(void *priv)
{
struct remoteproc *rproc = priv;
while (1) {
char *done_polling = (char *)POLL_SHM_LOCATION;
if (*done_polling) {
remoteproc_get_notification(rproc, RSC_NOTIFY_ID_ANY);
break;
}
}
return 0;
}
void platform_release_rpmsg_vdev(struct rpmsg_device *rpdev)
{
if (rpdev->
(void)rpdev;
}
void platform_cleanup(void *platform)
{
struct remoteproc *rproc = platform;
if (rproc)
remoteproc_remove(rproc);
cleanup_system();
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2020 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLATFORM_INFO_H_
#define PLATFORM_INFO_H_
#include <openamp/remoteproc.h>
#include <openamp/virtio.h>
#include <openamp/rpmsg.h>
#if defined __cplusplus
extern "C" {
#endif
/* MicroBlaze memory attributes. Depends on MB memory the design */
#define DEVICE_SHARED 0x00000001U /* device, shareable */
#define DEVICE_NONSHARED 0x00000010U /* device, non shareable */
#define NORM_NSHARED_NCACHE 0x00000008U /* Non cacheable non shareable */
#define NORM_SHARED_NCACHE 0x0000000CU /* Non cacheable shareable */
#define PRIV_RW_USER_RW (0x00000003U << 8U) /* Full Access */
#define POLL_SHM_LOCATION 0x3EE40000
#define POLL_STOP 0x1U
struct remoteproc_priv {
const char *ipi_name; /**< IPI device name */
const char *ipi_bus_name; /**< IPI bus name */
struct metal_device *ipi_dev; /**< pointer to IPI device */
struct metal_io_region *ipi_io; /**< pointer to IPI i/o region */
unsigned int ipi_chn_mask; /**< IPI channel mask */
atomic_int ipi_nokick;
};
/**
* platform_init - initialize the platform
*
* Initialize the platform.
*
* @argc: number of arguments
* @argv: array of the input arguments
* @platform: pointer to store the platform data pointer
*
* return 0 for success or negative value for failure
*/
int platform_init(int argc, char *argv[], void **platform);
/**
* platform_create_rpmsg_vdev - create rpmsg vdev
*
* Create rpmsg virtio device, and return the rpmsg virtio
* device pointer.
*
* @platform: pointer to the private data
* @vdev_index: index of the virtio device, there can more than one vdev
* on the platform.
* @role: virtio master or virtio slave of the vdev
* @rst_cb: virtio device reset callback
* @ns_bind_cb: rpmsg name service bind callback
*
* return pointer to the rpmsg virtio device
*/
struct rpmsg_device *
platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index,
unsigned int role,
void (*rst_cb)(struct virtio_device *vdev),
rpmsg_ns_bind_cb ns_bind_cb);
/**
* platform_poll - platform poll function
*
* @platform: pointer to the platform
*
* return negative value for errors, otherwise 0.
*/
int platform_poll(void *platform);
/**
* platform_release_rpmsg_vdev - release rpmsg virtio device
*
* @rpdev: pointer to the rpmsg device
*/
void platform_release_rpmsg_vdev(struct rpmsg_device *rpdev);
/**
* platform_cleanup - clean up the platform resource
*
* @platform: pointer to the platform
*/
void platform_cleanup(void *platform);
#if defined __cplusplus
}
#endif
#endif /* PLATFORM_INFO_H_ */

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2020 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* This file populates resource table for BM remote
* for use by the Linux Master
*/
#include <openamp/open_amp.h>
#include "rsc_table.h"
/* Place resource table in special ELF section */
#define __section_t(S) __attribute__((__section__(#S)))
#define __resource __section_t(.resource_table)
#define RPMSG_IPU_C0_FEATURES 1
#define NUM_VRINGS 0x02
#define VRING_ALIGN 0x1000
#define RING_TX 0x3ed40000
#define RING_RX 0x3ed44000
#define VRING_SIZE 256
#define NUM_TABLE_ENTRIES 1
struct remote_resource_table __resource resources = {
/* Version */
1,
/* NUmber of table entries */
NUM_TABLE_ENTRIES,
/* reserved fields */
{0, 0,},
/* Offsets of rsc entries */
{
offsetof(struct remote_resource_table, rpmsg_vdev),
},
/* Virtio device entry */
{
RSC_VDEV, VIRTIO_ID_RPMSG, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0,
NUM_VRINGS, {0, 0},
},
/* Vring rsc entry - part of vdev rsc entry */
{RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0},
{RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0},
};
void *get_resource_table(int rsc_id, int *len)
{
(void)rsc_id;
*len = sizeof(resources);
return &resources;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Resource table declarations. Resource table is placed in a separate
* section of a bare-metal binary or firmware. It's used to describe
* shared memory (virtIO devices) resources the remoteproc master should
* initialize and / or use to communicate with the firmware.
*/
#ifndef RSC_TABLE_H_
#define RSC_TABLE_H_
#include <stddef.h>
#include <openamp/open_amp.h>
#if defined __cplusplus
extern "C" {
#endif
#define NO_RESOURCE_ENTRIES 8
/* Resource table for the given remote */
struct __packed remote_resource_table {
unsigned int version;
unsigned int num;
unsigned int reserved[2];
unsigned int offset[NO_RESOURCE_ENTRIES];
/* rpmsg vdev entry */
struct fw_rsc_vdev rpmsg_vdev;
struct fw_rsc_vdev_vring rpmsg_vring0;
struct fw_rsc_vdev_vring rpmsg_vring1;
};
void *get_resource_table(int rsc_id, int *len);
#if defined __cplusplus
}
#endif
#endif /* RSC_TABLE_H_ */

View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2020 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**************************************************************************
* FILE NAME
*
* zynqmp_mb_a53_rproc.c
*
* DESCRIPTION
*
* OpenAMP remoteproc implementation for Xilinx MicroBlaze design
* example. The design instanciates Xilinx MicroBlaze soft proccesor
* in ZynqMP's programmable logic and uses processing system (PS)
* DDR memory for its text and data. The APU in PS runs Linux with
* reserved-memory nodes in its device tree toaccommodat the
* MicroBlaze text, data.
*
**************************************************************************/
#include <metal/atomic.h>
#include <metal/assert.h>
#include <metal/device.h>
#include <metal/irq.h>
#include <metal/utilities.h>
#include <openamp/rpmsg_virtio.h>
#include "platform_info.h"
static struct remoteproc *
zynqmp_mb_a53_proc_init(struct remoteproc *rproc, struct remoteproc_ops *ops,
void *arg)
{
struct remoteproc_priv *prproc = arg;
if (!rproc || !prproc || !ops)
return NULL;
rproc->priv = prproc;
rproc->ops = ops;
return rproc;
}
static inline void zynqmp_mb_a53_proc_remove(struct remoteproc *rproc)
{
(void)rproc;
}
static void *
zynqmp_mb_a53_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
metal_phys_addr_t *da, size_t size,
unsigned int attribute, struct metal_io_region **io)
{
struct remoteproc_mem *mem;
metal_phys_addr_t lpa, lda;
struct metal_io_region *tmpio;
lpa = *pa;
lda = *da;
if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS)
return NULL;
if (lpa == METAL_BAD_PHYS)
lpa = lda;
if (lda == METAL_BAD_PHYS)
lda = lpa;
mem = metal_allocate_memory(sizeof(*mem));
if (!mem)
return NULL;
tmpio = metal_allocate_memory(sizeof(*tmpio));
if (!tmpio) {
metal_free_memory(mem);
return NULL;
}
remoteproc_init_mem(mem, NULL, lpa, lda, size, tmpio);
/* va is the same as pa in this platform */
metal_io_init(tmpio, (void *)lpa, &mem->pa, size,
sizeof(metal_phys_addr_t) << 3, attribute, NULL);
remoteproc_add_mem(rproc, mem);
*pa = lpa;
*da = lda;
if (io) {
*io = tmpio;
} else {
metal_free_memory(tmpio);
metal_free_memory(mem);
return NULL;
}
return metal_io_phys_to_virt(tmpio, mem->pa);
}
static int zynqmp_mb_a53_proc_notify(struct remoteproc *rproc, uint32_t id)
{
(void)rproc;
(void)id;
if (!rproc)
return -1;
char *notify = (char *)POLL_SHM_LOCATION;
*notify = POLL_STOP;
return 0;
}
/*
* processor operations from mb to a53. It defines
* notification operation and remote processor management operations.
*/
struct remoteproc_ops zynqmp_mb_a53_proc_ops = {
.init = zynqmp_mb_a53_proc_init,
.remove = zynqmp_mb_a53_proc_remove,
.mmap = zynqmp_mb_a53_proc_mmap,
.notify = zynqmp_mb_a53_proc_notify,
.start = NULL,
.stop = NULL,
.shutdown = NULL,
};

View File

@@ -0,0 +1,19 @@
include(CheckSymbolExists)
collect (APP_COMMON_SOURCES helper.c)
set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_remote.ld")
set_property (GLOBAL PROPERTY APP_LINKER_OPT "-T\"${_linker_script}\"")
find_path(XIL_INCLUDE_DIR NAMES xparameters.h PATHS ${CMAKE_FIND_ROOT_PATH})
collect (PROJECT_INC_DIRS "${XIL_INCLUDE_DIR}")
find_library(LIBXIL_LIB NAMES xil PATHS ${CMAKE_FIND_ROOT_PATH})
get_filename_component(LIBXIL_LIB_DIR ${LIBXIL_LIB} DIRECTORY)
collect(PROJECT_LIB_DIRS ${LIBXIL_LIB_DIR})
collect(PROJECT_LIB_DEPS xil)
collect(PROJECT_LIB_DEPS c)
collect(PROJECT_LIB_DEPS m)

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2020 Xilinx, Inc. All rights reserved.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "xparameters.h"
#include "xil_exception.h"
#include "xil_printf.h"
#include <metal/sys.h>
#include "platform_info.h"
static void system_metal_logger(enum metal_log_level level,
const char *format, ...)
{
(void)level;
(void)format;
}
/* Main hw machinery initialization entry point, called from main()*/
/* return 0 on success */
int init_system(void)
{
int ret;
struct metal_init_params metal_param = {
.log_handler = system_metal_logger,
.log_level = METAL_LOG_INFO,
};
/* Low level abstraction layer for openamp initialization */
ret = metal_init(&metal_param);
return ret;
}
void cleanup_system(void)
{
metal_finish();
}

View File

@@ -0,0 +1,218 @@
/*******************************************************************/
/* */
/* This file is automatically generated by linker script generator.*/
/* */
/* Version: 2020.1.0 */
/* */
/* Copyright (c) 2010-2020 Xilinx, Inc. All rights reserved. */
/* */
/* Description : MicroBlaze Linker Script */
/* */
/*******************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x400;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x1800;
/* Define Memories in the system */
MEMORY
{
psu_ddr_0_HP0_AXI_BASENAME_MEM_0 : ORIGIN = 0x70000050, LENGTH = 0x7FEFFFB0
rsc_table_psu_ddr_S_AXI_BASEADDR : ORIGIN = 0x3ED00000, LENGTH = 0x00040000
}
/* Specify the default entry point to the program */
ENTRY(_start)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.vectors.reset 0x70000000 : {
KEEP (*(.vectors.reset))
}
.vectors.sw_exception 0x70000008 : {
KEEP (*(.vectors.sw_exception))
}
.vectors.interrupt 0x70000010 : {
KEEP (*(.vectors.interrupt))
}
.vectors.hw_exception 0x70000020 : {
KEEP (*(.vectors.hw_exception))
}
.text : {
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.init : {
KEEP (*(.init))
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.fini : {
KEEP (*(.fini))
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
PROVIDE(__DTOR_END__ = .);
PROVIDE(___DTORS_END___ = .);
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.sdata2 : {
. = ALIGN(8);
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
. = ALIGN(8);
__sdata2_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.data : {
. = ALIGN(4);
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
__data_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.got : {
*(.got)
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.got1 : {
*(.got1)
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.got2 : {
*(.got2)
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.eh_frame : {
*(.eh_frame)
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.jcr : {
*(.jcr)
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.gcc_except_table : {
*(.gcc_except_table)
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.sdata : {
. = ALIGN(8);
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.sbss (NOLOAD) : {
. = ALIGN(4);
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
. = ALIGN(8);
__sbss_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(8);
_heap = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
.stack (NOLOAD) : {
_stack_end = .;
. += _STACK_SIZE;
. = ALIGN(8);
_stack = .;
__stack = _stack;
} > psu_ddr_0_HP0_AXI_BASENAME_MEM_0
/* Linux must have reserved-memory node for this resource_table */
.resource_table 0x3ed20000 : {
. = ALIGN(4);
*(.resource_table)
} > rsc_table_psu_ddr_S_AXI_BASEADDR
_end = .;
}

View File

@@ -1,2 +1,6 @@
# tests presently do not support microblaze
if (MACHINE MATCHES ".*microblaze.*")
return()
endif (MACHINE MATCHES ".*microblaze.*")
add_subdirectory (msg)