fp@922: /***************************************************************************** fp@922: * fp@922: * $Id$ fp@922: * fp@922: ****************************************************************************/ fp@922: fp@922: #include fp@922: #include fp@922: #include fp@922: #include fp@922: #include fp@922: fp@922: #include fp@922: #include fp@922: #include fp@922: using namespace std; fp@922: fp@922: #include "Master.h" fp@922: fp@922: /****************************************************************************/ fp@922: fp@922: Master::Master() fp@922: { fp@922: index = 0; fp@922: fd = -1; fp@922: } fp@922: fp@922: /****************************************************************************/ fp@922: fp@922: Master::~Master() fp@922: { fp@922: close(); fp@922: } fp@922: fp@922: /****************************************************************************/ fp@922: fp@922: void Master::open(unsigned int index) fp@922: { fp@922: stringstream deviceName; fp@922: fp@922: Master::index = index; fp@922: fp@922: deviceName << "/dev/EtherCAT" << index; fp@922: fp@922: if ((fd = ::open(deviceName.str().c_str(), O_RDONLY)) == -1) { fp@922: stringstream err; fp@922: err << "Failed to open master device " << deviceName.str() << ": " fp@922: << strerror(errno); fp@922: throw MasterException(err.str()); fp@922: } fp@922: } fp@922: fp@922: /****************************************************************************/ fp@922: fp@922: void Master::close() fp@922: { fp@922: if (fd == -1) fp@922: return; fp@922: fp@922: ::close(fd); fp@922: } fp@922: fp@922: /****************************************************************************/ fp@922: fp@949: void Master::outputData(int domainIndex) fp@949: { fp@949: if (domainIndex == -1) { fp@949: unsigned int numDomains = domainCount(), i; fp@949: fp@949: for (i = 0; i < numDomains; i++) { fp@949: outputDomainData(i); fp@949: } fp@949: } else { fp@949: outputDomainData(domainIndex); fp@949: } fp@949: } fp@949: fp@949: /****************************************************************************/ fp@949: fp@956: void Master::setDebug(const vector &commandArgs) fp@956: { fp@956: stringstream str; fp@956: int debugLevel; fp@956: fp@956: if (commandArgs.size() != 1) { fp@956: stringstream err; fp@956: err << "'debug' takes exactly one argument!"; fp@956: throw MasterException(err.str()); fp@956: } fp@956: fp@956: str << commandArgs[0]; fp@956: str >> debugLevel; fp@956: fp@956: if (str.fail()) { fp@956: stringstream err; fp@956: err << "Invalid debug level '" << commandArgs[0] << "'!"; fp@956: throw MasterException(err.str()); fp@956: } fp@956: fp@956: if (ioctl(fd, EC_IOCTL_DEBUG_LEVEL, debugLevel) < 0) { fp@956: stringstream err; fp@956: err << "Failed to set debug level: " << strerror(errno); fp@956: throw MasterException(err.str()); fp@956: } fp@956: } fp@956: fp@956: /****************************************************************************/ fp@956: fp@948: void Master::showDomains(int domainIndex) fp@948: { fp@948: if (domainIndex == -1) { fp@948: unsigned int numDomains = domainCount(), i; fp@948: fp@948: for (i = 0; i < numDomains; i++) { fp@948: showDomain(i); fp@948: } fp@948: } else { fp@948: showDomain(domainIndex); fp@948: } fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@922: void Master::listSlaves() fp@922: { fp@922: unsigned int numSlaves = slaveCount(), i; fp@935: ec_ioctl_slave_t slave; fp@922: uint16_t lastAlias, aliasIndex; fp@922: fp@922: lastAlias = 0; fp@922: aliasIndex = 0; fp@922: for (i = 0; i < numSlaves; i++) { fp@935: getSlave(&slave, i); fp@935: cout << setw(2) << i << " "; fp@935: fp@935: if (slave.alias) { fp@935: lastAlias = slave.alias; fp@922: aliasIndex = 0; fp@922: } fp@922: if (lastAlias) { fp@922: cout << setw(10) << "#" << lastAlias << ":" << aliasIndex; fp@922: } fp@922: fp@935: cout << " " << slaveState(slave.state) << " "; fp@935: fp@935: if (strlen(slave.name)) { fp@935: cout << slave.name; fp@922: } else { fp@935: cout << "0x" << hex << setfill('0') << slave.vendor_id fp@935: << ":0x" << slave.product_code; fp@922: } fp@922: fp@922: cout << endl; fp@922: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@935: void Master::listPdos(int slavePosition) fp@935: { fp@936: if (slavePosition == -1) { fp@936: unsigned int numSlaves = slaveCount(), i; fp@936: fp@936: for (i = 0; i < numSlaves; i++) { fp@936: listSlavePdos(i, true); fp@936: } fp@936: } else { fp@936: listSlavePdos(slavePosition, false); fp@936: } fp@936: } fp@936: fp@936: /****************************************************************************/ fp@936: fp@938: void Master::generateXml(int slavePosition) fp@938: { fp@938: if (slavePosition == -1) { fp@938: unsigned int numSlaves = slaveCount(), i; fp@938: fp@938: for (i = 0; i < numSlaves; i++) { fp@938: generateSlaveXml(i); fp@938: } fp@938: } else { fp@938: generateSlaveXml(slavePosition); fp@938: } fp@938: } fp@938: fp@938: /****************************************************************************/ fp@938: fp@949: void Master::outputDomainData(unsigned int domainIndex) fp@949: { fp@949: ec_ioctl_domain_t domain; fp@949: ec_ioctl_data_t data; fp@949: unsigned char *processData; fp@949: unsigned int i; fp@949: fp@949: getDomain(&domain, domainIndex); fp@949: fp@950: if (!domain.data_size) fp@950: return; fp@950: fp@949: processData = new unsigned char[domain.data_size]; fp@949: fp@950: try { fp@950: getData(&data, domainIndex, domain.data_size, processData); fp@950: } catch (MasterException &e) { fp@949: delete [] processData; fp@950: throw e; fp@949: } fp@949: fp@949: for (i = 0; i < data.data_size; i++) fp@949: cout << processData[i]; fp@949: cout.flush(); fp@949: fp@949: delete [] processData; fp@949: } fp@949: fp@949: /****************************************************************************/ fp@949: fp@948: void Master::showDomain(unsigned int domainIndex) fp@948: { fp@950: ec_ioctl_domain_t domain; fp@950: unsigned char *processData; fp@950: ec_ioctl_data_t data; fp@950: unsigned int i, j; fp@950: ec_ioctl_domain_fmmu_t fmmu; fp@950: unsigned int dataOffset; fp@948: fp@950: getDomain(&domain, domainIndex); fp@948: fp@948: cout << "Domain" << domainIndex << ":" fp@948: << " LogBaseAddr 0x" fp@950: << hex << setfill('0') << setw(8) << domain.logical_base_address fp@950: << ", Size " << dec << setfill(' ') << setw(3) << domain.data_size fp@948: << ", WorkingCounter " fp@951: << dec << domain.working_counter << "/" fp@951: << domain.expected_working_counter << endl; fp@950: fp@950: if (!domain.data_size) fp@950: return; fp@950: fp@950: processData = new unsigned char[domain.data_size]; fp@950: fp@950: try { fp@950: getData(&data, domainIndex, domain.data_size, processData); fp@950: } catch (MasterException &e) { fp@950: delete [] processData; fp@950: throw e; fp@950: } fp@950: fp@950: for (i = 0; i < domain.fmmu_count; i++) { fp@950: getFmmu(&fmmu, domainIndex, i); fp@950: fp@951: cout << " SlaveConfig " fp@951: << fmmu.slave_config_alias << ":" << fmmu.slave_config_position fp@951: << ", Dir " fp@951: << setfill(' ') << setw(3) << (fmmu.fmmu_dir ? "In" : "Out") fp@950: << ", LogAddr 0x" fp@950: << hex << setfill('0') << setw(8) << fmmu.logical_address fp@951: << ", Size " << dec << fmmu.data_size << endl; fp@950: fp@950: dataOffset = fmmu.logical_address - domain.logical_base_address; fp@950: if (dataOffset + fmmu.data_size > domain.data_size) { fp@950: stringstream err; fp@950: err << "Fmmu information corrupted!"; fp@950: delete [] processData; fp@950: throw MasterException(err.str()); fp@950: } fp@950: fp@950: cout << " " << hex << setfill('0'); fp@950: for (j = 0; j < fmmu.data_size; j++) { fp@950: cout << setw(2) fp@950: << (unsigned int) *(processData + dataOffset + j) << " "; fp@950: } fp@950: cout << endl; fp@950: } fp@950: fp@950: delete [] processData; fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@936: void Master::listSlavePdos(uint16_t slavePosition, bool printSlave) fp@936: { fp@935: ec_ioctl_slave_t slave; fp@935: ec_ioctl_sync_t sync; fp@935: ec_ioctl_pdo_t pdo; fp@935: ec_ioctl_pdo_entry_t entry; fp@935: unsigned int i, j, k; fp@935: fp@935: getSlave(&slave, slavePosition); fp@935: fp@936: if (printSlave) fp@936: cout << "=== Slave " << slavePosition << " ===" << endl; fp@936: fp@935: for (i = 0; i < slave.sync_count; i++) { fp@935: getSync(&sync, slavePosition, i); fp@935: fp@935: cout << "SM" << i << ":" fp@935: << " PhysAddr 0x" fp@935: << hex << setfill('0') << setw(4) << sync.physical_start_address fp@935: << ", DefaultSize " fp@935: << dec << setfill(' ') << setw(4) << sync.default_size fp@935: << ", ControlRegister 0x" fp@935: << hex << setfill('0') << setw(2) fp@935: << (unsigned int) sync.control_register fp@935: << ", Enable " << dec << (unsigned int) sync.enable fp@935: << endl; fp@935: fp@935: for (j = 0; j < sync.pdo_count; j++) { fp@935: getPdo(&pdo, slavePosition, i, j); fp@935: fp@935: cout << " " << (pdo.dir ? "T" : "R") << "xPdo 0x" fp@935: << hex << setfill('0') << setw(4) << pdo.index fp@935: << " \"" << pdo.name << "\"" << endl; fp@935: fp@935: for (k = 0; k < pdo.entry_count; k++) { fp@935: getPdoEntry(&entry, slavePosition, i, j, k); fp@935: fp@935: cout << " Pdo entry 0x" fp@935: << hex << setfill('0') << setw(4) << entry.index fp@935: << ":" << hex << setfill('0') << setw(2) fp@935: << (unsigned int) entry.subindex fp@935: << ", " << dec << (unsigned int) entry.bit_length fp@935: << " bit, \"" << entry.name << "\"" << endl; fp@935: } fp@935: } fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@938: void Master::generateSlaveXml(uint16_t slavePosition) fp@938: { fp@938: ec_ioctl_slave_t slave; fp@938: ec_ioctl_sync_t sync; fp@938: ec_ioctl_pdo_t pdo; fp@938: ec_ioctl_pdo_entry_t entry; fp@938: unsigned int i, j, k; fp@938: fp@938: getSlave(&slave, slavePosition); fp@938: fp@938: cout fp@938: << "" << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << slave.vendor_id << "" << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl; fp@938: fp@938: for (i = 0; i < slave.sync_count; i++) { fp@938: getSync(&sync, slavePosition, i); fp@938: fp@938: for (j = 0; j < sync.pdo_count; j++) { fp@938: getPdo(&pdo, slavePosition, i, j); fp@938: fp@938: cout fp@938: << " <" << (pdo.dir ? "T" : "R") << "xPdo>" << endl fp@938: << " #x" fp@938: << hex << setfill('0') << setw(4) << pdo.index fp@938: << "" << endl fp@938: << " " << pdo.name << "" << endl; fp@938: fp@938: for (k = 0; k < pdo.entry_count; k++) { fp@938: getPdoEntry(&entry, slavePosition, i, j, k); fp@938: fp@938: cout fp@938: << " " << endl fp@938: << " #x" fp@938: << hex << setfill('0') << setw(4) << entry.index fp@938: << "" << endl; fp@938: if (entry.index) fp@938: cout fp@938: << " " fp@938: << dec << (unsigned int) entry.subindex fp@938: << "" << endl; fp@938: fp@938: cout fp@938: << " " fp@938: << (unsigned int) entry.bit_length fp@938: << "" << endl; fp@938: fp@938: if (entry.index) { fp@938: cout fp@938: << " " << entry.name fp@938: << "" << endl fp@938: << " "; fp@938: fp@938: if (entry.bit_length == 1) { fp@938: cout << "BOOL"; fp@938: } else if (!(entry.bit_length % 8)) { fp@938: if (entry.bit_length <= 64) fp@938: cout << "UINT" << (unsigned int) entry.bit_length; fp@938: else fp@938: cout << "STRING(" fp@938: << (unsigned int) (entry.bit_length / 8) fp@938: << ")"; fp@938: } else { fp@938: cerr << "Invalid bit length " fp@938: << (unsigned int) entry.bit_length << endl; fp@938: } fp@938: fp@938: cout << "" << endl; fp@938: } fp@938: fp@938: cout << " " << endl; fp@938: } fp@938: fp@938: cout fp@938: << " " << endl; fp@938: } fp@938: } fp@938: fp@938: cout fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << "" << endl; fp@938: } fp@938: fp@938: /****************************************************************************/ fp@938: fp@948: unsigned int Master::domainCount() fp@948: { fp@948: int ret; fp@948: fp@948: if ((ret = ioctl(fd, EC_IOCTL_DOMAIN_COUNT, 0)) < 0) { fp@948: stringstream err; fp@948: err << "Failed to get number of domains: " << strerror(errno); fp@948: throw MasterException(err.str()); fp@948: } fp@948: fp@948: return ret; fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@935: unsigned int Master::slaveCount() fp@935: { fp@935: int ret; fp@935: fp@935: if ((ret = ioctl(fd, EC_IOCTL_SLAVE_COUNT, 0)) < 0) { fp@935: stringstream err; fp@948: err << "Failed to get number of slaves: " << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: fp@935: return ret; fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@948: void Master::getDomain(ec_ioctl_domain_t *data, unsigned int index) fp@948: { fp@948: data->index = index; fp@948: fp@948: if (ioctl(fd, EC_IOCTL_DOMAIN, data)) { fp@948: stringstream err; fp@948: err << "Failed to get domain: "; fp@948: if (errno == EINVAL) fp@948: err << "Domain " << index << " does not exist!"; fp@948: else fp@948: err << strerror(errno); fp@948: throw MasterException(err.str()); fp@948: } fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@950: void Master::getData(ec_ioctl_data_t *data, unsigned int domainIndex, fp@950: unsigned int dataSize, unsigned char *mem) fp@950: { fp@950: data->domain_index = domainIndex; fp@950: data->data_size = dataSize; fp@950: data->target = mem; fp@950: fp@950: if (ioctl(fd, EC_IOCTL_DATA, data) < 0) { fp@950: stringstream err; fp@950: err << "Failed to get domain data: " << strerror(errno); fp@950: throw MasterException(err.str()); fp@950: } fp@950: } fp@950: fp@950: /****************************************************************************/ fp@950: fp@935: void Master::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex) fp@935: { fp@935: slave->position = slaveIndex; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_SLAVE, slave)) { fp@935: stringstream err; fp@935: err << "Failed to get slave: "; fp@935: if (errno == EINVAL) fp@935: err << "Slave " << slaveIndex << " does not exist!"; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@950: void Master::getFmmu( fp@950: ec_ioctl_domain_fmmu_t *fmmu, fp@950: unsigned int domainIndex, fp@950: unsigned int fmmuIndex fp@950: ) fp@950: { fp@950: fmmu->domain_index = domainIndex; fp@950: fmmu->fmmu_index = fmmuIndex; fp@950: fp@950: if (ioctl(fd, EC_IOCTL_DOMAIN_FMMU, fmmu)) { fp@950: stringstream err; fp@950: err << "Failed to get domain FMMU: "; fp@950: if (errno == EINVAL) fp@950: err << "Either domain " << domainIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) fmmuIndex + 1 fp@950: << " FMMus!"; fp@950: else fp@950: err << strerror(errno); fp@950: throw MasterException(err.str()); fp@950: } fp@950: } fp@950: fp@950: /****************************************************************************/ fp@950: fp@935: void Master::getSync( fp@935: ec_ioctl_sync_t *sync, fp@935: uint16_t slaveIndex, fp@935: uint8_t syncIndex fp@935: ) fp@935: { fp@935: sync->slave_position = slaveIndex; fp@935: sync->sync_index = syncIndex; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_SYNC, sync)) { fp@935: stringstream err; fp@935: err << "Failed to get sync manager: "; fp@935: if (errno == EINVAL) fp@935: err << "Either slave " << slaveIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) syncIndex + 1 fp@935: << " sync managers!"; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@935: void Master::getPdo( fp@935: ec_ioctl_pdo_t *pdo, fp@935: uint16_t slaveIndex, fp@935: uint8_t syncIndex, fp@935: uint8_t pdoPos fp@935: ) fp@935: { fp@935: pdo->slave_position = slaveIndex; fp@935: pdo->sync_index = syncIndex; fp@935: pdo->pdo_pos = pdoPos; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_PDO, pdo)) { fp@935: stringstream err; fp@935: err << "Failed to get Pdo: "; fp@935: if (errno == EINVAL) fp@935: err << "Either slave " << slaveIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) syncIndex + 1 fp@935: << " sync managers, or sync manager " fp@935: << (unsigned int) syncIndex << " contains less than " fp@935: << pdoPos + 1 << " Pdos!" << endl; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@935: void Master::getPdoEntry( fp@935: ec_ioctl_pdo_entry_t *entry, fp@935: uint16_t slaveIndex, fp@935: uint8_t syncIndex, fp@935: uint8_t pdoPos, fp@935: uint8_t entryPos fp@935: ) fp@935: { fp@935: entry->slave_position = slaveIndex; fp@935: entry->sync_index = syncIndex; fp@935: entry->pdo_pos = pdoPos; fp@935: entry->entry_pos = entryPos; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_PDO_ENTRY, entry)) { fp@935: stringstream err; fp@935: err << "Failed to get Pdo entry: "; fp@935: if (errno == EINVAL) fp@935: err << "Either slave " << slaveIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) syncIndex + 1 fp@935: << " sync managers, or sync manager " fp@935: << (unsigned int) syncIndex << " contains less than " fp@935: << pdoPos + 1 << " Pdos, or the Pdo at position " << pdoPos fp@935: << " contains less than " << (unsigned int) entryPos + 1 fp@935: << " entries!" << endl; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@935: string Master::slaveState(uint8_t state) fp@922: { fp@922: switch (state) { fp@922: case 1: return "INIT"; fp@922: case 2: return "PREOP"; fp@922: case 4: return "SAFEOP"; fp@922: case 8: return "OP"; fp@922: default: return "???"; fp@922: } fp@922: } fp@922: fp@922: /****************************************************************************/