Make PDO CA access thread safe (#51)

This commit is contained in:
nakarlsson 2016-08-18 17:28:02 +02:00 committed by Hans-Erik Floryd
parent 43e4493346
commit 03601959b6
5 changed files with 75 additions and 65 deletions

View File

@ -769,39 +769,43 @@ int ecx_readPDOassign(ecx_contextt *context, uint16 Slave, uint16 PDOassign)
/** Read PDO assign structure in Complete Access mode /** Read PDO assign structure in Complete Access mode
* @param[in] context = context struct * @param[in] context = context struct
* @param[in] Slave = Slave number * @param[in] Slave = Slave number
* @param[in] Thread_n = Calling thread index
* @param[in] PDOassign = PDO assign object * @param[in] PDOassign = PDO assign object
* @return total bitlength of PDO assign * @return total bitlength of PDO assign
*/ */
int ecx_readPDOassignCA(ecx_contextt *context, uint16 Slave, uint16 PDOassign) int ecx_readPDOassignCA(ecx_contextt *context, uint16 Slave, int Thread_n,
uint16 PDOassign)
{ {
uint16 idxloop, nidx, subidxloop, idx, subidx; uint16 idxloop, nidx, subidxloop, idx, subidx;
int wkc, bsize = 0, rdl; int wkc, bsize = 0, rdl;
/* find maximum size of PDOassign buffer */ /* find maximum size of PDOassign buffer */
rdl = sizeof(ec_PDOassignt); rdl = sizeof(ec_PDOassignt);
context->PDOassign->n=0; context->PDOassign[Thread_n].n=0;
/* read rxPDOassign in CA mode, all subindexes are read in one struct */ /* read rxPDOassign in CA mode, all subindexes are read in one struct */
wkc = ecx_SDOread(context, Slave, PDOassign, 0x00, TRUE, &rdl, context->PDOassign, EC_TIMEOUTRXM); wkc = ecx_SDOread(context, Slave, PDOassign, 0x00, TRUE, &rdl,
&(context->PDOassign[Thread_n]), EC_TIMEOUTRXM);
/* positive result from slave ? */ /* positive result from slave ? */
if ((wkc > 0) && (context->PDOassign->n > 0)) if ((wkc > 0) && (context->PDOassign[Thread_n].n > 0))
{ {
nidx = context->PDOassign->n; nidx = context->PDOassign[Thread_n].n;
bsize = 0; bsize = 0;
/* for each PDO do */ /* for each PDO do */
for (idxloop = 1; idxloop <= nidx; idxloop++) for (idxloop = 1; idxloop <= nidx; idxloop++)
{ {
/* get index from PDOassign struct */ /* get index from PDOassign struct */
idx = etohs(context->PDOassign->index[idxloop - 1]); idx = etohs(context->PDOassign[Thread_n].index[idxloop - 1]);
if (idx > 0) if (idx > 0)
{ {
rdl = sizeof(ec_PDOdesct); context->PDOdesc->n = 0; rdl = sizeof(ec_PDOdesct); context->PDOdesc[Thread_n].n = 0;
/* read SDO's that are mapped in PDO, CA mode */ /* read SDO's that are mapped in PDO, CA mode */
wkc = ecx_SDOread(context, Slave,idx, 0x00, TRUE, &rdl, context->PDOdesc, EC_TIMEOUTRXM); wkc = ecx_SDOread(context, Slave,idx, 0x00, TRUE, &rdl,
subidx = context->PDOdesc->n; &(context->PDOdesc[Thread_n]), EC_TIMEOUTRXM);
subidx = context->PDOdesc[Thread_n].n;
/* extract all bitlengths of SDO's */ /* extract all bitlengths of SDO's */
for (subidxloop = 1; subidxloop <= subidx; subidxloop++) for (subidxloop = 1; subidxloop <= subidx; subidxloop++)
{ {
bsize += LO_BYTE(etohl(context->PDOdesc->PDO[subidxloop -1])); bsize += LO_BYTE(etohl(context->PDOdesc[Thread_n].PDO[subidxloop -1]));
} }
} }
} }
@ -932,13 +936,14 @@ int ecx_readPDOmap(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize)
* tries to read them and collect a full input and output mapping size * tries to read them and collect a full input and output mapping size
* of designated slave. Slave has to support CA, otherwise use ec_readPDOmap(). * of designated slave. Slave has to support CA, otherwise use ec_readPDOmap().
* *
* @param[in] context = context struct * @param[in] context = context struct
* @param[in] Slave = Slave number * @param[in] Slave = Slave number
* @param[out] Osize = Size in bits of output mapping (rxPDO) found * @param[in] Thread_n = Calling thread index
* @param[out] Isize = Size in bits of input mapping (txPDO) found * @param[out] Osize = Size in bits of output mapping (rxPDO) found
* @param[out] Isize = Size in bits of input mapping (txPDO) found
* @return >0 if mapping succesful. * @return >0 if mapping succesful.
*/ */
int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize) int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int Thread_n, int *Osize, int *Isize)
{ {
int wkc, rdl; int wkc, rdl;
int retVal = 0; int retVal = 0;
@ -950,13 +955,14 @@ int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize
*Osize = 0; *Osize = 0;
SMt_bug_add = 0; SMt_bug_add = 0;
rdl = sizeof(ec_SMcommtypet); rdl = sizeof(ec_SMcommtypet);
context->SMcommtype->n = 0; context->SMcommtype[Thread_n].n = 0;
/* read SyncManager Communication Type object count Complete Access*/ /* read SyncManager Communication Type object count Complete Access*/
wkc = ecx_SDOread(context, Slave, ECT_SDO_SMCOMMTYPE, 0x00, TRUE, &rdl, context->SMcommtype, EC_TIMEOUTRXM); wkc = ecx_SDOread(context, Slave, ECT_SDO_SMCOMMTYPE, 0x00, TRUE, &rdl,
&(context->SMcommtype[Thread_n]), EC_TIMEOUTRXM);
/* positive result from slave ? */ /* positive result from slave ? */
if ((wkc > 0) && (context->SMcommtype->n > 2)) if ((wkc > 0) && (context->SMcommtype[Thread_n].n > 2))
{ {
nSM = context->SMcommtype->n; nSM = context->SMcommtype[Thread_n].n;
/* limit to maximum number of SM defined, if true the slave can't be configured */ /* limit to maximum number of SM defined, if true the slave can't be configured */
if (nSM > EC_MAXSM) if (nSM > EC_MAXSM)
{ {
@ -966,7 +972,7 @@ int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize
/* iterate for every SM type defined */ /* iterate for every SM type defined */
for (iSM = 2 ; iSM < nSM ; iSM++) for (iSM = 2 ; iSM < nSM ; iSM++)
{ {
tSM = context->SMcommtype->SMtype[iSM]; tSM = context->SMcommtype[Thread_n].SMtype[iSM];
// start slave bug prevention code, remove if possible // start slave bug prevention code, remove if possible
if((iSM == 2) && (tSM == 2)) // SM2 has type 2 == mailbox out, this is a bug in the slave! if((iSM == 2) && (tSM == 2)) // SM2 has type 2 == mailbox out, this is a bug in the slave!
@ -989,7 +995,8 @@ int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize
if ((tSM == 3) || (tSM == 4)) if ((tSM == 3) || (tSM == 4))
{ {
/* read the assign PDO */ /* read the assign PDO */
Tsize = ecx_readPDOassignCA(context, Slave, ECT_SDO_PDOASSIGN + iSM ); Tsize = ecx_readPDOassignCA(context, Slave, Thread_n,
ECT_SDO_PDOASSIGN + iSM );
/* if a mapping is found */ /* if a mapping is found */
if (Tsize) if (Tsize)
{ {
@ -1445,12 +1452,13 @@ int ec_readPDOassign(uint16 Slave, uint16 PDOassign)
/** Read PDO assign structure in Complete Access mode /** Read PDO assign structure in Complete Access mode
* @param[in] Slave = Slave number * @param[in] Slave = Slave number
* @param[in] PDOassign = PDO assign object * @param[in] PDOassign = PDO assign object
* @param[in] Thread_n = Calling thread index
* @return total bitlength of PDO assign * @return total bitlength of PDO assign
* @see ecx_readPDOmap * @see ecx_readPDOmap
*/ */
int ec_readPDOassignCA(uint16 Slave, uint16 PDOassign) int ec_readPDOassignCA(uint16 Slave, uint16 PDOassign, int Thread_n)
{ {
return ecx_readPDOassignCA(&ecx_context, Slave, PDOassign); return ecx_readPDOassignCA(&ecx_context, Slave, Thread_n, PDOassign);
} }
/** CoE read PDO mapping. /** CoE read PDO mapping.
@ -1478,14 +1486,15 @@ int ec_readPDOmap(uint16 Slave, int *Osize, int *Isize)
* of designated slave. Slave has to support CA, otherwise use ec_readPDOmap(). * of designated slave. Slave has to support CA, otherwise use ec_readPDOmap().
* *
* @param[in] Slave = Slave number * @param[in] Slave = Slave number
* @param[in] Thread_n = Calling thread index
* @param[out] Osize = Size in bits of output mapping (rxPDO) found * @param[out] Osize = Size in bits of output mapping (rxPDO) found
* @param[out] Isize = Size in bits of input mapping (txPDO) found * @param[out] Isize = Size in bits of input mapping (txPDO) found
* @return >0 if mapping succesful. * @return >0 if mapping succesful.
* @see ecx_readPDOmap ec_readPDOmapCA * @see ecx_readPDOmap ec_readPDOmapCA
*/ */
int ec_readPDOmapCA(uint16 Slave, int *Osize, int *Isize) int ec_readPDOmapCA(uint16 Slave, int Thread_n, int *Osize, int *Isize)
{ {
return ecx_readPDOmapCA(&ecx_context, Slave, Osize, Isize); return ecx_readPDOmapCA(&ecx_context, Slave, Thread_n, Osize, Isize);
} }
/** CoE read Object Description List. /** CoE read Object Description List.

View File

@ -103,7 +103,7 @@ int ec_SDOwrite(uint16 Slave, uint16 Index, uint8 SubIndex,
int ec_RxPDO(uint16 Slave, uint16 RxPDOnumber , int psize, void *p); int ec_RxPDO(uint16 Slave, uint16 RxPDOnumber , int psize, void *p);
int ec_TxPDO(uint16 slave, uint16 TxPDOnumber , int *psize, void *p, int timeout); int ec_TxPDO(uint16 slave, uint16 TxPDOnumber , int *psize, void *p, int timeout);
int ec_readPDOmap(uint16 Slave, int *Osize, int *Isize); int ec_readPDOmap(uint16 Slave, int *Osize, int *Isize);
int ec_readPDOmapCA(uint16 Slave, int *Osize, int *Isize); int ec_readPDOmapCA(uint16 Slave, int Thread_n, int *Osize, int *Isize);
int ec_readODlist(uint16 Slave, ec_ODlistt *pODlist); int ec_readODlist(uint16 Slave, ec_ODlistt *pODlist);
int ec_readODdescription(uint16 Item, ec_ODlistt *pODlist); int ec_readODdescription(uint16 Item, ec_ODlistt *pODlist);
int ec_readOEsingle(uint16 Item, uint8 SubI, ec_ODlistt *pODlist, ec_OElistt *pOElist); int ec_readOEsingle(uint16 Item, uint8 SubI, ec_ODlistt *pODlist, ec_OElistt *pOElist);
@ -118,7 +118,7 @@ int ecx_SDOwrite(ecx_contextt *context, uint16 Slave, uint16 Index, uint8 SubInd
int ecx_RxPDO(ecx_contextt *context, uint16 Slave, uint16 RxPDOnumber , int psize, void *p); int ecx_RxPDO(ecx_contextt *context, uint16 Slave, uint16 RxPDOnumber , int psize, void *p);
int ecx_TxPDO(ecx_contextt *context, uint16 slave, uint16 TxPDOnumber , int *psize, void *p, int timeout); int ecx_TxPDO(ecx_contextt *context, uint16 slave, uint16 TxPDOnumber , int *psize, void *p, int timeout);
int ecx_readPDOmap(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize); int ecx_readPDOmap(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize);
int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize); int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int Thread_n, int *Osize, int *Isize);
int ecx_readODlist(ecx_contextt *context, uint16 Slave, ec_ODlistt *pODlist); int ecx_readODlist(ecx_contextt *context, uint16 Slave, ec_ODlistt *pODlist);
int ecx_readODdescription(ecx_contextt *context, uint16 Item, ec_ODlistt *pODlist); int ecx_readODdescription(ecx_contextt *context, uint16 Item, ec_ODlistt *pODlist);
int ecx_readOEsingle(ecx_contextt *context, uint16 Item, uint8 SubI, ec_ODlistt *pODlist, ec_OElistt *pOElist); int ecx_readOEsingle(ecx_contextt *context, uint16 Item, uint8 SubI, ec_ODlistt *pODlist, ec_OElistt *pOElist);

View File

@ -67,18 +67,16 @@
#define EC_PRINT(...) do {} while (0) #define EC_PRINT(...) do {} while (0)
#endif #endif
/* define maximum number of concurrent threads in mapping */
#define MAX_MAPT 8
typedef struct typedef struct
{ {
int thread_n;
int running; int running;
ecx_contextt *context; ecx_contextt *context;
uint16 slave; uint16 slave;
} ecx_mapt_t; } ecx_mapt_t;
ecx_mapt_t ecx_mapt[MAX_MAPT]; ecx_mapt_t ecx_mapt[EC_MAX_MAPT];
OSAL_THREAD_HANDLE ecx_threadh[MAX_MAPT]; OSAL_THREAD_HANDLE ecx_threadh[EC_MAX_MAPT];
#ifdef EC_VER1 #ifdef EC_VER1
/** Slave configuration structure */ /** Slave configuration structure */
@ -665,7 +663,7 @@ static int ecx_lookup_mapping(ecx_contextt *context, uint16 slave, int *Osize, i
return 0; return 0;
} }
static int ecx_map_coe_soe(ecx_contextt *context, uint16 slave) static int ecx_map_coe_soe(ecx_contextt *context, uint16 slave, int thread_n)
{ {
int Isize, Osize; int Isize, Osize;
int rval; int rval;
@ -691,7 +689,7 @@ static int ecx_map_coe_soe(ecx_contextt *context, uint16 slave)
if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */ if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
{ {
/* read PDO mapping via CoE and use Complete Access */ /* read PDO mapping via CoE and use Complete Access */
rval = ecx_readPDOmapCA(context, slave, &Osize, &Isize); rval = ecx_readPDOmapCA(context, slave, thread_n, &Osize, &Isize);
} }
if (!rval) /* CA not available or not succeeded */ if (!rval) /* CA not available or not succeeded */
{ {
@ -823,7 +821,7 @@ OSAL_THREAD_FUNC ecx_mapper_thread(void *param)
{ {
ecx_mapt_t *maptp; ecx_mapt_t *maptp;
maptp = param; maptp = param;
ecx_map_coe_soe(maptp->context, maptp->slave); ecx_map_coe_soe(maptp->context, maptp->slave, maptp->thread_n);
maptp->running = 0; maptp->running = 0;
} }
@ -831,11 +829,11 @@ static int ecx_find_mapt(void)
{ {
int p; int p;
p = 0; p = 0;
while((p < MAX_MAPT) && ecx_mapt[p].running) while((p < EC_MAX_MAPT) && ecx_mapt[p].running)
{ {
p++; p++;
} }
if(p < MAX_MAPT) if(p < EC_MAX_MAPT)
{ {
return p; return p;
} }
@ -849,7 +847,7 @@ static int ecx_get_threadcount(void)
{ {
int thrc, thrn; int thrc, thrn;
thrc = 0; thrc = 0;
for(thrn = 0 ; thrn < MAX_MAPT ; thrn++) for(thrn = 0 ; thrn < EC_MAX_MAPT ; thrn++)
{ {
thrc += ecx_mapt[thrn].running; thrc += ecx_mapt[thrn].running;
} }
@ -887,7 +885,7 @@ int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
context->grouplist[group].outputsWKC = 0; context->grouplist[group].outputsWKC = 0;
context->grouplist[group].inputsWKC = 0; context->grouplist[group].inputsWKC = 0;
for(thrn = 0 ; thrn < MAX_MAPT ; thrn++) for(thrn = 0 ; thrn < EC_MAX_MAPT ; thrn++)
{ {
ecx_mapt[thrn].running = 0; ecx_mapt[thrn].running = 0;
} }
@ -896,10 +894,10 @@ int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
{ {
if (!group || (group == context->slavelist[slave].group)) if (!group || (group == context->slavelist[slave].group))
{ {
if(MAX_MAPT <= 1) if(EC_MAX_MAPT <= 1)
{ {
/* serialised version */ /* serialised version */
ecx_map_coe_soe(context, slave); ecx_map_coe_soe(context, slave, 0);
} }
else else
{ {
@ -910,6 +908,7 @@ int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
} }
ecx_mapt[thrn].context = context; ecx_mapt[thrn].context = context;
ecx_mapt[thrn].slave = slave; ecx_mapt[thrn].slave = slave;
ecx_mapt[thrn].thread_n = thrn;
ecx_mapt[thrn].running = 1; ecx_mapt[thrn].running = 1;
osal_thread_create(&(ecx_threadh[thrn]), 128000, osal_thread_create(&(ecx_threadh[thrn]), 128000,
&ecx_mapper_thread, &(ecx_mapt[thrn])); &ecx_mapper_thread, &(ecx_mapt[thrn]));

View File

@ -117,11 +117,11 @@ static ec_eringt ec_elist;
static ec_idxstackT ec_idxstack; static ec_idxstackT ec_idxstack;
/** SyncManager Communication Type struct to store data of one slave */ /** SyncManager Communication Type struct to store data of one slave */
static ec_SMcommtypet ec_SMcommtype; static ec_SMcommtypet ec_SMcommtype[EC_MAX_MAPT];
/** PDO assign struct to store data of one slave */ /** PDO assign struct to store data of one slave */
static ec_PDOassignt ec_PDOassign; static ec_PDOassignt ec_PDOassign[EC_MAX_MAPT];
/** PDO description struct to store data of one slave */ /** PDO description struct to store data of one slave */
static ec_PDOdesct ec_PDOdesc; static ec_PDOdesct ec_PDOdesc[EC_MAX_MAPT];
/** buffer for EEPROM SM data */ /** buffer for EEPROM SM data */
static ec_eepromSMt ec_SM; static ec_eepromSMt ec_SM;
@ -136,27 +136,27 @@ ecx_portt ecx_port;
ecx_redportt ecx_redport; ecx_redportt ecx_redport;
ecx_contextt ecx_context = { ecx_contextt ecx_context = {
&ecx_port, // .port = &ecx_port, // .port =
&ec_slave[0], // .slavelist = &ec_slave[0], // .slavelist =
&ec_slavecount, // .slavecount = &ec_slavecount, // .slavecount =
EC_MAXSLAVE, // .maxslave = EC_MAXSLAVE, // .maxslave =
&ec_group[0], // .grouplist = &ec_group[0], // .grouplist =
EC_MAXGROUP, // .maxgroup = EC_MAXGROUP, // .maxgroup =
&ec_esibuf[0], // .esibuf = &ec_esibuf[0], // .esibuf =
&ec_esimap[0], // .esimap = &ec_esimap[0], // .esimap =
0, // .esislave = 0, // .esislave =
&ec_elist, // .elist = &ec_elist, // .elist =
&ec_idxstack, // .idxstack = &ec_idxstack, // .idxstack =
&EcatError, // .ecaterror = &EcatError, // .ecaterror =
0, // .DCtO = 0, // .DCtO =
0, // .DCl = 0, // .DCl =
&ec_DCtime, // .DCtime = &ec_DCtime, // .DCtime =
&ec_SMcommtype, // .SMcommtype = &ec_SMcommtype[0], // .SMcommtype =
&ec_PDOassign, // .PDOassign = &ec_PDOassign[0], // .PDOassign =
&ec_PDOdesc, // .PDOdesc = &ec_PDOdesc[0], // .PDOdesc =
&ec_SM, // .eepSM = &ec_SM, // .eepSM =
&ec_FMMU, // .eepFMMU = &ec_FMMU, // .eepFMMU =
NULL // .FOEhook() NULL // .FOEhook()
}; };
#endif #endif

View File

@ -73,6 +73,8 @@ extern "C"
#define EC_MAXFMMU 4 #define EC_MAXFMMU 4
/** max. Adapter */ /** max. Adapter */
#define EC_MAXLEN_ADAPTERNAME 128 #define EC_MAXLEN_ADAPTERNAME 128
/** define maximum number of concurrent threads in mapping */
#define EC_MAX_MAPT 8
typedef struct ec_adapter ec_adaptert; typedef struct ec_adapter ec_adaptert;
struct ec_adapter struct ec_adapter