Skip to content

Commit

Permalink
Fixed an issue with PVs being undefined after processing
Browse files Browse the repository at this point in the history
  • Loading branch information
JJL772 committed Nov 23, 2019
1 parent 87195cc commit 12b3740
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 37 deletions.
41 changes: 34 additions & 7 deletions ek9000App/src/devEK9000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void PollThreadFunc(void* param)
if(status)
continue;
uint16_t buf = 1;
elem->m_pDriver->doModbusIO(0, MODBUS_READ_HOLDING_REGISTERS, 0x1121, &buf, 1);
elem->m_pDriver->doModbusIO(0, MODBUS_WRITE_SINGLE_REGISTER, 0x1121, &buf, 1);
elem->Unlock();
}
}
Expand Down Expand Up @@ -290,6 +290,7 @@ CEK9000Device::CEK9000Device()
m_pPortName = (char *)malloc(1);
m_pPortName[0] = '\0';
this->m_Mutex = epicsMutexCreate();
this->queue = new epicsMessageQueue(500, sizeof(void*));
}

CEK9000Device::~CEK9000Device()
Expand Down Expand Up @@ -860,6 +861,29 @@ const char *CEK9000Device::LastErrorString()
return ErrorToString(LastError());
}

struct SMsg_t
{
void* rec;
void(*callback)(void*);
};

void CEK9000Device::QueueCallback(void(*callback)(void*), void* rec)
{
SMsg_t* msg = new SMsg_t;
// this->queue->trySend(&msg, sizeof(callback));
}

void CEK9000Device::ExecuteCallbacks()
{
this->Lock();
SMsg_t* msg;
while(this->queue->tryReceive(&msg, sizeof(msg)))
{
msg->callback(msg->rec);
}
this->Unlock();
}

const char *CEK9000Device::ErrorToString(int i)
{
if(i == EK_EADSERR)
Expand Down Expand Up @@ -1192,7 +1216,7 @@ void ek9000ConfigureTerminal(const iocshArgBuf *args)
void ek9000Stat(const iocshArgBuf *args)
{
const char *ek9k = args[0].sval;
if (!ek9k)
if (!ek9k || !g_pDeviceMgr)
{
epicsPrintf("Invalid parameter.\n");
return;
Expand Down Expand Up @@ -1233,10 +1257,10 @@ void ek9000Stat(const iocshArgBuf *args)
epicsPrintf("\tStatus: NOT CONNECTED\n");
epicsPrintf("\tIP: %s\n", dev->m_pIP);
epicsPrintf("\tAsyn Port Name: %s\n", dev->m_pPortName);
epicsPrintf("\tAO size: %u\n", ao);
epicsPrintf("\tAI size: %u\n", ai);
epicsPrintf("\tBI size: %u\n", bi);
epicsPrintf("\tBO size: %u\n", bo);
epicsPrintf("\tAO size: %u [bytes]\n", ao);
epicsPrintf("\tAI size: %u [bytes]\n", ai);
epicsPrintf("\tBI size: %u [bits]\n", bi);
epicsPrintf("\tBO size: %u [bits]\n", bo);
epicsPrintf("\tTCP connections: %u\n", tcp);
epicsPrintf("\tSerial number: %u\n", sn);
epicsPrintf("\tHardware Version: %u\n", hver);
Expand Down Expand Up @@ -1278,6 +1302,7 @@ void ek9000List(const iocshArgBuf* args)
{
epicsPrintf("Device: %s\n\tSlave Count: %i\n", dev->m_pName, dev->m_nTerms);
epicsPrintf("\tIP: %s\n", dev->m_pIP);
epicsPrintf("\tConnected: %s\n", dev->VerifyConnection() ? "TRUE" : "FALSE");
}
}

Expand Down Expand Up @@ -1377,7 +1402,9 @@ int ek9000RegisterFunctions()

/* ek9000Stat */
{
static const iocshFuncDef func = {"ek9000Stat", 0, NULL};
static const iocshArg arg1 = {"EK9000 Name", iocshArgString};
static const iocshArg*const args[] = {&arg1};
static const iocshFuncDef func = {"ek9000Stat", 1, args};
iocshRegister(&func, ek9000Stat);
}

Expand Down
67 changes: 67 additions & 0 deletions ek9000App/src/devEK9000.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <callback.h>
#include <epicsStdio.h>
#include <errlog.h>
#include <epicsMessageQueue.h>

#include <drvModbusAsyn.h>
#include <asynPortDriver.h>
Expand All @@ -41,6 +42,8 @@
#include <stdint.h>
#include <string.h>

#include <functional>

#define PORT_PREFIX "PORT_"

/* Choice strings */
Expand Down Expand Up @@ -369,13 +372,20 @@ class CEK9000Device
/* last device err */
int m_nError = EK_EOK;

/* Message queue */
epicsMessageQueue* queue;

public:
CEK9000Device();

/* Make sure to free everything */
~CEK9000Device();

public:
void QueueCallback(void(*callback)(void*), void* rec);

void ExecuteCallbacks();

/* Allows for better error handling (instead of using print statements to indicate error) */
static CEK9000Device *Create(const char *name, const char *ip, int terminal_count);

Expand Down Expand Up @@ -555,4 +565,61 @@ class CEK9000Device
}
};

#include <type_traits>
#include <typeinfo>

template<class...Args>
class iocshFunction
{
iocshArg* args;
iocshFuncDef funcdef;
int nargs;
std::function<void(Args...)> func;
public:
iocshFunction(const char* name, std::initializer_list<const char*> list, std::function<void(Args...)> fn) :
func(fn)
{
nargs = list.size();
if(nargs > 0)
args = (iocshArg*)malloc(list.size() * sizeof(iocshArg));
/* Use this to determine types */
std::vector<Args...> argbuf;

/* Handle all of the types, probably in the worst way possible */
int i = 0;
for(auto x : list)
{
iocshArgType argtype = getArgType(typeid(argbuf[i]));
args[i] = {x,argtype};
i++;
}
/* Register the function */
funcdef = {name, nargs, this->args};
iocshRegister(&this->funcdef, fn);
}

~iocshFunction()
{
free(args);
}

private:
void wrapper(const iocshArgBuf* argbuf)
{
}

iocshArgType getArgType(const std::type_info& info) const
{
if(info == typeid(int) || info == typeid(unsigned))
return iocshArgInt;
else if(info == typeid(float) || info == typeid(double) || info == typeid(long double))
return iocshArgDouble;
else if(info == typeid(const char*) || info == typeid(char*))
return iocshArgString;
else if(info == typeid(pdbbase))
return iocshArgPdbbase;
return iocshArgString;
}
};

#endif
14 changes: 10 additions & 4 deletions ek9000App/src/devEL1XXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <biRecord.h>
#include <iocsh.h>
#include <callback.h>
#include <alarm.h>
#include <recGbl.h>

#include <drvModbusAsyn.h>
#include <asynPortDriver.h>
Expand Down Expand Up @@ -90,6 +92,7 @@ static void EL10XX_ReadCallback(CALLBACK* callback)
if(status != epicsMutexLockOK)
{
DevError("EL10XX_ReadCallback(): %s\n", CEK9000Device::ErrorToString(EK_EMUTEXTIMEOUT));
recGblSetSevr(pRecord, READ_ALARM, INVALID_ALARM);
pRecord->pact = 0;
return;
}
Expand All @@ -104,6 +107,7 @@ static void EL10XX_ReadCallback(CALLBACK* callback)
/* Error states */
if(status)
{
recGblSetSevr(pRecord, READ_ALARM, INVALID_ALARM);
/* Check type of err */
if(status > 0x100)
{
Expand All @@ -113,8 +117,10 @@ static void EL10XX_ReadCallback(CALLBACK* callback)
DevError("EL10XX_ReadCallback(): %s\n", CEK9000Device::ErrorToString(status));
return;
}
pRecord->pact = 0;
pRecord->val = buf;
pRecord->rval = buf;
pRecord->udf = FALSE;
pRecord->pact = FALSE;
}

static long EL10XX_dev_report(int interest)
Expand All @@ -132,7 +138,6 @@ static long EL10XX_init_record(void* precord)
biRecord* pRecord = (biRecord*)precord;
pRecord->dpvt = malloc(sizeof(SEL10XXSupportData));
SEL10XXSupportData* dpvt = (SEL10XXSupportData*)pRecord->dpvt;

/* Get terminal */
char* name = NULL;
dpvt->m_pTerminal = CTerminal::ProcessRecordName(pRecord->name, dpvt->m_nChannel, name);
Expand All @@ -145,7 +150,6 @@ static long EL10XX_init_record(void* precord)
}
free(name);
dpvt->m_pDevice = dpvt->m_pTerminal->m_pDevice;

/* Lock mutex for modbus io */
int status = dpvt->m_pDevice->Lock();

Expand All @@ -161,6 +165,9 @@ static long EL10XX_init_record(void* precord)
dpvt->m_pDevice->ReadTerminalID(dpvt->m_pTerminal->m_nTerminalIndex, termid);

dpvt->m_pDevice->Unlock();

pRecord->udf = FALSE;

/* Invalid term id */
if(termid == 0 || termid != dpvt->m_pTerminal->m_nTerminalID)
{
Expand All @@ -179,7 +186,6 @@ static long EL10XX_read_record(void* precord)
callbackSetUser(pRecord, callback);
callbackSetPriority(priorityHigh, callback);
/* Indicate processing active */
pRecord->pact = 1;
callbackRequest(callback);
return 0;
}
19 changes: 13 additions & 6 deletions ek9000App/src/devEL2XXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
#include <mbboRecord.h>
#include <iocsh.h>
#include <callback.h>

#include <alarm.h>
#include <alarmString.h>
#include <recGbl.h>
#include <drvModbusAsyn.h>
#include <asynPortDriver.h>

Expand Down Expand Up @@ -94,6 +96,7 @@ static void EL20XX_WriteCallback(CALLBACK* callback)
if(status != epicsMutexLockOK)
{
DevError("EL20XX_WriteCallback(): %s\n", CEK9000Device::ErrorToString(status));
recGblSetSevr(pRecord, WRITE_ALARM, INVALID_ALARM);
pRecord->pact = 0;
return;
}
Expand All @@ -104,13 +107,16 @@ static void EL20XX_WriteCallback(CALLBACK* callback)
status = dpvt->m_pTerminal->doEK9000IO(MODBUS_WRITE_MULTIPLE_COILS,
dpvt->m_pTerminal->m_nOutputStart + (dpvt->m_nChannel-2), &buf, 1);

/* Processing done */
pRecord->pact = 0;
dpvt->m_pDevice->Unlock();

/* Processing done */
pRecord->pact = FALSE;
pRecord->rbv = pRecord->val;
pRecord->udf = FALSE;
/* check for errors... */
if(status)
{
recGblSetSevr(pRecord, WRITE_ALARM, INVALID_ALARM);
if(status > 0x100)
{
DevError("EL20XX_WriteCallback(): %s\n", CEK9000Device::ErrorToString(EK_EMODBUSERR));
Expand All @@ -120,7 +126,7 @@ static void EL20XX_WriteCallback(CALLBACK* callback)
return;
}
}

#if 0
static void EL20XX_ReadOutputs(void* precord)
{
boRecord* pRecord = (boRecord*)precord;
Expand All @@ -133,6 +139,7 @@ static void EL20XX_ReadOutputs(void* precord)
dpvt->m_pTerminal->m_nOutputStart + (dpvt->m_nChannel * 2), &buf, 1);
pRecord->rval = buf;
}
#endif

static long EL20XX_dev_report(int interest)
{
Expand Down Expand Up @@ -201,13 +208,13 @@ static long EL20XX_init_record(void* precord)
static long EL20XX_write_record(void* precord)
{
boRecord* pRecord = (boRecord*)precord;
SEL20XXSupportData* dat = (SEL20XXSupportData*)pRecord->dpvt;
CALLBACK* callback = (CALLBACK*)malloc(sizeof(CALLBACK));
*callback = *(CALLBACK*)EL20XX_WriteCallback;
callbackSetUser(pRecord, callback);
callbackSetPriority(priorityHigh, callback);
callbackSetCallback(EL20XX_WriteCallback, callback);
pRecord->pact = 1;
callbackRequest(callback);

//dat->m_pDevice->QueueCallback(EL20XX_WriteCallback, precord);
return 0;
}
16 changes: 12 additions & 4 deletions ek9000App/src/devEL3XXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <aiRecord.h>
#include <iocsh.h>
#include <callback.h>
#include <alarm.h>
#include <recGbl.h>

#include <drvModbusAsyn.h>
#include <asynPortDriver.h>
Expand Down Expand Up @@ -78,6 +80,7 @@ struct SEL30XXSupportData
int m_nChannel;
/* Compact or standard PDO used */
bool m_bCompactPDO;
bool isSigned;
};

static void EL30XX_ReadCallback(CALLBACK* callback)
Expand All @@ -97,6 +100,7 @@ static void EL30XX_ReadCallback(CALLBACK* callback)

if(status != epicsMutexLockOK)
{
recGblSetSevr(pRecord, READ_ALARM, INVALID_ALARM);
DevError("EL30XX_ReadCallback(): %s\n", CEK9000Device::ErrorToString(EK_EMUTEXTIMEOUT));
return;
}
Expand All @@ -105,13 +109,19 @@ static void EL30XX_ReadCallback(CALLBACK* callback)
status = dpvt->m_pTerminal->doEK9000IO(MODBUS_READ_INPUT_REGISTERS, dpvt->m_pTerminal->m_nInputStart +
((dpvt->m_nChannel-1) * 2), buf, 2);
/* Set props */
pRecord->rval = buf[0];
pRecord->pact = 0;
pRecord->rval = (uint16_t)buf[0];
if(dpvt->isSigned)
pRecord->val = (epicsFloat64)((int16_t)buf[0]);
else
pRecord->val = (epicsFloat64)((uint16_t)buf[0]);
pRecord->pact = FALSE;
pRecord->udf = FALSE;
dpvt->m_pTerminal->m_pDevice->Unlock();

/* Check for error */
if(status)
{
recGblSetSevr(pRecord, READ_ALARM, INVALID_ALARM);
if(status > 0x100)
{
DevError("EL30XX_ReadCallback(): %s\n", CEK9000Device::ErrorToString(EK_EMODBUSERR));
Expand Down Expand Up @@ -176,8 +186,6 @@ static long EL30XX_init_record(void *precord)
static long EL30XX_read_record(void *precord)
{
aiRecord* pRecord = (aiRecord*)precord;
/* indicate processing */
pRecord->pact = 1;
/* Allocate and set callback */
CALLBACK *callback = (CALLBACK *)malloc(sizeof(CALLBACK));
*callback = *(CALLBACK*)EL30XX_ReadCallback;
Expand Down
Loading

0 comments on commit 12b3740

Please sign in to comment.