180 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
180 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
181 return; |
181 return; |
182 |
182 |
183 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
183 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
184 fsm->state = ec_fsm_change_state_error; |
184 fsm->state = ec_fsm_change_state_error; |
185 EC_ERR("Failed to receive state datagram from slave %u: ", |
185 EC_SLAVE_ERR(slave, "Failed to receive state datagram: "); |
186 fsm->slave->ring_position); |
|
187 ec_datagram_print_state(datagram); |
186 ec_datagram_print_state(datagram); |
188 return; |
187 return; |
189 } |
188 } |
190 |
189 |
191 if (fsm->take_time) { |
190 if (fsm->take_time) { |
196 if (datagram->working_counter == 0) { |
195 if (datagram->working_counter == 0) { |
197 if (datagram->jiffies_received - fsm->jiffies_start >= 3 * HZ) { |
196 if (datagram->jiffies_received - fsm->jiffies_start >= 3 * HZ) { |
198 char state_str[EC_STATE_STRING_SIZE]; |
197 char state_str[EC_STATE_STRING_SIZE]; |
199 ec_state_string(fsm->requested_state, state_str, 0); |
198 ec_state_string(fsm->requested_state, state_str, 0); |
200 fsm->state = ec_fsm_change_state_error; |
199 fsm->state = ec_fsm_change_state_error; |
201 EC_ERR("Failed to set state %s on slave %u: ", |
200 EC_SLAVE_ERR(slave, "Failed to set state %s: ", state_str); |
202 state_str, fsm->slave->ring_position); |
|
203 ec_datagram_print_wc_error(datagram); |
201 ec_datagram_print_wc_error(datagram); |
204 return; |
202 return; |
205 } |
203 } |
206 |
204 |
207 // repeat writing new state to slave |
205 // repeat writing new state to slave |
213 |
211 |
214 if (unlikely(datagram->working_counter > 1)) { |
212 if (unlikely(datagram->working_counter > 1)) { |
215 char state_str[EC_STATE_STRING_SIZE]; |
213 char state_str[EC_STATE_STRING_SIZE]; |
216 ec_state_string(fsm->requested_state, state_str, 0); |
214 ec_state_string(fsm->requested_state, state_str, 0); |
217 fsm->state = ec_fsm_change_state_error; |
215 fsm->state = ec_fsm_change_state_error; |
218 EC_ERR("Failed to set state %s on slave %u: ", |
216 EC_SLAVE_ERR(slave, "Failed to set state %s: ", state_str); |
219 state_str, fsm->slave->ring_position); |
|
220 ec_datagram_print_wc_error(datagram); |
217 ec_datagram_print_wc_error(datagram); |
221 return; |
218 return; |
222 } |
219 } |
223 |
220 |
224 fsm->take_time = 1; |
221 fsm->take_time = 1; |
246 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
243 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
247 return; |
244 return; |
248 |
245 |
249 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
246 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
250 fsm->state = ec_fsm_change_state_error; |
247 fsm->state = ec_fsm_change_state_error; |
251 EC_ERR("Failed to receive state checking datagram from slave %u: ", |
248 EC_SLAVE_ERR(slave, "Failed to receive state checking datagram: "); |
252 slave->ring_position); |
|
253 ec_datagram_print_state(datagram); |
249 ec_datagram_print_state(datagram); |
254 return; |
250 return; |
255 } |
251 } |
256 |
252 |
257 if (datagram->working_counter != 1) { |
253 if (datagram->working_counter != 1) { |
258 char req_state[EC_STATE_STRING_SIZE]; |
254 char req_state[EC_STATE_STRING_SIZE]; |
259 ec_state_string(fsm->requested_state, req_state, 0); |
255 ec_state_string(fsm->requested_state, req_state, 0); |
260 fsm->state = ec_fsm_change_state_error; |
256 fsm->state = ec_fsm_change_state_error; |
261 EC_ERR("Failed to check state %s on slave %u: ", |
257 EC_SLAVE_ERR(slave, "Failed to check state %s: ", req_state); |
262 req_state, slave->ring_position); |
|
263 ec_datagram_print_wc_error(datagram); |
258 ec_datagram_print_wc_error(datagram); |
264 return; |
259 return; |
265 } |
260 } |
266 |
261 |
267 if (fsm->take_time) { |
262 if (fsm->take_time) { |
286 // Slave spontaneously changed its state just before the new state |
281 // Slave spontaneously changed its state just before the new state |
287 // was written. Accept current state as old state and wait for |
282 // was written. Accept current state as old state and wait for |
288 // state change |
283 // state change |
289 fsm->spontaneous_change = 1; |
284 fsm->spontaneous_change = 1; |
290 fsm->old_state = slave->current_state; |
285 fsm->old_state = slave->current_state; |
291 EC_WARN("Slave %u changed to %s in the meantime.\n", |
286 EC_SLAVE_WARN(slave, "Changed to %s in the meantime.\n", |
292 slave->ring_position, cur_state); |
287 cur_state); |
293 goto check_again; |
288 goto check_again; |
294 } |
289 } |
295 |
290 |
296 // state change error |
291 // state change error |
297 |
292 |
298 slave->error_flag = 1; |
293 slave->error_flag = 1; |
299 ec_state_string(fsm->requested_state, req_state, 0); |
294 ec_state_string(fsm->requested_state, req_state, 0); |
300 |
295 |
301 EC_ERR("Failed to set %s state, slave %u refused state change (%s).\n", |
296 EC_SLAVE_ERR(slave, "Failed to set %s state, slave refused state" |
302 req_state, slave->ring_position, cur_state); |
297 " change (%s).\n", req_state, cur_state); |
303 // fetch AL status error code |
298 // fetch AL status error code |
304 ec_datagram_fprd(datagram, slave->station_address, 0x0134, 2); |
299 ec_datagram_fprd(datagram, slave->station_address, 0x0134, 2); |
305 ec_datagram_zero(datagram); |
300 ec_datagram_zero(datagram); |
306 fsm->retries = EC_FSM_RETRIES; |
301 fsm->retries = EC_FSM_RETRIES; |
307 fsm->state = ec_fsm_change_state_code; |
302 fsm->state = ec_fsm_change_state_code; |
314 EC_AL_STATE_CHANGE_TIMEOUT * HZ) { |
309 EC_AL_STATE_CHANGE_TIMEOUT * HZ) { |
315 // timeout while checking |
310 // timeout while checking |
316 char state_str[EC_STATE_STRING_SIZE]; |
311 char state_str[EC_STATE_STRING_SIZE]; |
317 ec_state_string(fsm->requested_state, state_str, 0); |
312 ec_state_string(fsm->requested_state, state_str, 0); |
318 fsm->state = ec_fsm_change_state_error; |
313 fsm->state = ec_fsm_change_state_error; |
319 EC_ERR("Timeout while setting state %s on slave %u.\n", |
314 EC_SLAVE_ERR(slave, "Timeout while setting state %s.\n", state_str); |
320 state_str, slave->ring_position); |
|
321 return; |
315 return; |
322 } |
316 } |
323 |
317 |
324 check_again: |
318 check_again: |
325 // no timeout yet. check again |
319 // no timeout yet. check again |
404 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
398 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
405 return; |
399 return; |
406 |
400 |
407 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
401 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
408 fsm->state = ec_fsm_change_state_error; |
402 fsm->state = ec_fsm_change_state_error; |
409 EC_ERR("Failed to receive AL status code datagram from slave %u: ", |
403 EC_SLAVE_ERR(fsm->slave, "Failed to receive" |
410 fsm->slave->ring_position); |
404 " AL status code datagram: "); |
411 ec_datagram_print_state(datagram); |
405 ec_datagram_print_state(datagram); |
412 return; |
406 return; |
413 } |
407 } |
414 |
408 |
415 if (datagram->working_counter != 1) { |
409 if (datagram->working_counter != 1) { |
416 EC_WARN("Reception of AL status code datagram failed: "); |
410 EC_SLAVE_WARN(fsm->slave, "Reception of AL status code" |
|
411 " datagram failed: "); |
417 ec_datagram_print_wc_error(datagram); |
412 ec_datagram_print_wc_error(datagram); |
418 } else { |
413 } else { |
419 code = EC_READ_U16(datagram->data); |
414 code = EC_READ_U16(datagram->data); |
420 for (al_msg = al_status_messages; al_msg->code != 0xffff; al_msg++) { |
415 for (al_msg = al_status_messages; al_msg->code != 0xffff; al_msg++) { |
421 if (al_msg->code != code) continue; |
416 if (al_msg->code != code) continue; |
422 EC_ERR("AL status message 0x%04X: \"%s\".\n", |
417 EC_SLAVE_ERR(fsm->slave, "AL status message 0x%04X: \"%s\".\n", |
423 al_msg->code, al_msg->message); |
418 al_msg->code, al_msg->message); |
424 break; |
419 break; |
425 } |
420 } |
426 if (!al_msg->code) |
421 if (!al_msg->code) |
427 EC_ERR("Unknown AL status code 0x%04X.\n", code); |
422 EC_SLAVE_ERR(fsm->slave, "Unknown AL status code 0x%04X.\n", |
|
423 code); |
428 } |
424 } |
429 |
425 |
430 // acknowledge "old" slave state |
426 // acknowledge "old" slave state |
431 ec_fsm_change_state_start_ack(fsm); // execute immediately |
427 ec_fsm_change_state_start_ack(fsm); // execute immediately |
432 } |
428 } |
463 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
459 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
464 return; |
460 return; |
465 |
461 |
466 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
462 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
467 fsm->state = ec_fsm_change_state_error; |
463 fsm->state = ec_fsm_change_state_error; |
468 EC_ERR("Failed to receive state ack datagram for slave %u: ", |
464 EC_SLAVE_ERR(slave, "Failed to receive state ack datagram: "); |
469 slave->ring_position); |
|
470 ec_datagram_print_state(datagram); |
465 ec_datagram_print_state(datagram); |
471 return; |
466 return; |
472 } |
467 } |
473 |
468 |
474 if (datagram->working_counter != 1) { |
469 if (datagram->working_counter != 1) { |
475 fsm->state = ec_fsm_change_state_error; |
470 fsm->state = ec_fsm_change_state_error; |
476 EC_ERR("Reception of state ack datagram failed on slave %u: ", |
471 EC_SLAVE_ERR(slave, "Reception of state ack datagram failed: "); |
477 slave->ring_position); |
|
478 ec_datagram_print_wc_error(datagram); |
472 ec_datagram_print_wc_error(datagram); |
479 return; |
473 return; |
480 } |
474 } |
481 |
475 |
482 fsm->take_time = 1; |
476 fsm->take_time = 1; |
503 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
497 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
504 return; |
498 return; |
505 |
499 |
506 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
500 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
507 fsm->state = ec_fsm_change_state_error; |
501 fsm->state = ec_fsm_change_state_error; |
508 EC_ERR("Failed to receive state ack check datagram from slave %u: ", |
502 EC_SLAVE_ERR(slave, "Failed to receive state ack check datagram: "); |
509 slave->ring_position); |
|
510 ec_datagram_print_state(datagram); |
503 ec_datagram_print_state(datagram); |
511 return; |
504 return; |
512 } |
505 } |
513 |
506 |
514 if (datagram->working_counter != 1) { |
507 if (datagram->working_counter != 1) { |
515 fsm->state = ec_fsm_change_state_error; |
508 fsm->state = ec_fsm_change_state_error; |
516 EC_ERR("Reception of state ack check datagram failed on slave %u: ", |
509 EC_SLAVE_ERR(slave, "Reception of state ack check datagram failed: "); |
517 slave->ring_position); |
|
518 ec_datagram_print_wc_error(datagram); |
510 ec_datagram_print_wc_error(datagram); |
519 return; |
511 return; |
520 } |
512 } |
521 |
513 |
522 if (fsm->take_time) { |
514 if (fsm->take_time) { |
533 fsm->state = ec_fsm_change_state_error; |
525 fsm->state = ec_fsm_change_state_error; |
534 } |
526 } |
535 else { // EC_FSM_CHANGE_MODE_ACK_ONLY |
527 else { // EC_FSM_CHANGE_MODE_ACK_ONLY |
536 fsm->state = ec_fsm_change_state_end; |
528 fsm->state = ec_fsm_change_state_end; |
537 } |
529 } |
538 EC_INFO("Acknowledged state %s on slave %u.\n", |
530 EC_SLAVE_INFO(slave, "Acknowledged state %s.\n", state_str); |
539 state_str, slave->ring_position); |
|
540 return; |
531 return; |
541 } |
532 } |
542 |
533 |
543 if (datagram->jiffies_received - fsm->jiffies_start >= |
534 if (datagram->jiffies_received - fsm->jiffies_start >= |
544 EC_AL_STATE_CHANGE_TIMEOUT * HZ) { |
535 EC_AL_STATE_CHANGE_TIMEOUT * HZ) { |
545 // timeout while checking |
536 // timeout while checking |
546 char state_str[EC_STATE_STRING_SIZE]; |
537 char state_str[EC_STATE_STRING_SIZE]; |
547 ec_state_string(slave->current_state, state_str, 0); |
538 ec_state_string(slave->current_state, state_str, 0); |
548 fsm->state = ec_fsm_change_state_error; |
539 fsm->state = ec_fsm_change_state_error; |
549 EC_ERR("Timeout while acknowledging state %s on slave %u.\n", |
540 EC_SLAVE_ERR(slave, "Timeout while acknowledging state %s.\n", |
550 state_str, slave->ring_position); |
541 state_str); |
551 return; |
542 return; |
552 } |
543 } |
553 |
544 |
554 // reread new AL status |
545 // reread new AL status |
555 ec_datagram_fprd(datagram, slave->station_address, 0x0130, 2); |
546 ec_datagram_fprd(datagram, slave->station_address, 0x0130, 2); |