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 "globals.h"
00038 #include "master.h"
00039 #include "mailbox.h"
00040 #include "slave_config.h"
00041
00042 #include "fsm_slave_scan.h"
00043
00044
00045
00046 void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *);
00047 void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *);
00048 void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *);
00049 void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *);
00050 void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *);
00051 void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *);
00052 void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *);
00053 #ifdef EC_SII_ASSIGN
00054 void ec_fsm_slave_scan_state_assign_sii(ec_fsm_slave_scan_t *);
00055 #endif
00056 void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *);
00057 void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *);
00058 #ifdef EC_REGALIAS
00059 void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *);
00060 #endif
00061 void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *);
00062 void ec_fsm_slave_scan_state_sync(ec_fsm_slave_scan_t *);
00063 void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *);
00064
00065 void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *);
00066 void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *);
00067
00068 void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *);
00069 #ifdef EC_REGALIAS
00070 void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *);
00071 #endif
00072 void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *);
00073 void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *);
00074
00075
00076
00079 void ec_fsm_slave_scan_init(
00080 ec_fsm_slave_scan_t *fsm,
00081 ec_datagram_t *datagram,
00082 ec_fsm_slave_config_t *fsm_slave_config,
00084 ec_fsm_pdo_t *fsm_pdo
00085 )
00086 {
00087 fsm->datagram = datagram;
00088 fsm->fsm_slave_config = fsm_slave_config;
00089 fsm->fsm_pdo = fsm_pdo;
00090
00091
00092 ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
00093 }
00094
00095
00096
00099 void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *fsm )
00100 {
00101
00102 ec_fsm_sii_clear(&fsm->fsm_sii);
00103 }
00104
00105
00106
00111 void ec_fsm_slave_scan_start(
00112 ec_fsm_slave_scan_t *fsm,
00113 ec_slave_t *slave
00114 )
00115 {
00116 fsm->slave = slave;
00117 fsm->state = ec_fsm_slave_scan_state_start;
00118 }
00119
00120
00121
00126 int ec_fsm_slave_scan_running(const ec_fsm_slave_scan_t *fsm )
00127 {
00128 return fsm->state != ec_fsm_slave_scan_state_end
00129 && fsm->state != ec_fsm_slave_scan_state_error;
00130 }
00131
00132
00133
00141 int ec_fsm_slave_scan_exec(ec_fsm_slave_scan_t *fsm )
00142 {
00143 if (fsm->datagram->state == EC_DATAGRAM_SENT
00144 || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
00145
00146 return ec_fsm_slave_scan_running(fsm);
00147 }
00148
00149 fsm->state(fsm);
00150 return ec_fsm_slave_scan_running(fsm);
00151 }
00152
00153
00154
00159 int ec_fsm_slave_scan_success(const ec_fsm_slave_scan_t *fsm )
00160 {
00161 return fsm->state == ec_fsm_slave_scan_state_end;
00162 }
00163
00164
00165
00166
00167
00174 void ec_fsm_slave_scan_state_start(ec_fsm_slave_scan_t *fsm )
00175 {
00176
00177 ec_datagram_apwr(fsm->datagram, fsm->slave->ring_position, 0x0010, 2);
00178 EC_WRITE_U16(fsm->datagram->data, fsm->slave->station_address);
00179 fsm->retries = EC_FSM_RETRIES;
00180 fsm->state = ec_fsm_slave_scan_state_address;
00181 }
00182
00183
00184
00189 void ec_fsm_slave_scan_state_address(
00190 ec_fsm_slave_scan_t *fsm
00191 )
00192 {
00193 ec_datagram_t *datagram = fsm->datagram;
00194
00195 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00196 return;
00197
00198 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00199 fsm->state = ec_fsm_slave_scan_state_error;
00200 EC_SLAVE_ERR(fsm->slave,
00201 "Failed to receive station address datagram: ");
00202 ec_datagram_print_state(datagram);
00203 return;
00204 }
00205
00206 if (datagram->working_counter != 1) {
00207 fsm->slave->error_flag = 1;
00208 fsm->state = ec_fsm_slave_scan_state_error;
00209 EC_SLAVE_ERR(fsm->slave, "Failed to write station address: ");
00210 ec_datagram_print_wc_error(datagram);
00211 return;
00212 }
00213
00214
00215 ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0130, 2);
00216 ec_datagram_zero(datagram);
00217 fsm->retries = EC_FSM_RETRIES;
00218 fsm->state = ec_fsm_slave_scan_state_state;
00219 }
00220
00221
00222
00227 void ec_fsm_slave_scan_state_state(
00228 ec_fsm_slave_scan_t *fsm
00229 )
00230 {
00231 ec_datagram_t *datagram = fsm->datagram;
00232 ec_slave_t *slave = fsm->slave;
00233
00234 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00235 return;
00236
00237 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00238 fsm->state = ec_fsm_slave_scan_state_error;
00239 EC_SLAVE_ERR(slave, "Failed to receive AL state datagram: ");
00240 ec_datagram_print_state(datagram);
00241 return;
00242 }
00243
00244 if (datagram->working_counter != 1) {
00245 fsm->slave->error_flag = 1;
00246 fsm->state = ec_fsm_slave_scan_state_error;
00247 EC_SLAVE_ERR(slave, "Failed to read AL state: ");
00248 ec_datagram_print_wc_error(datagram);
00249 return;
00250 }
00251
00252 slave->current_state = EC_READ_U8(datagram->data);
00253 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
00254 char state_str[EC_STATE_STRING_SIZE];
00255 ec_state_string(slave->current_state, state_str, 0);
00256 EC_SLAVE_WARN(slave, "Slave has state error bit set (%s)!\n",
00257 state_str);
00258 }
00259
00260
00261 ec_datagram_fprd(datagram, fsm->slave->station_address, 0x0000, 12);
00262 ec_datagram_zero(datagram);
00263 fsm->retries = EC_FSM_RETRIES;
00264 fsm->state = ec_fsm_slave_scan_state_base;
00265 }
00266
00267
00268
00271 void ec_fsm_slave_scan_state_base(
00272 ec_fsm_slave_scan_t *fsm
00273 )
00274 {
00275 ec_datagram_t *datagram = fsm->datagram;
00276 ec_slave_t *slave = fsm->slave;
00277 u8 octet;
00278 int i;
00279
00280 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00281 return;
00282
00283 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00284 fsm->state = ec_fsm_slave_scan_state_error;
00285 EC_SLAVE_ERR(slave, "Failed to receive base data datagram: ");
00286 ec_datagram_print_state(datagram);
00287 return;
00288 }
00289
00290 if (datagram->working_counter != 1) {
00291 fsm->slave->error_flag = 1;
00292 fsm->state = ec_fsm_slave_scan_state_error;
00293 EC_SLAVE_ERR(slave, "Failed to read base data: ");
00294 ec_datagram_print_wc_error(datagram);
00295 return;
00296 }
00297
00298 slave->base_type = EC_READ_U8 (datagram->data);
00299 slave->base_revision = EC_READ_U8 (datagram->data + 1);
00300 slave->base_build = EC_READ_U16(datagram->data + 2);
00301
00302 slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
00303 if (slave->base_fmmu_count > EC_MAX_FMMUS) {
00304 EC_SLAVE_WARN(slave, "Slave has more FMMUs (%u) than the master can"
00305 " handle (%u).\n", slave->base_fmmu_count, EC_MAX_FMMUS);
00306 slave->base_fmmu_count = EC_MAX_FMMUS;
00307 }
00308
00309 slave->base_sync_count = EC_READ_U8(datagram->data + 5);
00310 if (slave->base_sync_count > EC_MAX_SYNC_MANAGERS) {
00311 EC_SLAVE_WARN(slave, "Slave provides more sync managers (%u)"
00312 " than the master can handle (%u).\n",
00313 slave->base_sync_count, EC_MAX_SYNC_MANAGERS);
00314 slave->base_sync_count = EC_MAX_SYNC_MANAGERS;
00315 }
00316
00317 octet = EC_READ_U8(datagram->data + 7);
00318 for (i = 0; i < EC_MAX_PORTS; i++) {
00319 slave->ports[i].desc = (octet >> (2 * i)) & 0x03;
00320 }
00321
00322 octet = EC_READ_U8(datagram->data + 8);
00323 slave->base_fmmu_bit_operation = octet & 0x01;
00324 slave->base_dc_supported = (octet >> 2) & 0x01;
00325 slave->base_dc_range = ((octet >> 3) & 0x01) ? EC_DC_64 : EC_DC_32;
00326
00327 if (slave->base_dc_supported) {
00328
00329 ec_datagram_fprd(datagram, slave->station_address, 0x0910,
00330 slave->base_dc_range == EC_DC_64 ? 8 : 4);
00331 ec_datagram_zero(datagram);
00332 fsm->retries = EC_FSM_RETRIES;
00333 fsm->state = ec_fsm_slave_scan_state_dc_cap;
00334 } else {
00335 ec_fsm_slave_scan_enter_datalink(fsm);
00336 }
00337 }
00338
00339
00340
00345 void ec_fsm_slave_scan_state_dc_cap(
00346 ec_fsm_slave_scan_t *fsm
00347 )
00348 {
00349 ec_datagram_t *datagram = fsm->datagram;
00350 ec_slave_t *slave = fsm->slave;
00351
00352 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00353 return;
00354
00355 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00356 fsm->state = ec_fsm_slave_scan_state_error;
00357 EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
00358 ec_datagram_print_state(datagram);
00359 return;
00360 }
00361
00362 if (datagram->working_counter == 1) {
00363 slave->has_dc_system_time = 1;
00364 EC_SLAVE_DBG(slave, 1, "Slave has the System Time register.\n");
00365 } else if (datagram->working_counter == 0) {
00366 EC_SLAVE_DBG(slave, 1, "Slave has no System Time register; delay "
00367 "measurement only.\n");
00368 } else {
00369 fsm->slave->error_flag = 1;
00370 fsm->state = ec_fsm_slave_scan_state_error;
00371 EC_SLAVE_ERR(slave, "Failed to determine, if system time register is "
00372 "supported: ");
00373 ec_datagram_print_wc_error(datagram);
00374 return;
00375 }
00376
00377
00378 ec_datagram_fprd(datagram, slave->station_address, 0x0900, 16);
00379 ec_datagram_zero(datagram);
00380 fsm->retries = EC_FSM_RETRIES;
00381 fsm->state = ec_fsm_slave_scan_state_dc_times;
00382 }
00383
00384
00385
00390 void ec_fsm_slave_scan_state_dc_times(
00391 ec_fsm_slave_scan_t *fsm
00392 )
00393 {
00394 ec_datagram_t *datagram = fsm->datagram;
00395 ec_slave_t *slave = fsm->slave;
00396 int i;
00397
00398 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00399 return;
00400
00401 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00402 fsm->state = ec_fsm_slave_scan_state_error;
00403 EC_SLAVE_ERR(slave, "Failed to receive system time datagram: ");
00404 ec_datagram_print_state(datagram);
00405 return;
00406 }
00407
00408 if (datagram->working_counter != 1) {
00409 fsm->slave->error_flag = 1;
00410 fsm->state = ec_fsm_slave_scan_state_error;
00411 EC_SLAVE_ERR(slave, "Failed to get DC receive times: ");
00412 ec_datagram_print_wc_error(datagram);
00413 return;
00414 }
00415
00416 for (i = 0; i < EC_MAX_PORTS; i++) {
00417 slave->ports[i].receive_time = EC_READ_U32(datagram->data + 4 * i);
00418 }
00419
00420 ec_fsm_slave_scan_enter_datalink(fsm);
00421 }
00422
00423
00424
00429 void ec_fsm_slave_scan_enter_datalink(
00430 ec_fsm_slave_scan_t *fsm
00431 )
00432 {
00433 ec_datagram_t *datagram = fsm->datagram;
00434 ec_slave_t *slave = fsm->slave;
00435
00436
00437 ec_datagram_fprd(datagram, slave->station_address, 0x0110, 2);
00438 ec_datagram_zero(datagram);
00439 fsm->retries = EC_FSM_RETRIES;
00440 fsm->state = ec_fsm_slave_scan_state_datalink;
00441 }
00442
00443
00444
00447 void ec_fsm_slave_scan_enter_sii_size(
00448 ec_fsm_slave_scan_t *fsm
00449 )
00450 {
00451
00452
00453 fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET;
00454 ec_fsm_sii_read(&fsm->fsm_sii, fsm->slave, fsm->sii_offset,
00455 EC_FSM_SII_USE_CONFIGURED_ADDRESS);
00456 fsm->state = ec_fsm_slave_scan_state_sii_size;
00457 fsm->state(fsm);
00458 }
00459
00460
00461
00462 #ifdef EC_SII_ASSIGN
00463
00466 void ec_fsm_slave_scan_enter_assign_sii(
00467 ec_fsm_slave_scan_t *fsm
00468 )
00469 {
00470 ec_datagram_t *datagram = fsm->datagram;
00471 ec_slave_t *slave = fsm->slave;
00472
00473 EC_SLAVE_DBG(slave, 1, "Assigning SII access to EtherCAT.\n");
00474
00475
00476 ec_datagram_fpwr(datagram, slave->station_address, 0x0500, 1);
00477 EC_WRITE_U8(datagram->data, 0x00);
00478 fsm->retries = EC_FSM_RETRIES;
00479 fsm->state = ec_fsm_slave_scan_state_assign_sii;
00480 }
00481
00482 #endif
00483
00484
00485
00490 void ec_fsm_slave_scan_state_datalink(
00491 ec_fsm_slave_scan_t *fsm
00492 )
00493 {
00494 ec_datagram_t *datagram = fsm->datagram;
00495 ec_slave_t *slave = fsm->slave;
00496 uint16_t dl_status;
00497 unsigned int i;
00498
00499 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00500 return;
00501
00502 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00503 fsm->state = ec_fsm_slave_scan_state_error;
00504 EC_SLAVE_ERR(slave, "Failed to receive DL status datagram: ");
00505 ec_datagram_print_state(datagram);
00506 return;
00507 }
00508
00509 if (datagram->working_counter != 1) {
00510 fsm->slave->error_flag = 1;
00511 fsm->state = ec_fsm_slave_scan_state_error;
00512 EC_SLAVE_ERR(slave, "Failed to read DL status: ");
00513 ec_datagram_print_wc_error(datagram);
00514 return;
00515 }
00516
00517 dl_status = EC_READ_U16(datagram->data);
00518 for (i = 0; i < EC_MAX_PORTS; i++) {
00519 slave->ports[i].link.link_up =
00520 dl_status & (1 << (4 + i)) ? 1 : 0;
00521 slave->ports[i].link.loop_closed =
00522 dl_status & (1 << (8 + i * 2)) ? 1 : 0;
00523 slave->ports[i].link.signal_detected =
00524 dl_status & (1 << (9 + i * 2)) ? 1 : 0;
00525 }
00526
00527 #ifdef EC_SII_ASSIGN
00528 ec_fsm_slave_scan_enter_assign_sii(fsm);
00529 #else
00530 ec_fsm_slave_scan_enter_sii_size(fsm);
00531 #endif
00532 }
00533
00534
00535
00536 #ifdef EC_SII_ASSIGN
00537
00542 void ec_fsm_slave_scan_state_assign_sii(
00543 ec_fsm_slave_scan_t *fsm
00544 )
00545 {
00546 ec_datagram_t *datagram = fsm->datagram;
00547 ec_slave_t *slave = fsm->slave;
00548
00549 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00550 return;
00551 }
00552
00553 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00554 EC_SLAVE_WARN(slave, "Failed to receive SII assignment datagram: ");
00555 ec_datagram_print_state(datagram);
00556
00557 goto continue_with_sii_size;
00558 }
00559
00560 if (datagram->working_counter != 1) {
00561 EC_SLAVE_WARN(slave, "Failed to assign SII to EtherCAT: ");
00562 ec_datagram_print_wc_error(datagram);
00563
00564 }
00565
00566 continue_with_sii_size:
00567 ec_fsm_slave_scan_enter_sii_size(fsm);
00568 }
00569
00570 #endif
00571
00572
00573
00578 void ec_fsm_slave_scan_state_sii_size(
00579 ec_fsm_slave_scan_t *fsm
00580 )
00581 {
00582 ec_slave_t *slave = fsm->slave;
00583 uint16_t cat_type, cat_size;
00584
00585 if (ec_fsm_sii_exec(&fsm->fsm_sii))
00586 return;
00587
00588 if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
00589 fsm->slave->error_flag = 1;
00590 fsm->state = ec_fsm_slave_scan_state_error;
00591 EC_SLAVE_ERR(slave, "Failed to determine SII content size:"
00592 " Reading word offset 0x%04x failed. Assuming %u words.\n",
00593 fsm->sii_offset, EC_FIRST_SII_CATEGORY_OFFSET);
00594 slave->sii_nwords = EC_FIRST_SII_CATEGORY_OFFSET;
00595 goto alloc_sii;
00596 }
00597
00598 cat_type = EC_READ_U16(fsm->fsm_sii.value);
00599 cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
00600
00601 if (cat_type != 0xFFFF) {
00602 off_t next_offset = 2UL + fsm->sii_offset + cat_size;
00603 if (next_offset >= EC_MAX_SII_SIZE) {
00604 EC_SLAVE_WARN(slave, "SII size exceeds %u words"
00605 " (0xffff limiter missing?).\n", EC_MAX_SII_SIZE);
00606
00607 slave->sii_nwords = EC_FIRST_SII_CATEGORY_OFFSET;
00608 goto alloc_sii;
00609 }
00610 fsm->sii_offset = next_offset;
00611 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
00612 EC_FSM_SII_USE_CONFIGURED_ADDRESS);
00613 ec_fsm_sii_exec(&fsm->fsm_sii);
00614 return;
00615 }
00616
00617 slave->sii_nwords = fsm->sii_offset + 1;
00618
00619 alloc_sii:
00620 if (slave->sii_words) {
00621 EC_SLAVE_WARN(slave, "Freeing old SII data...\n");
00622 kfree(slave->sii_words);
00623 }
00624
00625 if (!(slave->sii_words =
00626 (uint16_t *) kmalloc(slave->sii_nwords * 2, GFP_KERNEL))) {
00627 EC_SLAVE_ERR(slave, "Failed to allocate %zu words of SII data.\n",
00628 slave->sii_nwords);
00629 slave->sii_nwords = 0;
00630 slave->error_flag = 1;
00631 fsm->state = ec_fsm_slave_scan_state_error;
00632 return;
00633 }
00634
00635
00636
00637 fsm->state = ec_fsm_slave_scan_state_sii_data;
00638 fsm->sii_offset = 0x0000;
00639 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
00640 EC_FSM_SII_USE_CONFIGURED_ADDRESS);
00641 ec_fsm_sii_exec(&fsm->fsm_sii);
00642 }
00643
00644
00645
00650 void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *fsm )
00651 {
00652 ec_slave_t *slave = fsm->slave;
00653 uint16_t *cat_word, cat_type, cat_size;
00654
00655 if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
00656
00657 if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
00658 fsm->slave->error_flag = 1;
00659 fsm->state = ec_fsm_slave_scan_state_error;
00660 EC_SLAVE_ERR(slave, "Failed to fetch SII contents.\n");
00661 return;
00662 }
00663
00664
00665
00666 if (fsm->sii_offset + 2 <= slave->sii_nwords) {
00667 memcpy(slave->sii_words + fsm->sii_offset, fsm->fsm_sii.value, 4);
00668 } else {
00669 memcpy(slave->sii_words + fsm->sii_offset, fsm->fsm_sii.value, 2);
00670 }
00671
00672 if (fsm->sii_offset + 2 < slave->sii_nwords) {
00673
00674 fsm->sii_offset += 2;
00675 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
00676 EC_FSM_SII_USE_CONFIGURED_ADDRESS);
00677 ec_fsm_sii_exec(&fsm->fsm_sii);
00678 return;
00679 }
00680
00681
00682
00683 ec_slave_clear_sync_managers(slave);
00684
00685 slave->sii.alias =
00686 EC_READ_U16(slave->sii_words + 0x0004);
00687 slave->effective_alias = slave->sii.alias;
00688 slave->sii.vendor_id =
00689 EC_READ_U32(slave->sii_words + 0x0008);
00690 slave->sii.product_code =
00691 EC_READ_U32(slave->sii_words + 0x000A);
00692 slave->sii.revision_number =
00693 EC_READ_U32(slave->sii_words + 0x000C);
00694 slave->sii.serial_number =
00695 EC_READ_U32(slave->sii_words + 0x000E);
00696 slave->sii.boot_rx_mailbox_offset =
00697 EC_READ_U16(slave->sii_words + 0x0014);
00698 slave->sii.boot_rx_mailbox_size =
00699 EC_READ_U16(slave->sii_words + 0x0015);
00700 slave->sii.boot_tx_mailbox_offset =
00701 EC_READ_U16(slave->sii_words + 0x0016);
00702 slave->sii.boot_tx_mailbox_size =
00703 EC_READ_U16(slave->sii_words + 0x0017);
00704 slave->sii.std_rx_mailbox_offset =
00705 EC_READ_U16(slave->sii_words + 0x0018);
00706 slave->sii.std_rx_mailbox_size =
00707 EC_READ_U16(slave->sii_words + 0x0019);
00708 slave->sii.std_tx_mailbox_offset =
00709 EC_READ_U16(slave->sii_words + 0x001A);
00710 slave->sii.std_tx_mailbox_size =
00711 EC_READ_U16(slave->sii_words + 0x001B);
00712 slave->sii.mailbox_protocols =
00713 EC_READ_U16(slave->sii_words + 0x001C);
00714
00715 if (slave->sii_nwords == EC_FIRST_SII_CATEGORY_OFFSET) {
00716
00717 fsm->state = ec_fsm_slave_scan_state_end;
00718 return;
00719 }
00720
00721 if (slave->sii_nwords < EC_FIRST_SII_CATEGORY_OFFSET + 1) {
00722 EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
00723 " First category header missing.\n");
00724 goto end;
00725 }
00726
00727
00728 cat_word = slave->sii_words + EC_FIRST_SII_CATEGORY_OFFSET;
00729 while (EC_READ_U16(cat_word) != 0xFFFF) {
00730
00731
00732 if (cat_word + 2 - slave->sii_words > slave->sii_nwords) {
00733 EC_SLAVE_ERR(slave, "Unexpected end of SII data:"
00734 " Category header incomplete.\n");
00735 goto end;
00736 }
00737
00738 cat_type = EC_READ_U16(cat_word) & 0x7FFF;
00739 cat_size = EC_READ_U16(cat_word + 1);
00740 cat_word += 2;
00741
00742 if (cat_word + cat_size - slave->sii_words > slave->sii_nwords) {
00743 EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
00744 " Category data incomplete.\n");
00745 goto end;
00746 }
00747
00748 switch (cat_type) {
00749 case 0x000A:
00750 if (ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word,
00751 cat_size * 2))
00752 goto end;
00753 break;
00754 case 0x001E:
00755 if (ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word,
00756 cat_size * 2))
00757 goto end;
00758 break;
00759 case 0x0028:
00760 break;
00761 case 0x0029:
00762 if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,
00763 cat_size * 2))
00764 goto end;
00765 break;
00766 case 0x0032:
00767 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
00768 cat_size * 2, EC_DIR_INPUT))
00769 goto end;
00770 break;
00771 case 0x0033:
00772 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
00773 cat_size * 2, EC_DIR_OUTPUT))
00774 goto end;
00775 break;
00776 default:
00777 EC_SLAVE_DBG(slave, 1, "Unknown category type 0x%04X.\n",
00778 cat_type);
00779 }
00780
00781 cat_word += cat_size;
00782 if (cat_word - slave->sii_words >= slave->sii_nwords) {
00783 EC_SLAVE_WARN(slave, "Unexpected end of SII data:"
00784 " Next category header missing.\n");
00785 goto end;
00786 }
00787 }
00788
00789 #ifdef EC_REGALIAS
00790 ec_fsm_slave_scan_enter_regalias(fsm);
00791 #else
00792 if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
00793 ec_fsm_slave_scan_enter_preop(fsm);
00794 } else {
00795 fsm->state = ec_fsm_slave_scan_state_end;
00796 }
00797 #endif
00798 return;
00799
00800 end:
00801 EC_SLAVE_ERR(slave, "Failed to analyze category data.\n");
00802 fsm->slave->error_flag = 1;
00803 fsm->state = ec_fsm_slave_scan_state_error;
00804 }
00805
00806
00807
00808 #ifdef EC_REGALIAS
00809
00812 void ec_fsm_slave_scan_enter_regalias(
00813 ec_fsm_slave_scan_t *fsm
00814 )
00815 {
00816 ec_datagram_t *datagram = fsm->datagram;
00817 ec_slave_t *slave = fsm->slave;
00818
00819
00820 EC_SLAVE_DBG(slave, 1, "Reading alias from register.\n");
00821 ec_datagram_fprd(datagram, slave->station_address, 0x0012, 2);
00822 ec_datagram_zero(datagram);
00823 fsm->retries = EC_FSM_RETRIES;
00824 fsm->state = ec_fsm_slave_scan_state_regalias;
00825 }
00826
00827
00828
00831 void ec_fsm_slave_scan_state_regalias(
00832 ec_fsm_slave_scan_t *fsm
00833 )
00834 {
00835 ec_datagram_t *datagram = fsm->datagram;
00836 ec_slave_t *slave = fsm->slave;
00837
00838 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00839 return;
00840
00841 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00842 fsm->state = ec_fsm_slave_scan_state_error;
00843 EC_SLAVE_ERR(slave, "Failed to receive register alias datagram: ");
00844 ec_datagram_print_state(datagram);
00845 return;
00846 }
00847
00848 if (datagram->working_counter != 1) {
00849 EC_SLAVE_DBG(slave, 1, "Failed to read register alias.\n");
00850 } else {
00851 slave->effective_alias = EC_READ_U16(datagram->data);
00852 EC_SLAVE_DBG(slave, 1, "Read alias %u from register.\n",
00853 slave->effective_alias);
00854 }
00855
00856 if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
00857 ec_fsm_slave_scan_enter_preop(fsm);
00858 } else {
00859 fsm->state = ec_fsm_slave_scan_state_end;
00860 }
00861 }
00862
00863 #endif // defined EC_REGALIAS
00864
00865
00866
00869 void ec_fsm_slave_scan_enter_preop(
00870 ec_fsm_slave_scan_t *fsm
00871 )
00872 {
00873 ec_slave_t *slave = fsm->slave;
00874 uint8_t current_state = slave->current_state & EC_SLAVE_STATE_MASK;
00875
00876 if (current_state != EC_SLAVE_STATE_PREOP
00877 && current_state != EC_SLAVE_STATE_SAFEOP
00878 && current_state != EC_SLAVE_STATE_OP) {
00879 if (slave->master->debug_level) {
00880 char str[EC_STATE_STRING_SIZE];
00881 ec_state_string(current_state, str, 0);
00882 EC_SLAVE_DBG(slave, 0, "Slave is not in the state"
00883 " to do mailbox com (%s), setting to PREOP.\n", str);
00884 }
00885
00886 fsm->state = ec_fsm_slave_scan_state_preop;
00887 ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
00888 ec_fsm_slave_config_start(fsm->fsm_slave_config, slave);
00889 ec_fsm_slave_config_exec(fsm->fsm_slave_config);
00890 } else {
00891 EC_SLAVE_DBG(slave, 1, "Reading mailbox"
00892 " sync manager configuration.\n");
00893
00894
00895
00896 ec_datagram_fprd(fsm->datagram, slave->station_address, 0x0800,
00897 EC_SYNC_PAGE_SIZE * 2);
00898 fsm->retries = EC_FSM_RETRIES;
00899 fsm->state = ec_fsm_slave_scan_state_sync;
00900 }
00901 }
00902
00903
00904
00907 void ec_fsm_slave_scan_state_preop(
00908 ec_fsm_slave_scan_t *fsm
00909 )
00910 {
00911 if (ec_fsm_slave_config_exec(fsm->fsm_slave_config))
00912 return;
00913
00914 if (!ec_fsm_slave_config_success(fsm->fsm_slave_config)) {
00915 fsm->state = ec_fsm_slave_scan_state_error;
00916 return;
00917 }
00918
00919 ec_fsm_slave_scan_enter_pdos(fsm);
00920 }
00921
00922
00923
00926 void ec_fsm_slave_scan_state_sync(
00927 ec_fsm_slave_scan_t *fsm
00928 )
00929 {
00930 ec_datagram_t *datagram = fsm->datagram;
00931 ec_slave_t *slave = fsm->slave;
00932
00933 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
00934 return;
00935
00936 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00937 fsm->state = ec_fsm_slave_scan_state_error;
00938 EC_SLAVE_ERR(slave, "Failed to receive sync manager"
00939 " configuration datagram: ");
00940 ec_datagram_print_state(datagram);
00941 return;
00942 }
00943
00944 if (datagram->working_counter != 1) {
00945 fsm->slave->error_flag = 1;
00946 fsm->state = ec_fsm_slave_scan_state_error;
00947 EC_SLAVE_ERR(slave, "Failed to read DL status: ");
00948 ec_datagram_print_wc_error(datagram);
00949 return;
00950 }
00951
00952 slave->configured_rx_mailbox_offset = EC_READ_U16(datagram->data);
00953 slave->configured_rx_mailbox_size = EC_READ_U16(datagram->data + 2);
00954 slave->configured_tx_mailbox_offset = EC_READ_U16(datagram->data + 8);
00955 slave->configured_tx_mailbox_size = EC_READ_U16(datagram->data + 10);
00956
00957 EC_SLAVE_DBG(slave, 1, "Mailbox configuration:\n");
00958 EC_SLAVE_DBG(slave, 1, " RX offset=0x%04x size=%u\n",
00959 slave->configured_rx_mailbox_offset,
00960 slave->configured_rx_mailbox_size);
00961 EC_SLAVE_DBG(slave, 1, " TX offset=0x%04x size=%u\n",
00962 slave->configured_tx_mailbox_offset,
00963 slave->configured_tx_mailbox_size);
00964
00965 ec_fsm_slave_scan_enter_pdos(fsm);
00966 }
00967
00968
00969
00972 void ec_fsm_slave_scan_enter_pdos(
00973 ec_fsm_slave_scan_t *fsm
00974 )
00975 {
00976 ec_slave_t *slave = fsm->slave;
00977
00978 EC_SLAVE_DBG(slave, 1, "Scanning PDO assignment and mapping.\n");
00979 fsm->state = ec_fsm_slave_scan_state_pdos;
00980 ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave);
00981 ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram);
00982 }
00983
00984
00985
00988 void ec_fsm_slave_scan_state_pdos(
00989 ec_fsm_slave_scan_t *fsm
00990 )
00991 {
00992 if (ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram)) {
00993 return;
00994 }
00995
00996 if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
00997 fsm->state = ec_fsm_slave_scan_state_error;
00998 return;
00999 }
01000
01001
01002 fsm->state = ec_fsm_slave_scan_state_end;
01003 }
01004
01005
01006
01007
01008
01011 void ec_fsm_slave_scan_state_error(
01012 ec_fsm_slave_scan_t *fsm
01013 )
01014 {
01015 }
01016
01017
01018
01021 void ec_fsm_slave_scan_state_end(
01022 ec_fsm_slave_scan_t *fsm
01023 )
01024 {
01025 }
01026
01027