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
00030
00031
00032
00033
00039
00040
00041 #include "globals.h"
00042 #include "fsm.h"
00043 #include "master.h"
00044 #include "mailbox.h"
00045
00046
00047
00048 void ec_fsm_master_start(ec_fsm_t *);
00049 void ec_fsm_master_broadcast(ec_fsm_t *);
00050 void ec_fsm_master_read_states(ec_fsm_t *);
00051 void ec_fsm_master_validate_vendor(ec_fsm_t *);
00052 void ec_fsm_master_validate_product(ec_fsm_t *);
00053 void ec_fsm_master_rewrite_addresses(ec_fsm_t *);
00054 void ec_fsm_master_configure_slave(ec_fsm_t *);
00055 void ec_fsm_master_scan_slaves(ec_fsm_t *);
00056 void ec_fsm_master_write_eeprom(ec_fsm_t *);
00057
00058 void ec_fsm_startup_start(ec_fsm_t *);
00059 void ec_fsm_startup_broadcast(ec_fsm_t *);
00060 void ec_fsm_startup_scan(ec_fsm_t *);
00061
00062 void ec_fsm_configuration_start(ec_fsm_t *);
00063 void ec_fsm_configuration_conf(ec_fsm_t *);
00064
00065 void ec_fsm_slavescan_start(ec_fsm_t *);
00066 void ec_fsm_slavescan_address(ec_fsm_t *);
00067 void ec_fsm_slavescan_state(ec_fsm_t *);
00068 void ec_fsm_slavescan_base(ec_fsm_t *);
00069 void ec_fsm_slavescan_datalink(ec_fsm_t *);
00070 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *);
00071 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *);
00072
00073 void ec_fsm_slaveconf_init(ec_fsm_t *);
00074 void ec_fsm_slaveconf_sync(ec_fsm_t *);
00075 void ec_fsm_slaveconf_preop(ec_fsm_t *);
00076 void ec_fsm_slaveconf_fmmu(ec_fsm_t *);
00077 void ec_fsm_slaveconf_sdoconf(ec_fsm_t *);
00078 void ec_fsm_slaveconf_saveop(ec_fsm_t *);
00079 void ec_fsm_slaveconf_op(ec_fsm_t *);
00080
00081 void ec_fsm_sii_start_reading(ec_fsm_t *);
00082 void ec_fsm_sii_read_check(ec_fsm_t *);
00083 void ec_fsm_sii_read_fetch(ec_fsm_t *);
00084 void ec_fsm_sii_start_writing(ec_fsm_t *);
00085 void ec_fsm_sii_write_check(ec_fsm_t *);
00086 void ec_fsm_sii_write_check2(ec_fsm_t *);
00087
00088 void ec_fsm_change_start(ec_fsm_t *);
00089 void ec_fsm_change_check(ec_fsm_t *);
00090 void ec_fsm_change_status(ec_fsm_t *);
00091 void ec_fsm_change_code(ec_fsm_t *);
00092 void ec_fsm_change_ack(ec_fsm_t *);
00093 void ec_fsm_change_check_ack(ec_fsm_t *);
00094
00095 void ec_fsm_coe_down_start(ec_fsm_t *);
00096 void ec_fsm_coe_down_request(ec_fsm_t *);
00097 void ec_fsm_coe_down_check(ec_fsm_t *);
00098 void ec_fsm_coe_down_response(ec_fsm_t *);
00099
00100 void ec_fsm_end(ec_fsm_t *);
00101 void ec_fsm_error(ec_fsm_t *);
00102
00103 void ec_canopen_abort_msg(uint32_t);
00104
00105
00106
00111 int ec_fsm_init(ec_fsm_t *fsm,
00112 ec_master_t *master
00113 )
00114 {
00115 fsm->master = master;
00116 fsm->master_state = ec_fsm_master_start;
00117 fsm->master_slaves_responding = 0;
00118 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
00119 fsm->master_validation = 0;
00120
00121 ec_datagram_init(&fsm->datagram);
00122 if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) {
00123 EC_ERR("Failed to allocate FSM datagram.\n");
00124 return -1;
00125 }
00126
00127 return 0;
00128 }
00129
00130
00131
00136 void ec_fsm_clear(ec_fsm_t *fsm )
00137 {
00138 ec_datagram_clear(&fsm->datagram);
00139 }
00140
00141
00142
00147 void ec_fsm_reset(ec_fsm_t *fsm )
00148 {
00149 fsm->master_state = ec_fsm_master_start;
00150 fsm->master_slaves_responding = 0;
00151 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
00152 }
00153
00154
00155
00160 void ec_fsm_execute(ec_fsm_t *fsm )
00161 {
00162 fsm->master_state(fsm);
00163 }
00164
00165
00166
00171 void ec_fsm_startup(ec_fsm_t *fsm)
00172 {
00173 fsm->master_state = ec_fsm_startup_start;
00174 }
00175
00176
00177
00183 int ec_fsm_startup_running(ec_fsm_t *fsm )
00184 {
00185 return fsm->master_state != ec_fsm_end &&
00186 fsm->master_state != ec_fsm_error;
00187 }
00188
00189
00190
00196 int ec_fsm_startup_success(ec_fsm_t *fsm )
00197 {
00198 return fsm->master_state == ec_fsm_end;
00199 }
00200
00201
00202
00207 void ec_fsm_configuration(ec_fsm_t *fsm)
00208 {
00209 fsm->master_state = ec_fsm_configuration_start;
00210 }
00211
00212
00213
00219 int ec_fsm_configuration_running(ec_fsm_t *fsm )
00220 {
00221 return fsm->master_state != ec_fsm_end &&
00222 fsm->master_state != ec_fsm_error;
00223 }
00224
00225
00226
00232 int ec_fsm_configuration_success(ec_fsm_t *fsm )
00233 {
00234 return fsm->master_state == ec_fsm_end;
00235 }
00236
00237
00238
00239
00240
00246 void ec_fsm_startup_start(ec_fsm_t *fsm)
00247 {
00248 ec_datagram_brd(&fsm->datagram, 0x0130, 2);
00249 ec_master_queue_datagram(fsm->master, &fsm->datagram);
00250 fsm->master_state = ec_fsm_startup_broadcast;
00251 }
00252
00253
00254
00260 void ec_fsm_startup_broadcast(ec_fsm_t *fsm )
00261 {
00262 ec_datagram_t *datagram = &fsm->datagram;
00263 unsigned int i;
00264 ec_slave_t *slave;
00265 ec_master_t *master = fsm->master;
00266
00267 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00268 EC_ERR("Failed tor receive broadcast datagram.\n");
00269 fsm->master_state = ec_fsm_error;
00270 return;
00271 }
00272
00273 EC_INFO("Scanning bus.\n");
00274
00275 ec_master_clear_slaves(master);
00276
00277 master->slave_count = datagram->working_counter;
00278
00279 if (!master->slave_count) {
00280
00281 fsm->master_state = ec_fsm_end;
00282 return;
00283 }
00284
00285
00286 for (i = 0; i < master->slave_count; i++) {
00287 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t),
00288 GFP_KERNEL))) {
00289 EC_ERR("Failed to allocate slave %i!\n", i);
00290 fsm->master_state = ec_fsm_error;
00291 return;
00292 }
00293
00294 if (ec_slave_init(slave, master, i, i + 1)) {
00295 fsm->master_state = ec_fsm_error;
00296 return;
00297 }
00298
00299 if (kobject_add(&slave->kobj)) {
00300 EC_ERR("Failed to add kobject.\n");
00301 kobject_put(&slave->kobj);
00302 fsm->master_state = ec_fsm_error;
00303 return;
00304 }
00305
00306 list_add_tail(&slave->list, &master->slaves);
00307 }
00308
00309
00310 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00311 fsm->slave_state = ec_fsm_slavescan_start;
00312 fsm->master_state = ec_fsm_startup_scan;
00313 fsm->master_state(fsm);
00314 return;
00315 }
00316
00317
00318
00324 void ec_fsm_startup_scan(ec_fsm_t *fsm )
00325 {
00326 ec_master_t *master = fsm->master;
00327 ec_slave_t *slave = fsm->slave;
00328
00329 fsm->slave_state(fsm);
00330
00331 if (fsm->slave_state == ec_fsm_error) {
00332 EC_ERR("Slave scanning failed.\n");
00333 fsm->master_state = ec_fsm_error;
00334 return;
00335 }
00336
00337 if (fsm->slave_state != ec_fsm_end) return;
00338
00339
00340 if (slave->list.next != &master->slaves) {
00341 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00342 fsm->slave_state = ec_fsm_slavescan_start;
00343 fsm->slave_state(fsm);
00344 return;
00345 }
00346
00347 EC_INFO("Bus scanning completed.\n");
00348
00349 ec_master_calc_addressing(master);
00350
00351 fsm->master_state = ec_fsm_end;
00352 }
00353
00354
00355
00356
00357
00362 void ec_fsm_configuration_start(ec_fsm_t *fsm )
00363 {
00364 ec_master_t *master = fsm->master;
00365
00366 if (list_empty(&master->slaves)) {
00367 fsm->master_state = ec_fsm_end;
00368 return;
00369 }
00370
00371
00372 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00373 fsm->slave_state = ec_fsm_slaveconf_init;
00374 fsm->change_new = EC_SLAVE_STATE_INIT;
00375 fsm->change_state = ec_fsm_change_start;
00376 fsm->master_state = ec_fsm_configuration_conf;
00377 fsm->master_state(fsm);
00378 }
00379
00380
00381
00386 void ec_fsm_configuration_conf(ec_fsm_t *fsm )
00387 {
00388 ec_master_t *master = fsm->master;
00389 ec_slave_t *slave = fsm->slave;
00390
00391 fsm->slave_state(fsm);
00392
00393 if (fsm->slave_state == ec_fsm_error) {
00394 fsm->master_state = ec_fsm_error;
00395 return;
00396 }
00397
00398 if (fsm->slave_state != ec_fsm_end) return;
00399
00400
00401 if (slave->list.next != &master->slaves) {
00402 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00403 fsm->slave_state = ec_fsm_slaveconf_init;
00404 fsm->change_new = EC_SLAVE_STATE_INIT;
00405 fsm->change_state = ec_fsm_change_start;
00406 fsm->master_state(fsm);
00407 return;
00408 }
00409
00410 fsm->master_state = ec_fsm_end;
00411 }
00412
00413
00414
00415
00416
00422 void ec_fsm_master_start(ec_fsm_t *fsm)
00423 {
00424 ec_datagram_brd(&fsm->datagram, 0x0130, 2);
00425 ec_master_queue_datagram(fsm->master, &fsm->datagram);
00426 fsm->master_state = ec_fsm_master_broadcast;
00427 }
00428
00429
00430
00436 void ec_fsm_master_broadcast(ec_fsm_t *fsm )
00437 {
00438 ec_datagram_t *datagram = &fsm->datagram;
00439 unsigned int topology_change, states_change, i;
00440 ec_slave_t *slave;
00441 ec_master_t *master = fsm->master;
00442
00443 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00444 if (!master->device->link_state) {
00445 fsm->master_slaves_responding = 0;
00446 list_for_each_entry(slave, &master->slaves, list) {
00447 slave->online = 0;
00448 }
00449 }
00450 fsm->master_state = ec_fsm_master_start;
00451 fsm->master_state(fsm);
00452 return;
00453 }
00454
00455 topology_change = (datagram->working_counter !=
00456 fsm->master_slaves_responding);
00457 states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states);
00458
00459 fsm->master_slave_states = EC_READ_U8(datagram->data);
00460 fsm->master_slaves_responding = datagram->working_counter;
00461
00462 if (topology_change) {
00463 EC_INFO("%i slave%s responding.\n",
00464 fsm->master_slaves_responding,
00465 fsm->master_slaves_responding == 1 ? "" : "s");
00466
00467 if (master->mode == EC_MASTER_MODE_OPERATION) {
00468 if (fsm->master_slaves_responding == master->slave_count) {
00469 fsm->master_validation = 1;
00470 }
00471 else {
00472 EC_WARN("Invalid slave count. Bus in tainted state.\n");
00473 }
00474 }
00475 }
00476
00477 if (states_change) {
00478 char states[25];
00479 ec_state_string(fsm->master_slave_states, states);
00480 EC_INFO("Slave states: %s.\n", states);
00481 }
00482
00483
00484 if (topology_change && master->mode == EC_MASTER_MODE_IDLE) {
00485 EC_INFO("Scanning bus.\n");
00486
00487 ec_master_eoe_stop(master);
00488 ec_master_clear_slaves(master);
00489
00490 master->slave_count = datagram->working_counter;
00491
00492 if (!master->slave_count) {
00493
00494 fsm->master_state = ec_fsm_master_start;
00495 fsm->master_state(fsm);
00496 return;
00497 }
00498
00499
00500 for (i = 0; i < master->slave_count; i++) {
00501 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t),
00502 GFP_ATOMIC))) {
00503 EC_ERR("Failed to allocate slave %i!\n", i);
00504 ec_master_clear_slaves(master);
00505 fsm->master_state = ec_fsm_master_start;
00506 fsm->master_state(fsm);
00507 return;
00508 }
00509
00510 if (ec_slave_init(slave, master, i, i + 1)) {
00511
00512 ec_master_clear_slaves(master);
00513 fsm->master_state = ec_fsm_master_start;
00514 fsm->master_state(fsm);
00515 return;
00516 }
00517
00518 if (kobject_add(&slave->kobj)) {
00519 EC_ERR("Failed to add kobject.\n");
00520 kobject_put(&slave->kobj);
00521 ec_master_clear_slaves(master);
00522 fsm->master_state = ec_fsm_master_start;
00523 fsm->master_state(fsm);
00524 return;
00525 }
00526
00527 list_add_tail(&slave->list, &master->slaves);
00528 }
00529
00530
00531 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00532 fsm->slave_state = ec_fsm_slavescan_start;
00533 fsm->master_state = ec_fsm_master_scan_slaves;
00534 fsm->master_state(fsm);
00535 return;
00536 }
00537
00538
00539 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00540 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2);
00541 ec_master_queue_datagram(master, &fsm->datagram);
00542 fsm->master_state = ec_fsm_master_read_states;
00543 }
00544
00545
00546
00552 void ec_fsm_master_action_process_states(ec_fsm_t *fsm
00554 )
00555 {
00556 ec_master_t *master = fsm->master;
00557 ec_slave_t *slave;
00558 char old_state[25], new_state[25];
00559
00560
00561 list_for_each_entry(slave, &master->slaves, list) {
00562 if (slave->error_flag ||
00563 !slave->online ||
00564 slave->requested_state == EC_SLAVE_STATE_UNKNOWN ||
00565 slave->current_state == slave->requested_state) continue;
00566
00567 ec_state_string(slave->current_state, old_state);
00568 ec_state_string(slave->requested_state, new_state);
00569 EC_INFO("Changing state of slave %i from %s to %s.\n",
00570 slave->ring_position, old_state, new_state);
00571
00572 fsm->slave = slave;
00573 fsm->slave_state = ec_fsm_slaveconf_init;
00574 fsm->change_new = EC_SLAVE_STATE_INIT;
00575 fsm->change_state = ec_fsm_change_start;
00576 fsm->master_state = ec_fsm_master_configure_slave;
00577 fsm->master_state(fsm);
00578 return;
00579 }
00580
00581
00582 ec_master_eoe_start(master);
00583
00584 if (master->mode == EC_MASTER_MODE_IDLE) {
00585
00586 list_for_each_entry(slave, &master->slaves, list) {
00587 if (!slave->new_eeprom_data) continue;
00588
00589 if (!slave->online || slave->error_flag) {
00590 kfree(slave->new_eeprom_data);
00591 slave->new_eeprom_data = NULL;
00592 EC_ERR("Discarding EEPROM data, slave %i not ready.\n",
00593 slave->ring_position);
00594 continue;
00595 }
00596
00597
00598 EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position);
00599 fsm->sii_offset = 0x0000;
00600 memcpy(fsm->sii_value, slave->new_eeprom_data, 2);
00601 fsm->sii_mode = 1;
00602 fsm->sii_state = ec_fsm_sii_start_writing;
00603 fsm->slave = slave;
00604 fsm->master_state = ec_fsm_master_write_eeprom;
00605 fsm->master_state(fsm);
00606 return;
00607 }
00608 }
00609
00610
00611 fsm->master_state = ec_fsm_master_start;
00612 fsm->master_state(fsm);
00613 }
00614
00615
00616
00621 void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm)
00623 {
00624 ec_master_t *master = fsm->master;
00625 ec_slave_t *slave = fsm->slave;
00626
00627
00628 if (slave->list.next != &master->slaves) {
00629
00630 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00631 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address,
00632 0x0130, 2);
00633 ec_master_queue_datagram(master, &fsm->datagram);
00634 fsm->master_state = ec_fsm_master_read_states;
00635 return;
00636 }
00637
00638
00639
00640
00641 if (fsm->master_validation) {
00642 fsm->master_validation = 0;
00643 list_for_each_entry(slave, &master->slaves, list) {
00644 if (slave->online) continue;
00645
00646
00647 EC_INFO("Validating bus.\n");
00648 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00649 fsm->master_state = ec_fsm_master_validate_vendor;
00650 fsm->sii_offset = 0x0008;
00651 fsm->sii_mode = 0;
00652 fsm->sii_state = ec_fsm_sii_start_reading;
00653 fsm->sii_state(fsm);
00654 return;
00655 }
00656 }
00657
00658 ec_fsm_master_action_process_states(fsm);
00659 }
00660
00661
00662
00668 void ec_fsm_master_read_states(ec_fsm_t *fsm )
00669 {
00670 ec_slave_t *slave = fsm->slave;
00671 ec_datagram_t *datagram = &fsm->datagram;
00672 uint8_t new_state;
00673
00674 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00675 fsm->master_state = ec_fsm_master_start;
00676 fsm->master_state(fsm);
00677 return;
00678 }
00679
00680
00681 if (datagram->working_counter != 1) {
00682 if (slave->online) {
00683 slave->online = 0;
00684 EC_INFO("Slave %i: offline.\n", slave->ring_position);
00685 }
00686 ec_fsm_master_action_next_slave_state(fsm);
00687 return;
00688 }
00689
00690
00691 new_state = EC_READ_U8(datagram->data);
00692 if (!slave->online) {
00693 char cur_state[25];
00694 slave->online = 1;
00695 slave->error_flag = 0;
00696 slave->current_state = new_state;
00697 ec_state_string(slave->current_state, cur_state);
00698 EC_INFO("Slave %i: online (%s).\n", slave->ring_position, cur_state);
00699 }
00700 else if (new_state != slave->current_state) {
00701 char old_state[25], cur_state[25];
00702 ec_state_string(slave->current_state, old_state);
00703 ec_state_string(new_state, cur_state);
00704 EC_INFO("Slave %i: %s -> %s.\n",
00705 slave->ring_position, old_state, cur_state);
00706 slave->current_state = new_state;
00707 }
00708
00709 ec_fsm_master_action_next_slave_state(fsm);
00710 }
00711
00712
00713
00719 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm )
00720 {
00721 ec_slave_t *slave = fsm->slave;
00722
00723 fsm->sii_state(fsm);
00724
00725 if (fsm->sii_state == ec_fsm_error) {
00726 fsm->slave->error_flag = 1;
00727 EC_ERR("Failed to validate vendor ID of slave %i.\n",
00728 slave->ring_position);
00729 fsm->master_state = ec_fsm_master_start;
00730 fsm->master_state(fsm);
00731 return;
00732 }
00733
00734 if (fsm->sii_state != ec_fsm_end) return;
00735
00736 if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) {
00737 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position);
00738 fsm->master_state = ec_fsm_master_start;
00739 fsm->master_state(fsm);
00740 return;
00741 }
00742
00743
00744 fsm->master_state = ec_fsm_master_validate_product;
00745 fsm->sii_offset = 0x000A;
00746 fsm->sii_mode = 0;
00747 fsm->sii_state = ec_fsm_sii_start_reading;
00748 fsm->sii_state(fsm);
00749 }
00750
00751
00752
00759 void ec_fsm_master_action_addresses(ec_fsm_t *fsm )
00760 {
00761 ec_datagram_t *datagram = &fsm->datagram;
00762
00763 while (fsm->slave->online) {
00764 if (fsm->slave->list.next == &fsm->master->slaves) {
00765 fsm->master_state = ec_fsm_master_start;
00766 fsm->master_state(fsm);
00767 return;
00768 }
00769
00770 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00771 }
00772
00773 EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position);
00774
00775
00776 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
00777 EC_WRITE_U16(datagram->data, fsm->slave->station_address);
00778 ec_master_queue_datagram(fsm->master, datagram);
00779 fsm->master_state = ec_fsm_master_rewrite_addresses;
00780 }
00781
00782
00783
00789 void ec_fsm_master_validate_product(ec_fsm_t *fsm )
00790 {
00791 ec_slave_t *slave = fsm->slave;
00792
00793 fsm->sii_state(fsm);
00794
00795 if (fsm->sii_state == ec_fsm_error) {
00796 fsm->slave->error_flag = 1;
00797 EC_ERR("Failed to validate product code of slave %i.\n",
00798 slave->ring_position);
00799 fsm->master_state = ec_fsm_master_start;
00800 fsm->master_state(fsm);
00801 return;
00802 }
00803
00804 if (fsm->sii_state != ec_fsm_end) return;
00805
00806 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) {
00807 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position);
00808 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code,
00809 EC_READ_U32(fsm->sii_value));
00810 fsm->master_state = ec_fsm_master_start;
00811 fsm->master_state(fsm);
00812 return;
00813 }
00814
00815
00816 if (slave->list.next == &fsm->master->slaves) {
00817 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list);
00818
00819 ec_fsm_master_action_addresses(fsm);
00820 return;
00821 }
00822
00823
00824 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00825 fsm->master_state = ec_fsm_master_validate_vendor;
00826 fsm->sii_offset = 0x0008;
00827 fsm->sii_mode = 0;
00828 fsm->sii_state = ec_fsm_sii_start_reading;
00829 fsm->sii_state(fsm);
00830 }
00831
00832
00833
00839 void ec_fsm_master_rewrite_addresses(ec_fsm_t *fsm
00841 )
00842 {
00843 ec_slave_t *slave = fsm->slave;
00844 ec_datagram_t *datagram = &fsm->datagram;
00845
00846 if (datagram->state != EC_DATAGRAM_RECEIVED
00847 || datagram->working_counter != 1) {
00848 EC_ERR("Failed to write station address on slave %i.\n",
00849 slave->ring_position);
00850 }
00851
00852 if (fsm->slave->list.next == &fsm->master->slaves) {
00853 fsm->master_state = ec_fsm_master_start;
00854 fsm->master_state(fsm);
00855 return;
00856 }
00857
00858
00859 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00860
00861 ec_fsm_master_action_addresses(fsm);
00862 }
00863
00864
00865
00871 void ec_fsm_master_scan_slaves(ec_fsm_t *fsm )
00872 {
00873 ec_master_t *master = fsm->master;
00874 ec_slave_t *slave = fsm->slave;
00875
00876
00877 fsm->slave_state(fsm);
00878
00879 if (fsm->slave_state != ec_fsm_end
00880 && fsm->slave_state != ec_fsm_error) return;
00881
00882
00883 if (slave->list.next != &master->slaves) {
00884 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00885 fsm->slave_state = ec_fsm_slavescan_start;
00886 fsm->slave_state(fsm);
00887 return;
00888 }
00889
00890 EC_INFO("Bus scanning completed.\n");
00891
00892 ec_master_calc_addressing(master);
00893
00894
00895 list_for_each_entry(slave, &master->slaves, list) {
00896 if (ec_slave_is_coupler(slave)) {
00897 slave->requested_state = EC_SLAVE_STATE_OP;
00898 }
00899 else {
00900 if (master->mode == EC_MASTER_MODE_OPERATION)
00901 slave->requested_state = EC_SLAVE_STATE_PREOP;
00902 else
00903 slave->requested_state = EC_SLAVE_STATE_INIT;
00904 }
00905 }
00906
00907 fsm->master_state = ec_fsm_master_start;
00908 fsm->master_state(fsm);
00909 }
00910
00911
00912
00918 void ec_fsm_master_configure_slave(ec_fsm_t *fsm
00920 )
00921 {
00922 fsm->slave_state(fsm);
00923
00924 if (fsm->slave_state != ec_fsm_end
00925 && fsm->slave_state != ec_fsm_error) return;
00926
00927 ec_fsm_master_action_process_states(fsm);
00928 }
00929
00930
00931
00936 void ec_fsm_master_write_eeprom(ec_fsm_t *fsm )
00937 {
00938 ec_slave_t *slave = fsm->slave;
00939
00940 fsm->sii_state(fsm);
00941
00942 if (fsm->sii_state == ec_fsm_error) {
00943 fsm->slave->error_flag = 1;
00944 EC_ERR("Failed to write EEPROM contents to slave %i.\n",
00945 slave->ring_position);
00946 kfree(slave->new_eeprom_data);
00947 slave->new_eeprom_data = NULL;
00948 fsm->master_state = ec_fsm_master_start;
00949 fsm->master_state(fsm);
00950 return;
00951 }
00952
00953 if (fsm->sii_state != ec_fsm_end) return;
00954
00955 fsm->sii_offset++;
00956 if (fsm->sii_offset < slave->new_eeprom_size) {
00957 memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2);
00958 fsm->sii_state = ec_fsm_sii_start_writing;
00959 fsm->sii_state(fsm);
00960 return;
00961 }
00962
00963
00964 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position);
00965 kfree(slave->new_eeprom_data);
00966 slave->new_eeprom_data = NULL;
00967
00968
00969
00970
00971 fsm->master_state = ec_fsm_master_start;
00972 fsm->master_state(fsm);
00973 return;
00974 }
00975
00976
00977
00978
00979
00986 void ec_fsm_slavescan_start(ec_fsm_t *fsm )
00987 {
00988 ec_datagram_t *datagram = &fsm->datagram;
00989
00990
00991 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
00992 EC_WRITE_U16(datagram->data, fsm->slave->station_address);
00993 ec_master_queue_datagram(fsm->master, datagram);
00994 fsm->slave_state = ec_fsm_slavescan_address;
00995 }
00996
00997
00998
01003 void ec_fsm_slavescan_address(ec_fsm_t *fsm )
01004 {
01005 ec_datagram_t *datagram = &fsm->datagram;
01006
01007 if (datagram->state != EC_DATAGRAM_RECEIVED
01008 || datagram->working_counter != 1) {
01009 fsm->slave->error_flag = 1;
01010 fsm->slave_state = ec_fsm_error;
01011 EC_ERR("Failed to write station address of slave %i.\n",
01012 fsm->slave->ring_position);
01013 return;
01014 }
01015
01016
01017 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2);
01018 ec_master_queue_datagram(fsm->master, datagram);
01019 fsm->slave_state = ec_fsm_slavescan_state;
01020 }
01021
01022
01023
01028 void ec_fsm_slavescan_state(ec_fsm_t *fsm )
01029 {
01030 ec_datagram_t *datagram = &fsm->datagram;
01031 ec_slave_t *slave = fsm->slave;
01032
01033 if (datagram->state != EC_DATAGRAM_RECEIVED
01034 || datagram->working_counter != 1) {
01035 fsm->slave->error_flag = 1;
01036 fsm->slave_state = ec_fsm_error;
01037 EC_ERR("Failed to read AL state of slave %i.\n",
01038 fsm->slave->ring_position);
01039 return;
01040 }
01041
01042 slave->current_state = EC_READ_U8(datagram->data);
01043 if (slave->current_state & EC_ACK) {
01044 EC_WARN("Slave %i has state error bit set (0x%02X)!\n",
01045 slave->ring_position, slave->current_state);
01046 slave->current_state &= 0x0F;
01047 }
01048
01049
01050 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6);
01051 ec_master_queue_datagram(fsm->master, datagram);
01052 fsm->slave_state = ec_fsm_slavescan_base;
01053 }
01054
01055
01056
01061 void ec_fsm_slavescan_base(ec_fsm_t *fsm )
01062 {
01063 ec_datagram_t *datagram = &fsm->datagram;
01064 ec_slave_t *slave = fsm->slave;
01065
01066 if (datagram->state != EC_DATAGRAM_RECEIVED
01067 || datagram->working_counter != 1) {
01068 fsm->slave->error_flag = 1;
01069 fsm->slave_state = ec_fsm_error;
01070 EC_ERR("Failed to read base data of slave %i.\n",
01071 slave->ring_position);
01072 return;
01073 }
01074
01075 slave->base_type = EC_READ_U8 (datagram->data);
01076 slave->base_revision = EC_READ_U8 (datagram->data + 1);
01077 slave->base_build = EC_READ_U16(datagram->data + 2);
01078 slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
01079 slave->base_sync_count = EC_READ_U8 (datagram->data + 5);
01080
01081 if (slave->base_fmmu_count > EC_MAX_FMMUS)
01082 slave->base_fmmu_count = EC_MAX_FMMUS;
01083
01084
01085 ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2);
01086 ec_master_queue_datagram(slave->master, datagram);
01087 fsm->slave_state = ec_fsm_slavescan_datalink;
01088 }
01089
01090
01091
01096 void ec_fsm_slavescan_datalink(ec_fsm_t *fsm )
01097 {
01098 ec_datagram_t *datagram = &fsm->datagram;
01099 ec_slave_t *slave = fsm->slave;
01100 uint16_t dl_status;
01101 unsigned int i;
01102
01103 if (datagram->state != EC_DATAGRAM_RECEIVED
01104 || datagram->working_counter != 1) {
01105 fsm->slave->error_flag = 1;
01106 fsm->slave_state = ec_fsm_error;
01107 EC_ERR("Failed to read DL status of slave %i.\n",
01108 slave->ring_position);
01109 return;
01110 }
01111
01112 dl_status = EC_READ_U16(datagram->data);
01113 for (i = 0; i < 4; i++) {
01114 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
01115 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
01116 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
01117 }
01118
01119
01120
01121 fsm->sii_offset = 0x0040;
01122 fsm->sii_mode = 1;
01123 fsm->sii_state = ec_fsm_sii_start_reading;
01124 fsm->slave_state = ec_fsm_slavescan_eeprom_size;
01125 fsm->slave_state(fsm);
01126 }
01127
01128
01129
01134 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *fsm )
01135 {
01136 ec_slave_t *slave = fsm->slave;
01137 uint16_t cat_type, cat_size;
01138
01139
01140 fsm->sii_state(fsm);
01141
01142 if (fsm->sii_state == ec_fsm_error) {
01143 fsm->slave->error_flag = 1;
01144 fsm->slave_state = ec_fsm_error;
01145 EC_ERR("Failed to read EEPROM size of slave %i.\n",
01146 slave->ring_position);
01147 return;
01148 }
01149
01150 if (fsm->sii_state != ec_fsm_end) return;
01151
01152 cat_type = EC_READ_U16(fsm->sii_value);
01153 cat_size = EC_READ_U16(fsm->sii_value + 2);
01154
01155 if (cat_type != 0xFFFF) {
01156 fsm->sii_offset += cat_size + 2;
01157 fsm->sii_state = ec_fsm_sii_start_reading;
01158 fsm->sii_state(fsm);
01159 return;
01160 }
01161
01162 slave->eeprom_size = (fsm->sii_offset + 1) * 2;
01163
01164 if (slave->eeprom_data) {
01165 EC_INFO("Freeing old EEPROM data on slave %i...\n",
01166 slave->ring_position);
01167 kfree(slave->eeprom_data);
01168 }
01169
01170 if (!(slave->eeprom_data =
01171 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
01172 fsm->slave->error_flag = 1;
01173 fsm->slave_state = ec_fsm_error;
01174 EC_ERR("Failed to allocate EEPROM data on slave %i.\n",
01175 slave->ring_position);
01176 return;
01177 }
01178
01179
01180
01181 fsm->sii_offset = 0x0000;
01182 fsm->sii_mode = 1;
01183 fsm->sii_state = ec_fsm_sii_start_reading;
01184 fsm->slave_state = ec_fsm_slavescan_eeprom_data;
01185 fsm->slave_state(fsm);
01186 }
01187
01188
01189
01194 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *fsm )
01195 {
01196 ec_slave_t *slave = fsm->slave;
01197 uint16_t *cat_word, cat_type, cat_size;
01198
01199
01200 fsm->sii_state(fsm);
01201
01202 if (fsm->sii_state == ec_fsm_error) {
01203 fsm->slave->error_flag = 1;
01204 fsm->slave_state = ec_fsm_error;
01205 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n",
01206 slave->ring_position);
01207 return;
01208 }
01209
01210 if (fsm->sii_state != ec_fsm_end) return;
01211
01212
01213
01214 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) {
01215 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4);
01216 }
01217 else {
01218 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 2);
01219 }
01220
01221 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) {
01222
01223 fsm->sii_offset += 2;
01224 fsm->sii_state = ec_fsm_sii_start_reading;
01225 fsm->sii_state(fsm);
01226 return;
01227 }
01228
01229
01230
01231 slave->sii_alias =
01232 EC_READ_U16(slave->eeprom_data + 2 * 0x0004);
01233 slave->sii_vendor_id =
01234 EC_READ_U32(slave->eeprom_data + 2 * 0x0008);
01235 slave->sii_product_code =
01236 EC_READ_U32(slave->eeprom_data + 2 * 0x000A);
01237 slave->sii_revision_number =
01238 EC_READ_U32(slave->eeprom_data + 2 * 0x000C);
01239 slave->sii_serial_number =
01240 EC_READ_U32(slave->eeprom_data + 2 * 0x000E);
01241 slave->sii_rx_mailbox_offset =
01242 EC_READ_U16(slave->eeprom_data + 2 * 0x0018);
01243 slave->sii_rx_mailbox_size =
01244 EC_READ_U16(slave->eeprom_data + 2 * 0x0019);
01245 slave->sii_tx_mailbox_offset =
01246 EC_READ_U16(slave->eeprom_data + 2 * 0x001A);
01247 slave->sii_tx_mailbox_size =
01248 EC_READ_U16(slave->eeprom_data + 2 * 0x001B);
01249 slave->sii_mailbox_protocols =
01250 EC_READ_U16(slave->eeprom_data + 2 * 0x001C);
01251
01252
01253 cat_word = (uint16_t *) slave->eeprom_data + 0x0040;
01254 while (EC_READ_U16(cat_word) != 0xFFFF) {
01255 cat_type = EC_READ_U16(cat_word) & 0x7FFF;
01256 cat_size = EC_READ_U16(cat_word + 1);
01257
01258 switch (cat_type) {
01259 case 0x000A:
01260 if (ec_slave_fetch_strings(slave, (uint8_t *) (cat_word + 2)))
01261 goto end;
01262 break;
01263 case 0x001E:
01264 ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2));
01265 break;
01266 case 0x0028:
01267 break;
01268 case 0x0029:
01269 if (ec_slave_fetch_sync(slave, (uint8_t *) (cat_word + 2),
01270 cat_size))
01271 goto end;
01272 break;
01273 case 0x0032:
01274 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
01275 cat_size, EC_TX_PDO))
01276 goto end;
01277 break;
01278 case 0x0033:
01279 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
01280 cat_size, EC_RX_PDO))
01281 goto end;
01282 break;
01283 default:
01284 EC_WARN("Unknown category type 0x%04X in slave %i.\n",
01285 cat_type, slave->ring_position);
01286 }
01287
01288 cat_word += cat_size + 2;
01289 }
01290
01291 fsm->slave_state = ec_fsm_end;
01292 return;
01293
01294 end:
01295 EC_ERR("Failed to analyze category data.\n");
01296 fsm->slave->error_flag = 1;
01297 fsm->slave_state = ec_fsm_error;
01298 }
01299
01300
01301
01302
01303
01308 void ec_fsm_slaveconf_init(ec_fsm_t *fsm )
01309 {
01310 ec_slave_t *slave = fsm->slave;
01311 ec_datagram_t *datagram = &fsm->datagram;
01312 const ec_sii_sync_t *sync;
01313
01314 fsm->change_state(fsm);
01315
01316 if (fsm->change_state == ec_fsm_error) {
01317 slave->error_flag = 1;
01318 fsm->slave_state = ec_fsm_error;
01319 return;
01320 }
01321
01322 if (fsm->change_state != ec_fsm_end) return;
01323
01324
01325 if (slave->current_state == slave->requested_state) {
01326 fsm->slave_state = ec_fsm_end;
01327 return;
01328 }
01329
01330
01331
01332
01333
01334 if (!slave->base_sync_count) {
01335 fsm->slave_state = ec_fsm_slaveconf_preop;
01336 fsm->change_new = EC_SLAVE_STATE_PREOP;
01337 fsm->change_state = ec_fsm_change_start;
01338 fsm->change_state(fsm);
01339 return;
01340 }
01341
01342
01343 ec_datagram_npwr(datagram, slave->station_address, 0x0800,
01344 EC_SYNC_SIZE * slave->base_sync_count);
01345 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
01346
01347 list_for_each_entry(sync, &slave->sii_syncs, list) {
01348 if (sync->index >= slave->base_sync_count) {
01349 EC_ERR("Invalid sync manager configuration found!");
01350 fsm->slave->error_flag = 1;
01351 fsm->slave_state = ec_fsm_error;
01352 return;
01353 }
01354 ec_sync_config(sync, slave,
01355 datagram->data + EC_SYNC_SIZE * sync->index);
01356 }
01357
01358 ec_master_queue_datagram(fsm->master, datagram);
01359 fsm->slave_state = ec_fsm_slaveconf_sync;
01360 }
01361
01362
01363
01368 void ec_fsm_slaveconf_sync(ec_fsm_t *fsm )
01369 {
01370 ec_datagram_t *datagram = &fsm->datagram;
01371 ec_slave_t *slave = fsm->slave;
01372
01373 if (datagram->state != EC_DATAGRAM_RECEIVED
01374 || datagram->working_counter != 1) {
01375 slave->error_flag = 1;
01376 fsm->slave_state = ec_fsm_error;
01377 EC_ERR("Failed to set sync managers on slave %i.\n",
01378 slave->ring_position);
01379 return;
01380 }
01381
01382 fsm->slave_state = ec_fsm_slaveconf_preop;
01383 fsm->change_new = EC_SLAVE_STATE_PREOP;
01384 fsm->change_state = ec_fsm_change_start;
01385 fsm->change_state(fsm);
01386 }
01387
01388
01389
01394 void ec_fsm_slaveconf_preop(ec_fsm_t *fsm )
01395 {
01396 ec_slave_t *slave = fsm->slave;
01397 ec_master_t *master = fsm->master;
01398 ec_datagram_t *datagram = &fsm->datagram;
01399 unsigned int j;
01400
01401 fsm->change_state(fsm);
01402
01403 if (fsm->change_state == ec_fsm_error) {
01404 slave->error_flag = 1;
01405 fsm->slave_state = ec_fsm_error;
01406 return;
01407 }
01408
01409 if (fsm->change_state != ec_fsm_end) return;
01410
01411
01412 if (slave->current_state == slave->requested_state) {
01413 fsm->slave_state = ec_fsm_end;
01414 return;
01415 }
01416
01417 if (!slave->base_fmmu_count) {
01418 if (list_empty(&slave->sdo_confs)) {
01419 fsm->slave_state = ec_fsm_slaveconf_saveop;
01420 fsm->change_new = EC_SLAVE_STATE_SAVEOP;
01421 fsm->change_state = ec_fsm_change_start;
01422 fsm->change_state(fsm);
01423 return;
01424 }
01425 fsm->slave_state = ec_fsm_slaveconf_sdoconf;
01426 fsm->sdodata = list_entry(slave->sdo_confs.next, ec_sdo_data_t, list);
01427 fsm->coe_state = ec_fsm_coe_down_start;
01428 fsm->coe_state(fsm);
01429 return;
01430 }
01431
01432
01433 ec_datagram_npwr(datagram, slave->station_address,
01434 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
01435 memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
01436 for (j = 0; j < slave->fmmu_count; j++) {
01437 ec_fmmu_config(&slave->fmmus[j], slave,
01438 datagram->data + EC_FMMU_SIZE * j);
01439 }
01440
01441 ec_master_queue_datagram(master, datagram);
01442 fsm->slave_state = ec_fsm_slaveconf_fmmu;
01443 }
01444
01445
01446
01451 void ec_fsm_slaveconf_fmmu(ec_fsm_t *fsm )
01452 {
01453 ec_datagram_t *datagram = &fsm->datagram;
01454 ec_slave_t *slave = fsm->slave;
01455
01456 if (datagram->state != EC_DATAGRAM_RECEIVED
01457 || datagram->working_counter != 1) {
01458 fsm->slave->error_flag = 1;
01459 fsm->slave_state = ec_fsm_error;
01460 EC_ERR("Failed to set FMMUs on slave %i.\n",
01461 fsm->slave->ring_position);
01462 return;
01463 }
01464
01465
01466 if (list_empty(&slave->sdo_confs)) {
01467
01468 fsm->slave_state = ec_fsm_slaveconf_saveop;
01469 fsm->change_new = EC_SLAVE_STATE_SAVEOP;
01470 fsm->change_state = ec_fsm_change_start;
01471 fsm->change_state(fsm);
01472 return;
01473 }
01474
01475 fsm->slave_state = ec_fsm_slaveconf_sdoconf;
01476 fsm->sdodata = list_entry(slave->sdo_confs.next, ec_sdo_data_t, list);
01477 fsm->coe_state = ec_fsm_coe_down_start;
01478 fsm->coe_state(fsm);
01479 }
01480
01481
01482
01487 void ec_fsm_slaveconf_sdoconf(ec_fsm_t *fsm )
01488 {
01489 fsm->coe_state(fsm);
01490
01491 if (fsm->coe_state == ec_fsm_error) {
01492 fsm->slave->error_flag = 1;
01493 fsm->slave_state = ec_fsm_error;
01494 return;
01495 }
01496
01497 if (fsm->coe_state != ec_fsm_end) return;
01498
01499
01500 if (fsm->sdodata->list.next != &fsm->slave->sdo_confs) {
01501 fsm->sdodata = list_entry(fsm->sdodata->list.next,
01502 ec_sdo_data_t, list);
01503 fsm->coe_state = ec_fsm_coe_down_start;
01504 fsm->coe_state(fsm);
01505 return;
01506 }
01507
01508
01509
01510
01511 fsm->slave_state = ec_fsm_slaveconf_saveop;
01512 fsm->change_new = EC_SLAVE_STATE_SAVEOP;
01513 fsm->change_state = ec_fsm_change_start;
01514 fsm->change_state(fsm);
01515 }
01516
01517
01518
01523 void ec_fsm_slaveconf_saveop(ec_fsm_t *fsm )
01524 {
01525 fsm->change_state(fsm);
01526
01527 if (fsm->change_state == ec_fsm_error) {
01528 fsm->slave->error_flag = 1;
01529 fsm->slave_state = ec_fsm_error;
01530 return;
01531 }
01532
01533 if (fsm->change_state != ec_fsm_end) return;
01534
01535
01536 if (fsm->slave->current_state == fsm->slave->requested_state) {
01537 fsm->slave_state = ec_fsm_end;
01538 return;
01539 }
01540
01541
01542 fsm->slave_state = ec_fsm_slaveconf_op;
01543 fsm->change_new = EC_SLAVE_STATE_OP;
01544 fsm->change_state = ec_fsm_change_start;
01545 fsm->change_state(fsm);
01546 }
01547
01548
01549
01554 void ec_fsm_slaveconf_op(ec_fsm_t *fsm )
01555 {
01556 fsm->change_state(fsm);
01557
01558 if (fsm->change_state == ec_fsm_error) {
01559 fsm->slave->error_flag = 1;
01560 fsm->slave_state = ec_fsm_error;
01561 return;
01562 }
01563
01564 if (fsm->change_state != ec_fsm_end) return;
01565
01566
01567 fsm->slave_state = ec_fsm_end;
01568 }
01569
01570
01571
01572
01573
01579 void ec_fsm_sii_start_reading(ec_fsm_t *fsm )
01580 {
01581 ec_datagram_t *datagram = &fsm->datagram;
01582
01583
01584 if (fsm->sii_mode) {
01585 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4);
01586 }
01587 else {
01588 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4);
01589 }
01590
01591 EC_WRITE_U8 (datagram->data, 0x00);
01592 EC_WRITE_U8 (datagram->data + 1, 0x01);
01593 EC_WRITE_U16(datagram->data + 2, fsm->sii_offset);
01594 ec_master_queue_datagram(fsm->master, datagram);
01595 fsm->sii_state = ec_fsm_sii_read_check;
01596 }
01597
01598
01599
01605 void ec_fsm_sii_read_check(ec_fsm_t *fsm )
01606 {
01607 ec_datagram_t *datagram = &fsm->datagram;
01608
01609 if (datagram->state != EC_DATAGRAM_RECEIVED
01610 || datagram->working_counter != 1) {
01611 EC_ERR("SII: Reception of read datagram failed.\n");
01612 fsm->sii_state = ec_fsm_error;
01613 return;
01614 }
01615
01616 fsm->sii_start = get_cycles();
01617
01618
01619 if (fsm->sii_mode) {
01620 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
01621 }
01622 else {
01623 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
01624 }
01625
01626 ec_master_queue_datagram(fsm->master, datagram);
01627 fsm->sii_state = ec_fsm_sii_read_fetch;
01628 }
01629
01630
01631
01637 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm )
01638 {
01639 ec_datagram_t *datagram = &fsm->datagram;
01640
01641 if (datagram->state != EC_DATAGRAM_RECEIVED
01642 || datagram->working_counter != 1) {
01643 EC_ERR("SII: Reception of check/fetch datagram failed.\n");
01644 fsm->sii_state = ec_fsm_error;
01645 return;
01646 }
01647
01648
01649 if (EC_READ_U8(datagram->data + 1) & 0x81) {
01650
01651 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
01652 EC_ERR("SII: Timeout.\n");
01653 fsm->sii_state = ec_fsm_error;
01654 #if 0
01655 EC_DBG("SII busy: %02X %02X %02X %02X\n",
01656 EC_READ_U8(datagram->data + 0),
01657 EC_READ_U8(datagram->data + 1),
01658 EC_READ_U8(datagram->data + 2),
01659 EC_READ_U8(datagram->data + 3));
01660 #endif
01661 }
01662
01663
01664 if (fsm->sii_mode) {
01665 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
01666 }
01667 else {
01668 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
01669 }
01670 ec_master_queue_datagram(fsm->master, datagram);
01671 return;
01672 }
01673
01674 #if 0
01675 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n",
01676 EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1),
01677 EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3),
01678 EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7),
01679 EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9));
01680 #endif
01681
01682
01683 memcpy(fsm->sii_value, datagram->data + 6, 4);
01684 fsm->sii_state = ec_fsm_end;
01685 }
01686
01687
01688
01694 void ec_fsm_sii_start_writing(ec_fsm_t *fsm )
01695 {
01696 ec_datagram_t *datagram = &fsm->datagram;
01697
01698
01699 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
01700 EC_WRITE_U8 (datagram->data, 0x01);
01701 EC_WRITE_U8 (datagram->data + 1, 0x02);
01702 EC_WRITE_U32(datagram->data + 2, fsm->sii_offset);
01703 memcpy(datagram->data + 6, fsm->sii_value, 2);
01704 ec_master_queue_datagram(fsm->master, datagram);
01705 fsm->sii_state = ec_fsm_sii_write_check;
01706 }
01707
01708
01709
01714 void ec_fsm_sii_write_check(ec_fsm_t *fsm )
01715 {
01716 ec_datagram_t *datagram = &fsm->datagram;
01717
01718 if (datagram->state != EC_DATAGRAM_RECEIVED
01719 || datagram->working_counter != 1) {
01720 EC_ERR("SII: Reception of write datagram failed.\n");
01721 fsm->sii_state = ec_fsm_error;
01722 return;
01723 }
01724
01725 fsm->sii_start = get_cycles();
01726
01727
01728 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
01729 ec_master_queue_datagram(fsm->master, datagram);
01730 fsm->sii_state = ec_fsm_sii_write_check2;
01731 }
01732
01733
01734
01739 void ec_fsm_sii_write_check2(ec_fsm_t *fsm )
01740 {
01741 ec_datagram_t *datagram = &fsm->datagram;
01742
01743 if (datagram->state != EC_DATAGRAM_RECEIVED
01744 || datagram->working_counter != 1) {
01745 EC_ERR("SII: Reception of write check datagram failed.\n");
01746 fsm->sii_state = ec_fsm_error;
01747 return;
01748 }
01749
01750 if (EC_READ_U8(datagram->data + 1) & 0x82) {
01751
01752 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
01753 EC_ERR("SII: Write timeout.\n");
01754 fsm->sii_state = ec_fsm_error;
01755 }
01756
01757
01758 ec_master_queue_datagram(fsm->master, datagram);
01759 }
01760 else if (EC_READ_U8(datagram->data + 1) & 0x40) {
01761 EC_ERR("SII: Write operation failed!\n");
01762 fsm->sii_state = ec_fsm_error;
01763 }
01764 else {
01765 fsm->sii_state = ec_fsm_end;
01766 }
01767 }
01768
01769
01770
01771
01772
01777 void ec_fsm_change_start(ec_fsm_t *fsm )
01778 {
01779 ec_datagram_t *datagram = &fsm->datagram;
01780 ec_slave_t *slave = fsm->slave;
01781
01782 fsm->change_jiffies = jiffies;
01783
01784
01785 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
01786 EC_WRITE_U16(datagram->data, fsm->change_new);
01787 ec_master_queue_datagram(fsm->master, datagram);
01788 fsm->change_state = ec_fsm_change_check;
01789 }
01790
01791
01792
01797 void ec_fsm_change_check(ec_fsm_t *fsm )
01798 {
01799 ec_datagram_t *datagram = &fsm->datagram;
01800 ec_slave_t *slave = fsm->slave;
01801
01802 if (datagram->state != EC_DATAGRAM_RECEIVED) {
01803 fsm->change_state = ec_fsm_error;
01804 EC_ERR("Failed to send state datagram to slave %i!\n",
01805 fsm->slave->ring_position);
01806 return;
01807 }
01808
01809 if (datagram->working_counter != 1) {
01810 if (jiffies - fsm->change_jiffies >= 3 * HZ) {
01811 fsm->change_state = ec_fsm_error;
01812 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not"
01813 " respond.\n", fsm->change_new, fsm->slave->ring_position);
01814 return;
01815 }
01816
01817
01818 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
01819 EC_WRITE_U16(datagram->data, fsm->change_new);
01820 ec_master_queue_datagram(fsm->master, datagram);
01821 return;
01822 }
01823
01824 fsm->change_jiffies = jiffies;
01825
01826
01827 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
01828 ec_master_queue_datagram(fsm->master, datagram);
01829 fsm->change_state = ec_fsm_change_status;
01830 }
01831
01832
01833
01838 void ec_fsm_change_status(ec_fsm_t *fsm )
01839 {
01840 ec_datagram_t *datagram = &fsm->datagram;
01841 ec_slave_t *slave = fsm->slave;
01842
01843 if (datagram->state != EC_DATAGRAM_RECEIVED
01844 || datagram->working_counter != 1) {
01845 fsm->change_state = ec_fsm_error;
01846 EC_ERR("Failed to check state 0x%02X on slave %i.\n",
01847 fsm->change_new, slave->ring_position);
01848 return;
01849 }
01850
01851 slave->current_state = EC_READ_U8(datagram->data);
01852
01853 if (slave->current_state == fsm->change_new) {
01854
01855 fsm->change_state = ec_fsm_end;
01856 return;
01857 }
01858
01859 if (slave->current_state & 0x10) {
01860
01861 fsm->change_new = slave->current_state & 0x0F;
01862 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
01863 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position,
01864 slave->current_state);
01865
01866 ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2);
01867 ec_master_queue_datagram(fsm->master, datagram);
01868 fsm->change_state = ec_fsm_change_code;
01869 return;
01870 }
01871
01872 if (jiffies - fsm->change_jiffies >= 100 * HZ / 1000) {
01873
01874 fsm->change_state = ec_fsm_error;
01875 EC_ERR("Timeout while setting state 0x%02X on slave %i.\n",
01876 fsm->change_new, slave->ring_position);
01877 return;
01878 }
01879
01880
01881 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
01882 ec_master_queue_datagram(fsm->master, datagram);
01883 }
01884
01885
01886
01891 const ec_code_msg_t al_status_messages[] = {
01892 {0x0001, "Unspecified error"},
01893 {0x0011, "Invalud requested state change"},
01894 {0x0012, "Unknown requested state"},
01895 {0x0013, "Bootstrap not supported"},
01896 {0x0014, "No valid firmware"},
01897 {0x0015, "Invalid mailbox configuration"},
01898 {0x0016, "Invalid mailbox configuration"},
01899 {0x0017, "Invalid sync manager configuration"},
01900 {0x0018, "No valid inputs available"},
01901 {0x0019, "No valid outputs"},
01902 {0x001A, "Synchronisation error"},
01903 {0x001B, "Sync manager watchdog"},
01904 {0x001C, "Invalid sync manager types"},
01905 {0x001D, "Invalid output configuration"},
01906 {0x001E, "Invalid input configuration"},
01907 {0x001F, "Invalid watchdog configuration"},
01908 {0x0020, "Slave needs cold start"},
01909 {0x0021, "Slave needs INIT"},
01910 {0x0022, "Slave needs PREOP"},
01911 {0x0023, "Slave needs SAVEOP"},
01912 {0x0030, "Invalid DC SYNCH configuration"},
01913 {0x0031, "Invalid DC latch configuration"},
01914 {0x0032, "PLL error"},
01915 {0x0033, "Invalid DC IO error"},
01916 {0x0034, "Invalid DC timeout error"},
01917 {0x0042, "MBOX EOE"},
01918 {0x0043, "MBOX COE"},
01919 {0x0044, "MBOX FOE"},
01920 {0x0045, "MBOX SOE"},
01921 {0x004F, "MBOX VOE"},
01922 {}
01923 };
01924
01925
01926
01931 void ec_fsm_change_code(ec_fsm_t *fsm )
01932 {
01933 ec_datagram_t *datagram = &fsm->datagram;
01934 ec_slave_t *slave = fsm->slave;
01935 uint32_t code;
01936 const ec_code_msg_t *al_msg;
01937
01938 if (datagram->state != EC_DATAGRAM_RECEIVED
01939 || datagram->working_counter != 1) {
01940 fsm->change_state = ec_fsm_error;
01941 EC_ERR("Reception of AL status code datagram failed.\n");
01942 return;
01943 }
01944
01945 if ((code = EC_READ_U16(datagram->data))) {
01946 for (al_msg = al_status_messages; al_msg->code; al_msg++) {
01947 if (al_msg->code != code) continue;
01948 EC_ERR("AL status message 0x%04X: \"%s\".\n",
01949 al_msg->code, al_msg->message);
01950 break;
01951 }
01952 if (!al_msg->code)
01953 EC_ERR("Unknown AL status code 0x%04X.\n", code);
01954 }
01955
01956
01957 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
01958 EC_WRITE_U16(datagram->data, slave->current_state);
01959 ec_master_queue_datagram(fsm->master, datagram);
01960 fsm->change_state = ec_fsm_change_ack;
01961 }
01962
01963
01964
01969 void ec_fsm_change_ack(ec_fsm_t *fsm )
01970 {
01971 ec_datagram_t *datagram = &fsm->datagram;
01972 ec_slave_t *slave = fsm->slave;
01973
01974 if (datagram->state != EC_DATAGRAM_RECEIVED
01975 || datagram->working_counter != 1) {
01976 fsm->change_state = ec_fsm_error;
01977 EC_ERR("Reception of state ack datagram failed.\n");
01978 return;
01979 }
01980
01981 fsm->change_jiffies = jiffies;
01982
01983
01984 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
01985 ec_master_queue_datagram(fsm->master, datagram);
01986 fsm->change_state = ec_fsm_change_check_ack;
01987 }
01988
01989
01990
01995 void ec_fsm_change_check_ack(ec_fsm_t *fsm )
01996 {
01997 ec_datagram_t *datagram = &fsm->datagram;
01998 ec_slave_t *slave = fsm->slave;
01999 ec_slave_state_t ack_state;
02000
02001 if (datagram->state != EC_DATAGRAM_RECEIVED
02002 || datagram->working_counter != 1) {
02003 fsm->change_state = ec_fsm_error;
02004 EC_ERR("Reception of state ack check datagram failed.\n");
02005 return;
02006 }
02007
02008 ack_state = EC_READ_U8(datagram->data);
02009
02010 if (ack_state == slave->current_state) {
02011 fsm->change_state = ec_fsm_error;
02012 EC_INFO("Acknowleged state 0x%02X on slave %i.\n",
02013 slave->current_state, slave->ring_position);
02014 return;
02015 }
02016
02017 if (jiffies - fsm->change_jiffies >= 100 * HZ / 1000) {
02018
02019 slave->current_state = EC_SLAVE_STATE_UNKNOWN;
02020 fsm->change_state = ec_fsm_error;
02021 EC_ERR("Timeout while acknowleging state 0x%02X on slave %i.\n",
02022 fsm->change_new, slave->ring_position);
02023 return;
02024 }
02025
02026
02027 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
02028 ec_master_queue_datagram(fsm->master, datagram);
02029 }
02030
02031
02032
02033
02034
02039 void ec_fsm_coe_down_start(ec_fsm_t *fsm )
02040 {
02041 ec_datagram_t *datagram = &fsm->datagram;
02042 ec_slave_t *slave = fsm->slave;
02043 ec_sdo_data_t *sdodata = fsm->sdodata;
02044 uint8_t *data;
02045
02046 EC_INFO("Downloading SDO 0x%04X:%i to slave %i.\n",
02047 sdodata->index, sdodata->subindex, slave->ring_position);
02048
02049 if (slave->sii_rx_mailbox_size < 6 + 10 + sdodata->size) {
02050 EC_ERR("SDO fragmenting not supported yet!\n");
02051 fsm->coe_state = ec_fsm_error;
02052 return;
02053 }
02054
02055 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
02056 sdodata->size + 10))) {
02057 fsm->coe_state = ec_fsm_error;
02058 return;
02059 }
02060
02061 EC_WRITE_U16(data, 0x2 << 12);
02062 EC_WRITE_U8 (data + 2, (0x1
02063 | 0x1 << 5));
02064 EC_WRITE_U16(data + 3, sdodata->index);
02065 EC_WRITE_U8 (data + 5, sdodata->subindex);
02066 EC_WRITE_U32(data + 6, sdodata->size);
02067 memcpy(data + 6, sdodata->data, sdodata->size);
02068
02069 ec_master_queue_datagram(fsm->master, datagram);
02070 fsm->coe_state = ec_fsm_coe_down_request;
02071 }
02072
02073
02074
02079 void ec_fsm_coe_down_request(ec_fsm_t *fsm )
02080 {
02081 ec_datagram_t *datagram = &fsm->datagram;
02082 ec_slave_t *slave = fsm->slave;
02083
02084 if (datagram->state != EC_DATAGRAM_RECEIVED
02085 || datagram->working_counter != 1) {
02086 fsm->coe_state = ec_fsm_error;
02087 EC_ERR("Reception of CoE download request failed.\n");
02088 return;
02089 }
02090
02091 fsm->coe_start = get_cycles();
02092
02093 ec_slave_mbox_prepare_check(slave, datagram);
02094 ec_master_queue_datagram(fsm->master, datagram);
02095 fsm->coe_state = ec_fsm_coe_down_check;
02096 }
02097
02098
02099
02104 void ec_fsm_coe_down_check(ec_fsm_t *fsm )
02105 {
02106 ec_datagram_t *datagram = &fsm->datagram;
02107 ec_slave_t *slave = fsm->slave;
02108
02109 if (datagram->state != EC_DATAGRAM_RECEIVED
02110 || datagram->working_counter != 1) {
02111 fsm->coe_state = ec_fsm_error;
02112 EC_ERR("Reception of CoE mailbox check datagram failed.\n");
02113 return;
02114 }
02115
02116 if (!ec_slave_mbox_check(datagram)) {
02117 if (get_cycles() - fsm->coe_start >= (cycles_t) 100 * cpu_khz) {
02118 fsm->coe_state = ec_fsm_error;
02119 EC_ERR("Timeout while checking SDO configuration on slave %i.\n",
02120 slave->ring_position);
02121 return;
02122 }
02123
02124 ec_slave_mbox_prepare_check(slave, datagram);
02125 ec_master_queue_datagram(fsm->master, datagram);
02126 return;
02127 }
02128
02129
02130 ec_slave_mbox_prepare_fetch(slave, datagram);
02131 ec_master_queue_datagram(fsm->master, datagram);
02132 fsm->coe_state = ec_fsm_coe_down_response;
02133 }
02134
02135
02136
02141 void ec_fsm_coe_down_response(ec_fsm_t *fsm )
02142 {
02143 ec_datagram_t *datagram = &fsm->datagram;
02144 ec_slave_t *slave = fsm->slave;
02145 uint8_t *data;
02146 size_t rec_size;
02147 ec_sdo_data_t *sdodata = fsm->sdodata;
02148
02149 if (datagram->state != EC_DATAGRAM_RECEIVED
02150 || datagram->working_counter != 1) {
02151 fsm->coe_state = ec_fsm_error;
02152 EC_ERR("Reception of CoE download response failed.\n");
02153 return;
02154 }
02155
02156 if (!(data = ec_slave_mbox_fetch(slave, datagram, 0x03, &rec_size))) {
02157 fsm->coe_state = ec_fsm_error;
02158 return;
02159 }
02160
02161 if (rec_size < 6) {
02162 fsm->coe_state = ec_fsm_error;
02163 EC_ERR("Received data is too small (%i bytes):\n", rec_size);
02164 ec_print_data(data, rec_size);
02165 return;
02166 }
02167
02168 if (EC_READ_U16(data) >> 12 == 0x2 &&
02169 EC_READ_U8 (data + 2) >> 5 == 0x4) {
02170 fsm->coe_state = ec_fsm_error;
02171 EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
02172 sdodata->index, sdodata->subindex, sdodata->size,
02173 slave->ring_position);
02174 if (rec_size < 10) {
02175 EC_ERR("Incomplete Abort command:\n");
02176 ec_print_data(data, rec_size);
02177 }
02178 else
02179 ec_canopen_abort_msg(EC_READ_U32(data + 6));
02180 return;
02181 }
02182
02183 if (EC_READ_U16(data) >> 12 != 0x3 ||
02184 EC_READ_U8 (data + 2) >> 5 != 0x3 ||
02185 EC_READ_U16(data + 3) != sdodata->index ||
02186 EC_READ_U8 (data + 5) != sdodata->subindex) {
02187 fsm->coe_state = ec_fsm_error;
02188 EC_ERR("SDO download 0x%04X:%X (%i bytes) failed:\n",
02189 sdodata->index, sdodata->subindex, sdodata->size);
02190 EC_ERR("Invalid SDO download response at slave %i!\n",
02191 slave->ring_position);
02192 ec_print_data(data, rec_size);
02193 return;
02194 }
02195
02196 fsm->coe_state = ec_fsm_end;
02197 }
02198
02199
02200
02208 const ec_code_msg_t sdo_abort_messages[] = {
02209 {0x05030000, "Toggle bit not changed"},
02210 {0x05040000, "SDO protocol timeout"},
02211 {0x05040001, "Client/Server command specifier not valid or unknown"},
02212 {0x05040005, "Out of memory"},
02213 {0x06010000, "Unsupported access to an object"},
02214 {0x06010001, "Attempt to read a write-only object"},
02215 {0x06010002, "Attempt to write a read-only object"},
02216 {0x06020000, "This object does not exist in the object directory"},
02217 {0x06040041, "The object cannot be mapped into the PDO"},
02218 {0x06040042, "The number and length of the objects to be mapped would"
02219 " exceed the PDO length"},
02220 {0x06040043, "General parameter incompatibility reason"},
02221 {0x06040047, "Gerneral internal incompatibility in device"},
02222 {0x06060000, "Access failure due to a hardware error"},
02223 {0x06070010, "Data type does not match, length of service parameter does"
02224 " not match"},
02225 {0x06070012, "Data type does not match, length of service parameter too"
02226 " high"},
02227 {0x06070013, "Data type does not match, length of service parameter too"
02228 " low"},
02229 {0x06090011, "Subindex does not exist"},
02230 {0x06090030, "Value range of parameter exceeded"},
02231 {0x06090031, "Value of parameter written too high"},
02232 {0x06090032, "Value of parameter written too low"},
02233 {0x06090036, "Maximum value is less than minimum value"},
02234 {0x08000000, "General error"},
02235 {0x08000020, "Data cannot be transferred or stored to the application"},
02236 {0x08000021, "Data cannot be transferred or stored to the application"
02237 " because of local control"},
02238 {0x08000022, "Data cannot be transferred or stored to the application"
02239 " because of the present device state"},
02240 {0x08000023, "Object dictionary dynamic generation fails or no object"
02241 " dictionary is present"},
02242 {}
02243 };
02244
02245
02246
02251 void ec_canopen_abort_msg(uint32_t abort_code)
02252 {
02253 const ec_code_msg_t *abort_msg;
02254
02255 for (abort_msg = sdo_abort_messages; abort_msg->code; abort_msg++) {
02256 if (abort_msg->code == abort_code) {
02257 EC_ERR("SDO abort message 0x%08X: \"%s\".\n",
02258 abort_msg->code, abort_msg->message);
02259 return;
02260 }
02261 }
02262
02263 EC_ERR("Unknown SDO abort code 0x%08X.\n", abort_code);
02264 }
02265
02266
02267
02268
02269
02274 void ec_fsm_error(ec_fsm_t *fsm )
02275 {
02276 }
02277
02278
02279
02284 void ec_fsm_end(ec_fsm_t *fsm )
02285 {
02286 }
02287
02288