Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: EasyCAT_LAB_simple EasyCAT_LAB_very_simple EasyCAT_LAB
ethercatconfig.c
00001 /* 00002 * Licensed under the GNU General Public License version 2 with exceptions. See 00003 * LICENSE file in the project root for full license information 00004 */ 00005 00006 /** \file 00007 * \brief 00008 * Configuration module for EtherCAT master. 00009 * 00010 * After successful initialisation with ec_init() or ec_init_redundant() 00011 * the slaves can be auto configured with this module. 00012 */ 00013 00014 #include <stdio.h> 00015 #include <string.h> 00016 #include "osal.h" 00017 #include "oshw.h" 00018 #include "ethercattype.h" 00019 #include "ethercatbase.h" 00020 #include "ethercatmain.h" 00021 #include "ethercatcoe.h" 00022 #include "ethercatsoe.h" 00023 #include "ethercatconfig.h" 00024 00025 00026 typedef struct 00027 { 00028 int thread_n; 00029 int running; 00030 ecx_contextt *context; 00031 uint16 slave; 00032 } ecx_mapt_t; 00033 00034 ecx_mapt_t ecx_mapt[EC_MAX_MAPT]; 00035 #if EC_MAX_MAPT > 1 00036 OSAL_THREAD_HANDLE ecx_threadh[EC_MAX_MAPT]; 00037 #endif 00038 00039 #ifdef EC_VER1 00040 /** Slave configuration structure */ 00041 typedef const struct 00042 { 00043 /** Manufacturer code of slave */ 00044 uint32 man; 00045 /** ID of slave */ 00046 uint32 id; 00047 /** Readable name */ 00048 char name[EC_MAXNAME + 1]; 00049 /** Data type */ 00050 uint8 Dtype; 00051 /** Input bits */ 00052 uint16 Ibits; 00053 /** Output bits */ 00054 uint16 Obits; 00055 /** SyncManager 2 address */ 00056 uint16 SM2a; 00057 /** SyncManager 2 flags */ 00058 uint32 SM2f; 00059 /** SyncManager 3 address */ 00060 uint16 SM3a; 00061 /** SyncManager 3 flags */ 00062 uint32 SM3f; 00063 /** FMMU 0 activation */ 00064 uint8 FM0ac; 00065 /** FMMU 1 activation */ 00066 uint8 FM1ac; 00067 } ec_configlist_t; 00068 00069 #include "ethercatconfiglist.h" 00070 #endif 00071 00072 /** standard SM0 flags configuration for mailbox slaves */ 00073 #define EC_DEFAULTMBXSM0 0x00010026 00074 /** standard SM1 flags configuration for mailbox slaves */ 00075 #define EC_DEFAULTMBXSM1 0x00010022 00076 /** standard SM0 flags configuration for digital output slaves */ 00077 #define EC_DEFAULTDOSM0 0x00010044 00078 00079 #ifdef EC_VER1 00080 /** Find slave in standard configuration list ec_configlist[] 00081 * 00082 * @param[in] man = manufacturer 00083 * @param[in] id = ID 00084 * @return index in ec_configlist[] when found, otherwise 0 00085 */ 00086 int ec_findconfig( uint32 man, uint32 id) 00087 { 00088 int i = 0; 00089 00090 do 00091 { 00092 i++; 00093 } while ( (ec_configlist[i].man != EC_CONFIGEND) && 00094 ((ec_configlist[i].man != man) || (ec_configlist[i].id != id)) ); 00095 if (ec_configlist[i].man == EC_CONFIGEND) 00096 { 00097 i = 0; 00098 } 00099 return i; 00100 } 00101 #endif 00102 00103 void ecx_init_context(ecx_contextt *context) 00104 { 00105 int lp; 00106 *(context->slavecount) = 0; 00107 /* clean ec_slave array */ 00108 memset(context->slavelist, 0x00, sizeof(ec_slavet) * context->maxslave); 00109 memset(context->grouplist, 0x00, sizeof(ec_groupt) * context->maxgroup); 00110 /* clear slave eeprom cache, does not actually read any eeprom */ 00111 ecx_siigetbyte(context, 0, EC_MAXEEPBUF); 00112 for(lp = 0; lp < context->maxgroup; lp++) 00113 { 00114 /* default start address per group entry */ 00115 context->grouplist[lp].logstartaddr = lp << EC_LOGGROUPOFFSET; 00116 } 00117 } 00118 00119 int ecx_detect_slaves(ecx_contextt *context) 00120 { 00121 uint8 b; 00122 uint16 w; 00123 int wkc; 00124 00125 /* make special pre-init register writes to enable MAC[1] local administered bit * 00126 * setting for old netX100 slaves */ 00127 b = 0x00; 00128 ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3); /* Ignore Alias register */ 00129 b = EC_STATE_INIT | EC_STATE_ACK; 00130 ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */ 00131 /* netX100 should now be happy */ 00132 ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */ 00133 wkc = ecx_BRD(context->port, 0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE); /* detect number of slaves */ 00134 if (wkc > 0) 00135 { 00136 /* this is strictly "less than" since the master is "slave 0" */ 00137 if (wkc < EC_MAXSLAVE) 00138 { 00139 *(context->slavecount) = wkc; 00140 } 00141 else 00142 { 00143 EC_PRINT("Error: too many slaves on network: num_slaves=%d, EC_MAXSLAVE=%d\n", 00144 wkc, EC_MAXSLAVE); 00145 return -2; 00146 } 00147 } 00148 return wkc; 00149 } 00150 00151 static void ecx_set_slaves_to_default(ecx_contextt *context) 00152 { 00153 uint8 b; 00154 uint16 w; 00155 uint8 zbuf[64]; 00156 memset(&zbuf, 0x00, sizeof(zbuf)); 00157 b = 0x00; 00158 ecx_BWR(context->port, 0x0000, ECT_REG_DLPORT , sizeof(b) , &b, EC_TIMEOUTRET3); /* deact loop manual */ 00159 w = htoes(0x0004); 00160 ecx_BWR(context->port, 0x0000, ECT_REG_IRQMASK , sizeof(w) , &w, EC_TIMEOUTRET3); /* set IRQ mask */ 00161 ecx_BWR(context->port, 0x0000, ECT_REG_RXERR , 8 , &zbuf, EC_TIMEOUTRET3); /* reset CRC counters */ 00162 ecx_BWR(context->port, 0x0000, ECT_REG_FMMU0 , 16 * 3 , &zbuf, EC_TIMEOUTRET3); /* reset FMMU's */ 00163 ecx_BWR(context->port, 0x0000, ECT_REG_SM0 , 8 * 4 , &zbuf, EC_TIMEOUTRET3); /* reset SyncM */ 00164 b = 0x00; 00165 ecx_BWR(context->port, 0x0000, ECT_REG_DCSYNCACT , sizeof(b) , &b, EC_TIMEOUTRET3); /* reset activation register */ 00166 ecx_BWR(context->port, 0x0000, ECT_REG_DCSYSTIME , 4 , &zbuf, EC_TIMEOUTRET3); /* reset system time+ofs */ 00167 w = htoes(0x1000); 00168 ecx_BWR(context->port, 0x0000, ECT_REG_DCSPEEDCNT , sizeof(w) , &w, EC_TIMEOUTRET3); /* DC speedstart */ 00169 w = htoes(0x0c00); 00170 ecx_BWR(context->port, 0x0000, ECT_REG_DCTIMEFILT , sizeof(w) , &w, EC_TIMEOUTRET3); /* DC filt expr */ 00171 b = 0x00; 00172 ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS , sizeof(b) , &b, EC_TIMEOUTRET3); /* Ignore Alias register */ 00173 b = EC_STATE_INIT | EC_STATE_ACK; 00174 ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL , sizeof(b) , &b, EC_TIMEOUTRET3); /* Reset all slaves to Init */ 00175 b = 2; 00176 ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG , sizeof(b) , &b, EC_TIMEOUTRET3); /* force Eeprom from PDI */ 00177 b = 0; 00178 ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG , sizeof(b) , &b, EC_TIMEOUTRET3); /* set Eeprom to master */ 00179 } 00180 00181 #ifdef EC_VER1 00182 static int ecx_config_from_table(ecx_contextt *context, uint16 slave) 00183 { 00184 int cindex; 00185 ec_slavet *csl; 00186 00187 csl = &(context->slavelist[slave]); 00188 cindex = ec_findconfig( csl->eep_man, csl->eep_id ); 00189 csl->configindex= cindex; 00190 /* slave found in configuration table ? */ 00191 if (cindex) 00192 { 00193 csl->Dtype = ec_configlist[cindex].Dtype; 00194 strcpy(csl->name ,ec_configlist[cindex].name); 00195 csl->Ibits = ec_configlist[cindex].Ibits; 00196 csl->Obits = ec_configlist[cindex].Obits; 00197 if (csl->Obits) 00198 { 00199 csl->FMMU0func = 1; 00200 } 00201 if (csl->Ibits) 00202 { 00203 csl->FMMU1func = 2; 00204 } 00205 csl->FMMU[0].FMMUactive = ec_configlist[cindex].FM0ac; 00206 csl->FMMU[1].FMMUactive = ec_configlist[cindex].FM1ac; 00207 csl->SM[2].StartAddr = htoes(ec_configlist[cindex].SM2a); 00208 csl->SM[2].SMflags = htoel(ec_configlist[cindex].SM2f); 00209 /* simple (no mailbox) output slave found ? */ 00210 if (csl->Obits && !csl->SM[2].StartAddr) 00211 { 00212 csl->SM[0].StartAddr = htoes(0x0f00); 00213 csl->SM[0].SMlength = htoes((csl->Obits + 7) / 8); 00214 csl->SM[0].SMflags = htoel(EC_DEFAULTDOSM0); 00215 csl->FMMU[0].FMMUactive = 1; 00216 csl->FMMU[0].FMMUtype = 2; 00217 csl->SMtype[0] = 3; 00218 } 00219 /* complex output slave */ 00220 else 00221 { 00222 csl->SM[2].SMlength = htoes((csl->Obits + 7) / 8); 00223 csl->SMtype[2] = 3; 00224 } 00225 csl->SM[3].StartAddr = htoes(ec_configlist[cindex].SM3a); 00226 csl->SM[3].SMflags = htoel(ec_configlist[cindex].SM3f); 00227 /* simple (no mailbox) input slave found ? */ 00228 if (csl->Ibits && !csl->SM[3].StartAddr) 00229 { 00230 csl->SM[1].StartAddr = htoes(0x1000); 00231 csl->SM[1].SMlength = htoes((csl->Ibits + 7) / 8); 00232 csl->SM[1].SMflags = htoel(0x00000000); 00233 csl->FMMU[1].FMMUactive = 1; 00234 csl->FMMU[1].FMMUtype = 1; 00235 csl->SMtype[1] = 4; 00236 } 00237 /* complex input slave */ 00238 else 00239 { 00240 csl->SM[3].SMlength = htoes((csl->Ibits + 7) / 8); 00241 csl->SMtype[3] = 4; 00242 } 00243 } 00244 return cindex; 00245 } 00246 #else 00247 static int ecx_config_from_table(ecx_contextt *context, uint16 slave) 00248 { 00249 (void)context; 00250 (void)slave; 00251 return 0; 00252 } 00253 #endif 00254 00255 /* If slave has SII and same slave ID done before, use previous data. 00256 * This is safe because SII is constant for same slave ID. 00257 */ 00258 static int ecx_lookup_prev_sii(ecx_contextt *context, uint16 slave) 00259 { 00260 int i, nSM; 00261 if ((slave > 1) && (*(context->slavecount) > 0)) 00262 { 00263 i = 1; 00264 while(((context->slavelist[i].eep_man != context->slavelist[slave].eep_man) || 00265 (context->slavelist[i].eep_id != context->slavelist[slave].eep_id ) || 00266 (context->slavelist[i].eep_rev != context->slavelist[slave].eep_rev)) && 00267 (i < slave)) 00268 { 00269 i++; 00270 } 00271 if(i < slave) 00272 { 00273 context->slavelist[slave].CoEdetails = context->slavelist[i].CoEdetails; 00274 context->slavelist[slave].FoEdetails = context->slavelist[i].FoEdetails; 00275 context->slavelist[slave].EoEdetails = context->slavelist[i].EoEdetails; 00276 context->slavelist[slave].SoEdetails = context->slavelist[i].SoEdetails; 00277 if(context->slavelist[i].blockLRW > 0) 00278 { 00279 context->slavelist[slave].blockLRW = 1; 00280 context->slavelist[0].blockLRW++; 00281 } 00282 context->slavelist[slave].Ebuscurrent = context->slavelist[i].Ebuscurrent; 00283 context->slavelist[0].Ebuscurrent += context->slavelist[slave].Ebuscurrent; 00284 memcpy(context->slavelist[slave].name, context->slavelist[i].name, EC_MAXNAME + 1); 00285 for( nSM=0 ; nSM < EC_MAXSM ; nSM++ ) 00286 { 00287 context->slavelist[slave].SM[nSM].StartAddr = context->slavelist[i].SM[nSM].StartAddr; 00288 context->slavelist[slave].SM[nSM].SMlength = context->slavelist[i].SM[nSM].SMlength; 00289 context->slavelist[slave].SM[nSM].SMflags = context->slavelist[i].SM[nSM].SMflags; 00290 } 00291 context->slavelist[slave].FMMU0func = context->slavelist[i].FMMU0func; 00292 context->slavelist[slave].FMMU1func = context->slavelist[i].FMMU1func; 00293 context->slavelist[slave].FMMU2func = context->slavelist[i].FMMU2func; 00294 context->slavelist[slave].FMMU3func = context->slavelist[i].FMMU3func; 00295 EC_PRINT("Copy SII slave %d from %d.\n", slave, i); 00296 return 1; 00297 } 00298 } 00299 return 0; 00300 } 00301 00302 /** Enumerate and init all slaves. 00303 * 00304 * @param[in] context = context struct 00305 * @param[in] usetable = TRUE when using configtable to init slaves, FALSE otherwise 00306 * @return Workcounter of slave discover datagram = number of slaves found 00307 */ 00308 int ecx_config_init(ecx_contextt *context, uint8 usetable) 00309 { 00310 uint16 slave, ADPh, configadr, ssigen; 00311 uint16 topology, estat; 00312 int16 topoc, slavec, aliasadr; 00313 uint8 b,h; 00314 uint8 SMc; 00315 uint32 eedat; 00316 int wkc, cindex, nSM; 00317 uint16 val16; 00318 00319 EC_PRINT("ec_config_init %d\n",usetable); 00320 ecx_init_context(context); 00321 wkc = ecx_detect_slaves(context); 00322 if (wkc > 0) 00323 { 00324 ecx_set_slaves_to_default(context); 00325 for (slave = 1; slave <= *(context->slavecount); slave++) 00326 { 00327 ADPh = (uint16)(1 - slave); 00328 val16 = ecx_APRDw(context->port, ADPh, ECT_REG_PDICTL, EC_TIMEOUTRET3); /* read interface type of slave */ 00329 context->slavelist[slave].Itype = etohs(val16); 00330 /* a node offset is used to improve readability of network frames */ 00331 /* this has no impact on the number of addressable slaves (auto wrap around) */ 00332 ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(slave + EC_NODEOFFSET) , EC_TIMEOUTRET3); /* set node address of slave */ 00333 if (slave == 1) 00334 { 00335 b = 1; /* kill non ecat frames for first slave */ 00336 } 00337 else 00338 { 00339 b = 0; /* pass all frames for following slaves */ 00340 } 00341 ecx_APWRw(context->port, ADPh, ECT_REG_DLCTL, htoes(b), EC_TIMEOUTRET3); /* set non ecat frame behaviour */ 00342 configadr = ecx_APRDw(context->port, ADPh, ECT_REG_STADR, EC_TIMEOUTRET3); 00343 configadr = etohs(configadr); 00344 context->slavelist[slave].configadr = configadr; 00345 ecx_FPRD(context->port, configadr, ECT_REG_ALIAS, sizeof(aliasadr), &aliasadr, EC_TIMEOUTRET3); 00346 context->slavelist[slave].aliasadr = etohs(aliasadr); 00347 ecx_FPRD(context->port, configadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET3); 00348 estat = etohs(estat); 00349 if (estat & EC_ESTAT_R64) /* check if slave can read 8 byte chunks */ 00350 { 00351 context->slavelist[slave].eep_8byte = 1; 00352 } 00353 ecx_readeeprom1(context, slave, ECT_SII_MANUF); /* Manuf */ 00354 } 00355 for (slave = 1; slave <= *(context->slavecount); slave++) 00356 { 00357 eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* Manuf */ 00358 context->slavelist[slave].eep_man = etohl(eedat); 00359 ecx_readeeprom1(context, slave, ECT_SII_ID); /* ID */ 00360 } 00361 for (slave = 1; slave <= *(context->slavecount); slave++) 00362 { 00363 eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* ID */ 00364 context->slavelist[slave].eep_id = etohl(eedat); 00365 ecx_readeeprom1(context, slave, ECT_SII_REV); /* revision */ 00366 } 00367 for (slave = 1; slave <= *(context->slavecount); slave++) 00368 { 00369 eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* revision */ 00370 context->slavelist[slave].eep_rev = etohl(eedat); 00371 ecx_readeeprom1(context, slave, ECT_SII_RXMBXADR); /* write mailbox address + mailboxsize */ 00372 } 00373 for (slave = 1; slave <= *(context->slavecount); slave++) 00374 { 00375 eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* write mailbox address and mailboxsize */ 00376 context->slavelist[slave].mbx_wo = (uint16)LO_WORD(etohl(eedat)); 00377 context->slavelist[slave].mbx_l = (uint16)HI_WORD(etohl(eedat)); 00378 if (context->slavelist[slave].mbx_l > 0) 00379 { 00380 ecx_readeeprom1(context, slave, ECT_SII_TXMBXADR); /* read mailbox offset */ 00381 } 00382 } 00383 for (slave = 1; slave <= *(context->slavecount); slave++) 00384 { 00385 if (context->slavelist[slave].mbx_l > 0) 00386 { 00387 eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); /* read mailbox offset */ 00388 context->slavelist[slave].mbx_ro = (uint16)LO_WORD(etohl(eedat)); /* read mailbox offset */ 00389 context->slavelist[slave].mbx_rl = (uint16)HI_WORD(etohl(eedat)); /*read mailbox length */ 00390 if (context->slavelist[slave].mbx_rl == 0) 00391 { 00392 context->slavelist[slave].mbx_rl = context->slavelist[slave].mbx_l; 00393 } 00394 ecx_readeeprom1(context, slave, ECT_SII_MBXPROTO); 00395 } 00396 configadr = context->slavelist[slave].configadr; 00397 val16 = ecx_FPRDw(context->port, configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET3); 00398 if ((etohs(val16) & 0x04) > 0) /* Support DC? */ 00399 { 00400 context->slavelist[slave].hasdc = TRUE; 00401 } 00402 else 00403 { 00404 context->slavelist[slave].hasdc = FALSE; 00405 } 00406 topology = ecx_FPRDw(context->port, configadr, ECT_REG_DLSTAT, EC_TIMEOUTRET3); /* extract topology from DL status */ 00407 topology = etohs(topology); 00408 h = 0; 00409 b = 0; 00410 if ((topology & 0x0300) == 0x0200) /* port0 open and communication established */ 00411 { 00412 h++; 00413 b |= 0x01; 00414 } 00415 if ((topology & 0x0c00) == 0x0800) /* port1 open and communication established */ 00416 { 00417 h++; 00418 b |= 0x02; 00419 } 00420 if ((topology & 0x3000) == 0x2000) /* port2 open and communication established */ 00421 { 00422 h++; 00423 b |= 0x04; 00424 } 00425 if ((topology & 0xc000) == 0x8000) /* port3 open and communication established */ 00426 { 00427 h++; 00428 b |= 0x08; 00429 } 00430 /* ptype = Physical type*/ 00431 val16 = ecx_FPRDw(context->port, configadr, ECT_REG_PORTDES, EC_TIMEOUTRET3); 00432 context->slavelist[slave].ptype = LO_BYTE(etohs(val16)); 00433 context->slavelist[slave].topology = h; 00434 context->slavelist[slave].activeports = b; 00435 /* 0=no links, not possible */ 00436 /* 1=1 link , end of line */ 00437 /* 2=2 links , one before and one after */ 00438 /* 3=3 links , split point */ 00439 /* 4=4 links , cross point */ 00440 /* search for parent */ 00441 context->slavelist[slave].parent = 0; /* parent is master */ 00442 if (slave > 1) 00443 { 00444 topoc = 0; 00445 slavec = slave - 1; 00446 do 00447 { 00448 topology = context->slavelist[slavec].topology; 00449 if (topology == 1) 00450 { 00451 topoc--; /* endpoint found */ 00452 } 00453 if (topology == 3) 00454 { 00455 topoc++; /* split found */ 00456 } 00457 if (topology == 4) 00458 { 00459 topoc += 2; /* cross found */ 00460 } 00461 if (((topoc >= 0) && (topology > 1)) || 00462 (slavec == 1)) /* parent found */ 00463 { 00464 context->slavelist[slave].parent = slavec; 00465 slavec = 1; 00466 } 00467 slavec--; 00468 } 00469 while (slavec > 0); 00470 } 00471 (void)ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE); //* check state change Init */ 00472 00473 /* set default mailbox configuration if slave has mailbox */ 00474 if (context->slavelist[slave].mbx_l>0) 00475 { 00476 context->slavelist[slave].SMtype[0] = 1; 00477 context->slavelist[slave].SMtype[1] = 2; 00478 context->slavelist[slave].SMtype[2] = 3; 00479 context->slavelist[slave].SMtype[3] = 4; 00480 context->slavelist[slave].SM[0].StartAddr = htoes(context->slavelist[slave].mbx_wo); 00481 context->slavelist[slave].SM[0].SMlength = htoes(context->slavelist[slave].mbx_l); 00482 context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0); 00483 context->slavelist[slave].SM[1].StartAddr = htoes(context->slavelist[slave].mbx_ro); 00484 context->slavelist[slave].SM[1].SMlength = htoes(context->slavelist[slave].mbx_rl); 00485 context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1); 00486 eedat = ecx_readeeprom2(context, slave, EC_TIMEOUTEEP); 00487 context->slavelist[slave].mbx_proto = etohl(eedat); 00488 } 00489 cindex = 0; 00490 /* use configuration table ? */ 00491 if (usetable == 1) 00492 { 00493 cindex = ecx_config_from_table(context, slave); 00494 } 00495 /* slave not in configuration table, find out via SII */ 00496 if (!cindex && !ecx_lookup_prev_sii(context, slave)) 00497 { 00498 ssigen = ecx_siifind(context, slave, ECT_SII_GENERAL); 00499 /* SII general section */ 00500 if (ssigen) 00501 { 00502 context->slavelist[slave].CoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x07); 00503 context->slavelist[slave].FoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x08); 00504 context->slavelist[slave].EoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x09); 00505 context->slavelist[slave].SoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x0a); 00506 if((ecx_siigetbyte(context, slave, ssigen + 0x0d) & 0x02) > 0) 00507 { 00508 context->slavelist[slave].blockLRW = 1; 00509 context->slavelist[0].blockLRW++; 00510 } 00511 context->slavelist[slave].Ebuscurrent = ecx_siigetbyte(context, slave, ssigen + 0x0e); 00512 context->slavelist[slave].Ebuscurrent += ecx_siigetbyte(context, slave, ssigen + 0x0f) << 8; 00513 context->slavelist[0].Ebuscurrent += context->slavelist[slave].Ebuscurrent; 00514 } 00515 /* SII strings section */ 00516 if (ecx_siifind(context, slave, ECT_SII_STRING) > 0) 00517 { 00518 ecx_siistring(context, context->slavelist[slave].name, slave, 1); 00519 } 00520 /* no name for slave found, use constructed name */ 00521 else 00522 { 00523 sprintf(context->slavelist[slave].name, "? M:%8.8x I:%8.8x", 00524 (unsigned int)context->slavelist[slave].eep_man, 00525 (unsigned int)context->slavelist[slave].eep_id); 00526 } 00527 /* SII SM section */ 00528 nSM = ecx_siiSM(context, slave, context->eepSM); 00529 if (nSM>0) 00530 { 00531 context->slavelist[slave].SM[0].StartAddr = htoes(context->eepSM->PhStart); 00532 context->slavelist[slave].SM[0].SMlength = htoes(context->eepSM->Plength); 00533 context->slavelist[slave].SM[0].SMflags = 00534 htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16)); 00535 SMc = 1; 00536 while ((SMc < EC_MAXSM) && ecx_siiSMnext(context, slave, context->eepSM, SMc)) 00537 { 00538 context->slavelist[slave].SM[SMc].StartAddr = htoes(context->eepSM->PhStart); 00539 context->slavelist[slave].SM[SMc].SMlength = htoes(context->eepSM->Plength); 00540 context->slavelist[slave].SM[SMc].SMflags = 00541 htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16)); 00542 SMc++; 00543 } 00544 } 00545 /* SII FMMU section */ 00546 if (ecx_siiFMMU(context, slave, context->eepFMMU)) 00547 { 00548 if (context->eepFMMU->FMMU0 !=0xff) 00549 { 00550 context->slavelist[slave].FMMU0func = context->eepFMMU->FMMU0; 00551 } 00552 if (context->eepFMMU->FMMU1 !=0xff) 00553 { 00554 context->slavelist[slave].FMMU1func = context->eepFMMU->FMMU1; 00555 } 00556 if (context->eepFMMU->FMMU2 !=0xff) 00557 { 00558 context->slavelist[slave].FMMU2func = context->eepFMMU->FMMU2; 00559 } 00560 if (context->eepFMMU->FMMU3 !=0xff) 00561 { 00562 context->slavelist[slave].FMMU3func = context->eepFMMU->FMMU3; 00563 } 00564 } 00565 } 00566 00567 if (context->slavelist[slave].mbx_l > 0) 00568 { 00569 if (context->slavelist[slave].SM[0].StartAddr == 0x0000) /* should never happen */ 00570 { 00571 EC_PRINT("Slave %d has no proper mailbox in configuration, try default.\n", slave); 00572 context->slavelist[slave].SM[0].StartAddr = htoes(0x1000); 00573 context->slavelist[slave].SM[0].SMlength = htoes(0x0080); 00574 context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0); 00575 context->slavelist[slave].SMtype[0] = 1; 00576 } 00577 if (context->slavelist[slave].SM[1].StartAddr == 0x0000) /* should never happen */ 00578 { 00579 EC_PRINT("Slave %d has no proper mailbox out configuration, try default.\n", slave); 00580 context->slavelist[slave].SM[1].StartAddr = htoes(0x1080); 00581 context->slavelist[slave].SM[1].SMlength = htoes(0x0080); 00582 context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1); 00583 context->slavelist[slave].SMtype[1] = 2; 00584 } 00585 /* program SM0 mailbox in and SM1 mailbox out for slave */ 00586 /* writing both SM in one datagram will solve timing issue in old NETX */ 00587 ecx_FPWR(context->port, configadr, ECT_REG_SM0, sizeof(ec_smt) * 2, 00588 &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3); 00589 } 00590 /* some slaves need eeprom available to PDI in init->preop transition */ 00591 ecx_eeprom2pdi(context, slave); 00592 /* request pre_op for slave */ 00593 ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP | EC_STATE_ACK) , EC_TIMEOUTRET3); /* set preop status */ 00594 } 00595 } 00596 return wkc; 00597 } 00598 00599 /* If slave has SII mapping and same slave ID done before, use previous mapping. 00600 * This is safe because SII mapping is constant for same slave ID. 00601 */ 00602 static int ecx_lookup_mapping(ecx_contextt *context, uint16 slave, int *Osize, int *Isize) 00603 { 00604 int i, nSM; 00605 if ((slave > 1) && (*(context->slavecount) > 0)) 00606 { 00607 i = 1; 00608 while(((context->slavelist[i].eep_man != context->slavelist[slave].eep_man) || 00609 (context->slavelist[i].eep_id != context->slavelist[slave].eep_id ) || 00610 (context->slavelist[i].eep_rev != context->slavelist[slave].eep_rev)) && 00611 (i < slave)) 00612 { 00613 i++; 00614 } 00615 if(i < slave) 00616 { 00617 for( nSM=0 ; nSM < EC_MAXSM ; nSM++ ) 00618 { 00619 context->slavelist[slave].SM[nSM].SMlength = context->slavelist[i].SM[nSM].SMlength; 00620 context->slavelist[slave].SMtype[nSM] = context->slavelist[i].SMtype[nSM]; 00621 } 00622 *Osize = context->slavelist[i].Obits; 00623 *Isize = context->slavelist[i].Ibits; 00624 context->slavelist[slave].Obits = *Osize; 00625 context->slavelist[slave].Ibits = *Isize; 00626 EC_PRINT("Copy mapping slave %d from %d.\n", slave, i); 00627 return 1; 00628 } 00629 } 00630 return 0; 00631 } 00632 00633 static int ecx_map_coe_soe(ecx_contextt *context, uint16 slave, int thread_n) 00634 { 00635 int Isize, Osize; 00636 int rval; 00637 00638 ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */ 00639 00640 EC_PRINT(" >Slave %d, configadr %x, state %2.2x\n", 00641 slave, context->slavelist[slave].configadr, context->slavelist[slave].state); 00642 00643 /* execute special slave configuration hook Pre-Op to Safe-OP */ 00644 if(context->slavelist[slave].PO2SOconfig) /* only if registered */ 00645 { 00646 context->slavelist[slave].PO2SOconfig(slave); 00647 } 00648 /* if slave not found in configlist find IO mapping in slave self */ 00649 if (!context->slavelist[slave].configindex) 00650 { 00651 Isize = 0; 00652 Osize = 0; 00653 if (context->slavelist[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */ 00654 { 00655 rval = 0; 00656 if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */ 00657 { 00658 /* read PDO mapping via CoE and use Complete Access */ 00659 rval = ecx_readPDOmapCA(context, slave, thread_n, &Osize, &Isize); 00660 } 00661 if (!rval) /* CA not available or not succeeded */ 00662 { 00663 /* read PDO mapping via CoE */ 00664 rval = ecx_readPDOmap(context, slave, &Osize, &Isize); 00665 } 00666 EC_PRINT(" CoE Osize:%d Isize:%d\n", Osize, Isize); 00667 } 00668 if ((!Isize && !Osize) && (context->slavelist[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */ 00669 { 00670 /* read AT / MDT mapping via SoE */ 00671 rval = ecx_readIDNmap(context, slave, &Osize, &Isize); 00672 context->slavelist[slave].SM[2].SMlength = htoes((Osize + 7) / 8); 00673 context->slavelist[slave].SM[3].SMlength = htoes((Isize + 7) / 8); 00674 EC_PRINT(" SoE Osize:%d Isize:%d\n", Osize, Isize); 00675 } 00676 context->slavelist[slave].Obits = Osize; 00677 context->slavelist[slave].Ibits = Isize; 00678 } 00679 00680 return 1; 00681 } 00682 00683 static int ecx_map_sii(ecx_contextt *context, uint16 slave) 00684 { 00685 int Isize, Osize; 00686 int nSM; 00687 ec_eepromPDOt eepPDO; 00688 00689 Osize = context->slavelist[slave].Obits; 00690 Isize = context->slavelist[slave].Ibits; 00691 00692 if (!Isize && !Osize) /* find PDO in previous slave with same ID */ 00693 { 00694 (void)ecx_lookup_mapping(context, slave, &Osize, &Isize); 00695 } 00696 if (!Isize && !Osize) /* find PDO mapping by SII */ 00697 { 00698 memset(&eepPDO, 0, sizeof(eepPDO)); 00699 Isize = (int)ecx_siiPDO(context, slave, &eepPDO, 0); 00700 EC_PRINT(" SII Isize:%d\n", Isize); 00701 for( nSM=0 ; nSM < EC_MAXSM ; nSM++ ) 00702 { 00703 if (eepPDO.SMbitsize[nSM] > 0) 00704 { 00705 context->slavelist[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8); 00706 context->slavelist[slave].SMtype[nSM] = 4; 00707 EC_PRINT(" SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]); 00708 } 00709 } 00710 Osize = (int)ecx_siiPDO(context, slave, &eepPDO, 1); 00711 EC_PRINT(" SII Osize:%d\n", Osize); 00712 for( nSM=0 ; nSM < EC_MAXSM ; nSM++ ) 00713 { 00714 if (eepPDO.SMbitsize[nSM] > 0) 00715 { 00716 context->slavelist[slave].SM[nSM].SMlength = htoes((eepPDO.SMbitsize[nSM] + 7) / 8); 00717 context->slavelist[slave].SMtype[nSM] = 3; 00718 EC_PRINT(" SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]); 00719 } 00720 } 00721 } 00722 context->slavelist[slave].Obits = Osize; 00723 context->slavelist[slave].Ibits = Isize; 00724 EC_PRINT(" ISIZE:%d %d OSIZE:%d\n", 00725 context->slavelist[slave].Ibits, Isize,context->slavelist[slave].Obits); 00726 00727 return 1; 00728 } 00729 00730 static int ecx_map_sm(ecx_contextt *context, uint16 slave) 00731 { 00732 uint16 configadr; 00733 int nSM; 00734 00735 configadr = context->slavelist[slave].configadr; 00736 00737 EC_PRINT(" SM programming\n"); 00738 if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[0].StartAddr) 00739 { 00740 ecx_FPWR(context->port, configadr, ECT_REG_SM0, 00741 sizeof(ec_smt), &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3); 00742 EC_PRINT(" SM0 Type:%d StartAddr:%4.4x Flags:%8.8x\n", 00743 context->slavelist[slave].SMtype[0], 00744 context->slavelist[slave].SM[0].StartAddr, 00745 context->slavelist[slave].SM[0].SMflags); 00746 } 00747 if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[1].StartAddr) 00748 { 00749 ecx_FPWR(context->port, configadr, ECT_REG_SM1, 00750 sizeof(ec_smt), &context->slavelist[slave].SM[1], EC_TIMEOUTRET3); 00751 EC_PRINT(" SM1 Type:%d StartAddr:%4.4x Flags:%8.8x\n", 00752 context->slavelist[slave].SMtype[1], 00753 context->slavelist[slave].SM[1].StartAddr, 00754 context->slavelist[slave].SM[1].SMflags); 00755 } 00756 /* program SM2 to SMx */ 00757 for( nSM = 2 ; nSM < EC_MAXSM ; nSM++ ) 00758 { 00759 if (context->slavelist[slave].SM[nSM].StartAddr) 00760 { 00761 /* check if SM length is zero -> clear enable flag */ 00762 if( context->slavelist[slave].SM[nSM].SMlength == 0) 00763 { 00764 context->slavelist[slave].SM[nSM].SMflags = 00765 htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) & EC_SMENABLEMASK); 00766 } 00767 /* if SM length is non zero always set enable flag */ 00768 else 00769 { 00770 context->slavelist[slave].SM[nSM].SMflags = 00771 htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) | ~EC_SMENABLEMASK); 00772 } 00773 ecx_FPWR(context->port, configadr, (uint16)(ECT_REG_SM0 + (nSM * sizeof(ec_smt))), 00774 sizeof(ec_smt), &context->slavelist[slave].SM[nSM], EC_TIMEOUTRET3); 00775 EC_PRINT(" SM%d Type:%d StartAddr:%4.4x Flags:%8.8x\n", nSM, 00776 context->slavelist[slave].SMtype[nSM], 00777 context->slavelist[slave].SM[nSM].StartAddr, 00778 context->slavelist[slave].SM[nSM].SMflags); 00779 } 00780 } 00781 if (context->slavelist[slave].Ibits > 7) 00782 { 00783 context->slavelist[slave].Ibytes = (context->slavelist[slave].Ibits + 7) / 8; 00784 } 00785 if (context->slavelist[slave].Obits > 7) 00786 { 00787 context->slavelist[slave].Obytes = (context->slavelist[slave].Obits + 7) / 8; 00788 } 00789 00790 return 1; 00791 } 00792 00793 #if EC_MAX_MAPT > 1 00794 OSAL_THREAD_FUNC ecx_mapper_thread(void *param) 00795 { 00796 ecx_mapt_t *maptp; 00797 maptp = param; 00798 ecx_map_coe_soe(maptp->context, maptp->slave, maptp->thread_n); 00799 maptp->running = 0; 00800 } 00801 00802 static int ecx_find_mapt(void) 00803 { 00804 int p; 00805 p = 0; 00806 while((p < EC_MAX_MAPT) && ecx_mapt[p].running) 00807 { 00808 p++; 00809 } 00810 if(p < EC_MAX_MAPT) 00811 { 00812 return p; 00813 } 00814 else 00815 { 00816 return -1; 00817 } 00818 } 00819 #endif 00820 00821 static int ecx_get_threadcount(void) 00822 { 00823 int thrc, thrn; 00824 thrc = 0; 00825 for(thrn = 0 ; thrn < EC_MAX_MAPT ; thrn++) 00826 { 00827 thrc += ecx_mapt[thrn].running; 00828 } 00829 return thrc; 00830 } 00831 00832 static void ecx_config_find_mappings(ecx_contextt *context, uint8 group) 00833 { 00834 int thrn, thrc; 00835 uint16 slave; 00836 00837 for (thrn = 0; thrn < EC_MAX_MAPT; thrn++) 00838 { 00839 ecx_mapt[thrn].running = 0; 00840 } 00841 /* find CoE and SoE mapping of slaves in multiple threads */ 00842 for (slave = 1; slave <= *(context->slavecount); slave++) 00843 { 00844 if (!group || (group == context->slavelist[slave].group)) 00845 { 00846 #if EC_MAX_MAPT > 1 00847 /* multi-threaded version */ 00848 while ((thrn = ecx_find_mapt()) < 0) 00849 { 00850 osal_usleep(1000); 00851 } 00852 ecx_mapt[thrn].context = context; 00853 ecx_mapt[thrn].slave = slave; 00854 ecx_mapt[thrn].thread_n = thrn; 00855 ecx_mapt[thrn].running = 1; 00856 osal_thread_create(&(ecx_threadh[thrn]), 128000, 00857 &ecx_mapper_thread, &(ecx_mapt[thrn])); 00858 #else 00859 /* serialised version */ 00860 ecx_map_coe_soe(context, slave, 0); 00861 #endif 00862 } 00863 } 00864 /* wait for all threads to finish */ 00865 do 00866 { 00867 thrc = ecx_get_threadcount(); 00868 if (thrc) 00869 { 00870 osal_usleep(1000); 00871 } 00872 } while (thrc); 00873 /* find SII mapping of slave and program SM */ 00874 for (slave = 1; slave <= *(context->slavecount); slave++) 00875 { 00876 if (!group || (group == context->slavelist[slave].group)) 00877 { 00878 ecx_map_sii(context, slave); 00879 ecx_map_sm(context, slave); 00880 } 00881 } 00882 } 00883 00884 static void ecx_config_create_input_mappings(ecx_contextt *context, void *pIOmap, 00885 uint8 group, int16 slave, uint32 * LogAddr, uint8 * BitPos) 00886 { 00887 int BitCount = 0; 00888 int ByteCount = 0; 00889 int FMMUsize = 0; 00890 int FMMUdone = 0; 00891 uint8 SMc = 0; 00892 uint16 EndAddr; 00893 uint16 SMlength; 00894 uint16 configadr; 00895 uint8 FMMUc; 00896 00897 EC_PRINT(" =Slave %d, INPUT MAPPING\n", slave); 00898 00899 configadr = context->slavelist[slave].configadr; 00900 FMMUc = context->slavelist[slave].FMMUunused; 00901 if (context->slavelist[slave].Obits) /* find free FMMU */ 00902 { 00903 while (context->slavelist[slave].FMMU[FMMUc].LogStart) 00904 { 00905 FMMUc++; 00906 } 00907 } 00908 /* search for SM that contribute to the input mapping */ 00909 while ((SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Ibits + 7) / 8))) 00910 { 00911 EC_PRINT(" FMMU %d\n", FMMUc); 00912 while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) 00913 { 00914 SMc++; 00915 } 00916 EC_PRINT(" SM%d\n", SMc); 00917 context->slavelist[slave].FMMU[FMMUc].PhysStart = 00918 context->slavelist[slave].SM[SMc].StartAddr; 00919 SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength); 00920 ByteCount += SMlength; 00921 BitCount += SMlength * 8; 00922 EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength; 00923 while ((BitCount < context->slavelist[slave].Ibits) && (SMc < (EC_MAXSM - 1))) /* more SM for input */ 00924 { 00925 SMc++; 00926 while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) 00927 { 00928 SMc++; 00929 } 00930 /* if addresses from more SM connect use one FMMU otherwise break up in multiple FMMU */ 00931 if (etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr) 00932 { 00933 break; 00934 } 00935 EC_PRINT(" SM%d\n", SMc); 00936 SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength); 00937 ByteCount += SMlength; 00938 BitCount += SMlength * 8; 00939 EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength; 00940 } 00941 00942 /* bit oriented slave */ 00943 if (!context->slavelist[slave].Ibytes) 00944 { 00945 context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr); 00946 context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos; 00947 *BitPos += context->slavelist[slave].Ibits - 1; 00948 if (*BitPos > 7) 00949 { 00950 *LogAddr += 1; 00951 *BitPos -= 8; 00952 } 00953 FMMUsize = *LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1; 00954 context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize); 00955 context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos; 00956 *BitPos += 1; 00957 if (*BitPos > 7) 00958 { 00959 *LogAddr += 1; 00960 *BitPos -= 8; 00961 } 00962 } 00963 /* byte oriented slave */ 00964 else 00965 { 00966 if (*BitPos) 00967 { 00968 *LogAddr += 1; 00969 *BitPos = 0; 00970 } 00971 context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr); 00972 context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos; 00973 *BitPos = 7; 00974 FMMUsize = ByteCount; 00975 if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Ibytes) 00976 { 00977 FMMUsize = context->slavelist[slave].Ibytes - FMMUdone; 00978 } 00979 *LogAddr += FMMUsize; 00980 context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize); 00981 context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos; 00982 *BitPos = 0; 00983 } 00984 FMMUdone += FMMUsize; 00985 if (context->slavelist[slave].FMMU[FMMUc].LogLength) 00986 { 00987 context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0; 00988 context->slavelist[slave].FMMU[FMMUc].FMMUtype = 1; 00989 context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1; 00990 /* program FMMU for input */ 00991 ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), 00992 sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3); 00993 /* add one for an input FMMU */ 00994 context->grouplist[group].inputsWKC++; 00995 } 00996 if (!context->slavelist[slave].inputs) 00997 { 00998 if (group) 00999 { 01000 context->slavelist[slave].inputs = 01001 (uint8 *)(pIOmap) + 01002 etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) - 01003 context->grouplist[group].logstartaddr; 01004 } 01005 else 01006 { 01007 context->slavelist[slave].inputs = 01008 (uint8 *)(pIOmap) + 01009 etohl(context->slavelist[slave].FMMU[FMMUc].LogStart); 01010 } 01011 context->slavelist[slave].Istartbit = 01012 context->slavelist[slave].FMMU[FMMUc].LogStartbit; 01013 EC_PRINT(" Inputs %p startbit %d\n", 01014 context->slavelist[slave].inputs, 01015 context->slavelist[slave].Istartbit); 01016 } 01017 FMMUc++; 01018 } 01019 context->slavelist[slave].FMMUunused = FMMUc; 01020 } 01021 01022 static void ecx_config_create_output_mappings(ecx_contextt *context, void *pIOmap, 01023 uint8 group, int16 slave, uint32 * LogAddr, uint8 * BitPos) 01024 { 01025 int BitCount = 0; 01026 int ByteCount = 0; 01027 int FMMUsize = 0; 01028 int FMMUdone = 0; 01029 uint8 SMc = 0; 01030 uint16 EndAddr; 01031 uint16 SMlength; 01032 uint16 configadr; 01033 uint8 FMMUc; 01034 01035 EC_PRINT(" OUTPUT MAPPING\n"); 01036 01037 FMMUc = context->slavelist[slave].FMMUunused; 01038 configadr = context->slavelist[slave].configadr; 01039 01040 /* search for SM that contribute to the output mapping */ 01041 while ((SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Obits + 7) / 8))) 01042 { 01043 EC_PRINT(" FMMU %d\n", FMMUc); 01044 while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) 01045 { 01046 SMc++; 01047 } 01048 EC_PRINT(" SM%d\n", SMc); 01049 context->slavelist[slave].FMMU[FMMUc].PhysStart = 01050 context->slavelist[slave].SM[SMc].StartAddr; 01051 SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength); 01052 ByteCount += SMlength; 01053 BitCount += SMlength * 8; 01054 EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength; 01055 while ((BitCount < context->slavelist[slave].Obits) && (SMc < (EC_MAXSM - 1))) /* more SM for output */ 01056 { 01057 SMc++; 01058 while ((SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) 01059 { 01060 SMc++; 01061 } 01062 /* if addresses from more SM connect use one FMMU otherwise break up in multiple FMMU */ 01063 if (etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr) 01064 { 01065 break; 01066 } 01067 EC_PRINT(" SM%d\n", SMc); 01068 SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength); 01069 ByteCount += SMlength; 01070 BitCount += SMlength * 8; 01071 EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength; 01072 } 01073 01074 /* bit oriented slave */ 01075 if (!context->slavelist[slave].Obytes) 01076 { 01077 context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr); 01078 context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos; 01079 *BitPos += context->slavelist[slave].Obits - 1; 01080 if (*BitPos > 7) 01081 { 01082 *LogAddr += 1; 01083 *BitPos -= 8; 01084 } 01085 FMMUsize = *LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1; 01086 context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize); 01087 context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos; 01088 *BitPos += 1; 01089 if (*BitPos > 7) 01090 { 01091 *LogAddr += 1; 01092 *BitPos -= 8; 01093 } 01094 } 01095 /* byte oriented slave */ 01096 else 01097 { 01098 if (*BitPos) 01099 { 01100 *LogAddr += 1; 01101 *BitPos = 0; 01102 } 01103 context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(*LogAddr); 01104 context->slavelist[slave].FMMU[FMMUc].LogStartbit = *BitPos; 01105 *BitPos = 7; 01106 FMMUsize = ByteCount; 01107 if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Obytes) 01108 { 01109 FMMUsize = context->slavelist[slave].Obytes - FMMUdone; 01110 } 01111 *LogAddr += FMMUsize; 01112 context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize); 01113 context->slavelist[slave].FMMU[FMMUc].LogEndbit = *BitPos; 01114 *BitPos = 0; 01115 } 01116 FMMUdone += FMMUsize; 01117 context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0; 01118 context->slavelist[slave].FMMU[FMMUc].FMMUtype = 2; 01119 context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1; 01120 /* program FMMU for output */ 01121 ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), 01122 sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3); 01123 context->grouplist[group].outputsWKC++; 01124 if (!context->slavelist[slave].outputs) 01125 { 01126 if (group) 01127 { 01128 context->slavelist[slave].outputs = 01129 (uint8 *)(pIOmap) + 01130 etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) - 01131 context->grouplist[group].logstartaddr; 01132 } 01133 else 01134 { 01135 context->slavelist[slave].outputs = 01136 (uint8 *)(pIOmap) + 01137 etohl(context->slavelist[slave].FMMU[FMMUc].LogStart); 01138 } 01139 context->slavelist[slave].Ostartbit = 01140 context->slavelist[slave].FMMU[FMMUc].LogStartbit; 01141 EC_PRINT(" slave %d Outputs %p startbit %d\n", 01142 slave, 01143 context->slavelist[slave].outputs, 01144 context->slavelist[slave].Ostartbit); 01145 } 01146 FMMUc++; 01147 } 01148 context->slavelist[slave].FMMUunused = FMMUc; 01149 } 01150 01151 /** Map all PDOs in one group of slaves to IOmap with Outputs/Inputs 01152 * in sequential order (legacy SOEM way). 01153 * 01154 * 01155 * @param[in] context = context struct 01156 * @param[out] pIOmap = pointer to IOmap 01157 * @param[in] group = group to map, 0 = all groups 01158 * @return IOmap size 01159 */ 01160 int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group) 01161 { 01162 uint16 slave, configadr; 01163 uint8 BitPos; 01164 uint32 LogAddr = 0; 01165 uint32 oLogAddr = 0; 01166 uint32 diff; 01167 uint16 currentsegment = 0; 01168 uint32 segmentsize = 0; 01169 01170 if ((*(context->slavecount) > 0) && (group < context->maxgroup)) 01171 { 01172 EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group); 01173 LogAddr = context->grouplist[group].logstartaddr; 01174 oLogAddr = LogAddr; 01175 BitPos = 0; 01176 context->grouplist[group].nsegments = 0; 01177 context->grouplist[group].outputsWKC = 0; 01178 context->grouplist[group].inputsWKC = 0; 01179 01180 /* Find mappings and program syncmanagers */ 01181 ecx_config_find_mappings(context, group); 01182 01183 /* do output mapping of slave and program FMMUs */ 01184 for (slave = 1; slave <= *(context->slavecount); slave++) 01185 { 01186 configadr = context->slavelist[slave].configadr; 01187 01188 if (!group || (group == context->slavelist[slave].group)) 01189 { 01190 /* create output mapping */ 01191 if (context->slavelist[slave].Obits) 01192 { 01193 ecx_config_create_output_mappings (context, pIOmap, group, slave, &LogAddr, &BitPos); 01194 diff = LogAddr - oLogAddr; 01195 oLogAddr = LogAddr; 01196 if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)) 01197 { 01198 context->grouplist[group].IOsegment[currentsegment] = segmentsize; 01199 if (currentsegment < (EC_MAXIOSEGMENTS - 1)) 01200 { 01201 currentsegment++; 01202 segmentsize = diff; 01203 } 01204 } 01205 else 01206 { 01207 segmentsize += diff; 01208 } 01209 } 01210 } 01211 } 01212 if (BitPos) 01213 { 01214 LogAddr++; 01215 oLogAddr = LogAddr; 01216 BitPos = 0; 01217 if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)) 01218 { 01219 context->grouplist[group].IOsegment[currentsegment] = segmentsize; 01220 if (currentsegment < (EC_MAXIOSEGMENTS - 1)) 01221 { 01222 currentsegment++; 01223 segmentsize = 1; 01224 } 01225 } 01226 else 01227 { 01228 segmentsize += 1; 01229 } 01230 } 01231 context->grouplist[group].outputs = pIOmap; 01232 context->grouplist[group].Obytes = LogAddr - context->grouplist[group].logstartaddr; 01233 context->grouplist[group].nsegments = currentsegment + 1; 01234 context->grouplist[group].Isegment = currentsegment; 01235 context->grouplist[group].Ioffset = segmentsize; 01236 if (!group) 01237 { 01238 context->slavelist[0].outputs = pIOmap; 01239 context->slavelist[0].Obytes = LogAddr - 01240 context->grouplist[group].logstartaddr; /* store output bytes in master record */ 01241 } 01242 01243 /* do input mapping of slave and program FMMUs */ 01244 for (slave = 1; slave <= *(context->slavecount); slave++) 01245 { 01246 configadr = context->slavelist[slave].configadr; 01247 if (!group || (group == context->slavelist[slave].group)) 01248 { 01249 /* create input mapping */ 01250 if (context->slavelist[slave].Ibits) 01251 { 01252 01253 ecx_config_create_input_mappings(context, pIOmap, group, slave, &LogAddr, &BitPos); 01254 diff = LogAddr - oLogAddr; 01255 oLogAddr = LogAddr; 01256 if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)) 01257 { 01258 context->grouplist[group].IOsegment[currentsegment] = segmentsize; 01259 if (currentsegment < (EC_MAXIOSEGMENTS - 1)) 01260 { 01261 currentsegment++; 01262 segmentsize = diff; 01263 } 01264 } 01265 else 01266 { 01267 segmentsize += diff; 01268 } 01269 } 01270 01271 ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */ 01272 ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , EC_TIMEOUTRET3); /* set safeop status */ 01273 01274 if (context->slavelist[slave].blockLRW) 01275 { 01276 context->grouplist[group].blockLRW++; 01277 } 01278 context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent; 01279 } 01280 } 01281 if (BitPos) 01282 { 01283 LogAddr++; 01284 oLogAddr = LogAddr; 01285 BitPos = 0; 01286 if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)) 01287 { 01288 context->grouplist[group].IOsegment[currentsegment] = segmentsize; 01289 if (currentsegment < (EC_MAXIOSEGMENTS - 1)) 01290 { 01291 currentsegment++; 01292 segmentsize = 1; 01293 } 01294 } 01295 else 01296 { 01297 segmentsize += 1; 01298 } 01299 } 01300 context->grouplist[group].IOsegment[currentsegment] = segmentsize; 01301 context->grouplist[group].nsegments = currentsegment + 1; 01302 context->grouplist[group].inputs = (uint8 *)(pIOmap) + context->grouplist[group].Obytes; 01303 context->grouplist[group].Ibytes = LogAddr - 01304 context->grouplist[group].logstartaddr - 01305 context->grouplist[group].Obytes; 01306 if (!group) 01307 { 01308 context->slavelist[0].inputs = (uint8 *)(pIOmap) + context->slavelist[0].Obytes; 01309 context->slavelist[0].Ibytes = LogAddr - 01310 context->grouplist[group].logstartaddr - 01311 context->slavelist[0].Obytes; /* store input bytes in master record */ 01312 } 01313 01314 EC_PRINT("IOmapSize %d\n", LogAddr - context->grouplist[group].logstartaddr); 01315 01316 return (LogAddr - context->grouplist[group].logstartaddr); 01317 } 01318 01319 return 0; 01320 } 01321 01322 /** Map all PDOs in one group of slaves to IOmap with Outputs/Inputs 01323 * overlapping. NOTE: Must use this for TI ESC when using LRW. 01324 * 01325 * @param[in] context = context struct 01326 * @param[out] pIOmap = pointer to IOmap 01327 * @param[in] group = group to map, 0 = all groups 01328 * @return IOmap size 01329 */ 01330 int ecx_config_overlap_map_group(ecx_contextt *context, void *pIOmap, uint8 group) 01331 { 01332 uint16 slave, configadr; 01333 uint8 BitPos; 01334 uint32 mLogAddr = 0; 01335 uint32 siLogAddr = 0; 01336 uint32 soLogAddr = 0; 01337 uint32 tempLogAddr; 01338 uint32 diff; 01339 uint16 currentsegment = 0; 01340 uint32 segmentsize = 0; 01341 01342 if ((*(context->slavecount) > 0) && (group < context->maxgroup)) 01343 { 01344 EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group); 01345 mLogAddr = context->grouplist[group].logstartaddr; 01346 siLogAddr = mLogAddr; 01347 soLogAddr = mLogAddr; 01348 BitPos = 0; 01349 context->grouplist[group].nsegments = 0; 01350 context->grouplist[group].outputsWKC = 0; 01351 context->grouplist[group].inputsWKC = 0; 01352 01353 /* Find mappings and program syncmanagers */ 01354 ecx_config_find_mappings(context, group); 01355 01356 /* do IO mapping of slave and program FMMUs */ 01357 for (slave = 1; slave <= *(context->slavecount); slave++) 01358 { 01359 configadr = context->slavelist[slave].configadr; 01360 siLogAddr = soLogAddr = mLogAddr; 01361 01362 if (!group || (group == context->slavelist[slave].group)) 01363 { 01364 /* create output mapping */ 01365 if (context->slavelist[slave].Obits) 01366 { 01367 01368 ecx_config_create_output_mappings(context, pIOmap, group, 01369 slave, &soLogAddr, &BitPos); 01370 if (BitPos) 01371 { 01372 soLogAddr++; 01373 BitPos = 0; 01374 } 01375 } 01376 01377 /* create input mapping */ 01378 if (context->slavelist[slave].Ibits) 01379 { 01380 ecx_config_create_input_mappings(context, pIOmap, group, 01381 slave, &siLogAddr, &BitPos); 01382 if (BitPos) 01383 { 01384 siLogAddr++; 01385 BitPos = 0; 01386 } 01387 } 01388 01389 tempLogAddr = (siLogAddr > soLogAddr) ? siLogAddr : soLogAddr; 01390 diff = tempLogAddr - mLogAddr; 01391 mLogAddr = tempLogAddr; 01392 01393 if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM)) 01394 { 01395 context->grouplist[group].IOsegment[currentsegment] = segmentsize; 01396 if (currentsegment < (EC_MAXIOSEGMENTS - 1)) 01397 { 01398 currentsegment++; 01399 segmentsize = diff; 01400 } 01401 } 01402 else 01403 { 01404 segmentsize += diff; 01405 } 01406 01407 ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */ 01408 ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP), EC_TIMEOUTRET3); /* set safeop status */ 01409 01410 if (context->slavelist[slave].blockLRW) 01411 { 01412 context->grouplist[group].blockLRW++; 01413 } 01414 context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent; 01415 01416 } 01417 } 01418 01419 context->grouplist[group].IOsegment[currentsegment] = segmentsize; 01420 context->grouplist[group].nsegments = currentsegment + 1; 01421 context->grouplist[group].Isegment = 0; 01422 context->grouplist[group].Ioffset = 0; 01423 01424 context->grouplist[group].Obytes = soLogAddr - context->grouplist[group].logstartaddr; 01425 context->grouplist[group].Ibytes = siLogAddr - context->grouplist[group].logstartaddr; 01426 context->grouplist[group].outputs = pIOmap; 01427 context->grouplist[group].inputs = (uint8 *)pIOmap + context->grouplist[group].Obytes; 01428 01429 /* Move calculated inputs with OBytes offset*/ 01430 for (slave = 1; slave <= *(context->slavecount); slave++) 01431 { 01432 context->slavelist[slave].inputs += context->grouplist[group].Obytes; 01433 } 01434 01435 if (!group) 01436 { 01437 /* store output bytes in master record */ 01438 context->slavelist[0].outputs = pIOmap; 01439 context->slavelist[0].Obytes = soLogAddr - context->grouplist[group].logstartaddr; 01440 context->slavelist[0].inputs = (uint8 *)pIOmap + context->slavelist[0].Obytes; 01441 context->slavelist[0].Ibytes = siLogAddr - context->grouplist[group].logstartaddr; 01442 } 01443 01444 EC_PRINT("IOmapSize %d\n", context->grouplist[group].Obytes + context->grouplist[group].Ibytes); 01445 01446 return (context->grouplist[group].Obytes + context->grouplist[group].Ibytes); 01447 } 01448 01449 return 0; 01450 } 01451 01452 01453 /** Recover slave. 01454 * 01455 * @param[in] context = context struct 01456 * @param[in] slave = slave to recover 01457 * @param[in] timeout = local timeout f.e. EC_TIMEOUTRET3 01458 * @return >0 if successful 01459 */ 01460 int ecx_recover_slave(ecx_contextt *context, uint16 slave, int timeout) 01461 { 01462 int rval; 01463 int wkc; 01464 uint16 ADPh, configadr, readadr; 01465 01466 rval = 0; 01467 configadr = context->slavelist[slave].configadr; 01468 ADPh = (uint16)(1 - slave); 01469 /* check if we found another slave than the requested */ 01470 readadr = 0xfffe; 01471 wkc = ecx_APRD(context->port, ADPh, ECT_REG_STADR, sizeof(readadr), &readadr, timeout); 01472 /* correct slave found, finished */ 01473 if(readadr == configadr) 01474 { 01475 return 1; 01476 } 01477 /* only try if no config address*/ 01478 if( (wkc > 0) && (readadr == 0)) 01479 { 01480 /* clear possible slaves at EC_TEMPNODE */ 01481 ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0); 01482 /* set temporary node address of slave */ 01483 if(ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(EC_TEMPNODE) , timeout) <= 0) 01484 { 01485 ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0); 01486 return 0; /* slave fails to respond */ 01487 } 01488 01489 context->slavelist[slave].configadr = EC_TEMPNODE; /* temporary config address */ 01490 ecx_eeprom2master(context, slave); /* set Eeprom control to master */ 01491 01492 /* check if slave is the same as configured before */ 01493 if ((ecx_FPRDw(context->port, EC_TEMPNODE, ECT_REG_ALIAS, timeout) == 01494 htoes(context->slavelist[slave].aliasadr)) && 01495 (ecx_readeeprom(context, slave, ECT_SII_ID, EC_TIMEOUTEEP) == 01496 htoel(context->slavelist[slave].eep_id)) && 01497 (ecx_readeeprom(context, slave, ECT_SII_MANUF, EC_TIMEOUTEEP) == 01498 htoel(context->slavelist[slave].eep_man)) && 01499 (ecx_readeeprom(context, slave, ECT_SII_REV, EC_TIMEOUTEEP) == 01500 htoel(context->slavelist[slave].eep_rev))) 01501 { 01502 rval = ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(configadr) , timeout); 01503 context->slavelist[slave].configadr = configadr; 01504 } 01505 else 01506 { 01507 /* slave is not the expected one, remove config address*/ 01508 ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , timeout); 01509 context->slavelist[slave].configadr = configadr; 01510 } 01511 } 01512 01513 return rval; 01514 } 01515 01516 /** Reconfigure slave. 01517 * 01518 * @param[in] context = context struct 01519 * @param[in] slave = slave to reconfigure 01520 * @param[in] timeout = local timeout f.e. EC_TIMEOUTRET3 01521 * @return Slave state 01522 */ 01523 int ecx_reconfig_slave(ecx_contextt *context, uint16 slave, int timeout) 01524 { 01525 int state, nSM, FMMUc; 01526 uint16 configadr; 01527 01528 configadr = context->slavelist[slave].configadr; 01529 if (ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_INIT) , timeout) <= 0) 01530 { 01531 return 0; 01532 } 01533 state = 0; 01534 ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */ 01535 /* check state change init */ 01536 state = ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE); 01537 if(state == EC_STATE_INIT) 01538 { 01539 /* program all enabled SM */ 01540 for( nSM = 0 ; nSM < EC_MAXSM ; nSM++ ) 01541 { 01542 if (context->slavelist[slave].SM[nSM].StartAddr) 01543 { 01544 ecx_FPWR(context->port, configadr, (uint16)(ECT_REG_SM0 + (nSM * sizeof(ec_smt))), 01545 sizeof(ec_smt), &context->slavelist[slave].SM[nSM], timeout); 01546 } 01547 } 01548 ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP) , timeout); 01549 state = ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */ 01550 if( state == EC_STATE_PRE_OP) 01551 { 01552 /* execute special slave configuration hook Pre-Op to Safe-OP */ 01553 if(context->slavelist[slave].PO2SOconfig) /* only if registered */ 01554 { 01555 context->slavelist[slave].PO2SOconfig(slave); 01556 } 01557 ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , timeout); /* set safeop status */ 01558 state = ecx_statecheck(context, slave, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE); /* check state change safe-op */ 01559 /* program configured FMMU */ 01560 for( FMMUc = 0 ; FMMUc < context->slavelist[slave].FMMUunused ; FMMUc++ ) 01561 { 01562 ecx_FPWR(context->port, configadr, (uint16)(ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc)), 01563 sizeof(ec_fmmut), &context->slavelist[slave].FMMU[FMMUc], timeout); 01564 } 01565 } 01566 } 01567 01568 return state; 01569 } 01570 01571 #ifdef EC_VER1 01572 /** Enumerate and init all slaves. 01573 * 01574 * @param[in] usetable = TRUE when using configtable to init slaves, FALSE otherwise 01575 * @return Workcounter of slave discover datagram = number of slaves found 01576 * @see ecx_config_init 01577 */ 01578 int ec_config_init(uint8 usetable) 01579 { 01580 return ecx_config_init(&ecx_context, usetable); 01581 } 01582 01583 /** Map all PDOs in one group of slaves to IOmap with Outputs/Inputs 01584 * in sequential order (legacy SOEM way). 01585 * 01586 * @param[out] pIOmap = pointer to IOmap 01587 * @param[in] group = group to map, 0 = all groups 01588 * @return IOmap size 01589 * @see ecx_config_map_group 01590 */ 01591 int ec_config_map_group(void *pIOmap, uint8 group) 01592 { 01593 return ecx_config_map_group(&ecx_context, pIOmap, group); 01594 } 01595 01596 /** Map all PDOs in one group of slaves to IOmap with Outputs/Inputs 01597 * overlapping. NOTE: Must use this for TI ESC when using LRW. 01598 * 01599 * @param[out] pIOmap = pointer to IOmap 01600 * @param[in] group = group to map, 0 = all groups 01601 * @return IOmap size 01602 * @see ecx_config_overlap_map_group 01603 */ 01604 int ec_config_overlap_map_group(void *pIOmap, uint8 group) 01605 { 01606 return ecx_config_overlap_map_group(&ecx_context, pIOmap, group); 01607 } 01608 01609 /** Map all PDOs from slaves to IOmap with Outputs/Inputs 01610 * in sequential order (legacy SOEM way). 01611 * 01612 * @param[out] pIOmap = pointer to IOmap 01613 * @return IOmap size 01614 */ 01615 int ec_config_map(void *pIOmap) 01616 { 01617 return ec_config_map_group(pIOmap, 0); 01618 } 01619 01620 /** Map all PDOs from slaves to IOmap with Outputs/Inputs 01621 * overlapping. NOTE: Must use this for TI ESC when using LRW. 01622 * 01623 * @param[out] pIOmap = pointer to IOmap 01624 * @return IOmap size 01625 */ 01626 int ec_config_overlap_map(void *pIOmap) 01627 { 01628 return ec_config_overlap_map_group(pIOmap, 0); 01629 } 01630 01631 /** Enumerate / map and init all slaves. 01632 * 01633 * @param[in] usetable = TRUE when using configtable to init slaves, FALSE otherwise 01634 * @param[out] pIOmap = pointer to IOmap 01635 * @return Workcounter of slave discover datagram = number of slaves found 01636 */ 01637 int ec_config(uint8 usetable, void *pIOmap) 01638 { 01639 int wkc; 01640 wkc = ec_config_init(usetable); 01641 if (wkc) 01642 { 01643 ec_config_map(pIOmap); 01644 } 01645 return wkc; 01646 } 01647 01648 /** Enumerate / map and init all slaves. 01649 * 01650 * @param[in] usetable = TRUE when using configtable to init slaves, FALSE otherwise 01651 * @param[out] pIOmap = pointer to IOmap 01652 * @return Workcounter of slave discover datagram = number of slaves found 01653 */ 01654 int ec_config_overlap(uint8 usetable, void *pIOmap) 01655 { 01656 int wkc; 01657 wkc = ec_config_init(usetable); 01658 if (wkc) 01659 { 01660 ec_config_overlap_map(pIOmap); 01661 } 01662 return wkc; 01663 } 01664 01665 /** Recover slave. 01666 * 01667 * @param[in] slave = slave to recover 01668 * @param[in] timeout = local timeout f.e. EC_TIMEOUTRET3 01669 * @return >0 if successful 01670 * @see ecx_recover_slave 01671 */ 01672 int ec_recover_slave(uint16 slave, int timeout) 01673 { 01674 return ecx_recover_slave(&ecx_context, slave, timeout); 01675 } 01676 01677 /** Reconfigure slave. 01678 * 01679 * @param[in] slave = slave to reconfigure 01680 * @param[in] timeout = local timeout f.e. EC_TIMEOUTRET3 01681 * @return Slave state 01682 * @see ecx_reconfig_slave 01683 */ 01684 int ec_reconfig_slave(uint16 slave, int timeout) 01685 { 01686 return ecx_reconfig_slave(&ecx_context, slave, timeout); 01687 } 01688 #endif
Generated on Tue Jul 12 2022 18:21:13 by
