From 31ffb4124719621f1d3bedd3bfe24d2c31eacef1 Mon Sep 17 00:00:00 2001 From: Ola Jeppsson Date: Thu, 21 Jan 2016 16:25:06 +0000 Subject: [PATCH] Add kernel mailbox interface test Kernel code here, will be included in official 'parallella-linux' when API:s have stabilized... https://github.com/olajep/parallella-linux/tree/wip-mailbox ``` Testing blocking wait with interrupts i: 00 from: 0x00000000 data: 0x00000000 i: 01 from: 0x00000000 data: 0x00000001 i: 02 from: 0x00000000 data: 0x00000002 i: 03 from: 0x00000000 data: 0x00000003 i: 04 from: 0x00000000 data: 0x00000004 i: 05 from: 0x00000000 data: 0x00000005 i: 06 from: 0x00000000 data: 0x00000006 i: 07 from: 0x00000000 data: 0x00000007 i: 08 from: 0x00000000 data: 0x00000008 i: 09 from: 0x00000000 data: 0x00000009 i: 10 from: 0x00000000 data: 0x0000000a i: 11 from: 0x00000000 data: 0x0000000b i: 12 from: 0x00000000 data: 0x0000000c i: 13 from: 0x00000000 data: 0x0000000d i: 14 from: 0x00000000 data: 0x0000000e i: 15 from: 0x00000000 data: 0x0000000f Reading 1000000 messages received: 1000000 errors: 0 time: 11.65s rate: 85808 msgs/s ``` Signed-off-by: Ola Jeppsson --- elink/sw/mailbox-test2/README.md | 5 + elink/sw/mailbox-test2/build.sh | 33 ++++++ elink/sw/mailbox-test2/run.sh | 12 ++ elink/sw/mailbox-test2/src/common.h | 13 +++ elink/sw/mailbox-test2/src/emain.c | 53 +++++++++ elink/sw/mailbox-test2/src/epiphany.h | 48 ++++++++ elink/sw/mailbox-test2/src/main.c | 151 ++++++++++++++++++++++++++ 7 files changed, 315 insertions(+) create mode 100644 elink/sw/mailbox-test2/README.md create mode 100755 elink/sw/mailbox-test2/build.sh create mode 100755 elink/sw/mailbox-test2/run.sh create mode 100644 elink/sw/mailbox-test2/src/common.h create mode 100644 elink/sw/mailbox-test2/src/emain.c create mode 100644 elink/sw/mailbox-test2/src/epiphany.h create mode 100644 elink/sw/mailbox-test2/src/main.c diff --git a/elink/sw/mailbox-test2/README.md b/elink/sw/mailbox-test2/README.md new file mode 100644 index 0000000..a850f8a --- /dev/null +++ b/elink/sw/mailbox-test2/README.md @@ -0,0 +1,5 @@ +# mailbox tests + +Kernel code here, will be included in official 'parallella-linux' +when API:s have stabilized... +https://github.com/olajep/parallella-linux/tree/wip-mailbox diff --git a/elink/sw/mailbox-test2/build.sh b/elink/sw/mailbox-test2/build.sh new file mode 100755 index 0000000..24e6269 --- /dev/null +++ b/elink/sw/mailbox-test2/build.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +ESDK=${EPIPHANY_HOME} +ELIBS="-L ${ESDK}/tools/host/lib" +EINCS="-I ${ESDK}/tools/host/include" +ELDF=${ESDK}/bsps/current/internal.ldf + +# Create the binaries directory +mkdir -p bin/ + +if [ -z "${CROSS_COMPILE+xxx}" ]; then +case $(uname -p) in + arm*) + # Use native arm compiler (no cross prefix) + CROSS_COMPILE= + ;; + *) + # Use cross compiler + CROSS_COMPILE="arm-linux-gnueabihf-" + ;; +esac +fi + +# Build HOST side application +${CROSS_COMPILE}gcc src/main.c -g -o bin/main.elf ${EINCS} ${ELIBS} -le-hal -le-loader -lpthread + +# Build DEVICE side program +OPT=3 +e-gcc -funroll-loops -g -T ${ELDF} -O${OPT} src/emain.c -o bin/emain.elf -le-lib + + diff --git a/elink/sw/mailbox-test2/run.sh b/elink/sw/mailbox-test2/run.sh new file mode 100755 index 0000000..d175ac1 --- /dev/null +++ b/elink/sw/mailbox-test2/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +SCRIPT=$(readlink -f "$0") +EXEPATH=$(dirname "$SCRIPT") + + +cd $EXEPATH/bin + +./main.elf + diff --git a/elink/sw/mailbox-test2/src/common.h b/elink/sw/mailbox-test2/src/common.h new file mode 100644 index 0000000..0c0b5d1 --- /dev/null +++ b/elink/sw/mailbox-test2/src/common.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#define STEP_ADDR 0x6000 +#define STOP_ADDR 0x6004 + +/* move to e-hal/e-lib when API is stabilized */ +struct e_message { + uint32_t from; + uint32_t data; +} __attribute__((packed)) __attribute__((aligned(8))); + diff --git a/elink/sw/mailbox-test2/src/emain.c b/elink/sw/mailbox-test2/src/emain.c new file mode 100644 index 0000000..6a21b89 --- /dev/null +++ b/elink/sw/mailbox-test2/src/emain.c @@ -0,0 +1,53 @@ +#include +#include + +#include "common.h" + +#define MAILBOX_ADDR 0x810F0730 +/* TODO: Move to e-lib */ +void e_send_message(uint32_t data) +{ + volatile struct e_message *mailbox = (struct e_message *) MAILBOX_ADDR; + struct e_message msg; + int i; + + msg.from = e_get_coreid(); + msg.data = data; + msg.from = data; + + /* FIXME: 64-bit burst writes to same address is broken in FPGA elink. + * For now resort to 32-bit messages */ + __asm__ __volatile__ ( + "str %[msg],[%[mailbox]]" + : + : [msg] "r" (msg), [mailbox] "r" (mailbox) + : "memory"); +} + +int main() +{ + volatile uint32_t *step = (uint32_t *) STEP_ADDR; + volatile uint32_t *stop = (uint32_t *) STOP_ADDR; + uint32_t prev_step = 0; + + int i; + + while (!(*stop)) { + while (prev_step == *step && !(*stop)) + ; + + if (*stop) + break; + + /* Create delay so host app have to wait */ + for (i = 0; i < 100000000; i++) + __asm__ __volatile__ ("nop" ::: "memory"); + + e_send_message(prev_step); + + prev_step++; + } + + for (i = 0; i < 1000000; i++) + e_send_message(prev_step++); +} diff --git a/elink/sw/mailbox-test2/src/epiphany.h b/elink/sw/mailbox-test2/src/epiphany.h new file mode 100644 index 0000000..4a68a6a --- /dev/null +++ b/elink/sw/mailbox-test2/src/epiphany.h @@ -0,0 +1,48 @@ +#ifndef EPIPHANY_H +#define EPIPHANY_H +#include + +/** Length of the Global shared memory region */ +#define GLOBAL_SHM_SIZE (4<<20) +#define SHM_LOCK_NAME "/eshmlock" + +#define SHM_MAGIC 0xabcdef00 + +typedef struct _EPIPHANY_ALLOC +{ + unsigned long size; + unsigned long flags; + unsigned long bus_addr; /* out */ + unsigned long phy_addr; /* out */ + unsigned long kvirt_addr; /* out */ + unsigned long uvirt_addr; /* out */ + unsigned long mmap_handle; /* Handle to use for mmap */ +} epiphany_alloc_t; + +struct epiphany_mailbox_msg { + __u32 from; + __u32 data; +} __attribute__((packed)); + +#define EPIPHANY_IOC_MAGIC 'k' + +#define E_IO(nr) _IO(EPIPHANY_IOC_MAGIC, nr) +#define E_IOR(nr, type) _IOR(EPIPHANY_IOC_MAGIC, nr, type) +#define E_IOW(nr, type) _IOW(EPIPHHANY_IOC_MAGIC, nr, type) +#define E_IOWR(nr, type) _IOWR(EPIPHANY_IOC_MAGIC, nr, type) + +/** + * If you add an IOC command, please update the + * EPIPHANY_IOC_MAXNR macro + */ + +#define EPIPHANY_IOC_GETSHM_CMD 24 +#define EPIPHANY_IOC_MAILBOX_READ_CMD 25 +#define EPIPHANY_IOC_MAILBOX_COUNT_CMD 26 +#define EPIPHANY_IOC_MAXNR 26 + +#define EPIPHANY_IOC_GETSHM E_IOWR(EPIPHANY_IOC_GETSHM_CMD, epiphany_alloc_t *) +#define EPIPHANY_IOC_MAILBOX_READ E_IOWR(EPIPHANY_IOC_MAILBOX_READ_CMD, struct epiphany_mailbox_msg) +#define EPIPHANY_IOC_MAILBOX_COUNT E_IO(EPIPHANY_IOC_MAILBOX_COUNT_CMD) + +#endif diff --git a/elink/sw/mailbox-test2/src/main.c b/elink/sw/mailbox-test2/src/main.c new file mode 100644 index 0000000..bfa1321 --- /dev/null +++ b/elink/sw/mailbox-test2/src/main.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include "epiphany.h" + +#include "common.h" + +/* TODO: Include in e-hal API */ +int e_mailbox_read(struct e_message *msg, int flags) +{ + int fd, rc; + struct epiphany_mailbox_msg kernel_msg; + + flags &= O_NONBLOCK; + + fd = open("/dev/epiphany", flags, O_RDONLY); + if (fd < 0) + return fd; + + rc = ioctl(fd, EPIPHANY_IOC_MAILBOX_READ, &kernel_msg); + if (rc) { + close(fd); + return rc; + } + +#if 0 + msg->from = kernel_msg.from; + msg->data = kernel_msg.data; +#else + /* work around FPGA Elink 64-bit burst bug + * Message can only be 32-bits for now so use lower bits for data + * and let sender be 0 */ + msg->from = 0; + msg->data = kernel_msg.from; +#endif + + close(fd); + + return 0; +} + +int e_mailbox_count() +{ + int fd, rc; + + fd = open("/dev/epiphany", 0, O_RDONLY); + if (fd < 0) + return fd; + + rc = ioctl(fd, EPIPHANY_IOC_MAILBOX_COUNT); + + close(fd); + return rc; +} + +int main(int argc, char *argv[]) +{ + unsigned rows, cols, i, count; + const uint32_t one = 1, zero = 0; + uint32_t step = 1; + e_platform_t platform; + e_epiphany_t dev; + int expected, received, errors; + double time, rate; + struct timespec start, stop; + struct e_message msg = { 0, 0 }; + + // initialize system, read platform params from + // default HDF. Then, reset the platform and + // get the actual system parameters. + e_init(NULL); + e_reset_system(); + + e_get_platform_info(&platform); + + //open the workgroup + rows = platform.rows; + cols = platform.cols; + e_open(&dev, 0, 0, rows, cols); + + //load the device program on the board + e_load_group("emain.elf", &dev, 0, 0, 1, 1, E_FALSE); + + + e_write(&dev, 0, 0, STOP_ADDR, &zero, sizeof(zero)); + e_write(&dev, 0, 0, STEP_ADDR, &zero, sizeof(zero)); + + e_start_group(&dev); + + /* Test blocking wait with interrupts */ + printf("Testing blocking wait with interrupts\n"); + for (i = 0; i < 16; i++) { + e_write(&dev, 0, 0, STEP_ADDR, &step, sizeof(step)); + step++; + /* Blocking wait while Epiphany performs dummy loop */ + e_mailbox_read(&msg, 0); + printf("i: %.2d from: 0x%08x data: 0x%08x\n", + i, msg.from, msg.data); + } + + e_write(&dev, 0, 0, STOP_ADDR, &one, sizeof(one)); + + + /* Test reading using count */ + + expected = 1000000; + received = 0; + errors = 0; + + printf("\nReading %d messages\n", expected); + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); + count = e_mailbox_count(); + while (count >= 0 && !errors && received < expected) { + if (!count) + sched_yield(); + + while (count--) { + if (!e_mailbox_read(&msg, 0)) + received++; + else + errors++; + } + count = e_mailbox_count(); + } + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &stop); + time = (double) (stop.tv_sec - start.tv_sec) + + (double) (stop.tv_nsec - start.tv_nsec) / 1000000000.0; + rate = (double) expected / time; + + printf("received: %d\terrors: %d\ttime: %3.2fs\trate: %d msgs/s\n", + received, errors, time, (int) rate); + + e_close(&dev); + e_finalize(); +}