3 Commits

Author SHA1 Message Date
8ae2aa7ecd fixing_strings (#1)
Reviewed-on: #1
Co-authored-by: Edward Wall <edward.wall@psi.ch>
Co-committed-by: Edward Wall <edward.wall@psi.ch>
2025-04-24 15:46:58 +02:00
7d4f57750b version test fix was incomplete 2022-02-17 14:59:31 +01:00
54e258db1a added option "writeall" to write the whole buff to DB - needed for SINQ 2020-02-12 08:53:12 +01:00
5 changed files with 52 additions and 9 deletions

View File

@ -1,7 +1,12 @@
include /ioc/tools/driver.makefile include /ioc/tools/driver.makefile
BUILDCLASSES+=Linux MODULE=sinqS7plcFW
BUILDCLASSES=Linux
EPICS_VERSIONS=7.0.7
ARCH_FILTER=RHEL%
DBDS += s7plcFWBase.dbd DBDS += s7plcFWBase.dbd
DBDS_3.14 += s7plcFWCalcout.dbd DBDS_3.14 += s7plcFWCalcout.dbd
DBDS_3.14 += s7plcFWReg.dbd DBDS_3.14 += s7plcFWReg.dbd
USR_CFLAGS += -Wall -Wextra -Wunused-result

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# SinqS7PLCFW
This is a fork of Dirk Zimoch's [epics\_driver\_modules/s7plcFW](https://git.psi.ch/epics_driver_modules/s7plcFW), with the following adjustments:
* The String offset, now takes the two prefix bytes (max string length, current
string length) into account, so you don't have to add 2 to each offset in
order for the driver to read the correct string
* The length of a String read from the SPS and written to the Val field of a
stringin record is no longer static, but instead read from the SPS directly,
to avoid having bytes leftover in the buffer from a previous string.
* The Makefile has been slightly adjusted, limiting the build targets.
The default driver behaviour is documented in the file [s7plcFW.html](./s7plcFW.html).

View File

@ -2033,7 +2033,11 @@ STATIC long s7plcFWInitRecordStringin(stringinRecord *record)
STATIC long s7plcFWReadStringin(stringinRecord *record) STATIC long s7plcFWReadStringin(stringinRecord *record)
{ {
// The SPS includes the max length of the string and the length of the
// current string, as the first two bytes in the register.
int status; int status;
epicsUInt8 uval8;
S7memPrivate_t *priv = (S7memPrivate_t *)record->dpvt; S7memPrivate_t *priv = (S7memPrivate_t *)record->dpvt;
if (!priv) if (!priv)
@ -2044,11 +2048,18 @@ STATIC long s7plcFWReadStringin(stringinRecord *record)
return -1; return -1;
} }
assert(priv->station); assert(priv->station);
status = s7plcFWRead(priv->station, priv->offs+1,
1, &uval8);
s7plcFWDebugLog(3, "stringin %s: read 8bit %02x\n",
record->name, uval8);
uval8 = uval8 <= priv->dlen ? uval8 : priv->dlen;
memset(record->val, 0, priv->dlen); memset(record->val, 0, priv->dlen);
status = s7plcFWReadArray(priv->station, priv->offs, status = s7plcFWReadArray(priv->station, priv->offs+2,
1, priv->dlen, record->val); 1, uval8, record->val);
s7plcFWDebugLog(3, "stringin %s: read array of %d 8bit values\n", s7plcFWDebugLog(3, "stringin %s: read array of %d 8bit values\n",
record->name, priv->dlen); record->name, uval8);
if (record->val[priv->dlen] && !memchr(record->val, 0, priv->dlen)) if (record->val[priv->dlen] && !memchr(record->val, 0, priv->dlen))
{ {
/* truncate oversize string */ /* truncate oversize string */

View File

@ -40,7 +40,7 @@
#include "drvS7plcFW.h" #include "drvS7plcFW.h"
#if ((EPICS_VERSION==3 && EPICS_REVISION>=14) || EPICS_VERSION>3) #ifndef BASE_VERSION
/* R3.14 */ /* R3.14 */
#include <dbAccess.h> #include <dbAccess.h>
#include <iocsh.h> #include <iocsh.h>
@ -52,6 +52,7 @@
#include <epicsExport.h> #include <epicsExport.h>
#else #else
/* R3.13 */ /* R3.13 */
#define EPICS_3_13
#include "compat3_13.h" #include "compat3_13.h"
#endif #endif
@ -136,6 +137,8 @@ struct s7plcFWStation {
char *fetchBuffer, *writeBuffer; char *fetchBuffer, *writeBuffer;
int swapBytes; int swapBytes;
float recvTimeout, recvDelay, outIOintDelay; float recvTimeout, recvDelay, outIOintDelay;
int writeAll; // flag, when != 0 then always write the whole buffer to DB (needed for SINQ)
}; };
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@ -171,8 +174,8 @@ STATIC long s7plcFWIoReport(int level)
printf(" NOT CONNECTED\n"); printf(" NOT CONNECTED\n");
} }
printf(" WRITE: Port=%5d Org=%3d Db=%3d Offs=%5d Size=%5d buffer@%p (%5d bytes)", printf(" WRITE: Port=%5d Org=%3d Db=%3d Offs=%5d Size=%5d buffer@%p (%5d bytes) %s",
station->writePort, station->writeOrg, station->writeDb, station->writeOffs, station->writeSize, station->writeBuffer, station->writeSize); station->writePort, station->writeOrg, station->writeDb, station->writeOffs, station->writeSize, station->writeBuffer, station->writeSize, (station->writeAll ? "" : "writeAll"));
if (station->writeConnStatus) { if (station->writeConnStatus) {
printf(" CONNECTED (fd=%d)\n", station->writeSocket); printf(" CONNECTED (fd=%d)\n", station->writeSocket);
} }
@ -248,6 +251,7 @@ int s7plcFWConfigure(char *name, char* IPaddr, char *fetchInfo, char *writeInfo,
unsigned char fetchDb, writeDb; unsigned char fetchDb, writeDb;
unsigned int fetchOffs, writeOffs; unsigned int fetchOffs, writeOffs;
unsigned int fetchSize, writeSize; unsigned int fetchSize, writeSize;
int writeAll;
if (!name) { if (!name) {
errlogSevPrintf(errlogFatal, "s7plcFWConfigure: missing name\n"); errlogSevPrintf(errlogFatal, "s7plcFWConfigure: missing name\n");
@ -268,6 +272,7 @@ int s7plcFWConfigure(char *name, char* IPaddr, char *fetchInfo, char *writeInfo,
extractPGDOS(fetchInfo, &fetchPort, &fetchOrg, &fetchDb, &fetchOffs, &fetchSize); extractPGDOS(fetchInfo, &fetchPort, &fetchOrg, &fetchDb, &fetchOffs, &fetchSize);
extractPGDOS(writeInfo, &writePort, &writeOrg, &writeDb, &writeOffs, &writeSize); extractPGDOS(writeInfo, &writePort, &writeOrg, &writeDb, &writeOffs, &writeSize);
writeAll = 0; if (strstr(writeInfo, "writeall") != NULL) writeAll = 1; // write the whole buffer to DB
if ((fetchPort == 0) || (fetchOrg == 0) || (fetchDb == 0) || ((fetchOffs%2) != 0) || (fetchSize == 0) || ((fetchSize%2) != 0)) { /* size & offs: only even numbers */ if ((fetchPort == 0) || (fetchOrg == 0) || (fetchDb == 0) || ((fetchOffs%2) != 0) || (fetchSize == 0) || ((fetchSize%2) != 0)) { /* size & offs: only even numbers */
fetchPort = fetchOrg = fetchDb = fetchOffs = fetchSize = 0; fetchPort = fetchOrg = fetchDb = fetchOffs = fetchSize = 0;
@ -309,6 +314,7 @@ int s7plcFWConfigure(char *name, char* IPaddr, char *fetchInfo, char *writeInfo,
station->writeOffs = writeOffs; station->writeOffs = writeOffs;
station->fetchSize = fetchSize; station->fetchSize = fetchSize;
station->writeSize = writeSize; station->writeSize = writeSize;
station->writeAll = writeAll;
if (fetchSize > 0) if (fetchSize > 0)
station->fetchBuffer = callocMustSucceed(1, fetchSize, "s7plcFWConfigure"); station->fetchBuffer = callocMustSucceed(1, fetchSize, "s7plcFWConfigure");
@ -365,7 +371,7 @@ int s7plcFWConfigure(char *name, char* IPaddr, char *fetchInfo, char *writeInfo,
} }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if (EPICS_REVISION>=14) #ifndef EPICS_3_13
static const iocshArg s7plcFWConfigureArg0 = { "name", iocshArgString }; static const iocshArg s7plcFWConfigureArg0 = { "name", iocshArgString };
static const iocshArg s7plcFWConfigureArg1 = { "IPaddr", iocshArgString }; static const iocshArg s7plcFWConfigureArg1 = { "IPaddr", iocshArgString };
static const iocshArg s7plcFWConfigureArg2 = { "fetchInfo", iocshArgString }; static const iocshArg s7plcFWConfigureArg2 = { "fetchInfo", iocshArgString };
@ -810,7 +816,12 @@ int s7plcFWWriteMaskedArray(s7plcFWStation *station, unsigned int offset, unsign
/* warning: we allways have to write even number of bytes - so it can happen that we have to write 1 or 2 bytes more than requested */ /* warning: we allways have to write even number of bytes - so it can happen that we have to write 1 or 2 bytes more than requested */
woffs = offset & 0xFFFFFFFE; /* we need even byte offset */ woffs = offset & 0xFFFFFFFE; /* we need even byte offset */
wlen = 0; if (woffs != offset) wlen += 1; wlen += nelem*dlen; if ((wlen % 2) != 0) wlen += 1; wlen = 0; if (woffs != offset) wlen += 1; wlen += nelem*dlen; if ((wlen % 2) != 0) wlen += 1;
wstatus = s7plcFWdoWrite(station, &station->writeBuffer[woffs], woffs, wlen); if (station->writeAll == 0) {
wstatus = s7plcFWdoWrite(station, &station->writeBuffer[woffs], woffs, wlen);
}
else {
wstatus = s7plcFWdoWrite(station, &station->writeBuffer[0], 0, station->writeSize);
}
if (wstatus != 0) { if (wstatus != 0) {
s7plcFWDebugLog(0, "s7plcFWWriteMaskedArray %s: s7plcFWdoWrite(%d, ...) failed\n", station->name, station->writeSocket); s7plcFWDebugLog(0, "s7plcFWWriteMaskedArray %s: s7plcFWdoWrite(%d, ...) failed\n", station->name, station->writeSocket);
s7plcFWCloseConnection(station, FOR_WRITE); s7plcFWCloseConnection(station, FOR_WRITE);

View File

@ -123,6 +123,9 @@ containing the
and and
<code>"writePort,writeOrg,writeDb,writeOffsetInDb,writeSizeOfDb"</code>. <code>"writePort,writeOrg,writeDb,writeOffsetInDb,writeSizeOfDb"</code>.
<br> <br>
For <code><i>writeInfo</i></code> you can add at the end of string an <code><i>writeall</i></code> option,
to allways write the whole buffer to DB. This is needed for PLCs as used in SINQ.
<br>
fetchPort and writePort come in pairs. Usualy starting at 2000,2001. fetchPort and writePort come in pairs. Usualy starting at 2000,2001.
<br> <br>
Offsets and Sizes are in bytes and must be <code>even numbers</code>. Offset will usualy be zero, but one does not neccessarilly have to start at the beginning of Db. The size is number of bytes to fetch or write starting from given offset - it does not have to go to the end of Db and it should never exceed the size of Db. Offsets and Sizes are in bytes and must be <code>even numbers</code>. Offset will usualy be zero, but one does not neccessarilly have to start at the beginning of Db. The size is number of bytes to fetch or write starting from given offset - it does not have to go to the end of Db and it should never exceed the size of Db.