void slaveinfo(char *ifname) { int cnt, i, j, nSM; uint16 ssigen, dtype; printf("Starting slaveinfo\n"); /* initialise SOEM, bind socket to ifname */ if (ec_init(ifname)) { printf("ec_init on %s succeeded.\n",ifname); /* find and auto-config slaves */ if ( ec_config(FALSE, &IOmap) > 0 ) { printf("%d slaves found and configured.\n",ec_slavecount); printf("Calculated workcounter %d\n",ec_group[0].expectedWKC); /* wait for all slaves to reach SAFE_OP state */ ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 3); if (ec_slave[0].state != EC_STATE_SAFE_OP ) { printf("Not all slaves reached safe operational state.\n"); ec_readstate(); for(i = 1; i<=ec_slavecount ; i++) { if(ec_slave[i].state != EC_STATE_SAFE_OP) { printf("Slave %d State=%2x StatusCode=%4x : %s\n", i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode)); } } } ec_configdc(); ec_readstate(); for( cnt = 1 ; cnt <= ec_slavecount ; cnt++) { printf("\nSlave:%d\n Name:%s\n Output size: %dbits\n Input size: %dbits\n State: %d\n Delay: %d[ns]\n Has DC: %d\n", cnt, ec_slave[cnt].name, ec_slave[cnt].Obits, ec_slave[cnt].Ibits, ec_slave[cnt].state, ec_slave[cnt].pdelay, ec_slave[cnt].hasdc); if (ec_slave[cnt].hasdc) printf(" DCParentport:%d\n", ec_slave[cnt].parentport); printf(" Activeports:%d.%d.%d.%d\n", (ec_slave[cnt].activeports & 0x01) > 0 , (ec_slave[cnt].activeports & 0x02) > 0 , (ec_slave[cnt].activeports & 0x04) > 0 , (ec_slave[cnt].activeports & 0x08) > 0 ); printf(" Configured address: %4.4x\n", ec_slave[cnt].configadr); printf(" Man: %8.8x ID: %8.8x Rev: %8.8x\n", (int)ec_slave[cnt].eep_man, (int)ec_slave[cnt].eep_id, (int)ec_slave[cnt].eep_rev); for(nSM = 0 ; nSM < EC_MAXSM ; nSM++) { if(ec_slave[cnt].SM[nSM].StartAddr > 0) printf(" SM%1d A:%4.4x L:%4d F:%8.8x Type:%d\n",nSM, ec_slave[cnt].SM[nSM].StartAddr, ec_slave[cnt].SM[nSM].SMlength, (int)ec_slave[cnt].SM[nSM].SMflags, ec_slave[cnt].SMtype[nSM]); } for(j = 0 ; j < ec_slave[cnt].FMMUunused ; j++) { printf(" FMMU%1d Ls:%8.8x Ll:%4d Lsb:%d Leb:%d Ps:%4.4x Psb:%d Ty:%2.2x Act:%2.2x\n", j, (int)ec_slave[cnt].FMMU[j].LogStart, ec_slave[cnt].FMMU[j].LogLength, ec_slave[cnt].FMMU[j].LogStartbit, ec_slave[cnt].FMMU[j].LogEndbit, ec_slave[cnt].FMMU[j].PhysStart, ec_slave[cnt].FMMU[j].PhysStartBit, ec_slave[cnt].FMMU[j].FMMUtype, ec_slave[cnt].FMMU[j].FMMUactive); } printf(" FMMUfunc 0:%d 1:%d 2:%d 3:%d\n", ec_slave[cnt].FMMU0func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU3func); printf(" MBX length wr: %d rd: %d MBX protocols : %2.2x\n", ec_slave[cnt].mbx_l, ec_slave[cnt].mbx_rl, ec_slave[cnt].mbx_proto); ssigen = ec_siifind(cnt, ECT_SII_GENERAL); /* SII general section */ if (ssigen) { ec_slave[cnt].CoEdetails = ec_siigetbyte(cnt, ssigen + 0x07); ec_slave[cnt].FoEdetails = ec_siigetbyte(cnt, ssigen + 0x08); ec_slave[cnt].EoEdetails = ec_siigetbyte(cnt, ssigen + 0x09); ec_slave[cnt].SoEdetails = ec_siigetbyte(cnt, ssigen + 0x0a); if((ec_siigetbyte(cnt, ssigen + 0x0d) & 0x02) > 0) { ec_slave[cnt].blockLRW = 1; ec_slave[0].blockLRW++; } ec_slave[cnt].Ebuscurrent = ec_siigetbyte(cnt, ssigen + 0x0e); ec_slave[cnt].Ebuscurrent += ec_siigetbyte(cnt, ssigen + 0x0f) << 8; ec_slave[0].Ebuscurrent += ec_slave[cnt].Ebuscurrent; } printf(" CoE details: %2.2x FoE details: %2.2x EoE details: %2.2x SoE details: %2.2x\n", ec_slave[cnt].CoEdetails, ec_slave[cnt].FoEdetails, ec_slave[cnt].EoEdetails, ec_slave[cnt].SoEdetails); printf(" Ebus current: %d[mA]\n only LRD/LWR:%d\n", ec_slave[cnt].Ebuscurrent, ec_slave[cnt].blockLRW); if ((ec_slave[cnt].mbx_proto & 0x04) && printSDO) { ODlist.Entries = 0; memset(&ODlist, 0, sizeof(ODlist)); if( ec_readODlist(cnt, &ODlist)) { printf(" CoE Object Description found, %d entries.\n",ODlist.Entries); for( i = 0 ; i < ODlist.Entries ; i++) { ec_readODdescription(i, &ODlist); while(EcatError) { printf("%s", ec_elist2string()); } printf(" Index: %4.4x Datatype: %4.4x Objectcode: %2.2x Name: %s\n", ODlist.Index[i], ODlist.DataType[i], ODlist.ObjectCode[i], ODlist.Name[i]); memset(&OElist, 0, sizeof(OElist)); ec_readOE(i, &ODlist, &OElist); while(EcatError) { printf("%s", ec_elist2string()); } for( j = 0 ; j < ODlist.MaxSub[i]+1 ; j++) { if ((OElist.DataType[j] > 0) && (OElist.BitLength[j] > 0)) { printf(" Sub: %2.2x Datatype: %4.4x Bitlength: %4.4x Obj.access: %4.4x Name: %s\n", j, OElist.DataType[j], OElist.BitLength[j], OElist.ObjAccess[j], OElist.Name[j]); if ((OElist.ObjAccess[j] & 0x0007)) { dtype = OElist.DataType[j]; printf(" Value :%s\n", SDO2string(cnt, ODlist.Index[i], j, OElist.DataType[j])); } } } } } else { while(EcatError) { printf("%s", ec_elist2string()); } } } } } else { printf("No slaves found!\n"); } printf("End slaveinfo, close socket\n"); /* stop SOEM, close socket */ ec_close(); } else { printf("No socket connection on %s\nExcecute as root\n",ifname); } }
/** 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; }