ethercatconfig.c
Go to the documentation of this file.
1 /*
2  * Licensed under the GNU General Public License version 2 with exceptions. See
3  * LICENSE file in the project root for full license information
4  */
5 
14 #include <stdio.h>
15 #include <string.h>
16 #include "osal.h"
17 #include "oshw.h"
18 #include "ethercattype.h"
19 #include "ethercatbase.h"
20 #include "ethercatmain.h"
21 #include "ethercatcoe.h"
22 #include "ethercatsoe.h"
23 #include "ethercatconfig.h"
24 
25 
26 typedef struct
27 {
28  int thread_n;
29  int running;
32 } ecx_mapt_t;
33 
35 #if EC_MAX_MAPT > 1
36 OSAL_THREAD_HANDLE ecx_threadh[EC_MAX_MAPT];
37 #endif
38 
39 #ifdef EC_VER1
40 
41 typedef const struct
42 {
48  char name[EC_MAXNAME + 1];
68 
69 #include "ethercatconfiglist.h"
70 #endif
71 
73 #define EC_DEFAULTMBXSM0 0x00010026
74 
75 #define EC_DEFAULTMBXSM1 0x00010022
76 
77 #define EC_DEFAULTDOSM0 0x00010044
78 
79 #ifdef EC_VER1
80 
87 {
88  int i = 0;
89 
90  do
91  {
92  i++;
93  } while ( (ec_configlist[i].man != EC_CONFIGEND) &&
94  ((ec_configlist[i].man != man) || (ec_configlist[i].id != id)) );
95  if (ec_configlist[i].man == EC_CONFIGEND)
96  {
97  i = 0;
98  }
99  return i;
100 }
101 #endif
102 
104 {
105  int lp;
106  *(context->slavecount) = 0;
107  /* clean ec_slave array */
108  memset(context->slavelist, 0x00, sizeof(ec_slavet) * context->maxslave);
109  memset(context->grouplist, 0x00, sizeof(ec_groupt) * context->maxgroup);
110  /* clear slave eeprom cache, does not actually read any eeprom */
111  ecx_siigetbyte(context, 0, EC_MAXEEPBUF);
112  for(lp = 0; lp < context->maxgroup; lp++)
113  {
114  /* default start address per group entry */
115  context->grouplist[lp].logstartaddr = lp << EC_LOGGROUPOFFSET;
116  }
117 }
118 
120 {
121  uint8 b;
122  uint16 w;
123  int wkc;
124 
125  /* make special pre-init register writes to enable MAC[1] local administered bit *
126  * setting for old netX100 slaves */
127  b = 0x00;
128  ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3); /* Ignore Alias register */
130  ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */
131  /* netX100 should now be happy */
132  ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */
133  wkc = ecx_BRD(context->port, 0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE); /* detect number of slaves */
134  if (wkc > 0)
135  {
136  /* this is strictly "less than" since the master is "slave 0" */
137  if (wkc < EC_MAXSLAVE)
138  {
139  *(context->slavecount) = wkc;
140  }
141  else
142  {
143  EC_PRINT("Error: too many slaves on network: num_slaves=%d, EC_MAXSLAVE=%d\n",
144  wkc, EC_MAXSLAVE);
145  return EC_SLAVECOUNTEXCEEDED;
146  }
147  }
148  return wkc;
149 }
150 
152 {
153  uint8 b;
154  uint16 w;
155  uint8 zbuf[64];
156  memset(&zbuf, 0x00, sizeof(zbuf));
157  b = 0x00;
158  ecx_BWR(context->port, 0x0000, ECT_REG_DLPORT , sizeof(b) , &b, EC_TIMEOUTRET3); /* deact loop manual */
159  w = htoes(0x0004);
160  ecx_BWR(context->port, 0x0000, ECT_REG_IRQMASK , sizeof(w) , &w, EC_TIMEOUTRET3); /* set IRQ mask */
161  ecx_BWR(context->port, 0x0000, ECT_REG_RXERR , 8 , &zbuf, EC_TIMEOUTRET3); /* reset CRC counters */
162  ecx_BWR(context->port, 0x0000, ECT_REG_FMMU0 , 16 * 3 , &zbuf, EC_TIMEOUTRET3); /* reset FMMU's */
163  ecx_BWR(context->port, 0x0000, ECT_REG_SM0 , 8 * 4 , &zbuf, EC_TIMEOUTRET3); /* reset SyncM */
164  b = 0x00;
165  ecx_BWR(context->port, 0x0000, ECT_REG_DCSYNCACT , sizeof(b) , &b, EC_TIMEOUTRET3); /* reset activation register */
166  ecx_BWR(context->port, 0x0000, ECT_REG_DCSYSTIME , 4 , &zbuf, EC_TIMEOUTRET3); /* reset system time+ofs */
167  w = htoes(0x1000);
168  ecx_BWR(context->port, 0x0000, ECT_REG_DCSPEEDCNT , sizeof(w) , &w, EC_TIMEOUTRET3); /* DC speedstart */
169  w = htoes(0x0c00);
170  ecx_BWR(context->port, 0x0000, ECT_REG_DCTIMEFILT , sizeof(w) , &w, EC_TIMEOUTRET3); /* DC filt expr */
171  b = 0x00;
172  ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS , sizeof(b) , &b, EC_TIMEOUTRET3); /* Ignore Alias register */
174  ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL , sizeof(b) , &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */
175  b = 2;
176  ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG , sizeof(b) , &b, EC_TIMEOUTRET3); /* force Eeprom from PDI */
177  b = 0;
178  ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG , sizeof(b) , &b, EC_TIMEOUTRET3); /* set Eeprom to master */
179 }
180 
181 #ifdef EC_VER1
183 {
184  int cindex;
185  ec_slavet *csl;
186 
187  csl = &(context->slavelist[slave]);
188  cindex = ec_findconfig( csl->eep_man, csl->eep_id );
189  csl->configindex= cindex;
190  /* slave found in configuration table ? */
191  if (cindex)
192  {
193  csl->Dtype = ec_configlist[cindex].Dtype;
194  strcpy(csl->name ,ec_configlist[cindex].name);
195  csl->Ibits = ec_configlist[cindex].Ibits;
196  csl->Obits = ec_configlist[cindex].Obits;
197  if (csl->Obits)
198  {
199  csl->FMMU0func = 1;
200  }
201  if (csl->Ibits)
202  {
203  csl->FMMU1func = 2;
204  }
205  csl->FMMU[0].FMMUactive = ec_configlist[cindex].FM0ac;
206  csl->FMMU[1].FMMUactive = ec_configlist[cindex].FM1ac;
207  csl->SM[2].StartAddr = htoes(ec_configlist[cindex].SM2a);
208  csl->SM[2].SMflags = htoel(ec_configlist[cindex].SM2f);
209  /* simple (no mailbox) output slave found ? */
210  if (csl->Obits && !csl->SM[2].StartAddr)
211  {
212  csl->SM[0].StartAddr = htoes(0x0f00);
213  csl->SM[0].SMlength = htoes((csl->Obits + 7) / 8);
214  csl->SM[0].SMflags = htoel(EC_DEFAULTDOSM0);
215  csl->FMMU[0].FMMUactive = 1;
216  csl->FMMU[0].FMMUtype = 2;
217  csl->SMtype[0] = 3;
218  }
219  /* complex output slave */
220  else
221  {
222  csl->SM[2].SMlength = htoes((csl->Obits + 7) / 8);
223  csl->SMtype[2] = 3;
224  }
225  csl->SM[3].StartAddr = htoes(ec_configlist[cindex].SM3a);
226  csl->SM[3].SMflags = htoel(ec_configlist[cindex].SM3f);
227  /* simple (no mailbox) input slave found ? */
228  if (csl->Ibits && !csl->SM[3].StartAddr)
229  {
230  csl->SM[1].StartAddr = htoes(0x1000);
231  csl->SM[1].SMlength = htoes((csl->Ibits + 7) / 8);
232  csl->SM[1].SMflags = htoel(0x00000000);
233  csl->FMMU[1].FMMUactive = 1;
234  csl->FMMU[1].FMMUtype = 1;
235  csl->SMtype[1] = 4;
236  }
237  /* complex input slave */
238  else
239  {
240  csl->SM[3].SMlength = htoes((csl->Ibits + 7) / 8);
241  csl->SMtype[3] = 4;
242  }
243  }
244  return cindex;
245 }
246 #else
247 static int ecx_config_from_table(ecx_contextt *context, uint16 slave)
248 {
249  (void)context;
250  (void)slave;
251  return 0;
252 }
253 #endif
254 
255 /* If slave has SII and same slave ID done before, use previous data.
256  * This is safe because SII is constant for same slave ID.
257  */
259 {
260  int i, nSM;
261  if ((slave > 1) && (*(context->slavecount) > 0))
262  {
263  i = 1;
264  while(((context->slavelist[i].eep_man != context->slavelist[slave].eep_man) ||
265  (context->slavelist[i].eep_id != context->slavelist[slave].eep_id ) ||
266  (context->slavelist[i].eep_rev != context->slavelist[slave].eep_rev)) &&
267  (i < slave))
268  {
269  i++;
270  }
271  if(i < slave)
272  {
273  context->slavelist[slave].CoEdetails = context->slavelist[i].CoEdetails;
274  context->slavelist[slave].FoEdetails = context->slavelist[i].FoEdetails;
275  context->slavelist[slave].EoEdetails = context->slavelist[i].EoEdetails;
276  context->slavelist[slave].SoEdetails = context->slavelist[i].SoEdetails;
277  if(context->slavelist[i].blockLRW > 0)
278  {
279  context->slavelist[slave].blockLRW = 1;
280  context->slavelist[0].blockLRW++;
281  }
282  context->slavelist[slave].Ebuscurrent = context->slavelist[i].Ebuscurrent;
283  context->slavelist[0].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
284  memcpy(context->slavelist[slave].name, context->slavelist[i].name, EC_MAXNAME + 1);
285  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
286  {
287  context->slavelist[slave].SM[nSM].StartAddr = context->slavelist[i].SM[nSM].StartAddr;
288  context->slavelist[slave].SM[nSM].SMlength = context->slavelist[i].SM[nSM].SMlength;
289  context->slavelist[slave].SM[nSM].SMflags = context->slavelist[i].SM[nSM].SMflags;
290  }
291  context->slavelist[slave].FMMU0func = context->slavelist[i].FMMU0func;
292  context->slavelist[slave].FMMU1func = context->slavelist[i].FMMU1func;
293  context->slavelist[slave].FMMU2func = context->slavelist[i].FMMU2func;
294  context->slavelist[slave].FMMU3func = context->slavelist[i].FMMU3func;
295  EC_PRINT("Copy SII slave %d from %d.\n", slave, i);
296  return 1;
297  }
298  }
299  return 0;
300 }
301 
308 int ecx_config_init(ecx_contextt *context, uint8 usetable)
309 {
310  uint16 slave, ADPh, configadr, ssigen;
311  uint16 topology, estat;
312  int16 topoc, slavec, aliasadr;
313  uint8 b,h;
314  uint8 SMc;
315  uint32 eedat;
316  int wkc, cindex, nSM;
317  uint16 val16;
318 
319  EC_PRINT("ec_config_init %d\n",usetable);
320  ecx_init_context(context);
321  wkc = ecx_detect_slaves(context);
322  if (wkc > 0)
323  {
324  ecx_set_slaves_to_default(context);
325  for (slave = 1; slave <= *(context->slavecount); slave++)
326  {
327  ADPh = (uint16)(1 - slave);
328  val16 = ecx_APRDw(context->port, ADPh, ECT_REG_PDICTL, EC_TIMEOUTRET3); /* read interface type of slave */
329  context->slavelist[slave].Itype = etohs(val16);
330  /* a node offset is used to improve readability of network frames */
331  /* this has no impact on the number of addressable slaves (auto wrap around) */
332  ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(slave + EC_NODEOFFSET) , EC_TIMEOUTRET3); /* set node address of slave */
333  if (slave == 1)
334  {
335  b = 1; /* kill non ecat frames for first slave */
336  }
337  else
338  {
339  b = 0; /* pass all frames for following slaves */
340  }
341  ecx_APWRw(context->port, ADPh, ECT_REG_DLCTL, htoes(b), EC_TIMEOUTRET3); /* set non ecat frame behaviour */
342  configadr = ecx_APRDw(context->port, ADPh, ECT_REG_STADR, EC_TIMEOUTRET3);
343  configadr = etohs(configadr);
344  context->slavelist[slave].configadr = configadr;
345  ecx_FPRD(context->port, configadr, ECT_REG_ALIAS, sizeof(aliasadr), &aliasadr, EC_TIMEOUTRET3);
346  context->slavelist[slave].aliasadr = etohs(aliasadr);
347  ecx_FPRD(context->port, configadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET3);
348  estat = etohs(estat);
349  if (estat & EC_ESTAT_R64) /* check if slave can read 8 byte chunks */
350  {
351  context->slavelist[slave].eep_8byte = 1;
352  }
353  ecx_readeeprom1(context, slave, ECT_SII_MANUF); /* Manuf */
354  }
355  for (slave = 1; slave <= *(context->slavecount); slave++)
356  {
357  eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* Manuf */
358  context->slavelist[slave].eep_man = etohl(eedat);
359  ecx_readeeprom1(context, slave, ECT_SII_ID); /* ID */
360  }
361  for (slave = 1; slave <= *(context->slavecount); slave++)
362  {
363  eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* ID */
364  context->slavelist[slave].eep_id = etohl(eedat);
365  ecx_readeeprom1(context, slave, ECT_SII_REV); /* revision */
366  }
367  for (slave = 1; slave <= *(context->slavecount); slave++)
368  {
369  eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* revision */
370  context->slavelist[slave].eep_rev = etohl(eedat);
371  ecx_readeeprom1(context, slave, ECT_SII_RXMBXADR); /* write mailbox address + mailboxsize */
372  }
373  for (slave = 1; slave <= *(context->slavecount); slave++)
374  {
375  eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* write mailbox address and mailboxsize */
376  context->slavelist[slave].mbx_wo = (uint16)LO_WORD(etohl(eedat));
377  context->slavelist[slave].mbx_l = (uint16)HI_WORD(etohl(eedat));
378  if (context->slavelist[slave].mbx_l > 0)
379  {
380  ecx_readeeprom1(context, slave, ECT_SII_TXMBXADR); /* read mailbox offset */
381  }
382  }
383  for (slave = 1; slave <= *(context->slavecount); slave++)
384  {
385  if (context->slavelist[slave].mbx_l > 0)
386  {
387  eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* read mailbox offset */
388  context->slavelist[slave].mbx_ro = (uint16)LO_WORD(etohl(eedat)); /* read mailbox offset */
389  context->slavelist[slave].mbx_rl = (uint16)HI_WORD(etohl(eedat)); /*read mailbox length */
390  if (context->slavelist[slave].mbx_rl == 0)
391  {
392  context->slavelist[slave].mbx_rl = context->slavelist[slave].mbx_l;
393  }
394  ecx_readeeprom1(context, slave, ECT_SII_MBXPROTO);
395  }
396  configadr = context->slavelist[slave].configadr;
397  val16 = ecx_FPRDw(context->port, configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET3);
398  if ((etohs(val16) & 0x04) > 0) /* Support DC? */
399  {
400  context->slavelist[slave].hasdc = TRUE;
401  }
402  else
403  {
404  context->slavelist[slave].hasdc = FALSE;
405  }
406  topology = ecx_FPRDw(context->port, configadr, ECT_REG_DLSTAT, EC_TIMEOUTRET3); /* extract topology from DL status */
407  topology = etohs(topology);
408  h = 0;
409  b = 0;
410  if ((topology & 0x0300) == 0x0200) /* port0 open and communication established */
411  {
412  h++;
413  b |= 0x01;
414  }
415  if ((topology & 0x0c00) == 0x0800) /* port1 open and communication established */
416  {
417  h++;
418  b |= 0x02;
419  }
420  if ((topology & 0x3000) == 0x2000) /* port2 open and communication established */
421  {
422  h++;
423  b |= 0x04;
424  }
425  if ((topology & 0xc000) == 0x8000) /* port3 open and communication established */
426  {
427  h++;
428  b |= 0x08;
429  }
430  /* ptype = Physical type*/
431  val16 = ecx_FPRDw(context->port, configadr, ECT_REG_PORTDES, EC_TIMEOUTRET3);
432  context->slavelist[slave].ptype = LO_BYTE(etohs(val16));
433  context->slavelist[slave].topology = h;
434  context->slavelist[slave].activeports = b;
435  /* 0=no links, not possible */
436  /* 1=1 link , end of line */
437  /* 2=2 links , one before and one after */
438  /* 3=3 links , split point */
439  /* 4=4 links , cross point */
440  /* search for parent */
441  context->slavelist[slave].parent = 0; /* parent is master */
442  if (slave > 1)
443  {
444  topoc = 0;
445  slavec = slave - 1;
446  do
447  {
448  topology = context->slavelist[slavec].topology;
449  if (topology == 1)
450  {
451  topoc--; /* endpoint found */
452  }
453  if (topology == 3)
454  {
455  topoc++; /* split found */
456  }
457  if (topology == 4)
458  {
459  topoc += 2; /* cross found */
460  }
461  if (((topoc >= 0) && (topology > 1)) ||
462  (slavec == 1)) /* parent found */
463  {
464  context->slavelist[slave].parent = slavec;
465  slavec = 1;
466  }
467  slavec--;
468  }
469  while (slavec > 0);
470  }
471  (void)ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE); //* check state change Init */
472 
473  /* set default mailbox configuration if slave has mailbox */
474  if (context->slavelist[slave].mbx_l>0)
475  {
476  context->slavelist[slave].SMtype[0] = 1;
477  context->slavelist[slave].SMtype[1] = 2;
478  context->slavelist[slave].SMtype[2] = 3;
479  context->slavelist[slave].SMtype[3] = 4;
480  context->slavelist[slave].SM[0].StartAddr = htoes(context->slavelist[slave].mbx_wo);
481  context->slavelist[slave].SM[0].SMlength = htoes(context->slavelist[slave].mbx_l);
482  context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
483  context->slavelist[slave].SM[1].StartAddr = htoes(context->slavelist[slave].mbx_ro);
484  context->slavelist[slave].SM[1].SMlength = htoes(context->slavelist[slave].mbx_rl);
485  context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
486  eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP);
487  context->slavelist[slave].mbx_proto = etohl(eedat);
488  }
489  cindex = 0;
490  /* use configuration table ? */
491  if (usetable == 1)
492  {
493  cindex = ecx_config_from_table(context, slave);
494  }
495  /* slave not in configuration table, find out via SII */
496  if (!cindex && !ecx_lookup_prev_sii(context, slave))
497  {
498  ssigen = ecx_siifind(context, slave, ECT_SII_GENERAL);
499  /* SII general section */
500  if (ssigen)
501  {
502  context->slavelist[slave].CoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x07);
503  context->slavelist[slave].FoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x08);
504  context->slavelist[slave].EoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x09);
505  context->slavelist[slave].SoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x0a);
506  if((ecx_siigetbyte(context, slave, ssigen + 0x0d) & 0x02) > 0)
507  {
508  context->slavelist[slave].blockLRW = 1;
509  context->slavelist[0].blockLRW++;
510  }
511  context->slavelist[slave].Ebuscurrent = ecx_siigetbyte(context, slave, ssigen + 0x0e);
512  context->slavelist[slave].Ebuscurrent += ecx_siigetbyte(context, slave, ssigen + 0x0f) << 8;
513  context->slavelist[0].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
514  }
515  /* SII strings section */
516  if (ecx_siifind(context, slave, ECT_SII_STRING) > 0)
517  {
518  ecx_siistring(context, context->slavelist[slave].name, slave, 1);
519  }
520  /* no name for slave found, use constructed name */
521  else
522  {
523  sprintf(context->slavelist[slave].name, "? M:%8.8x I:%8.8x",
524  (unsigned int)context->slavelist[slave].eep_man,
525  (unsigned int)context->slavelist[slave].eep_id);
526  }
527  /* SII SM section */
528  nSM = ecx_siiSM(context, slave, context->eepSM);
529  if (nSM>0)
530  {
531  context->slavelist[slave].SM[0].StartAddr = htoes(context->eepSM->PhStart);
532  context->slavelist[slave].SM[0].SMlength = htoes(context->eepSM->Plength);
533  context->slavelist[slave].SM[0].SMflags =
534  htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
535  SMc = 1;
536  while ((SMc < EC_MAXSM) && ecx_siiSMnext(context, slave, context->eepSM, SMc))
537  {
538  context->slavelist[slave].SM[SMc].StartAddr = htoes(context->eepSM->PhStart);
539  context->slavelist[slave].SM[SMc].SMlength = htoes(context->eepSM->Plength);
540  context->slavelist[slave].SM[SMc].SMflags =
541  htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
542  SMc++;
543  }
544  }
545  /* SII FMMU section */
546  if (ecx_siiFMMU(context, slave, context->eepFMMU))
547  {
548  if (context->eepFMMU->FMMU0 !=0xff)
549  {
550  context->slavelist[slave].FMMU0func = context->eepFMMU->FMMU0;
551  }
552  if (context->eepFMMU->FMMU1 !=0xff)
553  {
554  context->slavelist[slave].FMMU1func = context->eepFMMU->FMMU1;
555  }
556  if (context->eepFMMU->FMMU2 !=0xff)
557  {
558  context->slavelist[slave].FMMU2func = context->eepFMMU->FMMU2;
559  }
560  if (context->eepFMMU->FMMU3 !=0xff)
561  {
562  context->slavelist[slave].FMMU3func = context->eepFMMU->FMMU3;
563  }
564  }
565  }
566 
567  if (context->slavelist[slave].mbx_l > 0)
568  {
569  if (context->slavelist[slave].SM[0].StartAddr == 0x0000) /* should never happen */
570  {
571  EC_PRINT("Slave %d has no proper mailbox in configuration, try default.\n", slave);
572  context->slavelist[slave].SM[0].StartAddr = htoes(0x1000);
573  context->slavelist[slave].SM[0].SMlength = htoes(0x0080);
574  context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
575  context->slavelist[slave].SMtype[0] = 1;
576  }
577  if (context->slavelist[slave].SM[1].StartAddr == 0x0000) /* should never happen */
578  {
579  EC_PRINT("Slave %d has no proper mailbox out configuration, try default.\n", slave);
580  context->slavelist[slave].SM[1].StartAddr = htoes(0x1080);
581  context->slavelist[slave].SM[1].SMlength = htoes(0x0080);
582  context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
583  context->slavelist[slave].SMtype[1] = 2;
584  }
585  /* program SM0 mailbox in and SM1 mailbox out for slave */
586  /* writing both SM in one datagram will solve timing issue in old NETX */
587  ecx_FPWR(context->port, configadr, ECT_REG_SM0, sizeof(ec_smt) * 2,
588  &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
589  }
590  /* some slaves need eeprom available to PDI in init->preop transition */
591  ecx_eeprom2pdi(context, slave);
592  /* User may override automatic state change */
593  if (context->manualstatechange == 0)
594  {
595  /* request pre_op for slave */
596  ecx_FPWRw(context->port,
597  configadr,
600  EC_TIMEOUTRET3); /* set preop status */
601  }
602  }
603  }
604  return wkc;
605 }
606 
607 /* If slave has SII mapping and same slave ID done before, use previous mapping.
608  * This is safe because SII mapping is constant for same slave ID.
609  */
610 static int ecx_lookup_mapping(ecx_contextt *context, uint16 slave, int *Osize, int *Isize)
611 {
612  int i, nSM;
613  if ((slave > 1) && (*(context->slavecount) > 0))
614  {
615  i = 1;
616  while(((context->slavelist[i].eep_man != context->slavelist[slave].eep_man) ||
617  (context->slavelist[i].eep_id != context->slavelist[slave].eep_id ) ||
618  (context->slavelist[i].eep_rev != context->slavelist[slave].eep_rev)) &&
619  (i < slave))
620  {
621  i++;
622  }
623  if(i < slave)
624  {
625  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
626  {
627  context->slavelist[slave].SM[nSM].SMlength = context->slavelist[i].SM[nSM].SMlength;
628  context->slavelist[slave].SMtype[nSM] = context->slavelist[i].SMtype[nSM];
629  }
630  *Osize = context->slavelist[i].Obits;
631  *Isize = context->slavelist[i].Ibits;
632  context->slavelist[slave].Obits = *Osize;
633  context->slavelist[slave].Ibits = *Isize;
634  EC_PRINT("Copy mapping slave %d from %d.\n", slave, i);
635  return 1;
636  }
637  }
638  return 0;
639 }
640 
641 static int ecx_map_coe_soe(ecx_contextt *context, uint16 slave, int thread_n)
642 {
643  int Isize, Osize;
644  int rval;
645 
646  ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
647 
648  EC_PRINT(" >Slave %d, configadr %x, state %2.2x\n",
649  slave, context->slavelist[slave].configadr, context->slavelist[slave].state);
650 
651  /* execute special slave configuration hook Pre-Op to Safe-OP */
652  if(context->slavelist[slave].PO2SOconfig) /* only if registered */
653  {
654  context->slavelist[slave].PO2SOconfig(slave);
655  }
656  if (context->slavelist[slave].PO2SOconfigx) /* only if registered */
657  {
658  context->slavelist[slave].PO2SOconfigx(context, slave);
659  }
660  /* if slave not found in configlist find IO mapping in slave self */
661  if (!context->slavelist[slave].configindex)
662  {
663  Isize = 0;
664  Osize = 0;
665  if (context->slavelist[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */
666  {
667  rval = 0;
668  if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
669  {
670  /* read PDO mapping via CoE and use Complete Access */
671  rval = ecx_readPDOmapCA(context, slave, thread_n, &Osize, &Isize);
672  }
673  if (!rval) /* CA not available or not succeeded */
674  {
675  /* read PDO mapping via CoE */
676  rval = ecx_readPDOmap(context, slave, &Osize, &Isize);
677  }
678  EC_PRINT(" CoE Osize:%d Isize:%d\n", Osize, Isize);
679  }
680  if ((!Isize && !Osize) && (context->slavelist[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */
681  {
682  /* read AT / MDT mapping via SoE */
683  rval = ecx_readIDNmap(context, slave, &Osize, &Isize);
684  context->slavelist[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
685  context->slavelist[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
686  EC_PRINT(" SoE Osize:%d Isize:%d\n", Osize, Isize);
687  }
688  context->slavelist[slave].Obits = Osize;
689  context->slavelist[slave].Ibits = Isize;
690  }
691 
692  return 1;
693 }
694 
695 static int ecx_map_sii(ecx_contextt *context, uint16 slave)
696 {
697  int Isize, Osize;
698  int nSM;
699  ec_eepromPDOt eepPDO;
700 
701  Osize = context->slavelist[slave].Obits;
702  Isize = context->slavelist[slave].Ibits;
703 
704  if (!Isize && !Osize) /* find PDO in previous slave with same ID */
705  {
706  (void)ecx_lookup_mapping(context, slave, &Osize, &Isize);
707  }
708  if (!Isize && !Osize) /* find PDO mapping by SII */
709  {
710  memset(&eepPDO, 0, sizeof(eepPDO));
711  Isize = (int)ecx_siiPDO(context, slave, &eepPDO, 0);
712  EC_PRINT(" SII Isize:%d\n", Isize);
713  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
714  {
715  if (eepPDO.SMbitsize[nSM] > 0)
716  {
717  context->slavelist[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
718  context->slavelist[slave].SMtype[nSM] = 4;
719  EC_PRINT(" SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
720  }
721  }
722  Osize = (int)ecx_siiPDO(context, slave, &eepPDO, 1);
723  EC_PRINT(" SII Osize:%d\n", Osize);
724  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
725  {
726  if (eepPDO.SMbitsize[nSM] > 0)
727  {
728  context->slavelist[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
729  context->slavelist[slave].SMtype[nSM] = 3;
730  EC_PRINT(" SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
731  }
732  }
733  }
734  context->slavelist[slave].Obits = Osize;
735  context->slavelist[slave].Ibits = Isize;
736  EC_PRINT(" ISIZE:%d %d OSIZE:%d\n",
737  context->slavelist[slave].Ibits, Isize,context->slavelist[slave].Obits);
738 
739  return 1;
740 }
741 
742 static int ecx_map_sm(ecx_contextt *context, uint16 slave)
743 {
744  uint16 configadr;
745  int nSM;
746 
747  configadr = context->slavelist[slave].configadr;
748 
749  EC_PRINT(" SM programming\n");
750  if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[0].StartAddr)
751  {
752  ecx_FPWR(context->port, configadr, ECT_REG_SM0,
753  sizeof(ec_smt), &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
754  EC_PRINT(" SM0 Type:%d StartAddr:%4.4x Flags:%8.8x\n",
755  context->slavelist[slave].SMtype[0],
756  etohs(context->slavelist[slave].SM[0].StartAddr),
757  etohl(context->slavelist[slave].SM[0].SMflags));
758  }
759  if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[1].StartAddr)
760  {
761  ecx_FPWR(context->port, configadr, ECT_REG_SM1,
762  sizeof(ec_smt), &context->slavelist[slave].SM[1], EC_TIMEOUTRET3);
763  EC_PRINT(" SM1 Type:%d StartAddr:%4.4x Flags:%8.8x\n",
764  context->slavelist[slave].SMtype[1],
765  etohs(context->slavelist[slave].SM[1].StartAddr),
766  etohl(context->slavelist[slave].SM[1].SMflags));
767  }
768  /* program SM2 to SMx */
769  for( nSM = 2 ; nSM < EC_MAXSM ; nSM++ )
770  {
771  if (context->slavelist[slave].SM[nSM].StartAddr)
772  {
773  /* check if SM length is zero -> clear enable flag */
774  if( context->slavelist[slave].SM[nSM].SMlength == 0)
775  {
776  context->slavelist[slave].SM[nSM].SMflags =
777  htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) & EC_SMENABLEMASK);
778  }
779  /* if SM length is non zero always set enable flag */
780  else
781  {
782  context->slavelist[slave].SM[nSM].SMflags =
783  htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) | ~EC_SMENABLEMASK);
784  }
785  ecx_FPWR(context->port, configadr, (uint16)(ECT_REG_SM0 + (nSM * sizeof(ec_smt))),
786  sizeof(ec_smt), &context->slavelist[slave].SM[nSM], EC_TIMEOUTRET3);
787  EC_PRINT(" SM%d Type:%d StartAddr:%4.4x Flags:%8.8x\n", nSM,
788  context->slavelist[slave].SMtype[nSM],
789  etohs(context->slavelist[slave].SM[nSM].StartAddr),
790  etohl(context->slavelist[slave].SM[nSM].SMflags));
791  }
792  }
793  if (context->slavelist[slave].Ibits > 7)
794  {
795  context->slavelist[slave].Ibytes = (context->slavelist[slave].Ibits + 7) / 8;
796  }
797  if (context->slavelist[slave].Obits > 7)
798  {
799  context->slavelist[slave].Obytes = (context->slavelist[slave].Obits + 7) / 8;
800  }
801 
802  return 1;
803 }
804 
805 #if EC_MAX_MAPT > 1
806 OSAL_THREAD_FUNC ecx_mapper_thread(void *param)
807 {
808  ecx_mapt_t *maptp;
809  maptp = param;
810  ecx_map_coe_soe(maptp->context, maptp->slave, maptp->thread_n);
811  maptp->running = 0;
812 }
813 
814 static int ecx_find_mapt(void)
815 {
816  int p;
817  p = 0;
818  while((p < EC_MAX_MAPT) && ecx_mapt[p].running)
819  {
820  p++;
821  }
822  if(p < EC_MAX_MAPT)
823  {
824  return p;
825  }
826  else
827  {
828  return -1;
829  }
830 }
831 #endif
832 
833 static int ecx_get_threadcount(void)
834 {
835  int thrc, thrn;
836  thrc = 0;
837  for(thrn = 0 ; thrn < EC_MAX_MAPT ; thrn++)
838  {
839  thrc += ecx_mapt[thrn].running;
840  }
841  return thrc;
842 }
843 
844 static void ecx_config_find_mappings(ecx_contextt *context, uint8 group)
845 {
846  int thrn, thrc;
847  uint16 slave;
848 
849  for (thrn = 0; thrn < EC_MAX_MAPT; thrn++)
850  {
851  ecx_mapt[thrn].running = 0;
852  }
853  /* find CoE and SoE mapping of slaves in multiple threads */
854  for (slave = 1; slave <= *(context->slavecount); slave++)
855  {
856  if (!group || (group == context->slavelist[slave].group))
857  {
858 #if EC_MAX_MAPT > 1
859  /* multi-threaded version */
860  while ((thrn = ecx_find_mapt()) < 0)
861  {
862  osal_usleep(1000);
863  }
864  ecx_mapt[thrn].context = context;
865  ecx_mapt[thrn].slave = slave;
866  ecx_mapt[thrn].thread_n = thrn;
867  ecx_mapt[thrn].running = 1;
868  osal_thread_create(&(ecx_threadh[thrn]), 128000,
869  &ecx_mapper_thread, &(ecx_mapt[thrn]));
870 #else
871  /* serialised version */
872  ecx_map_coe_soe(context, slave, 0);
873 #endif
874  }
875  }
876  /* wait for all threads to finish */
877  do
878  {
879  thrc = ecx_get_threadcount();
880  if (thrc)
881  {
882  osal_usleep(1000);
883  }
884  } while (thrc);
885  /* find SII mapping of slave and program SM */
886  for (slave = 1; slave <= *(context->slavecount); slave++)
887  {
888  if (!group || (group == context->slavelist[slave].group))
889  {
890  ecx_map_sii(context, slave);
891  ecx_map_sm(context, slave);
892  }
893  }
894 }
895 
896 static void ecx_config_create_input_mappings(ecx_contextt *context, void *pIOmap,
897  uint8 group, int16 slave, uint32 * LogAddr, uint8 * BitPos)
898 {
899  int BitCount = 0;
900  int ByteCount = 0;
901  int FMMUsize = 0;
902  int FMMUdone = 0;
903  uint8 SMc = 0;
904  uint16 EndAddr;
905  uint16 SMlength;
906  uint16 configadr;
907  uint8 FMMUc;
908 
909  EC_PRINT(" =Slave %d, INPUT MAPPING\n", slave);
910 
911  configadr = context->slavelist[slave].configadr;
912  FMMUc = context->slavelist[slave].FMMUunused;
913  if (context->slavelist[slave].Obits) /* find free FMMU */
914  {
915  while (context->slavelist[slave].FMMU[FMMUc].LogStart)
916  {
917  FMMUc++;
918  }
919  }
920  /* search for SM that contribute to the input mapping */
921  while ((SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Ibits + 7) / 8)))
922  {
923  EC_PRINT(" FMMU %d\n", FMMUc);
924  while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4))
925  {
926  SMc++;
927  }
928  EC_PRINT(" SM%d\n", SMc);
929  context->slavelist[slave].FMMU[FMMUc].PhysStart =
930  context->slavelist[slave].SM[SMc].StartAddr;
931  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
932  ByteCount += SMlength;
933  BitCount += SMlength * 8;
934  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
935  while ((BitCount < context->slavelist[slave].Ibits) && (SMc < (EC_MAXSM - 1))) /* more SM for input */
936  {
937  SMc++;
938  while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4))
939  {
940  SMc++;
941  }
942  /* if addresses from more SM connect use one FMMU otherwise break up in multiple FMMU */
943  if (etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr)
944  {
945  break;
946  }
947  EC_PRINT(" SM%d\n", SMc);
948  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
949  ByteCount += SMlength;
950  BitCount += SMlength * 8;
951  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
952  }
953 
954  /* bit oriented slave */
955  if (!context->slavelist[slave].Ibytes)
956  {
957  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr);
958  context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos;
959  *BitPos += context->slavelist[slave].Ibits - 1;
960  if (*BitPos > 7)
961  {
962  *LogAddr += 1;
963  *BitPos -= 8;
964  }
965  FMMUsize = *LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
966  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
967  context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos;
968  *BitPos += 1;
969  if (*BitPos > 7)
970  {
971  *LogAddr += 1;
972  *BitPos -= 8;
973  }
974  }
975  /* byte oriented slave */
976  else
977  {
978  if (*BitPos)
979  {
980  *LogAddr += 1;
981  *BitPos = 0;
982  }
983  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr);
984  context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos;
985  *BitPos = 7;
986  FMMUsize = ByteCount;
987  if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Ibytes)
988  {
989  FMMUsize = context->slavelist[slave].Ibytes - FMMUdone;
990  }
991  *LogAddr += FMMUsize;
992  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
993  context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos;
994  *BitPos = 0;
995  }
996  FMMUdone += FMMUsize;
997  if (context->slavelist[slave].FMMU[FMMUc].LogLength)
998  {
999  context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
1000  context->slavelist[slave].FMMU[FMMUc].FMMUtype = 1;
1001  context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
1002  /* program FMMU for input */
1003  ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
1004  sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
1005  /* add one for an input FMMU */
1006  context->grouplist[group].inputsWKC++;
1007  }
1008  if (!context->slavelist[slave].inputs)
1009  {
1010  if (group)
1011  {
1012  context->slavelist[slave].inputs =
1013  (uint8 *)(pIOmap) +
1014  etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) -
1015  context->grouplist[group].logstartaddr;
1016  }
1017  else
1018  {
1019  context->slavelist[slave].inputs =
1020  (uint8 *)(pIOmap) +
1021  etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
1022  }
1023  context->slavelist[slave].Istartbit =
1024  context->slavelist[slave].FMMU[FMMUc].LogStartbit;
1025  EC_PRINT(" Inputs %p startbit %d\n",
1026  context->slavelist[slave].inputs,
1027  context->slavelist[slave].Istartbit);
1028  }
1029  FMMUc++;
1030  }
1031  context->slavelist[slave].FMMUunused = FMMUc;
1032 }
1033 
1034 static void ecx_config_create_output_mappings(ecx_contextt *context, void *pIOmap,
1035  uint8 group, int16 slave, uint32 * LogAddr, uint8 * BitPos)
1036 {
1037  int BitCount = 0;
1038  int ByteCount = 0;
1039  int FMMUsize = 0;
1040  int FMMUdone = 0;
1041  uint8 SMc = 0;
1042  uint16 EndAddr;
1043  uint16 SMlength;
1044  uint16 configadr;
1045  uint8 FMMUc;
1046 
1047  EC_PRINT(" OUTPUT MAPPING\n");
1048 
1049  FMMUc = context->slavelist[slave].FMMUunused;
1050  configadr = context->slavelist[slave].configadr;
1051 
1052  /* search for SM that contribute to the output mapping */
1053  while ((SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Obits + 7) / 8)))
1054  {
1055  EC_PRINT(" FMMU %d\n", FMMUc);
1056  while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3))
1057  {
1058  SMc++;
1059  }
1060  EC_PRINT(" SM%d\n", SMc);
1061  context->slavelist[slave].FMMU[FMMUc].PhysStart =
1062  context->slavelist[slave].SM[SMc].StartAddr;
1063  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
1064  ByteCount += SMlength;
1065  BitCount += SMlength * 8;
1066  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
1067  while ((BitCount < context->slavelist[slave].Obits) && (SMc < (EC_MAXSM - 1))) /* more SM for output */
1068  {
1069  SMc++;
1070  while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3))
1071  {
1072  SMc++;
1073  }
1074  /* if addresses from more SM connect use one FMMU otherwise break up in multiple FMMU */
1075  if (etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr)
1076  {
1077  break;
1078  }
1079  EC_PRINT(" SM%d\n", SMc);
1080  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
1081  ByteCount += SMlength;
1082  BitCount += SMlength * 8;
1083  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
1084  }
1085 
1086  /* bit oriented slave */
1087  if (!context->slavelist[slave].Obytes)
1088  {
1089  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr);
1090  context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos;
1091  *BitPos += context->slavelist[slave].Obits - 1;
1092  if (*BitPos > 7)
1093  {
1094  *LogAddr += 1;
1095  *BitPos -= 8;
1096  }
1097  FMMUsize = *LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
1098  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
1099  context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos;
1100  *BitPos += 1;
1101  if (*BitPos > 7)
1102  {
1103  *LogAddr += 1;
1104  *BitPos -= 8;
1105  }
1106  }
1107  /* byte oriented slave */
1108  else
1109  {
1110  if (*BitPos)
1111  {
1112  *LogAddr += 1;
1113  *BitPos = 0;
1114  }
1115  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr);
1116  context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos;
1117  *BitPos = 7;
1118  FMMUsize = ByteCount;
1119  if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Obytes)
1120  {
1121  FMMUsize = context->slavelist[slave].Obytes - FMMUdone;
1122  }
1123  *LogAddr += FMMUsize;
1124  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
1125  context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos;
1126  *BitPos = 0;
1127  }
1128  FMMUdone += FMMUsize;
1129  context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
1130  context->slavelist[slave].FMMU[FMMUc].FMMUtype = 2;
1131  context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
1132  /* program FMMU for output */
1133  ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
1134  sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
1135  context->grouplist[group].outputsWKC++;
1136  if (!context->slavelist[slave].outputs)
1137  {
1138  if (group)
1139  {
1140  context->slavelist[slave].outputs =
1141  (uint8 *)(pIOmap) +
1142  etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) -
1143  context->grouplist[group].logstartaddr;
1144  }
1145  else
1146  {
1147  context->slavelist[slave].outputs =
1148  (uint8 *)(pIOmap) +
1149  etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
1150  }
1151  context->slavelist[slave].Ostartbit =
1152  context->slavelist[slave].FMMU[FMMUc].LogStartbit;
1153  EC_PRINT(" slave %d Outputs %p startbit %d\n",
1154  slave,
1155  context->slavelist[slave].outputs,
1156  context->slavelist[slave].Ostartbit);
1157  }
1158  FMMUc++;
1159  }
1160  context->slavelist[slave].FMMUunused = FMMUc;
1161 }
1162 
1172 int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
1173 {
1174  uint16 slave, configadr;
1175  uint8 BitPos;
1176  uint32 LogAddr = 0;
1177  uint32 oLogAddr = 0;
1178  uint32 diff;
1179  uint16 currentsegment = 0;
1180  uint32 segmentsize = 0;
1181 
1182  if ((*(context->slavecount) > 0) && (group < context->maxgroup))
1183  {
1184  EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group);
1185  LogAddr = context->grouplist[group].logstartaddr;
1186  oLogAddr = LogAddr;
1187  BitPos = 0;
1188  context->grouplist[group].nsegments = 0;
1189  context->grouplist[group].outputsWKC = 0;
1190  context->grouplist[group].inputsWKC = 0;
1191 
1192  /* Find mappings and program syncmanagers */
1193  ecx_config_find_mappings(context, group);
1194 
1195  /* do output mapping of slave and program FMMUs */
1196  for (slave = 1; slave <= *(context->slavecount); slave++)
1197  {
1198  configadr = context->slavelist[slave].configadr;
1199 
1200  if (!group || (group == context->slavelist[slave].group))
1201  {
1202  /* create output mapping */
1203  if (context->slavelist[slave].Obits)
1204  {
1205  ecx_config_create_output_mappings (context, pIOmap, group, slave, &LogAddr, &BitPos);
1206  diff = LogAddr - oLogAddr;
1207  oLogAddr = LogAddr;
1208  if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
1209  {
1210  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
1211  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
1212  {
1213  currentsegment++;
1214  segmentsize = diff;
1215  }
1216  }
1217  else
1218  {
1219  segmentsize += diff;
1220  }
1221  }
1222  }
1223  }
1224  if (BitPos)
1225  {
1226  LogAddr++;
1227  oLogAddr = LogAddr;
1228  BitPos = 0;
1229  if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
1230  {
1231  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
1232  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
1233  {
1234  currentsegment++;
1235  segmentsize = 1;
1236  }
1237  }
1238  else
1239  {
1240  segmentsize += 1;
1241  }
1242  }
1243  context->grouplist[group].outputs = pIOmap;
1244  context->grouplist[group].Obytes = LogAddr - context->grouplist[group].logstartaddr;
1245  context->grouplist[group].nsegments = currentsegment + 1;
1246  context->grouplist[group].Isegment = currentsegment;
1247  context->grouplist[group].Ioffset = segmentsize;
1248  if (!group)
1249  {
1250  context->slavelist[0].outputs = pIOmap;
1251  context->slavelist[0].Obytes = LogAddr -
1252  context->grouplist[group].logstartaddr; /* store output bytes in master record */
1253  }
1254 
1255  /* do input mapping of slave and program FMMUs */
1256  for (slave = 1; slave <= *(context->slavecount); slave++)
1257  {
1258  configadr = context->slavelist[slave].configadr;
1259  if (!group || (group == context->slavelist[slave].group))
1260  {
1261  /* create input mapping */
1262  if (context->slavelist[slave].Ibits)
1263  {
1264 
1265  ecx_config_create_input_mappings(context, pIOmap, group, slave, &LogAddr, &BitPos);
1266  diff = LogAddr - oLogAddr;
1267  oLogAddr = LogAddr;
1268  if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
1269  {
1270  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
1271  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
1272  {
1273  currentsegment++;
1274  segmentsize = diff;
1275  }
1276  }
1277  else
1278  {
1279  segmentsize += diff;
1280  }
1281  }
1282 
1283  ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */
1284  /* User may override automatic state change */
1285  if (context->manualstatechange == 0)
1286  {
1287  /* request safe_op for slave */
1288  ecx_FPWRw(context->port,
1289  configadr,
1290  ECT_REG_ALCTL,
1292  EC_TIMEOUTRET3); /* set safeop status */
1293  }
1294  if (context->slavelist[slave].blockLRW)
1295  {
1296  context->grouplist[group].blockLRW++;
1297  }
1298  context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
1299  }
1300  }
1301  if (BitPos)
1302  {
1303  LogAddr++;
1304  oLogAddr = LogAddr;
1305  BitPos = 0;
1306  if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
1307  {
1308  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
1309  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
1310  {
1311  currentsegment++;
1312  segmentsize = 1;
1313  }
1314  }
1315  else
1316  {
1317  segmentsize += 1;
1318  }
1319  }
1320  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
1321  context->grouplist[group].nsegments = currentsegment + 1;
1322  context->grouplist[group].inputs = (uint8 *)(pIOmap) + context->grouplist[group].Obytes;
1323  context->grouplist[group].Ibytes = LogAddr -
1324  context->grouplist[group].logstartaddr -
1325  context->grouplist[group].Obytes;
1326  if (!group)
1327  {
1328  context->slavelist[0].inputs = (uint8 *)(pIOmap) + context->slavelist[0].Obytes;
1329  context->slavelist[0].Ibytes = LogAddr -
1330  context->grouplist[group].logstartaddr -
1331  context->slavelist[0].Obytes; /* store input bytes in master record */
1332  }
1333 
1334  EC_PRINT("IOmapSize %d\n", LogAddr - context->grouplist[group].logstartaddr);
1335 
1336  return (LogAddr - context->grouplist[group].logstartaddr);
1337  }
1338 
1339  return 0;
1340 }
1341 
1350 int ecx_config_overlap_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
1351 {
1352  uint16 slave, configadr;
1353  uint8 BitPos;
1354  uint32 mLogAddr = 0;
1355  uint32 siLogAddr = 0;
1356  uint32 soLogAddr = 0;
1357  uint32 tempLogAddr;
1358  uint32 diff;
1359  uint16 currentsegment = 0;
1360  uint32 segmentsize = 0;
1361 
1362  if ((*(context->slavecount) > 0) && (group < context->maxgroup))
1363  {
1364  EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group);
1365  mLogAddr = context->grouplist[group].logstartaddr;
1366  siLogAddr = mLogAddr;
1367  soLogAddr = mLogAddr;
1368  BitPos = 0;
1369  context->grouplist[group].nsegments = 0;
1370  context->grouplist[group].outputsWKC = 0;
1371  context->grouplist[group].inputsWKC = 0;
1372 
1373  /* Find mappings and program syncmanagers */
1374  ecx_config_find_mappings(context, group);
1375 
1376  /* do IO mapping of slave and program FMMUs */
1377  for (slave = 1; slave <= *(context->slavecount); slave++)
1378  {
1379  configadr = context->slavelist[slave].configadr;
1380  siLogAddr = soLogAddr = mLogAddr;
1381 
1382  if (!group || (group == context->slavelist[slave].group))
1383  {
1384  /* create output mapping */
1385  if (context->slavelist[slave].Obits)
1386  {
1387 
1388  ecx_config_create_output_mappings(context, pIOmap, group,
1389  slave, &soLogAddr, &BitPos);
1390  if (BitPos)
1391  {
1392  soLogAddr++;
1393  BitPos = 0;
1394  }
1395  }
1396 
1397  /* create input mapping */
1398  if (context->slavelist[slave].Ibits)
1399  {
1400  ecx_config_create_input_mappings(context, pIOmap, group,
1401  slave, &siLogAddr, &BitPos);
1402  if (BitPos)
1403  {
1404  siLogAddr++;
1405  BitPos = 0;
1406  }
1407  }
1408 
1409  tempLogAddr = (siLogAddr > soLogAddr) ? siLogAddr : soLogAddr;
1410  diff = tempLogAddr - mLogAddr;
1411  mLogAddr = tempLogAddr;
1412 
1413  if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
1414  {
1415  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
1416  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
1417  {
1418  currentsegment++;
1419  segmentsize = diff;
1420  }
1421  }
1422  else
1423  {
1424  segmentsize += diff;
1425  }
1426 
1427  ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */
1428  /* User may override automatic state change */
1429  if (context->manualstatechange == 0)
1430  {
1431  /* request safe_op for slave */
1432  ecx_FPWRw(context->port,
1433  configadr,
1434  ECT_REG_ALCTL,
1436  EC_TIMEOUTRET3);
1437  }
1438  if (context->slavelist[slave].blockLRW)
1439  {
1440  context->grouplist[group].blockLRW++;
1441  }
1442  context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
1443 
1444  }
1445  }
1446 
1447  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
1448  context->grouplist[group].nsegments = currentsegment + 1;
1449  context->grouplist[group].Isegment = 0;
1450  context->grouplist[group].Ioffset = 0;
1451 
1452  context->grouplist[group].Obytes = soLogAddr - context->grouplist[group].logstartaddr;
1453  context->grouplist[group].Ibytes = siLogAddr - context->grouplist[group].logstartaddr;
1454  context->grouplist[group].outputs = pIOmap;
1455  context->grouplist[group].inputs = (uint8 *)pIOmap + context->grouplist[group].Obytes;
1456 
1457  /* Move calculated inputs with OBytes offset*/
1458  for (slave = 1; slave <= *(context->slavecount); slave++)
1459  {
1460  context->slavelist[slave].inputs += context->grouplist[group].Obytes;
1461  }
1462 
1463  if (!group)
1464  {
1465  /* store output bytes in master record */
1466  context->slavelist[0].outputs = pIOmap;
1467  context->slavelist[0].Obytes = soLogAddr - context->grouplist[group].logstartaddr;
1468  context->slavelist[0].inputs = (uint8 *)pIOmap + context->slavelist[0].Obytes;
1469  context->slavelist[0].Ibytes = siLogAddr - context->grouplist[group].logstartaddr;
1470  }
1471 
1472  EC_PRINT("IOmapSize %d\n", context->grouplist[group].Obytes + context->grouplist[group].Ibytes);
1473 
1474  return (context->grouplist[group].Obytes + context->grouplist[group].Ibytes);
1475  }
1476 
1477  return 0;
1478 }
1479 
1480 
1488 int ecx_recover_slave(ecx_contextt *context, uint16 slave, int timeout)
1489 {
1490  int rval;
1491  int wkc;
1492  uint16 ADPh, configadr, readadr;
1493 
1494  rval = 0;
1495  configadr = context->slavelist[slave].configadr;
1496  ADPh = (uint16)(1 - slave);
1497  /* check if we found another slave than the requested */
1498  readadr = 0xfffe;
1499  wkc = ecx_APRD(context->port, ADPh, ECT_REG_STADR, sizeof(readadr), &readadr, timeout);
1500  /* correct slave found, finished */
1501  if(readadr == configadr)
1502  {
1503  return 1;
1504  }
1505  /* only try if no config address*/
1506  if( (wkc > 0) && (readadr == 0))
1507  {
1508  /* clear possible slaves at EC_TEMPNODE */
1509  ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
1510  /* set temporary node address of slave */
1511  if(ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(EC_TEMPNODE) , timeout) <= 0)
1512  {
1513  ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
1514  return 0; /* slave fails to respond */
1515  }
1516 
1517  context->slavelist[slave].configadr = EC_TEMPNODE; /* temporary config address */
1518  ecx_eeprom2master(context, slave); /* set Eeprom control to master */
1519 
1520  /* check if slave is the same as configured before */
1521  if ((ecx_FPRDw(context->port, EC_TEMPNODE, ECT_REG_ALIAS, timeout) ==
1522  htoes(context->slavelist[slave].aliasadr)) &&
1523  (ecx_readeeprom(context, slave, ECT_SII_ID, EC_TIMEOUTEEP) ==
1524  htoel(context->slavelist[slave].eep_id)) &&
1525  (ecx_readeeprom(context, slave, ECT_SII_MANUF, EC_TIMEOUTEEP) ==
1526  htoel(context->slavelist[slave].eep_man)) &&
1527  (ecx_readeeprom(context, slave, ECT_SII_REV, EC_TIMEOUTEEP) ==
1528  htoel(context->slavelist[slave].eep_rev)))
1529  {
1530  rval = ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(configadr) , timeout);
1531  context->slavelist[slave].configadr = configadr;
1532  }
1533  else
1534  {
1535  /* slave is not the expected one, remove config address*/
1536  ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , timeout);
1537  context->slavelist[slave].configadr = configadr;
1538  }
1539  }
1540 
1541  return rval;
1542 }
1543 
1551 int ecx_reconfig_slave(ecx_contextt *context, uint16 slave, int timeout)
1552 {
1553  int state, nSM, FMMUc;
1554  uint16 configadr;
1555 
1556  configadr = context->slavelist[slave].configadr;
1557  if (ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_INIT) , timeout) <= 0)
1558  {
1559  return 0;
1560  }
1561  state = 0;
1562  ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */
1563  /* check state change init */
1564  state = ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE);
1565  if(state == EC_STATE_INIT)
1566  {
1567  /* program all enabled SM */
1568  for( nSM = 0 ; nSM < EC_MAXSM ; nSM++ )
1569  {
1570  if (context->slavelist[slave].SM[nSM].StartAddr)
1571  {
1572  ecx_FPWR(context->port, configadr, (uint16)(ECT_REG_SM0 + (nSM * sizeof(ec_smt))),
1573  sizeof(ec_smt), &context->slavelist[slave].SM[nSM], timeout);
1574  }
1575  }
1576  ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP) , timeout);
1577  state = ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
1578  if( state == EC_STATE_PRE_OP)
1579  {
1580  /* execute special slave configuration hook Pre-Op to Safe-OP */
1581  if(context->slavelist[slave].PO2SOconfig) /* only if registered */
1582  {
1583  context->slavelist[slave].PO2SOconfig(slave);
1584  }
1585  ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , timeout); /* set safeop status */
1586  state = ecx_statecheck(context, slave, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE); /* check state change safe-op */
1587  /* program configured FMMU */
1588  for( FMMUc = 0 ; FMMUc < context->slavelist[slave].FMMUunused ; FMMUc++ )
1589  {
1590  ecx_FPWR(context->port, configadr, (uint16)(ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc)),
1591  sizeof(ec_fmmut), &context->slavelist[slave].FMMU[FMMUc], timeout);
1592  }
1593  }
1594  }
1595 
1596  return state;
1597 }
1598 
1599 #ifdef EC_VER1
1600 
1606 int ec_config_init(uint8 usetable)
1607 {
1608  return ecx_config_init(&ecx_context, usetable);
1609 }
1610 
1619 int ec_config_map_group(void *pIOmap, uint8 group)
1620 {
1621  return ecx_config_map_group(&ecx_context, pIOmap, group);
1622 }
1623 
1632 int ec_config_overlap_map_group(void *pIOmap, uint8 group)
1633 {
1634  return ecx_config_overlap_map_group(&ecx_context, pIOmap, group);
1635 }
1636 
1643 int ec_config_map(void *pIOmap)
1644 {
1645  return ec_config_map_group(pIOmap, 0);
1646 }
1647 
1654 int ec_config_overlap_map(void *pIOmap)
1655 {
1656  return ec_config_overlap_map_group(pIOmap, 0);
1657 }
1658 
1665 int ec_config(uint8 usetable, void *pIOmap)
1666 {
1667  int wkc;
1668  wkc = ec_config_init(usetable);
1669  if (wkc)
1670  {
1671  ec_config_map(pIOmap);
1672  }
1673  return wkc;
1674 }
1675 
1682 int ec_config_overlap(uint8 usetable, void *pIOmap)
1683 {
1684  int wkc;
1685  wkc = ec_config_init(usetable);
1686  if (wkc)
1687  {
1688  ec_config_overlap_map(pIOmap);
1689  }
1690  return wkc;
1691 }
1692 
1700 int ec_recover_slave(uint16 slave, int timeout)
1701 {
1702  return ecx_recover_slave(&ecx_context, slave, timeout);
1703 }
1704 
1712 int ec_reconfig_slave(uint16 slave, int timeout)
1713 {
1714  return ecx_reconfig_slave(&ecx_context, slave, timeout);
1715 }
1716 #endif
ec_smt SM[EC_MAXSM]
Definition: ethercatmain.h:143
#define EC_PRINT
uint16 mbx_ro
Definition: ethercatmain.h:163
int(* PO2SOconfigx)(ecx_contextt *context, uint16 slave)
Definition: ethercatmain.h:233
int ec_reconfig_slave(uint16 slave, int timeout)
static void ecx_config_create_input_mappings(ecx_contextt *context, void *pIOmap, uint8 group, int16 slave, uint32 *LogAddr, uint8 *BitPos)
static int ecx_lookup_mapping(ecx_contextt *context, uint16 slave, int *Osize, int *Isize)
uint16 slave
void ecx_init_context(ecx_contextt *context)
ec_eepromFMMUt * eepFMMU
Definition: ethercatmain.h:425
int ecx_detect_slaves(ecx_contextt *context)
int ecx_reconfig_slave(ecx_contextt *context, uint16 slave, int timeout)
uint8 ecx_siigetbyte(ecx_contextt *context, uint16 slave, uint16 address)
Definition: ethercatmain.c:334
uint16 outputsWKC
Definition: ethercatmain.h:266
#define EC_TIMEOUTSTATE
Definition: ethercattype.h:76
#define EC_SMENABLEMASK
Definition: ethercatmain.h:101
#define OSAL_THREAD_FUNC
uint16 aliasadr
Definition: ethercatmain.h:115
uint8 topology
Definition: ethercatmain.h:173
uint32 Ibytes
Definition: ethercatmain.h:137
#define htoel(A)
Definition: ethercattype.h:534
static void ecx_config_find_mappings(ecx_contextt *context, uint8 group)
uint16 PhStart
Definition: ethercatmain.h:291
int ecx_readIDNmap(ecx_contextt *context, uint16 slave, int *Osize, int *Isize)
Definition: ethercatsoe.c:312
#define ECT_MBXPROT_SOE
Definition: ethercatmain.h:91
#define EC_TIMEOUTSAFE
Definition: ethercattype.h:68
uint8 * outputs
Definition: ethercatmain.h:131
uint8_t uint8
Definition: osal.h:28
uint16 ecx_statecheck(ecx_contextt *context, uint16 slave, uint16 reqstate, int timeout)
Definition: ethercatmain.c:862
uint8 FoEdetails
Definition: ethercatmain.h:215
int ecx_APWRw(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 data, int timeout)
Definition: ethercatbase.c:384
#define EC_MAXEEPBUF
Definition: ethercattype.h:80
int16 Ebuscurrent
Definition: ethercatmain.h:221
uint8 FMMU2func
Definition: ethercatmain.h:153
#define EC_FIRSTDCDATAGRAM
Definition: ethercattype.h:56
uint16 Dtype
Definition: ethercatmain.h:125
int ec_recover_slave(uint16 slave, int timeout)
uint32 Obytes
Definition: ethercatmain.h:129
uint32 eep_rev
Definition: ethercatmain.h:121
uint16 mbx_rl
Definition: ethercatmain.h:161
ec_fmmut FMMU[EC_MAXFMMU]
Definition: ethercatmain.h:147
int ecx_FPWRw(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 data, int timeout)
Definition: ethercatbase.c:421
#define EC_TEMPNODE
uint16 state
Definition: ethercatmain.h:109
void ecx_siistring(ecx_contextt *context, char *str, uint16 slave, uint16 Sn)
Definition: ethercatmain.c:445
int ecx_FPWR(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:399
static int ecx_map_sm(ecx_contextt *context, uint16 slave)
uint16 configindex
Definition: ethercatmain.h:205
uint32 eep_id
Definition: ethercatmain.h:119
uint8 * outputs
Definition: ethercatmain.h:246
uint16_t uint16
Definition: osal.h:29
uint8 group
Definition: ethercatmain.h:225
uint8 SMtype[EC_MAXSM]
Definition: ethercatmain.h:145
int ec_config_overlap(uint8 usetable, void *pIOmap)
uint16 nsegments
Definition: ethercatmain.h:260
int ecx_eeprom2master(ecx_contextt *context, uint16 slave)
General typedefs and defines for EtherCAT.
uint16 parent
Definition: ethercatmain.h:179
#define etohs(A)
Definition: ethercattype.h:536
#define EC_CONFIGEND
Headerfile for ethercatcoe.c.
uint16 ecx_siiFMMU(ecx_contextt *context, uint16 slave, ec_eepromFMMUt *FMMU)
Definition: ethercatmain.c:503
#define TRUE
Definition: osal.h:19
uint8 Istartbit
Definition: ethercatmain.h:141
uint16 Ibits
Definition: ethercatmain.h:135
uint32 ecx_readeeprom(ecx_contextt *context, uint16 slave, uint16 eeproma, int timeout)
int ec_config_map(void *pIOmap)
int ecx_FPRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:318
#define OSAL_THREAD_HANDLE
int ec_config_overlap_map(void *pIOmap)
uint8 blockLRW
Definition: ethercatmain.h:258
uint8 CoEdetails
Definition: ethercatmain.h:213
static void ecx_set_slaves_to_default(ecx_contextt *context)
#define EC_MAXSM
Definition: ethercatmain.h:35
ecx_portt * port
Definition: ethercatmain.h:387
uint8 Activate
Definition: ethercatmain.h:295
uint32 IOsegment[EC_MAXIOSEGMENTS]
Definition: ethercatmain.h:272
uint16 ecx_siiSMnext(ecx_contextt *context, uint16 slave, ec_eepromSMt *SM, uint16 n)
Definition: ethercatmain.c:580
static int ecx_map_sii(ecx_contextt *context, uint16 slave)
ec_groupt * grouplist
Definition: ethercatmain.h:395
int ec_config_overlap_map_group(void *pIOmap, uint8 group)
PACKED_END PACKED_BEGIN struct PACKED ec_sm ec_smt
int ecx_config_init(ecx_contextt *context, uint8 usetable)
int ec_findconfig(uint32 man, uint32 id)
#define ECT_MBXPROT_COE
Definition: ethercatmain.h:89
char name[EC_MAXNAME+1]
Definition: ethercatmain.h:235
int ecx_BRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:185
int ecx_recover_slave(ecx_contextt *context, uint16 slave, int timeout)
uint16 SMbitsize[EC_MAXSM]
Definition: ethercatmain.h:308
uint32 ecx_readeeprom2(ecx_contextt *context, uint16 slave, int timeout)
DEPRECATED Configuration list of known EtherCAT slave devices.
uint16 configadr
Definition: ethercatmain.h:113
static int ecx_config_from_table(ecx_contextt *context, uint16 slave)
ec_eepromSMt * eepSM
Definition: ethercatmain.h:423
int osal_usleep(uint32 usec)
Definition: erika/osal.c:22
int osal_thread_create(void *thandle, int stacksize, void *func, void *param)
Definition: linux/osal.c:102
uint8 blockLRW
Definition: ethercatmain.h:223
int slave
Definition: aliastool.c:44
#define FALSE
Definition: osal.h:22
Headerfile for ethercatsoe.c.
uint32 logstartaddr
Definition: ethercatmain.h:242
uint16 Itype
Definition: ethercatmain.h:123
#define LO_BYTE(w)
Definition: ethercattype.h:514
uint32 Ibytes
Definition: ethercatmain.h:248
uint16 Plength
Definition: ethercatmain.h:292
int ecx_BWR(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:158
ecx_mapt_t ecx_mapt[EC_MAX_MAPT]
#define EC_MAX_MAPT
Definition: ethercatmain.h:41
#define EC_NODEOFFSET
#define EC_TIMEOUTEEP
Definition: ethercattype.h:70
#define EC_LOGGROUPOFFSET
Definition: ethercattype.h:84
static int ecx_map_coe_soe(ecx_contextt *context, uint16 slave, int thread_n)
uint32 Obytes
Definition: ethercatmain.h:244
int ecx_APRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:217
int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
uint8 EoEdetails
Definition: ethercatmain.h:217
#define HI_WORD(l)
Definition: ethercattype.h:520
ec_configlist_t ec_configlist[]
uint8 FMMU1func
Definition: ethercatmain.h:151
void ecx_readeeprom1(ecx_contextt *context, uint16 slave, uint16 eeproma)
uint8 eep_8byte
Definition: ethercatmain.h:209
#define LO_WORD(l)
Definition: ethercattype.h:518
uint8 * inputs
Definition: ethercatmain.h:250
#define EC_MAXLRWDATA
Definition: ethercattype.h:54
#define ECT_COEDET_SDOCA
Definition: ethercatmain.h:99
ecx_contextt * context
static void ecx_config_create_output_mappings(ecx_contextt *context, void *pIOmap, uint8 group, int16 slave, uint32 *LogAddr, uint8 *BitPos)
uint16 mbx_wo
Definition: ethercatmain.h:159
PACKED_BEGIN struct PACKED ec_fmmu ec_fmmut
Headerfile for ethercatbase.c.
int wkc
Definition: aliastool.c:47
#define EC_MAXSLAVE
Definition: ethercatmain.h:25
#define htoes(A)
Definition: ethercattype.h:533
#define EC_MAXNAME
Definition: ethercatmain.h:23
int ec_config(uint8 usetable, void *pIOmap)
int ecx_siiPDO(ecx_contextt *context, uint16 slave, ec_eepromPDOt *PDO, uint8 t)
Definition: ethercatmain.c:614
int ecx_eeprom2pdi(ecx_contextt *context, uint16 slave)
int(* PO2SOconfig)(uint16 slave)
Definition: ethercatmain.h:231
uint16 mbx_proto
Definition: ethercatmain.h:165
uint16 Obits
Definition: ethercatmain.h:127
uint8 activeports
Definition: ethercatmain.h:175
char name[EC_MAXNAME+1]
#define etohl(A)
Definition: ethercattype.h:537
int16 Ebuscurrent
Definition: ethercatmain.h:256
int ecx_config_overlap_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
uint16 Isegment
Definition: ethercatmain.h:262
Headerfile for ethercatmain.c.
uint8 FMMU0func
Definition: ethercatmain.h:149
uint32_t uint32
Definition: osal.h:30
#define EC_TIMEOUTRET3
Definition: ethercattype.h:66
uint16 ecx_FPRDw(ecx_portt *port, uint16 ADP, uint16 ADO, int timeout)
Definition: ethercatbase.c:343
uint16 mbx_l
Definition: ethercatmain.h:157
boolean hasdc
Definition: ethercatmain.h:169
uint16 ecx_APRDw(ecx_portt *port, uint16 ADP, uint16 ADO, int timeout)
Definition: ethercatbase.c:298
uint8 SoEdetails
Definition: ethercatmain.h:219
#define EC_DEFAULTMBXSM1
int16_t int16
Definition: osal.h:26
#define EC_SLAVECOUNTEXCEEDED
Definition: ethercattype.h:47
int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int Thread_n, int *Osize, int *Isize)
Definition: ethercatcoe.c:910
int16 ecx_siifind(ecx_contextt *context, uint16 slave, uint16 cat)
Definition: ethercatmain.c:405
#define EC_DEFAULTDOSM0
uint8 FMMUunused
Definition: ethercatmain.h:227
uint8 Ostartbit
Definition: ethercatmain.h:133
uint16 ecx_siiSM(ecx_contextt *context, uint16 slave, ec_eepromSMt *SM)
Definition: ethercatmain.c:543
Headerfile for ethercatconfig.c.
#define EC_MAXIOSEGMENTS
Definition: ethercatmain.h:29
uint8 ptype
Definition: ethercatmain.h:171
uint32 eep_man
Definition: ethercatmain.h:117
static int ecx_get_threadcount(void)
int ecx_readPDOmap(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize)
Definition: ethercatcoe.c:810
int ec_config_init(uint8 usetable)
#define EC_ESTAT_R64
Definition: ethercattype.h:271
static int ecx_lookup_prev_sii(ecx_contextt *context, uint16 slave)
uint8 FMMU3func
Definition: ethercatmain.h:155
int ec_config_map_group(void *pIOmap, uint8 group)
ec_slavet * slavelist
Definition: ethercatmain.h:389
#define EC_DEFAULTMBXSM0
uint16 Ioffset
Definition: ethercatmain.h:264
int manualstatechange
Definition: ethercatmain.h:431
uint16 inputsWKC
Definition: ethercatmain.h:268
int * slavecount
Definition: ethercatmain.h:391
uint8 * inputs
Definition: ethercatmain.h:139


soem
Author(s): Arthur Ketels and M.J.G. van den Molengraft
autogenerated on Mon Feb 28 2022 23:46:57