From b011c286aae1fddfcb3613c222a45da05926045f Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 30 Jul 2018 16:47:17 +0200 Subject: [PATCH] add streamReinit function --- GNUmakefile | 9 ++++-- documentation/processing.html | 51 ++++++++++++++++++++++------------ documentation/protocol.html | 9 +----- src/AsynDriverInterface.cc | 52 +++++++++++++++++++++++++++++++++++ src/Makefile | 3 ++ 5 files changed, 96 insertions(+), 28 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index f829db0..43aedfb 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -9,10 +9,10 @@ BUILDCLASSES += Linux DOCUDIR = documentation -ifdef EPICSVERSION -ifndef RECORDTYPES PCRE=1 ASYN=1 +ifdef EPICSVERSION +ifndef RECORDTYPES include src/CONFIG_STREAM export RECORDTYPES BUSSES FORMATS endif @@ -44,5 +44,10 @@ export DBDFILES = streamSup.dbd streamSup.dbd: @echo Creating $@ from $(RECORDTYPES) $(PERL) ../src/makedbd.pl $(RECORDTYPES) > $@ +ifdef BASE_3_14 +ifdef ASYN + echo "registrar(AsynDriverInterfaceRegistrar)" >> $@ +endif +endif endif diff --git a/documentation/processing.html b/documentation/processing.html index 73362ba..5c27473 100644 --- a/documentation/processing.html +++ b/documentation/processing.html @@ -54,9 +54,9 @@ its SEVR field set to INVALID and its
TIMEOUT
- The device could not be locked (LockTimeout) or the - device did not reply in time - (ReplyTimeout). + The device could not be locked (LockTimeout) because + other records are keeping the device busy or the device did not reply + in time (ReplyTimeout).
WRITE
@@ -96,13 +96,14 @@ will be set according to the original error.

2. Initialization

-Often, it is required to initialize records from the hardware after +Often, it is useful to initialize records from the hardware after booting the IOC, especially output records. For this purpose, initialization is formally handled as an exception. The @init handler is called as part of the initRecord() function during iocInit -before any scan task starts. +before any scan task starts and may be re-run +later under circumstances listed below.

In contrast to normal processing, the protocol @@ -120,7 +121,7 @@ If the handler fails, the record remains uninitialized: The @init handler has nothing to do with the PINI field. The handler does not process the record nor does it trigger -forward links or other PP links. +forward links or any links with the PP flag. It runs before PINI is handled. If the record has PINI=YES, the PINI processing is a normal processing after the @@ -147,19 +148,33 @@ read from a constant INP or DOL field, or restored from a bump-less reboot system (e.g. autosave from the synApps package).

-

-The @init handler is called again in the following situations: +

+ The @init handler is called in the following situations: +

    +
  • At startup by iocInit during record initialization + as described above. +
  • When the IOC is resumed with iocRun (after + beeing paused with iocPause) before the scan tasks + restart and before records with PINI=RUN are processed. +
  • When the protocol is + reloaded for example with + streamReload ["recordname"]. +
  • When StreamDevice detects that the device has + reconnected (after being disconnected). This includes the case that + the device was disconnected when the IOC started. + Be aware that some drivers test the connection only periodically, + e.g. the asynIPPort driver tests it every few seconds. + Thus there may be a small delay between the device being online + and the record re-initializing. +
  • When streamReinit + "asynPortname"[,addr] is called + (if using an asynDriver port). +
  • When the "magic value" 2 is written to the + .PROC field of the record. + In this case the record is processed and thus its FLNK + and links with the PP flag are triggered. +

-
    -
  • The device driver informs StreamDevice that the device has -reconnected after it had been disconnected. This is only detectable for -some types of busses. -
  • The IOC is resumed with iocRun after it had -been paused with iocPause. This requires EPICS 3.14.11 or higher. -
  • The record protocol has been reloaded -using the shell function streamReload or the subroutine -record funtion streamReloadSub. -

3. I/O Intr

diff --git a/documentation/protocol.html b/documentation/protocol.html index 4a73ed7..b5e24e0 100644 --- a/documentation/protocol.html +++ b/documentation/protocol.html @@ -558,15 +558,8 @@ There is a fixed set of exception handler names starting with Not really an exception but formally specified in the same syntax. This handler can be used to initialize an output record with a value read from the device. - Also see chapter Record Processing. + See also chapter Record Processing. - It is called at startup by iocInit during record - initialization and again whenever StreamDevice - detects that the device has reconnected after a disconnect or when the - IOC is resumed with iocRun after beeing paused or - when the protocol has been reloaded - or when the "magic value" 2 is written to the .PROC - field.

Example:

diff --git a/src/AsynDriverInterface.cc b/src/AsynDriverInterface.cc index 1b1b325..87523c5 100644 --- a/src/AsynDriverInterface.cc +++ b/src/AsynDriverInterface.cc @@ -32,6 +32,8 @@ extern "C" { #include "epicsAssert.h" #include "epicsTime.h" #include "epicsTimer.h" +#include "epicsStdioRedirect.h" +#include "iocsh.h" #endif #include "asynDriver.h" @@ -1558,3 +1560,53 @@ handleTimeout() clientName(), toStr(ioAction)); } } + +extern "C" long streamReinit(const char* portname, int addr) +{ + if (!portname) + { + fprintf(stderr, "Usage: streamReinit \"portname\", [addr]\n"); + return -1; + } + asynUser* pasynUser = pasynManager->createAsynUser(NULL, NULL); + if (!pasynUser) + { + fprintf(stderr, "Can't create asynUser\n"); + return -1; + } + asynStatus status = pasynManager->connectDevice(pasynUser, portname, addr); + if (status == asynSuccess) + status = pasynManager->exceptionDisconnect(pasynUser); + if (status == asynSuccess) + status = pasynManager->exceptionConnect(pasynUser); + if (status != asynSuccess) + fprintf(stderr, "%s\n", pasynUser->errorMessage); + pasynManager->disconnect(pasynUser); + pasynManager->freeAsynUser(pasynUser); + return status; +} + +#ifndef EPICS_3_13 +static const iocshArg streamReinitArg0 = + { "portname", iocshArgString }; +static const iocshArg streamReinitArg1 = + { "[addr]", iocshArgInt }; +static const iocshArg * const streamReinitArgs[] = + { &streamReinitArg0, &streamReinitArg1 }; +static const iocshFuncDef streamReinitDef = + { "streamReinit", 2, streamReinitArgs }; + +void streamReinitFunc(const iocshArgBuf *args) +{ + streamReinit(args[0].sval, args[1].ival); +} +static void AsynDriverInterfaceRegistrar () +{ + iocshRegister(&streamReinitDef, streamReinitFunc); +} + +extern "C" { +epicsExportRegistrar(AsynDriverInterfaceRegistrar); +} + +#endif diff --git a/src/Makefile b/src/Makefile index 00e6b59..3d59f95 100644 --- a/src/Makefile +++ b/src/Makefile @@ -87,6 +87,9 @@ streamReferences: ../CONFIG_STREAM # create stream.dbd from all RECORDTYPES $(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../CONFIG_STREAM $(PERL) ../makedbd.pl $(RECORDTYPES) > $@ +ifdef ASYN + echo "registrar(AsynDriverInterfaceRegistrar)" >> $@ +endif $(LIBRARY_DEFAULT).dbd$(DEP): ../CONFIG_STREAM echo $(LIBRARY_DEFAULT).dbd: $< > $@