diff --git a/.ci b/.ci index 7d9d42662..d675de24e 160000 --- a/.ci +++ b/.ci @@ -1 +1 @@ -Subproject commit 7d9d4266292d22f73c41ec5c73b6eab4f810f400 +Subproject commit d675de24e6a2be018f6ff1dc35618c16dd621727 diff --git a/.gitattributes b/.gitattributes index d71c782e0..5221674ea 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,22 @@ .appveyor/ export-ignore .appveyor.yml export-ignore README export-subst + +#Which files need CRLF handling +# default to automatic +* text=auto + +# batch script parser on windows requires CRLF +*.bat text eol=crlf + +# extensions for scripts which may be executable via. "#!..." must have LF +*.pl text eol=lf +*.plt text eol=lf +*.sh text eol=lf +*.cmd text eol=lf +# .cmd in unexpanded templates +*.cmd@* text eol=lf +# executable scripts w/o extensions +modules/ca/src/client/S99caRepeater@ text eol=lf +modules/libcom/src/log/S99logServer@ text eol=lf +startup/EpicsHostArch text eol=lf diff --git a/.github/workflows/ci-scripts-build.yml b/.github/workflows/ci-scripts-build.yml index 75dc48c91..b9b3a0c12 100644 --- a/.github/workflows/ci-scripts-build.yml +++ b/.github/workflows/ci-scripts-build.yml @@ -43,7 +43,9 @@ jobs: BCFG: ${{ matrix.configuration }} WINE: ${{ matrix.wine }} RTEMS: ${{ matrix.rtems }} + RTEMS_TARGET: ${{ matrix.rtems_target }} EXTRA: ${{ matrix.extra }} + TEST: ${{ matrix.test }} strategy: fail-fast: false matrix: @@ -78,17 +80,70 @@ jobs: extra: "CMD_CXXFLAGS=-std=c++11" name: "Ub-20 clang-10 C++11" + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-pc686-qemu + test: NO + name: "Ub-20 gcc-9 + RT-5.1 pc686" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-beatnik + test: NO + name: "Ub-20 gcc-9 + RT-5.1 beatnik" + + # Only build one RTEMS target per CPU family + # unless it's running the tests + # + # - os: ubuntu-20.04 + # cmp: gcc + # configuration: default + # rtems: "5" + # rtems_target: RTEMS-mvme3100 + # test: NO + # name: "Ub-20 gcc-9 + RT-5.1 mvme3100" + # + # - os: ubuntu-20.04 + # cmp: gcc + # configuration: default + # rtems: "5" + # rtems_target: RTEMS-qoriq_e500 + # test: NO + # name: "Ub-20 gcc-9 + RT-5.1 qoriq_e500" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-xilinx_zynq_a9_qemu + test: NO + name: "Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-uC5282 + test: NO + name: "Ub-20 gcc-9 + RT-5.1 uC5282" + - os: ubuntu-20.04 cmp: gcc configuration: default rtems: "4.10" name: "Ub-20 gcc-9 + RT-4.10" + rtems_target: RTEMS-pc386-qemu - os: ubuntu-20.04 cmp: gcc configuration: default rtems: "4.9" name: "Ub-20 gcc-9 + RT-4.9" + rtems_target: RTEMS-pc386-qemu - os: ubuntu-16.04 cmp: gcc-4.8 @@ -175,6 +230,7 @@ jobs: with: name: tapfiles ${{ matrix.name }} path: '**/O.*/*.tap' + if-no-files-found: ignore - name: Collect and show test results if: ${{ always() }} run: python .ci/cue.py -T 5M test-results diff --git a/configure/CONFIG b/configure/CONFIG index fab3c245f..df454b29b 100644 --- a/configure/CONFIG +++ b/configure/CONFIG @@ -16,6 +16,10 @@ ifneq ($(wildcard $(TOP)/configure/CONFIG_BASE_VERSION),) CONFIG = $(TOP)/configure BASE_TOP=YES else + ifneq ($(origin EPICS_BASE),file) + # Essential for the EPICS build system, see convertRelease.pl + $(error EPICS_BASE must be set in a configure/RELEASE file) + endif CONFIG ?= $(EPICS_BASE)/configure endif @@ -62,6 +66,9 @@ include $(CONFIG)/os/CONFIG.$(EPICS_HOST_ARCH).Common RELEASE_TOPS := $(shell $(CONVERTRELEASE) -T $(TOP) releaseTops) ifdef T_A + # Information from the target's compiler + # + -include $(EPICS_BASE)/cfg/TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A) # Cross compile specific definitions # diff --git a/configure/CONFIG.gnuCommon b/configure/CONFIG.gnuCommon index 79e20a6ef..b7740fc94 100644 --- a/configure/CONFIG.gnuCommon +++ b/configure/CONFIG.gnuCommon @@ -50,14 +50,13 @@ CODE_LDFLAGS += $(ASAN_LDFLAGS_$(ENABLE_ASAN)) PIPE_CFLAGS_YES_YES = -pipe PIPE_CFLAGS = $(PIPE_CFLAGS_$(GCC_PIPE)_$(GNU)) -PIPE_CXXFLAGS = $(PIPE_CFLAGS) STATIC_LDFLAGS_YES = -static STATIC_LDFLAGS_NO = SHRLIB_CFLAGS = -fPIC -SHRLIB_LDFLAGS = -shared -fPIC -LOADABLE_SHRLIB_LDFLAGS = -shared -fPIC +SHRLIB_LDFLAGS = -shared -fPIC -Wl,-h$@ +LOADABLE_SHRLIB_LDFLAGS = -shared -fPIC -Wl,-h$@ GNU_LDLIBS_YES = -lgcc diff --git a/configure/CONFIG_BASE b/configure/CONFIG_BASE index 03d0ff7be..4b15e4cdc 100644 --- a/configure/CONFIG_BASE +++ b/configure/CONFIG_BASE @@ -31,10 +31,12 @@ endif # BASE_TOP # Where to find the installed build tools # Windows does not like commands with relative paths starting ../ # so TOOLS must be an absolute path, although Perl scripts are OK. -# FIND_TOOL is for scripts run before the build reaches src/tools. +# FIND_TOOL is for scripts run before the build reaches src/tools +# and must also work in submodules when EPICS_BASE is not built. TOOLS = $(abspath $(EPICS_BASE_HOST_BIN)) -FIND_TOOL = $(firstword $(wildcard $(TOOLS)/$(1) $(EPICS_BASE)/src/tools/$(1))) +FIND_TOOL = $(firstword $(wildcard $(TOOLS)/$(1) \ + $(TOP)/src/tools/$(1)) $(EPICS_BASE)/src/tools/$(1)) #--------------------------------------------------------------- # EPICS Base build tools and tool flags diff --git a/configure/CONFIG_BASE_VERSION b/configure/CONFIG_BASE_VERSION index b0c57b763..efa0afee7 100644 --- a/configure/CONFIG_BASE_VERSION +++ b/configure/CONFIG_BASE_VERSION @@ -48,15 +48,15 @@ EPICS_VERSION = 7 EPICS_REVISION = 0 # EPICS_MODIFICATION must be a number >=0 and <256 -EPICS_MODIFICATION = 5 +EPICS_MODIFICATION = 6 # EPICS_PATCH_LEVEL must be a number (win32 resource file requirement) # Not included in the official EPICS version number if zero -EPICS_PATCH_LEVEL = 1 +EPICS_PATCH_LEVEL = 0 # Immediately after an official release the EPICS_PATCH_LEVEL is incremented # and the -DEV suffix is added (similar to the Maven -SNAPSHOT versions) -EPICS_DEV_SNAPSHOT=-DEV +EPICS_DEV_SNAPSHOT= # No changes should be needed below here diff --git a/configure/CONFIG_CA_VERSION b/configure/CONFIG_CA_VERSION index af570b0e7..ce95a0ad3 100644 --- a/configure/CONFIG_CA_VERSION +++ b/configure/CONFIG_CA_VERSION @@ -1,12 +1,12 @@ # Version number for the Channel Access API and shared library EPICS_CA_MAJOR_VERSION = 4 -EPICS_CA_MINOR_VERSION = 13 -EPICS_CA_MAINTENANCE_VERSION = 9 +EPICS_CA_MINOR_VERSION = 14 +EPICS_CA_MAINTENANCE_VERSION = 0 # Development flag, set to zero for release versions -EPICS_CA_DEVELOPMENT_FLAG = 1 +EPICS_CA_DEVELOPMENT_FLAG = 0 # Immediately after a release the MAINTENANCE_VERSION # will be incremented and the DEVELOPMENT_FLAG set to 1 diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index 825725973..316f971d7 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -71,6 +71,8 @@ INSTALL_DBD = $(INSTALL_LOCATION)/dbd INSTALL_DB = $(INSTALL_LOCATION)/db INSTALL_CONFIG = $(INSTALL_LOCATION)/configure +FINAL_LOCATION = $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION)) + # Directory for OS independant build created files COMMON_DIR = ../O.Common @@ -142,9 +144,10 @@ BUILDLIB_SUFFIX = $(BUILDLIB_SUFFIX_$(SHARED_LIBRARIES)) #-------------------------------------------------- # vpath directories POSIX_YES = os/posix +OS_IMPL_DIRS = $(if $(OS_API),os/$(OS_CLASS)-$(OS_API),) os/$(OS_CLASS) GENERIC_SRC_DIRS = .. $(SRC_DIRS) OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ - $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default )) + $(addprefix $(dir)/, $(OS_IMPL_DIRS) $(POSIX_$(POSIX)) os/default )) CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default )) ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS) @@ -257,7 +260,7 @@ OPT_CXXFLAGS = $(OPT_CXXFLAGS_$($(BUILD_CLASS)_OPT)) # Static build flags STATIC_CFLAGS = $(STATIC_CFLAGS_$(STATIC_BUILD)) -STATIC_CXXCFLAGS = $(STATIC_CXXFLAGS_$(STATIC_BUILD)) +STATIC_CXXFLAGS = $(STATIC_CXXFLAGS_$(STATIC_BUILD)) STATIC_LDFLAGS = $(STATIC_LDFLAGS_$(STATIC_BUILD)) STATIC_LDLIBS = $(STATIC_LDLIBS_$(STATIC_BUILD)) @@ -294,7 +297,7 @@ CFLAGS = $($(BUILD_CLASS)_CFLAGS) $(POSIX_CFLAGS) $(OPT_CFLAGS)\ CXXFLAGS = $($(BUILD_CLASS)_CXXFLAGS) $(POSIX_CXXFLAGS) $(OPT_CXXFLAGS)\ $(DEBUG_CXXFLAGS) $(PIPE_CFLAGS) $(WARN_CXXFLAGS) $(TARGET_CXXFLAGS)\ $(USR_CXXFLAGS) $(CMD_CXXFLAGS) $(ARCH_DEP_CXXFLAGS) $(CODE_CXXFLAGS)\ - $(STATIC_CXXCFLAGS) $(OP_SYS_CXXFLAGS) $(LIBRARY_SRC_CFLAGS) + $(STATIC_CXXFLAGS) $(OP_SYS_CXXFLAGS) $(LIBRARY_SRC_CFLAGS) LDFLAGS = $(OPT_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(CMD_LDFLAGS)\ $(POSIX_LDFLAGS) $(ARCH_DEP_LDFLAGS) $(DEBUG_LDFLAGS) $(OP_SYS_LDFLAGS)\ diff --git a/configure/CONFIG_DATABASE_VERSION b/configure/CONFIG_DATABASE_VERSION index 2205a5386..348a69b11 100644 --- a/configure/CONFIG_DATABASE_VERSION +++ b/configure/CONFIG_DATABASE_VERSION @@ -1,12 +1,12 @@ # Version number for the database APIs and shared library EPICS_DATABASE_MAJOR_VERSION = 3 -EPICS_DATABASE_MINOR_VERSION = 19 -EPICS_DATABASE_MAINTENANCE_VERSION = 1 +EPICS_DATABASE_MINOR_VERSION = 20 +EPICS_DATABASE_MAINTENANCE_VERSION = 0 # Development flag, set to zero for release versions -EPICS_DATABASE_DEVELOPMENT_FLAG = 1 +EPICS_DATABASE_DEVELOPMENT_FLAG = 0 # Immediately after a release the MAINTENANCE_VERSION # will be incremented and the DEVELOPMENT_FLAG set to 1 diff --git a/configure/CONFIG_LIBCOM_VERSION b/configure/CONFIG_LIBCOM_VERSION index 96f25ebaa..76a5a5fcf 100644 --- a/configure/CONFIG_LIBCOM_VERSION +++ b/configure/CONFIG_LIBCOM_VERSION @@ -1,12 +1,12 @@ # Version number for the libcom APIs and shared library EPICS_LIBCOM_MAJOR_VERSION = 3 -EPICS_LIBCOM_MINOR_VERSION = 19 -EPICS_LIBCOM_MAINTENANCE_VERSION = 1 +EPICS_LIBCOM_MINOR_VERSION = 20 +EPICS_LIBCOM_MAINTENANCE_VERSION = 0 # Development flag, set to zero for release versions -EPICS_LIBCOM_DEVELOPMENT_FLAG = 1 +EPICS_LIBCOM_DEVELOPMENT_FLAG = 0 # Immediately after a release the MAINTENANCE_VERSION # will be incremented and the DEVELOPMENT_FLAG set to 1 diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index 26ed2fb8d..d7d869a7e 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -17,9 +17,8 @@ # Currently Supporting: # cygwin-x86 (cygwin compiler used for host builds) # cygwin-x86_64 (cygwin compiler used for host builds) -# darwin-ppc (PowerPC based Apple running OSX) -# darwin-ppcx86 (Universal binaries for both CPUs) -# darwin-x86 (Intel based Apple running OSX) +# darwin-aarch64 (M1 based Apple using CLANG compiler) +# darwin-x86 (Intel based Apple using CLANG compiler) # freebsd-x86 (GNU compiler used for host builds) # freebsd-x86_64 (GNU compiler used for host builds) # linux-aarch64 (GNU compiler used for host builds) @@ -62,16 +61,8 @@ # ios-arm (darwin-x86 host) # ios-386 (darwin-x86 host) -# linux-386 (linux-x86 host) -# linux-486 (linux-x86 host) -# linux-586 (linux-x86 host) -# linux-686 (linux-x86 host) # linux-arm (linux-x86 or -x86_64 host) # linux-aarch64 (linux-x86_64 host) -# linux-athlon (linux-x86 host) -# linux-cris (Axis GNU crosscompiler on linux-x86 host) -# linux-cris_v10 (Axis GNU crosscompiler on linux-x86 host) -# linux-cris_v32 (Axis GNU crosscompiler on linux-x86 host) # linux-microblaze # linux-xscale_be # vxWorks-486 @@ -85,18 +76,20 @@ # vxWorks-ppc604_altivec # vxWorks-mpc8540 # vxWorks-mpc8548 -# RTEMS-at91rm9200ek +# RTEMS-beagleboneblack # RTEMS-beatnik -# RTEMS-gen68360 -# RTEMS-mcp750 -# RTEMS-mvme167 # RTEMS-mvme2100 # RTEMS-mvme2700 # RTEMS-mvme3100 # RTEMS-mvme5500 -# RTEMS-pc386 -# RTEMS-psim +# RTEMS-pc386 (RTEMS 4) +# RTEMS-pc386-qemu (RTEMS 4) +# RTEMS-pc686 (RTEMS 5) +# RTEMS-pc686-qemu (RTEMS 5) +# RTEMS-qoriq_e500 # RTEMS-uC5282 +# RTEMS-xilinx-zynq-a9_qemu +# RTEMS-xilinx_zynq_zedboard # win32-x86-mingw (linux-x86 or -x86_64 host) # @@ -104,7 +97,6 @@ # Definitions in configure/os/CONFIG_SITE..Common # may override this setting. CROSS_COMPILER_TARGET_ARCHS= -#CROSS_COMPILER_TARGET_ARCHS=vxWorks-ppc32 # If only some of your host architectures can compile the # above CROSS_COMPILER_TARGET_ARCHS specify those host @@ -151,6 +143,14 @@ CROSS_WARN=YES # different location then uncomment and set this. #INSTALL_LOCATION= +# The location from which files placed in INSTALL_LOCATION will actually run. +# This path is compiled into executables, and so should be an absolute. +# May be used to achieve the effect of autotools. eg. +# ./configure --prefix= +# make DESTDIR= +# Defaults to the absolute expansion of $(INSTALL_LOCATION) +#FINAL_LOCATION= + # Use POSIX thread priority scheduling (if available). # Must be either YES or NO USE_POSIX_THREAD_PRIORITY_SCHEDULING = YES diff --git a/configure/Makefile b/configure/Makefile index f48278dd3..ba77d5089 100644 --- a/configure/Makefile +++ b/configure/Makefile @@ -15,7 +15,8 @@ include $(TOP)/configure/CONFIG TOOLS = $(TOP)/src/tools CONFIGS += $(subst ../,,$(wildcard ../CONFIG*)) -CONFIGS += $(subst ../,,$(wildcard ../os/CONFIG*)) +CONFIGS += $(subst ../,,$(wildcard ../os/CONFIG.*)) +CONFIGS += $(subst ../,,$(wildcard ../os/CONFIG_SITE.*)) CONFIGS += $(subst ../,,$(wildcard ../RELEASE*)) CONFIGS += $(subst ../,,$(wildcard ../RULES*)) @@ -29,5 +30,9 @@ CFG += CONFIG_CA_VERSION CFG += CONFIG_DATABASE_MODULE CFG += CONFIG_DATABASE_VERSION +CFG += TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A) + include $(TOP)/configure/RULES +TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A): toolchain.c + $(PREPROCESS.cpp) diff --git a/configure/os/CONFIG.Common.RTEMS b/configure/os/CONFIG.Common.RTEMS index 1319a7b50..b7a42d137 100644 --- a/configure/os/CONFIG.Common.RTEMS +++ b/configure/os/CONFIG.Common.RTEMS @@ -28,12 +28,13 @@ ifneq ($(CONFIG),$(TOP)/configure) endif #-------------------------------------------------- -# Set RTEMS_BSP from T_A if not already done +# Set RTEMS_BSP and GNU_TARGET if not already done RTEMS_BSP ?= $(subst RTEMS-,,$(T_A)) +GNU_TARGET ?= $(RTEMS_TARGET_CPU)-rtems #------------------------------------------------------- # Pick up the RTEMS tool/path definitions from the RTEMS BSP directory. -include $(RTEMS_BASE)/$(RTEMS_TARGET_CPU)-rtems$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc +include $(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc include $(RTEMS_CUSTOM) include $(CONFIG.CC) @@ -41,7 +42,7 @@ include $(CONFIG.CC) # RTEMS cross-development tools CC = $(RTEMS_TOOLS)/bin/$(CC_FOR_TARGET) $(GCCSPECS) -fasm CCC = $(RTEMS_TOOLS)/bin/$(CXX) -CPP = $(RTEMS_TOOLS)/bin/$(CC_FOR_TARGET) -x c -E +CPP = $(RTEMS_TOOLS)/bin/$(CC_FOR_TARGET) -x c -E $(GCCSPECS) AR = $(RTEMS_TOOLS)/bin/$(AR_FOR_TARGET) LD = $(RTEMS_TOOLS)/bin/$(LD_FOR_TARGET) -r @@ -62,7 +63,7 @@ CFLAGS = $($(BUILD_CLASS)_CFLAGS) $(POSIX_CFLAGS) $(OPT_CFLAGS)\ CXXFLAGS = $($(BUILD_CLASS)_CXXFLAGS) $(POSIX_CXXFLAGS) $(OPT_CXXFLAGS)\ $(DEBUG_CXXFLAGS) $(PIPE_CFLAGS) $(WARN_CXXFLAGS) $(TARGET_CXXFLAGS)\ $(USR_CXXFLAGS) $(CMD_CXXFLAGS) $(ARCH_DEP_CXXFLAGS) $(CODE_CXXFLAGS)\ - $(STATIC_CXXCFLAGS) $(OP_SYS_CXXFLAGS) $(LIBRARY_SRC_CFLAGS) + $(STATIC_CXXFLAGS) $(OP_SYS_CXXFLAGS) $(LIBRARY_SRC_CFLAGS) LDFLAGS = $(OPT_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(CMD_LDFLAGS)\ $(POSIX_LDFLAGS) $(ARCH_DEP_LDFLAGS) $(DEBUG_LDFLAGS) $(OP_SYS_LDFLAGS)\ @@ -95,20 +96,39 @@ MODEXT=.obj OS_CLASS = RTEMS #-------------------------------------------------- -# Operating system flags -OP_SYS_LDLIBS += -lrtemsCom -lc -lrtemscpu -lCom -lnfs -lm -OP_SYS_LDFLAGS += $(CPU_CFLAGS) -u Init \ +# Operating system compile & link flags +OP_SYS_CFLAGS += -D__LINUX_ERRNO_EXTENSIONS__ + +OP_SYS_CFLAGS_NET_yes = -DRTEMS_LEGACY_STACK +OP_SYS_CFLAGS += $(OP_SYS_CFLAGS_NET_$(RTEMS_HAS_NETWORKING)) + +ifeq ($(RTEMS_HAS_POSIX_API),yes) +POSIX_CPPFLAGS = -D_GNU_SOURCE -D_DEFAULT_SOURCE +endif + +OP_SYS_LDLIBS_posix_NET_yes = -ltftpfs -lnfs -lz -ltelnetd +OP_SYS_LDLIBS_posix_NET_no = -ltftpfs -lbsd -lz +OP_SYS_LDLIBS_score_NET_yes = -lnfs +OP_SYS_LDLIBS_score_NET_no = -lnfs +OP_SYS_LDLIBS += -lrtemsCom -lCom +OP_SYS_LDLIBS += $(OP_SYS_LDLIBS_$(OS_API)_NET_$(RTEMS_HAS_NETWORKING)) +OP_SYS_LDLIBS += -lrtemscpu -lc -lm + +OP_SYS_LDFLAGS_posix = -u POSIX_Init +OP_SYS_LDFLAGS_score = -u Init \ $(PROJECT_RELEASE)/lib/no-dpmem.rel \ $(PROJECT_RELEASE)/lib/no-mp.rel \ $(PROJECT_RELEASE)/lib/no-part.rel \ $(PROJECT_RELEASE)/lib/no-signal.rel \ $(PROJECT_RELEASE)/lib/no-rtmon.rel +OP_SYS_LDFLAGS += $(CPU_CFLAGS) $(OP_SYS_LDFLAGS_$(OS_API)) +# Settings for GeSys MOD_SYS_LDFLAGS += $(CPU_CFLAGS) -Wl,-r -nostdlib # Do not link against libraries which are part of the Generic Image GESYS_LIBS += -lgcc -GESYS_LIBS += -lc -lm -lrtemscpu -lrtemsbsp -lrtems++ -lbspExt +GESYS_LIBS += -lc -lm -lrtemscpu -lrtemsbsp -lrtems++ GESYS_LIBS += -lcexp -ltecla_r -lspencer_regexp -lpmelf -lpmbfd GESYS_LIBS += -lnfs -ltelnetd -lrtems-gdb-stub diff --git a/configure/os/CONFIG.Common.RTEMS-at91rm9200ek b/configure/os/CONFIG.Common.RTEMS-at91rm9200ek deleted file mode 100644 index 735c07bb5..000000000 --- a/configure/os/CONFIG.Common.RTEMS-at91rm9200ek +++ /dev/null @@ -1,14 +0,0 @@ -# -# CONFIG.Common.RTEMS-at91rm9200ek -# Author: Ralf Hartmann -# BESSY -# Ralf.Hartmann@bessy.de -# -# Atmel AT91RM9200-EK evaluation kit -# using the AT91RM9200 ARM9-based 32-bit RISC microcontroller -# -# All RTEMS targets use the same Makefile fragment -# -RTEMS_BSP = at91rm9200ek -RTEMS_TARGET_CPU = arm -include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-beagleboneblack b/configure/os/CONFIG.Common.RTEMS-beagleboneblack new file mode 100644 index 000000000..4b6107b05 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-beagleboneblack @@ -0,0 +1,18 @@ +# +# CONFIG.Common.RTEMS-beaglebineblack +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = beagleboneblack +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/beagleboneblack/lib/ + +include $(CONFIG)/os/CONFIG.Common.RTEMS + + + diff --git a/configure/os/CONFIG.Common.RTEMS-beatnik b/configure/os/CONFIG.Common.RTEMS-beatnik index aaa45e4c9..b133fd489 100644 --- a/configure/os/CONFIG.Common.RTEMS-beatnik +++ b/configure/os/CONFIG.Common.RTEMS-beatnik @@ -8,14 +8,16 @@ EXE = .elf RTEMS_BSP = beatnik RTEMS_TARGET_CPU = powerpc GNU_TARGET = powerpc-rtems -ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL +# optimization trouble in postfix.c +ARCH_DEP_CFLAGS += -DRTEMS_HAS_ALTIVEC +#will use bootp +#ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL ARCH_DEP_CFLAGS += -DHAVE_MOTLOAD ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot +MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX)) define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ endef diff --git a/configure/os/CONFIG.Common.RTEMS-gen68360 b/configure/os/CONFIG.Common.RTEMS-gen68360 deleted file mode 100644 index 0a8a6e85e..000000000 --- a/configure/os/CONFIG.Common.RTEMS-gen68360 +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -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 deleted file mode 100644 index 035e6eb36..000000000 --- a/configure/os/CONFIG.Common.RTEMS-mcp750 +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -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 deleted file mode 100644 index 3651f966f..000000000 --- a/configure/os/CONFIG.Common.RTEMS-mvme167 +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -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 a8e8bf76e..930b33bad 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme2100 +++ b/configure/os/CONFIG.Common.RTEMS-mvme2100 @@ -11,8 +11,6 @@ GNU_TARGET = powerpc-rtems ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL ARCH_DEP_CFLAGS += -DHAVE_PPCBUG -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems @@ -21,6 +19,7 @@ define MUNCH_CMD $(PROJECT_RELEASE)/lib/bootloader.o \ --just-symbols=$< \ -b binary rtems.gz \ + --no-warn-mismatch \ -T $(PROJECT_RELEASE)/lib/ppcboot.lds \ -Map $<.map rm -f rtems.gz diff --git a/configure/os/CONFIG.Common.RTEMS-mvme2700 b/configure/os/CONFIG.Common.RTEMS-mvme2700 index a5ad7fbf5..0ee8ac862 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme2700 +++ b/configure/os/CONFIG.Common.RTEMS-mvme2700 @@ -1,7 +1,7 @@ # # Author: Matt Rippa # -RTEMS_BSP = mvme2700 +RTEMS_BSP = mvme2307 RTEMS_TARGET_CPU = powerpc ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL ARCH_DEP_CFLAGS += -DHAVE_PPCBUG @@ -15,11 +15,10 @@ define MUNCH_CMD $(PROJECT_RELEASE)/lib/bootloader.o \ --just-symbols=$< \ -b binary rtems.gz \ + --no-warn-mismatch \ -T $(PROJECT_RELEASE)/lib/ppcboot.lds \ -Map $<.map rm -f rtems.gz endef -OP_SYS_LDLIBS += -lbspExt - include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mvme3100 b/configure/os/CONFIG.Common.RTEMS-mvme3100 index 283e7d680..2cbf49a84 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme3100 +++ b/configure/os/CONFIG.Common.RTEMS-mvme3100 @@ -13,8 +13,6 @@ ARCH_DEP_CFLAGS += -DHAVE_MOTLOAD ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ diff --git a/configure/os/CONFIG.Common.RTEMS-mvme5500 b/configure/os/CONFIG.Common.RTEMS-mvme5500 index 0329185bb..a240a298a 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme5500 +++ b/configure/os/CONFIG.Common.RTEMS-mvme5500 @@ -14,13 +14,9 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 ARCH_DEP_CFLAGS += -DBSP_NVRAM_BASE_ADDR=0xf1110000 -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ endef -OP_SYS_LDLIBS += -lbspExt - include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-pc386 b/configure/os/CONFIG.Common.RTEMS-pc386 index 8dfa7d2ba..9fc518d6b 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc386 +++ b/configure/os/CONFIG.Common.RTEMS-pc386 @@ -1,12 +1,13 @@ +# CONFIG.Common.RTEMS-pc386 # -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment +# Definitions for the RTEMS-pc386 target, RTEMS 4.x only +# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc386 # +#------------------------------------------------------- + RTEMS_BSP = pc386 RTEMS_TARGET_CPU = i386 +GNU_TARGET = i386-rtems MUNCH_SUFFIX = .boot define MUNCH_CMD @@ -22,3 +23,10 @@ include $(CONFIG)/os/CONFIG.Common.RTEMS # Put text segment where it will work with etherboot # OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000 + +# This check must appear after the above include +ifeq ($(RTEMS_VERSION),5) + $(info *** This target is not compatible with the configured RTEMS version.) + $(info *** Build the RTEMS-pc686 (-qemu) target for RTEMS 5.x) + $(error Can't continue) +endif diff --git a/configure/os/CONFIG.Common.RTEMS-pc386-qemu b/configure/os/CONFIG.Common.RTEMS-pc386-qemu index 684f01a19..07bf30e7c 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc386-qemu +++ b/configure/os/CONFIG.Common.RTEMS-pc386-qemu @@ -6,6 +6,7 @@ #------------------------------------------------------- # Include definitions from RTEMS-pc386 +# For Tests overwrite it with pc686 include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386 RTEMS_QEMU_FIXUPS = YES diff --git a/configure/os/CONFIG.Common.RTEMS-pc686 b/configure/os/CONFIG.Common.RTEMS-pc686 new file mode 100644 index 000000000..882a2f3cb --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-pc686 @@ -0,0 +1,39 @@ +# CONFIG.Common.RTEMS-pc686 +# +# Definitions for the RTEMS-pc686 target, RTEMS 5.x only +# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc686 +# +#------------------------------------------------------- +# +# Author: W. Eric Norum +# Canadian Light Source +# eric@cls.usask.ca +# +# All RTEMS targets use the same Makefile fragment +# +RTEMS_BSP = pc686 +RTEMS_TARGET_CPU = i386 +GNU_TARGET = i386-rtems + +MUNCH_SUFFIX = .boot +define MUNCH_CMD + $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@ +endef + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/pc686/lib/ + +include $(CONFIG)/os/CONFIG.Common.RTEMS + +# +# Put text segment where it will work with etherboot +# +OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000 + + +# This check must appear after the above include +ifneq ($(RTEMS_VERSION),5) + $(info *** This target is not compatible with the configured RTEMS version.) + $(info *** Build the RTEMS-pc386 (-qemu) target for RTEMS 4.x) + $(error Can't continue) +endif diff --git a/configure/os/CONFIG.Common.RTEMS-pc686-qemu b/configure/os/CONFIG.Common.RTEMS-pc686-qemu new file mode 100644 index 000000000..1de543a30 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-pc686-qemu @@ -0,0 +1,11 @@ +# CONFIG.Common.RTEMS-pc686-qemu +# +# Definitions for the RTEMS-pc686-qemu target +# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc686-qemu +# +#------------------------------------------------------- + +# Include definitions from RTEMS-pc686 +include $(CONFIG)/os/CONFIG.Common.RTEMS-pc686 + +RTEMS_QEMU_FIXUPS = YES diff --git a/configure/os/CONFIG.Common.RTEMS-psim b/configure/os/CONFIG.Common.RTEMS-psim deleted file mode 100644 index 58ad72852..000000000 --- a/configure/os/CONFIG.Common.RTEMS-psim +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# University of Saskatchewan -# eric.norum@usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -RTEMS_BSP = psim -RTEMS_TARGET_CPU = ppc -include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-qoriq_e500 b/configure/os/CONFIG.Common.RTEMS-qoriq_e500 new file mode 100644 index 000000000..7f5c42e8e --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-qoriq_e500 @@ -0,0 +1,48 @@ +# +# CONFIG.Common.RTEMS-qoriq_e500 +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +EXE = .elf +RTEMS_BSP = qoriq_e500 +RTEMS_TARGET_CPU = powerpc +GNU_TARGET = powerpc-rtems +# optimization trouble in postfix.c +ARCH_DEP_CFLAGS += -DRTEMS_HAS_ALTIVEC +#will use bootp +#ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL + +#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 +#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 + +#netbsdlib +#ARCH_DEP_CFLAGS += -I$(RTEMS_BASE)/powerpc-rtems5/qoriq_e500/lib/include + +#OP_SYS_LDLIBS += -lbspExt #does not use posix stuff ... want to ignore +OP_SYS_LDLIBS += -Wl,--gc-sections +#ARCH_DEP_LDFLAGS = -mcpu=8540 -meabi -msdata=sysv -mstrict-align -mspe -mabi=spe -mfloat-gprs=double +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/powerpc-rtems5/qoriq_e500/lib + +MUNCH_SUFFIX = .img +MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX)) +define MUNCH_CMD + $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ + gzip -9 -f $@ + $(RTEMS_TOOLS)/bin/mkimage.py -A ppc -O linux -T kernel -a 0x4000 -e 0x4000 -n $* -d $@.gz $*.img +endef + +include $(CONFIG)/os/CONFIG.Common.RTEMS + +RTEMSSYMS=$(PRODNAME:%$(EXE)=%.sym) +RTEMSIMGS=$(PRODNAME:%$(EXE)=%.bin) +INSTALL_RTEMSSYMS=$(RTEMSSYMS:%=$(INSTALL_BIN)/%) +INSTALL_RTEMSIMGS=$(RTEMSIMGS:%=$(INSTALL_BIN)/%) + +%.sym: %$(EXE) + $(XSYMS) $^ $@ + +%.bin: %$(EXE) + $(OBJCOPY) -Obinary $^ $@ + +#PRODTARGETS+=$(INSTALL_RTEMSSYMS) $(INSTALL_RTEMSIMGS) diff --git a/configure/os/CONFIG.Common.RTEMS-uC5282 b/configure/os/CONFIG.Common.RTEMS-uC5282 index 2cb215aca..c0cdaff74 100644 --- a/configure/os/CONFIG.Common.RTEMS-uC5282 +++ b/configure/os/CONFIG.Common.RTEMS-uC5282 @@ -9,6 +9,10 @@ RTEMS_BSP = uC5282 RTEMS_TARGET_CPU = m68k ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL +# Hopefully a temporary fix: +ARCH_DEP_CXXFLAGS_5 = -std=c++98 +ARCH_DEP_CXXFLAGS += $(ARCH_DEP_CXXFLAGS_$(RTEMS_VERSION)) + MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@ diff --git a/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu new file mode 100644 index 000000000..83b518b69 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu @@ -0,0 +1,20 @@ +# +# CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = xilinx_zynq_a9_qemu +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +#use dhcp/bootp +ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_a9_qemu/lib/ + + +include $(CONFIG)/os/CONFIG.Common.RTEMS + diff --git a/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard new file mode 100644 index 000000000..bac33eb91 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard @@ -0,0 +1,19 @@ +# +# CONFIG.Common.RTEMS-xilinx_zynq_zedboard +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = xilinx_zynq_zedboard +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_zedboard/lib/ + + +include $(CONFIG)/os/CONFIG.Common.RTEMS + + + diff --git a/configure/os/CONFIG.Common.darwin-ppc b/configure/os/CONFIG.Common.darwin-ppc deleted file mode 100644 index 7ac704314..000000000 --- a/configure/os/CONFIG.Common.darwin-ppc +++ /dev/null @@ -1,14 +0,0 @@ -# CONFIG.Common.darwin-ppc -# -# This file is maintained by the build community. -# -# Definitions for darwin-ppc target builds -# Sites may override these definitions in CONFIG_SITE.Common.darwin-ppc -#------------------------------------------------------- - -# -# To build universal binaries, configure ARCH_CLASS -# in the file CONFIG_SITE.Common.darwin-ppc - -# Include definitions common to all Darwin targets -include $(CONFIG)/os/CONFIG.darwinCommon.darwinCommon diff --git a/configure/os/CONFIG.Common.darwin-ppcx86 b/configure/os/CONFIG.Common.darwin-ppcx86 deleted file mode 100644 index 12107944f..000000000 --- a/configure/os/CONFIG.Common.darwin-ppcx86 +++ /dev/null @@ -1,14 +0,0 @@ -# CONFIG.Common.darwin-ppcx86 -# -# This file is maintained by the build community. -# -# Definitions for Darwin universal PowerPC + x86 target builds -# Sites may override these definitions in CONFIG_SITE.Common.darwin-ppcx86 -#------------------------------------------------------- - -# -# To build universal binaries, configure ARCH_CLASS -# in the file CONFIG_SITE.Common.darwin-ppcx86 - -# Include definitions common to all Darwin targets -include $(CONFIG)/os/CONFIG.darwinCommon.darwinCommon diff --git a/configure/os/CONFIG.Common.linux-386 b/configure/os/CONFIG.Common.linux-386 deleted file mode 100644 index a224ff328..000000000 --- a/configure/os/CONFIG.Common.linux-386 +++ /dev/null @@ -1,21 +0,0 @@ -# CONFIG.Common.linux-386 -# -# This file is maintained by the build community. -# -# Definitions for linux-386 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-386 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -ARCH_DEP_CFLAGS = -march=i386 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i386-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-386 file, e.g. GNU_TARGET=i386-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-486 b/configure/os/CONFIG.Common.linux-486 deleted file mode 100644 index 79b533015..000000000 --- a/configure/os/CONFIG.Common.linux-486 +++ /dev/null @@ -1,19 +0,0 @@ -# CONFIG.Common.linux-486 -# -# Definitions for linux-486 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-486 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -ARCH_DEP_CFLAGS = -march=i486 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i486-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-486 file, e.g. GNU_TARGET=i486-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-586 b/configure/os/CONFIG.Common.linux-586 deleted file mode 100644 index b2b3b9b5c..000000000 --- a/configure/os/CONFIG.Common.linux-586 +++ /dev/null @@ -1,21 +0,0 @@ -# CONFIG.Common.linux-586 -# -# Definitions for linux-586 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-586 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -# i586 is equivalent to pentium -ARCH_DEP_CFLAGS = -march=i586 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i586-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-586 file, e.g. GNU_TARGET=i586-pc-linux-gnu - - diff --git a/configure/os/CONFIG.Common.linux-686 b/configure/os/CONFIG.Common.linux-686 deleted file mode 100644 index a327d7e43..000000000 --- a/configure/os/CONFIG.Common.linux-686 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG.Common.linux-686 -# -# Definitions for linux-686 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-686 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -# i686 is euivalent to pentiumpro -ARCH_DEP_CFLAGS = -march=i686 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i686-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-686 file, e.g. GNU_TARGET=i686-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-athlon b/configure/os/CONFIG.Common.linux-athlon deleted file mode 100644 index a773a4996..000000000 --- a/configure/os/CONFIG.Common.linux-athlon +++ /dev/null @@ -1,19 +0,0 @@ -# CONFIG.Common.linux-athlon -# -# Definitions for linux-athlon target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-athlon -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -ARCH_DEP_CFLAGS += -march=athlon-mp -mfpmath=sse - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. athlon-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-athlon file, e.g. GNU_TARGET=athlon-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-cris b/configure/os/CONFIG.Common.linux-cris deleted file mode 100644 index d419b23e8..000000000 --- a/configure/os/CONFIG.Common.linux-cris +++ /dev/null @@ -1,58 +0,0 @@ -# CONFIG.Common.linux-cris -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-cris target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-cris -#------------------------------------------------------- - -# Include definitions common to all linux targets -include $(CONFIG)/os/CONFIG.Common.linuxCommon - -ARCH_CLASS = cris - -ifeq ($(BUILD_CLASS),CROSS) - GNU_TARGET = cris-axis-linux-gnu - - # prefix of compiler tools - CMPLR_SUFFIX = - CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET)) - - # CROSS_TOP_DIR - # usually AXIS_TOP_DIR is defined via - # the init_env script of the SDK provided by Axis - # - ## AXIS_TOP_DIR defined? Make missing mandatory variable visible - AXIS_TOP_DIR?=UNDEFINED_ENV__AXIS_TOP_DIR - AXIS_SDK_DIR?=$(AXIS_TOP_DIR) - - # CROSS_INCLUDES - AXIS_SDK_TARGET_INCLUDE_DIR = $(AXIS_SDK_DIR)/target/$(GNU_TARGET)/include - AXIS_SDK_TARGET_INCLUDE_DIR +=$(AXIS_SDK_DIR)/target/$(GNU_TARGET)/usr/include - - CROSS_INCLUDES = $(addprefix -isystem ,$(AXIS_SDK_TARGET_INCLUDE_DIR)) - - # CROSS_LDFLAGS - AXIS_SDK_TARGET_LIB_DIR = $(AXIS_SDK_DIR)/target/$(GNU_TARGET)/lib - AXIS_SDK_TARGET_LIB_DIR += $(AXIS_SDK_DIR)/target/$(GNU_TARGET)/usr/lib - - CROSS_LDFLAGS = $(addprefix -L,$(AXIS_SDK_TARGET_LIB_DIR)) - --include $(CONFIG)/os/CONFIG_SITE.Common.linux-cris -ifeq ($(EPICS_HOST_ARCH), linux-x86) --include $(CONFIG)/os/CONFIG.linux-x86.linux-cris --include $(CONFIG)/os/CONFIG_SITE.linux-x86.linux-cris -endif -endif - -SHARED_LIBRARIES=NO -STATIC_BUILD=YES - -ARCH_DEP_CFLAGS += -mno-mul-bug-workaround -OP_SYS_CFLAGS += -mlinux -ARCH_DEP_CPPFLAGS += -D_cris_ -mlinux - -#uncomment CRIS_COMPILER_DEBUG for debugging cris-compiled code -#CRIS_COMPILER_DEBUG diff --git a/configure/os/CONFIG.darwin-ppc.Common b/configure/os/CONFIG.darwin-ppc.Common deleted file mode 100644 index ac176878f..000000000 --- a/configure/os/CONFIG.darwin-ppc.Common +++ /dev/null @@ -1,8 +0,0 @@ -# CONFIG.darwin-ppc.Common -# -# Definitions for darwin-ppc host builds -# Sites may override these definitions in CONFIG_SITE.darwin-ppc.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common diff --git a/configure/os/CONFIG.darwin-ppc.darwin-ppc-debug b/configure/os/CONFIG.darwin-ppc.darwin-ppc-debug deleted file mode 100644 index 985052031..000000000 --- a/configure/os/CONFIG.darwin-ppc.darwin-ppc-debug +++ /dev/null @@ -1,13 +0,0 @@ -# CONFIG.darwin-ppc.darwin-ppc-debug -# -# Definitions for darwin-ppc host - darwin-ppc-debug target build with debug compiler flags -# Sites may override these definitions in CONFIG_SITE.darwin-ppc.darwin-ppc-debug -#------------------------------------------------------- - --include $(CONFIG)/os/CONFIG.Common.darwin-ppc --include $(CONFIG)/os/CONFIG.darwin-ppc.darwin-ppc --include $(CONFIG)/os/CONFIG_SITE.Common.darwin-ppc --include $(CONFIG)/os/CONFIG_SITE.darwin-ppc.darwin-ppc - -BUILD_CLASS=HOST -HOST_OPT = NO diff --git a/configure/os/CONFIG.darwin-ppcx86.Common b/configure/os/CONFIG.darwin-ppcx86.Common deleted file mode 100644 index 749835ced..000000000 --- a/configure/os/CONFIG.darwin-ppcx86.Common +++ /dev/null @@ -1,8 +0,0 @@ -# CONFIG.darwin-ppcx86.Common -# -# Definitions for Darwin universal PowerPC + x86 host builds -# Sites may override these definitions in CONFIG_SITE.darwin-ppcx86.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common diff --git a/configure/os/CONFIG.darwin-x86.Common b/configure/os/CONFIG.darwin-x86.Common index e779f7dc1..c88d8f7ea 100644 --- a/configure/os/CONFIG.darwin-x86.Common +++ b/configure/os/CONFIG.darwin-x86.Common @@ -3,6 +3,6 @@ # Definitions for darwin-x86 host builds # Sites may override these definitions in CONFIG_SITE.darwin-x86.Common #------------------------------------------------------- - +#support for IPv6 etc. #Include definitions common to unix hosts include $(CONFIG)/os/CONFIG.UnixCommon.Common diff --git a/configure/os/CONFIG.darwinCommon.darwinCommon b/configure/os/CONFIG.darwinCommon.darwinCommon index bfd61830d..3ee6fd5f9 100644 --- a/configure/os/CONFIG.darwinCommon.darwinCommon +++ b/configure/os/CONFIG.darwinCommon.darwinCommon @@ -30,6 +30,7 @@ ARCH_DEP_LDFLAGS += $(ARCH_DEP_FLAGS) # # Special flags for Darwin # No common blocks (as required when using shared libraries) +# OS provides socket address length # OP_SYS_CFLAGS += -fno-common diff --git a/configure/os/CONFIG.linux-386.Common b/configure/os/CONFIG.linux-386.Common deleted file mode 100644 index 9a3633bdf..000000000 --- a/configure/os/CONFIG.linux-386.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-386.Common -# -# Definitions for linux-386 host builds -# Sites may override these definitions in CONFIG_SITE.linux-386.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-386.linux-386 b/configure/os/CONFIG.linux-386.linux-386 deleted file mode 100644 index f65ac46b7..000000000 --- a/configure/os/CONFIG.linux-386.linux-386 +++ /dev/null @@ -1,8 +0,0 @@ -# CONFIG.linux-386.linux-386 -# -# Definitions for linux-386 host - linux-386 target builds -# Sites may override these definitions in CONFIG_SITE.linux-386.linux-386 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 diff --git a/configure/os/CONFIG.linux-486.Common b/configure/os/CONFIG.linux-486.Common deleted file mode 100644 index c151b3218..000000000 --- a/configure/os/CONFIG.linux-486.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-486.Common -# -# Definitions for linux-486 host builds -# Sites may override these definitions in CONFIG_SITE.linux-486.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-486.linux-486 b/configure/os/CONFIG.linux-486.linux-486 deleted file mode 100644 index 551cacc29..000000000 --- a/configure/os/CONFIG.linux-486.linux-486 +++ /dev/null @@ -1,9 +0,0 @@ -# CONFIG.linux-486.linux-486 -# -# Definitions for linux-486 host - linux-486 target builds -# Sites may override these definitions in CONFIG_SITE.linux-486.linux-486 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 - diff --git a/configure/os/CONFIG.linux-586.Common b/configure/os/CONFIG.linux-586.Common deleted file mode 100644 index 43463e8a0..000000000 --- a/configure/os/CONFIG.linux-586.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-586.Common -# -# Definitions for linux-586 host builds -# Sites may override these definitions in CONFIG_SITE.linux-586.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-586.linux-586 b/configure/os/CONFIG.linux-586.linux-586 deleted file mode 100644 index 990bfad74..000000000 --- a/configure/os/CONFIG.linux-586.linux-586 +++ /dev/null @@ -1,9 +0,0 @@ -# CONFIG.linux-586.linux-586 -# -# Definitions for linux-586 host - linux-586 target builds -# Sites may override these definitions in CONFIG_SITE.linux-586.linux-586 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 - diff --git a/configure/os/CONFIG.linux-686.Common b/configure/os/CONFIG.linux-686.Common deleted file mode 100644 index f36cddeac..000000000 --- a/configure/os/CONFIG.linux-686.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-686.Common -# -# Definitions for linux-686 host builds -# Sites may override these definitions in CONFIG_SITE.linux-686.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-686.linux-686 b/configure/os/CONFIG.linux-686.linux-686 deleted file mode 100644 index e4195a40a..000000000 --- a/configure/os/CONFIG.linux-686.linux-686 +++ /dev/null @@ -1,9 +0,0 @@ -# CONFIG.linux-686.linux-686 -# -# Definitions for linux-686 host - linux-686 target builds -# Sites may override these definitions in CONFIG_SITE.linux-686.linux-686 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 - diff --git a/configure/os/CONFIG.linux-x86.linux-cris b/configure/os/CONFIG.linux-x86.linux-cris deleted file mode 100644 index 8244916e5..000000000 --- a/configure/os/CONFIG.linux-x86.linux-cris +++ /dev/null @@ -1,38 +0,0 @@ -# CONFIG.linux-x86.linux-cris -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-x86 host - linux-cris target builds -# Sites may override these definitions in CONFIG_SITE.linux-x86.linux-cris -#------------------------------------------------------- - -GNU_DIR = $(CRIS_CROSS_COMPILER) - -#STATIC_... -STATIC_LDFLAGS_YES= -Wl,-Bstatic - -## debian-gcc Bug#438641 -GNU_LDLIBS_YES = -STATIC_LDFLAGS_YES += -static-libgcc - -# if not in debug mode strip all symbols -ifndef CRIS_COMPILER_DEBUG -STATIC_LDFLAGS_YES += -Wl,--strip-all -endif - -ifeq ($(GNU),YES) -STATIC_LDFLAGS_NO = -lgcc -else -STATIC_LDFLAGS_NO = -endif - -STATIC_LDLIBS_YES= -STATIC_LDLIBS_NO= - -OPT_CXXFLAGS_YES = -Os - -ifeq ($(STATIC_BUILD), YES) - $(shell echo yes) -endif diff --git a/configure/os/CONFIG.linux-x86.linux-cris_v10 b/configure/os/CONFIG.linux-x86.linux-cris_v10 deleted file mode 100644 index a227ac07c..000000000 --- a/configure/os/CONFIG.linux-x86.linux-cris_v10 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG.linux-x86.linux-cris_v10 -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-x86 host - linux-cris_v10 target builds -# Sites may override these definitions in CONFIG_SITE.linux-x86.linux-cris_v10 -#------------------------------------------------------- - -# Include definitions common to all linux-cris targets -include $(CONFIG)/os/CONFIG.Common.linux-cris - -GNU_TARGET = cris-axis-linux-gnu - -ARCH_DEP_CFLAGS += -march=v10 - -# if you are using different places for cris_v10 cris_v32 -# you have to define for each architecture -# AXIS_SDK_DIR= diff --git a/configure/os/CONFIG.linux-x86.linux-cris_v32 b/configure/os/CONFIG.linux-x86.linux-cris_v32 deleted file mode 100644 index eee8f3344..000000000 --- a/configure/os/CONFIG.linux-x86.linux-cris_v32 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG.linux-x86.linux-cris_v32 -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-x86 host - linux-cris_v32 target builds -# Sites may override these definitions in CONFIG_SITE.linux-x86.linux-cris_v32 -#------------------------------------------------------- - -# Include definitions common to all linux-cris targets -include $(CONFIG)/os/CONFIG.Common.linux-cris - -GNU_TARGET = crisv32-axis-linux-gnu - -ARCH_DEP_CFLAGS += -march=v32 - -# if you are using different places for cris_v10 cris_v32 -# you have to define for each architecture -# AXIS_SDK_DIR= diff --git a/configure/os/CONFIG.linux-x86.linux-x86 b/configure/os/CONFIG.linux-x86.linux-x86 index f6a79241a..153ce0d68 100644 --- a/configure/os/CONFIG.linux-x86.linux-x86 +++ b/configure/os/CONFIG.linux-x86.linux-x86 @@ -11,6 +11,3 @@ STATIC_LDFLAGS_YES= -Wl,-Bstatic STATIC_LDFLAGS_NO= STATIC_LDLIBS_YES= -Wl,-Bdynamic STATIC_LDLIBS_NO= - -SHRLIB_LDFLAGS += -Wl,-h$@ -LOADABLE_SHRLIB_LDFLAGS += -Wl,-h$@ diff --git a/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu b/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu index 03476b833..dfa1522ea 100644 --- a/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu +++ b/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu @@ -18,6 +18,6 @@ STATIC_LDLIBS_NO= OP_SYS_LDFLAGS += -z ignore -z combreloc -z lazyload -SHRLIB_LDFLAGS += -Wl,-z,defs -Wl,-z,text -Wl,-h,$@ -LOADABLE_SHRLIB_LDFLAGS += -Wl,-z,text -Wl,-h,$@ +SHRLIB_LDFLAGS += -Wl,-z,defs -Wl,-z,text +LOADABLE_SHRLIB_LDFLAGS += -Wl,-z,text GNU_LDLIBS_YES += -lc diff --git a/configure/os/CONFIG.win32-x86.win32-x86 b/configure/os/CONFIG.win32-x86.win32-x86 index f43667867..29b61cf5c 100644 --- a/configure/os/CONFIG.win32-x86.win32-x86 +++ b/configure/os/CONFIG.win32-x86.win32-x86 @@ -49,9 +49,9 @@ OPT_CFLAGS_YES_NO = -Ox -Oy- OPT_CFLAGS_YES = $(OPT_CFLAGS_YES_$(OPT_WHOLE_PROGRAM)) # -# -Zi generate program database for debugging information +# -Z7 generate C7 compatible debugging information (inside .obj) # -RTCsu enable run-time error checks -OPT_CFLAGS_NO = -Zi -RTCsu +OPT_CFLAGS_NO = -Z7 -RTCsu # specify object file name and location OBJ_CFLAG = -Fo @@ -119,9 +119,9 @@ OPT_CXXFLAGS_YES_NO = -Ox -Oy- OPT_CXXFLAGS_YES = $(OPT_CXXFLAGS_YES_$(OPT_WHOLE_PROGRAM)) # -# -Zi generate program database for debugging information +# -Z7 generate C7 compatible debugging information (inside .obj) # -RTCsu enable run-time error checks -OPT_CXXFLAGS_NO = -RTCsu -Zi +OPT_CXXFLAGS_NO = -RTCsu -Z7 # specify object file name and location OBJ_CXXFLAG = -Fo @@ -143,20 +143,6 @@ STATIC_LDLIBS_NO= STATIC_LDFLAGS= RANLIB= -# -# option needed for parallel builds with Visual Studio 2013 onward -# VS2012 and above have VisualStudioVersion, so just need to exclude 2012 (11.0) -# -FS Force Synchronous PDB Writes -# -ifneq ($(VisualStudioVersion),) -ifneq ($(VisualStudioVersion),11.0) - OPT_CXXFLAGS_NO += -FS - OPT_CFLAGS_NO += -FS -endif -endif - - -# # add -profile here to run the ms profiler # -LTCG whole program optimization # -incremental:no full linking diff --git a/configure/os/CONFIG_SITE.Common.RTEMS b/configure/os/CONFIG_SITE.Common.RTEMS index 0b5d227ee..6857dc9a9 100644 --- a/configure/os/CONFIG_SITE.Common.RTEMS +++ b/configure/os/CONFIG_SITE.Common.RTEMS @@ -3,11 +3,26 @@ # Site-specific information for all RTEMS targets #------------------------------------------------------- -# Where to find RTEMS +# Where to find RTEMS, and what version is it # +# RTEMS_BASE must point to the specific installation of RTEMS to +# build the target code with. +# RTEMS_VERSION is used in the path to the toolsets inside that +# installation. For RTEMS 5 only the major version number is +# used, but for RTEMS 4.10.2 say all 3 components are required. +# + +# FHI: +#RTEMS_VERSION = 5 +#RTEMS_BASE = /home/h1/DBG/rtems +#RTEMS_BASE = /home/ad/MVME6100/rtems/$(RTEMS_VERSION) +#RTEMS_BASE = /opt/RTEMS/qoriq/rtems/$(RTEMS_VERSION) + # APS: -RTEMS_VERSION = 4.10.2 -RTEMS_BASE = /usr/local/vw/rtems/rtems-$(RTEMS_VERSION) +#RTEMS_VERSION = 4.10.2 +#RTEMS_BASE = /usr/local/vw/rtems/rtems-4.10.2 +#RTEMS_VERSION = 5 +#RTEMS_BASE = /usr/local/vw/rtems/rtems-5.1 # Cross-compile toolchain in $(RTEMS_TOOLS)/bin # diff --git a/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu index 027dcf4ab..0f930c5d9 100644 --- a/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu +++ b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu @@ -6,4 +6,4 @@ # 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 +CROSS_COMPILER_RUNTEST_ARCHS += $(T_A) diff --git a/configure/os/CONFIG_SITE.Common.RTEMS-pc686-qemu b/configure/os/CONFIG_SITE.Common.RTEMS-pc686-qemu new file mode 100644 index 000000000..4ed2ed36c --- /dev/null +++ b/configure/os/CONFIG_SITE.Common.RTEMS-pc686-qemu @@ -0,0 +1,9 @@ +# CONFIG_SITE.Common.RTEMS-pc686-qemu +# +# Site-specific overrides for the RTEMS-pc686-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 += $(T_A) diff --git a/configure/os/CONFIG_SITE.Common.darwin-ppc b/configure/os/CONFIG_SITE.Common.darwin-ppc deleted file mode 100644 index a2550147f..000000000 --- a/configure/os/CONFIG_SITE.Common.darwin-ppc +++ /dev/null @@ -1,12 +0,0 @@ -# CONFIG_SITE.Common.darwin-ppc -# -# Site override definitions for darwin-ppc target builds -#------------------------------------------------------- - -# Select which CPU architectures to include in your universal binaries: -# ppc -# ppc64 - Not tested - -ARCH_CLASS = ppc -#ARCH_CLASS = ppc64 -#ARCH_CLASS = ppc ppc64 diff --git a/configure/os/CONFIG_SITE.Common.darwin-ppcx86 b/configure/os/CONFIG_SITE.Common.darwin-ppcx86 deleted file mode 100644 index 2191d54f8..000000000 --- a/configure/os/CONFIG_SITE.Common.darwin-ppcx86 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG_SITE.Common.darwin-ppcx86 -# -# Site override definitions for darwin-ppcx86 target builds -#---------------------------------------------------------- - -# Select which CPU architectures to include in your universal binaries: -# ppc -# i386 -# ppc64 - Not tested -# x86_64 - Needs MacOS 10.4 with Universal SDK, or 10.5 or later. - -ARCH_CLASS = ppc i386 -#ARCH_CLASS = ppc x86_64 -#ARCH_CLASS = ppc i386 x86_64 -#ARCH_CLASS = ppc64 i386 -#ARCH_CLASS = ppc64 x86_64 -#ARCH_CLASS = ppc64 i386 x86_64 -#ARCH_CLASS = ppc ppc64 i386 -#ARCH_CLASS = ppc ppc64 x86_64 -#ARCH_CLASS = ppc ppc64 i386 x86_64 diff --git a/configure/os/CONFIG_SITE.Common.darwin-x86 b/configure/os/CONFIG_SITE.Common.darwin-x86 index 1c5c93696..e837d63f0 100644 --- a/configure/os/CONFIG_SITE.Common.darwin-x86 +++ b/configure/os/CONFIG_SITE.Common.darwin-x86 @@ -4,14 +4,12 @@ #------------------------------------------------------- # Select which CPU architecture(s) to include in your MacOS binaries: -# i386, x86_64, or both (fat binaries). +# x86_64 only, or arm64 as well (fat binaries). -#ARCH_CLASS = i386 ARCH_CLASS = x86_64 -#ARCH_CLASS = i386 x86_64 +#ARCH_CLASS = arm64 x86_64 -# -# Uncomment the following 3 lines to build with Apple's GCC instead of CLANG. +# Uncomment the following 3 lines to build with GCC instead of CLANG. # #CMPLR_CLASS = gcc #CC = gcc diff --git a/configure/os/CONFIG_SITE.Common.linux-cris b/configure/os/CONFIG_SITE.Common.linux-cris deleted file mode 100644 index 699f346ff..000000000 --- a/configure/os/CONFIG_SITE.Common.linux-cris +++ /dev/null @@ -1,34 +0,0 @@ -# CONFIG_SITE.Common.linux-cris -# -# Site-specific settings for the linux-cris target - -# NOTE: In most cases if SHARED_LIBRARIES is set to YES the -# shared libraries will be found automatically. However if the .so -# files are installed at a different path to their compile-time path -# then in order to be found at runtime do one of these: -# a) LD_LIBRARY_PATH must include the full absolute pathname to -# $(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH) when invoking base -# executables. -# b) Add the runtime path to SHRLIB_DEPLIB_DIRS and PROD_DEPLIB_DIRS, which -# will add the named directory to the list contained in the executables. -# c) Add the runtime path to /etc/ld.so.conf and run ldconfig -# to inform the system of the shared library location. - - -# Use GNU Readline if the header file is installed -COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \ - $(GNU_DIR)/include/readline/readline.h), READLINE, EPICS)) - -# If libreadline needs additional libraries to be linked with it, try -# uncommenting each of the lines below in turn, starting with the top -# one and working downwards, until the build succeeds. Do a 'make rebuild' -# from the top of the Base tree after changing this setting. - -# Needs -lncurses: -#COMMANDLINE_LIBRARY = READLINE_NCURSES - -# Needs -lcurses: -#COMMANDLINE_LIBRARY = READLINE_CURSES - -# Readline is broken or you don't want use it: -#COMMANDLINE_LIBRARY = EPICS diff --git a/configure/os/CONFIG_SITE.darwin-ppc.Common b/configure/os/CONFIG_SITE.darwin-ppc.Common deleted file mode 100644 index 05417e1f9..000000000 --- a/configure/os/CONFIG_SITE.darwin-ppc.Common +++ /dev/null @@ -1,4 +0,0 @@ -# CONFIG_SITE.darwin-ppc.Common -# -# Site override definitions for darwin-ppc host builds -#------------------------------------------------------- diff --git a/configure/os/CONFIG_SITE.darwin-ppcx86.Common b/configure/os/CONFIG_SITE.darwin-ppcx86.Common deleted file mode 100644 index 42bd00531..000000000 --- a/configure/os/CONFIG_SITE.darwin-ppcx86.Common +++ /dev/null @@ -1,4 +0,0 @@ -# CONFIG_SITE.darwin-ppcx86.Common -# -# Site override definitions for darwin-ppcx86 host builds -#------------------------------------------------------- diff --git a/configure/os/CONFIG_SITE.linux-x86.Common b/configure/os/CONFIG_SITE.linux-x86.Common index 08fbb3d44..744424bdb 100644 --- a/configure/os/CONFIG_SITE.linux-x86.Common +++ b/configure/os/CONFIG_SITE.linux-x86.Common @@ -1,3 +1,11 @@ +# CONFIG_SITE.linux-x86.Common +# +# Site override definitions for linux-x86 host builds +#------------------------------------------------------- + +#CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32 +#CROSS_COMPILER_TARGET_ARCHS = RTEMS-mvme2100 RTEMS-pc386-qemu + INSTALL_LOCATION=/usr/local/epics/base-$(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION) GNU_HOST_ARCH=i686 diff --git a/configure/os/CONFIG_SITE.linux-x86.linux-cris b/configure/os/CONFIG_SITE.linux-x86.linux-cris deleted file mode 100644 index eb756ca8a..000000000 --- a/configure/os/CONFIG_SITE.linux-x86.linux-cris +++ /dev/null @@ -1,14 +0,0 @@ -# CONFIG_SITE.linux-x86.linux-cris -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Site specific definitions for linux-x86 host - linux-cris target builds -#------------------------------------------------------- - -# define site specific location of cris cross compiler's gnu directory -# but without bin sub directory, this will be added automatically. - -CRIS_CROSS_COMPILER ?= UNDEFINED_ENV__CRIS_CROSS_COMPILER - diff --git a/configure/toolchain.c b/configure/toolchain.c new file mode 100644 index 000000000..a97085ae3 --- /dev/null +++ b/configure/toolchain.c @@ -0,0 +1,37 @@ +#ifdef _COMMENT_ +/* Extract compiler pre-defined macros as Make variables + * + * Expanded as $(INSTALL_CFG)/TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A) + * + * Must be careful not to #include any C definitions + * into what is really a Makefile snippet + * + * cf. https://sourceforge.net/p/predef/wiki/Home/ + */ +/* GCC preprocessor drops C comments from output. + * MSVC preprocessor emits C comments in output + */ +#endif + +#if defined(__GNUC__) && !defined(__clang__) +GCC_MAJOR = __GNUC__ +GCC_MINOR = __GNUC_MINOR__ +GCC_PATCH = __GNUC_PATCHLEVEL__ + +#elif defined(__clang__) +CLANG_MAJOR = __clang_major__ +CLANG_MINOR = __clang_minor__ +CLANG_PATCH = __clang_patchlevel__ + +#elif defined(_MSC_VER) +MSVC_VER = _MSC_VER +#endif + +#ifdef __rtems__ +#include +# if __RTEMS_MAJOR__>=5 +OS_API = posix +# else +OS_API = score +# endif +#endif diff --git a/documentation/README.cris b/documentation/README.cris deleted file mode 100644 index c44f31bb0..000000000 --- a/documentation/README.cris +++ /dev/null @@ -1,67 +0,0 @@ -cross compiling EPICS and - building IOC Applications for cris architectures - (linux-cris_v10, linux-cris_v32) -====================================================================== - -Please mail questions, comments, corrections, etc. ... -to P.Zumbruch@gsi.de -November 2007 - -Tools needed ------------- - - o Axis SDK - - Overview: - http://developer.axis.com/wiki/doku.php?id=axis:sdk - - Download: - http://www.axis.com/products/dev_sdk/download_dist.php - - Install HOWTO: - http://developer.axis.com/wiki/doku.php?id=axis:software_distribution_install_howto - o Axis GNU gcc release for cross compiling - - Download: - http://www.axis.com/products/dev_sdk/download_compiler.php - - Install HOWTO: - http://developer.axis.com/wiki/doku.php?id=axis:compiler_install - -Environment ------------ - - o CRIS_CROSS_COMPILER - - path to top directory of cris cross compiler, - where binaries are in sub directory bin/ - - if not set, the make process will stop at place - UNDEFINED_ENV__CRIS_CROSS_COMPILER - o AXIS_TOP_DIR?=UNDEFINED_ENV__AXIS_TOP_DIR - - path to axis SDK top directory - - if not set compile and link commands will contain references to - UNDEFINED_ENV__AXIS_TOP_DIR - - to set the necessary variables, execute - . ./init_env - in the top directory of the SDK provided here. - o CRIS_COMPILER_DEBUG - - if defined symbols won't be stripped, - resulting in comparably large files - -Building --------- - - o Edit the CONFIG_SITE files - - CONFIG_SITE.linux-x86.Common: - for CROSS_COMPILER_TARGET_ARCHS += linux-cris_v10 - for CROSS_COMPILER_TARGET_ARCHS += linux-cris_v32 - - optionally CONFIG_SITE.linux-x86.linux-cris - for setting CRIS_CROSS_COMPILER - - optionally create CONFIG_SITE.linux-x86.linux-cris_v10 - - optionally create CONFIG_SITE.linux-x86.linux-cris_v32 - o "make". - -Shared Libraries ----------------- - -Generating shared libraries is not supported. - - -Please feel free to contact me if you -encounter serious problems. - -Peter diff --git a/documentation/README.darwin.html b/documentation/README.darwin.html deleted file mode 100644 index dd11ce857..000000000 --- a/documentation/README.darwin.html +++ /dev/null @@ -1,184 +0,0 @@ - - -Installation notes for EPICS on Mac OS X (Darwin) - - - - -

Building EPICS base

-
    -
  • -To build base: -
      -
    1. -Set the EPICS_HOST_ARCH environment variable to darwin-ppc, darwin-x86 or darwin-ppcx86. -The scripts in the -base/startup directory can automate this. For example, here's part -of my Bash login script (~/.bash_login): -
      -#
      -# EPICS
      -#
      -EPICS_BASE="${HOME}/src/EPICS/base"
      -EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
      -. "${EPICS_BASE}"/startup/unix.sh
      -
      -
    2. -
    3. -cd to the EPICS base top-level source directory. -
    4. -
    5. -Uncomment the appropriate line in the relevent -EPICS_BASE/configure/os/CONFIG_SITE.Common.darwin-xxx file for your EPICS_HOST_ARCH value. -Newer versions of OS X (e.g. Snow Leopard) may include only 64 bit versions of some OS libraries, -so should only have the x86_64 ARCH_CLASS. -
    6. -
    7. -Run make. -
    8. -
    - -
  • - -
  • -As distributed, EPICS on Mac OS X uses the readline command line input -routines. IOC applications are more pleasant to interact with if -either the readline or libtecla library is used. The easiest -way to get either or both of these libraries on to your system is to -download and install them using the either the DarwinPorts -distribution or the Fink package manager. If you don't want to install -the readline library, set the COMMANDLINE_LIBRARY variable in one of -the CONFIG_SITE files to EPICS. -

    -Information on DarwinPorts is available from -the DarwinPorts -project page. -DarwinPorts binary packages are available from -here. -

    -Fink may be downloaded from -the Source Forge. -

  • - -
  • -If broadcasts are not seen locally, try adding "localhost" (127.0.0.1) -to the EPICS_CA_ADDR_LIST. -
  • -
- -

Building EPICS extensions

-

-Many extensions build and run properly on OS X. To build and run medm, first -obtain the X11 run-time and developer packages from Apple and the OpenMotif3 -package from Fink. - -

Objective-C and AppleScript

-

-Code written in Objective-C can be included in host or IOC applications. -Here are a couple of short Objective-C examples which can be used to send -AppleScript events to other applications on the OS X machine. - -

-/*
- * exampleAppleScriptRecord.m 
- *
- * Simple Objective-C/AppleScript subroutine record
- *
- * To use this record in an application:
- *
- * 1) Make the following changes to the application Makefile:
- *    - Add exampleAppleScriptRecord.m to the application SRCS.
- *    - Add -framework Foundation to the application LDFLAGS.
- * 2) Add the following line to the application database description:
- *      registrar(registerExampleAppleScript)
- * 3) Add a record to the application database:
- *      record(sub,"setVolume")
- *      {
- *          field(SNAM,"exampleAppleScriptProcess")
- *      }
- */
-#import <Foundation/Foundation.h>
-#include <registryFunction.h>
-#include <subRecord.h>
-#include <alarm.h>
-#include <errlog.h>
-#include <recGbl.h>
-#include <epicsExport.h>
-
-/*
- * Shim between EPICS and NSAppleScript class.
- */
-static long
-exampleAppleScriptProcess(struct subRecord *psub)
- {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    NSDictionary *err;
-    NSAppleScript *nsa;
-    
-    nsa = [[NSAppleScript alloc] initWithSource:[NSString stringWithFormat:
-                @"tell application \"Finder\" to set volume %g\n", psub->a]];
-    if ([nsa executeAndReturnError:&err] == nil) {
-        errlogPrintf("Failed to run AppleScript: %s\n",
-                        [[err objectForKey:NSAppleScriptErrorMessage] cString]);
-        recGblSetSevr(psub, SOFT_ALARM, INVALID_ALARM);
-    }
-    [nsa release];
-    [pool release];
-    return 0;
-}
-
-static registryFunctionRef subRef[] = {
-    {"exampleAppleScriptProcess",(REGISTRYFUNCTION)exampleAppleScriptProcess}
-};
-
-static void registerExampleAppleScript(void)
-{
-    registryFunctionRefAdd(subRef,NELEMENTS(subRef));
-}
-epicsExportRegistrar(registerExampleAppleScript);
-
-
-==============================================================================
-/*
- * runAppleScript.m 
- *
- * Simple Objective-C/AppleScript shim to allow EPICS application to
- * send arbitrary AppleScript messages to other applications.
- *
- * To use this subroutine in an application make the following
- * changes to the application Makefile:
- * - Add runAppleScript.m to the application SRCS.
- * - Add -framework Foundation to the application LDFLAGS.
- */
-#import <Foundation/Foundation.h>
-#include <errlog.h>
-
-int
-runAppleScript(const char *format, ...)
-{
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    NSString *script;
-    NSMutableDictionary *err;
-    NSAppleScript *nsa;
-    va_list args;
-    int ret = 0;
-    
-    va_start(args, format);
-    script = [[NSString alloc] initWithFormat:
-                            [NSString stringWithCString:format] arguments:args];
-    va_end(args);
-    err = [NSMutableDictionary dictionaryWithCapacity:10];
-    nsa = [[NSAppleScript alloc] initWithSource:script];
-    if ([nsa executeAndReturnError:&err] == nil) {
-        errlogPrintf("Failed to run AppleScript: %s\n",
-                        [[err objectForKey:NSAppleScriptErrorMessage] cString]);
-        ret = -1;
-    }
-    [script release];
-    [nsa release];
-    [pool release];
-    return ret;
-}
-
- - diff --git a/documentation/README.md b/documentation/README.md index 7e995bfde..a5310deb4 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -6,22 +6,23 @@ ### Table of Contents - - [What is EPICS base?](#0_0_1) - - [What is new in this release?](#0_0_2) - - [Copyright](#0_0_3) - - [Supported platforms](#0_0_4) - - [Supported compilers](#0_0_5) - - [Software requirements](#0_0_6) - - [Documentation](#0_0_8) - - [Directory Structure](#0_0_10) - - [Build related components](#0_0_11) - - [Building EPICS base (Unix and Win32)](#0_0_12) - - [Example application and extension](#0_0_13) - - [Multiple host platforms](#0_0_14) + - [What is EPICS base?](#what-is-epics-base?) + - [What is new in this release?](#what-is-new-in-this-release?) + - [Copyright](#copyright) + - [Supported platforms](#supported-platforms) + - [Supported compilers](#supported-compilers) + - [Software requirements](#software-requirements) + - [Host system storage requirements](#host-system-storage-requirements) + - [Documentation](#documentation) + - [Directory Structure](#directory-structure) + - [Site-specific build configuration](#site-specific-build-configuration) + - [Building EPICS base](#building-epics-base) + - [Example application and extension](#example-application-and-extension) + - [Multiple host platforms](#multiple-host-platforms) ----- -### What is EPICS base? +### What is EPICS base? The Experimental Physics and Industrial Control Systems (EPICS) is an extensible set of software components and tools with which application @@ -33,17 +34,17 @@ function. EPICS base allows an arbitrary number of target systems, IOCs (input/output controllers), and host systems, OPIs (operator interfaces) of various types. -### What is new in this release? +### What is new in this release? -Please check the `RELEASE_NOTES` file in the distribution for +Please check the `documentation/RELEASE_NOTES.md` file for description of changes and release migration details. -### Copyright Licenses +### Copyright -Please review the LICENSE file included in the distribution for legal -terms of usage. +Please review the `LICENSE` file included in the distribution for +legal terms of usage. -### Supported platforms +### Supported platforms The list of platforms supported by this version of EPICS base is given in the `configure/CONFIG_SITE` file. If you are trying to build EPICS @@ -54,7 +55,7 @@ base/configure/os/directory. You can start by copying existing configuration files in the configure/os directory and then make changes for your new platforms. -### Supported compilers +### Supported compilers This version of EPICS base has been built and tested using the host vendor's C and C++ compilers, as well as the GNU gcc and g++ @@ -63,27 +64,33 @@ targets. You may need the C and C++ compilers to be in your search path to do EPICS builds; check the definitions of CC and CCC in `base/configure/os/CONFIG..` if you have problems. -### Software requirements +### Software requirements -**GNU make** -You must use GNU make, gnumake, for any EPICS builds. Set your path so -that a gnumake version 4.1 or later is available. +#### GNU make + +You must use the GNU version of `make` for EPICS builds. Set your path +so that version 4.1 or later is available. The macOS version of `make` +is older but does still work. + +#### Perl -**Perl** You must have Perl version 5.10 or later installed. The EPICS configuration files do not specify the perl full pathname, so the perl executable must be found through your normal search path. -**Unzip and tar (Winzip on WIN32 systems)** +#### Unzip and tar (Winzip on WIN32 systems) + You must have tools available to unzip and untar the EPICS base distribution file. -**Target systems** +#### Target systems + EPICS supports IOCs running on embedded platforms such as VxWorks and RTEMS built using a cross-compiler, and also supports soft IOCs running as processes on the host platform. -**vxWorks** +#### vxWorks + You must have vxWorks 6.8 or later installed if any of your target systems are vxWorks systems; the C++ compiler from older versions cannot compile recently developed code. The vxWorks installation provides the @@ -96,127 +103,146 @@ Consult the [vxWorks 6.x](https://epics.anl.gov/base/vxWorks6.php) EPICS web pages about and the vxWorks documentation for information about configuring your vxWorks operating system for use with EPICS. -**RTEMS** +#### RTEMS + For RTEMS targets, you need RTEMS core and toolset version 4.9.x or -4.10.x (4.11 or 5.x are not yet supported). +4.10.x. RTEMS 5 is experimental in EPICS 7.0.6. -**GNU readline or Tecla library** -GNU readline and Tecla libraries can be used by the IOC shell to -provide command line editing and command line history recall and edit. -GNU readline (or Tecla library) must be installed on your target -system when `COMMANDLINE_LIBRARY` is set to READLINE (or TECLA) for -that target. EPICS (EPICS shell) is the default specified in -`CONFIG_COMMON`. A READLINE override is defined for linux-x86 in the -EPICS distribution. Comment out `COMMANDLINE_LIBRARY=READLINE` in -`configure/os/CONFIG_SITE.Common.linux-x86` if readline is not -installed on linux-x86. Command-line editing and history will then be -those supplied by the os. On vxWorks the ledLib command-line input -library is used instead. +#### Command Line Editing -### Documentation +GNU readline and other similar libraries can be used by the IOC shell +to provide command line editing and command line history recall. The +GNU readline development package (or Apple's emulator on macOS) must +be installed for a target when its build configuration variable +`COMMANDLINE_LIBRARY` is set to `READLINE`. The default specified in +`CONFIG_COMMON` is `EPICS`, but most linux target builds can detect if +readline is available and will then use it. RTEMS targets may be +configured to use `LIBTECLA` if available, and on vxWorks the OS's +ledLib line-editing library is normally used. -EPICS documentation is available through the [EPICS -website](https://epics.anl.gov/) at Argonne. +### Host system storage requirements + +The compressed tar file is approximately 3 MB in size. The +distribution source tree takes up approximately 21 MB. A 64-bit host +architecture may need around 610 MB to compile, while cross-compiled +targets are somewhat smaller. + +### Documentation + +EPICS documentation is available through the [EPICS website](https://epics.anl.gov/) at Argonne. Release specific documentation can also be found in the -base/documentation directory of the distribution. +`base/documentation` directory of the distribution. -### Directory Structure +### Directory Structure -#### Distribution directory structure: +#### Distribution directory structure ``` - base Root directory of the base distribution - base/configure Operating system independent build config files - base/configure/os Operating system dependent build config files - base/documentation Distribution documentation - base/src Source code in various subdirectories - base/startup Scripts for setting up path and environment + base Root directory of the distribution + base/configure Build rules and OS-independent config files + base/configure/os OS-dependent build config files + base/documentation Distribution documentation + base/src Source code in various subdirectories + base/startup Scripts for setting up path and environment ``` -#### Install directories created by the build: +#### Directories created by the build + +These are created in the root directory of the installation (`base` +above) or under the directory pointed to by the `INSTALL_LOCATION` +configuration variable if that has been set. ``` - bin Installed scripts and executables in subdirs - cfg Installed build configuration files - db Installed data bases - dbd Installed data base definitions - doc Installed documentation files - html Installed html documentation - include Installed header files - include/os Installed os specific header files in subdirs - include/compiler Installed compiler-specific header files - lib Installed libraries in arch subdirectories - lib/perl Installed perl modules - templates Installed templates + bin Installed scripts and executables in subdirs + cfg Installed build configuration files + db Installed database files + dbd Installed database definition files + html Installed html documentation + include Installed header files + include/os Installed OS-specific header files in subdirs + include/compiler Installed compiler-specific header files + lib Installed libraries in arch subdirectories + lib/perl Installed perl modules + templates Installed templates ``` -### Build related components +#### `base/documentation` Directory -#### base/documentation directory - contains setup, build, and install documents +This contains documents on how to setup, build, and install EPICS. ``` - README.md Instructions for setup and building epics base - README.darwin.html Installation notes for Mac OS X (Darwin) - RELEASE_NOTES.html Notes on release changes - KnownProblems.html List of known problems and workarounds + README.md This file + RELEASE_NOTES.md Notes on release changes + KnownProblems.html List of known problems and workarounds ``` -#### base/startup directory - contains scripts to set environment and path +#### `base/startup` Directory + +This contains several example scripts that show how to set up the +build environment and PATH for using EPICS. Sites would usually copy and/or modify these files as appropriate for their environment; they are not used by the build system at all. ``` - EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable - unix.csh C shell script to set path and env variables - unix.sh Bourne shell script to set path and env variables - win32.bat Bat file example to configure win32-x86 target - windows.bat Bat file example to configure windows-x64 target + EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable + unix.csh C shell script to set path and env variables + unix.sh Bourne shell script to set path and env variables + win32.bat Bat file example to configure win32-x86 target + windows.bat Bat file example to configure windows-x64 target ``` -#### base/configure directory - contains build definitions and rules +#### `base/configure` directory + +This contains build-system files providing definitions and rules +required by GNU Make to build EPICS. Users should only need to modify the `CONFIG_SITE` files to configure the EPICS build. ``` - CONFIG Includes configure files and allows variable overrides - CONFIG.CrossCommon Cross build definitions - CONFIG.gnuCommon Gnu compiler build definitions for all archs - CONFIG_ADDONS Definitions for and DEFAULT options - CONFIG_APP_INCLUDE - CONFIG_BASE EPICS base tool and location definitions - CONFIG_BASE_VERSION Definitions for EPICS base version number - CONFIG_COMMON Definitions common to all builds - CONFIG_ENV Definitions of EPICS environment variables - CONFIG_FILE_TYPE - CONFIG_SITE Site specific make definitions - CONFIG_SITE_ENV Site defaults for EPICS environment variables - MAKEFILE Installs CONFIG* RULES* creates - RELEASE Location of external products - RULES Includes appropriate rules file - RULES.Db Rules for database and database definition files - RULES.ioc Rules for application iocBoot/ioc* directory - RULES_ARCHS Definitions and rules for building architectures - RULES_BUILD Build and install rules and definitions - RULES_DIRS Definitions and rules for building subdirectories - RULES_EXPAND - RULES_FILE_TYPE - RULES_TARGET - RULES_TOP Rules specific to a dir (uninstall and tar) - Sample.Makefile Sample makefile with comments + CONFIG Main entry point for building EPICS + CONFIG.CrossCommon Cross build definitions + CONFIG.gnuCommon Gnu compiler build definitions for all archs + CONFIG_ADDONS Definitions for and DEFAULT options + CONFIG_APP_INCLUDE + CONFIG_BASE EPICS base tool and location definitions + CONFIG_BASE_VERSION Definitions for EPICS base version number + CONFIG_COMMON Definitions common to all builds + CONFIG_ENV Definitions of EPICS environment variables + CONFIG_FILE_TYPE + CONFIG_SITE Site specific make definitions + CONFIG_SITE_ENV Site defaults for EPICS environment variables + MAKEFILE Installs CONFIG* RULES* creates + RELEASE Location of external products + RULES Includes appropriate rules file + RULES.Db Rules for database and database definition files + RULES.ioc Rules for application iocBoot/ioc* directory + RULES_ARCHS Definitions and rules for building architectures + RULES_BUILD Build and install rules and definitions + RULES_DIRS Definitions and rules for building subdirectories + RULES_EXPAND + RULES_FILE_TYPE + RULES_TARGET + RULES_TOP Rules specific to a dir only + Sample.Makefile Sample makefile with comments ``` -#### base/configure/os directory - contains os-arch specific definitions +#### `base/configure/os` Directory + +Files in here provide definitions that are shared by or specific to particular host and/or target architectures. Users should only need to modify the `CONFIG_SITE` files in this directory to configure the EPICS build. ``` - CONFIG.. Specific host-target build definitions - CONFIG.Common. Specific target definitions for all hosts - CONFIG..Common Specific host definitions for all targets - CONFIG.UnixCommon.Common Definitions for Unix hosts and all targets - CONFIG.Common.UnixCommon Definitions for Unix targets and all hosts - CONFIG.Common.vxWorksCommon Specific host definitions for all vx targets - CONFIG_SITE.. Site specific host-target definitions - CONFIG_SITE.Common. Site specific target defs for all hosts - CONFIG_SITE..Common Site specific host defs for all targets + CONFIG.. Definitions for a specific host-target combination + CONFIG.Common. Definitions for a specific target, any host + CONFIG..Common Definitions for a specific host, any target + CONFIG.UnixCommon.Common Definitions for Unix hosts, any target + CONFIG.Common.UnixCommon Definitions for Unix targets, any host + CONFIG.Common.RTEMS Definitions for all RTEMS targets, any host + CONFIG.Common.vxWorksCommon Definitions for all vxWorks targets, any host + CONFIG_SITE.. Local settings for a specific host-target combination + CONFIG_SITE.Common. Local settings for a specific target, any host + CONFIG_SITE..Common Local settings for a specific host, any target + CONFIG_SITE.Common.RTEMS Local settings for all RTEMS targets, any host + CONFIG_SITE.Common.vxWorksCommon Local settings for all vxWorks targets, any host ``` -### Building EPICS base (Unix and Win32) +### Building EPICS base #### Unpack file @@ -228,74 +254,79 @@ systems. Files in the base/startup directory have been provided to help set required path and other environment variables. -* `EPICS_HOST_ARCH` -Before you can build or use this EPICS base, the environment variable -`EPICS_HOST_ARCH` must be defined. A perl script EpicsHostArch.pl in -the base/startup directory has been provided to help set -`EPICS_HOST_ARCH.` You should have `EPICS_HOST_ARCH` set to your -host operating system followed by a dash and then your host -architecture, e.g. linux-x86_64. If you are not using the OS -vendor's c/c++ compiler for host builds, you will need another dash -followed by the alternate compiler name (e.g. "-gnu" for GNU c/c++ -compilers on a solaris host or "-mingw" for MinGW c/c++ compilers on -Windows). See `configure/CONFIG_SITE` for a list of supported -`EPICS_HOST_ARCH` values. +* **`EPICS_HOST_ARCH`** -* `PATH` -As already mentioned, you must have the perl executable and you may -need C and C++ compilers in your search path. For building base you -also must have echo in your search path. For Unix host builds you -also need ln, cpp, cp, rm, mv, and mkdir in your search path and -/bin/chmod must exist. On some Unix systems you may also need ar and -ranlib in your path, and the C compiler may require as and ld in -your path. On solaris systems you need uname in your path. +Some host builds of EPICS require that the environment variable +`EPICS_HOST_ARCH` be defined. The perl script `EpicsHostArch.pl` in the +`base/startup` directory prints the value which the build will use if +the variable is not set before the build starts. Architecture names +start with the operating system followed by a dash and the host CPU +architecture, e.g. `linux-x86_64`. Some architecture names have another +dash followed by another keyword, for example when building for Windows +but using the MinGW compiler the name must be `windows-x64-mingw`. See +`configure/CONFIG_SITE` for a list of supported host architecture names. -* `LD_LIBRARY_PATH` -EPICS shared libraries and executables normally contain the full -path to any libraries they require. However, if you move the EPICS -files or directories from their build-time location then in order -for the shared libraries to be found at runtime `LD_LIBRARY_PATH` -must include the full pathname to -`$(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH)` when invoking -executables, or some equivalent OS-specific mechanism (such as -/etc/ld.so.conf on Linux) must be used. Shared libraries are now -built by default on all Unix type hosts. +* **`PATH`** +As already mentioned, you must have the `perl` executable and you may +need C and C++ compilers in your search path. When building base you +must have `echo` in your search path. For Unix host builds you will +also need `cp`, `rm`, `mv`, and `mkdir` in your search path. Some Unix +systems may also need `ar` and `ranlib`, and the C/C++ compilers may +require `as` and `ld` in your path. On Solaris systems you need +`uname` in your path. -#### Do site-specific build configuration +* **`LD_LIBRARY_PATH`** +EPICS shared libraries and executables normally contain the full path +to any libraries they require, so setting this variable is not usually +necessary. However, if you move the EPICS installation to a new +location after building it then in order for the shared libraries to +be found at runtime it may need to be set, or some equivalent +OS-specific mechanism such as `/etc/ld.so.conf` on Linux must be used. +Shared libraries are now built by default on all Unix type hosts. -**Site configuration** -To configure EPICS, you may want to modify the default definitions -in the following files: +### Site-specific build configuration + +#### Site configuration + +To configure EPICS, you may want to modify some values set in the +following files: +>>>>>>> mirror/3.15 ``` - configure/CONFIG_SITE Build choices. Specify target archs. - configure/CONFIG_SITE_ENV Environment variable defaults - configure/RELEASE TORNADO2 full path location + configure/CONFIG_SITE Build settings. Specify target archs. + configure/CONFIG_SITE_ENV Environment variable defaults ``` -**Host configuration** -To configure each host system, you may override the default -definitions by adding a new file in the configure/os directory with -override definitions. The new file should have the same name as the -distribution file to be overridden except with CONFIG in the name -changed to `CONFIG_SITE`. +#### Host configuration + +To configure each host system, you can override the default +definitions by adding a new settings file (or editing an existing +settings file) in the `configure/os` directory with your override +definitions. The settings file has the same name as the definitions +file to be overridden except with `CONFIG` in the name changed to +`CONFIG_SITE`. ``` - configure/os/CONFIG.. Host build settings - configure/os/CONFIG..Common Host common build settings + configure/os/CONFIG.. Host self-build definitions + configure/os/CONFIG..Common Host common build definitions + configure/os/CONFIG_SITE.. Host self-build overrides + configure/os/CONFIG_SITE..Common Host common build overrides ``` -**Target configuration** +#### Target configuration + To configure each target system, you may override the default -definitions by adding a new file in the configure/os directory with -override definitions. The new file should have the same name as the -distribution file to be overridden except with CONFIG in the name -replaced by `CONFIG_SITE`. This step is necessary even if the host -system is the only target system. +definitions by adding a new settings file (or editing an existing +settings file) in the `configure/os` directory with your override +definitions. The settings file has the same name as the definitions +file to be overridden except with `CONFIG` in the name changed to +`CONFIG_SITE`. ``` - configure/os/CONFIG.Common. Target common settings - configure/os/CONFIG.. Host-target settings + configure/os/CONFIG.Common. Target common definitions + configure/os/CONFIG.. Host-target definitions + configure/os/CONFIG_SITE.Common. Target common overrides + configure/os/CONFIG_SITE.. Host-target overrides ``` #### Build EPICS base @@ -305,24 +336,29 @@ by issuing the following commands in the distribution's root directory (base): ``` - gnumake clean uninstall - gnumake + make distclean + make ``` -The command "gnumake clean uninstall" will remove all files and -directories generated by a previous build. The command "gnumake" +The command `make distclean` will remove all files and +directories generated by a previous build. The command `make` will build and install everything for the configured host and targets. -It is recommended that you do a "gnumake clean uninstall" at the +It is recommended that you do a `make distclean` at the root directory of an EPICS directory structure before each complete rebuild to ensure that all components will be rebuilt. -### Example application and extension +In some cases GNU Make may have been installed as `gmake` or +`gnumake`, in which case the above commands will have to be adjusted +to match. -A perl tool, makeBaseApp.pl is included in the distribution file. This -script will create a sample application that can be built and then -executed to try out this release of base. +### Example application and extension + +A perl tool `makeBaseApp.pl` and several template applications are +included in the distribution. This script instantiates the selected +template into an empty directory to provide an example application +that can be built and then executed to try out this release of base. Instructions for building and executing the EPICS example application can be found in the section "Example Application" of Chapter 2, @@ -335,26 +371,30 @@ application as a host-based IOC, you will be able to quickly implement a complete EPICS system and be able to run channel access clients on the host system. -A perl script, makeBaseExt.pl, is included in the distribution file. -This script will create a sample extension that can be built and -executed. The makeBaseApp.pl and makeBaseExt.pl scripts are installed -into the install location `bin/` directory during the base -build. +Another perl script `makeBaseExt.pl` is also included in the +distribution file for creating an extensions tree and sample +application that can also be built and executed. Both these scripts +are installed into the install location `bin/` directory +during the base build. -### Multiple host platforms +### Multiple host platforms You can build using a single EPICS directory structure on multiple host systems and for multiple cross target systems. The intermediate and binary files generated by the build will be created in separate subdirectories and installed into the appropriate separate host/target -install directories. EPICS executables and perl scripts are installed -into the `$(INSTALL_LOCATION)/bin/` directories. Libraries are -installed into $`(INSTALL_LOCATION)/lib/`. The default -definition for `$(INSTALL_LOCATION)` is `$(TOP)` which is the root -directory in the distribution directory structure, base. Created -object files are stored in `O.` source subdirectories, This -allows objects for multiple cross target architectures to be -maintained at the same time. To build EPICS base for a specific +install directories. + +EPICS executables and perl scripts are installed into the +`$(INSTALL_LOCATION)/bin/` directories. Libraries are installed +into $`(INSTALL_LOCATION)/lib/`. The default definition for +`$(INSTALL_LOCATION)` is `$(TOP)` which is the root directory in the +distribution directory structure, `base`. Intermediate object files +are stored in `O.` source subdirectories during the build +process, to allow objects for multiple cross target architectures +to be maintained at the same time. + +To build EPICS base for a specific host/target combination you must have the proper host/target C/C++ cross compiler and target header files and the base/configure/os directory must have the appropriate configure files. diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index b53572b07..3fb6503a0 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -2,20 +2,136 @@ These release notes describe changes that have been made since the previous release of this series of EPICS Base. **Note that changes which were merged up -from commits to new releases in an older Base series are not described at the -top of this file but have entries that appear lower down, under the series to -which they were originally committed.** Thus it is important to read more than -just the first section to understand everything that has changed in each -release. +from commits to the 3.15 branch are not described at the top of this file but +lower down, under the 3.15 release to which they were originally committed.** +Thus it is important to read more than just the first section to understand +everything that has changed in each release. The PVA submodules each have their own individual sets of release notes which should also be read to understand what has changed since earlier releases. -**This version of EPICS has not been released yet.** -## Changes made on the 7.0 branch since 7.0.5 +## EPICS Release 7.0.6 - +### Support for obsolete architectures removed + +These target architectures have been removed: + ++ darwin-ppc, darwin-ppcx86 ++ linux-386, linux-486, linux-586, linux-686, linux-athlon (cross-build) ++ linux-cris, linux-cris_v10, linux-cris_v32 (cross-build) ++ RTEMS-at91rm9200ek, RTEMS-gen68360, RTEMS-mcp750, RTEMS-mvme167, +RTEMS-psim (cross-build) + +### Experimental Support for RTEMS 5 + +The new major release of the RTEMS real-time OS contains many changes +including the ability to support SMP systems. This release of EPICS +can still be built with RTEMS 4.9.x or 4.10.x and should work just +the same as earlier releases, although due to code having moved around +we recommend thorough testing before this release is first used in +production systems. + +This release of EPICS comes with support for several new RTEMS targets +running on RTEMS 5: + +- RTEMS-beagleboneblack +- RTEMS-pc686 +- RTEMS-qoriq_e500 (MVME2500) +- RTEMS-xilinx_zynq_a9_qemu +- RTEMS-xilinx_zynq_zedboard + +The EPICS support for RTEMS 4 has always relied on RTEMS-specific +kernel APIs which cannot be used on an SMP system, so a new port was +created to use the Posix real-time APIs that are now recommended for +RTEMS 5. Note that a single installation of EPICS cannot build both +RTEMS 4 and RTEMS 5 targets, if you need to support targets running +on both versions you must use a separate installation, and be sure +to run `make distclean` if switching a single source tree from one +to the other (both header files and dependency files are different +between the two and must be cleaned out). + +The configuration variable RTEMS_VERSION in the EPICS config file +`configure/os/CONFIG_SITE.Common.RTEMS` must be set to the full 3- +part version number for RTEMS 4 releases, e.g. `4.9.1`, `4.10.2` +but for RTEMS 5.1 and later it must only contain the major version +number e.g. `5`. + +Some RTEMS BSPs can be built and may work with the newer libbsd +network stack which RTEMS is moving over to, but most of the MVME +boards (and the uC5282) still require the legacy network stack. + +The dependency on bspExt has been removed, EPICS now provides its +own routine for VMEbus probing (or uses one built into the BSP). + +Anyone using this release on RTEMS is advised to discuss problems +building or running it on either the tech-talk or core-talk email +lists so the core developers can help with and find out about any +problems with the old or new port. + +Known Issues: +- MVME2100 and MVME2700 need changes to the RTEMS 5 BSP to build. +- VMEBus support is not yet available for the MVME2500 BSP. +- There are some known issues with floating point on MVME2500, + probably related to its newer e500 FPU. +- Changed network driver for beatnik to work with libbsd. Some + issues with DHCP, but network stack usable. Can load env from + NVRAM. + +### `epicsEnvShow` accepts a glob pattern + +The optional argument to epicsEnvShow can now be a glob pattern. + +### New function `epicsStrnGlobMatch()` + +The function `epicsStrnGlobMatch(char* str, size_t len, char* pattern)` +works exactly the same as `epicsStrGlobMatch()` but takes an additional +length arguments which limits the number of characters of `str` to match. + +### Automatic fallback to thread when unable to exec caRepeater + +A process using libca which does not find an existing caRepeater process +will attempt to start one by running the caRepeater executable. +This is not always possible, usually when caRepeater is not in `$PATH`. +Now, instead of printing a warning, an internal caRepeater thread +will be started (as is done be RTEMS and vxWorks targets). + +If this fallback occurs, the lifetime of the caRepeater thread +may be shorter than the lifetime of a separate caRepeater process +would have been. + +It remains the recommended practice to explicitly start a caRepeater +instance. Examples of both systemd (`caRepeater.service`) and sysv +(`S99caRepeater`) scripts may be found under `bin/`. + +### Glob pattern allowed in `var` command + +When used with one argument, the `var` command can be used with a glob pattern +for printing matching variables. + +### Formalize/fix `FINAL_LOCATION` + +The `FINAL_LOCATION` make variable has for some time been an undocumented +means of performing a staged build. This is a build which "installs" to +a temporary location, which will later be moved to a final location. + +This has now been added to `configure/CONFIG_SITE`. + +Usage analogous to the autotools recipe + +```sh +./configure --prefix=/usr/lib/epics +make install DESTDIR=/tmp/build +``` + +would be + +```sh +make INSTALL_LOCATION=/tmp/build FINAL_LOCATION=/usr/lib/epics +``` + +`FINAL_LOCATION` is now correctly used in systemd and sysv init scripts +`caRepeater.service`, `S99caRepeater`, and `S99logServer`. ### epicsEnvShow accepts glob pattern @@ -49,6 +165,116 @@ checking for and initializing the link in their `special()` routine. IOC shell will now ensure `${PWD}` is set on startup, and updated by the `cd` iocsh function. +### Add Alarm Message and Time Tag Fields + +Two new fields have been added to `dbCommon` so will be present in all +records: `AMSG` and `UTAG`. + +#### `AMSG` + +`AMSG` can hold an arbitrary 40-character string, providing additional +information about the alarm condition indicated in `STAT` and `SEVR`. With no +alarm it will hold an empty string. The new `recGblSetSevrMsg()` function can +be used in place of `recGblSetSevr()` to signal an alarm while providing a +message. + +For example, a device support's `read_bi()` routine for a hypothetical +multi-channel ethernet attached device might flag a communication error +between the IOC and controller, or an error involving a certain channel like +this: + +```c +static long read_bi(biRecord* prec) { + ... + if (!priv->connected) { + recGblSetSevrMsg(prec, COMM_ALARM, INVALID_ALARM, + "No controller connected"); + return S_dev_noDevice; + } + if (!priv->err) { + recGblSetSevrMsg(prec, READ_ALARM, INVALID_ALARM, + "Channel %u disconnexted", priv->chan); + return S_dev_noDevice; + } + return status; +} +``` + +#### `UTAG` + +`UTAG` holds an `epicsUInt64` value which is semantically part of the record's +timestamp (`TIME`). The value defaults to zero if not explicitly set. Device +support or an event time provider which supports this feature may write a tag +value directly to the `dbCommon::utag` field. + +`TSEL` links will copy both `TIME` and `UTAG` between records if the link type +supports this (CA links do not). + +A `utag` server side channel filter has been added which can be configured to +filter out monitor updates which don't pass the test `(UTAG & M) == V` where +`M` and `V` are client specified integers. For example running the command +`camonitor BPM0:X.{utag:{M:1,V:1}}` will only show updates for which +`(UTAG & 1) == 1` i.e. the least significant bit of the `UTAG` field is set. + +This feature is intended for use by intelligent devices which can provide +contextual information along with a value/alarm/time. For example, a beam +diagnostic device which is aware of whether a beam signal should be present +(eg. from a global timing system). + +#### Link Support + +Two new optional methods have been added to the Link Support Entry Table +(`struct lset`): `lset::getAlarmMsg()` and `lset::getTimeStampTag()`. See +comments in dbLink.h for details on implementing these. + +Two new accessor functions have also been added which call these methods: +`dbGetAlarmMsg()` and `dbGetTimeStampTag()`. + +#### Compatibility + +User code wishing to call these interfaces while maintaining compatibility with older +versions of Base may add some of the following macro definitions, and ensure +that the variables referenced by output pointers are initialized. + +```c +#ifndef HAS_ALARM_MESSAGE +# define recGblSetSevrMsg(REC, STAT, SEVR, ...) recGblSetSevr(REC, STAT, SEVR) +#endif +#ifndef dbGetAlarmMsg +# define dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) dbGetAlarm(LINK, STAT, SEVR) +#endif +#ifndef dbGetTimeStampTag +# define dbGetTimeStampTag(LINK, STAMP, TAG) dbGetTimeStamp(LINK, STAMP) +#endif +``` + + +### Timeouts for Unit Test Programs + +The unit test programs that are run by the `make runtests` or `make tapfiles` +commands get executed by a `.t` wrapper script which is normally generated by +the EPICS `makeTestfile.pl` program. Those generated wrapper scripts now +impose a time-limit on the test program they execute, and will kill it if it +runs for longer than 500 seconds (8 minutes 20) without exiting. That +time-limit can be changed for any such test by modifying the Makefile which +creates and runs the `.t` wrapper script. + +Setting the environment variable `EPICS_UNITTEST_TIMEOUT` to the desired +number of seconds while the Makefile is generating the test script changes the +timeout in that script. For example: + +``` + TESTSCRIPTS_HOST += hourLongTest.t + hourLongTest.t: export EPICS_UNITTEST_TIMEOUT=3600 +``` + +When selecting such a timeout remember that different Continuous Integration +systems such as GitHub Actions and Appveyor run on processors with different +speeds, so allow enough head-room for slower systems to complete the test. + +Test programs written directly in Perl as a `.plt` script should implement a +similar timeout for themselves. The "netget" test in Base does this in a way +that works on Windows as well as Unix-like hosts. ### Timeouts for Unit Test Programs @@ -1747,7 +1973,36 @@ header and removed the need for dbScan.c to reach into the internals of its # Changes incorporated from the 3.15 branch -## Changes made on the 3.15 branch since 3.15.8 +## Changes from the 3.15 branch since 3.15.9 + + +## Changes made between 3.15.8 and 3.15.9 + +### Use waitable timers on Microsoft Windows + +The `epicsEventWaitWithTimeout()` and `epicsThreadSleep()` functions have +been changed to use waitable timers. On Windows 10 version 1803 or higher +they will use high resolution timers for more consistent timing. + +See [this Google Groups thread](https://groups.google.com/a/chromium.org/g/scheduler-dev/c/0GlSPYreJeY) +for a comparison of the performance of different timers. + +### Build target for documentation + +The build target `inc` now works again after a very long hiatus. It now +generates and installs just the dbd, header and html files, without compiling +any C/C++ code. This can be used to speed up CI jobs that only generate +documentation. + +### Bug fixes + +- The error status returned by a record support's `special()` method is now propagated out of the `dbPut()` routine again (broken since 3.15.0). +- [gh: #80](https://github.com/epics-base/epics-base/issues/80), VS-2015 and +later have working strtod() +- [lp: #1776141](https://bugs.launchpad.net/epics-base/+bug/1776141), Catch +buffer overflow from long link strings +- [lp: #1899697](https://bugs.launchpad.net/epics-base/+bug/1899697), Records +in wrong PHAS order ### Change to the `junitfiles` self-test build target @@ -1755,7 +2010,9 @@ The names of the generated junit xml test output files have been changed from `.xml` to `-results.xml`, to allow better distinction from other xml files. (I.e., for easy wildcard matching.) ------ +### Fixes and code cleanups + +Issues reported by various static code checkers. ## Changes made between 3.15.7 and 3.15.8 diff --git a/modules/ca/src/client/Makefile b/modules/ca/src/client/Makefile index a8c0fed06..08394ea54 100644 --- a/modules/ca/src/client/Makefile +++ b/modules/ca/src/client/Makefile @@ -113,7 +113,7 @@ SCRIPTS_Linux = caRepeater.service EXPAND += S99caRepeater@ EXPAND += caRepeater.service@ -EXPAND_VARS = INSTALL_BIN=$(abspath $(INSTALL_BIN)) +EXPAND_VARS = INSTALL_BIN=$(FINAL_LOCATION)/bin/$(T_A) SRC_DIRS += $(CURDIR)/test PROD_HOST += ca_test diff --git a/modules/ca/src/client/caProto.h b/modules/ca/src/client/caProto.h index 1af7ec298..c6e211c11 100644 --- a/modules/ca/src/client/caProto.h +++ b/modules/ca/src/client/caProto.h @@ -17,6 +17,9 @@ #ifndef INC_caProto_H #define INC_caProto_H +// Pick up definition of IPPORT_USERRESERVED +#include + #define capStrOf(A) #A #define capStrOfX(A) capStrOf ( A ) diff --git a/modules/ca/src/client/caRepeater.cpp b/modules/ca/src/client/caRepeater.cpp index 7eaab508b..c8385ba3b 100644 --- a/modules/ca/src/client/caRepeater.cpp +++ b/modules/ca/src/client/caRepeater.cpp @@ -90,7 +90,7 @@ int main(int argc, char* argv[]) (void)detachinout; #endif - chdir ( "/" ); + (void)! chdir ( "/" ); ca_repeater (); return ( 0 ); } diff --git a/modules/ca/src/client/udpiiu.cpp b/modules/ca/src/client/udpiiu.cpp index ba1caa99b..723117a71 100644 --- a/modules/ca/src/client/udpiiu.cpp +++ b/modules/ca/src/client/udpiiu.cpp @@ -629,8 +629,8 @@ void epicsStdCall caStartRepeaterIfNotInstalled ( unsigned repeaterPort ) * repeater's port) */ osiSpawnDetachedProcessReturn osptr = - osiSpawnDetachedProcess ( "CA Repeater", "caRepeater" ); - if ( osptr == osiSpawnDetachedProcessNoSupport ) { + osiSpawnDetachedProcess ( "!CA Repeater", "caRepeater" ); + if ( osptr != osiSpawnDetachedProcessSuccess ) { epicsThreadId tid; tid = epicsThreadCreate ( "CAC-repeater", epicsThreadPriorityLow, @@ -639,9 +639,6 @@ void epicsStdCall caStartRepeaterIfNotInstalled ( unsigned repeaterPort ) fprintf ( stderr, "caStartRepeaterIfNotInstalled : unable to create CA repeater daemon thread\n" ); } } - else if ( osptr == osiSpawnDetachedProcessFail ) { - fprintf ( stderr, "caStartRepeaterIfNotInstalled (): unable to start CA repeater daemon detached process\n" ); - } } } diff --git a/modules/ca/src/perl/Cap5.xs b/modules/ca/src/perl/Cap5.xs index cc729340a..6d06a15f1 100644 --- a/modules/ca/src/perl/Cap5.xs +++ b/modules/ca/src/perl/Cap5.xs @@ -606,12 +606,12 @@ void CA_put(SV *ca_ref, SV *val, ...) { } } else { union { + void *dbr; dbr_char_t *dbr_char; dbr_long_t *dbr_long; dbr_double_t *dbr_double; char *dbr_string; - void *dbr; - } p; + } p = {0}; int i; chtype type = best_type(pch); @@ -699,12 +699,12 @@ void CA_put_callback(SV *ca_ref, SV *sub, SV *val, ...) { } } else { union { + void *dbr; dbr_char_t *dbr_char; dbr_long_t *dbr_long; dbr_double_t *dbr_double; char *dbr_string; - void *dbr; - } p; + } p = {0}; int i; chtype type = best_type(pch); diff --git a/modules/database/src/ioc/db/dbAccess.c b/modules/database/src/ioc/db/dbAccess.c index 46df26e83..295c6d543 100644 --- a/modules/database/src/ioc/db/dbAccess.c +++ b/modules/database/src/ioc/db/dbAccess.c @@ -360,6 +360,16 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options, *pushort++ = pcommon->ackt; pbuffer = (char *)pushort; } + if( (*options) & DBR_AMSG ) { + if (!pfl) { + STATIC_ASSERT(sizeof(pcommon->amsg)==sizeof(pfl->amsg)); + strncpy(pbuffer, pcommon->amsg, sizeof(pcommon->amsg)-1); + } else { + strncpy(pbuffer, pfl->amsg,sizeof(pfl->amsg)-1); + } + pbuffer[sizeof(pcommon->amsg)-1] = '\0'; + pbuffer += sizeof(pcommon->amsg); + } if( (*options) & DBR_UNITS ) { memset(pbuffer,'\0',dbr_units_size); if( prset && prset->get_units ){ @@ -392,6 +402,15 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options, } pbuffer = (char *)ptime; } + if( (*options) & DBR_UTAG ) { + epicsUInt64 *ptag = (epicsUInt64*)pbuffer; + if (!pfl) { + *ptag++ = pcommon->utag; + } else { + *ptag++ = pfl->utag; + } + pbuffer = (char *)ptag; + } if( (*options) & DBR_ENUM_STRS ) get_enum_strs(paddr, &pbuffer, prset, options); if( (*options) & (DBR_GR_LONG|DBR_GR_DOUBLE )) @@ -523,7 +542,7 @@ long dbProcess(dbCommon *precord) (precord->lcnt++ < MAX_LOCK) || (precord->sevr >= INVALID_ALARM)) goto all_done; - recGblSetSevr(precord, SCAN_ALARM, INVALID_ALARM); + recGblSetSevrMsg(precord, SCAN_ALARM, INVALID_ALARM, "Async in progress"); monitor_mask = recGblResetAlarms(precord); monitor_mask |= DBE_VALUE|DBE_LOG; pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes]; @@ -1385,7 +1404,8 @@ long dbPut(DBADDR *paddr, short dbrType, /* Always do special processing if needed */ if (special) { long status2 = dbPutSpecial(paddr, 1); - if (status2) goto done; + if (status2) + status = status2; } if (status) goto done; diff --git a/modules/database/src/ioc/db/dbAccessDefs.h b/modules/database/src/ioc/db/dbAccessDefs.h index bcd8d15df..771084170 100644 --- a/modules/database/src/ioc/db/dbAccessDefs.h +++ b/modules/database/src/ioc/db/dbAccessDefs.h @@ -33,16 +33,18 @@ DBCORE_API extern int dbAccessDebugPUTF; /* The database field and request types are defined in dbFldTypes.h*/ /* Data Base Request Options */ #define DBR_STATUS 0x00000001 -#define DBR_UNITS 0x00000002 -#define DBR_PRECISION 0x00000004 -#define DBR_TIME 0x00000008 -#define DBR_ENUM_STRS 0x00000010 -#define DBR_GR_LONG 0x00000020 -#define DBR_GR_DOUBLE 0x00000040 -#define DBR_CTRL_LONG 0x00000080 -#define DBR_CTRL_DOUBLE 0x00000100 -#define DBR_AL_LONG 0x00000200 -#define DBR_AL_DOUBLE 0x00000400 +#define DBR_AMSG 0x00000002 +#define DBR_UNITS 0x00000004 +#define DBR_PRECISION 0x00000008 +#define DBR_TIME 0x00000010 +#define DBR_UTAG 0x00000020 +#define DBR_ENUM_STRS 0x00000040 +#define DBR_GR_LONG 0x00000080 +#define DBR_GR_DOUBLE 0x00000100 +#define DBR_CTRL_LONG 0x00000200 +#define DBR_CTRL_DOUBLE 0x00000400 +#define DBR_AL_LONG 0x00000800 +#define DBR_AL_DOUBLE 0x00001000 /********************************************************************** * The next page contains macros for defining requests. @@ -100,6 +102,9 @@ DBCORE_API extern int dbAccessDebugPUTF; epicsUInt16 severity; /* alarm severity*/\ epicsUInt16 acks; /* alarm ack severity*/\ epicsUInt16 ackt; /* Acknowledge transient alarms?*/ +#define DB_AMSG_SIZE 40 +#define DBRamsg \ + char amsg[DB_AMSG_SIZE]; #define DB_UNITS_SIZE 16 #define DBRunits \ char units[DB_UNITS_SIZE]; /* units */ @@ -112,7 +117,9 @@ DBCORE_API extern int dbAccessDebugPUTF; * too late to change now. DBRprecision must be padded to * maintain 8-byte alignment. */ #define DBRtime \ - epicsTimeStamp time; /* time stamp*/ + epicsTimeStamp time; /* time stamp*/ +#define DBRutag \ + epicsUTag utag; #define DBRenumStrs \ epicsUInt32 no_str; /* number of strings*/\ epicsInt32 padenumStrs; /*padding to force 8 byte align*/\ diff --git a/modules/database/src/ioc/db/dbCommon.dbd.pod b/modules/database/src/ioc/db/dbCommon.dbd.pod index 36b9c1adb..5ad4627c5 100644 --- a/modules/database/src/ioc/db/dbCommon.dbd.pod +++ b/modules/database/src/ioc/db/dbCommon.dbd.pod @@ -279,6 +279,11 @@ support routines which write to the VAL field are responsible for setting UDF. special(SPC_NOMOD) menu(menuAlarmSevr) } + field(AMSG,DBF_STRING) { + prompt("Alarm Message") + special(SPC_NOMOD) + size(40) + } field(NSTA,DBF_MENU) { prompt("New Alarm Status") special(SPC_NOMOD) @@ -291,6 +296,11 @@ support routines which write to the VAL field are responsible for setting UDF. interest(2) menu(menuAlarmSevr) } + field(NAMSG,DBF_STRING) { + prompt("New Alarm Message") + special(SPC_NOMOD) + size(40) + } field(ACKS,DBF_MENU) { prompt("Alarm Ack Severity") special(SPC_NOMOD) @@ -514,6 +524,11 @@ field which is then used to acquire a timestamp. interest(2) extra("epicsTimeStamp time") } + field(UTAG,DBF_UINT64) { + prompt("Time Tag") + special(SPC_NOMOD) + interest(3) + } field(FLNK,DBF_FWDLINK) { prompt("Forward Process Link") promptgroup("20 - Scan") diff --git a/modules/database/src/ioc/db/dbDbLink.c b/modules/database/src/ioc/db/dbDbLink.c index 0fb325f30..f8cfd8b5e 100644 --- a/modules/database/src/ioc/db/dbDbLink.c +++ b/modules/database/src/ioc/db/dbDbLink.c @@ -337,8 +337,8 @@ static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize) return 0; } -static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) +static long dbDbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { dbChannel *chan = linkChannel(plink); dbCommon *precord = dbChannelRecord(chan); @@ -346,14 +346,20 @@ static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status, *status = precord->stat; if (severity) *severity = precord->sevr; + if (msgbuf && msgbuflen) { + strncpy(msgbuf, precord->amsg, msgbuflen-1); + msgbuf[msgbuflen-1] = '\0'; + } return 0; } -static long dbDbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp) +static long dbDbGetTimeStampTag(const struct link *plink, epicsTimeStamp *pstamp, epicsUTag *ptag) { dbChannel *chan = linkChannel(plink); dbCommon *precord = dbChannelRecord(chan); *pstamp = precord->time; + if(ptag) + *ptag = precord->utag; return 0; } @@ -401,9 +407,11 @@ static lset dbDb_lset = { dbDbGetValue, dbDbGetControlLimits, dbDbGetGraphicLimits, dbDbGetAlarmLimits, dbDbGetPrecision, dbDbGetUnits, - dbDbGetAlarm, dbDbGetTimeStamp, + NULL, NULL, dbDbPutValue, NULL, - dbDbScanFwdLink, doLocked + dbDbScanFwdLink, doLocked, + dbDbGetAlarmMsg, + dbDbGetTimeStampTag, }; diff --git a/modules/database/src/ioc/db/dbEvent.c b/modules/database/src/ioc/db/dbEvent.c index 6de565236..b3c641798 100644 --- a/modules/database/src/ioc/db/dbEvent.c +++ b/modules/database/src/ioc/db/dbEvent.c @@ -84,6 +84,7 @@ struct event_user { epicsMutexId lock; epicsEventId ppendsem; /* Wait while empty */ epicsEventId pflush_sem; /* wait for flush */ + epicsEventId pexitsem; /* wait for event task to join */ EXTRALABORFUNC *extralabor_sub;/* off load to event task */ void *extralabor_arg;/* parameter to above */ @@ -122,6 +123,8 @@ static char *EVENT_PEND_NAME = "eventTask"; static struct evSubscrip canceledEvent; +static epicsMutexId stopSync; + static unsigned short ringSpace ( const struct event_que *pevq ) { if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) { @@ -260,6 +263,10 @@ int dbel ( const char *pname, unsigned level ) */ void db_init_event_freelists (void) { + if (!stopSync) { + stopSync = epicsMutexMustCreate(); + } + if (!dbevEventUserFreeList) { freeListInitPvt(&dbevEventUserFreeList, sizeof(struct event_user),8); @@ -299,6 +306,9 @@ dbEventCtx db_init_events (void) return NULL; } + /* Flag will be cleared when event task starts */ + evUser->pendexit = TRUE; + evUser->firstque.evUser = evUser; evUser->firstque.writelock = epicsMutexCreate(); if (!evUser->firstque.writelock) @@ -313,6 +323,9 @@ dbEventCtx db_init_events (void) evUser->lock = epicsMutexCreate(); if (!evUser->lock) goto fail; + evUser->pexitsem = epicsEventCreate(epicsEventEmpty); + if (!evUser->pexitsem) + goto fail; evUser->flowCtrlMode = FALSE; evUser->extraLaborBusy = FALSE; @@ -327,6 +340,8 @@ fail: epicsEventDestroy (evUser->ppendsem); if(evUser->pflush_sem) epicsEventDestroy (evUser->pflush_sem); + if(evUser->pexitsem) + epicsEventDestroy (evUser->pexitsem); freeListFree(dbevEventUserFreeList,evUser); return NULL; } @@ -347,6 +362,7 @@ DBCORE_API void db_cleanup_events(void) dbevFieldLogFreeList = NULL; } + /* intentionally leak stopSync to avoid possible shutdown races */ /* * DB_CLOSE_EVENTS() * @@ -368,15 +384,31 @@ void db_close_events (dbEventCtx ctx) * hazardous to the system's health. */ epicsMutexMustLock ( evUser->lock ); - evUser->pendexit = TRUE; + if(!evUser->pendexit) { /* event task running */ + evUser->pendexit = TRUE; + epicsMutexUnlock ( evUser->lock ); + + /* notify the waiting task */ + epicsEventSignal(evUser->ppendsem); + /* wait for task to exit */ + epicsEventMustWait(evUser->pexitsem); + epicsThreadMustJoin(evUser->taskid); + + epicsMutexMustLock ( evUser->lock ); + } + epicsMutexUnlock ( evUser->lock ); - /* notify the waiting task */ - epicsEventSignal(evUser->ppendsem); + epicsMutexMustLock (stopSync); - if(evUser->taskid) - epicsThreadMustJoin(evUser->taskid); - /* evUser has been deleted by the worker */ + epicsEventDestroy(evUser->pexitsem); + epicsEventDestroy(evUser->ppendsem); + epicsEventDestroy(evUser->pflush_sem); + epicsMutexDestroy(evUser->lock); + + epicsMutexUnlock (stopSync); + + freeListFree(dbevEventUserFreeList, evUser); } /* @@ -675,7 +707,10 @@ static db_field_log* db_create_field_log (struct dbChannel *chan, int use_val) struct dbCommon *prec = dbChannelRecord(chan); pLog->stat = prec->stat; pLog->sevr = prec->sevr; + strncpy(pLog->amsg, prec->amsg, sizeof(pLog->amsg)-1); + pLog->amsg[sizeof(pLog->amsg)-1] = '\0'; pLog->time = prec->time; + pLog->utag = prec->utag; pLog->field_type = dbChannelFieldType(chan); pLog->field_size = dbChannelFieldSize(chan); pLog->no_elements = dbChannelElements(chan); @@ -1060,18 +1095,17 @@ static void event_task (void *pParm) } } - epicsEventDestroy(evUser->ppendsem); - epicsEventDestroy(evUser->pflush_sem); - epicsMutexDestroy(evUser->lock); - - if (dbevEventUserFreeList) - freeListFree(dbevEventUserFreeList, evUser); - else - fprintf(stderr, "%s exiting but dbevEventUserFreeList already NULL\n", - __FUNCTION__); - taskwdRemove(epicsThreadGetIdSelf()); + /* use stopSync to ensure pexitsem is not destroy'd + * until epicsEventSignal() has returned. + */ + epicsMutexMustLock (stopSync); + + epicsEventSignal(evUser->pexitsem); + + epicsMutexUnlock(stopSync); + return; } @@ -1111,6 +1145,7 @@ int db_start_events ( epicsMutexUnlock ( evUser->lock ); return DB_EVENT_ERROR; } + evUser->pendexit = FALSE; epicsMutexUnlock ( evUser->lock ); return DB_EVENT_OK; } diff --git a/modules/database/src/ioc/db/dbLink.c b/modules/database/src/ioc/db/dbLink.c index d23355e0e..f5d286447 100644 --- a/modules/database/src/ioc/db/dbLink.c +++ b/modules/database/src/ioc/db/dbLink.c @@ -313,10 +313,16 @@ long dbTryGetLink(struct link *plink, short dbrType, void *pbuffer, return plset->getValue(plink, dbrType, pbuffer, pnRequest); } +static +void setLinkAlarm(struct link* plink) +{ + recGblSetSevrMsg(plink->precord, LINK_ALARM, INVALID_ALARM, + "field %s", dbLinkFieldName(plink)); +} + long dbGetLink(struct link *plink, short dbrType, void *pbuffer, long *poptions, long *pnRequest) { - struct dbCommon *precord = plink->precord; long status; if (poptions && *poptions) { @@ -328,7 +334,7 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer, if (status == S_db_noLSET) return -1; if (status) - recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); + setLinkAlarm(plink); return status; } @@ -385,24 +391,42 @@ long dbGetUnits(const struct link *plink, char *units, int unitsSize) } long dbGetAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) + epicsEnum16 *severity) +{ + return dbGetAlarmMsg(plink, status, severity, NULL, 0); +} + +long dbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { lset *plset = plink->lset; - if (!plset || !plset->getAlarm) + if (plset && plset->getAlarmMsg) { + return plset->getAlarmMsg(plink, status, severity, msgbuf, msgbuflen); + } else if(plset && plset->getAlarm) { + return plset->getAlarm(plink, status, severity); + } else { return S_db_noLSET; - - return plset->getAlarm(plink, status, severity); + } } long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp) +{ + return dbGetTimeStampTag(plink, pstamp, NULL); +} + +long dbGetTimeStampTag(const struct link *plink, + epicsTimeStamp *pstamp, epicsUTag *ptag) { lset *plset = plink->lset; - if (!plset || !plset->getTimeStamp) + if (plset && plset->getTimeStampTag) { + return plset->getTimeStampTag(plink, pstamp, ptag); + } else if(plset && plset->getTimeStamp) { + return plset->getTimeStamp(plink, pstamp); + } else { return S_db_noLSET; - - return plset->getTimeStamp(plink, pstamp); + } } long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, @@ -416,9 +440,7 @@ long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, status = plset->putValue(plink, dbrType, pbuffer, nRequest); if (status) { - struct dbCommon *precord = plink->precord; - - recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); + setLinkAlarm(plink); } return status; } @@ -443,9 +465,7 @@ long dbPutLinkAsync(struct link *plink, short dbrType, const void *pbuffer, status = plset->putAsync(plink, dbrType, pbuffer, nRequest); if (status) { - struct dbCommon *precord = plink->precord; - - recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); + setLinkAlarm(plink); } return status; } diff --git a/modules/database/src/ioc/db/dbLink.h b/modules/database/src/ioc/db/dbLink.h index dd7163c8c..d1e454485 100644 --- a/modules/database/src/ioc/db/dbLink.h +++ b/modules/database/src/ioc/db/dbLink.h @@ -361,6 +361,29 @@ typedef struct lset { * @returns status value */ long (*doLocked)(struct link *plink, dbLinkUserCallback rtn, void *priv); + + /** @brief Extended version of getAlarm + * + * Equivalent of getAlarm() and also copy out alarm message string. + * The msgbuf argument may be NULL and/or msgbuflen==0, in which case + * the effect must be the same as a call to getAlarm(). + * + * Implementations must write a trailing nil to msgbuf whenever + * @code msgbuf!=NULL && msgbuflen>0 @endcode . + * + * @since 7.0.6 + */ + long (*getAlarmMsg)(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen); + + /** @brief Extended version of getTimeStamp + * + * Equivalent of getTimeStamp() and also copy out time tag. + * ptag may be NULL. + * + * @since Added after 7.0.6 + */ + long (*getTimeStampTag)(const struct link *plink, epicsTimeStamp *pstamp, epicsUTag *ptag); } lset; #define dbGetSevr(link, sevr) \ @@ -402,8 +425,20 @@ DBCORE_API long dbGetUnits(const struct link *plink, char *units, int unitsSize); DBCORE_API long dbGetAlarm(const struct link *plink, epicsEnum16 *status, epicsEnum16 *severity); +/** Get link alarm and message string. + * To ensure the complete message string is copied, ensure @code msgbuflen >= sizeof (dbCommon::amsg) @endcode . + * A trailing nil will be added whenever @code msgbuflen > 0 @endcode . + * @since 7.0.6 + */ +DBCORE_API long dbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen); +#define dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) DBCORE_API long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp); +/** @since 7.0.6 */ +DBCORE_API long dbGetTimeStampTag(const struct link *plink, + epicsTimeStamp *pstamp, epicsUTag *ptag); +#define dbGetTimeStampTag(LINK, STAMP, TAG) dbGetTimeStampTag(LINK, STAMP, TAG) DBCORE_API long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, long nRequest); DBCORE_API void dbLinkAsyncComplete(struct link *plink); diff --git a/modules/database/src/ioc/db/dbUnitTest.c b/modules/database/src/ioc/db/dbUnitTest.c index a4830a37c..805031bc2 100644 --- a/modules/database/src/ioc/db/dbUnitTest.c +++ b/modules/database/src/ioc/db/dbUnitTest.c @@ -266,7 +266,7 @@ done: void testdbPutArrFieldOk(const char* pv, short dbrType, unsigned long count, const void *pbuf) { dbChannel *chan = dbChannelCreate(pv); - long status; + long status = -1; if(!chan || (status=dbChannelOpen(chan))) { testFail("Channel error (%p, %ld) : %s", chan, status, pv); @@ -289,7 +289,7 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign const long vSize = dbValueSize(dbfType); const long nStore = vSize * nRequest; long status = S_dbLib_recNotFound; - char *gbuf, *gstore; + char *gbuf, *gstore = NULL; const char *pbuf = pbufraw; if(!chan || (status=dbChannelOpen(chan))) { diff --git a/modules/database/src/ioc/db/db_field_log.h b/modules/database/src/ioc/db/db_field_log.h index f9b7cfbd4..b9deb6fe9 100644 --- a/modules/database/src/ioc/db/db_field_log.h +++ b/modules/database/src/ioc/db/db_field_log.h @@ -113,8 +113,10 @@ typedef struct db_field_log { unsigned char mask; /* DBE_* mask */ /* the following are used for value and reference types */ epicsTimeStamp time; /* Time stamp */ + epicsUTag utag; unsigned short stat; /* Alarm Status */ unsigned short sevr; /* Alarm Severity */ + char amsg[40]; short field_type; /* DBF type of data */ short field_size; /* Size of a single element */ long no_elements; /* No of valid array elements */ diff --git a/modules/database/src/ioc/db/recGbl.c b/modules/database/src/ioc/db/recGbl.c index e9f6e5e89..9f5b90479 100644 --- a/modules/database/src/ioc/db/recGbl.c +++ b/modules/database/src/ioc/db/recGbl.c @@ -24,6 +24,7 @@ #include "epicsMath.h" #include "epicsPrint.h" #include "epicsStdlib.h" +#include "epicsStdio.h" #include "epicsTime.h" #include "errlog.h" @@ -184,6 +185,11 @@ unsigned short recGblResetAlarms(void *precord) if (new_sevr > INVALID_ALARM) new_sevr = INVALID_ALARM; + if(strcmp(pdbc->namsg, pdbc->amsg)!=0) { + strcpy(pdbc->amsg, pdbc->namsg); + stat_mask = DBE_ALARM; + } + pdbc->stat = new_stat; pdbc->sevr = new_sevr; pdbc->nsta = 0; @@ -198,6 +204,7 @@ unsigned short recGblResetAlarms(void *precord) } if (stat_mask) { db_post_events(pdbc, &pdbc->stat, stat_mask); + db_post_events(pdbc, &pdbc->amsg, stat_mask); val_mask = DBE_ALARM; if (!pdbc->ackt || new_sevr >= pdbc->acks) { @@ -211,18 +218,44 @@ unsigned short recGblResetAlarms(void *precord) } return val_mask; } +int recGblSetSevrMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, ...) +{ + int ret; + va_list args; + va_start(args, msg); + ret = recGblSetSevrVMsg(precord, new_stat, new_sevr, msg, args); + va_end(args); + return ret; +} -int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr) +int recGblSetSevrVMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, va_list args) { struct dbCommon *prec = precord; if (prec->nsev < new_sevr) { prec->nsta = new_stat; prec->nsev = new_sevr; + if(msg) { + epicsVsnprintf(prec->namsg, sizeof(prec->namsg)-1, msg, args); + prec->namsg[sizeof(prec->namsg)-1] = '\0'; + + } else { + prec->namsg[0] = '\0'; + } + prec->namsg[sizeof(prec->namsg)-1] = '\0'; return TRUE; } return FALSE; } +int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr) +{ + return recGblSetSevrMsg(precord, new_stat, new_sevr, NULL); +} + void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat, epicsEnum16 sevr) { @@ -271,7 +304,7 @@ void recGblGetTimeStampSimm(void *pvoid, const epicsEnum16 simm, struct link *si if (!dbLinkIsConstant(plink)) { if (plink->flags & DBLINK_FLAG_TSELisTIME) { - if (dbGetTimeStamp(plink, &prec->time)) + if (dbGetTimeStampTag(plink, &prec->time, &prec->utag)) errlogPrintf("recGblGetTimeStamp: dbGetTimeStamp failed for %s.TSEL\n", prec->name); return; diff --git a/modules/database/src/ioc/db/recGbl.h b/modules/database/src/ioc/db/recGbl.h index fd08123ef..e362b8bd4 100644 --- a/modules/database/src/ioc/db/recGbl.h +++ b/modules/database/src/ioc/db/recGbl.h @@ -15,6 +15,9 @@ #ifndef INCrecGblh #define INCrecGblh 1 +#include + +#include "compilerDependencies.h" #include "epicsTypes.h" #include "dbCoreAPI.h" @@ -22,6 +25,14 @@ extern "C" { #endif +/** Feature test macro for alarm message (AMSG) field and support + * + * Covers addition of dbCommon::amsg, recGblSetSevrMsg(), lset::getAlarmMsg() + * + * @since 7.0.6 + */ +#define HAS_ALARM_MESSAGE 1 + /*************************************************************************/ /* Structures needed for args */ @@ -62,6 +73,12 @@ DBCORE_API int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr); DBCORE_API void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat, epicsEnum16 sevr); +DBCORE_API int recGblSetSevrMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, ...) EPICS_PRINTF_STYLE(4,5); +DBCORE_API int recGblSetSevrVMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, va_list args); DBCORE_API void recGblFwdLink(void *precord); DBCORE_API void recGblGetTimeStamp(void *precord); DBCORE_API void recGblGetTimeStampSimm(void *prec, const epicsEnum16 simm, struct link *siol); diff --git a/modules/database/src/std/dev/devEnviron.c b/modules/database/src/std/dev/devEnviron.c index 77b89d001..910f1f0c7 100644 --- a/modules/database/src/std/dev/devEnviron.c +++ b/modules/database/src/std/dev/devEnviron.c @@ -63,7 +63,7 @@ static long read_lsi(lsiRecord *prec) prec->val[0] = 0; prec->len = 1; prec->udf = TRUE; - recGblSetSevr(prec, UDF_ALARM, prec->udfs); + recGblSetSevrMsg(prec, UDF_ALARM, prec->udfs, "No such ENV"); } return 0; @@ -114,7 +114,7 @@ static long read_stringin(stringinRecord *prec) else { prec->val[0] = 0; prec->udf = TRUE; - recGblSetSevr(prec, UDF_ALARM, prec->udfs); + recGblSetSevrMsg(prec, UDF_ALARM, prec->udfs, "No such ENV"); } return 0; diff --git a/modules/database/src/std/filters/Makefile b/modules/database/src/std/filters/Makefile index ee6a0ae68..b02999403 100644 --- a/modules/database/src/std/filters/Makefile +++ b/modules/database/src/std/filters/Makefile @@ -16,6 +16,7 @@ dbRecStd_SRCS += dbnd.c dbRecStd_SRCS += arr.c dbRecStd_SRCS += sync.c dbRecStd_SRCS += decimate.c +dbRecStd_SRCS += utag.c HTMLS += filters.html diff --git a/modules/database/src/std/filters/filters.dbd.pod b/modules/database/src/std/filters/filters.dbd.pod index 27e356f83..7b3146609 100644 --- a/modules/database/src/std/filters/filters.dbd.pod +++ b/modules/database/src/std/filters/filters.dbd.pod @@ -16,6 +16,8 @@ The following filters are available in this release: =item * L +=item * L + =back =head2 Using Filters @@ -285,3 +287,26 @@ once every minute: ... =cut + +registrar(utagInitialize) + +=head3 UTag Filter C<"utag"> + +This filter applies a test UTAG&M==V to the value taken from the UTAG record field +and drops those updates which evaluate as false. + +=head4 Parameters + +=over + +=item Mask C<"M"> + +Bit mask. + +=item Value C<"V"> + +Required value. + +=back + +=cut diff --git a/modules/database/src/std/filters/utag.c b/modules/database/src/std/filters/utag.c new file mode 100644 index 000000000..b17f3e8a0 --- /dev/null +++ b/modules/database/src/std/filters/utag.c @@ -0,0 +1,99 @@ +/*************************************************************************\ +* Copyright (c) 2020 Michael Davidsaver +* 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 + +typedef struct { + epicsInt32 mask, value; + int first; +} utagPvt; + +static const +chfPluginArgDef opts[] = { + chfInt32(utagPvt, mask, "M", 0, 1), + chfInt32(utagPvt, value, "V", 0, 1), + chfPluginArgEnd +}; + +static void * allocPvt(void) +{ + utagPvt *pvt; + pvt = calloc(1, sizeof(utagPvt)); + pvt->mask = 0xffffffff; + return pvt; +} + +static void freePvt(void *pvt) +{ + free(pvt); +} + +static int parse_ok(void *raw) +{ + utagPvt *pvt = (utagPvt*)raw; + pvt->first = 1; + return 0; +} + +static db_field_log* filter(void* raw, dbChannel *chan, db_field_log *pfl) +{ + utagPvt *pvt = (utagPvt*)raw; + epicsUTag utag = pfl->utag; + int drop = (utag&pvt->mask)!=pvt->value; + + if(pfl->ctx!=dbfl_context_event || pfl->mask&DBE_PROPERTY) { + /* never drop for reads, or property events */ + + } else if(pvt->first) { + /* never drop first */ + pvt->first = 0; + + } else if(drop) { + db_delete_field_log(pfl); + pfl = NULL; + } + + return pfl; +} + +static void channelRegisterPre(dbChannel *chan, void *pvt, + chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) +{ + *cb_out = filter; + *arg_out = pvt; +} + +static void channel_report(dbChannel *chan, void *raw, int level, const unsigned short indent) +{ + utagPvt *pvt = (utagPvt*)raw; + printf("%*sutag : mask=0x%08x value=0x%08x\n", indent, "", (epicsUInt32)pvt->mask, (epicsUInt32)pvt->value); +} + +static const +chfPluginIf pif = { + allocPvt, + freePvt, + NULL, /* parse_error */ + parse_ok, /* parse_ok */ + NULL, /* channel_open */ + channelRegisterPre, + NULL, /* channelRegisterPost */ + channel_report, + NULL, /* channel_close */ +}; + +static +void utagInitialize(void) +{ + chfPluginRegister("utag", &pif, opts); +} +epicsExportRegistrar(utagInitialize); diff --git a/modules/database/src/std/link/lnkCalc.c b/modules/database/src/std/link/lnkCalc.c index 8d7f72c69..46655850e 100644 --- a/modules/database/src/std/link/lnkCalc.c +++ b/modules/database/src/std/link/lnkCalc.c @@ -53,6 +53,7 @@ typedef struct calc_link { } pstate; epicsEnum16 stat; epicsEnum16 sevr; + char amsg[DB_AMSG_SIZE]; short prec; char *expr; char *major; @@ -66,6 +67,7 @@ typedef struct calc_link { struct link out; double arg[CALCPERFORM_NARGS]; epicsTimeStamp time; + epicsUTag utag; double val; } calc_link; @@ -385,9 +387,10 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent) if (level > 0) { if (clink->sevr) - printf("%*s Alarm: %s, %s\n", indent, "", + printf("%*s Alarm: %s, %s, \"%s\"\n", indent, "", epicsAlarmSeverityStrings[clink->sevr], - epicsAlarmConditionStrings[clink->stat]); + epicsAlarmConditionStrings[clink->stat], + clink->amsg); if (clink->post_major) printf("%*s Major expression: \"%s\"\n", indent, "", @@ -532,6 +535,7 @@ static long lnkCalc_getElements(const struct link *plink, long *nelements) struct lcvt { double *pval; epicsTimeStamp *ptime; + epicsUTag *ptag; }; static long readLocked(struct link *pinp, void *vvt) @@ -541,7 +545,7 @@ static long readLocked(struct link *pinp, void *vvt) long status = dbGetLink(pinp, DBR_DOUBLE, pvt->pval, NULL, &nReq); if (!status && pvt->ptime) - dbGetTimeStamp(pinp, pvt->ptime); + dbGetTimeStampTag(pinp, pvt->ptime, pvt->ptag); return status; } @@ -567,7 +571,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, long nReq = 1; if (i == clink->tinp) { - struct lcvt vt = {&clink->arg[i], &clink->time}; + struct lcvt vt = {&clink->arg[i], &clink->time, &clink->utag}; status = dbLinkDoLocked(child, readLocked, &vt); if (status == S_db_noLSET) @@ -576,6 +580,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) { prec->time = clink->time; + prec->utag = clink->utag; } } else @@ -583,6 +588,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, } clink->stat = 0; clink->sevr = 0; + clink->amsg[0] = '\0'; if (clink->post_expr) { status = calcPerform(clink->arg, &clink->val, clink->post_expr); @@ -604,7 +610,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MAJOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error"); } } @@ -615,7 +622,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MINOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_minor error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error"); } } @@ -643,7 +651,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, long nReq = 1; if (i == clink->tinp) { - struct lcvt vt = {&clink->arg[i], &clink->time}; + struct lcvt vt = {&clink->arg[i], &clink->time, &clink->utag}; status = dbLinkDoLocked(child, readLocked, &vt); if (status == S_db_noLSET) @@ -652,6 +660,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) { prec->time = clink->time; + prec->utag = clink->utag; } } else @@ -659,6 +668,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, } clink->stat = 0; clink->sevr = 0; + clink->amsg[0] = '\0'; /* Get the value being output as VAL */ status = conv(pbuffer, &clink->val, NULL); @@ -673,7 +683,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MAJOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error"); } } @@ -684,7 +695,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MINOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error"); } } @@ -718,8 +730,8 @@ static long lnkCalc_getUnits(const struct link *plink, char *units, int len) return 0; } -static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) +static long lnkCalc_getAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { calc_link *clink = CONTAINER(plink->value.json.jlink, struct calc_link, jlink); @@ -728,17 +740,23 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status, *status = clink->stat; if (severity) *severity = clink->sevr; + if (msgbuf && msgbuflen) { + strncpy(msgbuf, clink->amsg, msgbuflen-1); + msgbuf[msgbuflen-1] = '\0'; + } return 0; } -static long lnkCalc_getTimestamp(const struct link *plink, epicsTimeStamp *pstamp) +static long lnkCalc_getTimestampTag(const struct link *plink, epicsTimeStamp *pstamp, epicsUTag *ptag) { calc_link *clink = CONTAINER(plink->value.json.jlink, struct calc_link, jlink); if (clink->tinp >= 0) { *pstamp = clink->time; + if(ptag) + *ptag = clink->utag; return 0; } @@ -761,9 +779,11 @@ static lset lnkCalc_lset = { lnkCalc_getValue, NULL, NULL, NULL, lnkCalc_getPrecision, lnkCalc_getUnits, - lnkCalc_getAlarm, lnkCalc_getTimestamp, + NULL, NULL, lnkCalc_putValue, NULL, - NULL, doLocked + NULL, doLocked, + lnkCalc_getAlarmMsg, + lnkCalc_getTimestampTag, }; static jlif lnkCalcIf = { diff --git a/modules/database/src/std/rec/aiRecord.c b/modules/database/src/std/rec/aiRecord.c index c149211b9..8d31b07ff 100644 --- a/modules/database/src/std/rec/aiRecord.c +++ b/modules/database/src/std/rec/aiRecord.c @@ -432,7 +432,7 @@ static void convert(aiRecord *prec) default: /* must use breakpoint table */ if (cvtRawToEngBpt(&val,prec->linr,prec->init,(void *)&prec->pbrk,&prec->lbrk)!=0) { - recGblSetSevr(prec,SOFT_ALARM,MAJOR_ALARM); + recGblSetSevrMsg(prec,SOFT_ALARM,MAJOR_ALARM, "BPT Error"); } } diff --git a/modules/database/src/std/rec/calcoutRecord.c b/modules/database/src/std/rec/calcoutRecord.c index dbd6be3f9..eadcc5862 100644 --- a/modules/database/src/std/rec/calcoutRecord.c +++ b/modules/database/src/std/rec/calcoutRecord.c @@ -236,7 +236,7 @@ static long process(struct dbCommon *pcommon) } if (fetch_values(prec) == 0) { if (calcPerform(&prec->a, &prec->val, prec->rpcl)) { - recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM); + recGblSetSevrMsg(prec, CALC_ALARM, INVALID_ALARM, "calcPerform"); } else { prec->udf = isnan(prec->val); } @@ -610,7 +610,7 @@ static void execOutput(calcoutRecord *prec) break; case calcoutDOPT_Use_OVAL: if (calcPerform(&prec->a, &prec->oval, prec->orpc)) { - recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM); + recGblSetSevrMsg(prec, CALC_ALARM, INVALID_ALARM, "OCAL calcPerform"); } else { prec->udf = isnan(prec->oval); } @@ -770,7 +770,7 @@ static long writeValue(calcoutRecord *prec) if (!pcalcoutDSET || !pcalcoutDSET->write) { errlogPrintf("%s DSET write does not exist\n", prec->name); - recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); + recGblSetSevrMsg(prec, SOFT_ALARM, INVALID_ALARM, "DSET write does not exist"); prec->pact = TRUE; return(-1); } diff --git a/modules/database/src/std/softIoc/Makefile b/modules/database/src/std/softIoc/Makefile index a432d358d..35ef6cb34 100644 --- a/modules/database/src/std/softIoc/Makefile +++ b/modules/database/src/std/softIoc/Makefile @@ -28,7 +28,5 @@ softIoc_LIBS = $(EPICS_BASE_IOC_LIBS) DB += softIocExit.db -FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION)) - CLEANS += epicsInstallDir.h diff --git a/modules/database/src/std/softIoc/softMain.cpp b/modules/database/src/std/softIoc/softMain.cpp index cdb0f4a81..367e23ed8 100644 --- a/modules/database/src/std/softIoc/softMain.cpp +++ b/modules/database/src/std/softIoc/softMain.cpp @@ -249,7 +249,10 @@ int main(int argc, char *argv[]) } else { if (loadedDb || ranScript) { - epicsThreadExitMain(); + // non-interactive IOC. spin forever + while(true) { + epicsThreadSleep(1000.0); + } } else { usage(argv[0], dbd_file); diff --git a/modules/database/src/tools/Makefile b/modules/database/src/tools/Makefile index f54ab9c07..41bf086d3 100644 --- a/modules/database/src/tools/Makefile +++ b/modules/database/src/tools/Makefile @@ -40,7 +40,6 @@ HTMLS += dbdToHtml.html # Build Package Config Files -FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION)) C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CPPFLAGS)))) C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CFLAGS)))) PKGVARS += FINAL_LOCATION OS_CLASS CMPLR_CLASS C_CFLAGS LDFLAGS LDLIBS diff --git a/modules/database/test/ioc/db/Makefile b/modules/database/test/ioc/db/Makefile index 2ecc7e820..f059226d9 100644 --- a/modules/database/test/ioc/db/Makefile +++ b/modules/database/test/ioc/db/Makefile @@ -117,6 +117,13 @@ testHarness_SRCS += dbCACTest.cpp TESTS += dbCaLinkTest TESTFILES += ../dbCaLinkTest1.db ../dbCaLinkTest2.db ../dbCaLinkTest3.db +TESTPROD_HOST += dbDbLinkTest +dbDbLinkTest_SRCS += dbDbLinkTest.c +dbDbLinkTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += dbDbLinkTest.c +TESTS += dbDbLinkTest +TESTFILES += ../dbDbLinkTest.db + TESTPROD_HOST += scanIoTest scanIoTest_SRCS += scanIoTest.c scanIoTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp @@ -200,7 +207,9 @@ include $(TOP)/configure/RULES arrRecord$(DEP): $(COMMON_DIR)/arrRecord.h dbCaLinkTest$(DEP): $(COMMON_DIR)/xRecord.h $(COMMON_DIR)/arrRecord.h +dbDbLinkTest$(DEP): $(COMMON_DIR)/xRecord.h dbPutLinkTest$(DEP): $(COMMON_DIR)/xRecord.h +dbPutGetTest$(DEP): $(COMMON_DIR)/xRecord.h dbStressLock$(DEP): $(COMMON_DIR)/xRecord.h devx$(DEP): $(COMMON_DIR)/xRecord.h scanIoTest$(DEP): $(COMMON_DIR)/xRecord.h diff --git a/modules/database/test/ioc/db/callbackParallelTest.c b/modules/database/test/ioc/db/callbackParallelTest.c index 731ed361b..7955fb6a1 100644 --- a/modules/database/test/ioc/db/callbackParallelTest.c +++ b/modules/database/test/ioc/db/callbackParallelTest.c @@ -54,7 +54,7 @@ typedef struct myPvt { int resultFail; } myPvt; -epicsEventId finished; +static epicsEventId finished; static void myCallback(epicsCallback *pCallback) { diff --git a/modules/database/test/ioc/db/callbackTest.c b/modules/database/test/ioc/db/callbackTest.c index e83943b4a..2863720f0 100644 --- a/modules/database/test/ioc/db/callbackTest.c +++ b/modules/database/test/ioc/db/callbackTest.c @@ -54,7 +54,7 @@ typedef struct myPvt { int resultFail; } myPvt; -epicsEventId finished; +static epicsEventId finished; static void myCallback(epicsCallback *pCallback) diff --git a/modules/database/test/ioc/db/dbDbLinkTest.c b/modules/database/test/ioc/db/dbDbLinkTest.c new file mode 100644 index 000000000..489df4daf --- /dev/null +++ b/modules/database/test/ioc/db/dbDbLinkTest.c @@ -0,0 +1,136 @@ +/*************************************************************************\ + * Copyright (c) 2020 Michael Davidsaver + * SPDX-License-Identifier: EPICS + * 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 +#include + +#include "xRecord.h" + +void dbTestIoc_registerRecordDeviceDriver(struct dbBase *); + +static +void checkTime(void) +{ + epicsTimeStamp stamp; + epicsUTag tag; + + dbCommon* target = testdbRecordPtr("target"); + dbCommon* src = testdbRecordPtr("src"); + + testDiag("checkTime()"); + + dbScanLock(target); + target->time.secPastEpoch = 0x12345678; + target->time.nsec = 0x9abcdef0; + target->utag = 0xdeadbeef; + dbScanUnlock(target); + + dbScanLock(src); + testOk1(0==dbGetTimeStamp(dbGetDevLink(src), &stamp)); + dbScanUnlock(src); + + testOk1(stamp.secPastEpoch==0x12345678); + testOk1(stamp.nsec==0x9abcdef0); + stamp.secPastEpoch = 0; + stamp.nsec = 0; + + dbScanLock(src); + testOk1(0==dbGetTimeStampTag(dbGetDevLink(src), &stamp, &tag)); + dbScanUnlock(src); + + testOk1(stamp.secPastEpoch==0x12345678); + testOk1(stamp.nsec==0x9abcdef0); + testOk1(tag==0xdeadbeef); +} + +static +void alarmProc(xRecord *prec) +{ + recGblSetSevrMsg(prec, READ_ALARM, MAJOR_ALARM, "a %s", "message"); + prec->val = 0; +} + +static +void checkAlarm(void) +{ + epicsEnum16 stat, sevr; + + xRecord* target = (xRecord*)testdbRecordPtr("target"); + dbCommon* src = testdbRecordPtr("src"); + + char amsg[sizeof(src->amsg)]; + + testDiag("checkAlarm()"); + + dbScanLock((dbCommon*)target); + target->clbk = &alarmProc; + dbProcess((dbCommon*)target); + target->clbk = NULL; + dbScanUnlock((dbCommon*)target); + + dbScanLock(src); + testOk1(0==dbGetAlarm(dbGetDevLink(src), &stat, &sevr)); + dbScanUnlock(src); + + testOk1(stat==READ_ALARM); + testOk1(sevr==MAJOR_ALARM); + stat = sevr = 0; + + dbScanLock(src); + testOk1(0==dbGetAlarmMsg(dbGetDevLink(src), &stat, &sevr, amsg, sizeof(amsg))); + dbScanUnlock(src); + + testOk1(stat==READ_ALARM); + testOk1(sevr==MAJOR_ALARM); + testOk1(strcmp(amsg, "a message")==0); + stat = sevr = 0; + memset(amsg, 0, sizeof(amsg)); + + dbScanLock(src); + testOk1(0==dbGetAlarmMsg(dbGetDevLink(src), &stat, &sevr, amsg, 5)); + dbScanUnlock(src); + + testOk1(stat==READ_ALARM); + testOk1(sevr==MAJOR_ALARM); + testOk1(strcmp(amsg, "a me")==0); +} + +MAIN(dbDbLinkTest) +{ + testPlan(18); + + testdbPrepare(); + + testdbReadDatabase("dbTestIoc.dbd", NULL, NULL); + + dbTestIoc_registerRecordDeviceDriver(pdbbase); + + testdbReadDatabase("dbDbLinkTest.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + checkTime(); + checkAlarm(); + + testIocShutdownOk(); + + testdbCleanup(); + + return testDone(); +} diff --git a/modules/database/test/ioc/db/dbDbLinkTest.db b/modules/database/test/ioc/db/dbDbLinkTest.db new file mode 100644 index 000000000..39ce5d8ae --- /dev/null +++ b/modules/database/test/ioc/db/dbDbLinkTest.db @@ -0,0 +1,6 @@ +record(x, "target") { +} + +record(x, "src") { + field(INP, "target.VAL") +} diff --git a/modules/database/test/ioc/db/dbPutGetTest.c b/modules/database/test/ioc/db/dbPutGetTest.c index 742318e3a..8f539407d 100644 --- a/modules/database/test/ioc/db/dbPutGetTest.c +++ b/modules/database/test/ioc/db/dbPutGetTest.c @@ -7,12 +7,186 @@ #include #include +#include #include #include #include +#include +#include #include #include +#include "xRecord.h" + +typedef struct { + DBRstatus + DBRamsg + DBRunits + DBRprecision + DBRtime + DBRutag + DBRgrDouble + DBRctrlDouble + DBRalDouble +} dbMetaDouble; + +enum {dbMetaDoubleMask = DBR_STATUS | DBR_AMSG | DBR_UNITS | DBR_PRECISION | DBR_TIME | DBR_UTAG | DBR_GR_DOUBLE | DBR_CTRL_DOUBLE | DBR_AL_DOUBLE}; + +static +void testdbMetaDoubleSizes(void) +{ + dbMetaDouble meta; + size_t pos=0; + + testDiag("dbMetaDouble may not have padding"); +#define testOffset(FLD) do {\ + testOk(offsetof(dbMetaDouble, FLD)==pos, "offset(meta, " #FLD "), %u == %u", (unsigned)offsetof(dbMetaDouble, FLD), (unsigned)pos); \ + pos += sizeof(meta.FLD); \ +}while(0) + + testOffset(status); + testOffset(severity); + testOffset(acks); + testOffset(ackt); + testOffset(amsg); + testOffset(units); + testOffset(precision); + testOffset(time); + testOffset(utag); + testOffset(upper_disp_limit); + testOffset(lower_disp_limit); + testOffset(upper_ctrl_limit); + testOffset(lower_ctrl_limit); + testOffset(upper_alarm_limit); + testOffset(upper_warning_limit); + testOffset(lower_warning_limit); + testOffset(lower_alarm_limit); +#undef testOffset + testOk(sizeof(dbMetaDouble)==pos, "sizeof(dbMetaDouble), %u == %u", (unsigned)sizeof(dbMetaDouble), (unsigned)pos); +} + +static +void checkDoubleGet(dbChannel *chan, db_field_log* pfl) +{ + dbMetaDouble meta; + long options = (long)dbMetaDoubleMask; + long nReq = 0; + long status; + + status=dbChannelGet(chan, DBF_DOUBLE, &meta, &options, &nReq, pfl); + testOk(status==0, "dbGet OTST : %ld", status); + + testOk1(meta.severity==INVALID_ALARM); + testOk1(meta.status==UDF_ALARM); + testOk1(meta.acks==MAJOR_ALARM); + testOk1(meta.ackt==1); + testOk1(strncmp(meta.amsg, "oops", DB_UNITS_SIZE)==0); + testOk1(meta.time.secPastEpoch==0x12345678); + testOk1(meta.time.nsec==0x90abcdef); + testOk1(meta.utag==0x10203040); + testOk1(meta.precision.dp==0x12345678); + testOk1(strncmp(meta.units, "arbitrary", DB_UNITS_SIZE)==0); +#define limitEq(UL, FL, VAL) testOk(meta.UL ## _ ## FL ## _limit == (VAL), #UL "_" #FL "_limit (%f) == %f", meta.UL ## _ ## FL ## _limit, VAL) + limitEq(lower, disp, 10000000.0-1.0); + limitEq(upper, disp, 10000000.0+1.0); + limitEq(lower, ctrl, 10000000.0-2.0); + limitEq(upper, ctrl, 10000000.0+2.0); + limitEq(lower, alarm, 10000000.0-3.0); + limitEq(lower, warning, 10000000.0-4.0); + limitEq(upper, warning, 10000000.0+4.0); + limitEq(upper, alarm, 10000000.0+3.0); +#undef limitEq + +} + +static +void testdbMetaDoubleGet(void) +{ + xRecord* prec = (xRecord*)testdbRecordPtr("recmeta"); + dbChannel *chan = dbChannelCreate("recmeta.OTST"); + db_field_log *pfl; + evSubscrip evsub; + long status; + dbMetaDouble meta; + + STATIC_ASSERT(sizeof(meta.amsg)==sizeof(prec->amsg)); + STATIC_ASSERT(sizeof(meta.amsg)==sizeof(pfl->amsg)); + + if(!chan) + testAbort("Missing recmeta OTST"); + if((status=dbChannelOpen(chan))!=0) + testAbort("can't open recmeta OTST : %ld", status); + + dbScanLock((dbCommon*)prec); + /* ensure that all meta-data has different non-zero values */ + prec->otst = 10000000.0; + prec->sevr = INVALID_ALARM; + prec->stat = UDF_ALARM; + strcpy(prec->amsg, "oops"); + prec->acks = MAJOR_ALARM; + prec->time.secPastEpoch = 0x12345678; + prec->time.nsec = 0x90abcdef; + prec->utag = 0x10203040; + + testDiag("dbGet directly from record"); + checkDoubleGet(chan, NULL); + + testDiag("dbGet from field log"); + + /* bare minimum init for db_create_event_log() */ + memset(&evsub, 0, sizeof(evsub)); + evsub.chan = chan; + evsub.useValque = 1; + pfl = db_create_event_log(&evsub); + /* spoil things which should now come from field log */ + prec->sevr = 0; + prec->stat = 0; + strcpy(prec->amsg, "invalid"); + prec->time.secPastEpoch = 0xdeadbeef; + prec->time.nsec = 0xdeadbeef; + prec->utag = 0xdeadbeef; + + /* never any filters, so skip pre/post */ + checkDoubleGet(chan, pfl); + db_delete_field_log(pfl); + + dbScanUnlock((dbCommon*)prec); +} + +typedef struct { + DBRstatus + DBRamsg + DBRtime + DBRutag + DBRenumStrs +} dbMetaEnum; + +static +void testdbMetaEnumSizes(void) +{ + dbMetaEnum meta; + size_t pos=0; + + testDiag("dbMetaEnum may not have implicit padding"); +#define testOffset(FLD) do {\ + testOk(offsetof(dbMetaEnum, FLD)==pos, "offset(meta, " #FLD "), %u == %u", (unsigned)offsetof(dbMetaEnum, FLD), (unsigned)pos); \ + pos += sizeof(meta.FLD); \ +}while(0) + + testOffset(status); + testOffset(severity); + testOffset(acks); + testOffset(ackt); + testOffset(amsg); + testOffset(time); + testOffset(utag); + testOffset(no_str); + testOffset(padenumStrs); + testOffset(strs); +#undef testOffset + testOk(sizeof(dbMetaEnum)==pos, "sizeof(dbMetaEnum), %u == %u", (unsigned)sizeof(dbMetaEnum), (unsigned)pos); +} + static void testdbGetStringEqual(const char *pv, const char *expected) { @@ -139,13 +313,44 @@ void testPutArr(void) testdbGetArrFieldEqual("arr", DBR_LONG, 4, 3, buf); } +static +void testPutSpecial(void) +{ + const char val[] = "special"; + const char inp[] = "special.INP"; + const char sfx[] = "special.SFX"; + testDiag("testPutSpecial()"); + + /* There are separate sets of calls to dbPutSpecial() in + * dbPut() and in dbPutFieldLink() so we need to check + * both regular fields and link fields. + */ + testdbPutFieldOk(val, DBR_LONG, 1); + testdbPutFieldOk(inp, DBR_STRING, "1.0"); + testdbPutFieldOk(sfx, DBR_LONG, SFX_Before); /* Reject early */ + testdbPutFieldFail(S_db_Blocked, val, DBR_LONG, 2); + testdbGetFieldEqual(val, DBR_LONG, 1); /* Wasn't modified */ + testdbPutFieldFail(S_db_Blocked, inp, DBR_STRING, "2.0"); + testdbGetFieldEqual(inp, DBR_STRING, "1.0"); /* Wasn't modified */ + testdbPutFieldOk(sfx, DBR_LONG, SFX_After); /* Reject late */ + testdbPutFieldFail(S_db_Blocked, val, DBR_LONG, 3); + testdbPutFieldFail(S_db_Blocked, inp, DBR_STRING, "3.0"); + testdbPutFieldOk(sfx, DBR_LONG, SFX_None); + testdbPutFieldOk(val, DBR_LONG, 4); + testdbPutFieldOk(inp, DBR_STRING, "4.0"); +} + + void dbTestIoc_registerRecordDeviceDriver(struct dbBase *); MAIN(dbPutGet) { - testPlan(44); + testPlan(124); testdbPrepare(); + testdbMetaDoubleSizes(); + testdbMetaEnumSizes(); + testdbReadDatabase("dbTestIoc.dbd", NULL, NULL); dbTestIoc_registerRecordDeviceDriver(pdbbase); testdbReadDatabase("dbPutGetTest.db", NULL, NULL); @@ -158,12 +363,16 @@ MAIN(dbPutGet) testIocInitOk(); eltc(1); + testdbMetaDoubleGet(); + testLongLink(); testLongAttr(); testLongField(); testPutArr(); + testPutSpecial(); + testIocShutdownOk(); testdbCleanup(); diff --git a/modules/database/test/ioc/db/dbPutGetTest.db b/modules/database/test/ioc/db/dbPutGetTest.db index 816dc73f0..ccfc43998 100644 --- a/modules/database/test/ioc/db/dbPutGetTest.db +++ b/modules/database/test/ioc/db/dbPutGetTest.db @@ -44,3 +44,7 @@ record(arr, "arr") { field(FTVL, "ULONG") field(NELM, "10") } + +record(x, "recmeta") {} + +record(x, "special") {} diff --git a/modules/database/test/ioc/db/epicsRunDbTests.c b/modules/database/test/ioc/db/epicsRunDbTests.c index 602b15e05..6c7ce84c9 100644 --- a/modules/database/test/ioc/db/epicsRunDbTests.c +++ b/modules/database/test/ioc/db/epicsRunDbTests.c @@ -30,6 +30,7 @@ int dbLockTest(void); int dbPutLinkTest(void); int dbStaticTest(void); int dbCaLinkTest(void); +int dbDbLinkTest(void); int testDbChannel(void); int chfPluginTest(void); int arrShorthandTest(void); @@ -52,6 +53,7 @@ void epicsRunDbTests(void) runTest(dbPutLinkTest); runTest(dbStaticTest); runTest(dbCaLinkTest); + runTest(dbDbLinkTest); runTest(testDbChannel); runTest(arrShorthandTest); runTest(recGblCheckDeadbandTest); diff --git a/modules/database/test/ioc/db/xRecord.c b/modules/database/test/ioc/db/xRecord.c index 7cbcf1508..cd8fa74df 100644 --- a/modules/database/test/ioc/db/xRecord.c +++ b/modules/database/test/ioc/db/xRecord.c @@ -76,7 +76,95 @@ static long process(struct dbCommon *pcommon) return ret; } +static long special(struct dbAddr *paddr, int after) +{ + struct xRecord *prec = (struct xRecord *) paddr->precord; + if (dbGetFieldIndex(paddr) != xRecordVAL && + dbGetFieldIndex(paddr) != xRecordINP) { + recGblRecordError(S_db_badField, prec, "x: special"); + return S_db_badField; + } + if (prec->sfx == after) { + return S_db_Blocked; + } + return 0; +} + +long get_units(struct dbAddr *paddr, char *units) +{ + if(dbGetFieldIndex(paddr)==xRecordOTST) { + strncpy(units, "arbitrary", DB_UNITS_SIZE); + } + return 0; +} + +long get_precision(const struct dbAddr *paddr, long *precision) +{ + if(dbGetFieldIndex(paddr)==xRecordOTST) { + *precision = 0x12345678; + } + return 0; +} + +long get_graphic_double(struct dbAddr *paddr, struct dbr_grDouble *p) +{ + xRecord *prec = (xRecord *)paddr->precord; + if(dbGetFieldIndex(paddr)==xRecordOTST) { + p->lower_disp_limit = prec->otst-1.0; + p->upper_disp_limit = prec->otst+1.0; + } + return 0; +} + +long get_control_double(struct dbAddr *paddr, struct dbr_ctrlDouble *p) +{ + xRecord *prec = (xRecord *)paddr->precord; + if(dbGetFieldIndex(paddr)==xRecordOTST) { + p->lower_ctrl_limit = prec->otst-2.0; + p->upper_ctrl_limit = prec->otst+2.0; + } + return 0; +} +long get_alarm_double(struct dbAddr *paddr, struct dbr_alDouble *p) +{ + xRecord *prec = (xRecord *)paddr->precord; + if(dbGetFieldIndex(paddr)==xRecordOTST) { + p->lower_alarm_limit = prec->otst-3.0; + p->lower_warning_limit = prec->otst-4.0; + p->upper_warning_limit = prec->otst+4.0; + p->upper_alarm_limit = prec->otst+3.0; + } + return 0; +} + +#define report NULL +#define initialize NULL +#define get_value NULL +#define cvt_dbaddr NULL +#define get_array_info NULL +#define put_array_info NULL +#define get_enum_str NULL +#define get_enum_strs NULL +#define put_enum_str NULL + static rset xRSET = { - RSETNUMBER, NULL, NULL, init_record, process + RSETNUMBER, + report, + initialize, + init_record, + process, + special, + get_value, + cvt_dbaddr, + get_array_info, + put_array_info, + get_units, + get_precision, + get_enum_str, + get_enum_strs, + put_enum_str, + get_graphic_double, + get_control_double, + get_alarm_double }; epicsExportAddress(rset,xRSET); diff --git a/modules/database/test/ioc/db/xRecord.dbd b/modules/database/test/ioc/db/xRecord.dbd index 25013c042..620deac61 100644 --- a/modules/database/test/ioc/db/xRecord.dbd +++ b/modules/database/test/ioc/db/xRecord.dbd @@ -1,9 +1,16 @@ # This is a minimal record definition +menu(xSFX) { + choice(SFX_Before, "Before") + choice(SFX_After, "After") + choice(SFX_None, "None") +} + recordtype(x) { include "dbCommon.dbd" field(VAL, DBF_LONG) { prompt("Value") + special(SPC_MOD) } field(C8, DBF_CHAR) { prompt("Char") @@ -40,10 +47,20 @@ recordtype(x) { } field(INP, DBF_INLINK) { prompt("Input Link") + special(SPC_MOD) } field(CLBK, DBF_NOACCESS) { prompt("Processing callback") special(SPC_NOMOD) extra("void (*clbk)(struct xRecord*)") } + field(OTST, DBF_DOUBLE) { + prompt("dbGet() options test") + special(SPC_NOMOD) + } + field(SFX, DBF_MENU) { + prompt("Special effects") + menu(xSFX) + initial("None") + } } diff --git a/modules/database/test/std/rec/simmTest.c b/modules/database/test/std/rec/simmTest.c index 17e4d7fe4..1f4193378 100644 --- a/modules/database/test/std/rec/simmTest.c +++ b/modules/database/test/std/rec/simmTest.c @@ -12,9 +12,11 @@ #include #include #include +#include #include #include #include +#include #include "recSup.h" #include "aiRecord.h" @@ -414,6 +416,15 @@ void testSiolWrite(const char *name, * Asynchronous processing using simm:DELAY */ +static void +ping(CALLBACK *pcb) +{ + epicsEventId ev; + callbackGetUser(ev, pcb); + + epicsEventMustTrigger(ev); +} + static void testSimmDelay(const char *name, epicsFloat64 *psdly, @@ -422,6 +433,14 @@ void testSimmDelay(const char *name, epicsTimeStamp now; const double delay = 0.01; /* 10 ms */ double diff; + epicsEventId poked; + CALLBACK cb; + + memset(&cb, 0, sizeof(CALLBACK)); + poked = epicsEventMustCreate(epicsEventEmpty); + callbackSetCallback(ping, &cb); + callbackSetPriority(priorityLow, &cb); + callbackSetUser(poked, &cb); testDiag("## Asynchronous processing with simm:DELAY ##"); @@ -443,14 +462,11 @@ void testSimmDelay(const char *name, testdbPutFieldOk(namePROC, DBR_LONG, 0); testdbGetFieldEqual(namePACT, DBR_USHORT, 1); epicsTimeGetCurrent(&now); - epicsThreadSleep(1.75*delay); - if(testImpreciseTiming()) - testTodoBegin("imprecise"); + callbackRequestDelayed(&cb, 1.5 * delay); + epicsEventWait(poked); testdbGetFieldEqual(namePACT, DBR_USHORT, 0); diff = epicsTimeDiffInSeconds(mytime, &now); testOk(diff >= 0.0, "time stamp is recent (%.9f sec)", diff); - if(testImpreciseTiming()) - testTodoEnd(); /* Reset delay */ *psdly = -1.; diff --git a/modules/libcom/RTEMS/Makefile b/modules/libcom/RTEMS/Makefile index b46889db1..c939563fc 100644 --- a/modules/libcom/RTEMS/Makefile +++ b/modules/libcom/RTEMS/Makefile @@ -11,10 +11,14 @@ TOP = ../../.. include $(TOP)/configure/CONFIG include $(TOP)/configure/CONFIG_LIBCOM_VERSION +# check check +SRC_DIRS += ../$(OS_API) + PERL_SCRIPTS += epicsMakeMemFs.pl INC += epicsRtemsInitHooks.h INC += epicsMemFs.h +INC += epicsNtp.h ifeq ($(RTEMS_QEMU_FIXUPS),YES) rtems_init_CPPFLAGS += -DQEMU_FIXUPS @@ -27,11 +31,14 @@ rtemsCom_SRCS += setBootConfigFromNVRAM.c rtemsCom_SRCS += epicsRtemsInitHookPre.c rtemsCom_SRCS += epicsRtemsInitHookPost.c rtemsCom_SRCS += epicsMemFs.c +rtemsCom_SRCS += epicsNtp.c -ifeq ($(RTEMS_BSP),pc386) +ifeq ($(RTEMS_TARGET_CPU),i386) rtemsCom_SRCS += ne2kpci.c endif +rtems_config_CPPFLAGS += -DBSP_$(RTEMS_BSP) + LIBRARY_RTEMS = rtemsCom # shared library ABI version. diff --git a/modules/libcom/RTEMS/epicsNtp.c b/modules/libcom/RTEMS/epicsNtp.c new file mode 100644 index 000000000..760d62610 --- /dev/null +++ b/modules/libcom/RTEMS/epicsNtp.c @@ -0,0 +1,85 @@ +/*************************************************************************\ +* (C) 2014 David Lettier. +* http://www.lettier.com/ +* SPDX-License-Identifier: BSD-3-Clause +\*************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "epicsNtp.h" + +int epicsNtpGetTime(char *ntpIp, struct timespec *now) +{ + + int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket. + int portno = 123; // NTP UDP port number. + + // Create and zero out the packet. All 48 bytes worth. + ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + memset( &packet, 0, sizeof( ntp_packet ) ); + // Set the first byte's bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero. + *( ( char * ) &packet + 0 ) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2. + + // Create a UDP socket, convert the host-name to an IP address, set the port number, + // connect to the server, send the packet, and then read in the return packet. + struct sockaddr_in serv_addr; // Server address data structure. + + sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); // Create a UDP socket. + + if ( sockfd < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // Zero out the server address structure. + memset( ( char* ) &serv_addr, 0, sizeof( serv_addr ) ); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(ntpIp); + + serv_addr.sin_port = htons( portno ); + + // Call up the server using its IP address and port number. + if ( connect( sockfd, ( struct sockaddr * ) &serv_addr, sizeof( serv_addr) ) < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // Send it the NTP packet it wants. If n == -1, it failed. + n = write( sockfd, ( char* ) &packet, sizeof( ntp_packet ) ); + if ( n < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + +// Wait and receive the packet back from the server. If n == -1, it failed. + n = read( sockfd, ( char* ) &packet, sizeof( ntp_packet ) ); + if ( n < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // These two fields contain the time-stamp seconds as the packet left the NTP server. + // The number of seconds correspond to the seconds passed since 1900. + // ntohl() converts the bit/byte order from the network's to host's "endianness". + packet.txTm_s = ntohl( packet.txTm_s ); // Time-stamp seconds. + packet.txTm_f = ntohl( packet.txTm_f ); // Time-stamp fraction of a second. + + // Extract the 32 bits that represent the time-stamp seconds (since NTP epoch) from when the packet left the server. + // Subtract 70 years worth of seconds from the seconds since 1900. + // This leaves the seconds since the UNIX epoch of 1970. + // (1900)------------------(1970)**************************************(Time Packet Left the Server) + time_t txTm = ( time_t ) ( packet.txTm_s - NTP_TIMESTAMP_DELTA ); + now->tv_sec = txTm; + return 0; +} diff --git a/modules/libcom/RTEMS/epicsNtp.h b/modules/libcom/RTEMS/epicsNtp.h new file mode 100644 index 000000000..062970f30 --- /dev/null +++ b/modules/libcom/RTEMS/epicsNtp.h @@ -0,0 +1,42 @@ +/*************************************************************************\ +* (C) 2014 David Lettier. +* http://www.lettier.com/ +* SPDX-License-Identifier: BSD-3-Clause +\*************************************************************************/ +#ifndef EPICSNTP_H +#define EPICSNTP_H + +#define NTP_TIMESTAMP_DELTA 2208988800ull + +int epicsNtpGetTime(char *ntpIp, struct timespec *now); + +typedef struct +{ + + uint8_t li_vn_mode; // Eight bits. li, vn, and mode. + // li. Two bits. Leap indicator. + // vn. Three bits. Version number of the protocol. + // mode. Three bits. Client will pick mode 3 for client. + + uint8_t stratum; // Eight bits. Stratum level of the local clock. + uint8_t poll; // Eight bits. Maximum interval between successive messages. + uint8_t precision; // Eight bits. Precision of the local clock. + + uint32_t rootDelay; // 32 bits. Total round trip delay time. + uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source. + uint32_t refId; // 32 bits. Reference clock identifier. + + uint32_t refTm_s; // 32 bits. Reference time-stamp seconds. + uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second. + + uint32_t origTm_s; // 32 bits. Originate time-stamp seconds. + uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second. + + uint32_t rxTm_s; // 32 bits. Received time-stamp seconds. + uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second. + + uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds. + uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second. + +} ntp_packet; // Total: 384 bits or 48 bytes. +#endif // EPICSNTP_H diff --git a/modules/libcom/RTEMS/epicsRtemsInitHookPost.c b/modules/libcom/RTEMS/epicsRtemsInitHookPost.c index ba14aae4c..674c32662 100644 --- a/modules/libcom/RTEMS/epicsRtemsInitHookPost.c +++ b/modules/libcom/RTEMS/epicsRtemsInitHookPost.c @@ -10,9 +10,10 @@ * Dummy version -- use if application does not provide its own version */ #include "epicsRtemsInitHooks.h" - +#ifdef RTEMS_LEGACY_STACK int epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config) { return 0; } +#endif diff --git a/modules/libcom/RTEMS/epicsRtemsInitHookPre.c b/modules/libcom/RTEMS/epicsRtemsInitHookPre.c index 4c8544745..b84fa7ac3 100644 --- a/modules/libcom/RTEMS/epicsRtemsInitHookPre.c +++ b/modules/libcom/RTEMS/epicsRtemsInitHookPre.c @@ -10,9 +10,10 @@ * Dummy version -- use if application does not provide its own version */ #include "epicsRtemsInitHooks.h" - +#ifdef RTEMS_LEGACY_STACK int epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config) { return 0; } +#endif diff --git a/modules/libcom/RTEMS/epicsRtemsInitHooks.h b/modules/libcom/RTEMS/epicsRtemsInitHooks.h index cdbc74315..e08b7fa35 100644 --- a/modules/libcom/RTEMS/epicsRtemsInitHooks.h +++ b/modules/libcom/RTEMS/epicsRtemsInitHooks.h @@ -10,7 +10,9 @@ * Hooks into RTEMS startup code */ #include +#ifdef RTEMS_LEGACY_STACK #include +#endif extern char *env_nfsServer; extern char *env_nfsPath; @@ -23,8 +25,10 @@ extern "C" { /* * Return 0 for success, non-zero for failure (will cause panic) */ +#ifdef RTEMS_LEGACY_STACK int epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); int epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); +#endif /* Return 0 if local file system was setup, or non-zero (will fall back to network */ int epicsRtemsMountLocalFilesystem(char **argv); diff --git a/modules/libcom/RTEMS/posix/rtems_config.c b/modules/libcom/RTEMS/posix/rtems_config.c new file mode 100644 index 000000000..c9fa8a8d7 --- /dev/null +++ b/modules/libcom/RTEMS/posix/rtems_config.c @@ -0,0 +1,173 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS configuration for EPICS + * Author: W. Eric Norum + * norume@aps.anl.gov + * (630) 252-4793 + */ + +#include + +/* + *********************************************************************** + * RTEMS CONFIGURATION * + *********************************************************************** + */ + +extern void *POSIX_Init(void *argument); + +#define CONFIGURE_POSIX_INIT_THREAD_TABLE +#define CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT POSIX_Init +#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (64*1024) + +#define CONFIGURE_MAXIMUM_PERIODS 5 +#define CONFIGURE_MICROSECONDS_PER_TICK 10000 +#define CONFIGURE_MALLOC_STATISTICS 1 +/* MINIMUM_STACK_SIZE == 8K */ +#define CONFIGURE_EXTRA_TASK_STACKS (4000 * RTEMS_MINIMUM_STACK_SIZE) + +#if __RTEMS_MAJOR__ > 4 +#define CONFIGURE_FILESYSTEM_DEVFS +#define CONFIGURE_FILESYSTEM_TFTPFS +#endif +#define CONFIGURE_FILESYSTEM_NFS +#define CONFIGURE_FILESYSTEM_IMFS + +#ifndef RTEMS_LEGACY_STACK +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM +/* + * Configure LibBSD. + */ +//#define RTEMS_BSD_CONFIG_NET_PF_UNIX +//#define RTEMS_BSD_CONFIG_NET_IF_BRIDGE +//#define RTEMS_BSD_CONFIG_NET_IF_LAGG +//#define RTEMS_BSD_CONFIG_NET_IF_VLAN +#define RTEMS_BSD_CONFIG_BSP_CONFIG +#define RTEMS_BSD_CONFIG_INIT +#include +#endif // not LEGACY_STACK + +/* + * Configure RTEMS. + */ +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER + +/* Max FDs cannot exceed FD_SETSIZE from newlib (64) */ +#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 64 +#define CONFIGURE_IMFS_ENABLE_MKFIFO 2 + +#define CONFIGURE_MAXIMUM_NFS_MOUNTS 3 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 5 + +#define CONFIGURE_UNLIMITED_ALLOCATION_SIZE 32 +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK +#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE (64 * 1024) +#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 4 +#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (1 * 1024 * 1024) + +/* we are using POSIX_INIT needed by V4 +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024) +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT +#endif +*/ + +//#define RTEMS_PCI_CONFIG_LIB +//#define CONFIGURE_PCI_LIB PCI_LIB_AUTO + +#if __RTEMS_MAJOR__ > 4 +#define CONFIGURE_SHELL_COMMANDS_INIT + +#include + +#ifndef RTEMS_LEGACY_STACK +#include + +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_HOSTNAME_Command, \ + &rtems_shell_PING_Command, \ + &rtems_shell_ROUTE_Command, \ + &rtems_shell_NETSTAT_Command, \ + &rtems_shell_IFCONFIG_Command, \ + &rtems_shell_TCPDUMP_Command, \ + &rtems_shell_PFCTL_Command, \ + &rtems_shell_SYSCTL_Command +#else // LEGACY_STACK: +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_PING_Command, \ + &rtems_shell_ROUTE_Command, \ + &rtems_shell_IFCONFIG_Command +#endif + +#define CONFIGURE_SHELL_COMMAND_CPUUSE +#define CONFIGURE_SHELL_COMMAND_PERIODUSE +#define CONFIGURE_SHELL_COMMAND_STACKUSE +#define CONFIGURE_SHELL_COMMAND_PROFREPORT + +#define CONFIGURE_SHELL_COMMAND_CP +#define CONFIGURE_SHELL_COMMAND_PWD +#define CONFIGURE_SHELL_COMMAND_LS +#define CONFIGURE_SHELL_COMMAND_LN +#define CONFIGURE_SHELL_COMMAND_LSOF +#define CONFIGURE_SHELL_COMMAND_CHDIR +#define CONFIGURE_SHELL_COMMAND_CD +#define CONFIGURE_SHELL_COMMAND_MKDIR +#define CONFIGURE_SHELL_COMMAND_RMDIR +#define CONFIGURE_SHELL_COMMAND_CAT +#define CONFIGURE_SHELL_COMMAND_MV +#define CONFIGURE_SHELL_COMMAND_RM +#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO +#define CONFIGURE_SHELL_COMMAND_SHUTDOWN + +#include +#define RTEMS_BSD_CONFIG_BSP_CONFIG +#define RTEMS_BSD_CONFIG_SERVICE_TELNETD +#define RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE (16 * 1024) +#define RTEMS_BSD_CONFIG_SERVICE_FTPD +#define RTEMS_BSD_CONFIG_FIREWALL_PF +#else +#include +#endif // not LEGACY_STACK + +#if __RTEMS_MAJOR__ < 5 // still needed in Version 4? +#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(30) +#endif + +#define CONFIGURE_MAXIMUM_DRIVERS 40 + +/* + * This should be made BSP dependent, not CPU dependent but I know of no + * appropriate conditionals to use. + * The new general time support makes including the RTC driver less important. + */ +#if !defined(mpc604) && !defined(__mc68040__) && !defined(__mcf5200__) && \ + !defined(mpc7455) && !defined(__arm__) && !defined(__nios2__) + /* don't have RTC code */ +#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER +#endif + +#if defined(BSP_pc386) || defined(BSP_pc686) +#define RTEMS_BSD_CONFIG_DOMAIN_PAGE_MBUFS_SIZE (64 * 1024 * 1024) +#elif defined(BSP_qoriq_e500) +#define RTEMS_BSD_CONFIG_DOMAIN_PAGE_MBUFS_SIZE (32 * 1024 * 1024) +#endif + +#define CONFIGURE_INIT + +#include diff --git a/modules/libcom/RTEMS/posix/rtems_init.c b/modules/libcom/RTEMS/posix/rtems_init.c new file mode 100644 index 000000000..09c7d60a5 --- /dev/null +++ b/modules/libcom/RTEMS/posix/rtems_init.c @@ -0,0 +1,1183 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS startup task for EPICS + * Author: W. Eric Norum + * eric.norum@usask.ca + * (306) 966-5394 + */ + +/* + * This is the first implementation with posix and rtems5. + * Currently only dhcp is supported with libbsd. The reading of the + * environment variables from e.g. u-boot environment is still missing. + * Extensive tests so far only with qemu. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __RTEMS_MAJOR__ > 4 +#include +#else +#include +#endif + +#ifdef RTEMS_LEGACY_STACK +#include +#include +#else // libbsd stack +#include +#include +#include +#include +#endif + +#include +#if __RTEMS_MAJOR__ > 4 +#include +#endif +#include "epicsVersion.h" +#include "epicsThread.h" +#include "epicsTime.h" +#include "epicsExit.h" +#include "envDefs.h" +#include "errlog.h" +#include "logClient.h" +#include "osiUnistd.h" +#include "iocsh.h" +#include "osdTime.h" +#include "epicsMemFs.h" +#include "epicsEvent.h" +#include "errlog.h" + +#include "epicsRtemsInitHooks.h" + +#ifndef RTEMS_LEGACY_STACK +// setup own ntp-client to get time +#include "epicsNtp.h" +epicsEventId dhcpDone; +#endif + +/* these settings are needed by the rtems startup + * may provide by dhcp/bootp + * or environments from the "BIOS" like u-boot, motboot etc. + */ +char rtemsInit_NTP_server_ip[16] = "10.0.5.1"; +char bootp_server_name_init[128] = "1001.1001@10.0.5.1:/epics"; +char bootp_boot_file_name_init[128] = "/epics/myExample/bin/RTEMS-beatnik/myExample.boot"; +char bootp_cmdline_init[128] = "/epics/myExample/iocBoot/iocmyExample/st.cmd"; + +struct in_addr rtems_bsdnet_bootp_server_address; +/* TODO check rtems_bsdnet_bootp_cmdline */ +#ifndef RTEMS_LEGACY_STACK +char *rtems_bsdnet_bootp_server_name = bootp_server_name_init; +char *rtems_bsdnet_bootp_boot_file_name = bootp_boot_file_name_init; +char *rtems_bsdnet_bootp_cmdline = bootp_cmdline_init; +#endif // not LEGACY Stack + +/* + * Prototypes for some functions not in header files + */ +//void tzset(void); +int fileno(FILE *); +int main(int argc, char **argv); + +static void +logReset (void) +{ + void rtems_bsp_reset_cause(char *buf, size_t capacity) __attribute__((weak)); + void (*fp)(char *buf, size_t capacity) = rtems_bsp_reset_cause; + + if (fp) { + char buf[80]; + fp(buf, sizeof buf); + errlogPrintf ("Startup after %s.\n", buf); + } + else { + errlogPrintf ("Startup.\n"); + } +} + +/* + *********************************************************************** + * FATAL ERROR REPORTING * + *********************************************************************** + */ +/* + * Delay for a while, then terminate + */ +static void +delayedPanic (const char *msg) +{ + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); + rtems_panic ("%s", msg); +} + +/* + * Log error and terminate + */ +void +LogFatal (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + errlogVprintf (msg, ap); + va_end (ap); + delayedPanic (msg); +} + +/* + * Log RTEMS error and terminate + */ +void +LogRtemsFatal (const char *msg, rtems_status_code sc) +{ + errlogPrintf ("%s: %s\n", msg, rtems_status_text (sc)); + delayedPanic (msg); +} + +/* + * Log network error and terminate + */ +void +LogNetFatal (const char *msg, int err) +{ + errlogPrintf ("%s: %d\n", msg, err); + delayedPanic (msg); +} + +void * +mustMalloc(int size, const char *msg) +{ + void *p; + + if ((p = malloc (size)) == NULL) + LogFatal ("Can't allocate space for %s.\n", msg); + return p; +} + +/* + *********************************************************************** + * REMOTE FILE ACCESS * + *********************************************************************** + */ +#ifdef OMIT_NFS_SUPPORT +# 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) +{ + extern char _DownloadLocation[] __attribute__((weak)); + extern char _FlashBase[] __attribute__((weak)); + extern char _FlashSize[] __attribute__((weak)); + + argv[0] = rtems_bsdnet_bootp_boot_file_name; + if (epicsRtemsMountLocalFilesystem(argv)==0) { + return 1; /* FS setup successful */ +#ifdef RTEMS_LEGACY_STACK + } else if (_FlashSize && (_DownloadLocation || _FlashBase)) { + extern char _edata[]; + size_t flashIndex = _edata - _DownloadLocation; + char *header = _FlashBase + flashIndex; + + if (memcmp(header + 257, "ustar ", 8) == 0) { + int fd; + printf ("***** Unpack in-memory file system (IMFS) *****\n"); + if (rtems_tarfs_load("/", (unsigned char *)header, (size_t)_FlashSize - flashIndex) != 0) { + printf("Can't unpack tar filesystem\n"); + return 0; + } + if ((fd = open(rtems_bsdnet_bootp_cmdline, 0)) >= 0) { + close(fd); + printf ("***** Found startup script (%s) in IMFS *****\n", rtems_bsdnet_bootp_cmdline); + argv[1] = rtems_bsdnet_bootp_cmdline; + return 1; + } + printf ("***** Startup script (%s) not in IMFS *****\n", rtems_bsdnet_bootp_cmdline); + } +#endif /* only with old stack, check check libbsd dependency! */ + } + return 0; +} + +#ifndef OMIT_NFS_SUPPORT +int +nfsMount(char *uidhost, char *path, char *mntpoint) +{ + int devl = strlen(uidhost) + strlen(path) + 2; + char *dev; + int rval = -1; + + if ((dev = malloc(devl)) == NULL) { + fprintf(stderr,"nfsMount: out of memory\n"); + return -1; + } + sprintf(dev, "%s:%s", uidhost, path); + printf("Mount %s on %s\n", dev, mntpoint); + rval = mount_and_make_target_path ( + dev, mntpoint, RTEMS_FILESYSTEM_TYPE_NFS, + RTEMS_FILESYSTEM_READ_WRITE, NULL ); + if(rval) + perror("mount failed"); + free(dev); + return rval; +} +#define NFS_INIT +#endif + + +static void +initialize_remote_filesystem(char **argv, int hasLocalFilesystem) +{ +#ifdef OMIT_NFS_SUPPORT + printf ("***** Initializing TFTP *****\n"); + mount_and_make_target_path(NULL, + "/TFTP", + RTEMS_FILESYSTEM_TYPE_TFTPFS, + RTEMS_FILESYSTEM_READ_WRITE, + NULL); + if (!hasLocalFilesystem) { + char *path; + int pathsize = 200; + int l; + + path = mustMalloc(pathsize, "Command path name "); + strcpy (path, "/TFTP/BOOTP_HOST/epics/"); + l = strlen (path); + if (gethostname (&path[l], pathsize - l - 10) || (path[l] == '\0')) + { + LogFatal ("Can't get host name"); + } + strcat (path, "/st.cmd"); + argv[1] = path; + } +#else + char *server_name; + char *server_path; + char *mount_point; + char *cp; + int l = 0; + + printf ("***** Initializing NFS *****\n"); + NFS_INIT + if (env_nfsServer && env_nfsPath && env_nfsMountPoint) { + server_name = env_nfsServer; + server_path = env_nfsPath; + mount_point = env_nfsMountPoint; + cp = mount_point; + while ((cp = strchr(cp+1, '/')) != NULL) { + *cp = '\0'; + if ((mkdir (mount_point, 0755) != 0) + && (errno != EEXIST)) + LogFatal("Can't create directory \"%s\": %s.\n", + mount_point, strerror(errno)); + *cp = '/'; + } + argv[1] = rtems_bsdnet_bootp_cmdline; + } + else if (hasLocalFilesystem) { + return; + } + else { + /* + * Use first component of nvram/bootp command line pathname + * to set up initial NFS mount. A "/tftpboot/" is prepended + * if the pathname does not begin with a '/'. This allows + * NFS and TFTP to have a similar view of the remote system. + */ + if (rtems_bsdnet_bootp_cmdline[0] == '/') + cp = rtems_bsdnet_bootp_cmdline + 1; + else + cp = rtems_bsdnet_bootp_cmdline; + cp = strchr(cp, '/'); + if ((cp == NULL) + || ((l = cp - rtems_bsdnet_bootp_cmdline) == 0)) + LogFatal("\"%s\" is not a valid command pathname.\n", rtems_bsdnet_bootp_cmdline); + cp = mustMalloc(l + 20, "NFS mount paths"); + server_path = cp; + server_name = rtems_bsdnet_bootp_server_name; + if (rtems_bsdnet_bootp_cmdline[0] == '/') { + mount_point = server_path; + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); + mount_point[l] = '\0'; + argv[1] = rtems_bsdnet_bootp_cmdline; + /* + * Its probably common to embed the mount point in the server + * name so, when this is occurring, dont clobber the mount point + * by appending the first node from the command path. This allows + * the mount point to be a different path then the server's mount + * path. + * + * This allows for example a line similar to as follows the DHCP + * configuration file. + * + * server-name "159.233@192.168.0.123:/vol/vol0/bootRTEMS"; + */ + if ( server_name ) { + const size_t allocSize = strlen ( server_name ) + 2; + char * const pServerName = mustMalloc( allocSize, + "NFS mount paths"); + char * const pServerPath = mustMalloc ( allocSize, + "NFS mount paths"); + const int scanfStatus = sscanf ( + server_name, + "%[^:] : / %s", + pServerName, + pServerPath + 1u ); + if ( scanfStatus == 2 ) { + pServerPath[0u]= '/'; + server_name = pServerName; + // is this a general solution? + server_path = mount_point = pServerPath; + } + else { + free ( pServerName ); + free ( pServerPath ); + } + } + } + else { + char *abspath = mustMalloc(strlen(rtems_bsdnet_bootp_cmdline)+2,"Absolute command path"); + strcpy(server_path, "/tftpboot/"); + mount_point = server_path + strlen(server_path); + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); + mount_point[l] = '\0'; + mount_point--; + strcpy(abspath, "/"); + strcat(abspath, rtems_bsdnet_bootp_cmdline); + argv[1] = abspath; + } + } + errlogPrintf("nfsMount(\"%s\", \"%s\", \"%s\")\n", + server_name, server_path, mount_point); + nfsMount(server_name, server_path, mount_point); +#endif +} + +static +char rtems_etc_hosts[] = "127.0.0.1 localhost\n"; + +/* If it doesn't already exist, create /etc/hosts with an entry for 'localhost' */ +static +void fixup_hosts(void) +{ + FILE *fp; + int ret; + struct stat STAT; + + ret=stat("/etc/hosts", &STAT); + if(ret==0) + { + return; /* already exists, assume file */ + } else if(errno!=ENOENT) { + perror("error: fixup_hosts stat /etc/hosts"); + return; + } + + ret = mkdir("/etc", 0775); + if(ret!=0 && errno!=EEXIST) + { + perror("error: fixup_hosts create /etc"); + return; + } + + if((fp=fopen("/etc/hosts", "w"))==NULL) + { + perror("error: fixup_hosts create /etc/hosts"); + } + + if(fwrite(rtems_etc_hosts, 1, sizeof(rtems_etc_hosts)-1, fp)!=sizeof(rtems_etc_hosts)-1) + { + perror("error: failed to write /etc/hosts"); + } + + fclose(fp); +} + +/* + * Get to the startup script directory + * The TFTP filesystem requires a trailing '/' on chdir arguments. + */ +static void +set_directory (const char *commandline) +{ + const char *cp; + char *directoryPath; + int l; + + cp = strrchr(commandline, '/'); + if (cp == NULL) { + l = 0; + cp = "/"; + } + else { + l = cp - commandline; + cp = commandline; + } + directoryPath = mustMalloc(l + 2, "Command path directory "); + strncpy(directoryPath, cp, l); + directoryPath[l] = '/'; + directoryPath[l+1] = '\0'; + if (chdir (directoryPath) < 0) + LogFatal ("Can't set initial directory(%s): %s\n", directoryPath, strerror(errno)); + else + errlogPrintf("chdir(\"%s\")\n", directoryPath); + free(directoryPath); +} + +/* + *********************************************************************** + * RTEMS/EPICS COMMANDS * + *********************************************************************** + */ + +static const iocshArg rtshellArg0 = { "cmd", iocshArgString}; +static const iocshArg rtshellArg1 = { "args", iocshArgArgv}; +static const iocshArg * rtshellArgs[2] = { &rtshellArg0, &rtshellArg1}; +static const iocshFuncDef rtshellFuncDef = { "rt",2, rtshellArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "run rtems shell command" +#endif + }; + +static void rtshellCallFunc(const iocshArgBuf *args) +{ + rtems_shell_cmd_t *cmd = rtems_shell_lookup_cmd(args[0].sval); + int ret; + + if (!cmd) { + fprintf(stderr, "ERR: No such command\n"); + + } else { + fflush(stdout); + fflush(stderr); + ret = (*cmd->command)(args[1].aval.ac,args[1].aval.av); + fflush(stdout); + fflush(stderr); + if(ret) + fprintf(stderr, "ERR: %d\n",ret); + } +} + +/* + * RTEMS status + */ +static void +rtems_netstat (unsigned int level) +{ +#ifndef RTEMS_LEGACY_STACK + printf ("***** Sorry not implemented yet with the new network stack (bsdlib)\n"); +#else + rtems_bsdnet_show_if_stats (); + rtems_bsdnet_show_mbuf_stats (); + if (level >= 1) { + rtems_bsdnet_show_inet_routes (); + } + if (level >= 2) { + rtems_bsdnet_show_ip_stats (); + rtems_bsdnet_show_icmp_stats (); + rtems_bsdnet_show_udp_stats (); + rtems_bsdnet_show_tcp_stats (); + } +#endif +} + +static const iocshArg netStatArg0 = { "level",iocshArgInt}; +static const iocshArg * const netStatArgs[1] = {&netStatArg0}; +static const iocshFuncDef netStatFuncDef = {"netstat",1,netStatArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "show network status" +#endif + }; +static void netStatCallFunc(const iocshArgBuf *args) +{ + rtems_netstat(args[0].ival); +} + +static const iocshFuncDef heapSpaceFuncDef = {"heapSpace",0,NULL +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "show malloc statistic" +#endif + }; +static void heapSpaceCallFunc(const iocshArgBuf *args) +{ +#if __RTEMS_MAJOR__ > 4 + Heap_Information_block info; + double x; + + malloc_info (&info); + x = info.Stats.size - (unsigned long) + (info.Stats.lifetime_allocated - info.Stats.lifetime_freed); + if (x >= 1024*1024) + printf("Heap space: %.1f MB\n", x / (1024 * 1024)); + else + printf("Heap space: %.1f kB\n", x / 1024); +#else + rtems_malloc_statistics_t s; + double x; + + malloc_get_statistics(&s); + x = s.space_available - (unsigned long)(s.lifetime_allocated - s.lifetime_freed); + if (x >= 1024*1024) + printf("Heap space: %.1f MB\n", x / (1024 * 1024)); + else + printf("Heap space: %.1f kB\n", x / 1024); +#endif // RTEMS < 5 +} + +#ifndef OMIT_NFS_SUPPORT +static const iocshArg nfsMountArg0 = { "[uid.gid@]host",iocshArgString}; +static const iocshArg nfsMountArg1 = { "server path",iocshArgString}; +static const iocshArg nfsMountArg2 = { "mount point",iocshArgString}; +static const iocshArg * const nfsMountArgs[3] = {&nfsMountArg0,&nfsMountArg1, + &nfsMountArg2}; +static const iocshFuncDef nfsMountFuncDef = {"nfsMount",3,nfsMountArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "mount nfs drive" +#endif + }; +static void nfsMountCallFunc(const iocshArgBuf *args) +{ + char *cp = args[2].sval; + while ((cp = strchr(cp+1, '/')) != NULL) { + *cp = '\0'; + if ((mkdir (args[2].sval, 0755) != 0) && (errno != EEXIST)) { + printf("Can't create directory \"%s\": %s.\n", + args[2].sval, strerror(errno)); + return; + } + *cp = '/'; + } + nfsMount(args[0].sval, args[1].sval, args[2].sval); +} +#endif + + +void zoneset(const char *zone) +{ + if(zone) + setenv("TZ", zone, 1); + else + unsetenv("TZ"); + tzset(); +} + +static const iocshArg zonesetArg0 = {"zone string", iocshArgString}; +static const iocshArg * const zonesetArgs[1] = {&zonesetArg0}; +static const iocshFuncDef zonesetFuncDef = {"zoneset",1,zonesetArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "set timezone (obsolete?)" +#endif + }; +static void zonesetCallFunc(const iocshArgBuf *args) +{ + zoneset(args[0].sval); +} + + +/* + * Register RTEMS-specific commands + */ +static void iocshRegisterRTEMS (void) +{ + iocshRegister(&netStatFuncDef, netStatCallFunc); + iocshRegister(&heapSpaceFuncDef, heapSpaceCallFunc); +#ifndef OMIT_NFS_SUPPORT + iocshRegister(&nfsMountFuncDef, nfsMountCallFunc); +#endif + iocshRegister(&zonesetFuncDef, &zonesetCallFunc); + iocshRegister(&rtshellFuncDef, &rtshellCallFunc); +#if __RTEMS_MAJOR__ > 4 + rtems_shell_init_environment(); +#endif +} + +/* + * Set up the console serial line (no handshaking) + */ +static void +initConsole (void) +{ + struct termios t; + +printf("\n initConsole --- Info ---\n"); +printf("stdin: fileno: %d, ttyname: %s\n", fileno(stdin), ttyname(fileno(stdin))); +printf("stdout: fileno: %d, ttyname: %s\n", fileno(stdout), ttyname(fileno(stdout))); +printf("stderr: fileno: %d, ttyname: %s\n", fileno(stderr), ttyname(fileno(stderr))); + + if (tcgetattr (fileno (stdin), &t) < 0) { + printf ("tcgetattr failed: %s\n", strerror (errno)); + return; + } + t.c_iflag &= ~(IXOFF | IXON | IXANY); + if (tcsetattr (fileno (stdin), TCSANOW, &t) < 0) { + printf ("tcsetattr failed: %s\n", strerror (errno)); + return; + } +} + +/* + * Hook to ensure that BSP cleanup code gets run on exit + */ +static void +exitHandler(void) +{ + rtems_shutdown_executive(0); +} + +#ifndef RTEMS_LEGACY_STACK +static char* getPrimaryNetworkInterface(void) +{ + // lookup available network interfaces + char ifnamebuf[IF_NAMESIZE]; + char *ifname; + // get primary network interface + ifname = if_indextoname(1, &ifnamebuf[0]); + if (ifname == NULL) return (NULL); + printf("\n***** Primary Network interface : %s *****\n", ifname); + return (ifname); +} + +static void +dhcpcd_hook_handler(rtems_dhcpcd_hook *hook, char *const *env) +{ + int bound = 0; + char iName[16]; + char *name; + char *value; + char * env_position; + + (void)hook; + + char ifnamebuf[IF_NAMESIZE]; + sprintf(ifnamebuf, "%s", getPrimaryNetworkInterface()); + + while (*env != NULL) { + char const * interface = "interface"; + char const * reason = "reason"; + char const * bound_str = "BOUND"; + + name = strtok_r(*env,"=", &env_position); + value = strtok_r(NULL,"=", &env_position); + printf("all out ---> %s = %s\n", name, value); + + if (!strncmp(name, interface, strlen(interface)) && + !strcmp(value, ifnamebuf)) { + snprintf(iName, sizeof(iName), "%s", value); + } + + if (!strncmp(name, reason, strlen(reason)) && + !strncmp(value, bound_str, strlen(bound_str))) { + printf ("Interface %s bounded\n", iName); + bound = 1; + } + + if (bound) { + // as there is no ntp-support in rtems-libbsd, we call our own client + char const * new_ntp_servers = "new_ntp_servers"; + char const * new_host_name = "new_host_name"; + char const * new_tftp_server_name = "new_tftp_server_name"; + + if (!strncmp(name, new_ntp_servers, strlen(new_ntp_servers))) + snprintf(rtemsInit_NTP_server_ip, + sizeof(rtemsInit_NTP_server_ip), + "%s", value); + + if (!strncmp(name, new_host_name, strlen(new_host_name))) + sethostname (value, strlen (value)); + + if (!strncmp(name, new_tftp_server_name, strlen(new_tftp_server_name))){ + snprintf(rtems_bsdnet_bootp_server_name, + sizeof(bootp_server_name_init), + "%s", value); + printf(" rtems_bsdnet_bootp_server_name : %s\n", rtems_bsdnet_bootp_server_name); + } + if(!strncmp(name, "new_bootfile_name", 20)){ + snprintf(rtems_bsdnet_bootp_boot_file_name, + sizeof(bootp_boot_file_name_init), + "%s", value); + printf(" rtems_bsdnet_bootp_boot_file_name : %s\n", rtems_bsdnet_bootp_boot_file_name); + } + if(!strncmp(name, "new_rtems_cmdline", 20)){ + snprintf(rtems_bsdnet_bootp_cmdline, + sizeof(bootp_cmdline_init), + "%s", value); + printf(" rtems_bsdnet_bootp_cmdline : %s\n", rtems_bsdnet_bootp_cmdline); + } + } + ++env; + } + if (bound) + epicsEventSignal(dhcpDone); +} + +static rtems_dhcpcd_hook dhcpcd_hook = { + .name = "ioc boot", + .handler = dhcpcd_hook_handler +}; + +static void +default_network_on_exit(int exit_code, void *arg) +{ + rtems_printer printer; + + (void)arg; + + rtems_print_printer_printf(&printer); + rtems_stack_checker_report_usage_with_plugin(&printer); +} + +static void +default_network_set_self_prio(rtems_task_priority prio) +{ + rtems_status_code sc; + + sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void +default_network_dhcpcd(void) +{ + static const char default_cfg[] = "clientid test client\n"; + rtems_status_code sc; + int fd; + int rv; + ssize_t n; + struct stat statbuf; + + if (ENOENT == stat("/etc/dhcpcd.conf", &statbuf)) { + fd = open("/etc/dhcpcd.conf", O_CREAT | O_WRONLY, + S_IRWXU | S_IRWXG | S_IRWXO); + assert(fd >= 0); + + n = write(fd, default_cfg, sizeof(default_cfg) - 1); + assert(n == (ssize_t) sizeof(default_cfg) - 1); + + static const char fhi_cfg[] = + "nodhcp6\n" + "ipv4only\n" + "option ntp_servers\n" + "option rtems_cmdline\n" + "option tftp_server_name\n" + "option bootfile_name\n" + "define 129 string rtems_cmdline\n" + "timeout 0"; + + n = write(fd, fhi_cfg, sizeof(fhi_cfg) - 1); + assert(n == (ssize_t) sizeof(fhi_cfg) - 1); + + rv = close(fd); + assert(rv == 0); + } + + sc = rtems_dhcpcd_start(NULL); + assert(sc == RTEMS_SUCCESSFUL); +} +#endif // not RTEMS_LEGACY_STACK + +#if __RTEMS_MAJOR__>4 +/* + *********************************************************************** + * TELNET DAEMON * + *********************************************************************** + */ +#define LINE_SIZE 256 +static void +telnet_pseudoIocsh(char *name, __attribute__((unused))void *arg) +{ + char line[LINE_SIZE]; + int fid[3], save_fid[3]; + + printf("info: pty dev name = %s\n", name); + + save_fid[1] = dup2(1,1); + fid[1] = dup2( fileno(stdout), 1); + if (fid[1] == -1 ) printf("Can't dup stdout\n"); + save_fid[2] = dup2(2,2); + fid[2] = dup2( fileno(stderr), 2); + if (fid[2] == -1 ) printf("Can't dup stderr\n"); + + const char *prompt = "tIocSh> "; + + while (1) { + fputs(prompt, stdout); + fflush(stdout); + /* telnet close not detected ??? tbd */ + if (fgets(line, LINE_SIZE, stdin) == NULL) { + dup2(save_fid[1],1); + dup2(save_fid[2],2); + return; + } + if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; + if (!strncmp( line, "bye",3)) { + printf( "%s", "Will end session\n"); + dup2(save_fid[1],1); + dup2(save_fid[2],2); + return; + } + iocshCmd(line); + } +} + +#define SHELL_ENTRY telnet_pseudoIocsh + +/* + * Telnet daemon configuration + * 0 or NULL for most fields in thsi struct indicate default values to RTEMS. + */ +rtems_telnetd_config_table rtems_telnetd_config = { + .command = SHELL_ENTRY, + .arg = NULL, + .priority = 0, + .stack_size = 0, + .client_maximum = 0, + .login_check = NULL, + .keep_stdio = false +}; + +#endif + + +/* + * RTEMS Startup task + */ +void * +POSIX_Init ( void *argument __attribute__((unused))) +{ + int result; + char *argv[3] = { NULL, NULL, NULL }; + rtems_status_code sc; + struct timespec now; + char timeBuff[100]; + + initConsole (); + + /* + * Use BSP-supplied time of day if available otherwise supply default time. + * It is very likely that other time synchronization facilities in EPICS + * will soon override this value. + */ + /* check for RTC ... unfortunately seems to be missing with libbsd and qemu ? + if (checkRealtime() >= 0) { + setRealTimeToRTEMS(); + } else + */ + { + // set time to 14.4.2014 + now.tv_sec = 1397460606; + now.tv_nsec = 0; + sc = clock_settime(CLOCK_REALTIME, &now); + if (sc < 0) + printf ("***** Can't set time: %s\n", rtems_status_text (sc)); + } + sc = clock_gettime( CLOCK_REALTIME, &now); + if ( sc < 0) { + printf ("***** Can't get time: %s\n", rtems_status_text (sc)); + } else { + strftime(timeBuff, sizeof timeBuff, "%D %T", gmtime(&now.tv_sec)); + printf("time set to : %s.%09ld UTC\n", timeBuff, now.tv_nsec); + } + + /* + * Explain why we're here + */ + logReset(); + + /* TBD ... + * Architecture-specific hooks + */ +#ifdef RTEMS_LEGACY_STACK + if (epicsRtemsInitPreSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) + delayedPanic("epicsRtemsInitPreSetBootConfigFromNVRAM"); + if (rtems_bsdnet_config.bootp == NULL) { + extern void setBootConfigFromNVRAM(void); + setBootConfigFromNVRAM(); + } + if (epicsRtemsInitPostSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) + delayedPanic("epicsRtemsInitPostSetBootConfigFromNVRAM"); +#endif + /* + * Override RTEMS Posix configuration, it gets started with posix prio 2 + */ + epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityIocsh); + + /* + * Create a reasonable environment + */ + + putenv ("TERM=xterm"); + putenv ("IOCSH_HISTSIZE=20"); + + /* + * Display some OS information + */ + printf("\n***** RTEMS Version: %s *****\n", + rtems_get_version_string()); + +#ifndef RTEMS_LEGACY_STACK + /* + * Start network (libbsd) + * + * start qemu like this + * qemu-system-i386 -m 64 -no-reboot -serial stdio -display none \ + * -net nic,model=rtl8139,macaddr=0e:b0:ba:5e:ba:11 -net user,restrict=yes \ + * -append "--video=off --console=/dev/com1" -kernel libComTestHarness + */ + printf("\n***** Initializing network (libbsd, dhcpcd) *****\n"); + rtems_bsd_setlogpriority("debug"); + on_exit(default_network_on_exit, NULL); + + /* Let other tasks run to complete background work */ + default_network_set_self_prio(RTEMS_MAXIMUM_PRIORITY - 1U); + + /* supress all output from bsd network initialization */ + rtems_bsd_set_vprintf_handler(rtems_bsd_vprintf_handler_mute); + + sc = rtems_bsd_initialize(); + assert(sc == RTEMS_SUCCESSFUL); + + /* Let the callout timer allocate its resources */ + sc = rtems_task_wake_after(2); + assert(sc == RTEMS_SUCCESSFUL); + + printf("\n***** ifconfig lo0 *****\n"); + rtems_bsd_ifconfig_lo0(); + + printf("\n***** add dhcpcd hook *****\n"); + dhcpDone = epicsEventMustCreate(epicsEventEmpty); + rtems_dhcpcd_add_hook(&dhcpcd_hook); + + printf("\n***** Start default network dhcpcd *****\n"); + // if MY_BOOTP??? + default_network_dhcpcd(); + + /* this seems to be hard coded in the BSP -> Sebastian Huber ? */ + printf("\n--Info (hpj)-- bsd task prio IRQS: %d -----\n", rtems_bsd_get_task_priority("IRQS")); + printf("\n--Info (hpj)-- bsd task prio TIME: %d -----\n", rtems_bsd_get_task_priority("TIME")); + + + // wait for dhcp done ... should be if SYNCDHCP is used + epicsEventWaitStatus stat; + printf("\n ---- Waiting for DHCP ...\n"); + stat = epicsEventWaitWithTimeout(dhcpDone, 600); + if (stat == epicsEventOK) + epicsEventDestroy(dhcpDone); + else if (stat == epicsEventWaitTimeout) + printf("\n ---- DHCP timed out!\n"); + else + printf("\n ---- dhcpDone Event Unknown state %d\n", stat); + + const char* ifconfg_args[] = { + "ifconfig", NULL + }; + const char* netstat_args[] = { + "netstat", "-rn", NULL + }; + + printf("-------------- IFCONFIG -----------------\n"); + rtems_bsd_command_ifconfig(1, (char**) ifconfg_args); + printf("-------------- NETSTAT ------------------\n"); + rtems_bsd_command_netstat(2, (char**) netstat_args); + + /* until now there is no NTP support in libbsd -> Sebastian Huber ... */ + printf("\n***** Until now no NTP support in RTEMS 5 with rtems-libbsd *****\n"); + printf("\n***** Ask ntp server once... *****\n"); + if (epicsNtpGetTime(rtemsInit_NTP_server_ip, &now) < 0) { + printf ("***** Can't get time from ntp ...\n"); + } else { + if (clock_settime(CLOCK_REALTIME, &now) < 0){ + printf ("***** Can't set time: %s\n", rtems_status_text (sc)); + } else { + strftime(timeBuff, sizeof timeBuff, "%D %T", gmtime(&now.tv_sec)); + printf("time from ntp : %s.%09ld UTC\n", timeBuff, now.tv_nsec); + } + } +#else // Legacy stack, old network initialization + char *cp; + if ((cp = getenv("EPICS_TS_NTP_INET")) != NULL) + rtems_bsdnet_config.ntp_server[0] = cp; + + int rtems_bsdnet_ntpserver_count = 1; + struct in_addr rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count]; + memcpy(rtems_bsdnet_ntpserver, rtems_bsdnet_config.ntp_server, sizeof(struct in_addr)); + + if (rtems_bsdnet_config.network_task_priority == 0) + { + unsigned int p; + if (epicsThreadHighestPriorityLevelBelow(epicsThreadPriorityScanLow, &p) + == epicsThreadBooleanStatusSuccess) + { + rtems_bsdnet_config.network_task_priority = p; + } + } + printf("\n***** Initializing network (Legacy Stack) *****\n"); + rtems_bsdnet_initialize_network(); + printf("\n***** Network Status *****\n"); + rtems_netstat(3); + rtems_bsdnet_synchronize_ntp (0, 0); +#endif // not RTEMS_LEGACY_STACK + + /* show messages from network after initialization ? good idea? */ + //rtems_bsd_set_vprintf_handler(bsd_vprintf_handler_old); + + printf("\n***** Setting up file system *****\n"); + initialize_remote_filesystem(argv, initialize_local_filesystem(argv)); + fixup_hosts(); + + /* + * More environment: iocsh prompt and hostname + */ + { + char hostname[1024]; + gethostname(hostname, 1023); + char *cp = mustMalloc(strlen(hostname)+3, "iocsh prompt"); + sprintf(cp, "%s> ", hostname); + epicsEnvSet ("IOCSH_PS1", cp); + epicsEnvSet("IOC_NAME", hostname); + } + + if (getenv("") == NULL) { + const char *tzp = envGetConfigParamPtr(&EPICS_TZ); + if (tzp == NULL) { + printf("Warning -- no timezone information available -- times will be displayed as GMT.\n"); + } + + } + tzset(); + printf(" check for time registered , C++ initialization ...\n"); + //osdTimeRegister(); + /*/Volumes/Epics/myExample/bin/RTEMS-xilinx_zynq_a9_qemu + * Run the EPICS startup script + */ +#if __RTEMS_MAJOR__>4 + // if telnetd is requested ... + // printf(" Will try to start telnetd with prio %d ...\n", rtems_telnetd_config.priority); + // result = rtems_telnetd_initialize(); + // printf (" telnetd initialized with result %d\n", result); +#endif + + printf ("***** Preparing EPICS application *****\n"); + iocshRegisterRTEMS (); + set_directory (argv[1]); + epicsEnvSet ("IOC_STARTUP_SCRIPT", argv[1]); + atexit(exitHandler); + errlogFlush(); + printf ("***** Starting EPICS application *****\n"); + +#if 0 +// Start an rtems shell before main, for debugging RTEMS system issues + rtems_shell_init("SHLL", RTEMS_MINIMUM_STACK_SIZE * 4, + 100, "/dev/console", + false, true, + NULL); +#endif + + result = main ((sizeof argv / sizeof argv[0]) - 1, argv); + printf ("***** IOC application terminating *****\n"); + epicsThreadSleep(1.0); + epicsExit(result); + +#if defined(__rtems__) + delayedPanic("will reset rtems ... end of POSIX_Init"); +#endif + exit(0); +} + +#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 +#if __RTEMS_MAJOR__ > 4 +#include +#endif + +extern int BSPPrintkPort; +void bsp_predriver_hook(void) +{ +#if __RTEMS_MAJOR__ > 4 + Console_Port_Minor = BSP_CONSOLE_PORT_COM1; +#else + BSPConsolePort = BSP_CONSOLE_PORT_COM1; + +#endif + BSPPrintkPort = BSP_CONSOLE_PORT_COM1; +} +#endif + +/* reboot immediately when done. */ +#if defined(__i386__) && BSP_PRESS_KEY_FOR_RESET +void bsp_cleanup(void) +{ + void bsp_reset(); + bsp_reset(); +} +#endif + +#endif /* QEMU_FIXUPS */ + +int cexpdebug __attribute__((weak)); diff --git a/modules/libcom/RTEMS/rtems_netconfig.c b/modules/libcom/RTEMS/rtems_netconfig.c index 4f7a84149..0207512c7 100644 --- a/modules/libcom/RTEMS/rtems_netconfig.c +++ b/modules/libcom/RTEMS/rtems_netconfig.c @@ -15,8 +15,24 @@ */ #include #include +#include + +#define RTEMS_VERSION_INT VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, 0, 0) + +#ifdef RTEMS_LEGACY_STACK // old non libbsd stack #include +/* + * Comment (by sebastian.huber): + * + * This rtems_bsdnet_loopattach() was a hack and is no longer needed in RTEMS + * 4.11. + * + * -- + * Ticket URL: + */ + +#if RTEMS_VERSION_INT<=VERSION_INT(4,10,0,0) extern void rtems_bsdnet_loopattach(); static struct rtems_bsdnet_ifconfig loopback_config = { "lo0", /* name */ @@ -25,7 +41,7 @@ static struct rtems_bsdnet_ifconfig loopback_config = { "127.0.0.1", /* IP address */ "255.0.0.0", /* IP net mask */ }; - +#endif /* * The following conditionals select the network interface card. * @@ -37,19 +53,23 @@ 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 */ +#if RTEMS_VERSION_INT<=VERSION_INT(4,10,0,0) &loopback_config, /* link to next interface */ +#else + NULL, +#endif }; + 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 */ - &ne2k_driver_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 = { @@ -73,12 +93,14 @@ static struct rtems_bsdnet_ifconfig e3c509_driver_config = { # endif # endif -static struct rtems_bsdnet_ifconfig bsp_driver_config = { +static struct rtems_bsdnet_ifconfig netdriver_config = { RTEMS_BSP_NETWORK_DRIVER_NAME, /* name */ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* attach function */ +#if RTEMS_VERSION_INT<=VERSION_INT(4,10,0,0) &loopback_config, /* link to next interface */ +#endif }; -#define FIRST_DRIVER_CONFIG &bsp_driver_config +#define FIRST_DRIVER_CONFIG &netdriver_config #endif @@ -127,3 +149,11 @@ struct rtems_bsdnet_config rtems_bsdnet_config = { NULL, /* Host name */ MY_DOMAINNAME, /* Domain name */ }; +#else // libbsd "new" stack +// nothing to do?? +#endif // RTEMS_LEGACY_STACK + + + + + diff --git a/modules/libcom/RTEMS/rtems_config.c b/modules/libcom/RTEMS/score/rtems_config.c similarity index 100% rename from modules/libcom/RTEMS/rtems_config.c rename to modules/libcom/RTEMS/score/rtems_config.c diff --git a/modules/libcom/RTEMS/rtems_init.c b/modules/libcom/RTEMS/score/rtems_init.c similarity index 100% rename from modules/libcom/RTEMS/rtems_init.c rename to modules/libcom/RTEMS/score/rtems_init.c diff --git a/modules/libcom/RTEMS/setBootConfigFromNVRAM.c b/modules/libcom/RTEMS/setBootConfigFromNVRAM.c index 6fcca54b2..deb9f0654 100644 --- a/modules/libcom/RTEMS/setBootConfigFromNVRAM.c +++ b/modules/libcom/RTEMS/setBootConfigFromNVRAM.c @@ -12,7 +12,9 @@ #include #include #include +#ifdef RTEMS_LEGACY_STACK #include +#endif #include #include #include @@ -26,6 +28,7 @@ char *env_nfsServer; char *env_nfsPath; char *env_nfsMountPoint; +extern char* rtems_bsdnet_bootp_cmdline; /* * Split argument string of form nfs_server:nfs_export: * The nfs_export component will be used as: diff --git a/modules/libcom/src/calc/postfix.c b/modules/libcom/src/calc/postfix.c index 7d7a569a8..1a46bddf2 100644 --- a/modules/libcom/src/calc/postfix.c +++ b/modules/libcom/src/calc/postfix.c @@ -27,6 +27,10 @@ #include "postfixPvt.h" #include "libComAPI.h" +#ifdef RTEMS_HAS_ALTIVEC +#pragma GCC push_options +#pragma GCC optimize ("O0") +#endif /* declarations for postfix */ @@ -631,3 +635,6 @@ LIBCOM_API void } } } +#ifdef RTEMS_HAS_ALTIVEC +#pragma GCC pop_options +#endif diff --git a/modules/libcom/src/freeList/freeListLib.c b/modules/libcom/src/freeList/freeListLib.c old mode 100755 new mode 100644 diff --git a/modules/libcom/src/iocsh/initHooks.c b/modules/libcom/src/iocsh/initHooks.c index 922bb1d4d..70572934d 100644 --- a/modules/libcom/src/iocsh/initHooks.c +++ b/modules/libcom/src/iocsh/initHooks.c @@ -120,14 +120,25 @@ const char *initHookName(int state) "initHookAfterInitialProcess", "initHookAfterCaServerInit", "initHookAfterIocBuilt", + "initHookAtIocRun", "initHookAfterDatabaseRunning", "initHookAfterCaServerRunning", "initHookAfterIocRunning", + "initHookAtIocPause", "initHookAfterCaServerPaused", "initHookAfterDatabasePaused", "initHookAfterIocPaused", + + "initHookAtShutdown", + "initHookAfterCloseLinks", + "initHookAfterStopScan", + "initHookAfterStopCallback", + "initHookAfterStopLinks", + "initHookBeforeFree", + "initHookAfterShutdown", + "initHookAfterInterruptAccept", "initHookAtEnd" }; diff --git a/modules/libcom/src/log/Makefile b/modules/libcom/src/log/Makefile index 2dcfbc516..74d173575 100644 --- a/modules/libcom/src/log/Makefile +++ b/modules/libcom/src/log/Makefile @@ -24,5 +24,5 @@ iocLogServer_SYS_LIBS_WIN32 += user32 ws2_32 dbghelp SCRIPTS_HOST = S99logServer EXPAND += S99logServer@ -EXPAND_VARS = INSTALL_BIN=$(abspath $(INSTALL_BIN)) +EXPAND_VARS = INSTALL_BIN=$(FINAL_LOCATION)/bin/$(T_A) diff --git a/modules/libcom/src/misc/epicsString.h b/modules/libcom/src/misc/epicsString.h index 5bb8c87c1..24f1efb62 100644 --- a/modules/libcom/src/misc/epicsString.h +++ b/modules/libcom/src/misc/epicsString.h @@ -56,7 +56,7 @@ LIBCOM_API int epicsStrGlobMatch(const char *str, const char *pattern); * * @returns 1 if the first len characters of str match the pattern, 0 if not. * - * @since UNRELEASED + * @since 7.0.6 */ LIBCOM_API int epicsStrnGlobMatch(const char *str, size_t len, const char *pattern); diff --git a/modules/libcom/src/osi/epicsStdio.h b/modules/libcom/src/osi/epicsStdio.h index b37adfeb0..9bb5eb3e0 100644 --- a/modules/libcom/src/osi/epicsStdio.h +++ b/modules/libcom/src/osi/epicsStdio.h @@ -7,8 +7,42 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ - -/* epicsStdio.h */ +/** + * \file epicsStdio.h + * \brief Standardize the behaviour of stdio across EPICS targets + * + * \details + * The `epicsStdio.h` header includes the operating system's `stdio.h` header + * and if used should replace it. + * + * epicsSnprintf() and epicsVsnprintf() have the same semantics as the C99 + * functions snprintf() and vsnprintf(), but correct the behaviour of the + * implementations on some operating systems. + * + * The routines epicsGetStdin(), epicsGetStdout(), epicsGetStderr(), + * epicsStdoutPrintf(), epicsStdoutPuts(), and epicsStdoutPutchar() + * are not normally named directly in user code. They are provided for use by + * various macros which redefine several standard C identifiers. + * This is done so that any I/O through these standard streams can be + * redirected, usually to or from a file. The primary use of this facility + * is for iocsh() and any commands called from it, allowing redirection of + * the standard input and/or output streams while running those commands. + * In order for this redirection to work, all modules involved in such I/O + * must include `epicsStdio.h` instead of the system header `stdio.h`. + * The redirections are: + * - `stdin` becomes epicsGetStdin() + * - `stdout` becomes epicsGetStdout() + * - `stderr` becomes epicsGetStderr() + * - `printf` becomes epicsStdoutPrintf() + * - `puts` becomes epicsStdoutPuts() + * - `putchar` becomes epicsStdoutPutchar() + * + * The epicsSetThreadStdin(), epicsSetThreadStdout() and epicsSetThreadStderr() + * routines allow the standard file streams to be redirected on a per thread + * basis, e.g. calling epicsThreadStdout() will affect only the thread which + * calls it. To cancel a stream redirection, pass a NULL argument in another + * call to the same redirection routine that was used to set it. + */ #ifndef epicsStdioh #define epicsStdioh @@ -52,23 +86,76 @@ extern "C" { # define putchar epicsStdoutPutchar #endif +/** + * \brief epicsSnprintf() is meant to have the same semantics as the C99 + * function snprintf() + * + * \details + * This is provided because some architectures do not implement these functions, + * while others implement them incorrectly. + * Standardized as a C99 function, snprintf() acts like sprintf() except that + * the `size` argument gives the maximum number of characters (including the + * trailing zero byte) that may be placed in `str`. + * + * On some operating systems though the implementation of this function does + * not always return the correct value. If the OS implementation does not + * correctly return the number of characters that would have been written when + * the output gets truncated, it is not worth trying to fix this as long as + * they return `size-1` instead; the resulting string must always be correctly + * terminated with a zero byte. + * + * In some scenarios the epicsSnprintf() implementation may not provide the + * correct C99 semantics for the return value when `size` is given as zero. + * On these systems epicsSnprintf() can return an error (a value less than + * zero) when a buffer length of zero is passed in, so callers should not use + * that technique to calculate the length of the buffer required. + * + * \return The number of characters (not counting the terminating zero byte) + * that would be written to `str` if it was large enough to hold them all; the + * output has been truncated if the return value is `size` or more. + */ LIBCOM_API int epicsStdCall epicsSnprintf( char *str, size_t size, const char *format, ...) EPICS_PRINTF_STYLE(3,4); +/** + * \brief epicsVsnprintf() is meant to have the same semantics as the C99 + * function vsnprintf() + * + * \details + * This is provided because some architectures do not implement these functions, + * while others implement them incorrectly. + * Standardized as a C99 function, vsnprintf() acts like vsprintf() except that + * the `size` argument gives the maximum number of characters (including the + * trailing zero byte) that may be placed in `str`. + * + * On some operating systems though the implementation of this function does + * not always return the correct value. If the OS implementation does not + * correctly return the number of characters that would have been written when + * the output gets truncated, it is not worth trying to fix this as long as + * they return `size-1` instead; the resulting string must always be correctly + * terminated with a zero byte. + * + * In some scenarios the epicsSnprintf() implementation may not provide the + * correct C99 semantics for the return value when `size` is given as zero. + * On these systems epicsSnprintf() can return an error (a value less than + * zero) when a buffer length of zero is passed in, so callers should not use + * that technique to calculate the length of the buffer required. + * + * \return The number of characters (not counting the terminating zero byte) + * that would be written to `str` if it was large enough to hold them all; the + * output has been truncated if the return value is `size` or more. + */ LIBCOM_API int epicsStdCall epicsVsnprintf( char *str, size_t size, const char *format, va_list ap); -/* - * truncate to specified size (we dont use truncate() - * because it is not portable) - * - * pFileName - name (and optionally path) of file - * size - the new file size (if file is curretly larger) - * - * returns TF_OK if the file is less than size bytes - * or if it was successfully truncated. Returns - * TF_ERROR if the file could not be truncated. - */ enum TF_RETURN {TF_OK=0, TF_ERROR=1}; +/** + * \brief Truncate a file to a specified size + * \note The BSD function truncate() was not available on all targets + * \param pFileName Name (and optionally path) of file + * \param size The new file size (if files is currently larger) + * \return `TF_OK` if the file is less that size bytes or if it was successfully + * truncated; `TF_ERROR` if the file could not be truncated + */ LIBCOM_API enum TF_RETURN truncateFile ( const char *pFileName, unsigned long size ); /* The following are for redirecting stdin,stdout,stderr */ diff --git a/modules/libcom/src/osi/epicsThread.h b/modules/libcom/src/osi/epicsThread.h index f294c1d75..a9ad476b3 100644 --- a/modules/libcom/src/osi/epicsThread.h +++ b/modules/libcom/src/osi/epicsThread.h @@ -59,6 +59,7 @@ #include #include "libComAPI.h" +#include "compilerDependencies.h" #ifdef __cplusplus extern "C" { @@ -142,8 +143,12 @@ LIBCOM_API void epicsThreadRealtimeLock(void); * call this routine. This should be the last call in main, except the * final return. On most systems epicsThreadExitMain never returns.This * must only be called by the main thread. + * + * @deprecated Deprecated for lack of use. Please report any usage. + * Recommended replacement is loop + epicsThreadSleep(), + * epicsEventMustWait(), or similar. **/ -LIBCOM_API void epicsStdCall epicsThreadExitMain(void); +LIBCOM_API void epicsStdCall epicsThreadExitMain(void) EPICS_DEPRECATED; /** For use with epicsThreadCreateOpt() */ typedef struct epicsThreadOpts { diff --git a/modules/libcom/src/osi/epicsTime.h b/modules/libcom/src/osi/epicsTime.h index 0c3587fef..090fb5c48 100644 --- a/modules/libcom/src/osi/epicsTime.h +++ b/modules/libcom/src/osi/epicsTime.h @@ -36,6 +36,10 @@ typedef struct epicsTimeStamp { epicsUInt32 nsec; /**< \brief nanoseconds within second */ } epicsTimeStamp; +/** \brief Type of UTAG field (dbCommon::utag) + */ +typedef epicsUInt64 epicsUTag; + /** \brief Old time-stamp data type, deprecated. * \deprecated TS_STAMP was provided for compatibility with Base-3.13 code. * It will be removed in some future release of EPICS 7. diff --git a/modules/libcom/src/osi/os/Darwin/osdSock.h b/modules/libcom/src/osi/os/Darwin/osdSock.h index 5d266e326..e9350420f 100644 --- a/modules/libcom/src/osi/os/Darwin/osdSock.h +++ b/modules/libcom/src/osi/os/Darwin/osdSock.h @@ -56,6 +56,7 @@ typedef unsigned char osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN ESHUTDOWN #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE #ifndef SHUT_RD #define SHUT_RD 0 diff --git a/modules/libcom/src/osi/os/Linux/osdSock.h b/modules/libcom/src/osi/os/Linux/osdSock.h index 4a92be720..3a604c88e 100644 --- a/modules/libcom/src/osi/os/Linux/osdSock.h +++ b/modules/libcom/src/osi/os/Linux/osdSock.h @@ -63,6 +63,7 @@ typedef int osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN ESHUTDOWN #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE #ifndef SHUT_RD # define SHUT_RD 0 diff --git a/modules/libcom/src/osi/os/RTEMS-posix/devLibVMEOSD.c b/modules/libcom/src/osi/os/RTEMS-posix/devLibVMEOSD.c new file mode 100644 index 000000000..8ae1503ec --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/devLibVMEOSD.c @@ -0,0 +1,6 @@ +#ifdef RTEMS_LEGACY_STACK +#include "os/RTEMS-score/devLibVMEOSD.c" +#else +#pragma message "\n VME Support requires the RTEMS Legacy stack\n" +#include "os/default/devLibVMEOSD.c" +#endif diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c new file mode 100644 index 000000000..7c7ea8aad --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c @@ -0,0 +1,160 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* SPDX-License-Identifier: EPICS +* EPICS Base is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * We want to access information which is + * normally hidden from application programs. + */ +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 + +#define epicsExportSharedSymbols +#include +#include +#include +#include +#include +#include +#include "epicsMessageQueue.h" +#include "errlog.h" +#include + +#include +#include +#include + +static int idCnt; + +LIBCOM_API epicsMessageQueueId epicsStdCall +epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize) +{ + struct mq_attr the_attr; + epicsMessageQueueId id = (epicsMessageQueueId)calloc(1, sizeof(*id)); + sprintf(id->name, "MQ_%0d", epicsAtomicIncrIntT(&idCnt)); + the_attr.mq_maxmsg = capacity; + the_attr.mq_msgsize = maximumMessageSize; + id->id = mq_open(id->name, O_RDWR | O_CREAT | O_EXCL, 0644, &the_attr); + if (id->id <0) { + fprintf (stderr, "Can't create message queue: %s\n", strerror (errno)); + return NULL; + } + return id; +} + +LIBCOM_API void epicsStdCall epicsMessageQueueDestroy( + epicsMessageQueueId id) +{ + int rv; + rv = mq_close(id->id); + if( rv ) { + fprintf(stderr, "epicsMessageQueueDestroy mq_close failed: %s\n", + strerror(rv)); + } + rv = mq_unlink(id->name); + if( rv ) { + fprintf(stderr,"epicsMessageQueueDestroy mq_unlink %s failed: %s\n", + id->name, strerror(rv)); + } + free(id); +} + + +LIBCOM_API int epicsStdCall epicsMessageQueueTrySend( + epicsMessageQueueId id, + void *message, + unsigned int messageSize) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return mq_timedsend(id->id, (char const *)message, messageSize, 0, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int messageSize, + double timeout) +{ + struct timespec ts; + unsigned long micros; + + // assume timeout in sec + micros = (unsigned long)(timeout * 1000000.0); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += micros / 1000000L; + ts.tv_nsec += (micros % 1000000L) * 1000L; + + return mq_timedsend (id->id, (const char *)message, messageSize, 0, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueTryReceive( + epicsMessageQueueId id, + void *message, + unsigned int size) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int size, + double timeout) +{ + unsigned long micros; + struct timespec ts; + + micros = (unsigned long)(timeout * 1000000.0); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += micros / 1000000L; + ts.tv_nsec += (micros % 1000000L) * 1000L; + + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueuePending( + epicsMessageQueueId id) +{ + int rv; + struct mq_attr the_attr; + + rv = mq_getattr(id->id, &the_attr); + if (rv) { + fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n", + (unsigned int)id->id, id->name, strerror(rv)); + return -1; + } + return the_attr.mq_curmsgs; +} +LIBCOM_API void epicsStdCall epicsMessageQueueShow( + epicsMessageQueueId id, + int level) +{ + int rv; + struct mq_attr the_attr; + + rv = mq_getattr(id->id, &the_attr); + if (rv) { + fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n", + (unsigned int)id->id, id->name, strerror(rv)); + } + + printf("Message Queue Used:%ld Max Msg:%lu", the_attr.mq_curmsgs, the_attr.mq_maxmsg); + if (level >= 1) + printf(" Maximum size:%lu", the_attr.mq_msgsize); + + printf("\n"); +} diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h new file mode 100644 index 000000000..95e66e73e --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h @@ -0,0 +1,28 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * Very thin shims around RTEMS routines + */ +#include +#include + +struct epicsMessageQueueOSD { + mqd_t id; + char name[24]; +}; +#define epicsMessageQueueSend(q,m,l) (mq_send((q)->id, (const char*)(m), (l), 0)) +#define epicsMessageQueueReceive(q,m,s) (mq_receive((q)->id, (char*)(m), (s), NULL)) + diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c b/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c new file mode 100644 index 000000000..2ee16bf88 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c @@ -0,0 +1,8 @@ +#include +#include +#include +#ifndef RTEMS_LEGACY_STACK +#include +#endif + +#include "../posix/osdMutex.c" diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c b/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c new file mode 100644 index 000000000..5b202fd1d --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c @@ -0,0 +1,43 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +#include +#include +#include +#define epicsExportSharedSymbols +#include "osiPoolStatus.h" + +#if __RTEMS_MAJOR__<5 +/* + * * osiSufficentSpaceInPool () + * */ +LIBCOM_API int epicsStdCall osiSufficentSpaceInPool ( size_t contiguousBlockSize ) +{ + rtems_malloc_statistics_t s; + unsigned long n; + + malloc_get_statistics(&s); + n = s.space_available - (unsigned long)(s.lifetime_allocated - s.lifetime_freed); + return (n > (50000 + contiguousBlockSize)); +} + +#else +/* + * osiSufficentSpaceInPool () + */ +LIBCOM_API int epicsStdCall osiSufficentSpaceInPool ( size_t contiguousBlockSize ) +{ + unsigned long n; + Heap_Information_block info; + + malloc_info( &info ); + n = info.Stats.size - (unsigned long)(info.Stats.lifetime_allocated - info.Stats.lifetime_freed); + return (n > (50000 + contiguousBlockSize)); +} +#endif diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h b/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h new file mode 100644 index 000000000..f0a57c268 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h @@ -0,0 +1,81 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Linux specific socket include + */ + +#ifndef osdSockH +#define osdSockH + +#include + +#include +#include /* for MAXHOSTNAMELEN */ +#include +#include +#include +#include +#include +#include +#include +#include +#include /* close() and others */ + +typedef int SOCKET; +#define INVALID_SOCKET (-1) +#define SOCKERRNO errno +#define socket_ioctl(A,B,C) ioctl(A,B,C) +typedef int osiSockIoctl_t; +typedef socklen_t osiSocklen_t; +typedef char osiSockOptMcastLoop_t; +typedef char osiSockOptMcastTTL_t; + +#define FD_IN_FDSET(FD) ((FD)ifr_addr.sa_len + sizeof(pifreq->ifr_name)) + +#ifndef IPPORT_USERRESERVED +#define IPPORT_USERRESERVED 5000 +#endif + +#endif /*osdSockH*/ diff --git a/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c b/modules/libcom/src/osi/os/RTEMS-score/devLibVMEOSD.c similarity index 85% rename from modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c rename to modules/libcom/src/osi/os/RTEMS-score/devLibVMEOSD.c index f8b05421c..ed310eebc 100644 --- a/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c +++ b/modules/libcom/src/osi/os/RTEMS-score/devLibVMEOSD.c @@ -19,12 +19,16 @@ #include #include "devLibVME.h" #include +#include +#include #if defined(__PPC__) || defined(__mcf528x__) +/* EPICS VME support requires various routines to be provided by the + * BSP. Most MVME PowerPC BSPs provide them, plus the uC5282. + */ #if defined(__PPC__) #include -#include #endif @@ -126,8 +130,7 @@ static long rtemsDevInit(void) { /* assume the vme bridge has been initialized by bsp */ - /* init BSP extensions [memProbe etc.] */ - return bspExtInit(); + return 0; } /* @@ -245,18 +248,70 @@ static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options, return 0; } +#if defined(__m68k__) +/* All RTEMS m68k BSPs define this, m68k/shared/[misc/]memProbe.c */ +extern +rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval); +#else + +static +rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval) +{ + rtems_interrupt_level flags; + rtems_status_code ret = RTEMS_SUCCESSFUL; + epicsUInt32 val; + + /* bspExt allows caller to write uninitialized values, we don't */ + if(write && !pval) + return RTEMS_INVALID_NUMBER; + + switch(size) { + case 1: + case 2: + case 4: + break; + default: + return RTEMS_INVALID_SIZE; + } + + if(write) + memcpy(&val, pval, size); + + rtems_interrupt_disable(flags); + _BSP_clear_hostbridge_errors(0,1); + + if(!write) { + switch(size) { + case 1: val = ioread8(addr)<<24; break; + case 2: val = nat_ioread16(addr)<<16; break; + case 4: val = nat_ioread32(addr); break; + } + } else { + switch(size) { + case 1: iowrite8(addr, val>>24); break; + case 2: nat_iowrite16(addr, val>>16); break; + case 4: nat_iowrite32(addr, val); break; + } + } + + ret = _BSP_clear_hostbridge_errors(0,1); + rtems_interrupt_enable(flags); + + if(!write && pval) + memcpy(pval, &val, size); + + return ret; +} +#endif + /* * a bus error safe "wordSize" read at the specified address which returns * unsuccessful status if the device isnt present */ -rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval); static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue) { long status; - /* - * this global variable exists in the nivxi library - */ status = bspExtMemProbe ((void*)ptr, 0/*read*/, wordSize, pValue); if (status!=RTEMS_SUCCESSFUL) { return S_dev_noDevice; @@ -273,9 +328,6 @@ static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const voi { long status; - /* - * this global variable exists in the nivxi library - */ status = bspExtMemProbe ((void*)ptr, 1/*write*/, wordSize, (void*)pValue); if (status!=RTEMS_SUCCESSFUL) { return S_dev_noDevice; @@ -359,7 +411,7 @@ devLibVME *pdevLibVME; #endif /* defined(__PPC__) || defined(__mcf528x__) */ /* - * Some vxWorks convenience routines + * Some convenience routines */ void bcopyLongs(char *source, char *destination, int nlongs) diff --git a/modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.cpp b/modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.cpp rename to modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.h b/modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.h rename to modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.h diff --git a/modules/libcom/src/osi/os/RTEMS/epicsMath.h b/modules/libcom/src/osi/os/RTEMS-score/epicsMath.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsMath.h rename to modules/libcom/src/osi/os/RTEMS-score/epicsMath.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdEvent.c rename to modules/libcom/src/osi/os/RTEMS-score/osdEvent.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdEvent.h b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdEvent.h rename to modules/libcom/src/osi/os/RTEMS-score/osdEvent.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdFindSymbol.c b/modules/libcom/src/osi/os/RTEMS-score/osdFindSymbol.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdFindSymbol.c rename to modules/libcom/src/osi/os/RTEMS-score/osdFindSymbol.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdMutex.c b/modules/libcom/src/osi/os/RTEMS-score/osdMutex.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdMutex.c rename to modules/libcom/src/osi/os/RTEMS-score/osdMutex.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdMutex.h b/modules/libcom/src/osi/os/RTEMS-score/osdMutex.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdMutex.h rename to modules/libcom/src/osi/os/RTEMS-score/osdMutex.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdPoolStatus.c b/modules/libcom/src/osi/os/RTEMS-score/osdPoolStatus.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdPoolStatus.c rename to modules/libcom/src/osi/os/RTEMS-score/osdPoolStatus.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdProcess.c b/modules/libcom/src/osi/os/RTEMS-score/osdProcess.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdProcess.c rename to modules/libcom/src/osi/os/RTEMS-score/osdProcess.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdReadline.c b/modules/libcom/src/osi/os/RTEMS-score/osdReadline.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdReadline.c rename to modules/libcom/src/osi/os/RTEMS-score/osdReadline.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdSignal.cpp b/modules/libcom/src/osi/os/RTEMS-score/osdSignal.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdSignal.cpp rename to modules/libcom/src/osi/os/RTEMS-score/osdSignal.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/osdSock.h b/modules/libcom/src/osi/os/RTEMS-score/osdSock.h similarity index 96% rename from modules/libcom/src/osi/os/RTEMS/osdSock.h rename to modules/libcom/src/osi/os/RTEMS-score/osdSock.h index 49023fe78..ea765ece8 100644 --- a/modules/libcom/src/osi/os/RTEMS/osdSock.h +++ b/modules/libcom/src/osi/os/RTEMS-score/osdSock.h @@ -37,6 +37,10 @@ int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, str } #endif +#ifndef IPPORT_USERRESERVED +#define IPPORT_USERRESERVED 5000 +#endif + typedef int SOCKET; #define INVALID_SOCKET (-1) #define SOCKERRNO errno @@ -67,8 +71,8 @@ typedef unsigned char osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN EPIPE #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE -#define bzero(p,n) memset(p,0,n) #include #include #include diff --git a/modules/libcom/src/osi/os/RTEMS/osdSpin.c b/modules/libcom/src/osi/os/RTEMS-score/osdSpin.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdSpin.c rename to modules/libcom/src/osi/os/RTEMS-score/osdSpin.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdStrtod.h b/modules/libcom/src/osi/os/RTEMS-score/osdStrtod.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdStrtod.h rename to modules/libcom/src/osi/os/RTEMS-score/osdStrtod.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdThread.c b/modules/libcom/src/osi/os/RTEMS-score/osdThread.c similarity index 99% rename from modules/libcom/src/osi/os/RTEMS/osdThread.c rename to modules/libcom/src/osi/os/RTEMS-score/osdThread.c index dd65692c6..71a532e62 100644 --- a/modules/libcom/src/osi/os/RTEMS/osdThread.c +++ b/modules/libcom/src/osi/os/RTEMS-score/osdThread.c @@ -219,6 +219,8 @@ threadWrapper (rtems_task_argument arg) */ void epicsThreadExitMain (void) { + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); } static rtems_status_code diff --git a/modules/libcom/src/osi/os/RTEMS/osdThread.h b/modules/libcom/src/osi/os/RTEMS-score/osdThread.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdThread.h rename to modules/libcom/src/osi/os/RTEMS-score/osdThread.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdThreadExtra.c b/modules/libcom/src/osi/os/RTEMS-score/osdThreadExtra.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdThreadExtra.c rename to modules/libcom/src/osi/os/RTEMS-score/osdThreadExtra.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdTime.cpp b/modules/libcom/src/osi/os/RTEMS-score/osdTime.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdTime.cpp rename to modules/libcom/src/osi/os/RTEMS-score/osdTime.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/osdTime.h b/modules/libcom/src/osi/os/RTEMS-score/osdTime.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdTime.h rename to modules/libcom/src/osi/os/RTEMS-score/osdTime.h diff --git a/modules/libcom/src/osi/os/RTEMS/osiUnistd.h b/modules/libcom/src/osi/os/RTEMS-score/osiUnistd.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osiUnistd.h rename to modules/libcom/src/osi/os/RTEMS-score/osiUnistd.h diff --git a/modules/libcom/src/osi/os/WIN32/osdEvent.c b/modules/libcom/src/osi/os/WIN32/osdEvent.c index 996dbd3be..62117cb16 100644 --- a/modules/libcom/src/osi/os/WIN32/osdEvent.c +++ b/modules/libcom/src/osi/os/WIN32/osdEvent.c @@ -26,6 +26,8 @@ #include "libComAPI.h" #include "epicsEvent.h" +#include "osdThreadPvt.h" + typedef struct epicsEventOSD { HANDLE handle; } epicsEventOSD; @@ -90,27 +92,47 @@ LIBCOM_API epicsEventStatus epicsEventWait ( epicsEventId pSem ) LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout ( epicsEventId pSem, double timeOut ) { - static const unsigned mSecPerSec = 1000; + /* waitable timers use 100 nanosecond intervals, like FILETIME */ + static const unsigned ivalPerSec = 10000000u; /* number of 100ns intervals per second */ + static const unsigned mSecPerSec = 1000u; /* milliseconds per second */ + HANDLE handles[2]; DWORD status; - DWORD tmo; + LARGE_INTEGER tmo; + HANDLE timer; + LONGLONG nIvals; /* number of intervals */ if ( timeOut <= 0.0 ) { - tmo = 0u; + tmo.QuadPart = 0u; } - else if ( timeOut >= INFINITE / mSecPerSec ) { - tmo = INFINITE - 1; + else if ( timeOut >= INFINITE / mSecPerSec ) { + /* we need to apply a maximum wait time to stop an overflow. We choose (INFINITE - 1) milliseconds, + to be compatible with previous WaitForSingleObject() implementation */ + nIvals = (LONGLONG)(INFINITE - 1) * (ivalPerSec / mSecPerSec); + tmo.QuadPart = -nIvals; /* negative value means a relative time offset for timer */ } else { - tmo = ( DWORD ) ( ( timeOut * mSecPerSec ) + 0.5 ); - if ( tmo == 0 ) { - tmo = 1; - } + nIvals = (LONGLONG)(timeOut * ivalPerSec + 0.999999); + tmo.QuadPart = -nIvals; + } + + if (tmo.QuadPart < 0) { + timer = osdThreadGetTimer(); + if (!SetWaitableTimer(timer, &tmo, 0, NULL, NULL, 0)) { + return epicsEventError; + } + handles[0] = pSem->handle; + handles[1] = timer; + status = WaitForMultipleObjects (2, handles, FALSE, INFINITE); + } + else { + status = WaitForSingleObject(pSem->handle, 0); } - status = WaitForSingleObject ( pSem->handle, tmo ); if ( status == WAIT_OBJECT_0 ) { return epicsEventOK; } - else if ( status == WAIT_TIMEOUT ) { + else if ( status == WAIT_OBJECT_0 + 1 || status == WAIT_TIMEOUT ) { + /* WaitForMultipleObjects will trigger WAIT_OBJECT_0 + 1, + WaitForSingleObject will trigger WAIT_TIMEOUT */ return epicsEventWaitTimeout; } else { diff --git a/modules/libcom/src/osi/os/WIN32/osdProcess.c b/modules/libcom/src/osi/os/WIN32/osdProcess.c index 0f137bf37..cff1ed4bd 100644 --- a/modules/libcom/src/osi/os/WIN32/osdProcess.c +++ b/modules/libcom/src/osi/os/WIN32/osdProcess.c @@ -50,10 +50,14 @@ LIBCOM_API osiGetUserNameReturn epicsStdCall osiGetUserName (char *pBuf, unsigne LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess ( const char *pProcessName, const char *pBaseExecutableName ) { + BOOL silent = pProcessName && pProcessName[0]=='!'; BOOL status; STARTUPINFO startupInfo; PROCESS_INFORMATION processInfo; + if(silent) + pProcessName++; /* skip '!' */ + GetStartupInfo ( &startupInfo ); startupInfo.lpReserved = NULL; startupInfo.lpTitle = (char *) pProcessName; @@ -115,7 +119,7 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess /* Free the buffer. */ LocalFree (errStrMsgBuf); } - else { + else if(!silent) { fprintf (stderr, "!!WARNING!!\n"); fprintf (stderr, "Unable to locate executable \"%s\".\n", pBaseExecutableName); fprintf (stderr, "You may need to modify your \"path\" environment variable.\n"); diff --git a/modules/libcom/src/osi/os/WIN32/osdSock.h b/modules/libcom/src/osi/os/WIN32/osdSock.h index 87b0a880e..9eab6e76a 100644 --- a/modules/libcom/src/osi/os/WIN32/osdSock.h +++ b/modules/libcom/src/osi/os/WIN32/osdSock.h @@ -66,6 +66,7 @@ typedef DWORD osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN WSAESHUTDOWN #define SOCK_ENOTSOCK WSAENOTSOCK #define SOCK_EBADF WSAENOTSOCK +#define SOCK_EMSGSIZE WSAEMSGSIZE /* * Under WIN32, FD_SETSIZE is the max. number of sockets, diff --git a/modules/libcom/src/osi/os/WIN32/osdThread.c b/modules/libcom/src/osi/os/WIN32/osdThread.c index 6c00be4ca..cff3e45d4 100644 --- a/modules/libcom/src/osi/os/WIN32/osdThread.c +++ b/modules/libcom/src/osi/os/WIN32/osdThread.c @@ -19,9 +19,6 @@ #define VC_EXTRALEAN #define STRICT -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x400 /* No support for W95 */ -#endif #include #include /* for _endthread() etc */ @@ -33,6 +30,7 @@ #include "ellLib.h" #include "epicsExit.h" #include "epicsAtomic.h" +#include "osdThreadPvt.h" LIBCOM_API void osdThreadHooksRun(epicsThreadId id); @@ -55,6 +53,7 @@ typedef struct epicsThreadOSD { unsigned epicsPriority; char isSuspended; int joinable; + HANDLE timer; /* waitable timer */ } win32ThreadParam; typedef struct epicsThreadPrivateOSD { @@ -221,6 +220,19 @@ static win32ThreadGlobal * fetchWin32ThreadGlobal ( void ) return pWin32ThreadGlobal; } +static void epicsParmCleanupDataWIN32 ( win32ThreadParam * pParm ) +{ + if ( pParm ) { + if ( pParm->handle ) { + CloseHandle ( pParm->handle ); + } + if ( pParm->timer ) { + CloseHandle ( pParm->timer ); + } + free ( pParm ); + } +} + static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm ) { win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); @@ -239,8 +251,7 @@ static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm ) ellDelete ( & pGbl->threadList, & pParm->node ); LeaveCriticalSection ( & pGbl->mutex ); - CloseHandle ( pParm->handle ); - free ( pParm ); + epicsParmCleanupDataWIN32 ( pParm ); } } @@ -249,7 +260,8 @@ static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm ) */ LIBCOM_API void epicsStdCall epicsThreadExitMain ( void ) { - _endthread (); + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); } /* @@ -470,10 +482,10 @@ static unsigned WINAPI epicsWin32ThreadEntry ( LPVOID lpParameter ) } epicsExitCallAtThreadExits (); + /* * CAUTION: !!!! the thread id might continue to be used after this thread exits !!!! */ - if ( pGbl ) { TlsSetValue ( pGbl->tlsIndexThreadLibraryEPICS, (void*)0xdeadbeef ); } @@ -493,6 +505,16 @@ static win32ThreadParam * epicsThreadParmCreate ( const char *pName ) strcpy ( pParmWIN32->pName, pName ); pParmWIN32->isSuspended = 0; epicsAtomicIncrIntT(&pParmWIN32->refcnt); +#ifdef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION + pParmWIN32->timer = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); +#endif + if (pParmWIN32->timer == NULL) { + pParmWIN32->timer = CreateWaitableTimer(NULL, 0, NULL); + } + if (pParmWIN32->timer == NULL) { + free(pParmWIN32); + return NULL; + } } return pParmWIN32; } @@ -590,7 +612,7 @@ epicsThreadId epicsThreadCreateOpt ( CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, & threadId ); if ( pParmWIN32->handle == 0 ) { - free ( pParmWIN32 ); + epicsParmCleanupDataWIN32 ( pParmWIN32 ); return NULL; } /* weird win32 interface threadId parameter inconsistency */ @@ -600,8 +622,7 @@ epicsThreadId epicsThreadCreateOpt ( osdPriority = epicsThreadGetOsdPriorityValue (opts->priority); bstat = SetThreadPriority ( pParmWIN32->handle, osdPriority ); if (!bstat) { - CloseHandle ( pParmWIN32->handle ); - free ( pParmWIN32 ); + epicsParmCleanupDataWIN32 ( pParmWIN32 ); return NULL; } @@ -611,11 +632,10 @@ epicsThreadId epicsThreadCreateOpt ( wstat = ResumeThread ( pParmWIN32->handle ); if (wstat==0xFFFFFFFF) { - EnterCriticalSection ( & pGbl->mutex ); - ellDelete ( & pGbl->threadList, & pParmWIN32->node ); - LeaveCriticalSection ( & pGbl->mutex ); - CloseHandle ( pParmWIN32->handle ); - free ( pParmWIN32 ); + EnterCriticalSection ( & pGbl->mutex ); + ellDelete ( & pGbl->threadList, & pParmWIN32->node ); + LeaveCriticalSection ( & pGbl->mutex ); + epicsParmCleanupDataWIN32 ( pParmWIN32 ); return NULL; } @@ -777,24 +797,62 @@ LIBCOM_API int epicsStdCall epicsThreadIsSuspended ( epicsThreadId id ) } } +/** + * osdThreadGetTimer () + * return stored waitable timer object for thread + */ +HANDLE osdThreadGetTimer() +{ + win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); + win32ThreadParam * pParm; + + assert ( pGbl ); + + pParm = ( win32ThreadParam * ) + TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS ); + + return pParm->timer; +} + /* * epicsThreadSleep () */ LIBCOM_API void epicsStdCall epicsThreadSleep ( double seconds ) { - static const unsigned mSecPerSec = 1000; - DWORD milliSecDelay; + /* waitable timers use 100 nanosecond intervals, like FILETIME */ + static const unsigned ivalPerSec = 10000000u; /* number of 100ns intervals per second */ + static const unsigned mSecPerSec = 1000u; /* milliseconds per second */ + LARGE_INTEGER tmo; + HANDLE timer; + LONGLONG nIvals; /* number of intervals */ - if ( seconds > 0.0 ) { - seconds *= mSecPerSec; - seconds += 0.99999999; /* 8 9s here is optimal */ - milliSecDelay = ( seconds >= INFINITE ) ? - INFINITE - 1 : ( DWORD ) seconds; + if ( seconds <= 0.0 ) { + tmo.QuadPart = 0u; } - else { /* seconds <= 0 or NAN */ - milliSecDelay = 0u; + else if ( seconds >= INFINITE / mSecPerSec ) { + /* we need to apply a maximum wait time to stop an overflow. We choose (INFINITE - 1) milliseconds, + to be compatible with previous WaitForSingleObject() implementation */ + nIvals = (LONGLONG)(INFINITE - 1) * (ivalPerSec / mSecPerSec); + tmo.QuadPart = -nIvals; /* negative value means a relative time offset for timer */ + } + else { + nIvals = (LONGLONG)(seconds * ivalPerSec + 0.999999); + tmo.QuadPart = -nIvals; + } + + if (tmo.QuadPart == 0) { + Sleep ( 0 ); + } + else { + timer = osdThreadGetTimer(); + if (!SetWaitableTimer(timer, &tmo, 0, NULL, NULL, 0)) { + fprintf ( stderr, "epicsThreadSleep: SetWaitableTimer failed %lu\n", GetLastError() ); + return; + } + if (WaitForSingleObject(timer, INFINITE) != WAIT_OBJECT_0) { + fprintf ( stderr, "epicsThreadSleep: WaitForSingleObject failed %lu\n", GetLastError() ); + } } - Sleep ( milliSecDelay ); } /* diff --git a/modules/libcom/src/osi/os/WIN32/osdThreadPvt.h b/modules/libcom/src/osi/os/WIN32/osdThreadPvt.h new file mode 100644 index 000000000..f069841ef --- /dev/null +++ b/modules/libcom/src/osi/os/WIN32/osdThreadPvt.h @@ -0,0 +1,20 @@ +/*************************************************************************\ +* SPDX-License-Identifier: EPICS +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef osdThreadPvth +#define osdThreadPvth + +#ifdef __cplusplus +extern "C" { +#endif + +extern HANDLE osdThreadGetTimer(void); + +#ifdef __cplusplus +} +#endif + +#endif /* osdThreadPvth */ diff --git a/modules/libcom/src/osi/os/cygwin32/osdSock.h b/modules/libcom/src/osi/os/cygwin32/osdSock.h index 1d9aa818b..a725a7fe7 100644 --- a/modules/libcom/src/osi/os/cygwin32/osdSock.h +++ b/modules/libcom/src/osi/os/cygwin32/osdSock.h @@ -71,6 +71,7 @@ typedef int osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN ESHUTDOWN #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE #define ifreq_size(pifreq) (sizeof(pifreq->ifr_name)) diff --git a/modules/libcom/src/osi/os/default/epicsMMIODef.h b/modules/libcom/src/osi/os/default/epicsMMIODef.h index e8e869422..7de7b65de 100644 --- a/modules/libcom/src/osi/os/default/epicsMMIODef.h +++ b/modules/libcom/src/osi/os/default/epicsMMIODef.h @@ -130,7 +130,7 @@ bswap32(epicsUInt32 value) #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE /* Get hton[sl] declarations: */ -#include +#include /** @ingroup mmio *@{ diff --git a/modules/libcom/src/osi/os/freebsd/osdSock.h b/modules/libcom/src/osi/os/freebsd/osdSock.h index f6800e44f..8ebf37db8 100644 --- a/modules/libcom/src/osi/os/freebsd/osdSock.h +++ b/modules/libcom/src/osi/os/freebsd/osdSock.h @@ -61,6 +61,7 @@ typedef unsigned char osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN ESHUTDOWN #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE #ifndef SHUT_RD # define SHUT_RD 0 diff --git a/modules/libcom/src/osi/os/iOS/osdSock.h b/modules/libcom/src/osi/os/iOS/osdSock.h index c2aeabd67..34ee13d73 100644 --- a/modules/libcom/src/osi/os/iOS/osdSock.h +++ b/modules/libcom/src/osi/os/iOS/osdSock.h @@ -57,6 +57,7 @@ typedef unsigned char osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN ESHUTDOWN #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE #ifndef SHUT_RD #define SHUT_RD 0 diff --git a/modules/libcom/src/osi/os/posix/osdFindSymbol.c b/modules/libcom/src/osi/os/posix/osdFindSymbol.c index 6c26696c8..fc175fc60 100644 --- a/modules/libcom/src/osi/os/posix/osdFindSymbol.c +++ b/modules/libcom/src/osi/os/posix/osdFindSymbol.c @@ -7,9 +7,10 @@ \*************************************************************************/ /* osi/os/posix/osdFindSymbol.c */ +#include "epicsFindSymbol.h" + #include -#include "epicsFindSymbol.h" /* non-POSIX extension available on Linux (glibc at least) and OSX. */ diff --git a/modules/libcom/src/osi/os/posix/osdProcess.c b/modules/libcom/src/osi/os/posix/osdProcess.c index 56267d0b8..b2c26beb4 100644 --- a/modules/libcom/src/osi/os/posix/osdProcess.c +++ b/modules/libcom/src/osi/os/posix/osdProcess.c @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include #include "osiProcess.h" #include "errlog.h" @@ -61,12 +63,22 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess (const char *pProcessName, const char *pBaseExecutableName) { int status; + int silent = pProcessName && pProcessName[0]=='!'; + int fds[2]; /* [reader, writer] */ + + if(silent) + pProcessName++; /* skip '!' */ + + if(pipe(fds)) + return osiSpawnDetachedProcessFail; /* * create a duplicate process */ status = fork (); if (status < 0) { + close(fds[0]); + close(fds[1]); return osiSpawnDetachedProcessFail; } @@ -75,11 +87,29 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess * in the initiating (parent) process */ if (status) { - return osiSpawnDetachedProcessSuccess; - } + osiSpawnDetachedProcessReturn ret = osiSpawnDetachedProcessSuccess; + char buf; + ssize_t n; + close(fds[1]); - /* - * This is executed only by the new child process. + n = read(fds[0], &buf, 1); + /* Success if child exec'd without sending a '!'. + * Of course child may crash soon after, but can't + * wait around for this to happen. + */ + if(n!=0) { + ret = osiSpawnDetachedProcessFail; + } + + close(fds[0]); + return ret; + } + close(fds[0]); + (void)fcntl ( fds[1], F_SETFD, FD_CLOEXEC ); + + /* This is executed only by the new child process. + * Since we may be called from a library, we don't assume that + * all other code has set properly set FD_CLOEXEC. * Close all open files except for STDIO, so they will not * be inherited by the new program. */ @@ -89,6 +119,8 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess if (fd==STDIN_FILENO) continue; if (fd==STDOUT_FILENO) continue; if (fd==STDERR_FILENO) continue; + /* pipe to our parent will be closed automatically via FD_CLOEXEC */ + if (fd==fds[1]) continue; close (fd); } } @@ -109,12 +141,16 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess * Run the specified executable */ status = execlp (pBaseExecutableName, pBaseExecutableName, (char *)NULL); - if ( status < 0 ) { + if ( status < 0 && !silent ) { fprintf ( stderr, "**** The executable \"%s\" couldn't be located\n", pBaseExecutableName ); fprintf ( stderr, "**** because of errno = \"%s\".\n", strerror (errno) ); fprintf ( stderr, "**** You may need to modify your PATH environment variable.\n" ); fprintf ( stderr, "**** Unable to start \"%s\" process.\n", pProcessName); } + /* signal error to parent */ + ssize_t ret = write(fds[1], "!", 1); + (void)ret; /* not much we could do about this */ + close(fds[1]); /* Don't run our parent's atexit() handlers */ _exit ( -1 ); } diff --git a/modules/libcom/src/osi/os/posix/osdSock.c b/modules/libcom/src/osi/os/posix/osdSock.c index 52f52a085..4ebd0db73 100644 --- a/modules/libcom/src/osi/os/posix/osdSock.c +++ b/modules/libcom/src/osi/os/posix/osdSock.c @@ -36,6 +36,7 @@ /* with glibc, SOCK_CLOEXEC does not expand to a simple constant */ # define HAVE_SOCK_CLOEXEC #else +# undef SOCK_CLOEXEC # define SOCK_CLOEXEC (0) #endif diff --git a/modules/libcom/src/osi/os/posix/osdThread.c b/modules/libcom/src/osi/os/posix/osdThread.c index 0942d7343..541408fad 100644 --- a/modules/libcom/src/osi/os/posix/osdThread.c +++ b/modules/libcom/src/osi/os/posix/osdThread.c @@ -24,8 +24,14 @@ #include #include -#if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 -#include +#if (defined(_POSIX_MEMLOCK) && (_POSIX_MEMLOCK > 0) && !defined(__rtems__)) +# define USE_MEMLOCK 1 +#else +# define USE_MEMLOCK 0 +#endif + +#if USE_MEMLOCK +#include #endif #include "epicsStdio.h" @@ -426,7 +432,8 @@ static void epicsThreadInit(void) LIBCOM_API void epicsThreadRealtimeLock(void) { -#if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 +#if USE_MEMLOCK +#ifndef RTEMS_LEGACY_STACK // seems to be part of libbsd? if (pcommonAttr->maxPriority > pcommonAttr->minPriority) { int status = mlockall(MCL_CURRENT | MCL_FUTURE); @@ -451,6 +458,7 @@ void epicsThreadRealtimeLock(void) } } } +#endif // LEGACY STACK #endif } @@ -687,6 +695,10 @@ LIBCOM_API void epicsStdCall epicsThreadExitMain(void) epicsThreadOSD *pthreadInfo; epicsThreadInit(); + + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); if(pthreadInfo==NULL) pthreadInfo = createImplicit(); diff --git a/modules/libcom/src/osi/os/posix/osdTime.cpp b/modules/libcom/src/osi/os/posix/osdTime.cpp index 6d7b86048..b3bb84725 100644 --- a/modules/libcom/src/osi/os/posix/osdTime.cpp +++ b/modules/libcom/src/osi/os/posix/osdTime.cpp @@ -125,3 +125,15 @@ extern "C" LIBCOM_API void ++wakeTime->tv_sec; } } + +#ifdef __rtems__ +int osdTickGet() +{ + return epicsMonotonicGet(); // ns +} +int osdTickRateGet() +{ + return 1000000000; +} +void osdNTPReport() {} +#endif diff --git a/modules/libcom/src/osi/os/posix/osdTime.h b/modules/libcom/src/osi/os/posix/osdTime.h index 807b6d682..2aab01f3e 100644 --- a/modules/libcom/src/osi/os/posix/osdTime.h +++ b/modules/libcom/src/osi/os/posix/osdTime.h @@ -31,6 +31,14 @@ extern "C" { LIBCOM_API void epicsStdCall convertDoubleToWakeTime(double timeout,struct timespec *wakeTime); +#ifdef __rtems__ +void osdNTPInit(void); +int osdNTPGet(struct timespec *now); +int osdTickGet(void); +int osdTickRateGet(void); +void osdNTPReport(void); +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/modules/libcom/src/osi/os/solaris/osdSock.h b/modules/libcom/src/osi/os/solaris/osdSock.h index e125ac0c6..9cfabdf0a 100644 --- a/modules/libcom/src/osi/os/solaris/osdSock.h +++ b/modules/libcom/src/osi/os/solaris/osdSock.h @@ -69,6 +69,7 @@ typedef unsigned char osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN ESHUTDOWN #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE #ifndef SHUT_RD # define SHUT_RD 0 diff --git a/modules/libcom/src/osi/os/vxWorks/osdSock.h b/modules/libcom/src/osi/os/vxWorks/osdSock.h index 12bd8724e..8787eacbf 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdSock.h +++ b/modules/libcom/src/osi/os/vxWorks/osdSock.h @@ -90,6 +90,7 @@ typedef char osiSockOptMcastTTL_t; #define SOCK_SHUTDOWN ESHUTDOWN #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF +#define SOCK_EMSGSIZE EMSGSIZE #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7F000001 diff --git a/modules/libcom/src/osi/os/vxWorks/osdThread.c b/modules/libcom/src/osi/os/vxWorks/osdThread.c index b652b9720..0efb5cc45 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdThread.c +++ b/modules/libcom/src/osi/os/vxWorks/osdThread.c @@ -358,7 +358,8 @@ void epicsThreadResume(epicsThreadId id) void epicsThreadExitMain(void) { - errlogPrintf("epicsThreadExitMain was called for vxWorks. Why?\n"); + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); } unsigned int epicsThreadGetPriority(epicsThreadId id) diff --git a/modules/libcom/src/valgrind/valgrind.h b/modules/libcom/src/valgrind/valgrind.h old mode 100755 new mode 100644 diff --git a/modules/libcom/test/Makefile b/modules/libcom/test/Makefile old mode 100755 new mode 100644 index 556b8e329..0e50a1d74 --- a/modules/libcom/test/Makefile +++ b/modules/libcom/test/Makefile @@ -144,6 +144,11 @@ epicsThreadPoolTest_SRCS += epicsThreadPoolTest.c testHarness_SRCS += epicsThreadPoolTest.c TESTS += epicsThreadPoolTest +TESTPROD_HOST += initHookTest +initHookTest_SRCS += initHookTest.c +testHarness_SRCS += initHookTest.c +TESTS += initHookTest + TESTPROD_HOST += epicsExitTest epicsExitTest_SRCS += epicsExitTest.c testHarness_SRCS += epicsExitTest.c diff --git a/modules/libcom/test/epicsRunLibComTests.c b/modules/libcom/test/epicsRunLibComTests.c index d469fcf83..54c46a68e 100644 --- a/modules/libcom/test/epicsRunLibComTests.c +++ b/modules/libcom/test/epicsRunLibComTests.c @@ -50,6 +50,7 @@ int epicsTimeZoneTest(void); #endif int epicsTypesTest(void); int epicsInlineTest(void); +int initHookTest(void); int ipAddrToAsciiTest(void); int macDefExpandTest(void); int macLibTest(void); @@ -105,6 +106,7 @@ void epicsRunLibComTests(void) runTest(epicsTimeZoneTest); #endif runTest(epicsTypesTest); + runTest(initHookTest); runTest(ipAddrToAsciiTest); runTest(macDefExpandTest); runTest(macLibTest); diff --git a/modules/libcom/test/initHookTest.c b/modules/libcom/test/initHookTest.c new file mode 100644 index 000000000..688fea37b --- /dev/null +++ b/modules/libcom/test/initHookTest.c @@ -0,0 +1,30 @@ +/*************************************************************************\ +* Copyright (c) 2021 Michael Davidsaver +* SPDX-License-Identifier: EPICS +* 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 + +static +void testHookNames(void) +{ + const char* s; + + s = initHookName(initHookAtEnd); + testOk(strcmp(s, "initHookAtEnd")==0, "'%s' == 'initHookAtEnd'", s); +} + +MAIN(initHookTest) +{ + testPlan(1); + testHookNames(); + return testDone(); +} diff --git a/modules/libcom/test/osiSockTest.c b/modules/libcom/test/osiSockTest.c index f2adb41cd..284f828dc 100644 --- a/modules/libcom/test/osiSockTest.c +++ b/modules/libcom/test/osiSockTest.c @@ -243,6 +243,9 @@ void udpSockFanoutTestRx(void* raw) buf.bytes[sizeof(buf.bytes)-1] = '\0'; if(n<0) { + if(SOCKERRNO==SOCK_EMSGSIZE || SOCKERRNO==SOCK_EINTR) + continue; + testDiag("recvfrom error (%d)", (int)SOCKERRNO); break; } else if((n==sizeof(buf.bytes)) && buf.msg.cmd==htons(6) && buf.msg.size==htons(16) diff --git a/modules/normativeTypes b/modules/normativeTypes index 7a2d264f2..1250a3c23 160000 --- a/modules/normativeTypes +++ b/modules/normativeTypes @@ -1 +1 @@ -Subproject commit 7a2d264f2cb107bfd10adb23bc2b73d8323a79e4 +Subproject commit 1250a3c236f0aa92e0b5bd73647fd71d8a09360d diff --git a/modules/pvAccess b/modules/pvAccess index f72c7e653..3e6e6ae74 160000 --- a/modules/pvAccess +++ b/modules/pvAccess @@ -1 +1 @@ -Subproject commit f72c7e653c607f95daa818d14dfc928d59cfe8ff +Subproject commit 3e6e6ae74bf9e21cf36dcbd2165888560d35d82b diff --git a/modules/pvData b/modules/pvData index d3b4976ea..b1c830387 160000 --- a/modules/pvData +++ b/modules/pvData @@ -1 +1 @@ -Subproject commit d3b4976ea2b0d78075511f14d7f7bf9620dd4d14 +Subproject commit b1c8303870a04f1c3ee5a01a84aad2b2596e918c diff --git a/modules/pvDatabase b/modules/pvDatabase index a514ab7b5..8cac3975c 160000 --- a/modules/pvDatabase +++ b/modules/pvDatabase @@ -1 +1 @@ -Subproject commit a514ab7b51db108336dc234cb774af2603e51696 +Subproject commit 8cac3975cce67828a19e600fee85dd28df52fe2c diff --git a/modules/pva2pva b/modules/pva2pva index ff2253812..466d41ebb 160000 --- a/modules/pva2pva +++ b/modules/pva2pva @@ -1 +1 @@ -Subproject commit ff225381291419034a14a92fc14e591d8c5d9212 +Subproject commit 466d41ebb95a163133e07150d7841c03abfebf58 diff --git a/modules/pvaClient b/modules/pvaClient index 6eb977ae6..a34876e36 160000 --- a/modules/pvaClient +++ b/modules/pvaClient @@ -1 +1 @@ -Subproject commit 6eb977ae6617c888561ad620f2bff76a133e5f57 +Subproject commit a34876e36a56c9de9b172d6a83a9439bb330783d diff --git a/src/template/base/makeBaseApp.pl b/src/template/base/makeBaseApp.pl index e2df38dd6..f5b36d250 100644 --- a/src/template/base/makeBaseApp.pl +++ b/src/template/base/makeBaseApp.pl @@ -168,7 +168,7 @@ sub get_commandline_opts { #no args Cleanup(0) if $opt_h; # Locate epics_base - my ($command) = UnixPath($0); + my ($command) = UnixPath(AbsPath($0)); if ($opt_b) { # first choice is -b base $epics_base = UnixPath($opt_b); } elsif ($release{"EPICS_BASE"}) { # second choice is configure/RELEASE diff --git a/src/template/base/top/configure/CONFIG b/src/template/base/top/configure/CONFIG index c1a470322..34ace5775 100644 --- a/src/template/base/top/configure/CONFIG +++ b/src/template/base/top/configure/CONFIG @@ -8,9 +8,19 @@ RULES = $(EPICS_BASE) # RELEASE files point to other application tops include $(TOP)/configure/RELEASE -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common + ifdef T_A --include $(TOP)/configure/RELEASE.Common.$(T_A) --include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) + -include $(TOP)/configure/RELEASE.Common.$(T_A) + -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) +endif + +# Check EPICS_BASE is set properly +ifneq (file,$(origin EPICS_BASE)) + $(error EPICS_BASE must be set in a configure/RELEASE file) +else + ifeq ($(wildcard $(EPICS_BASE)/configure/CONFIG_BASE),) + $(error EPICS_BASE does not point to an EPICS installation) + endif endif CONFIG = $(RULES)/configure @@ -19,11 +29,17 @@ include $(CONFIG)/CONFIG # Override the Base definition: INSTALL_LOCATION = $(TOP) -# CONFIG_SITE files contain other build configuration settings +# CONFIG_SITE files contain local build configuration settings include $(TOP)/configure/CONFIG_SITE + +# Host-arch specific settings -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common + ifdef T_A + # Target-arch specific settings -include $(TOP)/configure/CONFIG_SITE.Common.$(T_A) + + # Host & target specific settings -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) endif diff --git a/src/template/ext/top/configure/CONFIG b/src/template/ext/top/configure/CONFIG index 321f6cea2..0c239bf18 100644 --- a/src/template/ext/top/configure/CONFIG +++ b/src/template/ext/top/configure/CONFIG @@ -1,13 +1,11 @@ # CONFIG - Load build configuration data # -# Do not make changes in this file, any site-specific -# overrides should be given in a CONFIG_SITE file. +# Do not make changes to this file! -# Where the build rules come from +# Allow user to override where the build rules come from RULES = $(EPICS_BASE) -INSTALL_IDLFILE = $(INSTALL) - +# RELEASE files point to other application tops include $(TOP)/configure/RELEASE -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH) -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common @@ -17,27 +15,38 @@ ifdef T_A -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) endif +# Check EPICS_BASE is set properly +ifneq (file,$(origin EPICS_BASE)) + $(error EPICS_BASE must be set in a configure/RELEASE file) +else + ifeq ($(wildcard $(EPICS_BASE)/configure/CONFIG_BASE),) + $(error EPICS_BASE does not point to an EPICS installation) + endif +endif + CONFIG = $(RULES)/configure include $(CONFIG)/CONFIG -# Override some Base definitions +# Override the Base definition: INSTALL_LOCATION = $(TOP) -# CONFIG_SITE files contain build configuration overrides +# CONFIG_SITE files contain local build configuration settings include $(TOP)/configure/CONFIG_SITE -# Host-arch specific settings +# Host-arch specific settings for extensions are in configure/os -include $(TOP)/configure/os/CONFIG_SITE.$(EPICS_HOST_ARCH).Common +ifdef T_A + # Target-arch specific settings for extensions are in configure/os + -include $(TOP)/configure/os/CONFIG_SITE.Common.$(T_A) + + # Host & target specific settings for extensions are in configure/os + -include $(TOP)/configure/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) +endif + +# Additional settings for extensions +INSTALL_IDLFILE = $(INSTALL) + ifdef INSTALL_LOCATION_EXTENSIONS INSTALL_LOCATION = $(INSTALL_LOCATION_EXTENSIONS) endif - -ifdef T_A - # Target-arch specific settings - -include $(TOP)/configure/os/CONFIG_SITE.Common.$(T_A) - - # Host & target specific combination settings - -include $(TOP)/configure/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) -endif - diff --git a/src/template/ext/top/configure/os/CONFIG.linux-x86.linux-386 b/src/template/ext/top/configure/os/CONFIG.linux-x86.linux-386 deleted file mode 100644 index ed73b3464..000000000 --- a/src/template/ext/top/configure/os/CONFIG.linux-x86.linux-386 +++ /dev/null @@ -1,2 +0,0 @@ - -include $(TOP)/configure/os/CONFIG_SITE.linux-x86.linux-x86 diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.Common.Common b/src/template/ext/top/configure/os/CONFIG_SITE.Common.Common deleted file mode 100644 index 21363a633..000000000 --- a/src/template/ext/top/configure/os/CONFIG_SITE.Common.Common +++ /dev/null @@ -1,10 +0,0 @@ -# -# Site Specific Configuration Information -# Only the local epics system manager should modify this file - -# java jdk definitions -#CLASSPATH += -classpath .:..:$(INSTALL_JAVA):$(JAVA_DIR)/bin/../classes:$(JAVA_DIR)/bin/../lib/classes.zip -#JAVACCMD = $(subst \,/,$(JAVA_DIR)/bin/javac$(EXE) $(CLASSPATH) $(JAVAC_FLAGS) ) -#JAVAHCMD = $(subst \,/,$(JAVA_DIR)/bin/javah$(EXE) -jni $(CLASSPATH) $(JAVAH_FLAGS)) -#JARCMD = $(subst \,/,$(JAVA_DIR)/bin/jar$(EXE) $(JAR_OPTIONS) $(MANIFEST) $(JAR) $(JAR_INPUT)) - diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.aix-ppc-gnu.aix-ppc-gnu b/src/template/ext/top/configure/os/CONFIG_SITE.aix-ppc-gnu.aix-ppc-gnu deleted file mode 100644 index 19d65aead..000000000 --- a/src/template/ext/top/configure/os/CONFIG_SITE.aix-ppc-gnu.aix-ppc-gnu +++ /dev/null @@ -1,11 +0,0 @@ -# -# Site Specific Configuration Information -# Only the local epics system manager should modify this file - -# Where to find utilities/libraries -# If you do not have a certain product, -# leave the line empty. -# - --include $(TOP)/configure/os/CONFIG_SITE.aix-ppc.aix-ppc - diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.aix-ppc.aix-ppc b/src/template/ext/top/configure/os/CONFIG_SITE.aix-ppc.aix-ppc deleted file mode 100644 index 3f40e0b37..000000000 --- a/src/template/ext/top/configure/os/CONFIG_SITE.aix-ppc.aix-ppc +++ /dev/null @@ -1,77 +0,0 @@ -# -# Site Specific Configuration Information -# Only the local epics system manager should modify this file - -# Where to find utilities/libraries -# If you do not have a certain product, -# leave the line empty. -# - --include $(TOP)/configure/os/CONFIG_SITE.Common.Common - -# sun X11 -X11_LIB = /usr/openwin/lib -X11_INC = /usr/openwin/include -# mit X11 -#X11_LIB = /opt/X11R5/lib -#X11_INC = /opt/X11R5/include -# osf motif -#MOTIF_INC = /opt/local/Motif2.0/include -#MOTIF_LIB = /opt/local/Motif2.0/lib -# sun SDK motif -#MOTIF_INC = /opt/SUNWmotif/include -#MOTIF_LIB = /opt/SUNWmotif/lib -# sun 5.4,5.6 SDK motif -MOTIF_INC = /usr/dt/include -MOTIF_LIB = /usr/dt/lib -OPENWIN = /usr/openwin - -INTERVIEWS_BIN=/usr/local/interviews/bin/O.solaris -INTERVIEWS_LIB=/usr/local/interviews/lib/O.solaris -IV_INC=/usr/local/interviews/include -IV-2_6_INC=/usr/local/interviews/include/IV-2_6 -IV_BIN=/usr/local/interviews/bin/O.solaris -IV_LIB=/usr/local/interviews/lib/O.solaris - -WINGZ_INC = /opt/local/Wingz2/incl -WINGZ_LIB = /opt/local/Wingz2/lib -#MATHEMATICA = /usr/local/math -# Define XRTGRAPH_EXTENSIONS = YES only if using XRT/graph 3.x -# and you want the extensions for MEDM -XRTGRAPH_EXTENSIONS = YES -XRTGRAPH = /opt/local/xrtgraph -QUESTWIN = /usr/local/questwin - -TK_LIB = /opt/local/lib -TK_INC = /opt/local/include -TCL_LIB = /opt/local/lib -TCL_INC = /opt/local/include -DP_LIB = /opt/local/lib -DP_INC = /opt/local/include -BLT_LIB = /opt/local/lib -BLT_INC = /opt/local/include - -IDL = /usr/local/idl -# IDL=$(IDL)/external/rpc is the sun4 version -IDLRPC = $(IDL)/external/rpc.solaris - -ZLIB_PREFIX = /usr/local/oag -ZLIB = $(notdir $(wildcard $(ZLIB_PREFIX)/lib/libz.a)) -ifeq ($(ZLIB) , libz.a) -ZLIB_LIB = $(ZLIB_PREFIX)/lib -ZLIB_INC = -I$(ZLIB_PREFIX)/include -ZLIB_CFLAG = -DzLib -ZLIB_PROD_LIB = z -z_DIR=$(ZLIB_PREFIX)/lib -else -ZLIB_LIB = -ZLIB_INC = -ZLIB_CFLAG = -ZLIB_PROD_LIB = -z_DIR= -endif - -PYTHON_DIR=/opt/local/lib/python2.2 -PYTHON_INCLUDE=/opt/local/include/python2.2 - -JAVA_DIR=/usr/java diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 b/src/template/ext/top/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 index f1745159b..9dd907a24 100644 --- a/src/template/ext/top/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 +++ b/src/template/ext/top/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 @@ -7,7 +7,6 @@ # leave the line empty. # --include $(TOP)/configure/os/CONFIG_SITE.Common.Common -include $(TOP)/configure/os/CONFIG_SITE.win32-x86.win32-x86 # ---------- java definitions diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.darwin-x86.darwin-x86 b/src/template/ext/top/configure/os/CONFIG_SITE.darwin-x86.darwin-x86 index 9e98c70ef..74f12920b 100644 --- a/src/template/ext/top/configure/os/CONFIG_SITE.darwin-x86.darwin-x86 +++ b/src/template/ext/top/configure/os/CONFIG_SITE.darwin-x86.darwin-x86 @@ -7,8 +7,6 @@ # leave the line empty. # --include $(TOP)/configure/os/CONFIG_SITE.Common.Common - PYTHON_DIR=/usr/lib/python2.2 PYTHON_INCLUDE=/System/Library/Frameworks/Python.framework/Versions/2.3/include/python2.3 diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.linux-x86.linux-athlon b/src/template/ext/top/configure/os/CONFIG_SITE.linux-x86.linux-athlon deleted file mode 100644 index 25036ccac..000000000 --- a/src/template/ext/top/configure/os/CONFIG_SITE.linux-x86.linux-athlon +++ /dev/null @@ -1,11 +0,0 @@ -# -# Site Specific Configuration Information -# Only the local epics system manager should modify this file - -# Where to find utilities/libraries -# If you do not have a certain product, -# leave the line empty. -# - - --include $(TOP)/configure/os/CONFIG_SITE.linux-x86.linux-x86 diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.linux-x86.linux-x86 b/src/template/ext/top/configure/os/CONFIG_SITE.linux-x86.linux-x86 index 8641a9d27..e74accbf0 100644 --- a/src/template/ext/top/configure/os/CONFIG_SITE.linux-x86.linux-x86 +++ b/src/template/ext/top/configure/os/CONFIG_SITE.linux-x86.linux-x86 @@ -7,8 +7,6 @@ # leave the line empty. # --include $(TOP)/configure/os/CONFIG_SITE.Common.Common - #X11_LIB=/usr/X11R6/lib #X11_INC=/usr/X11R6/include #MOTIF_LIB=/usr/X11R6/lib diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.solaris-sparc.solaris-sparc b/src/template/ext/top/configure/os/CONFIG_SITE.solaris-sparc.solaris-sparc index bd113bea3..db0622864 100644 --- a/src/template/ext/top/configure/os/CONFIG_SITE.solaris-sparc.solaris-sparc +++ b/src/template/ext/top/configure/os/CONFIG_SITE.solaris-sparc.solaris-sparc @@ -7,8 +7,6 @@ # leave the line empty. # --include $(TOP)/configure/os/CONFIG_SITE.Common.Common - # sun X11 X11_LIB = /usr/openwin/lib X11_INC = /usr/openwin/include diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.win32-x86-cygwin.win32-x86-cygwin b/src/template/ext/top/configure/os/CONFIG_SITE.win32-x86-cygwin.win32-x86-cygwin deleted file mode 100644 index f6ca56942..000000000 --- a/src/template/ext/top/configure/os/CONFIG_SITE.win32-x86-cygwin.win32-x86-cygwin +++ /dev/null @@ -1,11 +0,0 @@ -# -# Site Specific Configuration Information -# Only the local epics system manager should modify this file - -# Where to find utilities/libraries -# If you do not have a certain product, -# leave the line empty. -# - --include $(TOP)/configure/os/CONFIG_SITE.cygwin-x86.cygwin-x86 - diff --git a/src/template/ext/top/configure/os/CONFIG_SITE.win32-x86.win32-x86 b/src/template/ext/top/configure/os/CONFIG_SITE.win32-x86.win32-x86 index 8118893a7..f2614098b 100644 --- a/src/template/ext/top/configure/os/CONFIG_SITE.win32-x86.win32-x86 +++ b/src/template/ext/top/configure/os/CONFIG_SITE.win32-x86.win32-x86 @@ -9,8 +9,6 @@ # leave the line empty. # --include $(TOP)/configure/os/CONFIG_SITE.Common.Common - # If objects were compiled with different default runtime libraries # (not a good idea), specify which one you want to use in the product # by making it the default and the others nodefault. Use diff --git a/src/tools/EpicsHostArch.pl b/src/tools/EpicsHostArch.pl index 67e29c77e..abff49007 100644 --- a/src/tools/EpicsHostArch.pl +++ b/src/tools/EpicsHostArch.pl @@ -47,9 +47,8 @@ sub HostArch { my ($kernel, $hostname, $release, $version, $cpu) = uname; if (m/^darwin/) { for ($cpu) { - return 'darwin-x86' if m/^(i386|x86_64)/; - return 'darwin-ppc' if m/Power Macintosh/; - return 'darwin-aarch64' if m/arm64/; + return 'darwin-x86' if m/^x86_64/; + return 'darwin-aarch64' if m/^arm64/; } die "$0: macOS CPU type '$cpu' not recognized\n"; } diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl index 3375eb4f2..b8c596edb 100644 --- a/src/tools/convertRelease.pl +++ b/src/tools/convertRelease.pl @@ -227,6 +227,12 @@ sub envPaths { # Check RELEASE file consistency with support modules # sub checkRelease { + die "\nEPICS_BASE must be set in a configure/RELEASE file.\n\n" + unless grep(m/^(EPICS_BASE)$/, @apps) && + exists $macros{EPICS_BASE} && + $macros{EPICS_BASE} ne '' && + -f "$macros{EPICS_BASE}/configure/CONFIG_BASE"; + my $status = 0; delete $macros{RULES}; delete $macros{TOP}; diff --git a/src/tools/makeTestfile.pl b/src/tools/makeTestfile.pl index 455bd7f69..9bfb46f4f 100644 --- a/src/tools/makeTestfile.pl +++ b/src/tools/makeTestfile.pl @@ -6,7 +6,7 @@ # Operator of Los Alamos National Laboratory. # SPDX-License-Identifier: EPICS # EPICS BASE is distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. +# in file LICENSE that is included with this distribution. #************************************************************************* # The makeTestfile.pl script generates a file $target.t which is needed @@ -36,29 +36,37 @@ my $tool = basename($0); my $timeout = $ENV{EPICS_UNITTEST_TIMEOUT} // 500; # 8 min 20 sec my ($TA, $HA, $target, $exe) = @ARGV; -my $exec; +my ($exec, $error); -# 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 "$tool: I don't know how to create scripts for testing $TA on $HA\n"; - -} else { - $exec = "./$exe"; +if ($TA =~ /^win32-x86/ && $HA !~ /^win/) { + # Use WINE to run win32-x86 executables on non-windows hosts. + # New Debian derivatives have wine32 and wine64, older ones have + # wine and wine64. We prefer wine32 if present. + my $wine32 = "/usr/bin/wine32"; + $wine32 = "/usr/bin/wine" if ! -x $wine32; + $error = $exec = "$wine32 $exe"; +} +elsif ($TA =~ /^windows-x64/ && $HA !~ /^win/) { + # Use WINE to run windows-x64 executables on non-windows hosts. + $error = $exec = "wine64 $exe"; +} +elsif ($TA =~ /^RTEMS-pc[36]86-qemu$/) { + # Run the pc386 and pc686 test harness w/ QEMU + $exec = "qemu-system-i386 -m 64 -no-reboot " + . "-serial stdio -display none " + . "-net nic,model=e1000 -net nic,model=ne2k_pci " + . "-net user,restrict=yes " + . "-append --console=/dev/com1 " + . "-kernel $exe"; + $error = "qemu-system-i386 ... -kernel $exe"; +} +elsif ($TA =~ /^RTEMS-/) { + # Explicitly fail for other RTEMS targets + die "$tool: I don't know how to create scripts for testing $TA on $HA\n"; +} +else { + # Assume it's directly executable on other targets + $error = $exec = "./$exe"; } # Create the $target.t file @@ -114,12 +122,12 @@ my \$proc; if (! Win32::Process::Create(\$proc, abs_path('$exec'), '$exec', 1, NORMAL_PRIORITY_CLASS, '.')) { my \$err = Win32::FormatMessage(Win32::GetLastError()); - die "\$tool: Can't create Process for '$exec': \$err\\n"; + die "\$tool: Can't create Process for '$error': \$err\\n"; } if (! \$proc->Wait(1000 * \$timeout)) { \$proc->Kill(1); print "\\n#### Test stopped by \$tool after \$timeout seconds\\n"; - die "\$tool: Timed out '$exec' after \$timeout seconds\\n"; + die "\$tool: Timed out '$error' after \$timeout seconds\\n"; } my \$status; \$proc->GetExitCode(\$status); @@ -132,7 +140,7 @@ else { print $OUT <<__UNIX__; my \$pid = fork(); -die "\$tool: Can't fork for '$exec': \$!\\n" +die "\$tool: Can't fork for '$error': \$!\\n" unless defined \$pid; if (\$pid) { @@ -141,7 +149,7 @@ if (\$pid) { # Time's up, kill the child kill 9, \$pid; print "\\n#### Test stopped by \$tool after \$timeout seconds\\n"; - die "\$tool: Timed out '$exec' after \$timeout seconds\\n"; + die "\$tool: Timed out '$error' after \$timeout seconds\\n"; }; alarm \$timeout; @@ -152,7 +160,7 @@ if (\$pid) { else { # Child process exec '$exec' - or die "\$tool: Can't run '$exec': \$!\\n"; + or die "\$tool: Can't run '$error': \$!\\n"; } __UNIX__ } diff --git a/startup/win32.bat b/startup/win32.bat index dc50e6a72..818912547 100755 --- a/startup/win32.bat +++ b/startup/win32.bat @@ -1,106 +1,106 @@ -@echo off -rem ************************************************************************* -rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne -rem National Laboratory. -rem Copyright (c) 2002 The Regents of the University of California, as -rem Operator of Los Alamos National Laboratory. -rem SPDX-License-Identifier: EPICS -rem EPICS BASE is distributed subject to a Software License Agreement found -rem in file LICENSE that is included with this distribution. -rem ************************************************************************* -rem -rem Site-specific EPICS environment settings -rem -rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. -rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the -rem EPICS Base install host architecture bin directory to PATH. -rem - -rem ---------------------------------------------------------------------- -rem Site serviceable parts (These definitions may be modified) -rem ---------------------------------------------------------------------- - -rem The values of the definitions in this section must not contain -rem double-quotes. -rem -rem * Right: set _foo=C:\foo -rem * Right: set "_foo=C:\foo" -rem * Wrong: set _foo="C:\foo" - -rem Automatically set up the environment when possible ("yes" or "no"). -rem If set to yes, as much of the environment will be set up as possible. -rem If set to no, just the minimum environment will be set up. More -rem specific _auto_* definitions take precedence over this definition. -set _auto=no - -rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will -rem be reset to the value of _path_new. If set to no, PATH will not be -rem reset. -set _auto_path_reset=%_auto% - -rem Automatically append to PATH ("yes" or "no"). If set to yes, the -rem EPICS Base install host architecture bin directory will be added to -rem PATH if possible. If set to no, the bin directory will not be added -rem to PATH. -set _auto_path_append=%_auto% - -rem The new value for PATH. If _auto_path_reset is yes, PATH will be set -rem to it. -set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem - -rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl -rem is assumed to already be in PATH and will not be added. If nonempty, -rem Strawberry Perl will be added to PATH. -set _strawberry_perl_home=C:\Strawberry - -rem The location of Microsoft Visual Studio (pathname). -set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community - -rem The EPICS host architecture specification for EPICS_HOST_ARCH -rem (-[-] as defined in configure/CONFIG_SITE). -set _epics_host_arch=win32-x86 - -rem The install location of EPICS Base (pathname). If nonempty and -rem _auto_path_append is yes, it will be used to add the host architecture -rem bin directory to PATH. -set _epics_base= - -rem ---------------------------------------------------------------------- -rem Internal parts (There is typically no need to modify these) -rem ---------------------------------------------------------------------- - -rem Reset PATH -if "%_auto_path_reset%" == "yes" ( - set "PATH=%_path_new%" -) - -rem Add Strawberry Perl to PATH -if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl -rem Can't do this inside parentheses because PATH would be read only once -set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" -:after_add_strawberry_perl - -rem Set the environment for Microsoft Visual Studio -call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x86 - -rem Set the EPICS host architecture specification -set "EPICS_HOST_ARCH=%_epics_host_arch%" - -rem Add the EPICS Base host architecture bin directory to PATH -if "%_auto_path_append%" == "yes" ( - if not "%_epics_base%" == "" ( - set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" - ) -) - -rem Don't leak variables into the environment -set _auto= -set _auto_path_reset= -set _auto_path_append= -set _path_new= -set _strawberry_perl_home= -set _visual_studio_home= -set _epics_host_arch= -set _epics_base= +@echo off +rem ************************************************************************* +rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne +rem National Laboratory. +rem Copyright (c) 2002 The Regents of the University of California, as +rem Operator of Los Alamos National Laboratory. +rem SPDX-License-Identifier: EPICS +rem EPICS BASE is distributed subject to a Software License Agreement found +rem in file LICENSE that is included with this distribution. +rem ************************************************************************* +rem +rem Site-specific EPICS environment settings +rem +rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. +rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the +rem EPICS Base install host architecture bin directory to PATH. +rem + +rem ---------------------------------------------------------------------- +rem Site serviceable parts (These definitions may be modified) +rem ---------------------------------------------------------------------- + +rem The values of the definitions in this section must not contain +rem double-quotes. +rem +rem * Right: set _foo=C:\foo +rem * Right: set "_foo=C:\foo" +rem * Wrong: set _foo="C:\foo" + +rem Automatically set up the environment when possible ("yes" or "no"). +rem If set to yes, as much of the environment will be set up as possible. +rem If set to no, just the minimum environment will be set up. More +rem specific _auto_* definitions take precedence over this definition. +set _auto=no + +rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will +rem be reset to the value of _path_new. If set to no, PATH will not be +rem reset. +set _auto_path_reset=%_auto% + +rem Automatically append to PATH ("yes" or "no"). If set to yes, the +rem EPICS Base install host architecture bin directory will be added to +rem PATH if possible. If set to no, the bin directory will not be added +rem to PATH. +set _auto_path_append=%_auto% + +rem The new value for PATH. If _auto_path_reset is yes, PATH will be set +rem to it. +set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem + +rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl +rem is assumed to already be in PATH and will not be added. If nonempty, +rem Strawberry Perl will be added to PATH. +set _strawberry_perl_home=C:\Strawberry + +rem The location of Microsoft Visual Studio (pathname). +set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community + +rem The EPICS host architecture specification for EPICS_HOST_ARCH +rem (-[-] as defined in configure/CONFIG_SITE). +set _epics_host_arch=win32-x86 + +rem The install location of EPICS Base (pathname). If nonempty and +rem _auto_path_append is yes, it will be used to add the host architecture +rem bin directory to PATH. +set _epics_base= + +rem ---------------------------------------------------------------------- +rem Internal parts (There is typically no need to modify these) +rem ---------------------------------------------------------------------- + +rem Reset PATH +if "%_auto_path_reset%" == "yes" ( + set "PATH=%_path_new%" +) + +rem Add Strawberry Perl to PATH +if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl +rem Can't do this inside parentheses because PATH would be read only once +set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" +:after_add_strawberry_perl + +rem Set the environment for Microsoft Visual Studio +call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x86 + +rem Set the EPICS host architecture specification +set "EPICS_HOST_ARCH=%_epics_host_arch%" + +rem Add the EPICS Base host architecture bin directory to PATH +if "%_auto_path_append%" == "yes" ( + if not "%_epics_base%" == "" ( + set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" + ) +) + +rem Don't leak variables into the environment +set _auto= +set _auto_path_reset= +set _auto_path_append= +set _path_new= +set _strawberry_perl_home= +set _visual_studio_home= +set _epics_host_arch= +set _epics_base= diff --git a/startup/windows.bat b/startup/windows.bat index a36e43fdb..27b6dcc0b 100644 --- a/startup/windows.bat +++ b/startup/windows.bat @@ -1,106 +1,106 @@ -@echo off -rem ************************************************************************* -rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne -rem National Laboratory. -rem Copyright (c) 2002 The Regents of the University of California, as -rem Operator of Los Alamos National Laboratory. -rem SPDX-License-Identifier: EPICS -rem EPICS BASE is distributed subject to a Software License Agreement found -rem in file LICENSE that is included with this distribution. -rem ************************************************************************* -rem -rem Site-specific EPICS environment settings -rem -rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. -rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the -rem EPICS Base install host architecture bin directory to PATH. -rem - -rem ---------------------------------------------------------------------- -rem Site serviceable parts (These definitions may be modified) -rem ---------------------------------------------------------------------- - -rem The values of the definitions in this section must not contain -rem double-quotes. -rem -rem * Right: set _foo=C:\foo -rem * Right: set "_foo=C:\foo" -rem * Wrong: set _foo="C:\foo" - -rem Automatically set up the environment when possible ("yes" or "no"). -rem If set to yes, as much of the environment will be set up as possible. -rem If set to no, just the minimum environment will be set up. More -rem specific _auto_* definitions take precedence over this definition. -set _auto=no - -rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will -rem be reset to the value of _path_new. If set to no, PATH will not be -rem reset. -set _auto_path_reset=%_auto% - -rem Automatically append to PATH ("yes" or "no"). If set to yes, the -rem EPICS Base install host architecture bin directory will be added to -rem PATH if possible. If set to no, the bin directory will not be added -rem to PATH. -set _auto_path_append=%_auto% - -rem The new value for PATH. If _auto_path_reset is yes, PATH will be set -rem to it. -set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem - -rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl -rem is assumed to already be in PATH and will not be added. If nonempty, -rem Strawberry Perl will be added to PATH. -set _strawberry_perl_home=C:\Strawberry - -rem The location of Microsoft Visual Studio (pathname). -set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community - -rem The EPICS host architecture specification for EPICS_HOST_ARCH -rem (-[-] as defined in configure/CONFIG_SITE). -set _epics_host_arch=windows-x64 - -rem The install location of EPICS Base (pathname). If nonempty and -rem _auto_path_append is yes, it will be used to add the host architecture -rem bin directory to PATH. -set _epics_base= - -rem ---------------------------------------------------------------------- -rem Internal parts (There is typically no need to modify these) -rem ---------------------------------------------------------------------- - -rem Reset PATH -if "%_auto_path_reset%" == "yes" ( - set "PATH=%_path_new%" -) - -rem Add Strawberry Perl to PATH -if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl -rem Can't do this inside parentheses because PATH would be read only once -set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" -:after_add_strawberry_perl - -rem Set the environment for Microsoft Visual Studio -call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x64 - -rem Set the EPICS host architecture specification -set "EPICS_HOST_ARCH=%_epics_host_arch%" - -rem Add the EPICS Base host architecture bin directory to PATH -if "%_auto_path_append%" == "yes" ( - if not "%_epics_base%" == "" ( - set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" - ) -) - -rem Don't leak variables into the environment -set _auto= -set _auto_path_reset= -set _auto_path_append= -set _path_new= -set _strawberry_perl_home= -set _visual_studio_home= -set _epics_host_arch= -set _epics_base= +@echo off +rem ************************************************************************* +rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne +rem National Laboratory. +rem Copyright (c) 2002 The Regents of the University of California, as +rem Operator of Los Alamos National Laboratory. +rem SPDX-License-Identifier: EPICS +rem EPICS BASE is distributed subject to a Software License Agreement found +rem in file LICENSE that is included with this distribution. +rem ************************************************************************* +rem +rem Site-specific EPICS environment settings +rem +rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. +rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the +rem EPICS Base install host architecture bin directory to PATH. +rem + +rem ---------------------------------------------------------------------- +rem Site serviceable parts (These definitions may be modified) +rem ---------------------------------------------------------------------- + +rem The values of the definitions in this section must not contain +rem double-quotes. +rem +rem * Right: set _foo=C:\foo +rem * Right: set "_foo=C:\foo" +rem * Wrong: set _foo="C:\foo" + +rem Automatically set up the environment when possible ("yes" or "no"). +rem If set to yes, as much of the environment will be set up as possible. +rem If set to no, just the minimum environment will be set up. More +rem specific _auto_* definitions take precedence over this definition. +set _auto=no + +rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will +rem be reset to the value of _path_new. If set to no, PATH will not be +rem reset. +set _auto_path_reset=%_auto% + +rem Automatically append to PATH ("yes" or "no"). If set to yes, the +rem EPICS Base install host architecture bin directory will be added to +rem PATH if possible. If set to no, the bin directory will not be added +rem to PATH. +set _auto_path_append=%_auto% + +rem The new value for PATH. If _auto_path_reset is yes, PATH will be set +rem to it. +set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem + +rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl +rem is assumed to already be in PATH and will not be added. If nonempty, +rem Strawberry Perl will be added to PATH. +set _strawberry_perl_home=C:\Strawberry + +rem The location of Microsoft Visual Studio (pathname). +set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community + +rem The EPICS host architecture specification for EPICS_HOST_ARCH +rem (-[-] as defined in configure/CONFIG_SITE). +set _epics_host_arch=windows-x64 + +rem The install location of EPICS Base (pathname). If nonempty and +rem _auto_path_append is yes, it will be used to add the host architecture +rem bin directory to PATH. +set _epics_base= + +rem ---------------------------------------------------------------------- +rem Internal parts (There is typically no need to modify these) +rem ---------------------------------------------------------------------- + +rem Reset PATH +if "%_auto_path_reset%" == "yes" ( + set "PATH=%_path_new%" +) + +rem Add Strawberry Perl to PATH +if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl +rem Can't do this inside parentheses because PATH would be read only once +set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" +:after_add_strawberry_perl + +rem Set the environment for Microsoft Visual Studio +call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x64 + +rem Set the EPICS host architecture specification +set "EPICS_HOST_ARCH=%_epics_host_arch%" + +rem Add the EPICS Base host architecture bin directory to PATH +if "%_auto_path_append%" == "yes" ( + if not "%_epics_base%" == "" ( + set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" + ) +) + +rem Don't leak variables into the environment +set _auto= +set _auto_path_reset= +set _auto_path_append= +set _path_new= +set _strawberry_perl_home= +set _visual_studio_home= +set _epics_host_arch= +set _epics_base=