00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00035
00036
00037 #include <asm/div64.h>
00038
00039 #include "globals.h"
00040 #include "master.h"
00041 #include "mailbox.h"
00042 #include "slave_config.h"
00043 #include "fsm_slave_config.h"
00044
00045
00046
00052 #define EC_DC_MAX_SYNC_DIFF_NS 10000
00053
00056 #define EC_DC_SYNC_WAIT_MS 5000
00057
00060 #define EC_DC_START_OFFSET 100000000ULL
00061
00062
00063
00064 void ec_fsm_slave_config_state_start(ec_fsm_slave_config_t *);
00065 void ec_fsm_slave_config_state_init(ec_fsm_slave_config_t *);
00066 void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *);
00067 void ec_fsm_slave_config_state_clear_sync(ec_fsm_slave_config_t *);
00068 void ec_fsm_slave_config_state_dc_clear_assign(ec_fsm_slave_config_t *);
00069 void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *);
00070 #ifdef EC_SII_ASSIGN
00071 void ec_fsm_slave_config_state_assign_pdi(ec_fsm_slave_config_t *);
00072 #endif
00073 void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *);
00074 #ifdef EC_SII_ASSIGN
00075 void ec_fsm_slave_config_state_assign_ethercat(ec_fsm_slave_config_t *);
00076 #endif
00077 void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *);
00078 void ec_fsm_slave_config_state_soe_conf_preop(ec_fsm_slave_config_t *);
00079 void ec_fsm_slave_config_state_watchdog_divider(ec_fsm_slave_config_t *);
00080 void ec_fsm_slave_config_state_watchdog(ec_fsm_slave_config_t *);
00081 void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *);
00082 void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *);
00083 void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *);
00084 void ec_fsm_slave_config_state_dc_cycle(ec_fsm_slave_config_t *);
00085 void ec_fsm_slave_config_state_dc_sync_check(ec_fsm_slave_config_t *);
00086 void ec_fsm_slave_config_state_dc_start(ec_fsm_slave_config_t *);
00087 void ec_fsm_slave_config_state_dc_assign(ec_fsm_slave_config_t *);
00088 void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *);
00089 void ec_fsm_slave_config_state_soe_conf_safeop(ec_fsm_slave_config_t *);
00090 void ec_fsm_slave_config_state_op(ec_fsm_slave_config_t *);
00091
00092 void ec_fsm_slave_config_enter_init(ec_fsm_slave_config_t *);
00093 void ec_fsm_slave_config_enter_clear_sync(ec_fsm_slave_config_t *);
00094 void ec_fsm_slave_config_enter_dc_clear_assign(ec_fsm_slave_config_t *);
00095 void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *);
00096 #ifdef EC_SII_ASSIGN
00097 void ec_fsm_slave_config_enter_assign_pdi(ec_fsm_slave_config_t *);
00098 #endif
00099 void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *);
00100 void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *);
00101 void ec_fsm_slave_config_enter_soe_conf_preop(ec_fsm_slave_config_t *);
00102 void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *);
00103 void ec_fsm_slave_config_enter_watchdog_divider(ec_fsm_slave_config_t *);
00104 void ec_fsm_slave_config_enter_watchdog(ec_fsm_slave_config_t *);
00105 void ec_fsm_slave_config_enter_pdo_sync(ec_fsm_slave_config_t *);
00106 void ec_fsm_slave_config_enter_fmmu(ec_fsm_slave_config_t *);
00107 void ec_fsm_slave_config_enter_dc_cycle(ec_fsm_slave_config_t *);
00108 void ec_fsm_slave_config_enter_safeop(ec_fsm_slave_config_t *);
00109 void ec_fsm_slave_config_enter_soe_conf_safeop(ec_fsm_slave_config_t *);
00110 void ec_fsm_slave_config_enter_op(ec_fsm_slave_config_t *);
00111
00112 void ec_fsm_slave_config_state_end(ec_fsm_slave_config_t *);
00113 void ec_fsm_slave_config_state_error(ec_fsm_slave_config_t *);
00114
00115 void ec_fsm_slave_config_reconfigure(ec_fsm_slave_config_t *);
00116
00117
00118
00121 void ec_fsm_slave_config_init(
00122 ec_fsm_slave_config_t *fsm,
00123 ec_datagram_t *datagram,
00124 ec_fsm_change_t *fsm_change,
00125 ec_fsm_coe_t *fsm_coe,
00126 ec_fsm_soe_t *fsm_soe,
00127 ec_fsm_pdo_t *fsm_pdo
00128 )
00129 {
00130 ec_sdo_request_init(&fsm->request_copy);
00131 ec_soe_request_init(&fsm->soe_request_copy);
00132
00133 fsm->datagram = datagram;
00134 fsm->fsm_change = fsm_change;
00135 fsm->fsm_coe = fsm_coe;
00136 fsm->fsm_soe = fsm_soe;
00137 fsm->fsm_pdo = fsm_pdo;
00138 }
00139
00140
00141
00144 void ec_fsm_slave_config_clear(
00145 ec_fsm_slave_config_t *fsm
00146 )
00147 {
00148 ec_sdo_request_clear(&fsm->request_copy);
00149 ec_soe_request_clear(&fsm->soe_request_copy);
00150 }
00151
00152
00153
00156 void ec_fsm_slave_config_start(
00157 ec_fsm_slave_config_t *fsm,
00158 ec_slave_t *slave
00159 )
00160 {
00161 fsm->slave = slave;
00162 fsm->state = ec_fsm_slave_config_state_start;
00163 }
00164
00165
00166
00170 int ec_fsm_slave_config_running(
00171 const ec_fsm_slave_config_t *fsm
00172 )
00173 {
00174 return fsm->state != ec_fsm_slave_config_state_end
00175 && fsm->state != ec_fsm_slave_config_state_error;
00176 }
00177
00178
00179
00187 int ec_fsm_slave_config_exec(
00188 ec_fsm_slave_config_t *fsm
00189 )
00190 {
00191 if (fsm->datagram->state == EC_DATAGRAM_SENT
00192 || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
00193
00194 return ec_fsm_slave_config_running(fsm);
00195 }
00196
00197 fsm->state(fsm);
00198 return ec_fsm_slave_config_running(fsm);
00199 }
00200
00201
00202
00206 int ec_fsm_slave_config_success(
00207 const ec_fsm_slave_config_t *fsm
00208 )
00209 {
00210 return fsm->state == ec_fsm_slave_config_state_end;
00211 }
00212
00213
00214
00215
00216
00219 void ec_fsm_slave_config_state_start(
00220 ec_fsm_slave_config_t *fsm
00221 )
00222 {
00223 EC_SLAVE_DBG(fsm->slave, 1, "Configuring...\n");
00224 ec_fsm_slave_config_enter_init(fsm);
00225 }
00226
00227
00228
00231 void ec_fsm_slave_config_enter_init(
00232 ec_fsm_slave_config_t *fsm
00233 )
00234 {
00235 ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
00236 ec_fsm_change_exec(fsm->fsm_change);
00237 fsm->state = ec_fsm_slave_config_state_init;
00238 }
00239
00240
00241
00244 void ec_fsm_slave_config_state_init(
00245 ec_fsm_slave_config_t *fsm
00246 )
00247 {
00248 ec_slave_t *slave = fsm->slave;
00249 ec_datagram_t *datagram = fsm->datagram;
00250
00251 if (ec_fsm_change_exec(fsm->fsm_change)) return;
00252
00253 if (!ec_fsm_change_success(fsm->fsm_change)) {
00254 if (!fsm->fsm_change->spontaneous_change)
00255 slave->error_flag = 1;
00256 fsm->state = ec_fsm_slave_config_state_error;
00257 return;
00258 }
00259
00260 EC_SLAVE_DBG(slave, 1, "Now in INIT.\n");
00261
00262 if (!slave->base_fmmu_count) {
00263 ec_fsm_slave_config_enter_clear_sync(fsm);
00264 return;
00265 }
00266
00267 EC_SLAVE_DBG(slave, 1, "Clearing FMMU configurations...\n");
00268
00269
00270 ec_datagram_fpwr(datagram, slave->station_address,
00271 0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
00272 ec_datagram_zero(datagram);
00273 fsm->retries = EC_FSM_RETRIES;
00274 fsm->state = ec_fsm_slave_config_state_clear_fmmus;
00275 }
00276
00277
00278
00281 void ec_fsm_slave_config_state_clear_fmmus(
00282 ec_fsm_slave_config_t *fsm
00283 )
00284 {
00285 ec_datagram_t *datagram = fsm->datagram;
00286
00287 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00288 return;
00289
00290 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00291 fsm->state = ec_fsm_slave_config_state_error;
00292 EC_SLAVE_ERR(fsm->slave, "Failed receive FMMU clearing datagram.\n");
00293 return;
00294 }
00295
00296 if (datagram->working_counter != 1) {
00297 fsm->slave->error_flag = 1;
00298 fsm->state = ec_fsm_slave_config_state_error;
00299 EC_SLAVE_ERR(fsm->slave, "Failed to clear FMMUs: ");
00300 ec_datagram_print_wc_error(datagram);
00301 return;
00302 }
00303
00304 ec_fsm_slave_config_enter_clear_sync(fsm);
00305 }
00306
00307
00308
00311 void ec_fsm_slave_config_enter_clear_sync(
00312 ec_fsm_slave_config_t *fsm
00313 )
00314 {
00315 ec_slave_t *slave = fsm->slave;
00316 ec_datagram_t *datagram = fsm->datagram;
00317 size_t sync_size;
00318
00319 if (!slave->base_sync_count) {
00320
00321 ec_fsm_slave_config_enter_dc_clear_assign(fsm);
00322 return;
00323 }
00324
00325 EC_SLAVE_DBG(slave, 1, "Clearing sync manager configurations...\n");
00326
00327 sync_size = EC_SYNC_PAGE_SIZE * slave->base_sync_count;
00328
00329
00330 ec_datagram_fpwr(datagram, slave->station_address, 0x0800, sync_size);
00331 ec_datagram_zero(datagram);
00332 fsm->retries = EC_FSM_RETRIES;
00333 fsm->state = ec_fsm_slave_config_state_clear_sync;
00334 }
00335
00336
00337
00340 void ec_fsm_slave_config_state_clear_sync(
00341 ec_fsm_slave_config_t *fsm
00342 )
00343 {
00344 ec_datagram_t *datagram = fsm->datagram;
00345
00346 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00347 return;
00348
00349 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00350 fsm->state = ec_fsm_slave_config_state_error;
00351 EC_SLAVE_ERR(fsm->slave, "Failed receive sync manager"
00352 " clearing datagram.\n");
00353 return;
00354 }
00355
00356 if (datagram->working_counter != 1) {
00357 fsm->slave->error_flag = 1;
00358 fsm->state = ec_fsm_slave_config_state_error;
00359 EC_SLAVE_ERR(fsm->slave,
00360 "Failed to clear sync manager configurations: ");
00361 ec_datagram_print_wc_error(datagram);
00362 return;
00363 }
00364
00365 ec_fsm_slave_config_enter_dc_clear_assign(fsm);
00366 }
00367
00368
00369
00372 void ec_fsm_slave_config_enter_dc_clear_assign(
00373 ec_fsm_slave_config_t *fsm
00374 )
00375 {
00376 ec_slave_t *slave = fsm->slave;
00377 ec_datagram_t *datagram = fsm->datagram;
00378
00379 if (!slave->base_dc_supported || !slave->has_dc_system_time) {
00380 ec_fsm_slave_config_enter_mbox_sync(fsm);
00381 return;
00382 }
00383
00384 EC_SLAVE_DBG(slave, 1, "Clearing DC assignment...\n");
00385
00386 ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
00387 ec_datagram_zero(datagram);
00388 fsm->retries = EC_FSM_RETRIES;
00389 fsm->state = ec_fsm_slave_config_state_dc_clear_assign;
00390 }
00391
00392
00393
00396 void ec_fsm_slave_config_state_dc_clear_assign(
00397 ec_fsm_slave_config_t *fsm
00398 )
00399 {
00400 ec_datagram_t *datagram = fsm->datagram;
00401
00402 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00403 return;
00404
00405 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00406 fsm->state = ec_fsm_slave_config_state_error;
00407 EC_SLAVE_ERR(fsm->slave, "Failed receive DC assignment"
00408 " clearing datagram.\n");
00409 return;
00410 }
00411
00412 if (datagram->working_counter != 1) {
00413
00414 EC_SLAVE_DBG(fsm->slave, 1, "Failed to clear DC assignment: ");
00415 ec_datagram_print_wc_error(datagram);
00416 }
00417
00418 ec_fsm_slave_config_enter_mbox_sync(fsm);
00419 }
00420
00421
00422
00425 void ec_fsm_slave_config_enter_mbox_sync(
00426 ec_fsm_slave_config_t *fsm
00427 )
00428 {
00429 ec_slave_t *slave = fsm->slave;
00430 ec_datagram_t *datagram = fsm->datagram;
00431 unsigned int i;
00432
00433
00434 if (slave->current_state == slave->requested_state) {
00435 fsm->state = ec_fsm_slave_config_state_end;
00436 EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
00437 return;
00438 }
00439
00440 if (!slave->sii.mailbox_protocols) {
00441
00442 EC_SLAVE_DBG(slave, 1, "Slave does not support"
00443 " mailbox communication.\n");
00444 #ifdef EC_SII_ASSIGN
00445 ec_fsm_slave_config_enter_assign_pdi(fsm);
00446 #else
00447 ec_fsm_slave_config_enter_boot_preop(fsm);
00448 #endif
00449 return;
00450 }
00451
00452 EC_SLAVE_DBG(slave, 1, "Configuring mailbox sync managers...\n");
00453
00454 if (slave->requested_state == EC_SLAVE_STATE_BOOT) {
00455 ec_sync_t sync;
00456
00457 ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
00458 EC_SYNC_PAGE_SIZE * 2);
00459 ec_datagram_zero(datagram);
00460
00461 ec_sync_init(&sync, slave);
00462 sync.physical_start_address = slave->sii.boot_rx_mailbox_offset;
00463 sync.control_register = 0x26;
00464 sync.enable = 1;
00465 ec_sync_page(&sync, 0, slave->sii.boot_rx_mailbox_size,
00466 EC_DIR_INVALID,
00467 0,
00468 datagram->data);
00469 slave->configured_rx_mailbox_offset =
00470 slave->sii.boot_rx_mailbox_offset;
00471 slave->configured_rx_mailbox_size =
00472 slave->sii.boot_rx_mailbox_size;
00473
00474 ec_sync_init(&sync, slave);
00475 sync.physical_start_address = slave->sii.boot_tx_mailbox_offset;
00476 sync.control_register = 0x22;
00477 sync.enable = 1;
00478 ec_sync_page(&sync, 1, slave->sii.boot_tx_mailbox_size,
00479 EC_DIR_INVALID,
00480 0,
00481 datagram->data + EC_SYNC_PAGE_SIZE);
00482 slave->configured_tx_mailbox_offset =
00483 slave->sii.boot_tx_mailbox_offset;
00484 slave->configured_tx_mailbox_size =
00485 slave->sii.boot_tx_mailbox_size;
00486
00487 } else if (slave->sii.sync_count >= 2) {
00488 ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
00489 EC_SYNC_PAGE_SIZE * slave->sii.sync_count);
00490 ec_datagram_zero(datagram);
00491
00492 for (i = 0; i < 2; i++) {
00493 ec_sync_page(&slave->sii.syncs[i], i,
00494 slave->sii.syncs[i].default_length,
00495 NULL,
00496 0,
00497 datagram->data + EC_SYNC_PAGE_SIZE * i);
00498 }
00499
00500 slave->configured_rx_mailbox_offset =
00501 slave->sii.syncs[0].physical_start_address;
00502 slave->configured_rx_mailbox_size =
00503 slave->sii.syncs[0].default_length;
00504 slave->configured_tx_mailbox_offset =
00505 slave->sii.syncs[1].physical_start_address;
00506 slave->configured_tx_mailbox_size =
00507 slave->sii.syncs[1].default_length;
00508 } else {
00509 ec_sync_t sync;
00510
00511 EC_SLAVE_DBG(slave, 1, "Slave does not provide"
00512 " mailbox sync manager configurations.\n");
00513
00514 ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
00515 EC_SYNC_PAGE_SIZE * 2);
00516 ec_datagram_zero(datagram);
00517
00518 ec_sync_init(&sync, slave);
00519 sync.physical_start_address = slave->sii.std_rx_mailbox_offset;
00520 sync.control_register = 0x26;
00521 sync.enable = 1;
00522 ec_sync_page(&sync, 0, slave->sii.std_rx_mailbox_size,
00523 NULL,
00524 0,
00525 datagram->data);
00526 slave->configured_rx_mailbox_offset =
00527 slave->sii.std_rx_mailbox_offset;
00528 slave->configured_rx_mailbox_size =
00529 slave->sii.std_rx_mailbox_size;
00530
00531 ec_sync_init(&sync, slave);
00532 sync.physical_start_address = slave->sii.std_tx_mailbox_offset;
00533 sync.control_register = 0x22;
00534 sync.enable = 1;
00535 ec_sync_page(&sync, 1, slave->sii.std_tx_mailbox_size,
00536 NULL,
00537 0,
00538 datagram->data + EC_SYNC_PAGE_SIZE);
00539 slave->configured_tx_mailbox_offset =
00540 slave->sii.std_tx_mailbox_offset;
00541 slave->configured_tx_mailbox_size =
00542 slave->sii.std_tx_mailbox_size;
00543 }
00544
00545 fsm->take_time = 1;
00546
00547 fsm->retries = EC_FSM_RETRIES;
00548 fsm->state = ec_fsm_slave_config_state_mbox_sync;
00549 }
00550
00551
00552
00557 void ec_fsm_slave_config_state_mbox_sync(
00558 ec_fsm_slave_config_t *fsm
00559 )
00560 {
00561 ec_datagram_t *datagram = fsm->datagram;
00562 ec_slave_t *slave = fsm->slave;
00563
00564 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00565 return;
00566
00567 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00568 fsm->state = ec_fsm_slave_config_state_error;
00569 EC_SLAVE_ERR(slave, "Failed to receive sync manager"
00570 " configuration datagram: ");
00571 ec_datagram_print_state(datagram);
00572 return;
00573 }
00574
00575 if (fsm->take_time) {
00576 fsm->take_time = 0;
00577 fsm->jiffies_start = datagram->jiffies_sent;
00578 }
00579
00580
00581
00582
00583
00584
00585 if (datagram->working_counter == 0) {
00586 unsigned long diff = datagram->jiffies_received - fsm->jiffies_start;
00587
00588 if (diff >= HZ) {
00589 slave->error_flag = 1;
00590 fsm->state = ec_fsm_slave_config_state_error;
00591 EC_SLAVE_ERR(slave, "Timeout while configuring"
00592 " mailbox sync managers.\n");
00593 return;
00594 } else {
00595 EC_SLAVE_DBG(slave, 1, "Resending after %u ms...\n",
00596 (unsigned int) diff * 1000 / HZ);
00597 }
00598
00599
00600 fsm->retries = EC_FSM_RETRIES;
00601 return;
00602 }
00603 else if (datagram->working_counter != 1) {
00604 slave->error_flag = 1;
00605 fsm->state = ec_fsm_slave_config_state_error;
00606 EC_SLAVE_ERR(slave, "Failed to set sync managers: ");
00607 ec_datagram_print_wc_error(datagram);
00608 return;
00609 }
00610
00611 #ifdef EC_SII_ASSIGN
00612 ec_fsm_slave_config_enter_assign_pdi(fsm);
00613 #else
00614 ec_fsm_slave_config_enter_boot_preop(fsm);
00615 #endif
00616 }
00617
00618
00619
00620 #ifdef EC_SII_ASSIGN
00621
00624 void ec_fsm_slave_config_enter_assign_pdi(
00625 ec_fsm_slave_config_t *fsm
00626 )
00627 {
00628 ec_datagram_t *datagram = fsm->datagram;
00629 ec_slave_t *slave = fsm->slave;
00630
00631 if (fsm->slave->requested_state != EC_SLAVE_STATE_BOOT) {
00632 EC_SLAVE_DBG(slave, 1, "Assigning SII access to PDI.\n");
00633
00634 ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 0x01);
00635 EC_WRITE_U8(datagram->data, 0x01);
00636 fsm->retries = EC_FSM_RETRIES;
00637 fsm->state = ec_fsm_slave_config_state_assign_pdi;
00638 }
00639 else {
00640 ec_fsm_slave_config_enter_boot_preop(fsm);
00641 }
00642 }
00643
00644
00645
00648 void ec_fsm_slave_config_state_assign_pdi(
00649 ec_fsm_slave_config_t *fsm
00650 )
00651 {
00652 ec_datagram_t *datagram = fsm->datagram;
00653 ec_slave_t *slave = fsm->slave;
00654
00655 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00656 return;
00657 }
00658
00659 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00660 EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: ");
00661 ec_datagram_print_state(datagram);
00662 goto cont_preop;
00663 }
00664
00665 if (datagram->working_counter != 1) {
00666 EC_SLAVE_WARN(slave, "Failed to assign SII to PDI: ");
00667 ec_datagram_print_wc_error(datagram);
00668 }
00669
00670 cont_preop:
00671 ec_fsm_slave_config_enter_boot_preop(fsm);
00672 }
00673
00674 #endif
00675
00676
00677
00680 void ec_fsm_slave_config_enter_boot_preop(
00681 ec_fsm_slave_config_t *fsm
00682 )
00683 {
00684 fsm->state = ec_fsm_slave_config_state_boot_preop;
00685
00686 if (fsm->slave->requested_state != EC_SLAVE_STATE_BOOT) {
00687 ec_fsm_change_start(fsm->fsm_change,
00688 fsm->slave, EC_SLAVE_STATE_PREOP);
00689 } else {
00690 ec_fsm_change_start(fsm->fsm_change,
00691 fsm->slave, EC_SLAVE_STATE_BOOT);
00692 }
00693
00694 ec_fsm_change_exec(fsm->fsm_change);
00695 }
00696
00697
00698
00701 void ec_fsm_slave_config_state_boot_preop(
00702 ec_fsm_slave_config_t *fsm
00703 )
00704 {
00705 ec_slave_t *slave = fsm->slave;
00706
00707 if (ec_fsm_change_exec(fsm->fsm_change)) {
00708 return;
00709 }
00710
00711 if (!ec_fsm_change_success(fsm->fsm_change)) {
00712 if (!fsm->fsm_change->spontaneous_change)
00713 slave->error_flag = 1;
00714 fsm->state = ec_fsm_slave_config_state_error;
00715 return;
00716 }
00717
00718
00719 slave->jiffies_preop = fsm->datagram->jiffies_received;
00720
00721 EC_SLAVE_DBG(slave, 1, "Now in %s.\n",
00722 slave->requested_state != EC_SLAVE_STATE_BOOT ? "PREOP" : "BOOT");
00723
00724 #ifdef EC_SII_ASSIGN
00725 EC_SLAVE_DBG(slave, 1, "Assigning SII access back to EtherCAT.\n");
00726
00727 ec_datagram_fpwr(fsm->datagram, slave->station_address, 0x0500, 0x01);
00728 EC_WRITE_U8(fsm->datagram->data, 0x00);
00729 fsm->retries = EC_FSM_RETRIES;
00730 fsm->state = ec_fsm_slave_config_state_assign_ethercat;
00731 #else
00732 if (slave->current_state == slave->requested_state) {
00733 fsm->state = ec_fsm_slave_config_state_end;
00734 EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
00735 return;
00736 }
00737
00738 ec_fsm_slave_config_enter_sdo_conf(fsm);
00739 #endif
00740 }
00741
00742
00743
00744 #ifdef EC_SII_ASSIGN
00745
00748 void ec_fsm_slave_config_state_assign_ethercat(
00749 ec_fsm_slave_config_t *fsm
00750 )
00751 {
00752 ec_datagram_t *datagram = fsm->datagram;
00753 ec_slave_t *slave = fsm->slave;
00754
00755 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00756 return;
00757 }
00758
00759 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00760 EC_SLAVE_WARN(slave, "Failed receive SII assignment datagram: ");
00761 ec_datagram_print_state(datagram);
00762 goto cont_sdo_conf;
00763 }
00764
00765 if (datagram->working_counter != 1) {
00766 EC_SLAVE_WARN(slave, "Failed to assign SII back to EtherCAT: ");
00767 ec_datagram_print_wc_error(datagram);
00768 }
00769
00770 cont_sdo_conf:
00771 if (slave->current_state == slave->requested_state) {
00772 fsm->state = ec_fsm_slave_config_state_end;
00773 EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
00774 return;
00775 }
00776
00777 ec_fsm_slave_config_enter_sdo_conf(fsm);
00778 }
00779
00780 #endif
00781
00782
00783
00786 void ec_fsm_slave_config_enter_sdo_conf(
00787 ec_fsm_slave_config_t *fsm
00788 )
00789 {
00790 ec_slave_t *slave = fsm->slave;
00791
00792 if (!slave->config) {
00793 ec_fsm_slave_config_enter_pdo_sync(fsm);
00794 return;
00795 }
00796
00797
00798 if (list_empty(&slave->config->sdo_configs)) {
00799 ec_fsm_slave_config_enter_soe_conf_preop(fsm);
00800 return;
00801 }
00802
00803
00804 fsm->state = ec_fsm_slave_config_state_sdo_conf;
00805 fsm->request = list_entry(fsm->slave->config->sdo_configs.next,
00806 ec_sdo_request_t, list);
00807 ec_sdo_request_copy(&fsm->request_copy, fsm->request);
00808 ecrt_sdo_request_write(&fsm->request_copy);
00809 ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
00810 ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram);
00811 }
00812
00813
00814
00817 void ec_fsm_slave_config_state_sdo_conf(
00818 ec_fsm_slave_config_t *fsm
00819 )
00820 {
00821 if (ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram)) {
00822 return;
00823 }
00824
00825 if (!ec_fsm_coe_success(fsm->fsm_coe)) {
00826 EC_SLAVE_ERR(fsm->slave, "SDO configuration failed.\n");
00827 fsm->slave->error_flag = 1;
00828 fsm->state = ec_fsm_slave_config_state_error;
00829 return;
00830 }
00831
00832 if (!fsm->slave->config) {
00833 ec_fsm_slave_config_reconfigure(fsm);
00834 return;
00835 }
00836
00837
00838 if (fsm->request->list.next != &fsm->slave->config->sdo_configs) {
00839 fsm->request = list_entry(fsm->request->list.next,
00840 ec_sdo_request_t, list);
00841 ec_sdo_request_copy(&fsm->request_copy, fsm->request);
00842 ecrt_sdo_request_write(&fsm->request_copy);
00843 ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
00844 ec_fsm_coe_exec(fsm->fsm_coe, fsm->datagram);
00845 return;
00846 }
00847
00848
00849 ec_fsm_slave_config_enter_soe_conf_preop(fsm);
00850 }
00851
00852
00853
00856 void ec_fsm_slave_config_enter_soe_conf_preop(
00857 ec_fsm_slave_config_t *fsm
00858 )
00859 {
00860 ec_slave_t *slave = fsm->slave;
00861 ec_soe_request_t *req;
00862
00863 if (!slave->config) {
00864 ec_fsm_slave_config_enter_pdo_sync(fsm);
00865 return;
00866 }
00867
00868 list_for_each_entry(req, &slave->config->soe_configs, list) {
00869 if (req->al_state == EC_AL_STATE_PREOP) {
00870
00871 fsm->state = ec_fsm_slave_config_state_soe_conf_preop;
00872 fsm->soe_request = req;
00873 ec_soe_request_copy(&fsm->soe_request_copy, fsm->soe_request);
00874 ec_soe_request_write(&fsm->soe_request_copy);
00875 ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
00876 &fsm->soe_request_copy);
00877 ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
00878 return;
00879 }
00880 }
00881
00882
00883 ec_fsm_slave_config_enter_pdo_conf(fsm);
00884 }
00885
00886
00887
00890 void ec_fsm_slave_config_state_soe_conf_preop(
00891 ec_fsm_slave_config_t *fsm
00892 )
00893 {
00894 ec_slave_t *slave = fsm->slave;
00895
00896 if (ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram)) {
00897 return;
00898 }
00899
00900 if (!ec_fsm_soe_success(fsm->fsm_soe)) {
00901 EC_SLAVE_ERR(slave, "SoE configuration failed.\n");
00902 fsm->slave->error_flag = 1;
00903 fsm->state = ec_fsm_slave_config_state_error;
00904 return;
00905 }
00906
00907 if (!fsm->slave->config) {
00908 ec_fsm_slave_config_reconfigure(fsm);
00909 return;
00910 }
00911
00912
00913 while (fsm->soe_request->list.next != &fsm->slave->config->soe_configs) {
00914 fsm->soe_request = list_entry(fsm->soe_request->list.next,
00915 ec_soe_request_t, list);
00916 if (fsm->soe_request->al_state == EC_AL_STATE_PREOP) {
00917 ec_soe_request_copy(&fsm->soe_request_copy, fsm->soe_request);
00918 ec_soe_request_write(&fsm->soe_request_copy);
00919 ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
00920 &fsm->soe_request_copy);
00921 ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
00922 return;
00923 }
00924 }
00925
00926
00927 ec_fsm_slave_config_enter_pdo_conf(fsm);
00928 }
00929
00930
00931
00934 void ec_fsm_slave_config_enter_pdo_conf(
00935 ec_fsm_slave_config_t *fsm
00936 )
00937 {
00938
00939 ec_fsm_pdo_start_configuration(fsm->fsm_pdo, fsm->slave);
00940 fsm->state = ec_fsm_slave_config_state_pdo_conf;
00941 fsm->state(fsm);
00942 }
00943
00944
00945
00948 void ec_fsm_slave_config_state_pdo_conf(
00949 ec_fsm_slave_config_t *fsm
00950 )
00951 {
00952
00953
00954 if (ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram)) {
00955 return;
00956 }
00957
00958 if (!fsm->slave->config) {
00959 ec_fsm_slave_config_reconfigure(fsm);
00960 return;
00961 }
00962
00963 if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
00964 EC_SLAVE_WARN(fsm->slave, "PDO configuration failed.\n");
00965 }
00966
00967 ec_fsm_slave_config_enter_watchdog_divider(fsm);
00968 }
00969
00970
00971
00974 void ec_fsm_slave_config_enter_watchdog_divider(
00975 ec_fsm_slave_config_t *fsm
00976 )
00977 {
00978 ec_slave_t *slave = fsm->slave;
00979 ec_datagram_t *datagram = fsm->datagram;
00980 ec_slave_config_t *config = slave->config;
00981
00982 if (config && config->watchdog_divider) {
00983 EC_SLAVE_DBG(slave, 1, "Setting watchdog divider to %u.\n",
00984 config->watchdog_divider);
00985
00986 ec_datagram_fpwr(datagram, slave->station_address, 0x0400, 2);
00987 EC_WRITE_U16(datagram->data, config->watchdog_divider);
00988 fsm->retries = EC_FSM_RETRIES;
00989 fsm->state = ec_fsm_slave_config_state_watchdog_divider;
00990 } else {
00991 ec_fsm_slave_config_enter_watchdog(fsm);
00992 }
00993 }
00994
00995
00996
00999 void ec_fsm_slave_config_state_watchdog_divider(
01000 ec_fsm_slave_config_t *fsm
01001 )
01002 {
01003 ec_datagram_t *datagram = fsm->datagram;
01004 ec_slave_t *slave = fsm->slave;
01005
01006 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01007 return;
01008
01009 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01010 fsm->state = ec_fsm_slave_config_state_error;
01011 EC_SLAVE_ERR(slave, "Failed to receive watchdog divider"
01012 " configuration datagram: ");
01013 ec_datagram_print_state(datagram);
01014 return;
01015 }
01016
01017 if (datagram->working_counter != 1) {
01018 slave->error_flag = 1;
01019 EC_SLAVE_WARN(slave, "Failed to set watchdog divider: ");
01020 ec_datagram_print_wc_error(datagram);
01021 return;
01022 }
01023
01024 ec_fsm_slave_config_enter_watchdog(fsm);
01025 }
01026
01027
01028
01031 void ec_fsm_slave_config_enter_watchdog(
01032 ec_fsm_slave_config_t *fsm
01033 )
01034 {
01035 ec_datagram_t *datagram = fsm->datagram;
01036 ec_slave_t *slave = fsm->slave;
01037 ec_slave_config_t *config = slave->config;
01038
01039 if (config && config->watchdog_intervals) {
01040 EC_SLAVE_DBG(slave, 1, "Setting process data"
01041 " watchdog intervals to %u.\n", config->watchdog_intervals);
01042
01043 ec_datagram_fpwr(datagram, slave->station_address, 0x0420, 2);
01044 EC_WRITE_U16(datagram->data, config->watchdog_intervals);
01045
01046 fsm->retries = EC_FSM_RETRIES;
01047 fsm->state = ec_fsm_slave_config_state_watchdog;
01048 } else {
01049 ec_fsm_slave_config_enter_pdo_sync(fsm);
01050 }
01051 }
01052
01053
01054
01058 void ec_fsm_slave_config_state_watchdog(
01059 ec_fsm_slave_config_t *fsm
01060 )
01061 {
01062 ec_datagram_t *datagram = fsm->datagram;
01063 ec_slave_t *slave = fsm->slave;
01064
01065 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01066 return;
01067
01068 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01069 fsm->state = ec_fsm_slave_config_state_error;
01070 EC_SLAVE_ERR(slave, "Failed to receive sync manager"
01071 " watchdog configuration datagram: ");
01072 ec_datagram_print_state(datagram);
01073 return;
01074 }
01075
01076 if (datagram->working_counter != 1) {
01077 EC_SLAVE_WARN(slave, "Failed to set process data"
01078 " watchdog intervals: ");
01079 ec_datagram_print_wc_error(datagram);
01080 }
01081
01082 ec_fsm_slave_config_enter_pdo_sync(fsm);
01083 }
01084
01085
01086
01089 void ec_fsm_slave_config_enter_pdo_sync(
01090 ec_fsm_slave_config_t *fsm
01091 )
01092 {
01093 ec_slave_t *slave = fsm->slave;
01094 ec_datagram_t *datagram = fsm->datagram;
01095 unsigned int i, j, offset, num_pdo_syncs;
01096 uint8_t sync_index;
01097 const ec_sync_t *sync;
01098 uint16_t size;
01099
01100 if (slave->sii.mailbox_protocols) {
01101 offset = 2;
01102 } else {
01103 offset = 0;
01104 }
01105
01106 if (slave->sii.sync_count <= offset) {
01107
01108 ec_fsm_slave_config_enter_fmmu(fsm);
01109 return;
01110 }
01111
01112 num_pdo_syncs = slave->sii.sync_count - offset;
01113
01114
01115 ec_datagram_fpwr(datagram, slave->station_address,
01116 0x0800 + EC_SYNC_PAGE_SIZE * offset,
01117 EC_SYNC_PAGE_SIZE * num_pdo_syncs);
01118 ec_datagram_zero(datagram);
01119
01120 for (i = 0; i < num_pdo_syncs; i++) {
01121 const ec_sync_config_t *sync_config;
01122 uint8_t pdo_xfer = 0;
01123 sync_index = i + offset;
01124 sync = &slave->sii.syncs[sync_index];
01125
01126 if (slave->config) {
01127 const ec_slave_config_t *sc = slave->config;
01128 sync_config = &sc->sync_configs[sync_index];
01129 size = ec_pdo_list_total_size(&sync_config->pdos);
01130
01131
01132
01133 for (j = 0; j < sc->used_fmmus; j++) {
01134 if (sc->fmmu_configs[j].sync_index == sync_index) {
01135 pdo_xfer = 1;
01136 break;
01137 }
01138 }
01139
01140 } else {
01141 sync_config = NULL;
01142 size = sync->default_length;
01143 }
01144
01145 ec_sync_page(sync, sync_index, size, sync_config, pdo_xfer,
01146 datagram->data + EC_SYNC_PAGE_SIZE * i);
01147 }
01148
01149 fsm->retries = EC_FSM_RETRIES;
01150 fsm->state = ec_fsm_slave_config_state_pdo_sync;
01151 }
01152
01153
01154
01157 void ec_fsm_slave_config_state_pdo_sync(
01158 ec_fsm_slave_config_t *fsm
01159 )
01160 {
01161 ec_datagram_t *datagram = fsm->datagram;
01162 ec_slave_t *slave = fsm->slave;
01163
01164 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01165 return;
01166
01167 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01168 fsm->state = ec_fsm_slave_config_state_error;
01169 EC_SLAVE_ERR(slave, "Failed to receive process data sync"
01170 " manager configuration datagram: ");
01171 ec_datagram_print_state(datagram);
01172 return;
01173 }
01174
01175 if (datagram->working_counter != 1) {
01176 slave->error_flag = 1;
01177 fsm->state = ec_fsm_slave_config_state_error;
01178 EC_SLAVE_ERR(slave, "Failed to set process data sync managers: ");
01179 ec_datagram_print_wc_error(datagram);
01180 return;
01181 }
01182
01183 ec_fsm_slave_config_enter_fmmu(fsm);
01184 }
01185
01186
01187
01190 void ec_fsm_slave_config_enter_fmmu(
01191 ec_fsm_slave_config_t *fsm
01192 )
01193 {
01194 ec_slave_t *slave = fsm->slave;
01195 ec_datagram_t *datagram = fsm->datagram;
01196 unsigned int i;
01197 const ec_fmmu_config_t *fmmu;
01198 const ec_sync_t *sync;
01199
01200 if (!slave->config) {
01201 ec_fsm_slave_config_enter_safeop(fsm);
01202 return;
01203 }
01204
01205 if (slave->base_fmmu_count < slave->config->used_fmmus) {
01206 slave->error_flag = 1;
01207 fsm->state = ec_fsm_slave_config_state_error;
01208 EC_SLAVE_ERR(slave, "Slave has less FMMUs (%u)"
01209 " than requested (%u).\n", slave->base_fmmu_count,
01210 slave->config->used_fmmus);
01211 return;
01212 }
01213
01214 if (!slave->base_fmmu_count) {
01215 ec_fsm_slave_config_enter_dc_cycle(fsm);
01216 return;
01217 }
01218
01219
01220 ec_datagram_fpwr(datagram, slave->station_address,
01221 0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
01222 ec_datagram_zero(datagram);
01223 for (i = 0; i < slave->config->used_fmmus; i++) {
01224 fmmu = &slave->config->fmmu_configs[i];
01225 if (!(sync = ec_slave_get_sync(slave, fmmu->sync_index))) {
01226 slave->error_flag = 1;
01227 fsm->state = ec_fsm_slave_config_state_error;
01228 EC_SLAVE_ERR(slave, "Failed to determine PDO sync manager"
01229 " for FMMU!\n");
01230 return;
01231 }
01232 ec_fmmu_config_page(fmmu, sync,
01233 datagram->data + EC_FMMU_PAGE_SIZE * i);
01234 }
01235
01236 fsm->retries = EC_FSM_RETRIES;
01237 fsm->state = ec_fsm_slave_config_state_fmmu;
01238 }
01239
01240
01241
01244 void ec_fsm_slave_config_state_fmmu(
01245 ec_fsm_slave_config_t *fsm
01246 )
01247 {
01248 ec_datagram_t *datagram = fsm->datagram;
01249 ec_slave_t *slave = fsm->slave;
01250
01251 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01252 return;
01253
01254 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01255 fsm->state = ec_fsm_slave_config_state_error;
01256 EC_SLAVE_ERR(slave, "Failed to receive FMMUs datagram: ");
01257 ec_datagram_print_state(datagram);
01258 return;
01259 }
01260
01261 if (datagram->working_counter != 1) {
01262 slave->error_flag = 1;
01263 fsm->state = ec_fsm_slave_config_state_error;
01264 EC_SLAVE_ERR(slave, "Failed to set FMMUs: ");
01265 ec_datagram_print_wc_error(datagram);
01266 return;
01267 }
01268
01269 ec_fsm_slave_config_enter_dc_cycle(fsm);
01270 }
01271
01272
01273
01276 void ec_fsm_slave_config_enter_dc_cycle(
01277 ec_fsm_slave_config_t *fsm
01278 )
01279 {
01280 ec_datagram_t *datagram = fsm->datagram;
01281 ec_slave_t *slave = fsm->slave;
01282 ec_slave_config_t *config = slave->config;
01283
01284 if (!config) {
01285 ec_fsm_slave_config_reconfigure(fsm);
01286 return;
01287 }
01288
01289 if (config->dc_assign_activate) {
01290 if (!slave->base_dc_supported || !slave->has_dc_system_time) {
01291 EC_SLAVE_WARN(slave, "Slave seems not to support"
01292 " distributed clocks!\n");
01293 }
01294
01295 EC_SLAVE_DBG(slave, 1, "Setting DC cycle times to %u / %u.\n",
01296 config->dc_sync[0].cycle_time, config->dc_sync[1].cycle_time);
01297
01298
01299 ec_datagram_fpwr(datagram, slave->station_address, 0x09A0, 8);
01300 EC_WRITE_U32(datagram->data, config->dc_sync[0].cycle_time);
01301 EC_WRITE_U32(datagram->data + 4, config->dc_sync[1].cycle_time);
01302 fsm->retries = EC_FSM_RETRIES;
01303 fsm->state = ec_fsm_slave_config_state_dc_cycle;
01304 } else {
01305
01306 ec_fsm_slave_config_enter_safeop(fsm);
01307 }
01308 }
01309
01310
01311
01314 void ec_fsm_slave_config_state_dc_cycle(
01315 ec_fsm_slave_config_t *fsm
01316 )
01317 {
01318 ec_datagram_t *datagram = fsm->datagram;
01319 ec_slave_t *slave = fsm->slave;
01320 ec_slave_config_t *config = slave->config;
01321
01322 if (!config) {
01323 ec_fsm_slave_config_reconfigure(fsm);
01324 return;
01325 }
01326
01327 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01328 return;
01329
01330 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01331 fsm->state = ec_fsm_slave_config_state_error;
01332 EC_SLAVE_ERR(slave, "Failed to receive DC cycle times datagram: ");
01333 ec_datagram_print_state(datagram);
01334 return;
01335 }
01336
01337 if (datagram->working_counter != 1) {
01338 slave->error_flag = 1;
01339 fsm->state = ec_fsm_slave_config_state_error;
01340 EC_SLAVE_ERR(slave, "Failed to set DC cycle times: ");
01341 ec_datagram_print_wc_error(datagram);
01342 return;
01343 }
01344
01345 EC_SLAVE_DBG(slave, 1, "Checking for synchrony.\n");
01346
01347 fsm->jiffies_start = jiffies;
01348 ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4);
01349 fsm->retries = EC_FSM_RETRIES;
01350 fsm->state = ec_fsm_slave_config_state_dc_sync_check;
01351 }
01352
01353
01354
01357 void ec_fsm_slave_config_state_dc_sync_check(
01358 ec_fsm_slave_config_t *fsm
01359 )
01360 {
01361 ec_datagram_t *datagram = fsm->datagram;
01362 ec_slave_t *slave = fsm->slave;
01363 ec_master_t *master = slave->master;
01364 ec_slave_config_t *config = slave->config;
01365 uint32_t abs_sync_diff;
01366 unsigned long diff_ms;
01367 ec_sync_signal_t *sync0 = &config->dc_sync[0];
01368 u64 start_time;
01369
01370 if (!config) {
01371 ec_fsm_slave_config_reconfigure(fsm);
01372 return;
01373 }
01374
01375 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01376 return;
01377
01378 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01379 fsm->state = ec_fsm_slave_config_state_error;
01380 EC_SLAVE_ERR(slave, "Failed to receive DC sync check datagram: ");
01381 ec_datagram_print_state(datagram);
01382 return;
01383 }
01384
01385 if (datagram->working_counter != 1) {
01386 slave->error_flag = 1;
01387 fsm->state = ec_fsm_slave_config_state_error;
01388 EC_SLAVE_ERR(slave, "Failed to check DC synchrony: ");
01389 ec_datagram_print_wc_error(datagram);
01390 return;
01391 }
01392
01393 abs_sync_diff = EC_READ_U32(datagram->data) & 0x7fffffff;
01394 diff_ms = (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ;
01395
01396 if (abs_sync_diff > EC_DC_MAX_SYNC_DIFF_NS) {
01397
01398 if (diff_ms >= EC_DC_SYNC_WAIT_MS) {
01399 EC_SLAVE_WARN(slave, "Slave did not sync after %lu ms.\n",
01400 diff_ms);
01401 } else {
01402 EC_SLAVE_DBG(slave, 1, "Sync after %4lu ms: %10u ns\n",
01403 diff_ms, abs_sync_diff);
01404
01405
01406 ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4);
01407 fsm->retries = EC_FSM_RETRIES;
01408 return;
01409 }
01410 } else {
01411 EC_SLAVE_DBG(slave, 1, "%u ns difference after %lu ms.\n",
01412 abs_sync_diff, diff_ms);
01413 }
01414
01415
01416 start_time = master->app_time + EC_DC_START_OFFSET;
01417
01418
01419 if (sync0->cycle_time) {
01420
01421 if (master->has_app_time) {
01422 u64 diff, start;
01423 u32 remainder;
01424
01425 diff = start_time - master->app_start_time;
01426 remainder = do_div(diff, sync0->cycle_time);
01427
01428 start = start_time +
01429 sync0->cycle_time - remainder + sync0->shift_time;
01430
01431 EC_SLAVE_DBG(slave, 1, "app_start_time=%llu\n",
01432 master->app_start_time);
01433 EC_SLAVE_DBG(slave, 1, " app_time=%llu\n", master->app_time);
01434 EC_SLAVE_DBG(slave, 1, " start_time=%llu\n", start_time);
01435 EC_SLAVE_DBG(slave, 1, " cycle_time=%u\n", sync0->cycle_time);
01436 EC_SLAVE_DBG(slave, 1, " shift_time=%i\n", sync0->shift_time);
01437 EC_SLAVE_DBG(slave, 1, " remainder=%u\n", remainder);
01438 EC_SLAVE_DBG(slave, 1, " start=%llu\n", start);
01439 start_time = start;
01440 } else {
01441 EC_SLAVE_WARN(slave, "No application time supplied."
01442 " Cyclic start time will not be in phase.\n");
01443 }
01444 }
01445
01446 EC_SLAVE_DBG(slave, 1, "Setting DC cyclic operation"
01447 " start time to %llu.\n", start_time);
01448
01449 ec_datagram_fpwr(datagram, slave->station_address, 0x0990, 8);
01450 EC_WRITE_U64(datagram->data, start_time);
01451 fsm->retries = EC_FSM_RETRIES;
01452 fsm->state = ec_fsm_slave_config_state_dc_start;
01453 }
01454
01455
01456
01459 void ec_fsm_slave_config_state_dc_start(
01460 ec_fsm_slave_config_t *fsm
01461 )
01462 {
01463 ec_datagram_t *datagram = fsm->datagram;
01464 ec_slave_t *slave = fsm->slave;
01465 ec_slave_config_t *config = slave->config;
01466
01467 if (!config) {
01468 ec_fsm_slave_config_reconfigure(fsm);
01469 return;
01470 }
01471
01472 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01473 return;
01474
01475 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01476 fsm->state = ec_fsm_slave_config_state_error;
01477 EC_SLAVE_ERR(slave, "Failed to receive DC start time datagram: ");
01478 ec_datagram_print_state(datagram);
01479 return;
01480 }
01481
01482 if (datagram->working_counter != 1) {
01483 slave->error_flag = 1;
01484 fsm->state = ec_fsm_slave_config_state_error;
01485 EC_SLAVE_ERR(slave, "Failed to set DC start time: ");
01486 ec_datagram_print_wc_error(datagram);
01487 return;
01488 }
01489
01490 EC_SLAVE_DBG(slave, 1, "Setting DC AssignActivate to 0x%04x.\n",
01491 config->dc_assign_activate);
01492
01493
01494 ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
01495 EC_WRITE_U16(datagram->data, config->dc_assign_activate);
01496 fsm->retries = EC_FSM_RETRIES;
01497 fsm->state = ec_fsm_slave_config_state_dc_assign;
01498 }
01499
01500
01501
01504 void ec_fsm_slave_config_state_dc_assign(
01505 ec_fsm_slave_config_t *fsm
01506 )
01507 {
01508 ec_datagram_t *datagram = fsm->datagram;
01509 ec_slave_t *slave = fsm->slave;
01510
01511 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01512 return;
01513
01514 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01515 fsm->state = ec_fsm_slave_config_state_error;
01516 EC_SLAVE_ERR(slave, "Failed to receive DC activation datagram: ");
01517 ec_datagram_print_state(datagram);
01518 return;
01519 }
01520
01521 if (datagram->working_counter != 1) {
01522 slave->error_flag = 1;
01523 fsm->state = ec_fsm_slave_config_state_error;
01524 EC_SLAVE_ERR(slave, "Failed to activate DC: ");
01525 ec_datagram_print_wc_error(datagram);
01526 return;
01527 }
01528
01529 ec_fsm_slave_config_enter_safeop(fsm);
01530 }
01531
01532
01533
01536 void ec_fsm_slave_config_enter_safeop(
01537 ec_fsm_slave_config_t *fsm
01538 )
01539 {
01540 fsm->state = ec_fsm_slave_config_state_safeop;
01541 ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_SAFEOP);
01542 ec_fsm_change_exec(fsm->fsm_change);
01543 }
01544
01545
01546
01549 void ec_fsm_slave_config_state_safeop(
01550 ec_fsm_slave_config_t *fsm
01551 )
01552 {
01553 ec_slave_t *slave = fsm->slave;
01554
01555 if (ec_fsm_change_exec(fsm->fsm_change)) return;
01556
01557 if (!ec_fsm_change_success(fsm->fsm_change)) {
01558 if (!fsm->fsm_change->spontaneous_change)
01559 fsm->slave->error_flag = 1;
01560 fsm->state = ec_fsm_slave_config_state_error;
01561 return;
01562 }
01563
01564
01565
01566 EC_SLAVE_DBG(slave, 1, "Now in SAFEOP.\n");
01567
01568 if (fsm->slave->current_state == fsm->slave->requested_state) {
01569 fsm->state = ec_fsm_slave_config_state_end;
01570 EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
01571 return;
01572 }
01573
01574 ec_fsm_slave_config_enter_soe_conf_safeop(fsm);
01575 }
01576
01577
01578
01581 void ec_fsm_slave_config_enter_soe_conf_safeop(
01582 ec_fsm_slave_config_t *fsm
01583 )
01584 {
01585 ec_slave_t *slave = fsm->slave;
01586 ec_soe_request_t *req;
01587
01588 if (!slave->config) {
01589 ec_fsm_slave_config_enter_op(fsm);
01590 return;
01591 }
01592
01593 list_for_each_entry(req, &slave->config->soe_configs, list) {
01594 if (req->al_state == EC_AL_STATE_SAFEOP) {
01595
01596 fsm->state = ec_fsm_slave_config_state_soe_conf_safeop;
01597 fsm->soe_request = req;
01598 ec_soe_request_copy(&fsm->soe_request_copy, fsm->soe_request);
01599 ec_soe_request_write(&fsm->soe_request_copy);
01600 ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
01601 &fsm->soe_request_copy);
01602 ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
01603 return;
01604 }
01605 }
01606
01607
01608 ec_fsm_slave_config_enter_op(fsm);
01609 }
01610
01611
01612
01615 void ec_fsm_slave_config_state_soe_conf_safeop(
01616 ec_fsm_slave_config_t *fsm
01617 )
01618 {
01619 ec_slave_t *slave = fsm->slave;
01620
01621 if (ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram)) {
01622 return;
01623 }
01624
01625 if (!ec_fsm_soe_success(fsm->fsm_soe)) {
01626 EC_SLAVE_ERR(slave, "SoE configuration failed.\n");
01627 fsm->slave->error_flag = 1;
01628 fsm->state = ec_fsm_slave_config_state_error;
01629 return;
01630 }
01631
01632 if (!fsm->slave->config) {
01633 ec_fsm_slave_config_reconfigure(fsm);
01634 return;
01635 }
01636
01637
01638 while (fsm->soe_request->list.next != &fsm->slave->config->soe_configs) {
01639 fsm->soe_request = list_entry(fsm->soe_request->list.next,
01640 ec_soe_request_t, list);
01641 if (fsm->soe_request->al_state == EC_AL_STATE_SAFEOP) {
01642 ec_soe_request_copy(&fsm->soe_request_copy, fsm->soe_request);
01643 ec_soe_request_write(&fsm->soe_request_copy);
01644 ec_fsm_soe_transfer(fsm->fsm_soe, fsm->slave,
01645 &fsm->soe_request_copy);
01646 ec_fsm_soe_exec(fsm->fsm_soe, fsm->datagram);
01647 return;
01648 }
01649 }
01650
01651
01652 ec_fsm_slave_config_enter_op(fsm);
01653 }
01654
01655
01656
01659 void ec_fsm_slave_config_enter_op(
01660 ec_fsm_slave_config_t *fsm
01661 )
01662 {
01663
01664 fsm->state = ec_fsm_slave_config_state_op;
01665 ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_OP);
01666 ec_fsm_change_exec(fsm->fsm_change);
01667 }
01668
01669
01670
01673 void ec_fsm_slave_config_state_op(
01674 ec_fsm_slave_config_t *fsm
01675 )
01676 {
01677 ec_slave_t *slave = fsm->slave;
01678
01679 if (ec_fsm_change_exec(fsm->fsm_change)) return;
01680
01681 if (!ec_fsm_change_success(fsm->fsm_change)) {
01682 if (!fsm->fsm_change->spontaneous_change)
01683 slave->error_flag = 1;
01684 fsm->state = ec_fsm_slave_config_state_error;
01685 return;
01686 }
01687
01688
01689
01690 EC_SLAVE_DBG(slave, 1, "Now in OP. Finished configuration.\n");
01691
01692 fsm->state = ec_fsm_slave_config_state_end;
01693 }
01694
01695
01696
01699 void ec_fsm_slave_config_reconfigure(
01700 ec_fsm_slave_config_t *fsm
01701 )
01702 {
01703 EC_SLAVE_DBG(fsm->slave, 1, "Slave configuration detached during "
01704 "configuration. Reconfiguring.");
01705
01706 ec_fsm_slave_config_enter_init(fsm);
01707 }
01708
01709
01710
01711
01712
01715 void ec_fsm_slave_config_state_error(
01716 ec_fsm_slave_config_t *fsm
01717 )
01718 {
01719 }
01720
01721
01722
01725 void ec_fsm_slave_config_state_end(
01726 ec_fsm_slave_config_t *fsm
01727 )
01728 {
01729 }
01730
01731