65 */ |
65 */ |
66 #define DEBUG_LONG 0 |
66 #define DEBUG_LONG 0 |
67 |
67 |
68 /*****************************************************************************/ |
68 /*****************************************************************************/ |
69 |
69 |
70 void ec_fsm_coe_dict_start(ec_fsm_coe_t *); |
70 void ec_fsm_coe_dict_start(ec_fsm_coe_t *, ec_datagram_t *); |
71 void ec_fsm_coe_dict_request(ec_fsm_coe_t *); |
71 void ec_fsm_coe_dict_request(ec_fsm_coe_t *, ec_datagram_t *); |
72 void ec_fsm_coe_dict_check(ec_fsm_coe_t *); |
72 void ec_fsm_coe_dict_check(ec_fsm_coe_t *, ec_datagram_t *); |
73 void ec_fsm_coe_dict_response(ec_fsm_coe_t *); |
73 void ec_fsm_coe_dict_response(ec_fsm_coe_t *, ec_datagram_t *); |
74 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *); |
74 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *, ec_datagram_t *); |
75 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *); |
75 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *, ec_datagram_t *); |
76 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *); |
76 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *, ec_datagram_t *); |
77 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *); |
77 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *, ec_datagram_t *); |
78 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *); |
78 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *, ec_datagram_t *); |
79 void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *); |
79 void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *, ec_datagram_t *); |
80 |
80 |
81 void ec_fsm_coe_down_start(ec_fsm_coe_t *); |
81 void ec_fsm_coe_down_start(ec_fsm_coe_t *, ec_datagram_t *); |
82 void ec_fsm_coe_down_request(ec_fsm_coe_t *); |
82 void ec_fsm_coe_down_request(ec_fsm_coe_t *, ec_datagram_t *); |
83 void ec_fsm_coe_down_check(ec_fsm_coe_t *); |
83 void ec_fsm_coe_down_check(ec_fsm_coe_t *, ec_datagram_t *); |
84 void ec_fsm_coe_down_response(ec_fsm_coe_t *); |
84 void ec_fsm_coe_down_response(ec_fsm_coe_t *, ec_datagram_t *); |
85 void ec_fsm_coe_down_seg_check(ec_fsm_coe_t *); |
85 void ec_fsm_coe_down_seg_check(ec_fsm_coe_t *, ec_datagram_t *); |
86 void ec_fsm_coe_down_seg_response(ec_fsm_coe_t *); |
86 void ec_fsm_coe_down_seg_response(ec_fsm_coe_t *, ec_datagram_t *); |
87 |
87 |
88 void ec_fsm_coe_up_start(ec_fsm_coe_t *); |
88 void ec_fsm_coe_up_start(ec_fsm_coe_t *, ec_datagram_t *); |
89 void ec_fsm_coe_up_request(ec_fsm_coe_t *); |
89 void ec_fsm_coe_up_request(ec_fsm_coe_t *, ec_datagram_t *); |
90 void ec_fsm_coe_up_check(ec_fsm_coe_t *); |
90 void ec_fsm_coe_up_check(ec_fsm_coe_t *, ec_datagram_t *); |
91 void ec_fsm_coe_up_response(ec_fsm_coe_t *); |
91 void ec_fsm_coe_up_response(ec_fsm_coe_t *, ec_datagram_t *); |
92 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *); |
92 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *, ec_datagram_t *); |
93 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *); |
93 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *, ec_datagram_t *); |
94 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *); |
94 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *, ec_datagram_t *); |
95 |
95 |
96 void ec_fsm_coe_end(ec_fsm_coe_t *); |
96 void ec_fsm_coe_end(ec_fsm_coe_t *, ec_datagram_t *); |
97 void ec_fsm_coe_error(ec_fsm_coe_t *); |
97 void ec_fsm_coe_error(ec_fsm_coe_t *, ec_datagram_t *); |
98 |
98 |
99 /*****************************************************************************/ |
99 /*****************************************************************************/ |
100 |
100 |
101 /** |
101 /** SDO abort messages. |
102 SDO abort messages. |
102 * |
103 The "abort SDO transfer request" supplies an abort code, |
103 * The "abort SDO transfer request" supplies an abort code, which can be |
104 which can be translated to clear text. This table does |
104 * translated to clear text. This table does the mapping of the codes and |
105 the mapping of the codes and messages. |
105 * messages. |
106 */ |
106 */ |
107 |
|
108 const ec_code_msg_t sdo_abort_messages[] = { |
107 const ec_code_msg_t sdo_abort_messages[] = { |
109 {0x05030000, "Toggle bit not changed"}, |
108 {0x05030000, "Toggle bit not changed"}, |
110 {0x05040000, "SDO protocol timeout"}, |
109 {0x05040000, "SDO protocol timeout"}, |
111 {0x05040001, "Client/Server command specifier not valid or unknown"}, |
110 {0x05040001, "Client/Server command specifier not valid or unknown"}, |
112 {0x05040005, "Out of memory"}, |
111 {0x05040005, "Out of memory"}, |
161 EC_SLAVE_ERR(slave, "Unknown SDO abort code 0x%08X.\n", abort_code); |
163 EC_SLAVE_ERR(slave, "Unknown SDO abort code 0x%08X.\n", abort_code); |
162 } |
164 } |
163 |
165 |
164 /*****************************************************************************/ |
166 /*****************************************************************************/ |
165 |
167 |
166 /** |
168 /** Constructor. |
167 Constructor. |
169 */ |
168 */ |
170 void ec_fsm_coe_init( |
169 |
171 ec_fsm_coe_t *fsm /**< Finite state machine */ |
170 void ec_fsm_coe_init(ec_fsm_coe_t *fsm, /**< finite state machine */ |
172 ) |
171 ec_mailbox_t *mbox /**< mailbox */ |
|
172 ) |
|
173 { |
173 { |
174 fsm->state = NULL; |
174 fsm->state = NULL; |
175 fsm->mbox = mbox; |
175 fsm->datagram = NULL; |
176 } |
176 } |
177 |
177 |
178 /*****************************************************************************/ |
178 /*****************************************************************************/ |
179 |
179 |
180 /** |
180 /** Destructor. |
181 Destructor. |
181 */ |
182 */ |
182 void ec_fsm_coe_clear( |
183 |
183 ec_fsm_coe_t *fsm /**< Finite state machine */ |
184 void ec_fsm_coe_clear(ec_fsm_coe_t *fsm /**< finite state machine */) |
184 ) |
185 { |
185 { |
186 } |
186 } |
187 |
187 |
188 /*****************************************************************************/ |
188 /*****************************************************************************/ |
189 |
189 |
190 /** |
190 /** Starts reading a slaves' SDO dictionary. |
191 Starts reading a slaves' SDO dictionary. |
191 */ |
192 */ |
192 void ec_fsm_coe_dictionary( |
193 |
193 ec_fsm_coe_t *fsm, /**< Finite state machine */ |
194 void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, /**< finite state machine */ |
194 ec_slave_t *slave /**< EtherCAT slave */ |
195 ec_slave_t *slave /**< EtherCAT slave */ |
195 ) |
196 ) |
|
197 { |
196 { |
198 fsm->slave = slave; |
197 fsm->slave = slave; |
199 fsm->state = ec_fsm_coe_dict_start; |
198 fsm->state = ec_fsm_coe_dict_start; |
200 } |
199 } |
201 |
200 |
202 /*****************************************************************************/ |
201 /*****************************************************************************/ |
203 |
202 |
204 /** |
203 /** Starts to transfer an SDO to/from a slave. |
205 Starts to transfer an SDO to/from a slave. |
204 */ |
206 */ |
|
207 |
|
208 void ec_fsm_coe_transfer( |
205 void ec_fsm_coe_transfer( |
209 ec_fsm_coe_t *fsm, /**< State machine. */ |
206 ec_fsm_coe_t *fsm, /**< State machine. */ |
210 ec_slave_t *slave, /**< EtherCAT slave. */ |
207 ec_slave_t *slave, /**< EtherCAT slave. */ |
211 ec_sdo_request_t *request /**< SDO request. */ |
208 ec_sdo_request_t *request /**< SDO request. */ |
212 ) |
209 ) |
213 { |
210 { |
214 fsm->slave = slave; |
211 fsm->slave = slave; |
215 fsm->request = request; |
212 fsm->request = request; |
216 if (request->dir == EC_DIR_OUTPUT) |
213 |
|
214 if (request->dir == EC_DIR_OUTPUT) { |
217 fsm->state = ec_fsm_coe_down_start; |
215 fsm->state = ec_fsm_coe_down_start; |
218 else |
216 } |
|
217 else { |
219 fsm->state = ec_fsm_coe_up_start; |
218 fsm->state = ec_fsm_coe_up_start; |
220 } |
219 } |
221 |
220 } |
222 /*****************************************************************************/ |
221 |
223 |
222 /*****************************************************************************/ |
224 /** |
223 |
225 Executes the current state of the state machine. |
224 /** Executes the current state of the state machine. |
226 \return false, if state machine has terminated |
225 * |
227 */ |
226 * \return 1 if the datagram was used, else 0. |
228 |
227 */ |
229 int ec_fsm_coe_exec(ec_fsm_coe_t *fsm /**< finite state machine */) |
228 int ec_fsm_coe_exec( |
230 { |
229 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
231 fsm->state(fsm); |
230 ec_datagram_t *datagram /**< Datagram to use. */ |
232 |
231 ) |
233 return fsm->state != ec_fsm_coe_end && fsm->state != ec_fsm_coe_error; |
232 { |
234 } |
233 int datagram_used = 0; |
235 |
234 |
236 /*****************************************************************************/ |
235 if (fsm->datagram && |
237 |
236 (fsm->datagram->state == EC_DATAGRAM_INIT || |
238 /** |
237 fsm->datagram->state == EC_DATAGRAM_QUEUED || |
239 Returns, if the state machine terminated with success. |
238 fsm->datagram->state == EC_DATAGRAM_SENT)) { |
240 \return non-zero if successful. |
239 // datagram not received yet |
241 */ |
240 return datagram_used; |
242 |
241 } |
243 int ec_fsm_coe_success(ec_fsm_coe_t *fsm /**< Finite state machine */) |
242 |
|
243 fsm->state(fsm, datagram); |
|
244 |
|
245 datagram_used = |
|
246 fsm->state != ec_fsm_coe_end && fsm->state != ec_fsm_coe_error; |
|
247 |
|
248 if (datagram_used) { |
|
249 fsm->datagram = datagram; |
|
250 } else { |
|
251 fsm->datagram = NULL; |
|
252 } |
|
253 |
|
254 return datagram_used; |
|
255 } |
|
256 |
|
257 /*****************************************************************************/ |
|
258 |
|
259 /** Returns, if the state machine terminated with success. |
|
260 * \return non-zero if successful. |
|
261 */ |
|
262 int ec_fsm_coe_success( |
|
263 const ec_fsm_coe_t *fsm /**< Finite state machine */ |
|
264 ) |
244 { |
265 { |
245 return fsm->state == ec_fsm_coe_end; |
266 return fsm->state == ec_fsm_coe_end; |
246 } |
267 } |
247 |
268 |
248 /*****************************************************************************/ |
269 /*****************************************************************************/ |
278 |
306 |
279 /****************************************************************************** |
307 /****************************************************************************** |
280 * CoE dictionary state machine |
308 * CoE dictionary state machine |
281 *****************************************************************************/ |
309 *****************************************************************************/ |
282 |
310 |
283 /** |
311 /** Prepare a dictionary request. |
284 CoE state: DICT START. |
312 * |
285 */ |
313 * \return Zero on success, otherwise a negative error code. |
286 |
314 */ |
287 void ec_fsm_coe_dict_start(ec_fsm_coe_t *fsm /**< finite state machine */) |
315 int ec_fsm_coe_prepare_dict( |
288 { |
316 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
289 ec_mailbox_t *mbox = fsm->mbox; |
317 ec_datagram_t *datagram /**< Datagram to use. */ |
290 ec_slave_t *slave = fsm->slave; |
318 ) |
291 uint8_t *data; |
319 { |
292 |
320 ec_slave_t *slave = fsm->slave; |
293 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) { |
321 uint8_t *data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8); |
294 EC_SLAVE_ERR(slave, "Slave does not support CoE!\n"); |
|
295 fsm->state = ec_fsm_coe_error; |
|
296 return; |
|
297 } |
|
298 |
|
299 if (slave->sii.has_general && !slave->sii.coe_details.enable_sdo_info) { |
|
300 EC_SLAVE_ERR(slave, "Slave does not support" |
|
301 " SDO information service!\n"); |
|
302 fsm->state = ec_fsm_coe_error; |
|
303 return; |
|
304 } |
|
305 |
|
306 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, 8); |
|
307 if (IS_ERR(data)) { |
322 if (IS_ERR(data)) { |
308 fsm->state = ec_fsm_coe_error; |
323 return PTR_ERR(data); |
309 return; |
|
310 } |
324 } |
311 |
325 |
312 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
326 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
313 EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request |
327 EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request |
314 EC_WRITE_U8 (data + 3, 0x00); |
328 EC_WRITE_U8 (data + 3, 0x00); |
315 EC_WRITE_U16(data + 4, 0x0000); |
329 EC_WRITE_U16(data + 4, 0x0000); |
316 EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs! |
330 EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs! |
317 |
331 |
|
332 fsm->state = ec_fsm_coe_dict_request; |
|
333 return 0; |
|
334 } |
|
335 |
|
336 /*****************************************************************************/ |
|
337 |
|
338 /** CoE state: DICT START. |
|
339 */ |
|
340 void ec_fsm_coe_dict_start( |
|
341 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
|
342 ec_datagram_t *datagram /**< Datagram to use. */ |
|
343 ) |
|
344 { |
|
345 ec_slave_t *slave = fsm->slave; |
|
346 |
|
347 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) { |
|
348 EC_SLAVE_ERR(slave, "Slave does not support CoE!\n"); |
|
349 fsm->state = ec_fsm_coe_error; |
|
350 return; |
|
351 } |
|
352 |
|
353 if (slave->sii.has_general && !slave->sii.coe_details.enable_sdo_info) { |
|
354 EC_SLAVE_ERR(slave, "Slave does not support" |
|
355 " SDO information service!\n"); |
|
356 fsm->state = ec_fsm_coe_error; |
|
357 return; |
|
358 } |
|
359 |
318 fsm->retries = EC_FSM_RETRIES; |
360 fsm->retries = EC_FSM_RETRIES; |
319 fsm->state = ec_fsm_coe_dict_request; |
361 |
320 } |
362 if (ec_fsm_coe_prepare_dict(fsm, datagram)) { |
321 |
363 fsm->state = ec_fsm_coe_error; |
322 /*****************************************************************************/ |
364 } |
323 |
365 } |
324 /** |
366 |
325 CoE state: DICT REQUEST. |
367 /*****************************************************************************/ |
326 \todo Timeout behavior |
368 |
327 */ |
369 /** CoE state: DICT REQUEST. |
328 |
370 * \todo Timeout behavior |
329 void ec_fsm_coe_dict_request(ec_fsm_coe_t *fsm /**< finite state machine */) |
371 */ |
330 { |
372 void ec_fsm_coe_dict_request( |
331 ec_mailbox_t *mbox = fsm->mbox; |
373 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
332 ec_datagram_t *datagram = mbox->datagram; |
374 ec_datagram_t *datagram /**< Datagram to use. */ |
333 ec_slave_t *slave = fsm->slave; |
375 ) |
334 |
376 { |
335 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
377 ec_slave_t *slave = fsm->slave; |
336 && fsm->retries--) { |
378 |
337 return; // FIXME: request again? |
379 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
338 } |
380 if (ec_fsm_coe_prepare_dict(fsm, datagram)) { |
339 |
381 fsm->state = ec_fsm_coe_error; |
340 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
382 } |
|
383 return; |
|
384 } |
|
385 |
|
386 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
341 fsm->state = ec_fsm_coe_error; |
387 fsm->state = ec_fsm_coe_error; |
342 EC_SLAVE_ERR(slave, "Failed to receive CoE dictionary" |
388 EC_SLAVE_ERR(slave, "Failed to receive CoE dictionary" |
343 " request datagram: "); |
389 " request datagram: "); |
344 ec_datagram_print_state(datagram); |
390 ec_datagram_print_state(fsm->datagram); |
345 return; |
391 return; |
346 } |
392 } |
347 |
393 |
348 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
394 if (fsm->datagram->working_counter != 1) { |
349 fsm->state = ec_fsm_coe_error; |
395 fsm->state = ec_fsm_coe_error; |
350 EC_SLAVE_ERR(slave, "Reception of CoE dictionary request failed: "); |
396 EC_SLAVE_ERR(slave, "Reception of CoE dictionary request failed: "); |
351 ec_datagram_print_wc_error(datagram); |
397 ec_datagram_print_wc_error(fsm->datagram); |
352 return; |
398 return; |
353 } |
399 } |
354 |
400 |
355 fsm->jiffies_start = datagram->jiffies_sent; |
401 fsm->jiffies_start = fsm->datagram->jiffies_sent; |
356 |
402 |
357 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
403 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
358 fsm->retries = EC_FSM_RETRIES; |
404 fsm->retries = EC_FSM_RETRIES; |
359 fsm->state = ec_fsm_coe_dict_check; |
405 fsm->state = ec_fsm_coe_dict_check; |
360 } |
406 } |
361 |
407 |
362 /*****************************************************************************/ |
408 /*****************************************************************************/ |
363 |
409 |
364 /** |
410 /** CoE state: DICT CHECK. |
365 CoE state: DICT CHECK. |
411 */ |
366 */ |
412 void ec_fsm_coe_dict_check( |
367 |
413 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
368 void ec_fsm_coe_dict_check(ec_fsm_coe_t *fsm /**< finite state machine */) |
414 ec_datagram_t *datagram /**< Datagram to use. */ |
369 { |
415 ) |
370 ec_mailbox_t *mbox = fsm->mbox; |
416 { |
371 ec_datagram_t *datagram = mbox->datagram; |
417 ec_slave_t *slave = fsm->slave; |
372 ec_slave_t *slave = fsm->slave; |
418 |
373 |
419 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
374 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
420 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
375 && fsm->retries--) { |
421 return; |
376 return; |
422 } |
377 } |
423 |
378 |
424 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
379 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
|
380 fsm->state = ec_fsm_coe_error; |
425 fsm->state = ec_fsm_coe_error; |
381 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
426 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
382 ec_datagram_print_state(datagram); |
427 ec_datagram_print_state(fsm->datagram); |
383 return; |
428 return; |
384 } |
429 } |
385 |
430 |
386 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
431 if (fsm->datagram->working_counter != 1) { |
387 fsm->state = ec_fsm_coe_error; |
432 fsm->state = ec_fsm_coe_error; |
388 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
433 EC_SLAVE_ERR(slave,"Reception of CoE mailbox check" |
389 " datagram failed: "); |
434 " datagram failed: "); |
390 ec_datagram_print_wc_error(datagram); |
435 ec_datagram_print_wc_error(fsm->datagram); |
391 return; |
436 return; |
392 } |
437 } |
393 |
438 |
394 if (!ec_slave_mbox_check(mbox)) { |
439 if (!ec_slave_mbox_check(fsm->datagram)) { |
395 unsigned long diff_ms = |
440 unsigned long diff_ms = |
396 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
441 (fsm->datagram->jiffies_received - fsm->jiffies_start) * |
|
442 1000 / HZ; |
397 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { |
443 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { |
398 fsm->state = ec_fsm_coe_error; |
444 fsm->state = ec_fsm_coe_error; |
399 EC_SLAVE_ERR(slave, "Timeout while waiting for" |
445 EC_SLAVE_ERR(slave, "Timeout while waiting for" |
400 " SDO dictionary list response.\n"); |
446 " SDO dictionary list response.\n"); |
401 return; |
447 return; |
402 } |
448 } |
403 |
449 |
404 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
450 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
405 fsm->retries = EC_FSM_RETRIES; |
451 fsm->retries = EC_FSM_RETRIES; |
406 return; |
452 return; |
407 } |
453 } |
408 |
454 |
409 // Fetch response |
455 // Fetch response |
410 ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail. |
456 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
411 fsm->retries = EC_FSM_RETRIES; |
457 fsm->retries = EC_FSM_RETRIES; |
412 fsm->state = ec_fsm_coe_dict_response; |
458 fsm->state = ec_fsm_coe_dict_response; |
|
459 } |
|
460 |
|
461 /*****************************************************************************/ |
|
462 |
|
463 /** Prepare an object description request. |
|
464 * |
|
465 * \return Zero on success, otherwise a negative error code. |
|
466 */ |
|
467 int ec_fsm_coe_dict_prepare_desc( |
|
468 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
|
469 ec_datagram_t *datagram /**< Datagram to use. */ |
|
470 ) |
|
471 { |
|
472 ec_slave_t *slave = fsm->slave; |
|
473 u8 *data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8); |
|
474 if (IS_ERR(data)) { |
|
475 return PTR_ERR(data); |
|
476 } |
|
477 |
|
478 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
|
479 EC_WRITE_U8 (data + 2, 0x03); // Get object description request |
|
480 EC_WRITE_U8 (data + 3, 0x00); |
|
481 EC_WRITE_U16(data + 4, 0x0000); |
|
482 EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index |
|
483 |
|
484 fsm->state = ec_fsm_coe_dict_desc_request; |
|
485 return 0; |
413 } |
486 } |
414 |
487 |
415 /*****************************************************************************/ |
488 /*****************************************************************************/ |
416 |
489 |
417 /** |
490 /** |
418 CoE state: DICT RESPONSE. |
491 CoE state: DICT RESPONSE. |
419 \todo Timeout behavior |
492 \todo Timeout behavior |
420 */ |
493 */ |
421 |
494 |
422 void ec_fsm_coe_dict_response(ec_fsm_coe_t *fsm /**< finite state machine */) |
495 void ec_fsm_coe_dict_response( |
423 { |
496 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
424 ec_mailbox_t *mbox = fsm->mbox; |
497 ec_datagram_t *datagram /**< Datagram to use. */ |
425 ec_datagram_t *datagram = mbox->datagram; |
498 ) |
|
499 { |
426 ec_slave_t *slave = fsm->slave; |
500 ec_slave_t *slave = fsm->slave; |
427 uint8_t *data, mbox_prot; |
501 uint8_t *data, mbox_prot; |
428 size_t rec_size; |
502 size_t rec_size; |
429 unsigned int sdo_count, i; |
503 unsigned int sdo_count, i; |
430 uint16_t sdo_index, fragments_left; |
504 uint16_t sdo_index, fragments_left; |
431 ec_sdo_t *sdo; |
505 ec_sdo_t *sdo; |
432 bool first_segment; |
506 bool first_segment; |
433 size_t index_list_offset; |
507 size_t index_list_offset; |
434 |
508 |
435 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
509 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
436 && fsm->retries--) { |
510 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
437 return; // FIXME: request again? |
511 return; |
438 } |
512 } |
439 |
513 |
440 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
514 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
441 fsm->state = ec_fsm_coe_error; |
515 fsm->state = ec_fsm_coe_error; |
442 EC_SLAVE_ERR(slave, "Failed to receive CoE dictionary" |
516 EC_SLAVE_ERR(slave, "Failed to receive CoE dictionary" |
443 " response datagram: "); |
517 " response datagram: "); |
444 ec_datagram_print_state(datagram); |
518 ec_datagram_print_state(fsm->datagram); |
445 return; |
519 return; |
446 } |
520 } |
447 |
521 |
448 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
522 if (fsm->datagram->working_counter != 1) { |
449 fsm->state = ec_fsm_coe_error; |
523 fsm->state = ec_fsm_coe_error; |
450 EC_SLAVE_ERR(slave, "Reception of CoE dictionary response failed: "); |
524 EC_SLAVE_ERR(slave, "Reception of CoE dictionary response failed: "); |
451 ec_datagram_print_wc_error(datagram); |
525 ec_datagram_print_wc_error(fsm->datagram); |
452 return; |
526 return; |
453 } |
527 } |
454 |
528 |
455 data = ec_slave_mbox_fetch(slave, mbox, &mbox_prot, &rec_size); |
529 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size); |
456 if (IS_ERR(data)) { |
530 if (IS_ERR(data)) { |
457 fsm->state = ec_fsm_coe_error; |
531 fsm->state = ec_fsm_coe_error; |
458 return; |
532 return; |
459 } |
533 } |
460 |
534 |
558 } |
632 } |
559 |
633 |
560 // fetch SDO descriptions |
634 // fetch SDO descriptions |
561 fsm->sdo = list_entry(slave->sdo_dictionary.next, ec_sdo_t, list); |
635 fsm->sdo = list_entry(slave->sdo_dictionary.next, ec_sdo_t, list); |
562 |
636 |
563 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, 8); |
|
564 if (IS_ERR(data)) { |
|
565 fsm->state = ec_fsm_coe_error; |
|
566 return; |
|
567 } |
|
568 |
|
569 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
|
570 EC_WRITE_U8 (data + 2, 0x03); // Get object description request |
|
571 EC_WRITE_U8 (data + 3, 0x00); |
|
572 EC_WRITE_U16(data + 4, 0x0000); |
|
573 EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index |
|
574 |
|
575 fsm->retries = EC_FSM_RETRIES; |
637 fsm->retries = EC_FSM_RETRIES; |
576 fsm->state = ec_fsm_coe_dict_desc_request; |
638 if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) { |
|
639 fsm->state = ec_fsm_coe_error; |
|
640 } |
577 } |
641 } |
578 |
642 |
579 /*****************************************************************************/ |
643 /*****************************************************************************/ |
580 |
644 |
581 /** |
645 /** |
582 CoE state: DICT DESC REQUEST. |
646 CoE state: DICT DESC REQUEST. |
583 \todo Timeout behavior |
647 \todo Timeout behavior |
584 */ |
648 */ |
585 |
649 |
586 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *fsm /**< finite state machine */) |
650 void ec_fsm_coe_dict_desc_request( |
587 { |
651 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
588 ec_mailbox_t *mbox = fsm->mbox; |
652 ec_datagram_t *datagram /**< Datagram to use. */ |
589 ec_datagram_t *datagram = mbox->datagram; |
653 ) |
590 ec_slave_t *slave = fsm->slave; |
654 { |
591 |
655 ec_slave_t *slave = fsm->slave; |
592 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
656 |
593 && fsm->retries--) |
657 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
594 return; // FIXME: check for response first? |
658 if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) { |
595 |
659 fsm->state = ec_fsm_coe_error; |
596 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
660 } |
|
661 return; |
|
662 } |
|
663 |
|
664 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
597 fsm->state = ec_fsm_coe_error; |
665 fsm->state = ec_fsm_coe_error; |
598 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO" |
666 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO" |
599 " description request datagram: "); |
667 " description request datagram: "); |
600 ec_datagram_print_state(datagram); |
668 ec_datagram_print_state(fsm->datagram); |
601 return; |
669 return; |
602 } |
670 } |
603 |
671 |
604 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
672 if (fsm->datagram->working_counter != 1) { |
605 fsm->state = ec_fsm_coe_error; |
673 fsm->state = ec_fsm_coe_error; |
606 EC_SLAVE_ERR(slave, "Reception of CoE SDO description" |
674 EC_SLAVE_ERR(slave, "Reception of CoE SDO description" |
607 " request failed: "); |
675 " request failed: "); |
608 ec_datagram_print_wc_error(datagram); |
676 ec_datagram_print_wc_error(fsm->datagram); |
609 return; |
677 return; |
610 } |
678 } |
611 |
679 |
612 fsm->jiffies_start = datagram->jiffies_sent; |
680 fsm->jiffies_start = fsm->datagram->jiffies_sent; |
613 |
681 |
614 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
682 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
615 fsm->retries = EC_FSM_RETRIES; |
683 fsm->retries = EC_FSM_RETRIES; |
616 fsm->state = ec_fsm_coe_dict_desc_check; |
684 fsm->state = ec_fsm_coe_dict_desc_check; |
617 } |
685 } |
618 |
686 |
619 /*****************************************************************************/ |
687 /*****************************************************************************/ |
620 |
688 |
621 /** |
689 /** |
622 CoE state: DICT DESC CHECK. |
690 CoE state: DICT DESC CHECK. |
623 */ |
691 */ |
624 |
692 |
625 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *fsm /**< finite state machine */) |
693 void ec_fsm_coe_dict_desc_check( |
626 { |
694 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
627 ec_mailbox_t *mbox = fsm->mbox; |
695 ec_datagram_t *datagram /**< Datagram to use. */ |
628 ec_datagram_t *datagram = mbox->datagram; |
696 ) |
629 ec_slave_t *slave = fsm->slave; |
697 { |
630 |
698 ec_slave_t *slave = fsm->slave; |
631 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
699 |
632 && fsm->retries--) { |
700 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
633 return; |
701 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
634 } |
702 return; |
635 |
703 } |
636 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
704 |
|
705 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
637 fsm->state = ec_fsm_coe_error; |
706 fsm->state = ec_fsm_coe_error; |
638 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
707 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
639 ec_datagram_print_state(datagram); |
708 ec_datagram_print_state(fsm->datagram); |
640 return; |
709 return; |
641 } |
710 } |
642 |
711 |
643 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
712 if (fsm->datagram->working_counter != 1) { |
644 fsm->state = ec_fsm_coe_error; |
713 fsm->state = ec_fsm_coe_error; |
645 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
714 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
646 " datagram failed: "); |
715 " datagram failed: "); |
647 ec_datagram_print_wc_error(datagram); |
716 ec_datagram_print_wc_error(fsm->datagram); |
648 return; |
717 return; |
649 } |
718 } |
650 |
719 |
651 if (!ec_slave_mbox_check(mbox)) { |
720 if (!ec_slave_mbox_check(fsm->datagram)) { |
652 unsigned long diff_ms = |
721 unsigned long diff_ms = |
653 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
722 (fsm->datagram->jiffies_received - fsm->jiffies_start) * |
|
723 1000 / HZ; |
654 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { |
724 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { |
655 fsm->state = ec_fsm_coe_error; |
725 fsm->state = ec_fsm_coe_error; |
656 EC_SLAVE_ERR(slave, "Timeout while waiting for" |
726 EC_SLAVE_ERR(slave, "Timeout while waiting for" |
657 " SDO 0x%04x object description response.\n", |
727 " SDO 0x%04x object description response.\n", |
658 fsm->sdo->index); |
728 fsm->sdo->index); |
659 return; |
729 return; |
660 } |
730 } |
661 |
731 |
662 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
732 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
663 fsm->retries = EC_FSM_RETRIES; |
733 fsm->retries = EC_FSM_RETRIES; |
664 return; |
734 return; |
665 } |
735 } |
666 |
736 |
667 // Fetch response |
737 // Fetch response |
668 ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail. |
738 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
669 fsm->retries = EC_FSM_RETRIES; |
739 fsm->retries = EC_FSM_RETRIES; |
670 fsm->state = ec_fsm_coe_dict_desc_response; |
740 fsm->state = ec_fsm_coe_dict_desc_response; |
|
741 } |
|
742 |
|
743 /*****************************************************************************/ |
|
744 |
|
745 /** Prepare an entry description request. |
|
746 * |
|
747 * \return Zero on success, otherwise a negative error code. |
|
748 */ |
|
749 int ec_fsm_coe_dict_prepare_entry( |
|
750 ec_fsm_coe_t *fsm, /**< Finite state machine */ |
|
751 ec_datagram_t *datagram /**< Datagram to use. */ |
|
752 ) |
|
753 { |
|
754 ec_slave_t *slave = fsm->slave; |
|
755 u8 *data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10); |
|
756 if (IS_ERR(data)) { |
|
757 return PTR_ERR(data); |
|
758 } |
|
759 |
|
760 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
|
761 EC_WRITE_U8 (data + 2, 0x05); // Get entry description request |
|
762 EC_WRITE_U8 (data + 3, 0x00); |
|
763 EC_WRITE_U16(data + 4, 0x0000); |
|
764 EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index |
|
765 EC_WRITE_U8 (data + 8, fsm->subindex); // SDO subindex |
|
766 EC_WRITE_U8 (data + 9, 0x01); // value info (access rights only) |
|
767 |
|
768 fsm->state = ec_fsm_coe_dict_entry_request; |
|
769 return 0; |
671 } |
770 } |
672 |
771 |
673 /*****************************************************************************/ |
772 /*****************************************************************************/ |
674 |
773 |
675 /** |
774 /** |
676 CoE state: DICT DESC RESPONSE. |
775 CoE state: DICT DESC RESPONSE. |
677 \todo Timeout behavior |
776 \todo Timeout behavior |
678 */ |
777 */ |
679 |
778 |
680 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *fsm |
779 void ec_fsm_coe_dict_desc_response( |
681 /**< finite state machine */) |
780 ec_fsm_coe_t *fsm, /**< Finite state machine */ |
682 { |
781 ec_datagram_t *datagram /**< Datagram to use. */ |
683 ec_mailbox_t *mbox = fsm->mbox; |
782 ) |
684 ec_datagram_t *datagram = mbox->datagram; |
783 { |
685 ec_slave_t *slave = fsm->slave; |
784 ec_slave_t *slave = fsm->slave; |
686 ec_sdo_t *sdo = fsm->sdo; |
785 ec_sdo_t *sdo = fsm->sdo; |
687 uint8_t *data, mbox_prot; |
786 uint8_t *data, mbox_prot; |
688 size_t rec_size, name_size; |
787 size_t rec_size, name_size; |
689 |
788 |
690 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
789 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
691 && fsm->retries--) { |
790 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
692 return; // FIXME: request again? |
791 return; |
693 } |
792 } |
694 |
793 |
695 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
794 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
696 fsm->state = ec_fsm_coe_error; |
795 fsm->state = ec_fsm_coe_error; |
697 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO description" |
796 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO description" |
698 " response datagram: "); |
797 " response datagram: "); |
699 ec_datagram_print_state(datagram); |
798 ec_datagram_print_state(fsm->datagram); |
700 return; |
799 return; |
701 } |
800 } |
702 |
801 |
703 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
802 if (fsm->datagram->working_counter != 1) { |
704 fsm->state = ec_fsm_coe_error; |
803 fsm->state = ec_fsm_coe_error; |
705 EC_SLAVE_ERR(slave, "Reception of CoE SDO description" |
804 EC_SLAVE_ERR(slave, "Reception of CoE SDO description" |
706 " response failed: "); |
805 " response failed: "); |
707 ec_datagram_print_wc_error(datagram); |
806 ec_datagram_print_wc_error(fsm->datagram); |
708 return; |
807 return; |
709 } |
808 } |
710 |
809 |
711 data = ec_slave_mbox_fetch(slave, mbox, &mbox_prot, &rec_size); |
810 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size); |
712 if (IS_ERR(data)) { |
811 if (IS_ERR(data)) { |
713 fsm->state = ec_fsm_coe_error; |
812 fsm->state = ec_fsm_coe_error; |
714 return; |
813 return; |
715 } |
814 } |
716 |
815 |
796 } |
895 } |
797 |
896 |
798 // start fetching entries |
897 // start fetching entries |
799 |
898 |
800 fsm->subindex = 0; |
899 fsm->subindex = 0; |
801 |
|
802 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, 10); |
|
803 if (IS_ERR(data)) { |
|
804 fsm->state = ec_fsm_coe_error; |
|
805 return; |
|
806 } |
|
807 |
|
808 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
|
809 EC_WRITE_U8 (data + 2, 0x05); // Get entry description request |
|
810 EC_WRITE_U8 (data + 3, 0x00); |
|
811 EC_WRITE_U16(data + 4, 0x0000); |
|
812 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
|
813 EC_WRITE_U8 (data + 8, fsm->subindex); // SDO subindex |
|
814 EC_WRITE_U8 (data + 9, 0x01); // value info (access rights only) |
|
815 |
|
816 fsm->retries = EC_FSM_RETRIES; |
900 fsm->retries = EC_FSM_RETRIES; |
817 fsm->state = ec_fsm_coe_dict_entry_request; |
901 |
|
902 if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) { |
|
903 fsm->state = ec_fsm_coe_error; |
|
904 } |
818 } |
905 } |
819 |
906 |
820 /*****************************************************************************/ |
907 /*****************************************************************************/ |
821 |
908 |
822 /** |
909 /** |
823 CoE state: DICT ENTRY REQUEST. |
910 CoE state: DICT ENTRY REQUEST. |
824 \todo Timeout behavior |
911 \todo Timeout behavior |
825 */ |
912 */ |
826 |
913 |
827 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *fsm |
914 void ec_fsm_coe_dict_entry_request( |
828 /**< finite state machine */) |
915 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
829 { |
916 ec_datagram_t *datagram /**< Datagram to use. */ |
830 ec_mailbox_t *mbox = fsm->mbox; |
917 ) |
831 ec_datagram_t *datagram = mbox->datagram; |
918 { |
832 ec_slave_t *slave = fsm->slave; |
919 ec_slave_t *slave = fsm->slave; |
833 |
920 |
834 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
921 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
835 && fsm->retries--) { |
922 if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) { |
836 return; // FIXME: check for response first? |
923 fsm->state = ec_fsm_coe_error; |
837 } |
924 } |
838 |
925 return; |
839 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
926 } |
|
927 |
|
928 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
840 fsm->state = ec_fsm_coe_error; |
929 fsm->state = ec_fsm_coe_error; |
841 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO entry" |
930 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO entry" |
842 " request datagram: "); |
931 " request datagram: "); |
843 ec_datagram_print_state(datagram); |
932 ec_datagram_print_state(fsm->datagram); |
844 return; |
933 return; |
845 } |
934 } |
846 |
935 |
847 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
936 if (fsm->datagram->working_counter != 1) { |
848 fsm->state = ec_fsm_coe_error; |
937 fsm->state = ec_fsm_coe_error; |
849 EC_SLAVE_ERR(slave, "Reception of CoE SDO entry request failed: "); |
938 EC_SLAVE_ERR(slave, "Reception of CoE SDO entry request failed: "); |
850 ec_datagram_print_wc_error(datagram); |
939 ec_datagram_print_wc_error(fsm->datagram); |
851 return; |
940 return; |
852 } |
941 } |
853 |
942 |
854 fsm->jiffies_start = datagram->jiffies_sent; |
943 fsm->jiffies_start = fsm->datagram->jiffies_sent; |
855 |
944 |
856 ec_slave_mbox_prepare_check(slave, mbox); // can not fail |
945 ec_slave_mbox_prepare_check(slave, datagram); // can not fail |
857 fsm->retries = EC_FSM_RETRIES; |
946 fsm->retries = EC_FSM_RETRIES; |
858 fsm->state = ec_fsm_coe_dict_entry_check; |
947 fsm->state = ec_fsm_coe_dict_entry_check; |
859 } |
948 } |
860 |
949 |
861 /*****************************************************************************/ |
950 /*****************************************************************************/ |
862 |
951 |
863 /** |
952 /** |
864 CoE state: DICT ENTRY CHECK. |
953 CoE state: DICT ENTRY CHECK. |
865 */ |
954 */ |
866 |
955 |
867 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *fsm |
956 void ec_fsm_coe_dict_entry_check( |
868 /**< finite state machine */) |
957 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
869 { |
958 ec_datagram_t *datagram /**< Datagram to use. */ |
870 ec_mailbox_t *mbox = fsm->mbox; |
959 ) |
871 ec_datagram_t *datagram = mbox->datagram; |
960 { |
872 ec_slave_t *slave = fsm->slave; |
961 ec_slave_t *slave = fsm->slave; |
873 |
962 |
874 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
963 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
875 && fsm->retries--) { |
964 ec_slave_mbox_prepare_check(slave, datagram); // can not fail |
876 return; |
965 return; |
877 } |
966 } |
878 |
967 |
879 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
968 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
880 fsm->state = ec_fsm_coe_error; |
969 fsm->state = ec_fsm_coe_error; |
881 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
970 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
882 ec_datagram_print_state(datagram); |
971 ec_datagram_print_state(fsm->datagram); |
883 return; |
972 return; |
884 } |
973 } |
885 |
974 |
886 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
975 if (fsm->datagram->working_counter != 1) { |
887 fsm->state = ec_fsm_coe_error; |
976 fsm->state = ec_fsm_coe_error; |
888 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
977 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
889 " datagram failed: "); |
978 " datagram failed: "); |
890 ec_datagram_print_wc_error(datagram); |
979 ec_datagram_print_wc_error(fsm->datagram); |
891 return; |
980 return; |
892 } |
981 } |
893 |
982 |
894 if (!ec_slave_mbox_check(mbox)) { |
983 if (!ec_slave_mbox_check(fsm->datagram)) { |
895 unsigned long diff_ms = |
984 unsigned long diff_ms = |
896 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
985 (fsm->datagram->jiffies_received - fsm->jiffies_start) * |
|
986 1000 / HZ; |
897 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { |
987 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) { |
898 fsm->state = ec_fsm_coe_error; |
988 fsm->state = ec_fsm_coe_error; |
899 EC_SLAVE_ERR(slave, "Timeout while waiting for" |
989 EC_SLAVE_ERR(slave, "Timeout while waiting for" |
900 " SDO entry 0x%04x:%x description response.\n", |
990 " SDO entry 0x%04x:%x description response.\n", |
901 fsm->sdo->index, fsm->subindex); |
991 fsm->sdo->index, fsm->subindex); |
902 return; |
992 return; |
903 } |
993 } |
904 |
994 |
905 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
995 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
906 fsm->retries = EC_FSM_RETRIES; |
996 fsm->retries = EC_FSM_RETRIES; |
907 return; |
997 return; |
908 } |
998 } |
909 |
999 |
910 // Fetch response |
1000 // Fetch response |
911 ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail. |
1001 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
912 fsm->retries = EC_FSM_RETRIES; |
1002 fsm->retries = EC_FSM_RETRIES; |
913 fsm->state = ec_fsm_coe_dict_entry_response; |
1003 fsm->state = ec_fsm_coe_dict_entry_response; |
914 } |
1004 } |
915 |
1005 |
916 /*****************************************************************************/ |
1006 /*****************************************************************************/ |
1060 |
1152 |
1061 list_add_tail(&entry->list, &sdo->entries); |
1153 list_add_tail(&entry->list, &sdo->entries); |
1062 } |
1154 } |
1063 |
1155 |
1064 if (fsm->subindex < sdo->max_subindex) { |
1156 if (fsm->subindex < sdo->max_subindex) { |
|
1157 |
1065 fsm->subindex++; |
1158 fsm->subindex++; |
1066 |
1159 fsm->retries = EC_FSM_RETRIES; |
1067 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, 10); |
1160 |
1068 if (IS_ERR(data)) { |
1161 if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) { |
1069 fsm->state = ec_fsm_coe_error; |
1162 fsm->state = ec_fsm_coe_error; |
1070 return; |
1163 } |
1071 } |
1164 |
1072 |
|
1073 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
|
1074 EC_WRITE_U8 (data + 2, 0x05); // Get entry description request |
|
1075 EC_WRITE_U8 (data + 3, 0x00); |
|
1076 EC_WRITE_U16(data + 4, 0x0000); |
|
1077 EC_WRITE_U16(data + 6, sdo->index); // SDO index |
|
1078 EC_WRITE_U8 (data + 8, fsm->subindex); // SDO subindex |
|
1079 EC_WRITE_U8 (data + 9, 0x00); // value info (no values) |
|
1080 |
|
1081 fsm->retries = EC_FSM_RETRIES; |
|
1082 fsm->state = ec_fsm_coe_dict_entry_request; |
|
1083 return; |
1165 return; |
1084 } |
1166 } |
1085 |
1167 |
1086 // another SDO description to fetch? |
1168 // another SDO description to fetch? |
1087 if (fsm->sdo->list.next != &slave->sdo_dictionary) { |
1169 if (fsm->sdo->list.next != &slave->sdo_dictionary) { |
|
1170 |
1088 fsm->sdo = list_entry(fsm->sdo->list.next, ec_sdo_t, list); |
1171 fsm->sdo = list_entry(fsm->sdo->list.next, ec_sdo_t, list); |
1089 |
1172 fsm->retries = EC_FSM_RETRIES; |
1090 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, 8); |
1173 |
1091 if (IS_ERR(data)) { |
1174 if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) { |
1092 fsm->state = ec_fsm_coe_error; |
1175 fsm->state = ec_fsm_coe_error; |
1093 return; |
1176 } |
1094 } |
1177 |
1095 |
|
1096 EC_WRITE_U16(data, 0x8 << 12); // SDO information |
|
1097 EC_WRITE_U8 (data + 2, 0x03); // Get object description request |
|
1098 EC_WRITE_U8 (data + 3, 0x00); |
|
1099 EC_WRITE_U16(data + 4, 0x0000); |
|
1100 EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index |
|
1101 |
|
1102 fsm->retries = EC_FSM_RETRIES; |
|
1103 fsm->state = ec_fsm_coe_dict_desc_request; |
|
1104 return; |
1178 return; |
1105 } |
1179 } |
1106 |
1180 |
1107 fsm->state = ec_fsm_coe_end; |
1181 fsm->state = ec_fsm_coe_end; |
1108 } |
1182 } |
1109 |
1183 |
1110 /****************************************************************************** |
1184 /****************************************************************************** |
1111 * CoE state machine |
1185 * CoE state machine |
1112 *****************************************************************************/ |
1186 *****************************************************************************/ |
1113 |
1187 |
|
1188 /** Prepare a donwnload request. |
|
1189 * |
|
1190 * \return Zero on success, otherwise a negative error code. |
|
1191 */ |
|
1192 int ec_fsm_coe_prepare_down_start( |
|
1193 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
|
1194 ec_datagram_t *datagram /**< Datagram to use. */ |
|
1195 ) |
|
1196 { |
|
1197 u8 *data; |
|
1198 ec_slave_t *slave = fsm->slave; |
|
1199 ec_sdo_request_t *request = fsm->request; |
|
1200 uint8_t data_set_size; |
|
1201 |
|
1202 if (request->data_size <= 4) { // use expedited transfer type |
|
1203 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, |
|
1204 EC_COE_DOWN_REQ_HEADER_SIZE); |
|
1205 if (IS_ERR(data)) { |
|
1206 request->errno = PTR_ERR(data); |
|
1207 return PTR_ERR(data); |
|
1208 } |
|
1209 |
|
1210 fsm->remaining = 0; |
|
1211 |
|
1212 data_set_size = 4 - request->data_size; |
|
1213 |
|
1214 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
|
1215 EC_WRITE_U8 (data + 2, (0x3 // size specified, expedited |
|
1216 | data_set_size << 2 |
|
1217 | ((request->complete_access ? 1 : 0) << 4) |
|
1218 | 0x1 << 5)); // Download request |
|
1219 EC_WRITE_U16(data + 3, request->index); |
|
1220 EC_WRITE_U8 (data + 5, |
|
1221 request->complete_access ? 0x00 : request->subindex); |
|
1222 memcpy(data + 6, request->data, request->data_size); |
|
1223 memset(data + 6 + request->data_size, 0x00, 4 - request->data_size); |
|
1224 |
|
1225 if (slave->master->debug_level) { |
|
1226 EC_SLAVE_DBG(slave, 1, "Expedited download request:\n"); |
|
1227 ec_print_data(data, EC_COE_DOWN_REQ_HEADER_SIZE); |
|
1228 } |
|
1229 } |
|
1230 else { // request->data_size > 4, use normal transfer type |
|
1231 size_t data_size, |
|
1232 max_data_size = |
|
1233 slave->configured_rx_mailbox_size - EC_MBOX_HEADER_SIZE, |
|
1234 required_data_size = |
|
1235 EC_COE_DOWN_REQ_HEADER_SIZE + request->data_size; |
|
1236 |
|
1237 if (max_data_size < required_data_size) { |
|
1238 // segmenting needed |
|
1239 data_size = max_data_size; |
|
1240 } else { |
|
1241 data_size = required_data_size; |
|
1242 } |
|
1243 |
|
1244 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, |
|
1245 data_size); |
|
1246 if (IS_ERR(data)) { |
|
1247 request->errno = PTR_ERR(data); |
|
1248 return PTR_ERR(data); |
|
1249 } |
|
1250 |
|
1251 fsm->offset = 0; |
|
1252 fsm->remaining = request->data_size; |
|
1253 |
|
1254 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
|
1255 EC_WRITE_U8(data + 2, |
|
1256 0x1 // size indicator, normal |
|
1257 | ((request->complete_access ? 1 : 0) << 4) |
|
1258 | 0x1 << 5); // Download request |
|
1259 EC_WRITE_U16(data + 3, request->index); |
|
1260 EC_WRITE_U8 (data + 5, |
|
1261 request->complete_access ? 0x00 : request->subindex); |
|
1262 EC_WRITE_U32(data + 6, request->data_size); |
|
1263 |
|
1264 if (data_size > EC_COE_DOWN_REQ_HEADER_SIZE) { |
|
1265 size_t segment_size = data_size - EC_COE_DOWN_REQ_HEADER_SIZE; |
|
1266 memcpy(data + EC_COE_DOWN_REQ_HEADER_SIZE, |
|
1267 request->data, segment_size); |
|
1268 fsm->offset += segment_size; |
|
1269 fsm->remaining -= segment_size; |
|
1270 } |
|
1271 |
|
1272 if (slave->master->debug_level) { |
|
1273 EC_SLAVE_DBG(slave, 1, "Normal download request:\n"); |
|
1274 ec_print_data(data, data_size); |
|
1275 } |
|
1276 } |
|
1277 |
|
1278 fsm->state = ec_fsm_coe_down_request; |
|
1279 return 0; |
|
1280 } |
|
1281 |
|
1282 /****************************************************************************/ |
|
1283 |
1114 /** CoE state: DOWN START. |
1284 /** CoE state: DOWN START. |
1115 */ |
1285 */ |
1116 void ec_fsm_coe_down_start( |
1286 void ec_fsm_coe_down_start( |
1117 ec_fsm_coe_t *fsm /**< finite state machine */ |
1287 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
1118 ) |
1288 ec_datagram_t *datagram /**< Datagram to use. */ |
1119 { |
1289 ) |
1120 ec_mailbox_t *mbox = fsm->mbox; |
1290 { |
1121 ec_slave_t *slave = fsm->slave; |
1291 ec_slave_t *slave = fsm->slave; |
1122 ec_sdo_request_t *request = fsm->request; |
1292 ec_sdo_request_t *request = fsm->request; |
1123 uint8_t *data; |
|
1124 uint8_t data_set_size; |
|
1125 |
1293 |
1126 if (fsm->slave->master->debug_level) { |
1294 if (fsm->slave->master->debug_level) { |
1127 char subidxstr[10]; |
1295 char subidxstr[10]; |
1128 if (request->complete_access) { |
1296 if (request->complete_access) { |
1129 subidxstr[0] = 0x00; |
1297 subidxstr[0] = 0x00; |
1140 request->errno = EPROTONOSUPPORT; |
1308 request->errno = EPROTONOSUPPORT; |
1141 fsm->state = ec_fsm_coe_error; |
1309 fsm->state = ec_fsm_coe_error; |
1142 return; |
1310 return; |
1143 } |
1311 } |
1144 |
1312 |
1145 if (slave->configured_rx_mailbox_size < |
1313 if (slave->configured_rx_mailbox_size < |
1146 EC_MBOX_HEADER_SIZE + EC_COE_DOWN_REQ_HEADER_SIZE) { |
1314 EC_MBOX_HEADER_SIZE + EC_COE_DOWN_REQ_HEADER_SIZE) { |
1147 EC_SLAVE_ERR(slave, "Mailbox too small!\n"); |
1315 EC_SLAVE_ERR(slave, "Mailbox too small!\n"); |
1148 request->errno = EOVERFLOW; |
1316 request->errno = EOVERFLOW; |
1149 fsm->state = ec_fsm_coe_error; |
1317 fsm->state = ec_fsm_coe_error; |
1150 return; |
1318 return; |
1151 } |
1319 } |
1152 |
1320 |
1153 if (request->data_size <= 4) { // use expedited transfer type |
|
1154 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, |
|
1155 EC_COE_DOWN_REQ_HEADER_SIZE); |
|
1156 if (IS_ERR(data)) { |
|
1157 request->errno = PTR_ERR(data); |
|
1158 fsm->state = ec_fsm_coe_error; |
|
1159 return; |
|
1160 } |
|
1161 |
|
1162 fsm->remaining = 0; |
|
1163 |
|
1164 data_set_size = 4 - request->data_size; |
|
1165 |
|
1166 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
|
1167 EC_WRITE_U8 (data + 2, (0x3 // size specified, expedited |
|
1168 | data_set_size << 2 |
|
1169 | ((request->complete_access ? 1 : 0) << 4) |
|
1170 | 0x1 << 5)); // Download request |
|
1171 EC_WRITE_U16(data + 3, request->index); |
|
1172 EC_WRITE_U8 (data + 5, |
|
1173 request->complete_access ? 0x00 : request->subindex); |
|
1174 memcpy(data + 6, request->data, request->data_size); |
|
1175 memset(data + 6 + request->data_size, 0x00, 4 - request->data_size); |
|
1176 |
|
1177 if (slave->master->debug_level) { |
|
1178 EC_SLAVE_DBG(slave, 1, "Expedited download request:\n"); |
|
1179 ec_print_data(data, EC_COE_DOWN_REQ_HEADER_SIZE); |
|
1180 } |
|
1181 } |
|
1182 else { // request->data_size > 4, use normal transfer type |
|
1183 size_t data_size, |
|
1184 max_data_size = |
|
1185 slave->configured_rx_mailbox_size - EC_MBOX_HEADER_SIZE, |
|
1186 required_data_size = |
|
1187 EC_COE_DOWN_REQ_HEADER_SIZE + request->data_size; |
|
1188 |
|
1189 if (max_data_size < required_data_size) { |
|
1190 // segmenting needed |
|
1191 data_size = max_data_size; |
|
1192 } else { |
|
1193 data_size = required_data_size; |
|
1194 } |
|
1195 |
|
1196 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, |
|
1197 data_size); |
|
1198 if (IS_ERR(data)) { |
|
1199 request->errno = PTR_ERR(data); |
|
1200 fsm->state = ec_fsm_coe_error; |
|
1201 return; |
|
1202 } |
|
1203 |
|
1204 fsm->offset = 0; |
|
1205 fsm->remaining = request->data_size; |
|
1206 |
|
1207 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
|
1208 EC_WRITE_U8(data + 2, |
|
1209 0x1 // size indicator, normal |
|
1210 | ((request->complete_access ? 1 : 0) << 4) |
|
1211 | 0x1 << 5); // Download request |
|
1212 EC_WRITE_U16(data + 3, request->index); |
|
1213 EC_WRITE_U8 (data + 5, |
|
1214 request->complete_access ? 0x00 : request->subindex); |
|
1215 EC_WRITE_U32(data + 6, request->data_size); |
|
1216 |
|
1217 if (data_size > EC_COE_DOWN_REQ_HEADER_SIZE) { |
|
1218 size_t segment_size = data_size - EC_COE_DOWN_REQ_HEADER_SIZE; |
|
1219 memcpy(data + EC_COE_DOWN_REQ_HEADER_SIZE, |
|
1220 request->data, segment_size); |
|
1221 fsm->offset += segment_size; |
|
1222 fsm->remaining -= segment_size; |
|
1223 } |
|
1224 |
|
1225 if (slave->master->debug_level) { |
|
1226 EC_SLAVE_DBG(slave, 1, "Normal download request:\n"); |
|
1227 ec_print_data(data, data_size); |
|
1228 } |
|
1229 } |
|
1230 |
1321 |
1231 fsm->request->jiffies_sent = jiffies; |
1322 fsm->request->jiffies_sent = jiffies; |
1232 fsm->retries = EC_FSM_RETRIES; |
1323 fsm->retries = EC_FSM_RETRIES; |
1233 fsm->state = ec_fsm_coe_down_request; |
1324 |
|
1325 if (ec_fsm_coe_prepare_down_start(fsm, datagram)) { |
|
1326 fsm->state = ec_fsm_coe_error; |
|
1327 } |
1234 } |
1328 } |
1235 |
1329 |
1236 /*****************************************************************************/ |
1330 /*****************************************************************************/ |
1237 |
1331 |
1238 /** |
1332 /** |
1239 CoE state: DOWN REQUEST. |
1333 CoE state: DOWN REQUEST. |
1240 \todo Timeout behavior |
1334 \todo Timeout behavior |
1241 */ |
1335 */ |
1242 |
1336 |
1243 void ec_fsm_coe_down_request(ec_fsm_coe_t *fsm /**< finite state machine */) |
1337 void ec_fsm_coe_down_request( |
1244 { |
1338 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
1245 ec_mailbox_t *mbox = fsm->mbox; |
1339 ec_datagram_t *datagram /**< Datagram to use. */ |
1246 ec_datagram_t *datagram = mbox->datagram; |
1340 ) |
|
1341 { |
1247 ec_slave_t *slave = fsm->slave; |
1342 ec_slave_t *slave = fsm->slave; |
1248 unsigned long diff_ms; |
1343 unsigned long diff_ms; |
1249 |
1344 |
1250 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
1345 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
1251 && fsm->retries--) { |
1346 if (ec_fsm_coe_prepare_down_start(fsm, datagram)) { |
1252 return; // FIXME: check for response first? |
1347 fsm->state = ec_fsm_coe_error; |
1253 } |
1348 } |
1254 |
1349 return; |
1255 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
1350 } |
|
1351 |
|
1352 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
1256 fsm->request->errno = EIO; |
1353 fsm->request->errno = EIO; |
1257 fsm->state = ec_fsm_coe_error; |
1354 fsm->state = ec_fsm_coe_error; |
1258 EC_SLAVE_ERR(slave, "Failed to receive CoE download" |
1355 EC_SLAVE_ERR(slave, "Failed to receive CoE download" |
1259 " request datagram: "); |
1356 " request datagram: "); |
1260 ec_datagram_print_state(datagram); |
1357 ec_datagram_print_state(fsm->datagram); |
1261 return; |
1358 return; |
1262 } |
1359 } |
1263 |
1360 |
1264 diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ; |
1361 diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ; |
1265 |
1362 |
1266 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
1363 if (fsm->datagram->working_counter != 1) { |
1267 if (ec_mbox_is_datagram_wc(mbox, 0)) { |
1364 if (!fsm->datagram->working_counter) { |
1268 if (diff_ms < fsm->request->response_timeout) { |
1365 if (diff_ms < fsm->request->response_timeout) { |
1269 #if DEBUG_RETRIES |
1366 #if DEBUG_RETRIES |
1270 EC_SLAVE_DBG(slave, 1, "Slave did not respond to SDO" |
1367 EC_SLAVE_DBG(slave, 1, "Slave did not respond to SDO" |
1271 " download request. Retrying after %lu ms...\n", |
1368 " download request. Retrying after %lu ms...\n", |
1272 diff_ms); |
1369 diff_ms); |
1273 #endif |
1370 #endif |
1274 // no response; send request datagram again |
1371 // no response; send request datagram again |
|
1372 if (ec_fsm_coe_prepare_down_start(fsm, datagram)) { |
|
1373 fsm->state = ec_fsm_coe_error; |
|
1374 } |
1275 return; |
1375 return; |
1276 } |
1376 } |
1277 } |
1377 } |
1278 fsm->request->errno = EIO; |
1378 fsm->request->errno = EIO; |
1279 fsm->state = ec_fsm_coe_error; |
1379 fsm->state = ec_fsm_coe_error; |
1280 EC_SLAVE_ERR(slave, "Reception of CoE download request" |
1380 EC_SLAVE_ERR(slave, "Reception of CoE download request" |
1281 " for SDO 0x%04x:%x failed with timeout after %lu ms: ", |
1381 " for SDO 0x%04x:%x failed with timeout after %lu ms: ", |
1282 fsm->request->index, fsm->request->subindex, diff_ms); |
1382 fsm->request->index, fsm->request->subindex, diff_ms); |
1283 ec_datagram_print_wc_error(datagram); |
1383 ec_datagram_print_wc_error(fsm->datagram); |
1284 return; |
1384 return; |
1285 } |
1385 } |
1286 |
1386 |
1287 #if DEBUG_LONG |
1387 #if DEBUG_LONG |
1288 if (diff_ms > 200) { |
1388 if (diff_ms > 200) { |
1289 EC_SLAVE_WARN(slave, "SDO 0x%04x:%x download took %lu ms.\n", |
1389 EC_SLAVE_WARN(slave, "SDO 0x%04x:%x download took %lu ms.\n", |
1290 fsm->request->index, fsm->request->subindex, diff_ms); |
1390 fsm->request->index, fsm->request->subindex, diff_ms); |
1291 } |
1391 } |
1292 #endif |
1392 #endif |
1293 |
1393 |
1294 fsm->jiffies_start = datagram->jiffies_sent; |
1394 fsm->jiffies_start = fsm->datagram->jiffies_sent; |
1295 |
1395 |
1296 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
1396 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
1297 fsm->retries = EC_FSM_RETRIES; |
1397 fsm->retries = EC_FSM_RETRIES; |
1298 fsm->state = ec_fsm_coe_down_check; |
1398 fsm->state = ec_fsm_coe_down_check; |
1299 } |
1399 } |
1300 |
1400 |
1301 /*****************************************************************************/ |
1401 /*****************************************************************************/ |
1302 |
1402 |
1303 /** CoE state: DOWN CHECK. |
1403 /** CoE state: DOWN CHECK. |
1304 */ |
1404 */ |
1305 void ec_fsm_coe_down_check(ec_fsm_coe_t *fsm /**< finite state machine */) |
1405 void ec_fsm_coe_down_check( |
1306 { |
1406 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
1307 ec_mailbox_t *mbox = fsm->mbox; |
1407 ec_datagram_t *datagram /**< Datagram to use. */ |
1308 ec_datagram_t *datagram = mbox->datagram; |
1408 ) |
1309 ec_slave_t *slave = fsm->slave; |
1409 { |
1310 |
1410 ec_slave_t *slave = fsm->slave; |
1311 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
1411 |
1312 && fsm->retries--) { |
1412 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
1313 return; |
1413 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
1314 } |
1414 return; |
1315 |
1415 } |
1316 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
1416 |
|
1417 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
1317 fsm->request->errno = EIO; |
1418 fsm->request->errno = EIO; |
1318 fsm->state = ec_fsm_coe_error; |
1419 fsm->state = ec_fsm_coe_error; |
1319 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check" |
1420 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check" |
1320 " datagram: "); |
1421 " datagram: "); |
1321 ec_datagram_print_state(datagram); |
1422 ec_datagram_print_state(fsm->datagram); |
1322 return; |
1423 return; |
1323 } |
1424 } |
1324 |
1425 |
1325 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
1426 if (fsm->datagram->working_counter != 1) { |
1326 fsm->request->errno = EIO; |
1427 fsm->request->errno = EIO; |
1327 fsm->state = ec_fsm_coe_error; |
1428 fsm->state = ec_fsm_coe_error; |
1328 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
1429 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
1329 " datagram failed: "); |
1430 " datagram failed: "); |
1330 ec_datagram_print_wc_error(datagram); |
1431 ec_datagram_print_wc_error(fsm->datagram); |
1331 return; |
1432 return; |
1332 } |
1433 } |
1333 |
1434 |
1334 if (!ec_slave_mbox_check(mbox)) { |
1435 if (!ec_slave_mbox_check(fsm->datagram)) { |
1335 unsigned long diff_ms = |
1436 unsigned long diff_ms = |
1336 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
1437 (fsm->datagram->jiffies_received - fsm->jiffies_start) * |
|
1438 1000 / HZ; |
1337 if (diff_ms >= fsm->request->response_timeout) { |
1439 if (diff_ms >= fsm->request->response_timeout) { |
1338 fsm->request->errno = EIO; |
1440 fsm->request->errno = EIO; |
1339 fsm->state = ec_fsm_coe_error; |
1441 fsm->state = ec_fsm_coe_error; |
1340 EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting" |
1442 EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting" |
1341 " for SDO 0x%04x:%x download response.\n", diff_ms, |
1443 " for SDO 0x%04x:%x download response.\n", diff_ms, |
1342 fsm->request->index, fsm->request->subindex); |
1444 fsm->request->index, fsm->request->subindex); |
1343 return; |
1445 return; |
1344 } |
1446 } |
1345 |
1447 |
1346 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
1448 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
1347 fsm->retries = EC_FSM_RETRIES; |
1449 fsm->retries = EC_FSM_RETRIES; |
1348 return; |
1450 return; |
1349 } |
1451 } |
1350 |
1452 |
1351 // Fetch response |
1453 // Fetch response |
1352 ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail. |
1454 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
1353 fsm->retries = EC_FSM_RETRIES; |
1455 fsm->retries = EC_FSM_RETRIES; |
1354 fsm->state = ec_fsm_coe_down_response; |
1456 fsm->state = ec_fsm_coe_down_response; |
1355 } |
1457 } |
1356 |
1458 |
1357 /*****************************************************************************/ |
1459 /*****************************************************************************/ |
1358 |
1460 |
1359 /** Prepare a download segment request. |
1461 /** Prepare a download segment request. |
1360 */ |
1462 */ |
1361 void ec_fsm_coe_down_prepare_segment_request( |
1463 void ec_fsm_coe_down_prepare_segment_request( |
1362 ec_fsm_coe_t *fsm /**< finite state machine */ |
1464 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
1363 ) |
1465 ec_datagram_t *datagram /**< Datagram to use. */ |
1364 { |
1466 ) |
1365 ec_mailbox_t *mbox = fsm->mbox; |
1467 { |
1366 ec_slave_t *slave = fsm->slave; |
1468 ec_slave_t *slave = fsm->slave; |
1367 ec_sdo_request_t *request = fsm->request; |
1469 ec_sdo_request_t *request = fsm->request; |
1368 size_t max_segment_size = |
1470 size_t max_segment_size = |
1369 slave->configured_rx_mailbox_size |
1471 slave->configured_rx_mailbox_size |
1370 - EC_MBOX_HEADER_SIZE |
1472 - EC_MBOX_HEADER_SIZE |
1371 - EC_COE_DOWN_SEG_REQ_HEADER_SIZE; |
1473 - EC_COE_DOWN_SEG_REQ_HEADER_SIZE; |
1372 size_t segment_size, data_size; |
1474 size_t data_size; |
1373 uint8_t last_segment, seg_data_size, *data; |
1475 uint8_t last_segment, seg_data_size, *data; |
1374 |
1476 |
1375 if (fsm->remaining > max_segment_size) { |
1477 if (fsm->remaining > max_segment_size) { |
1376 segment_size = max_segment_size; |
1478 fsm->segment_size = max_segment_size; |
1377 last_segment = 0; |
1479 last_segment = 0; |
1378 } else { |
1480 } else { |
1379 segment_size = fsm->remaining; |
1481 fsm->segment_size = fsm->remaining; |
1380 last_segment = 1; |
1482 last_segment = 1; |
1381 } |
1483 } |
1382 |
1484 |
1383 if (segment_size > EC_COE_DOWN_SEG_MIN_DATA_SIZE) { |
1485 if (fsm->segment_size > EC_COE_DOWN_SEG_MIN_DATA_SIZE) { |
1384 seg_data_size = 0x00; |
1486 seg_data_size = 0x00; |
1385 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE + segment_size; |
1487 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE + fsm->segment_size; |
1386 } else { |
1488 } else { |
1387 seg_data_size = EC_COE_DOWN_SEG_MIN_DATA_SIZE - segment_size; |
1489 seg_data_size = EC_COE_DOWN_SEG_MIN_DATA_SIZE - fsm->segment_size; |
1388 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE |
1490 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE |
1389 + EC_COE_DOWN_SEG_MIN_DATA_SIZE; |
1491 + EC_COE_DOWN_SEG_MIN_DATA_SIZE; |
1390 } |
1492 } |
1391 |
1493 |
1392 data = ec_slave_mbox_prepare_send(slave, mbox, 0x03, |
1494 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, |
1393 data_size); |
1495 data_size); |
1394 if (IS_ERR(data)) { |
1496 if (IS_ERR(data)) { |
1395 request->errno = PTR_ERR(data); |
1497 request->errno = PTR_ERR(data); |
1396 fsm->state = ec_fsm_coe_error; |
1498 fsm->state = ec_fsm_coe_error; |
1397 return; |
1499 return; |
1398 } |
1500 } |
1399 |
1501 |
1400 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
1502 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
1401 EC_WRITE_U8(data + 2, (last_segment ? 1 : 0) |
1503 EC_WRITE_U8(data + 2, (last_segment ? 1 : 0) |
1402 | (seg_data_size << 1) |
1504 | (seg_data_size << 1) |
1403 | (fsm->toggle << 4) |
1505 | (fsm->toggle << 4) |
1404 | (0x00 << 5)); // Download segment request |
1506 | (0x00 << 5)); // Download segment request |
1405 memcpy(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE, |
1507 memcpy(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE, |
1406 request->data + fsm->offset, segment_size); |
1508 request->data + fsm->offset, fsm->segment_size); |
1407 if (segment_size < EC_COE_DOWN_SEG_MIN_DATA_SIZE) { |
1509 if (fsm->segment_size < EC_COE_DOWN_SEG_MIN_DATA_SIZE) { |
1408 memset(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE + segment_size, 0x00, |
1510 memset(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE + fsm->segment_size, |
1409 EC_COE_DOWN_SEG_MIN_DATA_SIZE - segment_size); |
1511 0x00, EC_COE_DOWN_SEG_MIN_DATA_SIZE - fsm->segment_size); |
1410 } |
1512 } |
1411 |
|
1412 fsm->offset += segment_size; |
|
1413 fsm->remaining -= segment_size; |
|
1414 |
1513 |
1415 if (slave->master->debug_level) { |
1514 if (slave->master->debug_level) { |
1416 EC_SLAVE_DBG(slave, 1, "Download segment request:\n"); |
1515 EC_SLAVE_DBG(slave, 1, "Download segment request:\n"); |
1417 ec_print_data(data, data_size); |
1516 ec_print_data(data, data_size); |
1418 } |
1517 } |
1545 |
1645 |
1546 /** |
1646 /** |
1547 CoE state: DOWN SEG CHECK. |
1647 CoE state: DOWN SEG CHECK. |
1548 */ |
1648 */ |
1549 |
1649 |
1550 void ec_fsm_coe_down_seg_check(ec_fsm_coe_t *fsm /**< finite state machine */) |
1650 void ec_fsm_coe_down_seg_check( |
1551 { |
1651 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
1552 ec_mailbox_t *mbox = fsm->mbox; |
1652 ec_datagram_t *datagram /**< Datagram to use. */ |
1553 ec_datagram_t *datagram = mbox->datagram; |
1653 ) |
1554 ec_slave_t *slave = fsm->slave; |
1654 { |
1555 |
1655 ec_slave_t *slave = fsm->slave; |
1556 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
1656 |
1557 && fsm->retries--) { |
1657 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
1558 return; |
1658 return; |
1559 } |
1659 |
1560 |
1660 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
1561 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
|
1562 fsm->request->errno = EIO; |
1661 fsm->request->errno = EIO; |
1563 fsm->state = ec_fsm_coe_error; |
1662 fsm->state = ec_fsm_coe_error; |
1564 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
1663 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
1565 ec_datagram_print_state(datagram); |
1664 ec_datagram_print_state(fsm->datagram); |
1566 return; |
1665 return; |
1567 } |
1666 } |
1568 |
1667 |
1569 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
1668 if (fsm->datagram->working_counter != 1) { |
1570 fsm->request->errno = EIO; |
1669 fsm->request->errno = EIO; |
1571 fsm->state = ec_fsm_coe_error; |
1670 fsm->state = ec_fsm_coe_error; |
1572 EC_SLAVE_ERR(slave, "Reception of CoE mailbox segment check" |
1671 EC_SLAVE_ERR(slave, "Reception of CoE mailbox segment check" |
1573 " datagram failed: "); |
1672 " datagram failed: "); |
1574 ec_datagram_print_wc_error(datagram); |
1673 ec_datagram_print_wc_error(fsm->datagram); |
1575 return; |
1674 return; |
1576 } |
1675 } |
1577 |
1676 |
1578 if (!ec_slave_mbox_check(mbox)) { |
1677 if (!ec_slave_mbox_check(fsm->datagram)) { |
1579 unsigned long diff_ms = |
1678 unsigned long diff_ms = |
1580 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
1679 (fsm->datagram->jiffies_received - fsm->jiffies_start) * |
|
1680 1000 / HZ; |
1581 if (diff_ms >= fsm->request->response_timeout) { |
1681 if (diff_ms >= fsm->request->response_timeout) { |
1582 fsm->request->errno = EIO; |
1682 fsm->request->errno = EIO; |
1583 fsm->state = ec_fsm_coe_error; |
1683 fsm->state = ec_fsm_coe_error; |
1584 EC_SLAVE_ERR(slave, "Timeout while waiting for SDO download" |
1684 EC_SLAVE_ERR(slave, "Timeout while waiting for SDO download" |
1585 " segment response.\n"); |
1685 " segment response.\n"); |
1586 return; |
1686 return; |
1587 } |
1687 } |
1588 |
1688 |
1589 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
1689 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
1590 fsm->retries = EC_FSM_RETRIES; |
1690 fsm->retries = EC_FSM_RETRIES; |
1591 return; |
1691 return; |
1592 } |
1692 } |
1593 |
1693 |
1594 // Fetch response |
1694 // Fetch response |
1595 ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail. |
1695 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
1596 fsm->retries = EC_FSM_RETRIES; |
1696 fsm->retries = EC_FSM_RETRIES; |
1597 fsm->state = ec_fsm_coe_down_seg_response; |
1697 fsm->state = ec_fsm_coe_down_seg_response; |
1598 } |
1698 } |
1599 |
1699 |
1600 /*****************************************************************************/ |
1700 /*****************************************************************************/ |
1767 if (master->debug_level) { |
1859 if (master->debug_level) { |
1768 EC_SLAVE_DBG(slave, 1, "Upload request:\n"); |
1860 EC_SLAVE_DBG(slave, 1, "Upload request:\n"); |
1769 ec_print_data(data, 10); |
1861 ec_print_data(data, 10); |
1770 } |
1862 } |
1771 |
1863 |
|
1864 fsm->state = ec_fsm_coe_up_request; |
|
1865 return 0; |
|
1866 } |
|
1867 |
|
1868 /*****************************************************************************/ |
|
1869 |
|
1870 /** |
|
1871 CoE state: UP START. |
|
1872 */ |
|
1873 |
|
1874 void ec_fsm_coe_up_start( |
|
1875 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
|
1876 ec_datagram_t *datagram /**< Datagram to use. */ |
|
1877 ) |
|
1878 { |
|
1879 ec_slave_t *slave = fsm->slave; |
|
1880 ec_sdo_request_t *request = fsm->request; |
|
1881 |
|
1882 EC_SLAVE_DBG(slave, 1, "Uploading SDO 0x%04X:%02X.\n", |
|
1883 request->index, request->subindex); |
|
1884 |
|
1885 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) { |
|
1886 EC_SLAVE_ERR(slave, "Slave does not support CoE!\n"); |
|
1887 request->errno = EPROTONOSUPPORT; |
|
1888 fsm->state = ec_fsm_coe_error; |
|
1889 return; |
|
1890 } |
|
1891 |
|
1892 fsm->retries = EC_FSM_RETRIES; |
1772 fsm->request->jiffies_sent = jiffies; |
1893 fsm->request->jiffies_sent = jiffies; |
1773 fsm->retries = EC_FSM_RETRIES; |
1894 |
1774 fsm->state = ec_fsm_coe_up_request; |
1895 if (ec_fsm_coe_prepare_up(fsm, datagram)) { |
1775 } |
1896 fsm->state = ec_fsm_coe_error; |
1776 |
1897 } |
1777 /*****************************************************************************/ |
1898 } |
1778 |
1899 |
|
1900 /*****************************************************************************/ |
1779 /** |
1901 /** |
1780 CoE state: UP REQUEST. |
1902 CoE state: UP REQUEST. |
1781 \todo Timeout behavior |
1903 \todo Timeout behavior |
1782 */ |
1904 */ |
1783 |
1905 |
1784 void ec_fsm_coe_up_request(ec_fsm_coe_t *fsm /**< finite state machine */) |
1906 void ec_fsm_coe_up_request( |
1785 { |
1907 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
1786 ec_mailbox_t *mbox = fsm->mbox; |
1908 ec_datagram_t *datagram /**< Datagram to use. */ |
1787 ec_datagram_t *datagram = mbox->datagram; |
1909 ) |
|
1910 { |
1788 ec_slave_t *slave = fsm->slave; |
1911 ec_slave_t *slave = fsm->slave; |
1789 unsigned long diff_ms; |
1912 unsigned long diff_ms; |
1790 |
1913 |
1791 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
1914 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
1792 && fsm->retries--) { |
1915 if (ec_fsm_coe_prepare_up(fsm, datagram)) { |
1793 return; // FIXME: check for response first? |
1916 fsm->state = ec_fsm_coe_error; |
1794 } |
1917 } |
1795 |
1918 return; |
1796 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
1919 } |
|
1920 |
|
1921 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
1797 fsm->request->errno = EIO; |
1922 fsm->request->errno = EIO; |
1798 fsm->state = ec_fsm_coe_error; |
1923 fsm->state = ec_fsm_coe_error; |
1799 EC_SLAVE_ERR(slave, "Failed to receive CoE upload request: "); |
1924 EC_SLAVE_ERR(slave, "Failed to receive CoE upload request: "); |
1800 ec_datagram_print_state(datagram); |
1925 ec_datagram_print_state(fsm->datagram); |
1801 return; |
1926 return; |
1802 } |
1927 } |
1803 |
1928 |
1804 diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ; |
1929 diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ; |
1805 |
1930 |
1806 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
1931 if (fsm->datagram->working_counter != 1) { |
1807 if (ec_mbox_is_datagram_wc(mbox, 0)) { |
1932 if (!fsm->datagram->working_counter) { |
1808 if (diff_ms < fsm->request->response_timeout) { |
1933 if (diff_ms < fsm->request->response_timeout) { |
1809 #if DEBUG_RETRIES |
1934 #if DEBUG_RETRIES |
1810 EC_SLAVE_DBG(slave, 1, "Slave did not respond to" |
1935 EC_SLAVE_DBG(slave, 1, "Slave did not respond to" |
1811 " SDO upload request. Retrying after %lu ms...\n", |
1936 " SDO upload request. Retrying after %lu ms...\n", |
1812 diff_ms); |
1937 diff_ms); |
1813 #endif |
1938 #endif |
1814 // no response; send request datagram again |
1939 // no response; send request datagram again |
|
1940 if (ec_fsm_coe_prepare_up(fsm, datagram)) { |
|
1941 fsm->state = ec_fsm_coe_error; |
|
1942 } |
1815 return; |
1943 return; |
1816 } |
1944 } |
1817 } |
1945 } |
1818 fsm->request->errno = EIO; |
1946 fsm->request->errno = EIO; |
1819 fsm->state = ec_fsm_coe_error; |
1947 fsm->state = ec_fsm_coe_error; |
1820 EC_SLAVE_ERR(slave, "Reception of CoE upload request for" |
1948 EC_SLAVE_ERR(slave, "Reception of CoE upload request for" |
1821 " SDO 0x%04x:%x failed with timeout after %lu ms: ", |
1949 " SDO 0x%04x:%x failed with timeout after %lu ms: ", |
1822 fsm->request->index, fsm->request->subindex, diff_ms); |
1950 fsm->request->index, fsm->request->subindex, diff_ms); |
1823 ec_datagram_print_wc_error(datagram); |
1951 ec_datagram_print_wc_error(fsm->datagram); |
1824 return; |
1952 return; |
1825 } |
1953 } |
1826 |
1954 |
1827 #if DEBUG_LONG |
1955 #if DEBUG_LONG |
1828 if (diff_ms > 200) { |
1956 if (diff_ms > 200) { |
1829 EC_SLAVE_WARN(slave, "SDO 0x%04x:%x upload took %lu ms.\n", |
1957 EC_SLAVE_WARN(slave, "SDO 0x%04x:%x upload took %lu ms.\n", |
1830 fsm->request->index, fsm->request->subindex, diff_ms); |
1958 fsm->request->index, fsm->request->subindex, diff_ms); |
1831 } |
1959 } |
1832 #endif |
1960 #endif |
1833 |
1961 |
1834 fsm->jiffies_start = datagram->jiffies_sent; |
1962 fsm->jiffies_start = fsm->datagram->jiffies_sent; |
1835 |
1963 |
1836 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
1964 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
1837 fsm->retries = EC_FSM_RETRIES; |
1965 fsm->retries = EC_FSM_RETRIES; |
1838 fsm->state = ec_fsm_coe_up_check; |
1966 fsm->state = ec_fsm_coe_up_check; |
1839 } |
1967 } |
1840 |
1968 |
1841 /*****************************************************************************/ |
1969 /*****************************************************************************/ |
1842 |
1970 |
1843 /** |
1971 /** |
1844 CoE state: UP CHECK. |
1972 CoE state: UP CHECK. |
1845 */ |
1973 */ |
1846 |
1974 |
1847 void ec_fsm_coe_up_check(ec_fsm_coe_t *fsm /**< finite state machine */) |
1975 void ec_fsm_coe_up_check( |
1848 { |
1976 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
1849 ec_mailbox_t *mbox = fsm->mbox; |
1977 ec_datagram_t *datagram /**< Datagram to use. */ |
1850 ec_datagram_t *datagram = mbox->datagram; |
1978 ) |
1851 ec_slave_t *slave = fsm->slave; |
1979 { |
1852 |
1980 ec_slave_t *slave = fsm->slave; |
1853 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
1981 |
1854 && fsm->retries--) { |
1982 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
1855 return; |
1983 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
1856 } |
1984 return; |
1857 |
1985 } |
1858 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
1986 |
|
1987 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
1859 fsm->request->errno = EIO; |
1988 fsm->request->errno = EIO; |
1860 fsm->state = ec_fsm_coe_error; |
1989 fsm->state = ec_fsm_coe_error; |
1861 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
1990 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: "); |
1862 ec_datagram_print_state(datagram); |
1991 ec_datagram_print_state(fsm->datagram); |
1863 return; |
1992 return; |
1864 } |
1993 } |
1865 |
1994 |
1866 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
1995 if (fsm->datagram->working_counter != 1) { |
1867 fsm->request->errno = EIO; |
1996 fsm->request->errno = EIO; |
1868 fsm->state = ec_fsm_coe_error; |
1997 fsm->state = ec_fsm_coe_error; |
1869 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
1998 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check" |
1870 " datagram failed: "); |
1999 " datagram failed: "); |
1871 ec_datagram_print_wc_error(datagram); |
2000 ec_datagram_print_wc_error(fsm->datagram); |
1872 return; |
2001 return; |
1873 } |
2002 } |
1874 |
2003 |
1875 if (!ec_slave_mbox_check(mbox)) { |
2004 if (!ec_slave_mbox_check(fsm->datagram)) { |
1876 unsigned long diff_ms = |
2005 unsigned long diff_ms = |
1877 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
2006 (fsm->datagram->jiffies_received - fsm->jiffies_start) * |
|
2007 1000 / HZ; |
1878 if (diff_ms >= fsm->request->response_timeout) { |
2008 if (diff_ms >= fsm->request->response_timeout) { |
1879 fsm->request->errno = EIO; |
2009 fsm->request->errno = EIO; |
1880 fsm->state = ec_fsm_coe_error; |
2010 fsm->state = ec_fsm_coe_error; |
1881 EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting for" |
2011 EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting for" |
1882 " SDO 0x%04x:%x upload response.\n", diff_ms, |
2012 " SDO 0x%04x:%x upload response.\n", diff_ms, |
1883 fsm->request->index, fsm->request->subindex); |
2013 fsm->request->index, fsm->request->subindex); |
1884 return; |
2014 return; |
1885 } |
2015 } |
1886 |
2016 |
1887 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
2017 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
1888 fsm->retries = EC_FSM_RETRIES; |
2018 fsm->retries = EC_FSM_RETRIES; |
1889 return; |
2019 return; |
1890 } |
2020 } |
1891 |
2021 |
1892 // Fetch response |
2022 // Fetch response |
1893 ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail. |
2023 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
1894 fsm->retries = EC_FSM_RETRIES; |
2024 fsm->retries = EC_FSM_RETRIES; |
1895 fsm->state = ec_fsm_coe_up_response; |
2025 fsm->state = ec_fsm_coe_up_response; |
1896 } |
2026 } |
1897 |
2027 |
1898 /*****************************************************************************/ |
2028 /*****************************************************************************/ |
1899 |
2029 |
1900 /** Prepare an SDO upload segment request. |
2030 /** Prepare an SDO upload segment request. |
1901 */ |
2031 */ |
1902 void ec_fsm_coe_up_prepare_segment_request( |
2032 void ec_fsm_coe_up_prepare_segment_request( |
1903 ec_fsm_coe_t *fsm /**< Finite state machine */ |
2033 ec_fsm_coe_t *fsm, /**< Finite state machine */ |
|
2034 ec_datagram_t *datagram /**< Datagram to use. */ |
1904 ) |
2035 ) |
1905 { |
2036 { |
1906 uint8_t *data = |
2037 uint8_t *data = |
1907 ec_slave_mbox_prepare_send(fsm->slave, fsm->mbox, 0x03, 10); |
2038 ec_slave_mbox_prepare_send(fsm->slave, datagram, 0x03, 10); |
1908 if (IS_ERR(data)) { |
2039 if (IS_ERR(data)) { |
1909 fsm->request->errno = PTR_ERR(data); |
2040 fsm->request->errno = PTR_ERR(data); |
1910 fsm->state = ec_fsm_coe_error; |
2041 fsm->state = ec_fsm_coe_error; |
1911 return; |
2042 return; |
1912 } |
2043 } |
2129 /** |
2261 /** |
2130 CoE state: UP REQUEST. |
2262 CoE state: UP REQUEST. |
2131 \todo Timeout behavior |
2263 \todo Timeout behavior |
2132 */ |
2264 */ |
2133 |
2265 |
2134 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *fsm /**< finite state machine */) |
2266 void ec_fsm_coe_up_seg_request( |
2135 { |
2267 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
2136 ec_mailbox_t *mbox = fsm->mbox; |
2268 ec_datagram_t *datagram /**< Datagram to use. */ |
2137 ec_datagram_t *datagram = mbox->datagram; |
2269 ) |
2138 ec_slave_t *slave = fsm->slave; |
2270 { |
2139 |
2271 ec_slave_t *slave = fsm->slave; |
2140 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
2272 |
2141 && fsm->retries--) { |
2273 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
2142 return; // FIXME: check for response first? |
2274 ec_fsm_coe_up_prepare_segment_request(fsm, datagram); |
2143 } |
2275 return; |
2144 |
2276 } |
2145 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
2277 |
|
2278 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
2146 fsm->request->errno = EIO; |
2279 fsm->request->errno = EIO; |
2147 fsm->state = ec_fsm_coe_error; |
2280 fsm->state = ec_fsm_coe_error; |
2148 EC_SLAVE_ERR(slave, "Failed to receive CoE upload segment" |
2281 EC_SLAVE_ERR(slave, "Failed to receive CoE upload segment" |
2149 " request datagram: "); |
2282 " request datagram: "); |
2150 ec_datagram_print_state(datagram); |
2283 ec_datagram_print_state(fsm->datagram); |
2151 return; |
2284 return; |
2152 } |
2285 } |
2153 |
2286 |
2154 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
2287 if (fsm->datagram->working_counter != 1) { |
2155 fsm->request->errno = EIO; |
2288 fsm->request->errno = EIO; |
2156 fsm->state = ec_fsm_coe_error; |
2289 fsm->state = ec_fsm_coe_error; |
2157 EC_SLAVE_ERR(slave, "Reception of CoE upload segment" |
2290 EC_SLAVE_ERR(slave, "Reception of CoE upload segment" |
2158 " request failed: "); |
2291 " request failed: "); |
2159 ec_datagram_print_wc_error(datagram); |
2292 ec_datagram_print_wc_error(fsm->datagram); |
2160 return; |
2293 return; |
2161 } |
2294 } |
2162 |
2295 |
2163 fsm->jiffies_start = datagram->jiffies_sent; |
2296 fsm->jiffies_start = fsm->datagram->jiffies_sent; |
2164 |
2297 |
2165 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
2298 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
2166 fsm->retries = EC_FSM_RETRIES; |
2299 fsm->retries = EC_FSM_RETRIES; |
2167 fsm->state = ec_fsm_coe_up_seg_check; |
2300 fsm->state = ec_fsm_coe_up_seg_check; |
2168 } |
2301 } |
2169 |
2302 |
2170 /*****************************************************************************/ |
2303 /*****************************************************************************/ |
2171 |
2304 |
2172 /** |
2305 /** |
2173 CoE state: UP CHECK. |
2306 CoE state: UP CHECK. |
2174 */ |
2307 */ |
2175 |
2308 |
2176 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *fsm /**< finite state machine */) |
2309 void ec_fsm_coe_up_seg_check( |
2177 { |
2310 ec_fsm_coe_t *fsm, /**< Finite state machine. */ |
2178 ec_mailbox_t *mbox = fsm->mbox; |
2311 ec_datagram_t *datagram /**< Datagram to use. */ |
2179 ec_datagram_t *datagram = mbox->datagram; |
2312 ) |
2180 ec_slave_t *slave = fsm->slave; |
2313 { |
2181 |
2314 ec_slave_t *slave = fsm->slave; |
2182 if (ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_TIMED_OUT) |
2315 |
2183 && fsm->retries--) { |
2316 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) { |
2184 return; |
2317 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
2185 } |
2318 return; |
2186 |
2319 } |
2187 if (!ec_mbox_is_datagram_state(mbox, EC_DATAGRAM_RECEIVED)) { |
2320 |
|
2321 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) { |
2188 fsm->request->errno = EIO; |
2322 fsm->request->errno = EIO; |
2189 fsm->state = ec_fsm_coe_error; |
2323 fsm->state = ec_fsm_coe_error; |
2190 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check" |
2324 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check" |
2191 " datagram: "); |
2325 " datagram: "); |
2192 ec_datagram_print_state(datagram); |
2326 ec_datagram_print_state(fsm->datagram); |
2193 return; |
2327 return; |
2194 } |
2328 } |
2195 |
2329 |
2196 if (!ec_mbox_is_datagram_wc(mbox, 1)) { |
2330 if (fsm->datagram->working_counter != 1) { |
2197 fsm->request->errno = EIO; |
2331 fsm->request->errno = EIO; |
2198 fsm->state = ec_fsm_coe_error; |
2332 fsm->state = ec_fsm_coe_error; |
2199 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check datagram" |
2333 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check datagram" |
2200 " failed: "); |
2334 " failed: "); |
2201 ec_datagram_print_wc_error(datagram); |
2335 ec_datagram_print_wc_error(fsm->datagram); |
2202 return; |
2336 return; |
2203 } |
2337 } |
2204 |
2338 |
2205 if (!ec_slave_mbox_check(mbox)) { |
2339 if (!ec_slave_mbox_check(fsm->datagram)) { |
2206 unsigned long diff_ms = |
2340 unsigned long diff_ms = |
2207 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
2341 (fsm->datagram->jiffies_received - fsm->jiffies_start) * |
|
2342 1000 / HZ; |
2208 if (diff_ms >= fsm->request->response_timeout) { |
2343 if (diff_ms >= fsm->request->response_timeout) { |
2209 fsm->request->errno = EIO; |
2344 fsm->request->errno = EIO; |
2210 fsm->state = ec_fsm_coe_error; |
2345 fsm->state = ec_fsm_coe_error; |
2211 EC_SLAVE_ERR(slave, "Timeout while waiting for SDO upload" |
2346 EC_SLAVE_ERR(slave, "Timeout while waiting for SDO upload" |
2212 " segment response.\n"); |
2347 " segment response.\n"); |
2213 return; |
2348 return; |
2214 } |
2349 } |
2215 |
2350 |
2216 ec_slave_mbox_prepare_check(slave, mbox); // can not fail. |
2351 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
2217 fsm->retries = EC_FSM_RETRIES; |
2352 fsm->retries = EC_FSM_RETRIES; |
2218 return; |
2353 return; |
2219 } |
2354 } |
2220 |
2355 |
2221 // Fetch response |
2356 // Fetch response |
2222 ec_slave_mbox_prepare_fetch(slave, mbox); // can not fail. |
2357 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
2223 fsm->retries = EC_FSM_RETRIES; |
2358 fsm->retries = EC_FSM_RETRIES; |
2224 fsm->state = ec_fsm_coe_up_seg_response; |
2359 fsm->state = ec_fsm_coe_up_seg_response; |
2225 } |
2360 } |
2226 |
2361 |
2227 /*****************************************************************************/ |
2362 /*****************************************************************************/ |