# HG changeset patch # User Florian Pose # Date 1488556153 -3600 # Node ID 459758a800b31c21841d51d87ccfc5f69f47883d # Parent b9cda70ec8b079c9657e0741a67f89e1d5398fa7 Optionally output CRC diagnosis information in graph. diff -r b9cda70ec8b0 -r 459758a800b3 tool/CommandGraph.cpp --- a/tool/CommandGraph.cpp Fri Mar 03 16:36:00 2017 +0100 +++ b/tool/CommandGraph.cpp Fri Mar 03 16:49:13 2017 +0100 @@ -29,6 +29,7 @@ #include #include +#include using namespace std; #include "CommandGraph.h" @@ -47,7 +48,9 @@ { stringstream str; - str << binaryBaseName << " " << getName() << " [OPTIONS]" << endl + str + << binaryBaseName << " " << getName() << " [OPTIONS]" << endl + << binaryBaseName << " " << getName() << " [OPTIONS] " << endl << endl << getBriefDescription() << endl << endl @@ -58,19 +61,42 @@ << endl << " ethercat graph | dot -Tsvg > bus.svg" << endl << endl - << "See 'man dot' for more information." << endl; + << "See 'man dot' for more information." << endl + << endl + << "Additional information at edges and nodes is selected via" << endl + << "the first argument:" << endl + << " DC - DC timing" << endl + << " CRC - CRC error register information" << endl + << endl; return str.str(); } /****************************************************************************/ +enum Info { + None, + DC, + CRC +}; + +#define REG_SIZE (20) + +struct CrcInfo { + unsigned int crc[EC_MAX_PORTS]; + unsigned int phy[EC_MAX_PORTS]; + unsigned int fwd[EC_MAX_PORTS]; + unsigned int lnk[EC_MAX_PORTS]; +}; + void CommandGraph::execute(const StringVector &args) { + Info info = None; ec_ioctl_master_t master; - unsigned int i; typedef vector SlaveVector; SlaveVector slaves; + typedef vector CrcInfoVector; + CrcInfoVector crcInfos; ec_ioctl_slave_t slave; SlaveVector::const_iterator si; map portMedia; @@ -84,19 +110,64 @@ portMedia[EC_PORT_EBUS] = "EBUS"; mediaWeights[EC_PORT_EBUS] = 5; - if (args.size()) { + if (args.size() > 1) { stringstream err; - err << "'" << getName() << "' takes no arguments!"; + err << "'" << getName() << "' takes either one or no arguments!"; throwInvalidUsageException(err); } + if (args.size() == 1) { + string arg = args[0]; + transform(arg.begin(), arg.end(), + arg.begin(), (int (*) (int)) std::toupper); + if (arg == "DC") { + info = DC; + } + else if (arg == "CRC") { + info = CRC; + } + else { + stringstream err; + err << "Unknown argument \"" << args[0] << "\"!"; + throwInvalidUsageException(err); + } + } + MasterDevice m(getSingleMasterIndex()); m.open(MasterDevice::Read); m.getMaster(&master); - for (i = 0; i < master.slave_count; i++) { + for (unsigned int i = 0; i < master.slave_count; i++) { m.getSlave(&slave, i); slaves.push_back(slave); + + } + + if (info == CRC) { + uint8_t data[REG_SIZE]; + ec_ioctl_slave_reg_t io; + io.emergency = 0; + io.address = 0x0300; + io.size = REG_SIZE; + io.data = data; + + for (unsigned int i = 0; i < master.slave_count; i++) { + io.slave_position = i; + try { + m.readReg(&io); + } catch (MasterDeviceException &e) { + throw e; + } + + CrcInfo crcInfo; + for (int port = 0; port < EC_MAX_PORTS; port++) { + crcInfo.crc[port] = io.data[ 0 + port * 2]; + crcInfo.phy[port] = io.data[ 1 + port * 2]; + crcInfo.fwd[port] = io.data[ 8 + port]; + crcInfo.lnk[port] = io.data[16 + port]; + } + crcInfos.push_back(crcInfo); + } } cout << "/* EtherCAT bus graph. Generated by 'ethercat graph'. */" << endl @@ -134,7 +205,7 @@ << " / " << alias << ":" << pos; if (string(si->order).size()) cout << "\\n" << si->order; - if (si->dc_supported) { + if (info == DC && si->dc_supported) { cout << "\\nDC: "; if (si->has_dc_system_time) { switch (si->dc_range) { @@ -154,33 +225,46 @@ } cout << "\"]" << endl; - for (i = 1; i < EC_MAX_PORTS; i++) { - uint16_t next_pos = si->ports[i].next_slave; - ec_ioctl_slave_t *next = NULL; - - if (next_pos == 0xffff) + + for (int port = 1; port < EC_MAX_PORTS; port++) { + uint16_t next_pos = si->ports[port].next_slave; + + if (next_pos == 0xffff) { continue; - - if (next_pos < slaves.size()) { - next = &slaves[next_pos]; - } else { + } + + if (next_pos >= slaves.size()) { cerr << "Invalid next slave pointer." << endl; - } + continue; + } + + ec_ioctl_slave_t *next = &slaves[next_pos]; cout << " slave" << si->position << " -- " - << "slave" << next_pos << " [taillabel=\"" << i; - - if (si->dc_supported) { - cout << " [" << si->ports[i].delay_to_next_dc << "]"; - } + << "slave" << next_pos << " [taillabel=\"" << port; + + if (info == DC && si->dc_supported) { + cout << " [" << si->ports[port].delay_to_next_dc << "]"; + } + if (info == CRC) { + CrcInfo *crcInfo = &crcInfos[si->position]; + cout << " [" << crcInfo->crc[port] << "/" + << crcInfo->fwd[port] << "]"; + } + cout << "\",headlabel=\"0"; - if (next && next->dc_supported) { + if (info == DC && next->dc_supported) { cout << " [" << next->ports[0].delay_to_next_dc << "]"; } + if (info == CRC) { + CrcInfo *crcInfo = &crcInfos[next_pos]; + cout << " [" << crcInfo->crc[0] << "/" + << crcInfo->fwd[0] << "]"; + } cout << "\""; - mi = portMedia.find(si->ports[i].desc); + mi = portMedia.find(si->ports[port].desc); if (mi == portMedia.end() && next) { /* Try medium of next-hop slave. */ mi = portMedia.find(next->ports[0].desc); @@ -189,7 +273,7 @@ if (mi != portMedia.end()) cout << ",label=\"" << mi->second << "\""; - wi = mediaWeights.find(si->ports[i].desc); + wi = mediaWeights.find(si->ports[port].desc); if (wi != mediaWeights.end()) cout << ",weight=\"" << wi->second << "\"";