ethercatconfig.c
Go to the documentation of this file.
1 /*
2  * Simple Open EtherCAT Master Library
3  *
4  * File : ethercatconfig.c
5  * Version : 1.3.0
6  * Date : 24-02-2013
7  * Copyright (C) 2005-2013 Speciaal Machinefabriek Ketels v.o.f.
8  * Copyright (C) 2005-2013 Arthur Ketels
9  * Copyright (C) 2008-2009 TU/e Technische Universiteit Eindhoven
10  *
11  * SOEM is free software; you can redistribute it and/or modify it under
12  * the terms of the GNU General Public License version 2 as published by the Free
13  * Software Foundation.
14  *
15  * SOEM is distributed in the hope that it will be useful, but WITHOUT ANY
16  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18  * for more details.
19  *
20  * As a special exception, if other files instantiate templates or use macros
21  * or inline functions from this file, or you compile this file and link it
22  * with other works to produce a work based on this file, this file does not
23  * by itself cause the resulting work to be covered by the GNU General Public
24  * License. However the source code for this file must still be made available
25  * in accordance with section (3) of the GNU General Public License.
26  *
27  * This exception does not invalidate any other reasons why a work based on
28  * this file might be covered by the GNU General Public License.
29  *
30  * The EtherCAT Technology, the trade name and logo “EtherCAT” are the intellectual
31  * property of, and protected by Beckhoff Automation GmbH. You can use SOEM for
32  * the sole purpose of creating, using and/or selling or otherwise distributing
33  * an EtherCAT network master provided that an EtherCAT Master License is obtained
34  * from Beckhoff Automation GmbH.
35  *
36  * In case you did not receive a copy of the EtherCAT Master License along with
37  * SOEM write to Beckhoff Automation GmbH, Eiserstraße 5, D-33415 Verl, Germany
38  * (www.beckhoff.com).
39  */
40 
49 #include <stdio.h>
50 #include <string.h>
51 #include "osal.h"
52 #include "oshw.h"
53 #include "ethercattype.h"
54 #include "ethercatbase.h"
55 #include "ethercatmain.h"
56 #include "ethercatcoe.h"
57 #include "ethercatsoe.h"
58 #include "ethercatconfig.h"
59 
60 // define if debug printf is needed
61 //#define EC_DEBUG
62 
63 #ifdef EC_DEBUG
64 #define EC_PRINT printf
65 #else
66 #define EC_PRINT(...) do {} while (0)
67 #endif
68 
69 #ifdef EC_VER1
70 
71 typedef const struct
72 {
74  uint32 man;
76  uint32 id;
78  char name[EC_MAXNAME + 1];
80  uint8 Dtype;
82  uint16 Ibits;
84  uint16 Obits;
86  uint16 SM2a;
88  uint32 SM2f;
90  uint16 SM3a;
92  uint32 SM3f;
94  uint8 FM0ac;
96  uint8 FM1ac;
97 } ec_configlist_t;
98 
99 #include "ethercatconfiglist.h"
100 #endif
101 
103 #define EC_DEFAULTMBXSM0 0x00010026
104 
105 #define EC_DEFAULTMBXSM1 0x00010022
106 
107 #define EC_DEFAULTDOSM0 0x00010044
108 
109 #ifdef EC_VER1
110 
116 int ec_findconfig( uint32 man, uint32 id)
117 {
118  int i = 0;
119 
120  do
121  {
122  i++;
123  } while ( (ec_configlist[i].man != EC_CONFIGEND) &&
124  ((ec_configlist[i].man != man) || (ec_configlist[i].id != id)) );
125  if (ec_configlist[i].man == EC_CONFIGEND)
126  {
127  i = 0;
128  }
129  return i;
130 }
131 #endif
132 
139 int ecx_config_init(ecx_contextt *context, uint8 usetable)
140 {
141  uint16 w, slave, ADPh, configadr, ssigen;
142  uint16 topology, estat;
143  int16 topoc, slavec, aliasadr;
144  uint8 b,h;
145  uint8 zbuf[64];
146  uint8 SMc;
147  uint32 eedat;
148  int wkc, cindex, nSM, lp;
149 
150  EC_PRINT("ec_config_init %d\n",usetable);
151  *(context->slavecount) = 0;
152  /* clean ec_slave array */
153  memset(context->slavelist, 0x00, sizeof(ec_slavet) * context->maxslave);
154  memset(&zbuf, 0x00, sizeof(zbuf));
155  memset(context->grouplist, 0x00, sizeof(ec_groupt) * context->maxgroup);
156  /* clear slave eeprom cache */
157  ecx_siigetbyte(context, 0, EC_MAXEEPBUF);
158 
159  for(lp = 0; lp < context->maxgroup; lp++)
160  {
161  context->grouplist[lp].logstartaddr = lp << 16; /* default start address per group entry */
162  }
163  /* make special pre-init register writes to enable MAC[1] local administered bit *
164  * setting for old netX100 slaves */
165  b = 0x00;
166  ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3); /* Ignore Alias register */
168  ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */
169  /* netX100 should now be happy */
170 
171  wkc = ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */
172  printf("wkc = %d\n",wkc);
173 
174  w = 0x0000;
175  wkc = ecx_BRD(context->port, 0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE); /* detect number of slaves */
176  if (wkc > 0)
177  {
178  *(context->slavecount) = wkc;
179  b = 0x00;
180  ecx_BWR(context->port, 0x0000, ECT_REG_DLPORT, sizeof(b), &b, EC_TIMEOUTRET3); /* deact loop manual */
181  w = htoes(0x0004);
182  ecx_BWR(context->port, 0x0000, ECT_REG_IRQMASK, sizeof(w), &w, EC_TIMEOUTRET3); /* set IRQ mask */
183  ecx_BWR(context->port, 0x0000, ECT_REG_RXERR, 8, &zbuf, EC_TIMEOUTRET3); /* reset CRC counters */
184  ecx_BWR(context->port, 0x0000, ECT_REG_FMMU0, 16 * 3, &zbuf, EC_TIMEOUTRET3); /* reset FMMU's */
185  ecx_BWR(context->port, 0x0000, ECT_REG_SM0, 8 * 4, &zbuf, EC_TIMEOUTRET3); /* reset SyncM */
186  ecx_BWR(context->port, 0x0000, ECT_REG_DCSYSTIME, 4, &zbuf, EC_TIMEOUTRET3); /* reset system time+ofs */
187  w = htoes(0x1000);
188  ecx_BWR(context->port, 0x0000, ECT_REG_DCSPEEDCNT, sizeof(w), &w, EC_TIMEOUTRET3); /* DC speedstart */
189  w = htoes(0x0c00);
190  ecx_BWR(context->port, 0x0000, ECT_REG_DCTIMEFILT, sizeof(w), &w, EC_TIMEOUTRET3); /* DC filt expr */
191  b = 0x00;
192  ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3); /* Ignore Alias register */
194  ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */
195  b = 2;
196  ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET3); /* force Eeprom from PDI */
197  b = 0;
198  ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET3); /* set Eeprom to master */
199 
200  for (slave = 1; slave <= *(context->slavecount); slave++)
201  {
202  ADPh = (uint16)(1 - slave);
203  context->slavelist[slave].Itype =
204  etohs(ecx_APRDw(context->port, ADPh, ECT_REG_PDICTL, EC_TIMEOUTRET3)); /* read interface type of slave */
205  /* a node offset is used to improve readibility of network frames */
206  /* this has no impact on the number of addressable slaves (auto wrap around) */
207  ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(slave + EC_NODEOFFSET) , EC_TIMEOUTRET3); /* set node address of slave */
208  if (slave == 1)
209  {
210  b = 1; /* kill non ecat frames for first slave */
211  }
212  else
213  {
214  b = 0; /* pass all frames for following slaves */
215  }
216  ecx_APWRw(context->port, ADPh, ECT_REG_DLCTL, htoes(b), EC_TIMEOUTRET3); /* set non ecat frame behaviour */
217  configadr = etohs(ecx_APRDw(context->port, ADPh, ECT_REG_STADR, EC_TIMEOUTRET3));
218  context->slavelist[slave].configadr = configadr;
219  ecx_FPRD(context->port, configadr, ECT_REG_ALIAS, sizeof(aliasadr), &aliasadr, EC_TIMEOUTRET3);
220  context->slavelist[slave].aliasadr = etohs(aliasadr);
221  ecx_FPRD(context->port, configadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET3);
222  estat = etohs(estat);
223  if (estat & EC_ESTAT_R64) /* check if slave can read 8 byte chunks */
224  {
225  context->slavelist[slave].eep_8byte = 1;
226  }
227  ecx_readeeprom1(context, slave, ECT_SII_MANUF); /* Manuf */
228  }
229  for (slave = 1; slave <= *(context->slavecount); slave++)
230  {
231  context->slavelist[slave].eep_man =
232  etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* Manuf */
233  ecx_readeeprom1(context, slave, ECT_SII_ID); /* ID */
234  }
235  for (slave = 1; slave <= *(context->slavecount); slave++)
236  {
237  context->slavelist[slave].eep_id =
238  etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* ID */
239  ecx_readeeprom1(context, slave, ECT_SII_REV); /* revision */
240  }
241  for (slave = 1; slave <= *(context->slavecount); slave++)
242  {
243  context->slavelist[slave].eep_rev =
244  etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* revision */
245  ecx_readeeprom1(context, slave, ECT_SII_RXMBXADR); /* write mailbox address + mailboxsize */
246  }
247  for (slave = 1; slave <= *(context->slavecount); slave++)
248  {
249  eedat = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* write mailbox address and mailboxsize */
250  context->slavelist[slave].mbx_wo = (uint16)LO_WORD(eedat);
251  context->slavelist[slave].mbx_l = (uint16)HI_WORD(eedat);
252  if (context->slavelist[slave].mbx_l > 0)
253  {
254  ecx_readeeprom1(context, slave, ECT_SII_TXMBXADR); /* read mailbox offset */
255  }
256  }
257  for (slave = 1; slave <= *(context->slavecount); slave++)
258  {
259  if (context->slavelist[slave].mbx_l > 0)
260  {
261  eedat = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* read mailbox offset */
262  context->slavelist[slave].mbx_ro = (uint16)LO_WORD(eedat); /* read mailbox offset */
263  context->slavelist[slave].mbx_rl = (uint16)HI_WORD(eedat); /*read mailbox length */
264  if (context->slavelist[slave].mbx_rl == 0)
265  {
266  context->slavelist[slave].mbx_rl = context->slavelist[slave].mbx_l;
267  }
268  }
269  configadr = context->slavelist[slave].configadr;
270  if ((etohs(ecx_FPRDw(context->port, configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET3)) & 0x04) > 0) /* Support DC? */
271  {
272  context->slavelist[slave].hasdc = TRUE;
273  }
274  else
275  {
276  context->slavelist[slave].hasdc = FALSE;
277  }
278  topology = etohs(ecx_FPRDw(context->port, configadr, ECT_REG_DLSTAT, EC_TIMEOUTRET3)); /* extract topology from DL status */
279  h = 0;
280  b = 0;
281  if ((topology & 0x0300) == 0x0200) /* port0 open and communication established */
282  {
283  h++;
284  b |= 0x01;
285  }
286  if ((topology & 0x0c00) == 0x0800) /* port1 open and communication established */
287  {
288  h++;
289  b |= 0x02;
290  }
291  if ((topology & 0x3000) == 0x2000) /* port2 open and communication established */
292  {
293  h++;
294  b |= 0x04;
295  }
296  if ((topology & 0xc000) == 0x8000) /* port3 open and communication established */
297  {
298  h++;
299  b |= 0x08;
300  }
301  /* ptype = Physical type*/
302  context->slavelist[slave].ptype =
303  LO_BYTE(etohs(ecx_FPRDw(context->port, configadr, ECT_REG_PORTDES, EC_TIMEOUTRET3)));
304  context->slavelist[slave].topology = h;
305  context->slavelist[slave].activeports = b;
306  /* 0=no links, not possible */
307  /* 1=1 link , end of line */
308  /* 2=2 links , one before and one after */
309  /* 3=3 links , split point */
310  /* 4=4 links , cross point */
311  /* search for parent */
312  context->slavelist[slave].parent = 0; /* parent is master */
313  if (slave > 1)
314  {
315  topoc = 0;
316  slavec = slave - 1;
317  do
318  {
319  topology = context->slavelist[slavec].topology;
320  if (topology == 1)
321  {
322  topoc--; /* endpoint found */
323  }
324  if (topology == 3)
325  {
326  topoc++; /* split found */
327  }
328  if (topology == 4)
329  {
330  topoc += 2; /* cross found */
331  }
332  if (((topoc >= 0) && (topology > 1)) ||
333  (slavec == 1)) /* parent found */
334  {
335  context->slavelist[slave].parent = slavec;
336  slavec = 1;
337  }
338  slavec--;
339  }
340  while (slavec > 0);
341  }
342 
343  w = ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE); //* check state change Init */
344 
345  /* set default mailbox configuration if slave has mailbox */
346  if (context->slavelist[slave].mbx_l>0)
347  {
348  context->slavelist[slave].SMtype[0] = 1;
349  context->slavelist[slave].SMtype[1] = 2;
350  context->slavelist[slave].SMtype[2] = 3;
351  context->slavelist[slave].SMtype[3] = 4;
352  context->slavelist[slave].SM[0].StartAddr = htoes(context->slavelist[slave].mbx_wo);
353  context->slavelist[slave].SM[0].SMlength = htoes(context->slavelist[slave].mbx_l);
354  context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
355  context->slavelist[slave].SM[1].StartAddr = htoes(context->slavelist[slave].mbx_ro);
356  context->slavelist[slave].SM[1].SMlength = htoes(context->slavelist[slave].mbx_rl);
357  context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
358  context->slavelist[slave].mbx_proto =
360  }
361  cindex = 0;
362  #ifdef EC_VER1
363  /* use configuration table ? */
364  if (usetable)
365  {
366  cindex = ec_findconfig( context->slavelist[slave].eep_man, context->slavelist[slave].eep_id );
367  context->slavelist[slave].configindex= cindex;
368  }
369  /* slave found in configuration table ? */
370  if (cindex)
371  {
372  context->slavelist[slave].Dtype = ec_configlist[cindex].Dtype;
373  strcpy(context->slavelist[slave].name ,ec_configlist[cindex].name);
374  context->slavelist[slave].Ibits = ec_configlist[cindex].Ibits;
375  context->slavelist[slave].Obits = ec_configlist[cindex].Obits;
376  if (context->slavelist[slave].Obits)
377  {
378  context->slavelist[slave].FMMU0func = 1;
379  }
380  if (context->slavelist[slave].Ibits)
381  {
382  context->slavelist[slave].FMMU1func = 2;
383  }
384  context->slavelist[slave].FMMU[0].FMMUactive = ec_configlist[cindex].FM0ac;
385  context->slavelist[slave].FMMU[1].FMMUactive = ec_configlist[cindex].FM1ac;
386  context->slavelist[slave].SM[2].StartAddr = htoes(ec_configlist[cindex].SM2a);
387  context->slavelist[slave].SM[2].SMflags = htoel(ec_configlist[cindex].SM2f);
388  /* simple (no mailbox) output slave found ? */
389  if (context->slavelist[slave].Obits && !context->slavelist[slave].SM[2].StartAddr)
390  {
391  context->slavelist[slave].SM[0].StartAddr = htoes(0x0f00);
392  context->slavelist[slave].SM[0].SMlength = htoes((context->slavelist[slave].Obits + 7) / 8);
393  context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTDOSM0);
394  context->slavelist[slave].FMMU[0].FMMUactive = 1;
395  context->slavelist[slave].FMMU[0].FMMUtype = 2;
396  context->slavelist[slave].SMtype[0] = 3;
397  }
398  /* complex output slave */
399  else
400  {
401  context->slavelist[slave].SM[2].SMlength = htoes((context->slavelist[slave].Obits + 7) / 8);
402  context->slavelist[slave].SMtype[2] = 3;
403  }
404  context->slavelist[slave].SM[3].StartAddr = htoes(ec_configlist[cindex].SM3a);
405  context->slavelist[slave].SM[3].SMflags = htoel(ec_configlist[cindex].SM3f);
406  /* simple (no mailbox) input slave found ? */
407  if (context->slavelist[slave].Ibits && !context->slavelist[slave].SM[3].StartAddr)
408  {
409  context->slavelist[slave].SM[1].StartAddr = htoes(0x1000);
410  context->slavelist[slave].SM[1].SMlength = htoes((context->slavelist[slave].Ibits + 7) / 8);
411  context->slavelist[slave].SM[1].SMflags = htoel(0x00000000);
412  context->slavelist[slave].FMMU[1].FMMUactive = 1;
413  context->slavelist[slave].FMMU[1].FMMUtype = 1;
414  context->slavelist[slave].SMtype[1] = 4;
415  }
416  /* complex input slave */
417  else
418  {
419  context->slavelist[slave].SM[3].SMlength = htoes((context->slavelist[slave].Ibits + 7) / 8);
420  context->slavelist[slave].SMtype[3] = 4;
421  }
422  }
423  /* slave not in configuration table, find out via SII */
424  else
425  #endif
426  {
427  ssigen = ecx_siifind(context, slave, ECT_SII_GENERAL);
428  /* SII general section */
429  if (ssigen)
430  {
431  context->slavelist[slave].CoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x07);
432  context->slavelist[slave].FoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x08);
433  context->slavelist[slave].EoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x09);
434  context->slavelist[slave].SoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x0a);
435  if((ecx_siigetbyte(context, slave, ssigen + 0x0d) & 0x02) > 0)
436  {
437  context->slavelist[slave].blockLRW = 1;
438  context->slavelist[0].blockLRW++;
439  }
440  context->slavelist[slave].Ebuscurrent = ecx_siigetbyte(context, slave, ssigen + 0x0e);
441  context->slavelist[slave].Ebuscurrent += ecx_siigetbyte(context, slave, ssigen + 0x0f) << 8;
442  context->slavelist[0].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
443  }
444  /* SII strings section */
445  if (ecx_siifind(context, slave, ECT_SII_STRING) > 0)
446  {
447  ecx_siistring(context, context->slavelist[slave].name, slave, 1);
448  }
449  /* no name for slave found, use constructed name */
450  else
451  {
452  sprintf(context->slavelist[slave].name, "? M:%8.8x I:%8.8x",
453  (unsigned int)context->slavelist[slave].eep_man,
454  (unsigned int)context->slavelist[slave].eep_id);
455  }
456  /* SII SM section */
457  nSM = ecx_siiSM(context, slave, context->eepSM);
458  if (nSM>0)
459  {
460  context->slavelist[slave].SM[0].StartAddr = htoes(context->eepSM->PhStart);
461  context->slavelist[slave].SM[0].SMlength = htoes(context->eepSM->Plength);
462  context->slavelist[slave].SM[0].SMflags =
463  htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
464  SMc = 1;
465  while ((SMc < EC_MAXSM) && ecx_siiSMnext(context, slave, context->eepSM, SMc))
466  {
467  context->slavelist[slave].SM[SMc].StartAddr = htoes(context->eepSM->PhStart);
468  context->slavelist[slave].SM[SMc].SMlength = htoes(context->eepSM->Plength);
469  context->slavelist[slave].SM[SMc].SMflags =
470  htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
471  SMc++;
472  }
473  }
474  /* SII FMMU section */
475  if (ecx_siiFMMU(context, slave, context->eepFMMU))
476  {
477  if (context->eepFMMU->FMMU0 !=0xff)
478  {
479  context->slavelist[slave].FMMU0func = context->eepFMMU->FMMU0;
480  }
481  if (context->eepFMMU->FMMU1 !=0xff)
482  {
483  context->slavelist[slave].FMMU1func = context->eepFMMU->FMMU1;
484  }
485  if (context->eepFMMU->FMMU2 !=0xff)
486  {
487  context->slavelist[slave].FMMU2func = context->eepFMMU->FMMU2;
488  }
489  if (context->eepFMMU->FMMU3 !=0xff)
490  {
491  context->slavelist[slave].FMMU3func = context->eepFMMU->FMMU3;
492  }
493  }
494  }
495 
496  if (context->slavelist[slave].mbx_l > 0)
497  {
498  if (context->slavelist[slave].SM[0].StartAddr == 0x0000) /* should never happen */
499  {
500  EC_PRINT("Slave %d has no proper mailbox in configuration, try default.\n", slave);
501  context->slavelist[slave].SM[0].StartAddr = htoes(0x1000);
502  context->slavelist[slave].SM[0].SMlength = htoes(0x0080);
503  context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
504  context->slavelist[slave].SMtype[0] = 1;
505  }
506  if (context->slavelist[slave].SM[1].StartAddr == 0x0000) /* should never happen */
507  {
508  EC_PRINT("Slave %d has no proper mailbox out configuration, try default.\n", slave);
509  context->slavelist[slave].SM[1].StartAddr = htoes(0x1080);
510  context->slavelist[slave].SM[1].SMlength = htoes(0x0080);
511  context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
512  context->slavelist[slave].SMtype[1] = 2;
513  }
514  /* program SM0 mailbox in and SM1 mailbox out for slave */
515  /* writing both SM in one datagram will solve timing issue in old NETX */
516  ecx_FPWR(context->port, configadr, ECT_REG_SM0, sizeof(ec_smt) * 2,
517  &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
518  }
519  /* request pre_op for slave */
520  ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP | EC_STATE_ACK) , EC_TIMEOUTRET3); /* set preop status */
521  }
522  }
523  return wkc;
524 }
525 
533 int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
534 {
535  uint16 slave, configadr;
536  int Isize, Osize, BitCount, ByteCount, FMMUsize, FMMUdone;
537  uint16 SMlength, EndAddr;
538  uint8 BitPos;
539  uint8 SMc, FMMUc;
540  uint32 LogAddr = 0;
541  uint32 oLogAddr = 0;
542  uint32 diff;
543  int nSM, rval;
544  ec_eepromPDOt eepPDO;
545  uint16 currentsegment = 0;
546  uint32 segmentsize = 0;
547 
548  if ((*(context->slavecount) > 0) && (group < context->maxgroup))
549  {
550  EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group);
551  LogAddr = context->grouplist[group].logstartaddr;
552  oLogAddr = LogAddr;
553  BitPos = 0;
554  context->grouplist[group].nsegments = 0;
555  context->grouplist[group].outputsWKC = 0;
556  context->grouplist[group].inputsWKC = 0;
557 
558  /* find output mapping of slave and program FMMU */
559  for (slave = 1; slave <= *(context->slavecount); slave++)
560  {
561  configadr = context->slavelist[slave].configadr;
562 
563  ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
564 
565  EC_PRINT(" >Slave %d, configadr %x, state %2.2x\n",
566  slave, context->slavelist[slave].configadr, context->slavelist[slave].state);
567 
568  /* execute special slave configuration hook Pre-Op to Safe-OP */
569  if(context->slavelist[slave].PO2SOconfig) /* only if registered */
570  {
571  context->slavelist[slave].PO2SOconfig(slave);
572  }
573  if (!group || (group == context->slavelist[slave].group))
574  {
575 
576  /* if slave not found in configlist find IO mapping in slave self */
577  if (!context->slavelist[slave].configindex)
578  {
579  Isize = 0;
580  Osize = 0;
581  if (context->slavelist[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */
582  {
583  rval = 0;
584  if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
585  /* read PDO mapping via CoE and use Complete Access */
586  {
587  rval = ecx_readPDOmapCA(context, slave, &Osize, &Isize);
588  }
589  if (!rval) /* CA not available or not succeeded */
590  {
591  /* read PDO mapping via CoE */
592  rval = ecx_readPDOmap(context, slave, &Osize, &Isize);
593  }
594  EC_PRINT(" CoE Osize:%d Isize:%d\n", Osize, Isize);
595  }
596  if ((!Isize && !Osize) && (context->slavelist[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */
597  {
598  /* read AT / MDT mapping via SoE */
599  rval = ecx_readIDNmap(context, slave, &Osize, &Isize);
600  context->slavelist[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
601  context->slavelist[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
602  EC_PRINT(" SoE Osize:%d Isize:%d\n", Osize, Isize);
603  }
604  if (!Isize && !Osize) /* find PDO mapping by SII */
605  {
606  memset(&eepPDO, 0, sizeof(eepPDO));
607  Isize = (int)ecx_siiPDO(context, slave, &eepPDO, 0);
608  EC_PRINT(" SII Isize:%d\n", Isize);
609  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
610  {
611  if (eepPDO.SMbitsize[nSM] > 0)
612  {
613  context->slavelist[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
614  context->slavelist[slave].SMtype[nSM] = 4;
615  EC_PRINT(" SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
616  }
617  }
618  Osize = (int)ecx_siiPDO(context, slave, &eepPDO, 1);
619  EC_PRINT(" SII Osize:%d\n", Osize);
620  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
621  {
622  if (eepPDO.SMbitsize[nSM] > 0)
623  {
624  context->slavelist[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
625  context->slavelist[slave].SMtype[nSM] = 3;
626  EC_PRINT(" SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
627  }
628  }
629  }
630  context->slavelist[slave].Obits = Osize;
631  context->slavelist[slave].Ibits = Isize;
632  EC_PRINT(" ISIZE:%d %d OSIZE:%d\n",
633  context->slavelist[slave].Ibits, Isize,context->slavelist[slave].Obits);
634  }
635 
636  EC_PRINT(" SM programming\n");
637  if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[0].StartAddr)
638  {
639  ecx_FPWR(context->port, configadr, ECT_REG_SM0,
640  sizeof(ec_smt), &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
641  EC_PRINT(" SM0 Type:%d StartAddr:%4.4x Flags:%8.8x\n",
642  context->slavelist[slave].SMtype[0],
643  context->slavelist[slave].SM[0].StartAddr,
644  context->slavelist[slave].SM[0].SMflags);
645  }
646  if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[1].StartAddr)
647  {
648  ecx_FPWR(context->port, configadr, ECT_REG_SM1,
649  sizeof(ec_smt), &context->slavelist[slave].SM[1], EC_TIMEOUTRET3);
650  EC_PRINT(" SM1 Type:%d StartAddr:%4.4x Flags:%8.8x\n",
651  context->slavelist[slave].SMtype[1],
652  context->slavelist[slave].SM[1].StartAddr,
653  context->slavelist[slave].SM[1].SMflags);
654  }
655  /* program SM2 to SMx */
656  for( nSM = 2 ; nSM < EC_MAXSM ; nSM++ )
657  {
658  if (context->slavelist[slave].SM[nSM].StartAddr)
659  {
660  /* check if SM length is zero -> clear enable flag */
661  if( context->slavelist[slave].SM[nSM].SMlength == 0)
662  {
663  context->slavelist[slave].SM[nSM].SMflags =
664  htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) & EC_SMENABLEMASK);
665  }
666  ecx_FPWR(context->port, configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)),
667  sizeof(ec_smt), &context->slavelist[slave].SM[nSM], EC_TIMEOUTRET3);
668  EC_PRINT(" SM%d Type:%d StartAddr:%4.4x Flags:%8.8x\n", nSM,
669  context->slavelist[slave].SMtype[nSM],
670  context->slavelist[slave].SM[nSM].StartAddr,
671  context->slavelist[slave].SM[nSM].SMflags);
672  }
673  }
674  if (context->slavelist[slave].Ibits > 7)
675  {
676  context->slavelist[slave].Ibytes = (context->slavelist[slave].Ibits + 7) / 8;
677  }
678  if (context->slavelist[slave].Obits > 7)
679  {
680  context->slavelist[slave].Obytes = (context->slavelist[slave].Obits + 7) / 8;
681  }
682  FMMUc = context->slavelist[slave].FMMUunused;
683  SMc = 0;
684  BitCount = 0;
685  ByteCount = 0;
686  EndAddr = 0;
687  FMMUsize = 0;
688  FMMUdone = 0;
689  /* create output mapping */
690  if (context->slavelist[slave].Obits)
691  {
692  EC_PRINT(" OUTPUT MAPPING\n");
693  /* search for SM that contribute to the output mapping */
694  while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Obits + 7) / 8)))
695  {
696  EC_PRINT(" FMMU %d\n", FMMUc);
697  while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;
698  EC_PRINT(" SM%d\n", SMc);
699  context->slavelist[slave].FMMU[FMMUc].PhysStart =
700  context->slavelist[slave].SM[SMc].StartAddr;
701  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
702  ByteCount += SMlength;
703  BitCount += SMlength * 8;
704  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
705  while ( (BitCount < context->slavelist[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for output */
706  {
707  SMc++;
708  while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;
709  /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
710  if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr )
711  {
712  break;
713  }
714  EC_PRINT(" SM%d\n", SMc);
715  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
716  ByteCount += SMlength;
717  BitCount += SMlength * 8;
718  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
719  }
720 
721  /* bit oriented slave */
722  if (!context->slavelist[slave].Obytes)
723  {
724  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
725  context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
726  BitPos += context->slavelist[slave].Obits - 1;
727  if (BitPos > 7)
728  {
729  LogAddr++;
730  BitPos -= 8;
731  }
732  FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
733  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
734  context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
735  BitPos ++;
736  if (BitPos > 7)
737  {
738  LogAddr++;
739  BitPos -= 8;
740  }
741  }
742  /* byte oriented slave */
743  else
744  {
745  if (BitPos)
746  {
747  LogAddr++;
748  BitPos = 0;
749  }
750  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
751  context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
752  BitPos = 7;
753  FMMUsize = ByteCount;
754  if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Obytes)
755  {
756  FMMUsize = context->slavelist[slave].Obytes - FMMUdone;
757  }
758  LogAddr += FMMUsize;
759  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
760  context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
761  BitPos = 0;
762  }
763  FMMUdone += FMMUsize;
764  context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
765  context->slavelist[slave].FMMU[FMMUc].FMMUtype = 2;
766  context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
767  /* program FMMU for output */
768  ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
769  sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
770  context->grouplist[group].outputsWKC++;
771  if (!context->slavelist[slave].outputs)
772  {
773  context->slavelist[slave].outputs =
774  (uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
775  context->slavelist[slave].Ostartbit =
776  context->slavelist[slave].FMMU[FMMUc].LogStartbit;
777  EC_PRINT(" slave %d Outputs %p startbit %d\n",
778  slave,
779  context->slavelist[slave].outputs,
780  context->slavelist[slave].Ostartbit);
781  }
782  FMMUc++;
783  }
784  context->slavelist[slave].FMMUunused = FMMUc;
785  diff = LogAddr - oLogAddr;
786  oLogAddr = LogAddr;
787  if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
788  {
789  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
790  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
791  {
792  currentsegment++;
793  segmentsize = diff;
794  }
795  }
796  else
797  {
798  segmentsize += diff;
799  }
800  }
801  }
802  }
803  if (BitPos)
804  {
805  LogAddr++;
806  oLogAddr = LogAddr;
807  BitPos = 0;
808  if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
809  {
810  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
811  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
812  {
813  currentsegment++;
814  segmentsize = 1;
815  }
816  }
817  else
818  {
819  segmentsize += 1;
820  }
821  }
822  context->grouplist[group].outputs = pIOmap;
823  context->grouplist[group].Obytes = LogAddr;
824  context->grouplist[group].nsegments = currentsegment + 1;
825  context->grouplist[group].Isegment = currentsegment;
826  context->grouplist[group].Ioffset = segmentsize;
827  if (!group)
828  {
829  context->slavelist[0].outputs = pIOmap;
830  context->slavelist[0].Obytes = LogAddr; /* store output bytes in master record */
831  }
832 
833  /* do input mapping of slave and program FMMUs */
834  for (slave = 1; slave <= *(context->slavecount); slave++)
835  {
836  configadr = context->slavelist[slave].configadr;
837  FMMUc = context->slavelist[slave].FMMUunused;
838  if (context->slavelist[slave].Obits) /* find free FMMU */
839  {
840  while ( context->slavelist[slave].FMMU[FMMUc].LogStart ) FMMUc++;
841  }
842  SMc = 0;
843  BitCount = 0;
844  ByteCount = 0;
845  EndAddr = 0;
846  FMMUsize = 0;
847  FMMUdone = 0;
848  /* create input mapping */
849  if (context->slavelist[slave].Ibits)
850  {
851  EC_PRINT(" =Slave %d, INPUT MAPPING\n", slave);
852  /* search for SM that contribute to the input mapping */
853  while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Ibits + 7) / 8)))
854  {
855  EC_PRINT(" FMMU %d\n", FMMUc);
856  while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;
857  EC_PRINT(" SM%d\n", SMc);
858  context->slavelist[slave].FMMU[FMMUc].PhysStart =
859  context->slavelist[slave].SM[SMc].StartAddr;
860  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
861  ByteCount += SMlength;
862  BitCount += SMlength * 8;
863  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
864  while ( (BitCount < context->slavelist[slave].Ibits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for input */
865  {
866  SMc++;
867  while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;
868  /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
869  if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr )
870  {
871  break;
872  }
873  EC_PRINT(" SM%d\n", SMc);
874  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
875  ByteCount += SMlength;
876  BitCount += SMlength * 8;
877  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
878  }
879 
880  /* bit oriented slave */
881  if (!context->slavelist[slave].Ibytes)
882  {
883  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
884  context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
885  BitPos += context->slavelist[slave].Ibits - 1;
886  if (BitPos > 7)
887  {
888  LogAddr++;
889  BitPos -= 8;
890  }
891  FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
892  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
893  context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
894  BitPos ++;
895  if (BitPos > 7)
896  {
897  LogAddr++;
898  BitPos -= 8;
899  }
900  }
901  /* byte oriented slave */
902  else
903  {
904  if (BitPos)
905  {
906  LogAddr++;
907  BitPos = 0;
908  }
909  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
910  context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
911  BitPos = 7;
912  FMMUsize = ByteCount;
913  if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Ibytes)
914  {
915  FMMUsize = context->slavelist[slave].Ibytes - FMMUdone;
916  }
917  LogAddr += FMMUsize;
918  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
919  context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
920  BitPos = 0;
921  }
922  FMMUdone += FMMUsize;
923  if (context->slavelist[slave].FMMU[FMMUc].LogLength)
924  {
925  context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
926  context->slavelist[slave].FMMU[FMMUc].FMMUtype = 1;
927  context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
928  /* program FMMU for input */
929  ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
930  sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
931  /* add one for an input FMMU */
932  context->grouplist[group].inputsWKC++;
933  }
934  if (!context->slavelist[slave].inputs)
935  {
936  context->slavelist[slave].inputs =
937  (uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
938  context->slavelist[slave].Istartbit =
939  context->slavelist[slave].FMMU[FMMUc].LogStartbit;
940  EC_PRINT(" Inputs %p startbit %d\n",
941  context->slavelist[slave].inputs,
942  context->slavelist[slave].Istartbit);
943  }
944  FMMUc++;
945  }
946  context->slavelist[slave].FMMUunused = FMMUc;
947  diff = LogAddr - oLogAddr;
948  oLogAddr = LogAddr;
949  if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
950  {
951  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
952  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
953  {
954  currentsegment++;
955  segmentsize = diff;
956  }
957  }
958  else
959  {
960  segmentsize += diff;
961  }
962  }
963 
964  ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */
965  ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , EC_TIMEOUTRET3); /* set safeop status */
966 
967  if (context->slavelist[slave].blockLRW)
968  {
969  context->grouplist[group].blockLRW++;
970  }
971  context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
972  }
973  if (BitPos)
974  {
975  LogAddr++;
976  oLogAddr = LogAddr;
977  BitPos = 0;
978  if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
979  {
980  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
981  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
982  {
983  currentsegment++;
984  segmentsize = 1;
985  }
986  }
987  else
988  {
989  segmentsize += 1;
990  }
991  }
992  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
993  context->grouplist[group].nsegments = currentsegment + 1;
994  context->grouplist[group].inputs = (uint8 *)(pIOmap) + context->grouplist[group].Obytes;
995  context->grouplist[group].Ibytes = LogAddr - context->grouplist[group].Obytes;
996  if (!group)
997  {
998  context->slavelist[0].inputs = (uint8 *)(pIOmap) + context->slavelist[0].Obytes;
999  context->slavelist[0].Ibytes = LogAddr - context->slavelist[0].Obytes; /* store input bytes in master record */
1000  }
1001 
1002  EC_PRINT("IOmapSize %d\n", LogAddr - context->grouplist[group].logstartaddr);
1003 
1004  return (LogAddr - context->grouplist[group].logstartaddr);
1005  }
1006 
1007  return 0;
1008 }
1009 
1017 int ecx_recover_slave(ecx_contextt *context, uint16 slave, int timeout)
1018 {
1019  int rval;
1020  uint16 ADPh, configadr, readadr, wkc;
1021 
1022  rval = 0;
1023  configadr = context->slavelist[slave].configadr;
1024  ADPh = (uint16)(1 - slave);
1025  /* check if we found another slave than the requested */
1026  readadr = 0xfffe;
1027  wkc = ecx_APRD(context->port, ADPh, ECT_REG_STADR, sizeof(readadr), &readadr, timeout);
1028  /* correct slave found, finished */
1029  if(readadr == configadr)
1030  {
1031  return 1;
1032  }
1033  /* only try if no config address*/
1034  if( (wkc > 0) && (readadr == 0))
1035  {
1036  /* clear possible slaves at EC_TEMPNODE */
1037  ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
1038  /* set temporary node address of slave */
1039  if(ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(EC_TEMPNODE) , timeout) <= 0)
1040  {
1041  ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
1042  return 0; /* slave fails to respond */
1043  }
1044 
1045  context->slavelist[slave].configadr = EC_TEMPNODE; /* temporary config address */
1046  ecx_eeprom2master(context, slave); /* set Eeprom control to master */
1047 
1048  /* check if slave is the same as configured before */
1049  if ((ecx_FPRDw(context->port, EC_TEMPNODE, ECT_REG_ALIAS, timeout) ==
1050  context->slavelist[slave].aliasadr) &&
1051  (ecx_readeeprom(context, slave, ECT_SII_ID, EC_TIMEOUTEEP) ==
1052  context->slavelist[slave].eep_id) &&
1053  (ecx_readeeprom(context, slave, ECT_SII_MANUF, EC_TIMEOUTEEP) ==
1054  context->slavelist[slave].eep_man) &&
1055  (ecx_readeeprom(context, slave, ECT_SII_REV, EC_TIMEOUTEEP) ==
1056  context->slavelist[slave].eep_rev))
1057  {
1058  rval = ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(configadr) , timeout);
1059  context->slavelist[slave].configadr = configadr;
1060  }
1061  else
1062  {
1063  /* slave is not the expected one, remove config address*/
1064  ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , timeout);
1065  context->slavelist[slave].configadr = configadr;
1066  }
1067  }
1068 
1069  return rval;
1070 }
1071 
1079 int ecx_reconfig_slave(ecx_contextt *context, uint16 slave, int timeout)
1080 {
1081  int state, nSM, FMMUc;
1082  uint16 configadr;
1083 
1084  configadr = context->slavelist[slave].configadr;
1085  if (ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_INIT) , timeout) <= 0)
1086  {
1087  return 0;
1088  }
1089  state = 0;
1090  ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */
1091  /* check state change init */
1092  state = ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE);
1093  if(state == EC_STATE_INIT)
1094  {
1095  /* program all enabled SM */
1096  for( nSM = 0 ; nSM < EC_MAXSM ; nSM++ )
1097  {
1098  if (context->slavelist[slave].SM[nSM].StartAddr)
1099  {
1100  ecx_FPWR(context->port, configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)),
1101  sizeof(ec_smt), &context->slavelist[slave].SM[nSM], timeout);
1102  }
1103  }
1104  ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP) , timeout);
1105  state = ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
1106  if( state == EC_STATE_PRE_OP)
1107  {
1108  /* execute special slave configuration hook Pre-Op to Safe-OP */
1109  if(context->slavelist[slave].PO2SOconfig) /* only if registered */
1110  {
1111  context->slavelist[slave].PO2SOconfig(slave);
1112  }
1113  ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , timeout); /* set safeop status */
1114  state = ecx_statecheck(context, slave, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE); /* check state change safe-op */
1115  /* program configured FMMU */
1116  for( FMMUc = 0 ; FMMUc < context->slavelist[slave].FMMUunused ; FMMUc++ )
1117  {
1118  ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
1119  sizeof(ec_fmmut), &context->slavelist[slave].FMMU[FMMUc], timeout);
1120  }
1121  }
1122  }
1123 
1124  return state;
1125 }
1126 
1127 #ifdef EC_VER1
1128 int ec_config_init(uint8 usetable)
1129 {
1130  return ecx_config_init(&ecx_context, usetable);
1131 }
1132 
1133 int ec_config_map_group(void *pIOmap, uint8 group)
1134 {
1135  return ecx_config_map_group(&ecx_context, pIOmap, group);
1136 }
1137 
1143 int ec_config_map(void *pIOmap)
1144 {
1145  return ec_config_map_group(pIOmap, 0);
1146 }
1147 
1154 int ec_config(uint8 usetable, void *pIOmap)
1155 {
1156  int wkc;
1157  wkc = ec_config_init(usetable);
1158  if (wkc)
1159  {
1160  ec_config_map(pIOmap);
1161  }
1162  return wkc;
1163 }
1164 
1165 int ec_recover_slave(uint16 slave, int timeout)
1166 {
1167  return ecx_recover_slave(&ecx_context, slave, timeout);
1168 }
1169 
1170 int ec_reconfig_slave(uint16 slave, int timeout)
1171 {
1172  return ecx_reconfig_slave(&ecx_context, slave, timeout);
1173 }
1174 #endif
uint16 mbx_rl
Definition: ethercatmain.h:192
void ecx_siistring(ecx_contextt *context, char *str, uint16 slave, uint16 Sn)
Definition: ethercatmain.c:474
int ecx_FPWR(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:409
char name[EC_MAXNAME+1]
Definition: ethercatmain.h:264
uint8 FMMU2func
Definition: ethercatmain.h:184
uint32 Obytes
Definition: ethercatmain.h:160
ec_eepromFMMUt * eepFMMU
Definition: ethercatmain.h:454
uint8 FMMUunused
Definition: ethercatmain.h:258
uint16 Ioffset
Definition: ethercatmain.h:293
uint32 eep_id
Definition: ethercatmain.h:150
uint8 FoEdetails
Definition: ethercatmain.h:246
uint16 Plength
Definition: ethercatmain.h:321
ec_slavet * slavelist
Definition: ethercatmain.h:418
uint16 aliasadr
Definition: ethercatmain.h:146
int ecx_reconfig_slave(ecx_contextt *context, uint16 slave, int timeout)
#define EC_TIMEOUTSTATE
Definition: ethercattype.h:102
#define EC_SMENABLEMASK
Definition: ethercatmain.h:134
uint16 Ibits
Definition: ethercatmain.h:166
#define htoel(A)
Definition: ethercattype.h:548
uint8 topology
Definition: ethercatmain.h:204
int(* PO2SOconfig)(uint16 slave)
Definition: ethercatmain.h:262
#define ECT_MBXPROT_SOE
Definition: ethercatmain.h:124
#define EC_TIMEOUTSAFE
Definition: ethercattype.h:94
ec_groupt * grouplist
Definition: ethercatmain.h:424
uint8_t uint8
Definition: osal.h:33
uint16 ecx_siiSMnext(ecx_contextt *context, uint16 slave, ec_eepromSMt *SM, uint16 n)
Definition: ethercatmain.c:609
int ecx_BWR(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:168
uint8 * inputs
Definition: ethercatmain.h:170
uint16 mbx_l
Definition: ethercatmain.h:188
uint8 SoEdetails
Definition: ethercatmain.h:250
int ecx_readIDNmap(ecx_contextt *context, uint16 slave, int *Osize, int *Isize)
Definition: ethercatsoe.c:346
#define EC_MAXEEPBUF
Definition: ethercattype.h:106
ec_smt SM[EC_MAXSM]
Definition: ethercatmain.h:174
#define EC_FIRSTDCDATAGRAM
Definition: ethercattype.h:82
uint16 ecx_FPRDw(ecx_portt *port, uint16 ADP, uint16 ADO, int timeout)
Definition: ethercatbase.c:353
int ecx_BRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:195
#define EC_TEMPNODE
uint32 Obytes
Definition: ethercatmain.h:273
uint8 group
Definition: ethercatmain.h:256
uint8 FMMU3func
Definition: ethercatmain.h:186
uint16_t uint16
Definition: osal.h:34
uint8 * outputs
Definition: ethercatmain.h:162
uint16 Dtype
Definition: ethercatmain.h:156
uint8 Istartbit
Definition: ethercatmain.h:172
#define EC_PRINT(...)
uint16 mbx_proto
Definition: ethercatmain.h:196
int ecx_eeprom2pdi(ecx_contextt *context, uint16 slave)
General typedefs and defines for EtherCAT.
#define etohs(A)
Definition: ethercattype.h:550
#define EC_CONFIGEND
Headerfile for ethercatcoe.c.
#define TRUE
Definition: osal.h:28
uint8 SMtype[EC_MAXSM]
Definition: ethercatmain.h:176
int ecx_APRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:227
#define EC_MAXSM
Definition: ethercatmain.h:70
uint16 parent
Definition: ethercatmain.h:210
uint16 ecx_statecheck(ecx_contextt *context, uint16 slave, uint16 reqstate, int timeout)
Definition: ethercatmain.c:773
int ecx_config_init(ecx_contextt *context, uint8 usetable)
int16 ecx_siifind(ecx_contextt *context, uint16 slave, uint16 cat)
Definition: ethercatmain.c:434
#define ECT_MBXPROT_COE
Definition: ethercatmain.h:122
uint32 IOsegment[EC_MAXIOSEGMENTS]
Definition: ethercatmain.h:301
int ecx_recover_slave(ecx_contextt *context, uint16 slave, int timeout)
uint16 mbx_ro
Definition: ethercatmain.h:194
uint16 nsegments
Definition: ethercatmain.h:289
uint32 ecx_readeeprom(ecx_contextt *context, uint16 slave, uint16 eeproma, int timeout)
DEPRICATED Configuration list of known EtherCAT slave devices.
uint16 SMbitsize[EC_MAXSM]
Definition: ethercatmain.h:337
boolean hasdc
Definition: ethercatmain.h:200
#define FALSE
Definition: osal.h:29
uint16 Isegment
Definition: ethercatmain.h:291
int ecx_readPDOmap(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize)
Definition: ethercatcoe.c:839
ecx_portt * port
Definition: ethercatmain.h:416
Headerfile for ethercatsoe.c.
uint16 Obits
Definition: ethercatmain.h:158
uint8 FMMU0func
Definition: ethercatmain.h:180
#define LO_BYTE(w)
Definition: ethercattype.h:528
#define EC_NODEOFFSET
int ecx_siiPDO(ecx_contextt *context, uint16 slave, ec_eepromPDOt *PDO, uint8 t)
Definition: ethercatmain.c:643
uint16 ecx_APRDw(ecx_portt *port, uint16 ADP, uint16 ADO, int timeout)
Definition: ethercatbase.c:308
#define EC_TIMEOUTEEP
Definition: ethercattype.h:96
void ecx_readeeprom1(ecx_contextt *context, uint16 slave, uint16 eeproma)
int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
#define HI_WORD(l)
Definition: ethercattype.h:534
ec_configlist_t ec_configlist[]
uint8 eep_8byte
Definition: ethercatmain.h:240
uint32 eep_man
Definition: ethercatmain.h:148
#define LO_WORD(l)
Definition: ethercattype.h:532
#define EC_MAXLRWDATA
Definition: ethercattype.h:80
#define ECT_COEDET_SDOCA
Definition: ethercatmain.h:132
Headerfile for ethercatbase.c.
#define htoes(A)
Definition: ethercattype.h:547
#define EC_MAXNAME
Definition: ethercatmain.h:58
uint32 logstartaddr
Definition: ethercatmain.h:271
uint8 CoEdetails
Definition: ethercatmain.h:244
int ecx_eeprom2master(ecx_contextt *context, uint16 slave)
uint16 outputsWKC
Definition: ethercatmain.h:295
#define etohl(A)
Definition: ethercattype.h:551
uint16 ecx_siiSM(ecx_contextt *context, uint16 slave, ec_eepromSMt *SM)
Definition: ethercatmain.c:572
uint8 FMMU1func
Definition: ethercatmain.h:182
uint16 mbx_wo
Definition: ethercatmain.h:190
int ecx_APWRw(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 data, int timeout)
Definition: ethercatbase.c:394
Headerfile for ethercatmain.c.
uint8 blockLRW
Definition: ethercatmain.h:287
uint32_t uint32
Definition: osal.h:35
int16 Ebuscurrent
Definition: ethercatmain.h:252
#define EC_TIMEOUTRET3
Definition: ethercattype.h:92
int ecx_FPWRw(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 data, int timeout)
Definition: ethercatbase.c:431
uint32 Ibytes
Definition: ethercatmain.h:168
uint8 EoEdetails
Definition: ethercatmain.h:248
uint32 Ibytes
Definition: ethercatmain.h:277
#define EC_DEFAULTMBXSM1
int16_t int16
Definition: osal.h:31
uint16 state
Definition: ethercatmain.h:140
uint16 configindex
Definition: ethercatmain.h:236
int ecx_readPDOmapCA(ecx_contextt *context, uint16 Slave, int *Osize, int *Isize)
Definition: ethercatcoe.c:940
uint8 * inputs
Definition: ethercatmain.h:279
#define EC_DEFAULTDOSM0
uint16 Itype
Definition: ethercatmain.h:154
uint32 ecx_readeeprom2(ecx_contextt *context, uint16 slave, int timeout)
uint16 PhStart
Definition: ethercatmain.h:320
PACKED_BEGIN struct PACKED ec_fmmut
Headerfile for ethercatconfig.c.
uint16 inputsWKC
Definition: ethercatmain.h:297
uint8 activeports
Definition: ethercatmain.h:206
uint8 * outputs
Definition: ethercatmain.h:275
uint16 configadr
Definition: ethercatmain.h:144
#define EC_MAXIOSEGMENTS
Definition: ethercatmain.h:64
uint16 ecx_siiFMMU(ecx_contextt *context, uint16 slave, ec_eepromFMMUt *FMMU)
Definition: ethercatmain.c:532
PACKED_END PACKED_BEGIN struct PACKED ec_smt
uint8 blockLRW
Definition: ethercatmain.h:254
uint32 eep_rev
Definition: ethercatmain.h:152
uint8 ptype
Definition: ethercatmain.h:202
int16 Ebuscurrent
Definition: ethercatmain.h:285
int ecx_FPRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:328
ec_eepromSMt * eepSM
Definition: ethercatmain.h:452
uint8 ecx_siigetbyte(ecx_contextt *context, uint16 slave, uint16 address)
Definition: ethercatmain.c:365
#define EC_ESTAT_R64
Definition: ethercattype.h:293
#define EC_DEFAULTMBXSM0
ec_fmmut FMMU[EC_MAXFMMU]
Definition: ethercatmain.h:178
int * slavecount
Definition: ethercatmain.h:420
uint8 Ostartbit
Definition: ethercatmain.h:164


youbot_driver
Author(s): Jan Paulus
autogenerated on Mon Jun 10 2019 15:46:24