improve both ecx_statecheck and ecx_readstate

- in ecx_statecheck only one iteration is done through the slave list if needed
- in ecx_readstate only one datagram is used if possible
This commit is contained in:
MagnaboscoAndrea 2016-10-23 13:18:34 +02:00
parent 3be652a0e0
commit 298397bcc3

View File

@ -756,12 +756,62 @@ int ecx_FPRD_multi(ecx_contextt *context, int n, uint16 *configlst, ec_alstatust
*/ */
int ecx_readstate(ecx_contextt *context) int ecx_readstate(ecx_contextt *context)
{ {
uint16 slave, fslave, lslave, configadr, lowest, rval; uint16 slave, fslave, lslave, configadr, lowest, rval, bitwisestate;
ec_alstatust sl[MAX_FPRD_MULTI]; ec_alstatust sl[MAX_FPRD_MULTI];
uint16 slca[MAX_FPRD_MULTI]; uint16 slca[MAX_FPRD_MULTI];
boolean noerrorflag, allslavessamestate;
lowest = 0xff; /* Try to establish the state of all slaves sending only one broadcast datargam.
* This way a number of datagrams equal to the number of slaves will be sent only if needed.*/
rval = 0;
ecx_BRD(context->port, 0, ECT_REG_ALSTAT, sizeof(rval), &rval, EC_TIMEOUTRET);
rval = etohs(rval);
bitwisestate = (rval & 0x0f);
if ((rval & EC_STATE_ERROR) == 0)
{
noerrorflag = TRUE;
context->slavelist[0].ALstatuscode = 0; context->slavelist[0].ALstatuscode = 0;
}
else
{
noerrorflag = FALSE;
}
switch (bitwisestate)
{
case EC_STATE_INIT:
case EC_STATE_PRE_OP:
case EC_STATE_BOOT:
case EC_STATE_SAFE_OP:
case EC_STATE_OPERATIONAL:
allslavessamestate = TRUE;
context->slavelist[0].state = bitwisestate;
break;
default:
allslavessamestate = FALSE;
break;
}
if (noerrorflag && allslavessamestate)
{
/* No slave has toggled the error flag so the alstatuscode
* (even if different from 0) should be ignored and
* the slaves have reached the same state so the internal state
* can be updated without sending any datagram. */
for (slave = 1; slave <= *(context->slavecount); slave++)
{
context->slavelist[slave].ALstatuscode = 0x0000;
context->slavelist[slave].state = bitwisestate;
}
lowest = bitwisestate;
}
else
{
/* Not all slaves have the same state or at least one is in error so one datagram per slave
* is needed. */
context->slavelist[0].ALstatuscode = 0;
lowest = 0xff;
fslave = 1; fslave = 1;
do do
{ {
@ -772,7 +822,7 @@ int ecx_readstate(ecx_contextt *context)
} }
for (slave = fslave; slave <= lslave; slave++) for (slave = fslave; slave <= lslave; slave++)
{ {
const ec_alstatust zero = {0, 0, 0}; const ec_alstatust zero = { 0, 0, 0 };
configadr = context->slavelist[slave].configadr; configadr = context->slavelist[slave].configadr;
slca[slave - fslave] = configadr; slca[slave - fslave] = configadr;
@ -792,8 +842,9 @@ int ecx_readstate(ecx_contextt *context)
context->slavelist[0].ALstatuscode |= context->slavelist[slave].ALstatuscode; context->slavelist[0].ALstatuscode |= context->slavelist[slave].ALstatuscode;
} }
fslave = lslave + 1; fslave = lslave + 1;
} while(lslave < *(context->slavecount)); } while (lslave < *(context->slavecount));
context->slavelist[0].state = lowest; context->slavelist[0].state = lowest;
}
return lowest; return lowest;
} }
@ -851,36 +902,70 @@ uint16 ecx_statecheck(ecx_contextt *context, uint16 slave, uint16 reqstate, int
{ {
uint16 bitwisestate; uint16 bitwisestate;
uint16 slaveindex; uint16 slaveindex;
boolean allslavessamestate;
boolean noerrorflag;
rval = 0; rval = 0;
ecx_BRD(context->port, 0, ECT_REG_ALSTAT, sizeof(rval), &rval , EC_TIMEOUTRET); ecx_BRD(context->port, 0, ECT_REG_ALSTAT, sizeof(rval), &rval , EC_TIMEOUTRET);
rval = etohs(rval); rval = etohs(rval);
bitwisestate = (rval & 0x0f); bitwisestate = (rval & 0x0f);
if((rval & 0xf0) == 0) if ((rval & EC_STATE_ERROR) == 0)
{ {
/* No slave has toggled the error flag so the alstatuscode (even if different from 0) should be ignored */ noerrorflag = TRUE;
for(slaveindex = 1; slaveindex <= *(context->slavecount); slaveindex++) context->slavelist[0].ALstatuscode = 0;
{
context->slavelist[slaveindex].ALstatuscode = 0x0000;
} }
else
{
noerrorflag = FALSE;
} }
switch(bitwisestate) switch (bitwisestate)
{ {
case EC_STATE_INIT: case EC_STATE_INIT:
case EC_STATE_PRE_OP: case EC_STATE_PRE_OP:
case EC_STATE_BOOT: case EC_STATE_BOOT:
case EC_STATE_SAFE_OP: case EC_STATE_SAFE_OP:
case EC_STATE_OPERATIONAL: case EC_STATE_OPERATIONAL:
/* All the slaves have reached the same state so we can update the state of every slave */ allslavessamestate = TRUE;
for(slaveindex = 1; slaveindex <= *(context->slavecount); slaveindex++) break;
default:
allslavessamestate = FALSE;
break;
}
if (noerrorflag || allslavessamestate)
{
if (noerrorflag && allslavessamestate)
{
/* No slave has toggled the error flag so the alstatuscode
* (even if different from 0) should be ignored and
* the slaves have reached the same state so the internal state
* can be updated without sending any datagram. */
for (slaveindex = 1; slaveindex <= *(context->slavecount); slaveindex++)
{
context->slavelist[slaveindex].ALstatuscode = 0x0000;
context->slavelist[slaveindex].state = bitwisestate;
}
}
else if (noerrorflag)
{
/* No slave has toggled the error flag so the alstatuscode
* (even if different from 0) should be ignored. */
for (slaveindex = 1; slaveindex <= *(context->slavecount); slaveindex++)
{
context->slavelist[slaveindex].ALstatuscode = 0x0000;
}
}
else
{
/* All the slaves have reached the same state therefore
* the internal state can be updated without sending any datagram. */
for (slaveindex = 1; slaveindex <= *(context->slavecount); slaveindex++)
{ {
context->slavelist[slaveindex].state = bitwisestate; context->slavelist[slaveindex].state = bitwisestate;
} }
break; }
default:
break;
} }
} }
else else