add streamReinit function

This commit is contained in:
2018-07-30 16:47:17 +02:00
parent fb58a80b0c
commit b011c286aa
5 changed files with 96 additions and 28 deletions

View File

@ -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

View File

@ -54,9 +54,9 @@ its <code>SEVR</code> field set to <code>INVALID</code> and its
<dl>
<dt><code>TIMEOUT</code></dt>
<dd>
The device could not be locked (<code>LockTimeout</code>) or the
device did not reply in time
(<a href="protocol.html#sysvar"><code>ReplyTimeout</code></a>).
The device could not be locked (<code>LockTimeout</code>) because
other records are keeping the device busy or the device did not reply
in time (<a href="protocol.html#sysvar"><code>ReplyTimeout</code></a>).
</dd>
<dt><code>WRITE</code></dt>
<dd>
@ -96,13 +96,14 @@ will be set according to the original error.
<a name="init"></a>
<h2>2. Initialization</h2>
<p>
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
<a href="protocol.html#except">exception</a>.
The <code>@init</code> handler is called as part of the
<code>initRecord()</code> function during <code>iocInit</code>
before any scan task starts.
before any scan task starts <span class="new">and may be re-run
later under circumstances listed below</span>.
</p>
<p>
In contrast to <a href="#proc">normal processing</a>, the protocol
@ -120,7 +121,7 @@ If the handler fails, the record remains uninitialized:
The <code>@init</code> handler has nothing to do with the
<code>PINI</code> field.
The handler does <u>not</u> process the record nor does it trigger
forward links or other PP links.
forward links or any links with the <code>PP</code> flag.
It runs <u>before</u> <code>PINI</code> is handled.
If the record has <code>PINI=YES</code>, the <code>PINI</code>
processing is a <a href="#proc">normal processing</a> after the
@ -147,19 +148,33 @@ read from a constant <code>INP</code> or <code>DOL</code> field,
or restored from a bump-less reboot system
(e.g. <em>autosave</em> from the <em>synApps</em> package).
</p>
<p class="new">
The <code>@init</code> handler is called again in the following situations:
<p>
The <code>@init</code> handler is called in the following situations:
<ul>
<li>At startup by <code>iocInit</code> during record initialization
as described above.
<li class="new">When the IOC is resumed with <code>iocRun</code> (after
beeing paused with <code>iocPause</code>) before the scan tasks
restart and before records with <code>PINI=RUN</code> are processed.
<li class="new">When the protocol is
<a href="setup.html#reload">reloaded</a></span> for example with
<code>streamReload ["<var>recordname</var>"]</code>.
<li class="new">When <em>StreamDevice</em> 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 <em>asynIPPort</em> driver tests it every few seconds.
Thus there may be a small delay between the device being online
and the record re-initializing.
<li class="new">When <code>streamReinit
"<var>asynPortname</var>"[,<var>addr</var>]</code> is called
(if using an <em>asynDriver</em> port).
<li class="new">When the "magic value" <code>2</code> is written to the
<code>.PROC</code> field of the record.
In this case the record is processed and thus its <code>FLNK</code>
and links with the <code>PP</code> flag are triggered.
</ul>
</p>
<ul class="new">
<li>The device driver informs <em>StreamDevice</em> that the device has
reconnected after it had been disconnected. This is only detectable for
some types of busses.
<li>The IOC is resumed with <code>iocRun</code> after it had
been paused with <code>iocPause</code>. This requires EPICS 3.14.11 or higher.
<li>The record protocol has been <a href="setup.html#reload">reloaded</a>
using the shell function <code>streamReload</code> or the subroutine
record funtion <code>streamReloadSub</code>.
</ul>
<a name="iointr"></a>
<h2>3. I/O Intr</h2>

View File

@ -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 <a href="processing.html#init">Record Processing</a>.
See also chapter <a href="processing.html#init">Record Processing</a>.
It is called at startup by <code>iocInit</code> during record
initialization <span class="new">and again whenever <em>StreamDevice</em>
detects that the device has reconnected after a disconnect or when the
IOC is resumed with <code>iocRun</code> after beeing paused or
when the protocol has been <a href="setup.html#reload">reloaded</a></span>
or when the "magic value" <code>2</code> is written to the <code>.PROC</code>
field.
</dd>
</dl>
<h3>Example:</h3>

View File

@ -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

View File

@ -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: $< > $@