45 |
46 |
46 string CommandGraph::helpString(const string &binaryBaseName) const |
47 string CommandGraph::helpString(const string &binaryBaseName) const |
47 { |
48 { |
48 stringstream str; |
49 stringstream str; |
49 |
50 |
50 str << binaryBaseName << " " << getName() << " [OPTIONS]" << endl |
51 str |
|
52 << binaryBaseName << " " << getName() << " [OPTIONS]" << endl |
|
53 << binaryBaseName << " " << getName() << " [OPTIONS] <INFO>" << endl |
51 << endl |
54 << endl |
52 << getBriefDescription() << endl |
55 << getBriefDescription() << endl |
53 << endl |
56 << endl |
54 << "The bus is output in DOT language (see" << endl |
57 << "The bus is output in DOT language (see" << endl |
55 << "http://www.graphviz.org/doc/info/lang.html), which can" << endl |
58 << "http://www.graphviz.org/doc/info/lang.html), which can" << endl |
56 << "be processed with the tools from the Graphviz" << endl |
59 << "be processed with the tools from the Graphviz" << endl |
57 << "package. Example:" << endl |
60 << "package. Example:" << endl |
58 << endl |
61 << endl |
59 << " ethercat graph | dot -Tsvg > bus.svg" << endl |
62 << " ethercat graph | dot -Tsvg > bus.svg" << endl |
60 << endl |
63 << endl |
61 << "See 'man dot' for more information." << endl; |
64 << "See 'man dot' for more information." << endl |
|
65 << endl |
|
66 << "Additional information at edges and nodes is selected via" << endl |
|
67 << "the first argument:" << endl |
|
68 << " DC - DC timing" << endl |
|
69 << " CRC - CRC error register information" << endl |
|
70 << endl; |
62 |
71 |
63 return str.str(); |
72 return str.str(); |
64 } |
73 } |
65 |
74 |
66 /****************************************************************************/ |
75 /****************************************************************************/ |
67 |
76 |
|
77 enum Info { |
|
78 None, |
|
79 DC, |
|
80 CRC |
|
81 }; |
|
82 |
|
83 #define REG_SIZE (20) |
|
84 |
|
85 struct CrcInfo { |
|
86 unsigned int crc[EC_MAX_PORTS]; |
|
87 unsigned int phy[EC_MAX_PORTS]; |
|
88 unsigned int fwd[EC_MAX_PORTS]; |
|
89 unsigned int lnk[EC_MAX_PORTS]; |
|
90 }; |
|
91 |
68 void CommandGraph::execute(const StringVector &args) |
92 void CommandGraph::execute(const StringVector &args) |
69 { |
93 { |
|
94 Info info = None; |
70 ec_ioctl_master_t master; |
95 ec_ioctl_master_t master; |
71 unsigned int i; |
|
72 typedef vector<ec_ioctl_slave_t> SlaveVector; |
96 typedef vector<ec_ioctl_slave_t> SlaveVector; |
73 SlaveVector slaves; |
97 SlaveVector slaves; |
|
98 typedef vector<CrcInfo> CrcInfoVector; |
|
99 CrcInfoVector crcInfos; |
74 ec_ioctl_slave_t slave; |
100 ec_ioctl_slave_t slave; |
75 SlaveVector::const_iterator si; |
101 SlaveVector::const_iterator si; |
76 map<int, string> portMedia; |
102 map<int, string> portMedia; |
77 map<int, string>::const_iterator mi; |
103 map<int, string>::const_iterator mi; |
78 map<int, int> mediaWeights; |
104 map<int, int> mediaWeights; |
82 mediaWeights[EC_PORT_MII] = 1; |
108 mediaWeights[EC_PORT_MII] = 1; |
83 |
109 |
84 portMedia[EC_PORT_EBUS] = "EBUS"; |
110 portMedia[EC_PORT_EBUS] = "EBUS"; |
85 mediaWeights[EC_PORT_EBUS] = 5; |
111 mediaWeights[EC_PORT_EBUS] = 5; |
86 |
112 |
87 if (args.size()) { |
113 if (args.size() > 1) { |
88 stringstream err; |
114 stringstream err; |
89 err << "'" << getName() << "' takes no arguments!"; |
115 err << "'" << getName() << "' takes either one or no arguments!"; |
90 throwInvalidUsageException(err); |
116 throwInvalidUsageException(err); |
|
117 } |
|
118 |
|
119 if (args.size() == 1) { |
|
120 string arg = args[0]; |
|
121 transform(arg.begin(), arg.end(), |
|
122 arg.begin(), (int (*) (int)) std::toupper); |
|
123 if (arg == "DC") { |
|
124 info = DC; |
|
125 } |
|
126 else if (arg == "CRC") { |
|
127 info = CRC; |
|
128 } |
|
129 else { |
|
130 stringstream err; |
|
131 err << "Unknown argument \"" << args[0] << "\"!"; |
|
132 throwInvalidUsageException(err); |
|
133 } |
91 } |
134 } |
92 |
135 |
93 MasterDevice m(getSingleMasterIndex()); |
136 MasterDevice m(getSingleMasterIndex()); |
94 m.open(MasterDevice::Read); |
137 m.open(MasterDevice::Read); |
95 m.getMaster(&master); |
138 m.getMaster(&master); |
96 |
139 |
97 for (i = 0; i < master.slave_count; i++) { |
140 for (unsigned int i = 0; i < master.slave_count; i++) { |
98 m.getSlave(&slave, i); |
141 m.getSlave(&slave, i); |
99 slaves.push_back(slave); |
142 slaves.push_back(slave); |
|
143 |
|
144 } |
|
145 |
|
146 if (info == CRC) { |
|
147 uint8_t data[REG_SIZE]; |
|
148 ec_ioctl_slave_reg_t io; |
|
149 io.emergency = 0; |
|
150 io.address = 0x0300; |
|
151 io.size = REG_SIZE; |
|
152 io.data = data; |
|
153 |
|
154 for (unsigned int i = 0; i < master.slave_count; i++) { |
|
155 io.slave_position = i; |
|
156 try { |
|
157 m.readReg(&io); |
|
158 } catch (MasterDeviceException &e) { |
|
159 throw e; |
|
160 } |
|
161 |
|
162 CrcInfo crcInfo; |
|
163 for (int port = 0; port < EC_MAX_PORTS; port++) { |
|
164 crcInfo.crc[port] = io.data[ 0 + port * 2]; |
|
165 crcInfo.phy[port] = io.data[ 1 + port * 2]; |
|
166 crcInfo.fwd[port] = io.data[ 8 + port]; |
|
167 crcInfo.lnk[port] = io.data[16 + port]; |
|
168 } |
|
169 crcInfos.push_back(crcInfo); |
|
170 } |
100 } |
171 } |
101 |
172 |
102 cout << "/* EtherCAT bus graph. Generated by 'ethercat graph'. */" << endl |
173 cout << "/* EtherCAT bus graph. Generated by 'ethercat graph'. */" << endl |
103 << endl |
174 << endl |
104 << "strict graph bus {" << endl |
175 << "strict graph bus {" << endl |
132 cout << " slave" << si->position << " [shape=\"box\"" |
203 cout << " slave" << si->position << " [shape=\"box\"" |
133 << ",label=\"" << si->position |
204 << ",label=\"" << si->position |
134 << " / " << alias << ":" << pos; |
205 << " / " << alias << ":" << pos; |
135 if (string(si->order).size()) |
206 if (string(si->order).size()) |
136 cout << "\\n" << si->order; |
207 cout << "\\n" << si->order; |
137 if (si->dc_supported) { |
208 if (info == DC && si->dc_supported) { |
138 cout << "\\nDC: "; |
209 cout << "\\nDC: "; |
139 if (si->has_dc_system_time) { |
210 if (si->has_dc_system_time) { |
140 switch (si->dc_range) { |
211 switch (si->dc_range) { |
141 case EC_DC_32: |
212 case EC_DC_32: |
142 cout << "32 bit"; |
213 cout << "32 bit"; |
152 } |
223 } |
153 cout << "\\nDelay: " << si->transmission_delay << " ns"; |
224 cout << "\\nDelay: " << si->transmission_delay << " ns"; |
154 } |
225 } |
155 cout << "\"]" << endl; |
226 cout << "\"]" << endl; |
156 |
227 |
157 for (i = 1; i < EC_MAX_PORTS; i++) { |
228 |
158 uint16_t next_pos = si->ports[i].next_slave; |
229 for (int port = 1; port < EC_MAX_PORTS; port++) { |
159 ec_ioctl_slave_t *next = NULL; |
230 uint16_t next_pos = si->ports[port].next_slave; |
160 |
231 |
161 if (next_pos == 0xffff) |
232 if (next_pos == 0xffff) { |
162 continue; |
233 continue; |
163 |
234 } |
164 if (next_pos < slaves.size()) { |
235 |
165 next = &slaves[next_pos]; |
236 if (next_pos >= slaves.size()) { |
166 } else { |
|
167 cerr << "Invalid next slave pointer." << endl; |
237 cerr << "Invalid next slave pointer." << endl; |
168 } |
238 continue; |
|
239 } |
|
240 |
|
241 ec_ioctl_slave_t *next = &slaves[next_pos]; |
169 |
242 |
170 cout << " slave" << si->position << " -- " |
243 cout << " slave" << si->position << " -- " |
171 << "slave" << next_pos << " [taillabel=\"" << i; |
244 << "slave" << next_pos << " [taillabel=\"" << port; |
172 |
245 |
173 if (si->dc_supported) { |
246 if (info == DC && si->dc_supported) { |
174 cout << " [" << si->ports[i].delay_to_next_dc << "]"; |
247 cout << " [" << si->ports[port].delay_to_next_dc << "]"; |
175 } |
248 } |
|
249 if (info == CRC) { |
|
250 CrcInfo *crcInfo = &crcInfos[si->position]; |
|
251 cout << " [" << crcInfo->crc[port] << "/" |
|
252 << crcInfo->fwd[port] << "]"; |
|
253 } |
|
254 |
176 cout << "\",headlabel=\"0"; |
255 cout << "\",headlabel=\"0"; |
177 |
256 |
178 if (next && next->dc_supported) { |
257 if (info == DC && next->dc_supported) { |
179 cout << " [" << next->ports[0].delay_to_next_dc << "]"; |
258 cout << " [" << next->ports[0].delay_to_next_dc << "]"; |
180 } |
259 } |
|
260 if (info == CRC) { |
|
261 CrcInfo *crcInfo = &crcInfos[next_pos]; |
|
262 cout << " [" << crcInfo->crc[0] << "/" |
|
263 << crcInfo->fwd[0] << "]"; |
|
264 } |
181 cout << "\""; |
265 cout << "\""; |
182 |
266 |
183 mi = portMedia.find(si->ports[i].desc); |
267 mi = portMedia.find(si->ports[port].desc); |
184 if (mi == portMedia.end() && next) { |
268 if (mi == portMedia.end() && next) { |
185 /* Try medium of next-hop slave. */ |
269 /* Try medium of next-hop slave. */ |
186 mi = portMedia.find(next->ports[0].desc); |
270 mi = portMedia.find(next->ports[0].desc); |
187 } |
271 } |
188 |
272 |
189 if (mi != portMedia.end()) |
273 if (mi != portMedia.end()) |
190 cout << ",label=\"" << mi->second << "\""; |
274 cout << ",label=\"" << mi->second << "\""; |
191 |
275 |
192 wi = mediaWeights.find(si->ports[i].desc); |
276 wi = mediaWeights.find(si->ports[port].desc); |
193 if (wi != mediaWeights.end()) |
277 if (wi != mediaWeights.end()) |
194 cout << ",weight=\"" << wi->second << "\""; |
278 cout << ",weight=\"" << wi->second << "\""; |
195 |
279 |
196 cout << "]" << endl; |
280 cout << "]" << endl; |
197 } |
281 } |