/** Recover slave. * * @param[in] slave = slave to recover * @return >0 if successful */ int ec_recover_slave(uint16 slave) { int rval; uint16 ADPh, configadr; rval = 0; configadr = ec_slave[slave].configadr; /* clear possible slaves at EC_TEMPNODE */ ec_FPWRw(EC_TEMPNODE, ECT_REG_STADR, htoes(0), 0); ADPh = (uint16)(1 - slave); /* set temporary node address of slave */ if (ec_APWRw(ADPh, ECT_REG_STADR, htoes(EC_TEMPNODE), EC_TIMEOUTRET) <= 0) return 0; /* slave fails to respond */ ec_slave[slave].configadr = EC_TEMPNODE; /* temporary config address */ ec_eeprom2master(slave); /* set Eeprom control to master */ /* check if slave is the same as configured before */ if ((ec_FPRDw(EC_TEMPNODE, ECT_REG_ALIAS, EC_TIMEOUTRET) == ec_slave[slave].aliasadr) && (ec_readeeprom(slave, ECT_SII_ID, EC_TIMEOUTEEP) == ec_slave[slave].eep_id) && (ec_readeeprom(slave, ECT_SII_MANUF, EC_TIMEOUTEEP) == ec_slave[slave].eep_man) && (ec_readeeprom(slave, ECT_SII_REV, EC_TIMEOUTEEP) == ec_slave[slave].eep_rev)) { rval = ec_FPWRw(EC_TEMPNODE, ECT_REG_STADR, htoes(configadr), EC_TIMEOUTRET); ec_slave[slave].configadr = configadr; } else { /* slave is not the expected one, remove config address*/ ec_FPWRw(EC_TEMPNODE, ECT_REG_STADR, htoes(0), EC_TIMEOUTRET); ec_slave[slave].configadr = configadr; } return rval; }
/** Enumerate and init all slaves. * * @param[in] usetable = TRUE when using configtable to init slaves, FALSE otherwise * @return Workcounter of slave discover datagram = number of slaves found */ int ec_config_init(uint8 usetable) { uint16 w, slave, ADPh, configadr, mbx_wo, mbx_ro, mbx_l, ssigen; uint16 topology, estat; int16 topoc, slavec; uint8 b,h; uint8 zbuf[64]; uint8 SMc; uint32 eedat; int wkc, cindex, nSM; ec_slavecount = 0; /* clean ec_slave array */ memset(&ec_slave, 0x00, sizeof(ec_slave)); memset(&zbuf, 0x00, sizeof(zbuf)); w = 0x0000; wkc = ec_BRD(0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE); /* detect number of slaves */ if (wkc > 0) { ec_slavecount = wkc; b = 0x00; ec_BWR(0x0000, ECT_REG_DLPORT, sizeof(b), &b, EC_TIMEOUTRET); /* deact loop manual */ w = htoes(0x0004); ec_BWR(0x0000, ECT_REG_IRQMASK, sizeof(w), &w, EC_TIMEOUTRET); /* set IRQ mask */ ec_BWR(0x0000, ECT_REG_RXERR, 8, &zbuf, EC_TIMEOUTRET); /* reset CRC counters */ ec_BWR(0x0000, ECT_REG_FMMU0, 16 * 3, &zbuf, EC_TIMEOUTRET); /* reset FMMU's */ ec_BWR(0x0000, ECT_REG_SM0, 8 * 4, &zbuf, EC_TIMEOUTRET); /* reset SyncM */ ec_BWR(0x0000, ECT_REG_DCSYSTIME, 4, &zbuf, EC_TIMEOUTRET); /* reset system time+ofs */ w = htoes(0x1000); ec_BWR(0x0000, ECT_REG_DCSPEEDCNT, sizeof(w), &w, EC_TIMEOUTRET); /* DC speedstart */ w = htoes(0x0c00); ec_BWR(0x0000, ECT_REG_DCTIMEFILT, sizeof(w), &w, EC_TIMEOUTRET); /* DC filt expr */ b = 0x00; ec_BWR(0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET); /* Ignore Alias register */ b = EC_STATE_INIT | EC_STATE_ACK; ec_BWR(0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET); /* Reset all slaves to Init */ b = 2; ec_BWR(0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET); /* force Eeprom from PDI */ b = 0; ec_BWR(0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET); /* set Eeprom to master */ for (slave = 1; slave <= ec_slavecount; slave++) { ADPh = (uint16)(1 - slave); ec_slave[slave].Itype = etohs(ec_APRDw(ADPh, ECT_REG_PDICTL, EC_TIMEOUTRET)); /* read interface type of slave */ /* a node offset is used to improve readibility of network frames */ /* this has no impact on the number of addressable slaves (auto wrap around) */ ec_APWRw(ADPh, ECT_REG_STADR, htoes(slave + EC_NODEOFFSET) , EC_TIMEOUTRET); /* set node address of slave */ if (slave == 1) { b = 1; /* kill non ecat frames for first slave */ } else { b = 0; /* pass all frames for following slaves */ } ec_APWRw(ADPh, ECT_REG_DLCTL, htoes(b), EC_TIMEOUTRET); /* set non ecat frame behaviour */ configadr = etohs(ec_APRDw(ADPh, ECT_REG_STADR, EC_TIMEOUTRET)); ec_slave[slave].configadr = configadr; ec_FPRD(configadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET); estat = etohs(estat); if ((estat & (1 << 6))) /* check if slave can read 8 byte chunks */ { ec_slave[slave].eep_8byte = 1; } ec_readeeprom1(slave, ECT_SII_MANUF); /* Manuf */ } for (slave = 1; slave <= ec_slavecount; slave++) { ec_slave[slave].eep_man = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* Manuf */ ec_readeeprom1(slave, ECT_SII_ID); /* ID */ } for (slave = 1; slave <= ec_slavecount; slave++) { ec_slave[slave].eep_id = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* ID */ ec_readeeprom1(slave, ECT_SII_REV); /* revision */ } for (slave = 1; slave <= ec_slavecount; slave++) { ec_slave[slave].eep_rev = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* revision */ ec_readeeprom1(slave, ECT_SII_RXMBXADR); /* write mailbox address + mailboxsize */ } for (slave = 1; slave <= ec_slavecount; slave++) { eedat = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* write mailbox address and mailboxsize */ ec_slave[slave].mbx_wo = (uint16)LO_WORD(eedat); ec_slave[slave].mbx_l = (uint16)HI_WORD(eedat); if (ec_slave[slave].mbx_l > 0) { ec_readeeprom1(slave, ECT_SII_TXMBXADR); /* read mailbox offset */ } } for (slave = 1; slave <= ec_slavecount; slave++) { if (ec_slave[slave].mbx_l > 0) { ec_slave[slave].mbx_ro = (uint16)etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* read mailbox offset */ } configadr = ec_slave[slave].configadr; mbx_ro = ec_slave[slave].mbx_ro; mbx_wo = ec_slave[slave].mbx_wo; mbx_l = ec_slave[slave].mbx_l; if ((etohs(ec_FPRDw(configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET)) & 0x04) > 0) /* Support DC? */ { ec_slave[slave].hasdc = TRUE; } else { ec_slave[slave].hasdc = FALSE; } topology = etohs(ec_FPRDw(configadr, ECT_REG_DLSTAT, EC_TIMEOUTRET)); /* extract topology from DL status */ h = 0; b = 0; if ((topology & 0x0300) == 0x0200) /* port0 open and communication established */ { h++; b |= 0x01; } if ((topology & 0x0c00) == 0x0800) /* port1 open and communication established */ { h++; b |= 0x02; } if ((topology & 0x3000) == 0x2000) /* port2 open and communication established */ { h++; b |= 0x04; } if ((topology & 0xc000) == 0x8000) /* port3 open and communication established */ { h++; b |= 0x08; } /* ptype = Physical type*/ ec_slave[slave].ptype = LO_BYTE(etohs(ec_FPRDw(configadr, ECT_REG_PORTDES, EC_TIMEOUTRET))); ec_slave[slave].topology = h; ec_slave[slave].activeports = b; /* 0=no links, not possible */ /* 1=1 link , end of line */ /* 2=2 links , one before and one after */ /* 3=3 links , split point */ /* 4=4 links , cross point */ /* search for parent */ ec_slave[slave].parent = 0; /* parent is master */ if (slave > 1) { topoc = 0; slavec = slave - 1; do { topology = ec_slave[slavec].topology; if (topology == 1) { topoc--; /* endpoint found */ } if (topology == 3) { topoc++; /* split found */ } if (topology == 4) { topoc+=2; /* cross found */ } if (((topoc >= 0) && (topology > 1)) || (slavec == 1)) /* parent found */ { ec_slave[slave].parent = slavec; slavec = 1; } slavec--; } while (slavec > 0); } w = ec_statecheck(slave, EC_STATE_INIT, EC_TIMEOUTSTATE); //* check state change Init */ /* set default mailbox configuration if slave has mailbox */ if (ec_slave[slave].mbx_l>0) { ec_slave[slave].SMtype[0] = 0; ec_slave[slave].SMtype[1] = 1; ec_slave[slave].SMtype[2] = 2; ec_slave[slave].SMtype[3] = 3; ec_slave[slave].SM[0].StartAddr = htoes(ec_slave[slave].mbx_wo); ec_slave[slave].SM[0].SMlength = htoes(ec_slave[slave].mbx_l); ec_slave[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0); ec_slave[slave].SM[1].StartAddr = htoes(ec_slave[slave].mbx_ro); ec_slave[slave].SM[1].SMlength = htoes(ec_slave[slave].mbx_l); ec_slave[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1); ec_slave[slave].mbx_proto = ec_readeeprom (slave, ECT_SII_MBXPROTO, EC_TIMEOUTEEP); } cindex = 0; /* use configuration table ? */ if (usetable) { cindex = ec_findconfig( ec_slave[slave].eep_man, ec_slave[slave].eep_id ); ec_slave[slave].configindex= cindex; } /* slave found in configuration table ? */ if (cindex) { ec_slave[slave].Dtype = ec_configlist[cindex].Dtype; strcpy( ec_slave[slave].name ,ec_configlist[cindex].name); ec_slave[slave].Ibits = ec_configlist[cindex].Ibits; ec_slave[slave].Obits = ec_configlist[cindex].Obits; if (ec_slave[slave].Obits) { ec_slave[slave].FMMU0func = 1; } if (ec_slave[slave].Ibits) { ec_slave[slave].FMMU1func = 2; } ec_slave[slave].FMMU[0].FMMUactive = ec_configlist[cindex].FM0ac; ec_slave[slave].FMMU[1].FMMUactive = ec_configlist[cindex].FM1ac; ec_slave[slave].SM[2].StartAddr = htoes(ec_configlist[cindex].SM2a); ec_slave[slave].SM[2].SMflags = htoel(ec_configlist[cindex].SM2f); /* simple (no mailbox) output slave found ? */ if (ec_slave[slave].Obits && !ec_slave[slave].SM[2].StartAddr) { ec_slave[slave].SM[0].StartAddr = htoes(0x0f00); ec_slave[slave].SM[0].SMlength = htoes((ec_slave[slave].Obits + 7) / 8); ec_slave[slave].SM[0].SMflags = htoel(EC_DEFAULTDOSM0); ec_slave[slave].FMMU[0].FMMUactive = 1; ec_slave[slave].FMMU[0].FMMUtype = 2; ec_slave[slave].SMtype[0] = 2; } /* complex output slave */ else { ec_slave[slave].SM[2].SMlength = htoes((ec_slave[slave].Obits + 7) / 8); ec_slave[slave].SMtype[2] = 2; } ec_slave[slave].SM[3].StartAddr = htoes(ec_configlist[cindex].SM3a); ec_slave[slave].SM[3].SMflags = htoel(ec_configlist[cindex].SM3f); /* simple (no mailbox) input slave found ? */ if (ec_slave[slave].Ibits && !ec_slave[slave].SM[3].StartAddr) { ec_slave[slave].SM[1].StartAddr = htoes(0x1000); ec_slave[slave].SM[1].SMlength = htoes((ec_slave[slave].Ibits + 7) / 8); ec_slave[slave].SM[1].SMflags = htoel(0x00000000); ec_slave[slave].FMMU[1].FMMUactive = 1; ec_slave[slave].FMMU[1].FMMUtype = 1; ec_slave[slave].SMtype[1] = 3; } /* complex input slave */ else { ec_slave[slave].SM[3].SMlength = htoes((ec_slave[slave].Ibits + 7) / 8); ec_slave[slave].SMtype[3] = 3; } } /* slave not in configuration table, find out via SII */ else { ssigen = ec_siifind(slave, ECT_SII_GENERAL); /* SII general section */ if (ssigen) { ec_slave[slave].CoEdetails = ec_siigetbyte(slave, ssigen + 0x07); ec_slave[slave].FoEdetails = ec_siigetbyte(slave, ssigen + 0x08); ec_slave[slave].EoEdetails = ec_siigetbyte(slave, ssigen + 0x09); ec_slave[slave].SoEdetails = ec_siigetbyte(slave, ssigen + 0x0a); if((ec_siigetbyte(slave, ssigen + 0x0d) & 0x02) > 0) { ec_slave[slave].blockLRW = 1; ec_slave[0].blockLRW++; } ec_slave[slave].Ebuscurrent = ec_siigetbyte(slave, ssigen + 0x0e); ec_slave[slave].Ebuscurrent += ec_siigetbyte(slave, ssigen + 0x0f) << 8; ec_slave[0].Ebuscurrent += ec_slave[slave].Ebuscurrent; } /* SII strings section */ if (ec_siifind(slave, ECT_SII_STRING) > 0) { ec_siistring(ec_slave[slave].name, slave, 1); } /* no name for slave found, use constructed name */ else { sprintf(ec_slave[slave].name, "? M:%8.8x I:%8.8x", (unsigned int)ec_slave[slave].eep_man, (unsigned int)ec_slave[slave].eep_id); } /* SII SM section */ nSM = ec_siiSM (slave,&ec_SM); if (nSM>0) { ec_slave[slave].SM[0].StartAddr = htoes(ec_SM.PhStart); ec_slave[slave].SM[0].SMlength = htoes(ec_SM.Plength); ec_slave[slave].SM[0].SMflags = htoel((ec_SM.Creg) + (ec_SM.Activate << 16)); SMc = 1; while ((SMc < EC_MAXSM) && ec_siiSMnext(slave, &ec_SM, SMc)) { ec_slave[slave].SM[SMc].StartAddr = htoes(ec_SM.PhStart); ec_slave[slave].SM[SMc].SMlength = htoes(ec_SM.Plength); ec_slave[slave].SM[SMc].SMflags = htoel((ec_SM.Creg) + (ec_SM.Activate << 16)); SMc++; } } /* SII FMMU section */ if (ec_siiFMMU(slave, &ec_FMMU)) { if (ec_FMMU.FMMU0 !=0xff) ec_slave[slave].FMMU0func = ec_FMMU.FMMU0; if (ec_FMMU.FMMU1 !=0xff) ec_slave[slave].FMMU1func = ec_FMMU.FMMU1; if (ec_FMMU.FMMU2 !=0xff) ec_slave[slave].FMMU2func = ec_FMMU.FMMU2; if (ec_FMMU.FMMU3 !=0xff) ec_slave[slave].FMMU3func = ec_FMMU.FMMU3; } } if (ec_slave[slave].mbx_l > 0) { if (ec_slave[slave].SM[0].StartAddr == 0x0000) /* should never happen */ { ec_slave[slave].SM[0].StartAddr = htoes(0x1000); ec_slave[slave].SM[0].SMlength = htoes(0x0080); ec_slave[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0); ec_slave[slave].SMtype[0] = 0; } if (ec_slave[slave].SM[1].StartAddr == 0x0000) /* should never happen */ { ec_slave[slave].SM[1].StartAddr = htoes(0x1080); ec_slave[slave].SM[1].SMlength = htoes(0x0080); ec_slave[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1); ec_slave[slave].SMtype[1] = 1; } /* program SM0 mailbox in for slave */ ec_FPWR (configadr, ECT_REG_SM0, sizeof(ec_smt), &ec_slave[slave].SM[0], EC_TIMEOUTRET); /* program SM1 mailbox out for slave */ // usleep(1000); // was needed for NETX (needs internal time after SM update) ec_FPWR (configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET); } ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP | EC_STATE_ACK) , EC_TIMEOUTRET); /* set preop status */ } } return wkc; }