diff --git a/.travis.yml b/.travis.yml index 5079bff0c..9b092e0fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,8 @@ env: - CMPLR=clang STATIC=YES - WINE=32 TEST=NO STATIC=YES - WINE=32 TEST=NO STATIC=NO - - RTEMS=4.10 TEST=NO - - RTEMS=4.9 TEST=NO + - RTEMS=4.10 TEST=YES + - RTEMS=4.9 TEST=YES addons: apt: packages: @@ -25,8 +25,8 @@ addons: - flex - texinfo - install-info + - qemu-system-x86 cache: directories: - $HOME/.cache -install: sh ci/travis-prepare.sh > configure/os/CONFIG_SITE.Common.RTEMS RTEMS_VERSION=$RTEMS -RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386 +RTEMS_BASE=/home/travis/.rtems EOF cat << EOF >> configure/CONFIG_SITE -CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386 +CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386-qemu +CROSS_COMPILER_RUNTEST_ARCHS += RTEMS-pc386-qemu EOF # find local qemu-system-i386 - export PATH="$HOME/.cache/qemu/usr/bin:$PATH" echo -n "Using QEMU: " type qemu-system-i386 || echo "Missing qemu" - EXTRA=RTEMS_QEMU_FIXUPS=YES fi make -j2 $EXTRA diff --git a/ci/travis-prepare.sh b/ci/travis-prepare.sh deleted file mode 100644 index fd8c6fb4b..000000000 --- a/ci/travis-prepare.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -set -e -x - -die() { - echo "$1" >&2 - exit 1 -} - -CURDIR="$PWD" - -QDIR="$HOME/.cache/qemu" - -if [ -n "$RTEMS" -a "$TEST" = "YES" ] -then - git clone --quiet --branch vme --depth 10 https://github.com/mdavidsaver/qemu.git "$HOME/.build/qemu" - cd "$HOME/.build/qemu" - - HEAD=`git log -n1 --pretty=format:%H` - echo "HEAD revision $HEAD" - - [ -e "$HOME/.cache/qemu/built" ] && BUILT=`cat "$HOME/.cache/qemu/built"` - echo "Cached revision $BUILT" - - if [ "$HEAD" != "$BUILT" ] - then - echo "Building QEMU" - git submodule --quiet update --init - - install -d "$HOME/.build/qemu/build" - cd "$HOME/.build/qemu/build" - - "$HOME/.build/qemu/configure" --prefix="$HOME/.cache/qemu/usr" --target-list=i386-softmmu --disable-werror - make -j2 - make install - - echo "$HEAD" > "$HOME/.cache/qemu/built" - fi -fi - -cd "$CURDIR" diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 4f0d0a465..9aff11c8c 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -385,7 +385,7 @@ endif # Generate a perl program to exec the real test binary. %.t: %$(EXE) $(TOOLS)/makeTestfile.pl @$(RM) $@ - $(PERL) $(TOOLS)/makeTestfile.pl $@ $< + $(PERL) $(TOOLS)/makeTestfile.pl $(T_A) $(EPICS_HOST_ARCH) $@ $< #--------------------------------------------------------------- # Generate header with version number from VCS diff --git a/configure/os/CONFIG.Common.RTEMS b/configure/os/CONFIG.Common.RTEMS index c22e37a66..214ba794d 100644 --- a/configure/os/CONFIG.Common.RTEMS +++ b/configure/os/CONFIG.Common.RTEMS @@ -27,9 +27,13 @@ ifneq ($(CONFIG),$(TOP)/configure) -include $(TOP)/configure/CONFIG_SITE.Common.RTEMS endif +#-------------------------------------------------- +# Set RTEMS_BSP from T_A if not already done +RTEMS_BSP ?= $(subst RTEMS-,,$(T_A)) + #------------------------------------------------------- # Pick up the RTEMS tool/path definitions from the RTEMS BSP directory. -include $(RTEMS_BASE)/$(RTEMS_TARGET_CPU)-rtems$(RTEMS_VERSION)/$(subst RTEMS-,,$(T_A))/Makefile.inc +include $(RTEMS_BASE)/$(RTEMS_TARGET_CPU)-rtems$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc include $(RTEMS_CUSTOM) include $(CONFIG.CC) diff --git a/configure/os/CONFIG.Common.RTEMS-at91rm9200ek b/configure/os/CONFIG.Common.RTEMS-at91rm9200ek index 6f5f97732..735c07bb5 100644 --- a/configure/os/CONFIG.Common.RTEMS-at91rm9200ek +++ b/configure/os/CONFIG.Common.RTEMS-at91rm9200ek @@ -9,5 +9,6 @@ # # All RTEMS targets use the same Makefile fragment # -RTEMS_TARGET_CPU=arm +RTEMS_BSP = at91rm9200ek +RTEMS_TARGET_CPU = arm include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-beatnik b/configure/os/CONFIG.Common.RTEMS-beatnik index aaf611638..aaa45e4c9 100644 --- a/configure/os/CONFIG.Common.RTEMS-beatnik +++ b/configure/os/CONFIG.Common.RTEMS-beatnik @@ -5,6 +5,7 @@ # All RTEMS targets use the same Makefile fragment # EXE = .elf +RTEMS_BSP = beatnik RTEMS_TARGET_CPU = powerpc GNU_TARGET = powerpc-rtems ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL diff --git a/configure/os/CONFIG.Common.RTEMS-gen68360 b/configure/os/CONFIG.Common.RTEMS-gen68360 index a6663afc2..0a8a6e85e 100644 --- a/configure/os/CONFIG.Common.RTEMS-gen68360 +++ b/configure/os/CONFIG.Common.RTEMS-gen68360 @@ -5,5 +5,6 @@ # # All RTEMS targets use the same Makefile fragment # -RTEMS_TARGET_CPU=m68k +RTEMS_BSP = gen68360 +RTEMS_TARGET_CPU = m68k include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mcp750 b/configure/os/CONFIG.Common.RTEMS-mcp750 index d834ad9ec..035e6eb36 100644 --- a/configure/os/CONFIG.Common.RTEMS-mcp750 +++ b/configure/os/CONFIG.Common.RTEMS-mcp750 @@ -5,5 +5,6 @@ # # All RTEMS targets use the same Makefile fragment # -RTEMS_TARGET_CPU=ppc +RTEMS_BSP = mcp750 +RTEMS_TARGET_CPU = ppc include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mvme167 b/configure/os/CONFIG.Common.RTEMS-mvme167 index a6663afc2..3651f966f 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme167 +++ b/configure/os/CONFIG.Common.RTEMS-mvme167 @@ -5,5 +5,6 @@ # # All RTEMS targets use the same Makefile fragment # -RTEMS_TARGET_CPU=m68k +RTEMS_BSP = mvme167 +RTEMS_TARGET_CPU = m68k include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mvme2100 b/configure/os/CONFIG.Common.RTEMS-mvme2100 index 0ae64c791..a8e8bf76e 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme2100 +++ b/configure/os/CONFIG.Common.RTEMS-mvme2100 @@ -5,6 +5,7 @@ # All RTEMS targets use the same Makefile fragment # EXE = .elf +RTEMS_BSP = mvme2100 RTEMS_TARGET_CPU = powerpc GNU_TARGET = powerpc-rtems ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL diff --git a/configure/os/CONFIG.Common.RTEMS-mvme2700 b/configure/os/CONFIG.Common.RTEMS-mvme2700 index 899fab17f..a5ad7fbf5 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme2700 +++ b/configure/os/CONFIG.Common.RTEMS-mvme2700 @@ -1,6 +1,7 @@ # # Author: Matt Rippa # +RTEMS_BSP = mvme2700 RTEMS_TARGET_CPU = powerpc ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL ARCH_DEP_CFLAGS += -DHAVE_PPCBUG diff --git a/configure/os/CONFIG.Common.RTEMS-mvme3100 b/configure/os/CONFIG.Common.RTEMS-mvme3100 index e94d46211..283e7d680 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme3100 +++ b/configure/os/CONFIG.Common.RTEMS-mvme3100 @@ -5,6 +5,7 @@ # All RTEMS targets use the same Makefile fragment # EXE = .elf +RTEMS_BSP = mvme3100 RTEMS_TARGET_CPU = powerpc GNU_TARGET = powerpc-rtems ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL diff --git a/configure/os/CONFIG.Common.RTEMS-mvme5500 b/configure/os/CONFIG.Common.RTEMS-mvme5500 index 44ef7ea3e..0329185bb 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme5500 +++ b/configure/os/CONFIG.Common.RTEMS-mvme5500 @@ -5,6 +5,7 @@ # All RTEMS targets use the same Makefile fragment # EXE = .elf +RTEMS_BSP = mvme5500 RTEMS_TARGET_CPU = powerpc GNU_TARGET = powerpc-rtems ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL diff --git a/configure/os/CONFIG.Common.RTEMS-pc386 b/configure/os/CONFIG.Common.RTEMS-pc386 index 92ef4ac22..8dfa7d2ba 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc386 +++ b/configure/os/CONFIG.Common.RTEMS-pc386 @@ -5,14 +5,15 @@ # # All RTEMS targets use the same Makefile fragment # -RTEMS_TARGET_CPU=i386 +RTEMS_BSP = pc386 +RTEMS_TARGET_CPU = i386 MUNCH_SUFFIX = .boot define MUNCH_CMD - $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< temp.bin + $(RM) $*.bin + $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $*.bin $(BIN2BOOT) $@ 0x00097E00 \ - $(PROJECT_RELEASE)/lib/start16.bin 0x00097C00 0 temp.bin 0x00100000 0 - rm -f temp.bin + $(PROJECT_RELEASE)/lib/start16.bin 0x00097C00 0 $*.bin 0x00100000 0 endef include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-pc386-qemu b/configure/os/CONFIG.Common.RTEMS-pc386-qemu new file mode 100644 index 000000000..684f01a19 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-pc386-qemu @@ -0,0 +1,11 @@ +# CONFIG.Common.RTEMS-pc386-qemu +# +# Definitions for the RTEMS-pc386-qemu target +# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc386-qemu +# +#------------------------------------------------------- + +# Include definitions from RTEMS-pc386 +include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386 + +RTEMS_QEMU_FIXUPS = YES diff --git a/configure/os/CONFIG.Common.RTEMS-psim b/configure/os/CONFIG.Common.RTEMS-psim index 230d72e1f..58ad72852 100644 --- a/configure/os/CONFIG.Common.RTEMS-psim +++ b/configure/os/CONFIG.Common.RTEMS-psim @@ -5,5 +5,6 @@ # # All RTEMS targets use the same Makefile fragment # -RTEMS_TARGET_CPU=ppc +RTEMS_BSP = psim +RTEMS_TARGET_CPU = ppc include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-uC5282 b/configure/os/CONFIG.Common.RTEMS-uC5282 index 6b0903e07..2cb215aca 100644 --- a/configure/os/CONFIG.Common.RTEMS-uC5282 +++ b/configure/os/CONFIG.Common.RTEMS-uC5282 @@ -5,6 +5,7 @@ # # All RTEMS targets use the same Makefile fragment # +RTEMS_BSP = uC5282 RTEMS_TARGET_CPU = m68k ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL diff --git a/configure/os/CONFIG_SITE.Common.RTEMS-pc386 b/configure/os/CONFIG_SITE.Common.RTEMS-pc386 deleted file mode 100644 index c772c44fc..000000000 --- a/configure/os/CONFIG_SITE.Common.RTEMS-pc386 +++ /dev/null @@ -1,3 +0,0 @@ -# -# Site-specific overrides for RTEMS-pc386 target -# diff --git a/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu new file mode 100644 index 000000000..027dcf4ab --- /dev/null +++ b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu @@ -0,0 +1,9 @@ +# CONFIG_SITE.Common.RTEMS-pc386-qemu +# +# Site-specific overrides for the RTEMS-pc386-qemu target +# + +# If you're building this architecture you _probably_ want to +# run the tests for it under QEMU, but if not you can turn +# them off here by commenting out this line: +CROSS_COMPILER_RUNTEST_ARCHS += RTEMS-pc386-qemu diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 3f98c6f06..90ceb77e4 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -19,6 +19,32 @@ --> +

RTEMS build configuration update, running tests under QEMU

+ +

This release includes the ability to run the EPICS unit tests built for a +special version of the RTEMS-pc386 target architecture on systems that have an +appropriate QEMU emulator installed (qemu-system-i386). It is also now +possible to create sub-architectures of RTEMS targets, whereas previously the +EPICS target architecture name had to be RTEMS-$(RTEMS_BSP).

+ +

The new target RTEMS-pc386-qemu builds binaries that can be run in +the qemu-system-i386 PC System emulator. This target is a derivative of +the original RTEMS-pc386 target but with additional software to build +an in-memory file-system, and some minor modifications to allow the unit tests +to work properly under QEMU. When this target is enabled, building any of the +make targets that cause the built-in self-tests to be run (such as +make runtests) will also run the tests for RTEMS using QEMU.

+ +

To allow the new 3-component RTEMS target name, the EPICS build system for +RTEMS was modified to allow a configure/os/CONFIG.Common.<arch> +file to set the RTEMS_BSP variable to inform the build what RTEMS BSP +to use. Previously this was inferred from the value of the T_A make +variable, but that prevents having multiple EPICS targets that build against the +same BSP. All the included RTEMS target configuration files have been updated; +build configuration files for out-of-tree RTEMS targets will continue to work as +the original rules are used to set RTEMS_BSP if it hasn't been set when +needed.

+

Link type enhancements

This release adds three new link types: "state", "debug" and "trace". The diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 37ec3da74..90ca9da35 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -175,6 +175,8 @@ testHarness_SRCS += epicsRunDbTests.c dbTestHarness_SRCS += $(testHarness_SRCS) dbTestHarness_SRCS_RTEMS += rtemsTestHarness.c +PROD_SRCS_RTEMS += rtemsTestData.c + PROD_vxWorks = dbTestHarness PROD_RTEMS = dbTestHarness @@ -182,6 +184,10 @@ TESTSPEC_vxWorks = dbTestHarness.munch; epicsRunDbTests TESTSPEC_RTEMS = dbTestHarness.boot; epicsRunDbTests TESTSCRIPTS_HOST += $(TESTS:%=%.t) +ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),) +TESTPROD_RTEMS = $(TESTPROD_HOST) +TESTSCRIPTS_RTEMS += $(TESTS:%=%.t) +endif include $(TOP)/configure/RULES @@ -193,3 +199,5 @@ devx$(DEP): $(COMMON_DIR)/xRecord.h scanIoTest$(DEP): $(COMMON_DIR)/xRecord.h xRecord$(DEP): $(COMMON_DIR)/xRecord.h +rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl + $(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES) diff --git a/src/ioc/db/test/dbStressLock.c b/src/ioc/db/test/dbStressLock.c index 376587975..03a8e8b54 100644 --- a/src/ioc/db/test/dbStressLock.c +++ b/src/ioc/db/test/dbStressLock.c @@ -228,6 +228,11 @@ MAIN(dbStressTest) testPlan(80+nworkers*3); +#if defined(__rtems__) + testSkip(80+nworkers*3, "Test assumes time sliced preempting scheduling"); + return testDone(); +#endif + priv = callocMustSucceed(nworkers, sizeof(*priv), "no memory"); testDiag("lock set stress test"); diff --git a/src/libCom/RTEMS/Makefile b/src/libCom/RTEMS/Makefile index 4c0b64c04..22a92733c 100644 --- a/src/libCom/RTEMS/Makefile +++ b/src/libCom/RTEMS/Makefile @@ -10,7 +10,11 @@ TOP=../../.. include $(TOP)/configure/CONFIG INC += epicsRtemsInitHooks.h +INC += epicsMemFs.h +ifeq ($(RTEMS_QEMU_FIXUPS),YES) +rtems_init_CPPFLAGS += -DQEMU_FIXUPS +endif rtemsCom_SRCS += rtems_init.c rtemsCom_SRCS += rtems_config.c rtemsCom_SRCS += rtems_netconfig.c @@ -18,6 +22,11 @@ rtemsCom_SRCS += rtems_util.c rtemsCom_SRCS += setBootConfigFromNVRAM.c rtemsCom_SRCS += epicsRtemsInitHookPre.c rtemsCom_SRCS += epicsRtemsInitHookPost.c +rtemsCom_SRCS += epicsMemFs.c + +ifeq ($(RTEMS_BSP),pc386) +rtemsCom_SRCS += ne2kpci.c +endif LIBRARY_RTEMS = rtemsCom diff --git a/src/libCom/RTEMS/epicsMemFs.c b/src/libCom/RTEMS/epicsMemFs.c new file mode 100644 index 000000000..4689d210f --- /dev/null +++ b/src/libCom/RTEMS/epicsMemFs.c @@ -0,0 +1,110 @@ +/*************************************************************************\ +* Copyright (c) 2014 Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "epicsMemFs.h" + +#ifndef PATH_MAX +# define PATH_MAX 100 +#endif + +int epicsMemFsLoad(const epicsMemFS *fs) +{ + char initdir[PATH_MAX]; + const epicsMemFile * const *fileptr = fs->files; + + if(getcwd(initdir, sizeof(initdir)-1)==NULL) { + perror("getcwd"); + return errno; + } + initdir[sizeof(initdir)-1] = '\0'; + + for(;*fileptr; fileptr++) { + const epicsMemFile *curfile = *fileptr; + int fd; + ssize_t ret; + size_t sofar; + const char * const *dir = curfile->directory; + /* jump back to the root each time, + * slow but simple. + */ + if(chdir(initdir)) { + perror("chdir"); + return errno; + } + + printf("-> /"); + + /* traverse directory tree, creating as necessary */ + for(;*dir; dir++) { + int ret; + if(**dir=='.') continue; /* ignore '.' and '..' */ + printf("%s/", *dir); + ret = chdir(*dir); + if(ret==-1 && errno==ENOENT) { + /* this directory doesn't exist */ + if(mkdir(*dir,0744)==-1) { + printf("\n"); + perror("mkdir"); + return errno; + } + if(chdir(*dir)==-1) { + printf("\n"); + perror("chdir2"); + return errno; + } + } else if(ret==-1) { + printf("\n"); + perror("chdir1"); + return errno; + } + } + + /* no file name creates an empty directory */ + if(!curfile->name) { + printf("\n"); + continue; + } + printf("%s", curfile->name); + + /* create or overwrite */ + fd = open(curfile->name, O_WRONLY|O_CREAT|O_TRUNC, 0644); + + if(fd==-1) { + printf("\n"); + perror("open"); + return errno; + } + + sofar = 0; + + while(sofarsize) { + ret = write(fd, curfile->data+sofar, curfile->size-sofar); + if(ret<=0) { + printf("\n"); + perror("write"); + return errno; + } + sofar += ret; + } + + close(fd); + printf(" - ok\n"); + } + + if(chdir(initdir)) + perror("chdir"); + + return 0; +} diff --git a/src/libCom/RTEMS/epicsMemFs.h b/src/libCom/RTEMS/epicsMemFs.h new file mode 100644 index 000000000..c57f4d793 --- /dev/null +++ b/src/libCom/RTEMS/epicsMemFs.h @@ -0,0 +1,24 @@ +/*************************************************************************\ +* Copyright (c) 2014 Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +#ifndef EPICSMEMFS_H +#define EPICSMEMFS_H + +#include + +typedef struct { + const char * const *directory; /* NULL terminated list of directories */ + const char *name; /* file name */ + const char *data; /* file contents */ + size_t size; /* size of file contents in bytes */ +} epicsMemFile; + +typedef struct { + const epicsMemFile * const *files; +} epicsMemFS; + +int epicsMemFsLoad(const epicsMemFS *fs); + +#endif // EPICSMEMFS_H diff --git a/src/libCom/RTEMS/epicsRtemsInitHooks.h b/src/libCom/RTEMS/epicsRtemsInitHooks.h index b7f09c100..4313f19e3 100644 --- a/src/libCom/RTEMS/epicsRtemsInitHooks.h +++ b/src/libCom/RTEMS/epicsRtemsInitHooks.h @@ -21,3 +21,5 @@ extern char *env_nfsMountPoint; */ int epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); int epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); +/* Return 0 if local file system was setup, or non-zero (will fall back to network */ +int epicsRtemsMountLocalFilesystem(char **argv); diff --git a/src/libCom/RTEMS/ne2kpci.c b/src/libCom/RTEMS/ne2kpci.c new file mode 100644 index 000000000..909d885f1 --- /dev/null +++ b/src/libCom/RTEMS/ne2kpci.c @@ -0,0 +1,58 @@ +/*************************************************************************\ +* Copyright (c) 2015 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Wrapper around the ISA ne2000 driver to support detection of the PCI variant. + * Can be used with the ne2k_pci device provided by QEMU. + * + * eg. "qemu-system-i386 ... -net nic,model=ne2k_pci" + */ + +#include +#include +#include +#include +#include + +/* The plain ISA driver attach() + * which doesn't (can't?) do any test to see if + * the HW is really present + */ +extern int +rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach); + +int +rtems_ne2kpci_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) +{ + uint8_t irq; + uint32_t bar0; + int B, D, F, ret; + printk("Probing for NE2000 on PCI (aka. Realtek 8029)\n"); + + if(pci_find_device(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029, 0, &B, &D, &F)) + { + printk("Not found\n"); + return 0; + } + + printk("Found %d:%d.%d\n", B, D, F); + + ret = pci_read_config_dword(B, D, F, PCI_BASE_ADDRESS_0, &bar0); + ret|= pci_read_config_byte(B, D, F, PCI_INTERRUPT_LINE, &irq); + + if(ret || (bar0&PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_IO) + { + printk("Failed reading card config\n"); + return 0; + } + + config->irno = irq; + config->port = bar0&PCI_BASE_ADDRESS_IO_MASK; + + printk("Using port=0x%x irq=%u\n", (unsigned)config->port, config->irno); + + return rtems_ne_driver_attach(config, attach); +} diff --git a/src/libCom/RTEMS/rtems_init.c b/src/libCom/RTEMS/rtems_init.c index 82871da0d..7dbf2594f 100644 --- a/src/libCom/RTEMS/rtems_init.c +++ b/src/libCom/RTEMS/rtems_init.c @@ -33,6 +33,7 @@ #include #include +#include "epicsVersion.h" #include "epicsThread.h" #include "epicsTime.h" #include "epicsExit.h" @@ -42,9 +43,12 @@ #include "osiUnistd.h" #include "iocsh.h" #include "osdTime.h" +#include "epicsMemFs.h" #include "epicsRtemsInitHooks.h" +#define RTEMS_VERSION_INT VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, 0, 0) + /* * Prototypes for some functions not in header files */ @@ -138,6 +142,31 @@ mustMalloc(int size, const char *msg) # include #endif +const epicsMemFS *epicsRtemsFSImage __attribute__((weak)); +const epicsMemFS *epicsRtemsFSImage = (void*)&epicsRtemsFSImage; + +/* hook to allow app specific FS setup */ +int +epicsRtemsMountLocalFilesystem(char **argv) __attribute__((weak)); +int +epicsRtemsMountLocalFilesystem(char **argv) +{ + if(epicsRtemsFSImage==(void*)&epicsRtemsFSImage) + return -1; /* no FS image provided. */ + else if(epicsRtemsFSImage==NULL) + return 0; /* no FS image provided, but none is needed. */ + else { + printf("***** Using compiled in file data *****\n"); + if (epicsMemFsLoad(epicsRtemsFSImage) != 0) { + printf("Can't unpack tar filesystem\n"); + return -1; + } else { + argv[1] = "/"; + return 0; + } + } +} + static int initialize_local_filesystem(char **argv) { @@ -146,7 +175,9 @@ initialize_local_filesystem(char **argv) extern char _FlashSize[] __attribute__((weak)); argv[0] = rtems_bsdnet_bootp_boot_file_name; - if (_FlashSize && (_DownloadLocation || _FlashBase)) { + if (epicsRtemsMountLocalFilesystem(argv)==0) { + return 1; /* FS setup successful */ + } else if (_FlashSize && (_DownloadLocation || _FlashBase)) { extern char _edata[]; size_t flashIndex = _edata - _DownloadLocation; char *header = _FlashBase + flashIndex; @@ -596,6 +627,7 @@ Init (rtems_task_argument ignored) } printf("\n***** Initializing network *****\n"); rtems_bsdnet_initialize_network(); + printf("\n***** Setting up file system *****\n"); initialize_remote_filesystem(argv, initialize_local_filesystem(argv)); fixup_hosts(); @@ -666,3 +698,37 @@ Init (rtems_task_argument ignored) epicsThreadSleep(1.0); epicsExit(result); } + +#if defined(QEMU_FIXUPS) +/* Override some hooks (weak symbols) + * if BSP defaults aren't configured for running tests. + */ + + +/* Ensure that stdio goes to serial (so it can be captured) */ +#if defined(__i386__) && !USE_COM1_AS_CONSOLE +#include +extern int BSPPrintkPort; +void bsp_predriver_hook(void) +{ + BSPConsolePort = BSP_CONSOLE_PORT_COM1; + BSPPrintkPort = BSP_CONSOLE_PORT_COM1; +} +#endif + +/* reboot immediately when done. */ +#if defined(__i386__) && BSP_PRESS_KEY_FOR_RESET +void bsp_cleanup(void) +{ +#if RTEMS_VERSION_INT>=VERSION_INT(4,10,0,0) + void bsp_reset(); + bsp_reset(); +#else + rtemsReboot(); +#endif +} +#endif + +#endif /* QEMU_FIXUPS */ + +int cexpdebug __attribute__((weak)); diff --git a/src/libCom/RTEMS/rtems_netconfig.c b/src/libCom/RTEMS/rtems_netconfig.c index 832a6646b..d0c500c92 100644 --- a/src/libCom/RTEMS/rtems_netconfig.c +++ b/src/libCom/RTEMS/rtems_netconfig.c @@ -36,11 +36,19 @@ static struct rtems_bsdnet_ifconfig loopback_config = { * application directory and make the appropriate changes. */ #if defined(__i386__) + +extern int +rtems_ne2kpci_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach); +static struct rtems_bsdnet_ifconfig ne2k_driver_config = { + "ne2", /* name */ + rtems_ne2kpci_driver_attach, /* attach function */ + &loopback_config, /* link to next interface */ +}; extern int rtems_fxp_attach (struct rtems_bsdnet_ifconfig *, int); static struct rtems_bsdnet_ifconfig fxp_driver_config = { "fxp1", /* name */ rtems_fxp_attach, /* attach function */ - &loopback_config, /* link to next interface */ + &ne2k_driver_config, /* link to next interface */ }; extern int rtems_3c509_driver_attach (struct rtems_bsdnet_ifconfig *, int); static struct rtems_bsdnet_ifconfig e3c509_driver_config = { diff --git a/src/libCom/misc/testMain.h b/src/libCom/misc/testMain.h index 4db72c39e..7c4d9b29b 100644 --- a/src/libCom/misc/testMain.h +++ b/src/libCom/misc/testMain.h @@ -27,7 +27,13 @@ * } */ -#if defined(vxWorks) || defined(__rtems__) +#if defined(__rtems__) + #ifdef __cplusplus + #define MAIN(prog) extern "C" int prog(void); extern "C" int main() __attribute__((weak, alias(#prog))); extern "C" int prog(void) + #else + #define MAIN(prog) int prog(); int main() __attribute__((weak, alias(#prog))); int prog() + #endif +#elif defined(vxWorks) #ifdef __cplusplus #define MAIN(prog) extern "C" int prog(void) #else diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index c78bdbb9f..faf97b718 100755 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -14,11 +14,18 @@ PROD_LIBS += Com PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32 PROD_SYS_LIBS_solaris += socket nsl +PROD_SRCS_RTEMS += rtemsTestData.c + +ifeq ($(EPICS_HOST_ARCH),$(T_A)) +# skip except for host arch due to custom .plt + TESTPROD_HOST += epicsUnitTestTest epicsUnitTestTest_SRCS += epicsUnitTestTest.c # Not much point running this on vxWorks or RTEMS... TESTS += epicsUnitTestTest +endif + TESTPROD_HOST += epicsTypesTest epicsTypesTest_SRCS += epicsTypesTest.cpp testHarness_SRCS += epicsTypesTest.cpp @@ -237,6 +244,10 @@ TESTSPEC_vxWorks = libComTestHarness.munch; epicsRunLibComTests TESTSPEC_RTEMS = libComTestHarness.boot; epicsRunLibComTests TESTSCRIPTS_HOST += $(TESTS:%=%.t) +ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),) +TESTPROD_RTEMS = $(TESTPROD_HOST) +TESTSCRIPTS_RTEMS += $(filter-out epicsUnitTestTest.t, $(TESTS:%=%.t)) +endif # The following are not test programs, they measure performance. diff --git a/src/libCom/test/rtemsTestData.c b/src/libCom/test/rtemsTestData.c new file mode 100644 index 000000000..7b68976c5 --- /dev/null +++ b/src/libCom/test/rtemsTestData.c @@ -0,0 +1,6 @@ +#include "epicsMemFs.h" + +/* no local files needed for these tests, + * so skip local FS setup + */ +const epicsMemFS *epicsRtemsFSImage = NULL; diff --git a/src/std/filters/test/Makefile b/src/std/filters/test/Makefile index 6e6ad79c6..d6d9973f6 100644 --- a/src/std/filters/test/Makefile +++ b/src/std/filters/test/Makefile @@ -62,6 +62,8 @@ testHarness_SRCS += epicsRunFilterTests.c filterTestHarness_SRCS += $(testHarness_SRCS) filterTestHarness_SRCS_RTEMS += rtemsTestHarness.c +PROD_SRCS_RTEMS += rtemsTestData.c + PROD_vxWorks = filterTestHarness PROD_RTEMS = filterTestHarness @@ -69,6 +71,10 @@ TESTSPEC_vxWorks = filterTestHarness.munch; epicsRunFilterTests TESTSPEC_RTEMS = filterTestHarness.boot; epicsRunFilterTests TESTSCRIPTS_HOST += $(TESTS:%=%.t) +ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),) +TESTPROD_RTEMS = $(TESTPROD_HOST) +TESTSCRIPTS_RTEMS += $(TESTS:%=%.t) +endif include $(TOP)/configure/RULES @@ -78,3 +84,6 @@ dbndTest$(DEP): $(COMMON_DIR)/xRecord.h syncTest$(DEP): $(COMMON_DIR)/xRecord.h arrRecord$(DEP): $(COMMON_DIR)/arrRecord.h arrTest$(DEP): $(COMMON_DIR)/arrRecord.h + +rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl + $(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES) diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index 99fe4d9eb..3fcc6bdeb 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -138,6 +138,8 @@ testHarness_SRCS += epicsRunRecordTests.c recordTestHarness_SRCS += $(testHarness_SRCS) recordTestHarness_SRCS_RTEMS += rtemsTestHarness.c +PROD_SRCS_RTEMS += rtemsTestData.c + PROD_vxWorks = recordTestHarness PROD_RTEMS = recordTestHarness @@ -145,5 +147,12 @@ TESTSPEC_vxWorks = recordTestHarness.munch; epicsRunRecordTests TESTSPEC_RTEMS = recordTestHarness.boot; epicsRunRecordTests TESTSCRIPTS_HOST += $(TESTS:%=%.t) +ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),) +TESTPROD_RTEMS = $(TESTPROD_HOST) +TESTSCRIPTS_RTEMS += $(TESTS:%=%.t) +endif include $(TOP)/configure/RULES + +rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl + $(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES) diff --git a/src/tools/Makefile b/src/tools/Makefile index c7594ccbe..00e83ecba 100644 --- a/src/tools/Makefile +++ b/src/tools/Makefile @@ -51,6 +51,7 @@ PERL_SCRIPTS += mkmf.pl PERL_SCRIPTS += munch.pl PERL_SCRIPTS += replaceVAR.pl PERL_SCRIPTS += tap-to-junit-xml.pl +PERL_SCRIPTS += epicsMakeMemFs.pl PERL_SCRIPTS += useManifestTool.pl PERL_SCRIPTS += genVersionHeader.pl diff --git a/src/tools/epicsMakeMemFs.pl b/src/tools/epicsMakeMemFs.pl new file mode 100644 index 000000000..a97074e0e --- /dev/null +++ b/src/tools/epicsMakeMemFs.pl @@ -0,0 +1,83 @@ +#!/usr/bin/env perl +# + +use File::Basename; + +use strict; + +my $outfile = shift; +my $varname = shift; + +open(my $DST, '>', $outfile) or die "Failed to open $outfile"; + +print $DST < +EOF + +my $N = 0; + +for my $fname (@ARGV) { + print "<- $fname\n"; + my $realfname = $fname; + + # strip leading "../" "./" or "/" + while ($fname =~ /^\.*\/(.*)$/) { $fname = $1; } + + my $file = basename($fname); + my @dirs = split('/', dirname($fname)); + + print $DST "/* begin $realfname */\nstatic const char * const file_${N}_dir[] = {"; + for my $dpart (@dirs) { + print $DST "\"$dpart\", "; + } + print $DST "NULL};\nstatic const char file_${N}_data[] = {\n "; + + open(my $SRC, '<', $realfname) or die "Failed to open $realfname"; + binmode($SRC); + + my $buf; + my $total = 0; + while (my $num = read($SRC, $buf, 32)) { + if($total != 0) { + print $DST ",\n "; + } + $total += $num; + my $out = join(",",map(ord,split(//,$buf))); + print $DST "$out"; + } + + close($SRC); + + print $DST < target.t executable +# target-arch and host-arch are EPICS build target names (eg. linux-x86) # target.t is the name of the Perl script to generate # executable is the name of the file the script runs use strict; -my ($target, $exe) = @ARGV; +my ($TA, $HA, $target, $exe) = @ARGV; +my $exec; + +# Use WINE to run windows target executables on non-windows host +if( $TA =~ /^win32-x86/ && $HA !~ /^win/ ) { + # new deb. derivatives have wine32 and wine64 + # older have wine and wine64 + # prefer wine32 if present + my $wine32 = "/usr/bin/wine32"; + $wine32 = "/usr/bin/wine" if ! -x $wine32; + $exec = "$wine32 $exe"; +} elsif( $TA =~ /^windows-x64/ && $HA !~ /^win/ ) { + $exec = "wine64 $exe"; + +# Run pc386 test harness w/ QEMU +} elsif( $TA =~ /^RTEMS-pc386-qemu$/ ) { + $exec = "qemu-system-i386 -m 64 -no-reboot -serial stdio -display none -net nic,model=ne2k_pci -net user,restrict=yes -kernel $exe"; + +# Explicitly fail for other RTEMS targets +} elsif( $TA =~ /^RTEMS-/ ) { + die "$0: I don't know how to create scripts for testing $TA on $HA\n"; + +} else { + $exec = "./$exe"; +} open(my $OUT, '>', $target) or die "Can't create $target: $!\n"; print $OUT <