Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

fsm.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: fsm.c 682 2006-11-07 12:13:30Z fp $
00004  *
00005  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
00006  *
00007  *  This file is part of the IgH EtherCAT Master.
00008  *
00009  *  The IgH EtherCAT Master is free software; you can redistribute it
00010  *  and/or modify it under the terms of the GNU General Public License
00011  *  as published by the Free Software Foundation; either version 2 of the
00012  *  License, or (at your option) any later version.
00013  *
00014  *  The IgH EtherCAT Master is distributed in the hope that it will be
00015  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with the IgH EtherCAT Master; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  *  The right to use EtherCAT Technology is granted and comes free of
00024  *  charge under condition of compatibility of product made by
00025  *  Licensee. People intending to distribute/sell products based on the
00026  *  code, have to sign an agreement to guarantee that products using
00027  *  software based on IgH EtherCAT master stay compatible with the actual
00028  *  EtherCAT specification (which are released themselves as an open
00029  *  standard) as the (only) precondition to have the right to use EtherCAT
00030  *  Technology, IP and trade marks.
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_acknowledge(ec_fsm_t *);
00052 void ec_fsm_master_validate_vendor(ec_fsm_t *);
00053 void ec_fsm_master_validate_product(ec_fsm_t *);
00054 void ec_fsm_master_rewrite_addresses(ec_fsm_t *);
00055 void ec_fsm_master_configure_slave(ec_fsm_t *);
00056 void ec_fsm_master_scan_slaves(ec_fsm_t *);
00057 void ec_fsm_master_write_eeprom(ec_fsm_t *);
00058 void ec_fsm_master_sdodict(ec_fsm_t *);
00059 void ec_fsm_master_sdo_request(ec_fsm_t *);
00060 void ec_fsm_master_end(ec_fsm_t *);
00061 void ec_fsm_master_error(ec_fsm_t *);
00062 
00063 void ec_fsm_slavescan_start(ec_fsm_t *);
00064 void ec_fsm_slavescan_address(ec_fsm_t *);
00065 void ec_fsm_slavescan_state(ec_fsm_t *);
00066 void ec_fsm_slavescan_base(ec_fsm_t *);
00067 void ec_fsm_slavescan_datalink(ec_fsm_t *);
00068 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *);
00069 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *);
00070 
00071 void ec_fsm_slaveconf_state_start(ec_fsm_t *);
00072 void ec_fsm_slaveconf_state_init(ec_fsm_t *);
00073 void ec_fsm_slaveconf_state_clear_fmmus(ec_fsm_t *);
00074 void ec_fsm_slaveconf_state_sync(ec_fsm_t *);
00075 void ec_fsm_slaveconf_state_preop(ec_fsm_t *);
00076 void ec_fsm_slaveconf_state_sync2(ec_fsm_t *);
00077 void ec_fsm_slaveconf_state_fmmu(ec_fsm_t *);
00078 void ec_fsm_slaveconf_state_sdoconf(ec_fsm_t *);
00079 void ec_fsm_slaveconf_state_saveop(ec_fsm_t *);
00080 void ec_fsm_slaveconf_state_op(ec_fsm_t *);
00081 
00082 void ec_fsm_slaveconf_enter_sync(ec_fsm_t *);
00083 void ec_fsm_slaveconf_enter_preop(ec_fsm_t *);
00084 void ec_fsm_slaveconf_enter_sync2(ec_fsm_t *);
00085 void ec_fsm_slaveconf_enter_fmmu(ec_fsm_t *);
00086 void ec_fsm_slaveconf_enter_sdoconf(ec_fsm_t *);
00087 void ec_fsm_slaveconf_enter_saveop(ec_fsm_t *);
00088 
00089 void ec_fsm_slave_state_end(ec_fsm_t *);
00090 void ec_fsm_slave_state_error(ec_fsm_t *);
00091 
00092 /*****************************************************************************/
00093 
00098 int ec_fsm_init(ec_fsm_t *fsm, 
00099                 ec_master_t *master 
00100                 )
00101 {
00102     fsm->master = master;
00103     fsm->master_state = ec_fsm_master_start;
00104     fsm->master_slaves_responding = 0;
00105     fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
00106     fsm->master_validation = 0;
00107 
00108     ec_datagram_init(&fsm->datagram);
00109     if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) {
00110         EC_ERR("Failed to allocate FSM datagram.\n");
00111         return -1;
00112     }
00113 
00114     // init sub-state-machines
00115     ec_fsm_sii_init(&fsm->fsm_sii, &fsm->datagram);
00116     ec_fsm_change_init(&fsm->fsm_change, &fsm->datagram);
00117     ec_fsm_coe_init(&fsm->fsm_coe, &fsm->datagram);
00118 
00119     return 0;
00120 }
00121 
00122 /*****************************************************************************/
00123 
00128 void ec_fsm_clear(ec_fsm_t *fsm )
00129 {
00130     // clear sub-state machines
00131     ec_fsm_sii_clear(&fsm->fsm_sii);
00132     ec_fsm_change_clear(&fsm->fsm_change);
00133     ec_fsm_coe_clear(&fsm->fsm_coe);
00134 
00135     ec_datagram_clear(&fsm->datagram);
00136 }
00137 
00138 /*****************************************************************************/
00139 
00145 int ec_fsm_exec(ec_fsm_t *fsm )
00146 {
00147     fsm->master_state(fsm);
00148 
00149     return ec_fsm_running(fsm);
00150 }
00151 
00152 /*****************************************************************************/
00153 
00158 int ec_fsm_running(ec_fsm_t *fsm )
00159 {
00160     return fsm->master_state != ec_fsm_master_end
00161         && fsm->master_state != ec_fsm_master_error;
00162 }
00163 
00164 /*****************************************************************************/
00165 
00170 int ec_fsm_success(ec_fsm_t *fsm )
00171 {
00172     return fsm->master_state == ec_fsm_master_end;
00173 }
00174 
00175 /******************************************************************************
00176  *  operation/idle state machine
00177  *****************************************************************************/
00178 
00184 void ec_fsm_master_start(ec_fsm_t *fsm)
00185 {
00186     ec_datagram_brd(&fsm->datagram, 0x0130, 2);
00187     ec_master_queue_datagram(fsm->master, &fsm->datagram);
00188     fsm->master_state = ec_fsm_master_broadcast;
00189 }
00190 
00191 /*****************************************************************************/
00192 
00198 void ec_fsm_master_broadcast(ec_fsm_t *fsm )
00199 {
00200     ec_datagram_t *datagram = &fsm->datagram;
00201     unsigned int topology_change, states_change, i;
00202     ec_slave_t *slave;
00203     ec_master_t *master = fsm->master;
00204 
00205     if (datagram->state != EC_DATAGRAM_RECEIVED) {
00206         if (!master->device->link_state) {
00207             fsm->master_slaves_responding = 0;
00208             list_for_each_entry(slave, &master->slaves, list) {
00209                 slave->online = 0;
00210             }
00211         }
00212         else {
00213             EC_ERR("Failed to receive broadcast datagram.\n");
00214         }
00215         fsm->master_state = ec_fsm_master_error;
00216         return;
00217     }
00218 
00219     topology_change = (datagram->working_counter !=
00220                        fsm->master_slaves_responding);
00221     states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states);
00222 
00223     fsm->master_slave_states = EC_READ_U8(datagram->data);
00224     fsm->master_slaves_responding = datagram->working_counter;
00225 
00226     if (topology_change) {
00227         EC_INFO("%i slave%s responding.\n",
00228                 fsm->master_slaves_responding,
00229                 fsm->master_slaves_responding == 1 ? "" : "s");
00230 
00231         if (master->mode == EC_MASTER_MODE_OPERATION) {
00232             if (fsm->master_slaves_responding == master->slave_count) {
00233                 fsm->master_validation = 1; // start validation later
00234             }
00235             else {
00236                 EC_WARN("Invalid slave count. Bus in tainted state.\n");
00237             }
00238         }
00239     }
00240 
00241     if (states_change) {
00242         char states[EC_STATE_STRING_SIZE];
00243         ec_state_string(fsm->master_slave_states, states);
00244         EC_INFO("Slave states: %s.\n", states);
00245     }
00246 
00247     // topology change in idle mode: clear all slaves and scan the bus
00248     if (topology_change && master->mode == EC_MASTER_MODE_IDLE) {
00249 
00250         ec_master_eoe_stop(master);
00251         ec_master_destroy_slaves(master);
00252 
00253         master->slave_count = datagram->working_counter;
00254 
00255         if (!master->slave_count) {
00256             // no slaves present -> finish state machine.
00257             fsm->master_state = ec_fsm_master_end;
00258             return;
00259         }
00260 
00261         // init slaves
00262         for (i = 0; i < master->slave_count; i++) {
00263             if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t),
00264                                                  GFP_ATOMIC))) {
00265                 EC_ERR("Failed to allocate slave %i!\n", i);
00266                 ec_master_destroy_slaves(master);
00267                 fsm->master_state = ec_fsm_master_error;
00268                 return;
00269             }
00270 
00271             if (ec_slave_init(slave, master, i, i + 1)) {
00272                 // freeing of "slave" already done
00273                 ec_master_destroy_slaves(master);
00274                 fsm->master_state = ec_fsm_master_error;
00275                 return;
00276             }
00277 
00278             list_add_tail(&slave->list, &master->slaves);
00279         }
00280 
00281         EC_INFO("Scanning bus.\n");
00282 
00283         // begin scanning of slaves
00284         fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00285         fsm->slave_state = ec_fsm_slavescan_start;
00286         fsm->master_state = ec_fsm_master_scan_slaves;
00287         fsm->master_state(fsm); // execute immediately
00288         return;
00289     }
00290 
00291     // fetch state from each slave
00292     fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00293     ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2);
00294     ec_master_queue_datagram(master, &fsm->datagram);
00295     fsm->master_state = ec_fsm_master_read_states;
00296 }
00297 
00298 /*****************************************************************************/
00299 
00305 void ec_fsm_master_action_process_states(ec_fsm_t *fsm
00307                                          )
00308 {
00309     ec_master_t *master = fsm->master;
00310     ec_slave_t *slave;
00311     char old_state[EC_STATE_STRING_SIZE], new_state[EC_STATE_STRING_SIZE];
00312 
00313     // check if any slaves are not in the state, they're supposed to be
00314     list_for_each_entry(slave, &master->slaves, list) {
00315         if (slave->error_flag
00316             || !slave->online
00317             || slave->requested_state == EC_SLAVE_STATE_UNKNOWN
00318             || (slave->current_state == slave->requested_state
00319                 && slave->configured)) continue;
00320 
00321         if (master->debug_level) {
00322             ec_state_string(slave->current_state, old_state);
00323             if (slave->current_state != slave->requested_state) {
00324                 ec_state_string(slave->requested_state, new_state);
00325                 EC_DBG("Changing state of slave %i (%s -> %s).\n",
00326                        slave->ring_position, old_state, new_state);
00327             }
00328             else if (!slave->configured) {
00329                 EC_DBG("Reconfiguring slave %i (%s).\n",
00330                        slave->ring_position, old_state);
00331             }
00332         }
00333 
00334         fsm->master_state = ec_fsm_master_configure_slave;
00335         fsm->slave = slave;
00336         fsm->slave_state = ec_fsm_slaveconf_state_start;
00337         fsm->slave_state(fsm); // execute immediately
00338         return;
00339     }
00340 
00341     // Check, if EoE processing has to be started
00342     ec_master_eoe_start(master);
00343 
00344     if (master->mode == EC_MASTER_MODE_IDLE) {
00345 
00346         // Check for a pending SDO request
00347         if (master->sdo_seq_master != master->sdo_seq_user) {
00348             if (master->debug_level)
00349                 EC_DBG("Processing SDO request...\n");
00350             slave = master->sdo_request->sdo->slave;
00351             if (slave->current_state == EC_SLAVE_STATE_INIT
00352                 || !slave->online) {
00353                 EC_ERR("Failed to process SDO request, slave %i not ready.\n",
00354                        slave->ring_position);
00355                 master->sdo_request->return_code = -1;
00356                 master->sdo_seq_master++;
00357             }
00358             else {
00359                 // start uploading SDO
00360                 fsm->slave = slave;
00361                 fsm->master_state = ec_fsm_master_sdo_request;
00362                 fsm->sdo_request = master->sdo_request;
00363                 ec_fsm_coe_upload(&fsm->fsm_coe, slave, fsm->sdo_request);
00364                 ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
00365                 return;
00366             }
00367         }
00368 
00369         // check, if slaves have an SDO dictionary to read out.
00370         list_for_each_entry(slave, &master->slaves, list) {
00371             if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)
00372                 || slave->sdo_dictionary_fetched
00373                 || slave->current_state == EC_SLAVE_STATE_INIT
00374                 || jiffies - slave->jiffies_preop < EC_WAIT_SDO_DICT * HZ
00375                 || !slave->online
00376                 || slave->error_flag) continue;
00377 
00378             if (master->debug_level) {
00379                 EC_DBG("Fetching SDO dictionary from slave %i.\n",
00380                        slave->ring_position);
00381             }
00382 
00383             slave->sdo_dictionary_fetched = 1;
00384 
00385             // start fetching SDO dictionary
00386             fsm->slave = slave;
00387             fsm->master_state = ec_fsm_master_sdodict;
00388             ec_fsm_coe_dictionary(&fsm->fsm_coe, slave);
00389             ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
00390             return;
00391         }
00392 
00393         // check for pending EEPROM write operations.
00394         list_for_each_entry(slave, &master->slaves, list) {
00395             if (!slave->new_eeprom_data) continue;
00396 
00397             if (!slave->online || slave->error_flag) {
00398                 kfree(slave->new_eeprom_data);
00399                 slave->new_eeprom_data = NULL;
00400                 EC_ERR("Discarding EEPROM data, slave %i not ready.\n",
00401                        slave->ring_position);
00402                 continue;
00403             }
00404 
00405             // found pending EEPROM write operation. execute it!
00406             EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position);
00407             fsm->slave = slave;
00408             fsm->sii_offset = 0x0000;
00409             ec_fsm_sii_write(&fsm->fsm_sii, slave, fsm->sii_offset,
00410                              slave->new_eeprom_data, EC_FSM_SII_NODE);
00411             fsm->master_state = ec_fsm_master_write_eeprom;
00412             fsm->master_state(fsm); // execute immediately
00413             return;
00414         }
00415     }
00416 
00417     fsm->master_state = ec_fsm_master_end;
00418 }
00419 
00420 /*****************************************************************************/
00421 
00426 void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm)
00428 {
00429     ec_master_t *master = fsm->master;
00430     ec_slave_t *slave = fsm->slave;
00431 
00432     // is there another slave to query?
00433     if (slave->list.next != &master->slaves) {
00434         // process next slave
00435         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00436         ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address,
00437                          0x0130, 2);
00438         ec_master_queue_datagram(master, &fsm->datagram);
00439         fsm->master_state = ec_fsm_master_read_states;
00440         return;
00441     }
00442 
00443     // all slave states read
00444 
00445     // check, if a bus validation has to be done
00446     if (fsm->master_validation) {
00447         fsm->master_validation = 0;
00448         list_for_each_entry(slave, &master->slaves, list) {
00449             if (slave->online) continue;
00450 
00451             // At least one slave is offline. validate!
00452             EC_INFO("Validating bus.\n");
00453             fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00454             fsm->master_state = ec_fsm_master_validate_vendor;
00455             ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x0008, EC_FSM_SII_POSITION);
00456             ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
00457             return;
00458         }
00459     }
00460 
00461     ec_fsm_master_action_process_states(fsm);
00462 }
00463 
00464 /*****************************************************************************/
00465 
00471 void ec_fsm_master_read_states(ec_fsm_t *fsm )
00472 {
00473     ec_slave_t *slave = fsm->slave;
00474     ec_datagram_t *datagram = &fsm->datagram;
00475     uint8_t new_state;
00476 
00477     if (datagram->state != EC_DATAGRAM_RECEIVED) {
00478         EC_ERR("Failed to receive AL state datagram for slave %i!\n",
00479                slave->ring_position);
00480         fsm->master_state = ec_fsm_master_error;
00481         return;
00482     }
00483 
00484     // did the slave not respond to its station address?
00485     if (datagram->working_counter != 1) {
00486         if (slave->online) {
00487             slave->online = 0;
00488             if (slave->master->debug_level)
00489                 EC_DBG("Slave %i: offline.\n", slave->ring_position);
00490         }
00491         ec_fsm_master_action_next_slave_state(fsm);
00492         return;
00493     }
00494 
00495     // slave responded
00496     new_state = EC_READ_U8(datagram->data);
00497     if (!slave->online) { // slave was offline before
00498         slave->online = 1;
00499         slave->error_flag = 0; // clear error flag
00500         slave->current_state = new_state;
00501         if (slave->master->debug_level) {
00502             char cur_state[EC_STATE_STRING_SIZE];
00503             ec_state_string(slave->current_state, cur_state);
00504             EC_DBG("Slave %i: online (%s).\n",
00505                    slave->ring_position, cur_state);
00506         }
00507     }
00508     else if (new_state != slave->current_state) {
00509         if (slave->master->debug_level) {
00510             char old_state[EC_STATE_STRING_SIZE],
00511                 cur_state[EC_STATE_STRING_SIZE];
00512             ec_state_string(slave->current_state, old_state);
00513             ec_state_string(new_state, cur_state);
00514             EC_DBG("Slave %i: %s -> %s.\n",
00515                    slave->ring_position, old_state, cur_state);
00516         }
00517         slave->current_state = new_state;
00518     }
00519 
00520     // check, if new slave state has to be acknowledged
00521     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR && !slave->error_flag) {
00522         ec_fsm_change_ack(&fsm->fsm_change, slave);
00523         ec_fsm_change_exec(&fsm->fsm_change);
00524         fsm->master_state = ec_fsm_master_acknowledge;
00525         return;
00526     }
00527 
00528     ec_fsm_master_action_next_slave_state(fsm);
00529 }
00530 
00531 /*****************************************************************************/
00532 
00537 void ec_fsm_master_acknowledge(ec_fsm_t *fsm )
00538 {
00539     ec_slave_t *slave = fsm->slave;
00540 
00541     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
00542 
00543     if (!ec_fsm_change_success(&fsm->fsm_change)) {
00544         fsm->slave->error_flag = 1;
00545         EC_ERR("Failed to acknowledge state change on slave %i.\n",
00546                slave->ring_position);
00547         fsm->master_state = ec_fsm_master_error;
00548         return;
00549     }
00550 
00551     ec_fsm_master_action_next_slave_state(fsm);
00552 }
00553 
00554 /*****************************************************************************/
00555 
00561 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm )
00562 {
00563     ec_slave_t *slave = fsm->slave;
00564 
00565     if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
00566 
00567     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
00568         fsm->slave->error_flag = 1;
00569         EC_ERR("Failed to validate vendor ID of slave %i.\n",
00570                slave->ring_position);
00571         fsm->master_state = ec_fsm_master_error;
00572         return;
00573     }
00574 
00575     if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_vendor_id) {
00576         EC_ERR("Slave %i has an invalid vendor ID!\n", slave->ring_position);
00577         fsm->master_state = ec_fsm_master_error;
00578         return;
00579     }
00580 
00581     // vendor ID is ok. check product code.
00582     fsm->master_state = ec_fsm_master_validate_product;
00583     ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x000A, EC_FSM_SII_POSITION);
00584     ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
00585 }
00586 
00587 /*****************************************************************************/
00588 
00595 void ec_fsm_master_action_addresses(ec_fsm_t *fsm )
00596 {
00597     ec_datagram_t *datagram = &fsm->datagram;
00598 
00599     while (fsm->slave->online) {
00600         if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
00601             fsm->master_state = ec_fsm_master_start;
00602             fsm->master_state(fsm); // execute immediately
00603             return;
00604         }
00605         // check next slave
00606         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00607     }
00608 
00609     if (fsm->master->debug_level)
00610         EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position);
00611 
00612     // write station address
00613     ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
00614     EC_WRITE_U16(datagram->data, fsm->slave->station_address);
00615     ec_master_queue_datagram(fsm->master, datagram);
00616     fsm->master_state = ec_fsm_master_rewrite_addresses;
00617 }
00618 
00619 /*****************************************************************************/
00620 
00626 void ec_fsm_master_validate_product(ec_fsm_t *fsm )
00627 {
00628     ec_slave_t *slave = fsm->slave;
00629 
00630     if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
00631 
00632     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
00633         fsm->slave->error_flag = 1;
00634         EC_ERR("Failed to validate product code of slave %i.\n",
00635                slave->ring_position);
00636         fsm->master_state = ec_fsm_master_error;
00637         return;
00638     }
00639 
00640     if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_product_code) {
00641         EC_ERR("Slave %i: invalid product code!\n", slave->ring_position);
00642         EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code,
00643                EC_READ_U32(fsm->fsm_sii.value));
00644         fsm->master_state = ec_fsm_master_error;
00645         return;
00646     }
00647 
00648     // have all states been validated?
00649     if (slave->list.next == &fsm->master->slaves) {
00650         fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list);
00651         // start writing addresses to offline slaves
00652         ec_fsm_master_action_addresses(fsm);
00653         return;
00654     }
00655 
00656     // validate next slave
00657     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00658     fsm->master_state = ec_fsm_master_validate_vendor;
00659     ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x0008, EC_FSM_SII_POSITION);
00660     ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
00661 }
00662 
00663 /*****************************************************************************/
00664 
00670 void ec_fsm_master_rewrite_addresses(ec_fsm_t *fsm
00672                                      )
00673 {
00674     ec_slave_t *slave = fsm->slave;
00675     ec_datagram_t *datagram = &fsm->datagram;
00676 
00677     if (datagram->state != EC_DATAGRAM_RECEIVED
00678         || datagram->working_counter != 1) {
00679         EC_ERR("Failed to write station address on slave %i.\n",
00680                slave->ring_position);
00681     }
00682 
00683     if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
00684         fsm->master_state = ec_fsm_master_start;
00685         fsm->master_state(fsm); // execute immediately
00686         return;
00687     }
00688 
00689     // check next slave
00690     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00691     // Write new station address to slave
00692     ec_fsm_master_action_addresses(fsm);
00693 }
00694 
00695 /*****************************************************************************/
00696 
00702 void ec_fsm_master_scan_slaves(ec_fsm_t *fsm )
00703 {
00704     ec_master_t *master = fsm->master;
00705     ec_slave_t *slave = fsm->slave;
00706 
00707     fsm->slave_state(fsm); // execute slave state machine
00708 
00709     if (fsm->slave_state != ec_fsm_slave_state_end
00710         && fsm->slave_state != ec_fsm_slave_state_error) return;
00711 
00712     // another slave to fetch?
00713     if (slave->list.next != &master->slaves) {
00714         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00715         fsm->slave_state = ec_fsm_slavescan_start;
00716         fsm->slave_state(fsm); // execute immediately
00717         return;
00718     }
00719 
00720     EC_INFO("Bus scanning completed.\n");
00721 
00722     ec_master_calc_addressing(master);
00723 
00724     // set initial states of all slaves to PREOP to make mailbox
00725     // communication possible
00726     list_for_each_entry(slave, &master->slaves, list) {
00727         ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
00728     }
00729 
00730     fsm->master_state = ec_fsm_master_end;
00731 }
00732 
00733 /*****************************************************************************/
00734 
00740 void ec_fsm_master_configure_slave(ec_fsm_t *fsm
00742                                    )
00743 {
00744     fsm->slave_state(fsm); // execute slave's state machine
00745 
00746     if (fsm->slave_state != ec_fsm_slave_state_end
00747         && fsm->slave_state != ec_fsm_slave_state_error) return;
00748 
00749     ec_fsm_master_action_process_states(fsm);
00750 }
00751 
00752 /*****************************************************************************/
00753 
00758 void ec_fsm_master_write_eeprom(ec_fsm_t *fsm )
00759 {
00760     ec_slave_t *slave = fsm->slave;
00761 
00762     if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
00763 
00764     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
00765         fsm->slave->error_flag = 1;
00766         EC_ERR("Failed to write EEPROM contents to slave %i.\n",
00767                slave->ring_position);
00768         kfree(slave->new_eeprom_data);
00769         slave->new_eeprom_data = NULL;
00770         fsm->master_state = ec_fsm_master_error;
00771         return;
00772     }
00773 
00774     fsm->sii_offset++;
00775     if (fsm->sii_offset < slave->new_eeprom_size) {
00776         ec_fsm_sii_write(&fsm->fsm_sii, slave, fsm->sii_offset,
00777                          slave->new_eeprom_data + fsm->sii_offset,
00778                          EC_FSM_SII_NODE);
00779         ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
00780         return;
00781     }
00782 
00783     // finished writing EEPROM
00784     EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position);
00785     kfree(slave->new_eeprom_data);
00786     slave->new_eeprom_data = NULL;
00787 
00788     // TODO: Evaluate new EEPROM contents!
00789 
00790     // restart master state machine.
00791     fsm->master_state = ec_fsm_master_start;
00792     fsm->master_state(fsm); // execute immediately
00793 }
00794 
00795 /*****************************************************************************/
00796 
00801 void ec_fsm_master_sdodict(ec_fsm_t *fsm )
00802 {
00803     ec_slave_t *slave = fsm->slave;
00804     ec_master_t *master = fsm->master;
00805 
00806     if (ec_fsm_coe_exec(&fsm->fsm_coe)) return;
00807 
00808     if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
00809         fsm->master_state = ec_fsm_master_error;
00810         return;
00811     }
00812 
00813     // SDO dictionary fetching finished
00814 
00815     if (master->debug_level) {
00816         unsigned int sdo_count, entry_count;
00817         ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
00818         EC_DBG("Fetched %i SDOs and %i entries from slave %i.\n",
00819                sdo_count, entry_count, slave->ring_position);
00820     }
00821 
00822     // restart master state machine.
00823     fsm->master_state = ec_fsm_master_start;
00824     fsm->master_state(fsm); // execute immediately
00825 }
00826 
00827 /*****************************************************************************/
00828 
00833 void ec_fsm_master_sdo_request(ec_fsm_t *fsm )
00834 {
00835     ec_master_t *master = fsm->master;
00836     ec_sdo_request_t *request = fsm->sdo_request;
00837 
00838     if (ec_fsm_coe_exec(&fsm->fsm_coe)) return;
00839 
00840     if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
00841         request->return_code = -1;
00842         master->sdo_seq_master++;
00843         fsm->master_state = ec_fsm_master_error;
00844         return;
00845     }
00846 
00847     // SDO dictionary fetching finished
00848 
00849     request->return_code = 1;
00850     master->sdo_seq_master++;
00851 
00852     // restart master state machine.
00853     fsm->master_state = ec_fsm_master_start;
00854     fsm->master_state(fsm); // execute immediately
00855 }
00856 
00857 /*****************************************************************************/
00858 
00863 void ec_fsm_master_error(ec_fsm_t *fsm )
00864 {
00865     fsm->master_state = ec_fsm_master_start;
00866 }
00867 
00868 /*****************************************************************************/
00869 
00874 void ec_fsm_master_end(ec_fsm_t *fsm )
00875 {
00876     fsm->master_state = ec_fsm_master_start;
00877 }
00878 
00879 /******************************************************************************
00880  *  slave scan state machine
00881  *****************************************************************************/
00882 
00889 void ec_fsm_slavescan_start(ec_fsm_t *fsm )
00890 {
00891     ec_datagram_t *datagram = &fsm->datagram;
00892 
00893     // write station address
00894     ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
00895     EC_WRITE_U16(datagram->data, fsm->slave->station_address);
00896     ec_master_queue_datagram(fsm->master, datagram);
00897     fsm->slave_state = ec_fsm_slavescan_address;
00898 }
00899 
00900 /*****************************************************************************/
00901 
00906 void ec_fsm_slavescan_address(ec_fsm_t *fsm )
00907 {
00908     ec_datagram_t *datagram = &fsm->datagram;
00909 
00910     if (datagram->state != EC_DATAGRAM_RECEIVED
00911         || datagram->working_counter != 1) {
00912         fsm->slave->error_flag = 1;
00913         fsm->slave_state = ec_fsm_slave_state_error;
00914         EC_ERR("Failed to write station address of slave %i.\n",
00915                fsm->slave->ring_position);
00916         return;
00917     }
00918 
00919     // Read AL state
00920     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2);
00921     ec_master_queue_datagram(fsm->master, datagram);
00922     fsm->slave_state = ec_fsm_slavescan_state;
00923 }
00924 
00925 /*****************************************************************************/
00926 
00931 void ec_fsm_slavescan_state(ec_fsm_t *fsm )
00932 {
00933     ec_datagram_t *datagram = &fsm->datagram;
00934     ec_slave_t *slave = fsm->slave;
00935 
00936     if (datagram->state != EC_DATAGRAM_RECEIVED
00937         || datagram->working_counter != 1) {
00938         fsm->slave->error_flag = 1;
00939         fsm->slave_state = ec_fsm_slave_state_error;
00940         EC_ERR("Failed to read AL state of slave %i.\n",
00941                fsm->slave->ring_position);
00942         return;
00943     }
00944 
00945     slave->current_state = EC_READ_U8(datagram->data);
00946     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
00947         char state_str[EC_STATE_STRING_SIZE];
00948         ec_state_string(slave->current_state, state_str);
00949         EC_WARN("Slave %i has state error bit set (%s)!\n",
00950                 slave->ring_position, state_str);
00951     }
00952 
00953     // read base data
00954     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6);
00955     ec_master_queue_datagram(fsm->master, datagram);
00956     fsm->slave_state = ec_fsm_slavescan_base;
00957 }
00958 
00959 /*****************************************************************************/
00960 
00965 void ec_fsm_slavescan_base(ec_fsm_t *fsm )
00966 {
00967     ec_datagram_t *datagram = &fsm->datagram;
00968     ec_slave_t *slave = fsm->slave;
00969 
00970     if (datagram->state != EC_DATAGRAM_RECEIVED
00971         || datagram->working_counter != 1) {
00972         fsm->slave->error_flag = 1;
00973         fsm->slave_state = ec_fsm_slave_state_error;
00974         EC_ERR("Failed to read base data of slave %i.\n",
00975                slave->ring_position);
00976         return;
00977     }
00978 
00979     slave->base_type       = EC_READ_U8 (datagram->data);
00980     slave->base_revision   = EC_READ_U8 (datagram->data + 1);
00981     slave->base_build      = EC_READ_U16(datagram->data + 2);
00982     slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
00983     slave->base_sync_count = EC_READ_U8 (datagram->data + 5);
00984 
00985     if (slave->base_fmmu_count > EC_MAX_FMMUS)
00986         slave->base_fmmu_count = EC_MAX_FMMUS;
00987 
00988     // read data link status
00989     ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2);
00990     ec_master_queue_datagram(slave->master, datagram);
00991     fsm->slave_state = ec_fsm_slavescan_datalink;
00992 }
00993 
00994 /*****************************************************************************/
00995 
01000 void ec_fsm_slavescan_datalink(ec_fsm_t *fsm )
01001 {
01002     ec_datagram_t *datagram = &fsm->datagram;
01003     ec_slave_t *slave = fsm->slave;
01004     uint16_t dl_status;
01005     unsigned int i;
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_slave_state_error;
01011         EC_ERR("Failed to read DL status of slave %i.\n",
01012                slave->ring_position);
01013         return;
01014     }
01015 
01016     dl_status = EC_READ_U16(datagram->data);
01017     for (i = 0; i < 4; i++) {
01018         slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
01019         slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
01020         slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
01021     }
01022 
01023     // Start fetching EEPROM size
01024 
01025     fsm->sii_offset = 0x0040; // first category header
01026     ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, EC_FSM_SII_NODE);
01027     fsm->slave_state = ec_fsm_slavescan_eeprom_size;
01028     fsm->slave_state(fsm); // execute state immediately
01029 }
01030 
01031 /*****************************************************************************/
01032 
01037 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *fsm )
01038 {
01039     ec_slave_t *slave = fsm->slave;
01040     uint16_t cat_type, cat_size;
01041 
01042     if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
01043 
01044     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
01045         fsm->slave->error_flag = 1;
01046         fsm->slave_state = ec_fsm_slave_state_error;
01047         EC_ERR("Failed to read EEPROM size of slave %i.\n",
01048                slave->ring_position);
01049         return;
01050     }
01051 
01052     cat_type = EC_READ_U16(fsm->fsm_sii.value);
01053     cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
01054 
01055     if (cat_type != 0xFFFF) { // not the last category
01056         fsm->sii_offset += cat_size + 2;
01057         ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
01058                         EC_FSM_SII_NODE);
01059         ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
01060         return;
01061     }
01062 
01063     slave->eeprom_size = (fsm->sii_offset + 1) * 2;
01064 
01065     if (slave->eeprom_data) {
01066         EC_INFO("Freeing old EEPROM data on slave %i...\n",
01067                 slave->ring_position);
01068         kfree(slave->eeprom_data);
01069     }
01070 
01071     if (!(slave->eeprom_data =
01072           (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
01073         fsm->slave->error_flag = 1;
01074         fsm->slave_state = ec_fsm_slave_state_error;
01075         EC_ERR("Failed to allocate EEPROM data on slave %i.\n",
01076                slave->ring_position);
01077         return;
01078     }
01079 
01080     // Start fetching EEPROM contents
01081 
01082     fsm->slave_state = ec_fsm_slavescan_eeprom_data;
01083     fsm->sii_offset = 0x0000;
01084     ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, EC_FSM_SII_NODE);
01085     ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
01086 }
01087 
01088 /*****************************************************************************/
01089 
01094 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *fsm )
01095 {
01096     ec_slave_t *slave = fsm->slave;
01097     uint16_t *cat_word, cat_type, cat_size;
01098 
01099     if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
01100 
01101     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
01102         fsm->slave->error_flag = 1;
01103         fsm->slave_state = ec_fsm_slave_state_error;
01104         EC_ERR("Failed to fetch EEPROM contents of slave %i.\n",
01105                slave->ring_position);
01106         return;
01107     }
01108 
01109     // 2 words fetched
01110 
01111     if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit
01112         memcpy(slave->eeprom_data + fsm->sii_offset * 2,
01113                fsm->fsm_sii.value, 4);
01114     }
01115     else { // copy the last word
01116         memcpy(slave->eeprom_data + fsm->sii_offset * 2,
01117                fsm->fsm_sii.value, 2);
01118     }
01119 
01120     if (fsm->sii_offset + 2 < slave->eeprom_size / 2) {
01121         // fetch the next 2 words
01122         fsm->sii_offset += 2;
01123         ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
01124                         EC_FSM_SII_NODE);
01125         ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
01126         return;
01127     }
01128 
01129     // Evaluate EEPROM contents
01130 
01131     slave->sii_alias =
01132         EC_READ_U16(slave->eeprom_data + 2 * 0x0004);
01133     slave->sii_vendor_id =
01134         EC_READ_U32(slave->eeprom_data + 2 * 0x0008);
01135     slave->sii_product_code =
01136         EC_READ_U32(slave->eeprom_data + 2 * 0x000A);
01137     slave->sii_revision_number =
01138         EC_READ_U32(slave->eeprom_data + 2 * 0x000C);
01139     slave->sii_serial_number =
01140         EC_READ_U32(slave->eeprom_data + 2 * 0x000E);
01141     slave->sii_rx_mailbox_offset =
01142         EC_READ_U16(slave->eeprom_data + 2 * 0x0018);
01143     slave->sii_rx_mailbox_size =
01144         EC_READ_U16(slave->eeprom_data + 2 * 0x0019);
01145     slave->sii_tx_mailbox_offset =
01146         EC_READ_U16(slave->eeprom_data + 2 * 0x001A);
01147     slave->sii_tx_mailbox_size =
01148         EC_READ_U16(slave->eeprom_data + 2 * 0x001B);
01149     slave->sii_mailbox_protocols =
01150         EC_READ_U16(slave->eeprom_data + 2 * 0x001C);
01151 
01152     // evaluate category data
01153     cat_word = (uint16_t *) slave->eeprom_data + 0x0040;
01154     while (EC_READ_U16(cat_word) != 0xFFFF) {
01155         cat_type = EC_READ_U16(cat_word) & 0x7FFF;
01156         cat_size = EC_READ_U16(cat_word + 1);
01157 
01158         switch (cat_type) {
01159             case 0x000A:
01160                 if (ec_slave_fetch_strings(slave, (uint8_t *) (cat_word + 2)))
01161                     goto end;
01162                 break;
01163             case 0x001E:
01164                 ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2));
01165                 break;
01166             case 0x0028:
01167                 break;
01168             case 0x0029:
01169                 if (ec_slave_fetch_sync(slave, (uint8_t *) (cat_word + 2),
01170                                         cat_size))
01171                     goto end;
01172                 break;
01173             case 0x0032:
01174                 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
01175                                        cat_size, EC_TX_PDO))
01176                     goto end;
01177                 break;
01178             case 0x0033:
01179                 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
01180                                        cat_size, EC_RX_PDO))
01181                     goto end;
01182                 break;
01183             default:
01184                 if (fsm->master->debug_level)
01185                     EC_WARN("Unknown category type 0x%04X in slave %i.\n",
01186                             cat_type, slave->ring_position);
01187         }
01188 
01189         cat_word += cat_size + 2;
01190     }
01191 
01192     fsm->slave_state = ec_fsm_slave_state_end;
01193     return;
01194 
01195 end:
01196     EC_ERR("Failed to analyze category data.\n");
01197     fsm->slave->error_flag = 1;
01198     fsm->slave_state = ec_fsm_slave_state_error;
01199 }
01200 
01201 /******************************************************************************
01202  *  slave configuration state machine
01203  *****************************************************************************/
01204 
01209 void ec_fsm_slaveconf_state_start(ec_fsm_t *fsm )
01210 {
01211     if (fsm->master->debug_level) {
01212         EC_DBG("Configuring slave %i...\n", fsm->slave->ring_position);
01213     }
01214 
01215     ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
01216     ec_fsm_change_exec(&fsm->fsm_change);
01217     fsm->slave_state = ec_fsm_slaveconf_state_init;
01218 }
01219 
01220 /*****************************************************************************/
01221 
01226 void ec_fsm_slaveconf_state_init(ec_fsm_t *fsm )
01227 {
01228     ec_master_t *master = fsm->master;
01229     ec_slave_t *slave = fsm->slave;
01230     ec_datagram_t *datagram = &fsm->datagram;
01231 
01232     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
01233 
01234     if (!ec_fsm_change_success(&fsm->fsm_change)) {
01235         slave->error_flag = 1;
01236         fsm->slave_state = ec_fsm_slave_state_error;
01237         return;
01238     }
01239 
01240     slave->configured = 1;
01241 
01242     if (master->debug_level) {
01243         EC_DBG("Slave %i is now in INIT.\n", slave->ring_position);
01244     }
01245 
01246     // check and reset CRC fault counters
01247     //ec_slave_check_crc(slave);
01248     // TODO: Implement state machine for CRC checking.
01249 
01250     if (!slave->base_fmmu_count) { // skip FMMU configuration
01251         ec_fsm_slaveconf_enter_sync(fsm);
01252         return;
01253     }
01254 
01255     if (master->debug_level)
01256         EC_DBG("Clearing FMMU configurations of slave %i...\n",
01257                slave->ring_position);
01258 
01259     // clear FMMU configurations
01260     ec_datagram_npwr(datagram, slave->station_address,
01261                      0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
01262     memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
01263     ec_master_queue_datagram(master, datagram);
01264     fsm->slave_state = ec_fsm_slaveconf_state_clear_fmmus;
01265 }
01266 
01267 /*****************************************************************************/
01268 
01273 void ec_fsm_slaveconf_state_clear_fmmus(ec_fsm_t *fsm)
01275 {
01276     ec_datagram_t *datagram = &fsm->datagram;
01277 
01278     if (datagram->state != EC_DATAGRAM_RECEIVED
01279         || datagram->working_counter != 1) {
01280         fsm->slave->error_flag = 1;
01281         fsm->slave_state = ec_fsm_slave_state_error;
01282         EC_ERR("Failed to clear FMMUs on slave %i.\n",
01283                fsm->slave->ring_position);
01284         return;
01285     }
01286 
01287     ec_fsm_slaveconf_enter_sync(fsm);
01288 }
01289 
01290 /*****************************************************************************/
01291 
01295 void ec_fsm_slaveconf_enter_sync(ec_fsm_t *fsm )
01296 {
01297     ec_master_t *master = fsm->master;
01298     ec_slave_t *slave = fsm->slave;
01299     ec_datagram_t *datagram = &fsm->datagram;
01300     const ec_sii_sync_t *sync;
01301     ec_sii_sync_t mbox_sync;
01302 
01303     // slave is now in INIT
01304     if (slave->current_state == slave->requested_state) {
01305         fsm->slave_state = ec_fsm_slave_state_end; // successful
01306         if (master->debug_level) {
01307             EC_DBG("Finished configuration of slave %i.\n",
01308                    slave->ring_position);
01309         }
01310         return;
01311     }
01312 
01313     if (!slave->base_sync_count) { // no sync managers
01314         ec_fsm_slaveconf_enter_preop(fsm);
01315         return;
01316     }
01317 
01318     if (master->debug_level) {
01319         EC_DBG("Configuring sync managers of slave %i.\n",
01320                slave->ring_position);
01321     }
01322 
01323     // configure sync managers
01324     ec_datagram_npwr(datagram, slave->station_address, 0x0800,
01325                      EC_SYNC_SIZE * slave->base_sync_count);
01326     memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
01327 
01328     if (list_empty(&slave->sii_syncs)) {
01329         if (slave->sii_rx_mailbox_offset && slave->sii_tx_mailbox_offset) {
01330             if (slave->master->debug_level)
01331                 EC_DBG("Guessing sync manager settings for slave %i.\n",
01332                        slave->ring_position);
01333             mbox_sync.index = 0;
01334             mbox_sync.physical_start_address = slave->sii_tx_mailbox_offset;
01335             mbox_sync.length = slave->sii_tx_mailbox_size;
01336             mbox_sync.control_register = 0x26;
01337             mbox_sync.enable = 0x01;
01338             mbox_sync.est_length = 0;
01339             ec_sync_config(&mbox_sync, slave,
01340                            datagram->data + EC_SYNC_SIZE * mbox_sync.index);
01341             mbox_sync.index = 1;
01342             mbox_sync.physical_start_address = slave->sii_rx_mailbox_offset;
01343             mbox_sync.length = slave->sii_rx_mailbox_size;
01344             mbox_sync.control_register = 0x22;
01345             mbox_sync.enable = 0x01;
01346             mbox_sync.est_length = 0;
01347             ec_sync_config(&mbox_sync, slave,
01348                            datagram->data + EC_SYNC_SIZE * mbox_sync.index);
01349         }
01350     }
01351     else if (slave->sii_mailbox_protocols) { // mailboxes present
01352         list_for_each_entry(sync, &slave->sii_syncs, list) {
01353             // only configure mailbox sync-managers
01354             if (sync->index != 0 && sync->index != 1) continue;
01355             ec_sync_config(sync, slave,
01356                            datagram->data + EC_SYNC_SIZE * sync->index);
01357         }
01358     }
01359 
01360     ec_master_queue_datagram(fsm->master, datagram);
01361     fsm->slave_state = ec_fsm_slaveconf_state_sync;
01362 }
01363 
01364 /*****************************************************************************/
01365 
01370 void ec_fsm_slaveconf_state_sync(ec_fsm_t *fsm )
01371 {
01372     ec_datagram_t *datagram = &fsm->datagram;
01373     ec_slave_t *slave = fsm->slave;
01374 
01375     if (datagram->state != EC_DATAGRAM_RECEIVED
01376         || datagram->working_counter != 1) {
01377         slave->error_flag = 1;
01378         fsm->slave_state = ec_fsm_slave_state_error;
01379         EC_ERR("Failed to set sync managers on slave %i.\n",
01380                slave->ring_position);
01381         return;
01382     }
01383 
01384     ec_fsm_slaveconf_enter_preop(fsm);
01385 }
01386 
01387 /*****************************************************************************/
01388 
01392 void ec_fsm_slaveconf_enter_preop(ec_fsm_t *fsm )
01393 {
01394     fsm->slave_state = ec_fsm_slaveconf_state_preop;
01395     ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP);
01396     ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
01397 }
01398 
01399 /*****************************************************************************/
01400 
01405 void ec_fsm_slaveconf_state_preop(ec_fsm_t *fsm )
01406 {
01407     ec_slave_t *slave = fsm->slave;
01408     ec_master_t *master = fsm->master;
01409 
01410     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
01411 
01412     if (!ec_fsm_change_success(&fsm->fsm_change)) {
01413         slave->error_flag = 1;
01414         fsm->slave_state = ec_fsm_slave_state_error;
01415         return;
01416     }
01417 
01418     // slave is now in PREOP
01419     slave->jiffies_preop = fsm->datagram.jiffies_received;
01420 
01421     if (master->debug_level) {
01422         EC_DBG("Slave %i is now in PREOP.\n", slave->ring_position);
01423     }
01424 
01425     if (slave->current_state == slave->requested_state) {
01426         fsm->slave_state = ec_fsm_slave_state_end; // successful
01427         if (master->debug_level) {
01428             EC_DBG("Finished configuration of slave %i.\n",
01429                    slave->ring_position);
01430         }
01431         return;
01432     }
01433 
01434     ec_fsm_slaveconf_enter_sync2(fsm);
01435 }
01436 
01437 /*****************************************************************************/
01438 
01442 void ec_fsm_slaveconf_enter_sync2(ec_fsm_t *fsm )
01443 {
01444     ec_slave_t *slave = fsm->slave;
01445     ec_datagram_t *datagram = &fsm->datagram;
01446     ec_sii_sync_t *sync;
01447 
01448     if (list_empty(&slave->sii_syncs)) {
01449         ec_fsm_slaveconf_enter_fmmu(fsm);
01450         return;
01451     }
01452 
01453     // configure sync managers for process data
01454     ec_datagram_npwr(datagram, slave->station_address, 0x0800,
01455                      EC_SYNC_SIZE * slave->base_sync_count);
01456     memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
01457 
01458     list_for_each_entry(sync, &slave->sii_syncs, list) {
01459         ec_sync_config(sync, slave,
01460                        datagram->data + EC_SYNC_SIZE * sync->index);
01461     }
01462 
01463     ec_master_queue_datagram(fsm->master, datagram);
01464     fsm->slave_state = ec_fsm_slaveconf_state_sync2;
01465 }
01466 
01467 /*****************************************************************************/
01468 
01473 void ec_fsm_slaveconf_state_sync2(ec_fsm_t *fsm )
01474 {
01475     ec_datagram_t *datagram = &fsm->datagram;
01476     ec_slave_t *slave = fsm->slave;
01477 
01478     if (datagram->state != EC_DATAGRAM_RECEIVED
01479         || datagram->working_counter != 1) {
01480         slave->error_flag = 1;
01481         fsm->slave_state = ec_fsm_slave_state_error;
01482         EC_ERR("Failed to set process data sync managers on slave %i.\n",
01483                slave->ring_position);
01484         return;
01485     }
01486 
01487     ec_fsm_slaveconf_enter_fmmu(fsm);
01488 }
01489 
01490 /*****************************************************************************/
01491 
01495 void ec_fsm_slaveconf_enter_fmmu(ec_fsm_t *fsm )
01496 {
01497     ec_slave_t *slave = fsm->slave;
01498     ec_master_t *master = slave->master;
01499     ec_datagram_t *datagram = &fsm->datagram;
01500     unsigned int j;
01501 
01502     if (!slave->base_fmmu_count) { // skip FMMU configuration
01503         ec_fsm_slaveconf_enter_sdoconf(fsm);
01504         return;
01505     }
01506 
01507     // configure FMMUs
01508     ec_datagram_npwr(datagram, slave->station_address,
01509                      0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
01510     memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
01511     for (j = 0; j < slave->fmmu_count; j++) {
01512         ec_fmmu_config(&slave->fmmus[j], slave,
01513                        datagram->data + EC_FMMU_SIZE * j);
01514     }
01515 
01516     ec_master_queue_datagram(master, datagram);
01517     fsm->slave_state = ec_fsm_slaveconf_state_fmmu;
01518 }
01519 
01520 /*****************************************************************************/
01521 
01526 void ec_fsm_slaveconf_state_fmmu(ec_fsm_t *fsm )
01527 {
01528     ec_datagram_t *datagram = &fsm->datagram;
01529     ec_slave_t *slave = fsm->slave;
01530 
01531     if (datagram->state != EC_DATAGRAM_RECEIVED
01532         || datagram->working_counter != 1) {
01533         fsm->slave->error_flag = 1;
01534         fsm->slave_state = ec_fsm_slave_state_error;
01535         EC_ERR("Failed to set FMMUs on slave %i.\n",
01536                fsm->slave->ring_position);
01537         return;
01538     }
01539 
01540     // No CoE configuration to be applied? Jump to SAVEOP state.
01541     if (list_empty(&slave->sdo_confs)) { // skip SDO configuration
01542         ec_fsm_slaveconf_enter_saveop(fsm);
01543         return;
01544     }
01545 
01546     ec_fsm_slaveconf_enter_sdoconf(fsm);
01547 }
01548 
01549 /*****************************************************************************/
01550 
01554 void ec_fsm_slaveconf_enter_sdoconf(ec_fsm_t *fsm )
01555 {
01556     ec_slave_t *slave = fsm->slave;
01557 
01558     if (list_empty(&slave->sdo_confs)) { // skip SDO configuration
01559         ec_fsm_slaveconf_enter_saveop(fsm);
01560         return;
01561     }
01562 
01563     // start SDO configuration
01564     fsm->slave_state = ec_fsm_slaveconf_state_sdoconf;
01565     fsm->sdodata = list_entry(fsm->slave->sdo_confs.next, ec_sdo_data_t, list);
01566     ec_fsm_coe_download(&fsm->fsm_coe, fsm->slave, fsm->sdodata);
01567     ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
01568 }
01569 
01570 /*****************************************************************************/
01571 
01576 void ec_fsm_slaveconf_state_sdoconf(ec_fsm_t *fsm )
01577 {
01578     if (ec_fsm_coe_exec(&fsm->fsm_coe)) return;
01579 
01580     if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
01581         fsm->slave->error_flag = 1;
01582         fsm->slave_state = ec_fsm_slave_state_error;
01583         return;
01584     }
01585 
01586     // Another SDO to configure?
01587     if (fsm->sdodata->list.next != &fsm->slave->sdo_confs) {
01588         fsm->sdodata = list_entry(fsm->sdodata->list.next,
01589                                   ec_sdo_data_t, list);
01590         ec_fsm_coe_download(&fsm->fsm_coe, fsm->slave, fsm->sdodata);
01591         ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
01592         return;
01593     }
01594 
01595     // All SDOs are now configured.
01596 
01597     // set state to SAVEOP
01598     ec_fsm_slaveconf_enter_saveop(fsm);
01599 }
01600 
01601 /*****************************************************************************/
01602 
01606 void ec_fsm_slaveconf_enter_saveop(ec_fsm_t *fsm )
01607 {
01608     fsm->slave_state = ec_fsm_slaveconf_state_saveop;
01609     ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_SAVEOP);
01610     ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
01611 }
01612 
01613 /*****************************************************************************/
01614 
01619 void ec_fsm_slaveconf_state_saveop(ec_fsm_t *fsm )
01620 {
01621     ec_master_t *master = fsm->master;
01622     ec_slave_t *slave = fsm->slave;
01623 
01624     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
01625 
01626     if (!ec_fsm_change_success(&fsm->fsm_change)) {
01627         fsm->slave->error_flag = 1;
01628         fsm->slave_state = ec_fsm_slave_state_error;
01629         return;
01630     }
01631 
01632     // slave is now in SAVEOP
01633 
01634     if (master->debug_level) {
01635         EC_DBG("Slave %i is now in SAVEOP.\n", slave->ring_position);
01636     }
01637 
01638     if (fsm->slave->current_state == fsm->slave->requested_state) {
01639         fsm->slave_state = ec_fsm_slave_state_end; // successful
01640         if (master->debug_level) {
01641             EC_DBG("Finished configuration of slave %i.\n",
01642                    slave->ring_position);
01643         }
01644         return;
01645     }
01646 
01647     // set state to OP
01648     fsm->slave_state = ec_fsm_slaveconf_state_op;
01649     ec_fsm_change_start(&fsm->fsm_change, slave, EC_SLAVE_STATE_OP);
01650     ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
01651 }
01652 
01653 /*****************************************************************************/
01654 
01659 void ec_fsm_slaveconf_state_op(ec_fsm_t *fsm )
01660 {
01661     ec_master_t *master = fsm->master;
01662     ec_slave_t *slave = fsm->slave;
01663 
01664     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
01665 
01666     if (!ec_fsm_change_success(&fsm->fsm_change)) {
01667         slave->error_flag = 1;
01668         fsm->slave_state = ec_fsm_slave_state_error;
01669         return;
01670     }
01671 
01672     // slave is now in OP
01673 
01674     if (master->debug_level) {
01675         EC_DBG("Slave %i is now in OP.\n", slave->ring_position);
01676         EC_DBG("Finished configuration of slave %i.\n", slave->ring_position);
01677     }
01678 
01679     fsm->slave_state = ec_fsm_slave_state_end; // successful
01680 }
01681 
01682 /******************************************************************************
01683  *  Common state functions
01684  *****************************************************************************/
01685 
01690 void ec_fsm_slave_state_error(ec_fsm_t *fsm )
01691 {
01692 }
01693 
01694 /*****************************************************************************/
01695 
01700 void ec_fsm_slave_state_end(ec_fsm_t *fsm )
01701 {
01702 }
01703 
01704 /*****************************************************************************/

Generated on Tue Nov 7 15:03:35 2006 for IgH EtherCAT master by  doxygen 1.4.4