fsm.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: fsm.c 533 2006-09-01 12:35:41Z 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_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  *  master startup state machine
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         // no slaves present -> finish state machine.
00281         fsm->master_state = ec_fsm_end;
00282         return;
00283     }
00284 
00285     // init slaves
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); // free
00302             fsm->master_state = ec_fsm_error;
00303             return;
00304         }
00305 
00306         list_add_tail(&slave->list, &master->slaves);
00307     }
00308 
00309     // begin scanning of slaves
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); // execute immediately
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); // execute slave state machine
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     // another slave to scan?
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); // execute immediately
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  *  master configuration state machine
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     // begin configuring slaves
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); // execute immediately
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); // execute slave's state machine
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     // another slave to configure?
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); // execute immediately
00407         return;
00408     }
00409 
00410     fsm->master_state = ec_fsm_end;
00411 }
00412 
00413 /******************************************************************************
00414  *  operation / idle state machine
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); // execute immediately
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; // start validation later
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     // topology change in idle mode: clear all slaves and scan the bus
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             // no slaves present -> finish state machine.
00494             fsm->master_state = ec_fsm_master_start;
00495             fsm->master_state(fsm); // execute immediately
00496             return;
00497         }
00498 
00499         // init slaves
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); // execute immediately
00507                 return;
00508             }
00509 
00510             if (ec_slave_init(slave, master, i, i + 1)) {
00511                 // freeing of "slave" already done
00512                 ec_master_clear_slaves(master);
00513                 fsm->master_state = ec_fsm_master_start;
00514                 fsm->master_state(fsm); // execute immediately
00515                 return;
00516             }
00517 
00518             if (kobject_add(&slave->kobj)) {
00519                 EC_ERR("Failed to add kobject.\n");
00520                 kobject_put(&slave->kobj); // free
00521                 ec_master_clear_slaves(master);
00522                 fsm->master_state = ec_fsm_master_start;
00523                 fsm->master_state(fsm); // execute immediately
00524                 return;
00525             }
00526 
00527             list_add_tail(&slave->list, &master->slaves);
00528         }
00529 
00530         // begin scanning of slaves
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); // execute immediately
00535         return;
00536     }
00537 
00538     // fetch state from each slave
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     // check if any slaves are not in the state, they're supposed to be
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); // execute immediately
00578         return;
00579     }
00580 
00581     // Check, if EoE processing has to be started
00582     ec_master_eoe_start(master);
00583 
00584     if (master->mode == EC_MASTER_MODE_IDLE) {
00585         // nothing to configure. check for pending EEPROM write operations.
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             // found pending EEPROM write operation. execute it!
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); // execute immediately
00606             return;
00607         }
00608     }
00609 
00610     // nothing to do. restart master state machine.
00611     fsm->master_state = ec_fsm_master_start;
00612     fsm->master_state(fsm); // execute immediately
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     // is there another slave to query?
00628     if (slave->list.next != &master->slaves) {
00629         // process next slave
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     // all slave states read
00639 
00640     // check, if a bus validation has to be done
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             // At least one slave is offline. validate!
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; // vendor ID
00651             fsm->sii_mode = 0;
00652             fsm->sii_state = ec_fsm_sii_start_reading;
00653             fsm->sii_state(fsm); // execute immediately
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); // execute immediately
00677         return;
00678     }
00679 
00680     // did the slave not respond to its station address?
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     // slave responded
00691     new_state = EC_READ_U8(datagram->data);
00692     if (!slave->online) { // slave was offline before
00693         char cur_state[25];
00694         slave->online = 1;
00695         slave->error_flag = 0; // clear error flag
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); // execute SII state machine
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); // execute immediately
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); // execute immediately
00740         return;
00741     }
00742 
00743     // vendor ID is ok. check product code.
00744     fsm->master_state = ec_fsm_master_validate_product;
00745     fsm->sii_offset = 0x000A; // product code
00746     fsm->sii_mode = 0;
00747     fsm->sii_state = ec_fsm_sii_start_reading;
00748     fsm->sii_state(fsm); // execute immediately
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) { // last slave?
00765             fsm->master_state = ec_fsm_master_start;
00766             fsm->master_state(fsm); // execute immediately
00767             return;
00768         }
00769         // check next slave
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     // write station address
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); // execute SII state machine
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); // execute immediately
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); // execute immediately
00812         return;
00813     }
00814 
00815     // have all states been validated?
00816     if (slave->list.next == &fsm->master->slaves) {
00817         fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list);
00818         // start writing addresses to offline slaves
00819         ec_fsm_master_action_addresses(fsm);
00820         return;
00821     }
00822 
00823     // validate next slave
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; // vendor ID
00827     fsm->sii_mode = 0;
00828     fsm->sii_state = ec_fsm_sii_start_reading;
00829     fsm->sii_state(fsm); // execute immediately
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) { // last slave?
00853         fsm->master_state = ec_fsm_master_start;
00854         fsm->master_state(fsm); // execute immediately
00855         return;
00856     }
00857 
00858     // check next slave
00859     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00860     // Write new station address to slave
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); // execute slave state machine
00878 
00879     if (fsm->slave_state != ec_fsm_end
00880         && fsm->slave_state != ec_fsm_error) return;
00881 
00882     // another slave to fetch?
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); // execute immediately
00887         return;
00888     }
00889 
00890     EC_INFO("Bus scanning completed.\n");
00891 
00892     ec_master_calc_addressing(master);
00893 
00894     // determine initial states.
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); // execute immediately
00909 }
00910 
00911 /*****************************************************************************/
00912 
00918 void ec_fsm_master_configure_slave(ec_fsm_t *fsm
00920                                    )
00921 {
00922     fsm->slave_state(fsm); // execute slave's state machine
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); // execute SII state machine
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); // execute immediately
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); // execute immediately
00960         return;
00961     }
00962 
00963     // finished writing EEPROM
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     // TODO: Evaluate new EEPROM contents!
00969 
00970     // restart master state machine.
00971     fsm->master_state = ec_fsm_master_start;
00972     fsm->master_state(fsm); // execute immediately
00973     return;
00974 }
00975 
00976 /******************************************************************************
00977  *  slave scan state machine
00978  *****************************************************************************/
00979 
00986 void ec_fsm_slavescan_start(ec_fsm_t *fsm )
00987 {
00988     ec_datagram_t *datagram = &fsm->datagram;
00989 
00990     // write station address
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     // Read AL state
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     // read base data
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     // read data link status
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     // Start fetching EEPROM size
01120 
01121     fsm->sii_offset = 0x0040; // first category header
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); // execute state immediately
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     // execute SII state machine
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) { // not the last category
01156         fsm->sii_offset += cat_size + 2;
01157         fsm->sii_state = ec_fsm_sii_start_reading;
01158         fsm->sii_state(fsm); // execute state immediately
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     // Start fetching EEPROM contents
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); // execute state immediately
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     // execute SII state machine
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     // 2 words fetched
01213 
01214     if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit
01215         memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4);
01216     }
01217     else { // copy the last word
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         // fetch the next 2 words
01223         fsm->sii_offset += 2;
01224         fsm->sii_state = ec_fsm_sii_start_reading;
01225         fsm->sii_state(fsm); // execute state immediately
01226         return;
01227     }
01228 
01229     // Evaluate EEPROM contents
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     // evaluate category data
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  *  slave configuration state machine
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); // execute state change state machine
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     // slave is now in INIT
01325     if (slave->current_state == slave->requested_state) {
01326         fsm->slave_state = ec_fsm_end; // successful
01327         return;
01328     }
01329 
01330     // check and reset CRC fault counters
01331     //ec_slave_check_crc(slave);
01332     // TODO: Implement state machine for CRC checking.
01333 
01334     if (!slave->base_sync_count) { // no sync managers
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); // execute immediately
01339         return;
01340     }
01341 
01342     // configure sync managers
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); // execute immediately
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); // execute state change state machine
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     // slave is now in PREOP
01412     if (slave->current_state == slave->requested_state) {
01413         fsm->slave_state = ec_fsm_end; // successful
01414         return;
01415     }
01416 
01417     if (!slave->base_fmmu_count) { // skip FMMU configuration
01418         if (list_empty(&slave->sdo_confs)) { // skip SDO configuration
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); // execute immediately
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); // execute immediately
01429         return;
01430     }
01431 
01432     // configure FMMUs
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     // No CoE configuration to be applied? Jump to SAVEOP state.
01466     if (list_empty(&slave->sdo_confs)) { // skip SDO configuration
01467         // set state to SAVEOP
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); // execute immediately
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); // execute immediately
01479 }
01480 
01481 /*****************************************************************************/
01482 
01487 void ec_fsm_slaveconf_sdoconf(ec_fsm_t *fsm )
01488 {
01489     fsm->coe_state(fsm); // execute CoE state machine
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     // Another SDO to configure?
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); // execute immediately
01505         return;
01506     }
01507 
01508     // All SDOs are now configured.
01509 
01510     // set state to SAVEOP
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); // execute immediately
01515 }
01516 
01517 /*****************************************************************************/
01518 
01523 void ec_fsm_slaveconf_saveop(ec_fsm_t *fsm )
01524 {
01525     fsm->change_state(fsm); // execute state change state machine
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     // slave is now in SAVEOP
01536     if (fsm->slave->current_state == fsm->slave->requested_state) {
01537         fsm->slave_state = ec_fsm_end; // successful
01538         return;
01539     }
01540 
01541     // set state to OP
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); // execute immediately
01546 }
01547 
01548 /*****************************************************************************/
01549 
01554 void ec_fsm_slaveconf_op(ec_fsm_t *fsm )
01555 {
01556     fsm->change_state(fsm); // execute state change state machine
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     // slave is now in OP
01567     fsm->slave_state = ec_fsm_end; // successful
01568 }
01569 
01570 /******************************************************************************
01571  *  SII state machine
01572  *****************************************************************************/
01573 
01579 void ec_fsm_sii_start_reading(ec_fsm_t *fsm )
01580 {
01581     ec_datagram_t *datagram = &fsm->datagram;
01582 
01583     // initiate read operation
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); // read-only access
01592     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
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     // issue check/fetch datagram
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     // check "busy bit"
01649     if (EC_READ_U8(datagram->data + 1) & 0x81) {
01650         // still busy... timeout?
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         // issue check/fetch datagram again
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     // SII value received.
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     // initiate write operation
01699     ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
01700     EC_WRITE_U8 (datagram->data,     0x01); // enable write access
01701     EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
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     // issue check/fetch datagram
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         // still busy... timeout?
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         // issue check/fetch datagram again
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 { // success
01765         fsm->sii_state = ec_fsm_end;
01766     }
01767 }
01768 
01769 /******************************************************************************
01770  *  state change state machine
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     // write new state to slave
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         // repeat writing new state to slave
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     // read AL status from slave
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         // state has been set successfully
01855         fsm->change_state = ec_fsm_end;
01856         return;
01857     }
01858 
01859     if (slave->current_state & 0x10) {
01860         // state change error
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         // fetch AL status error code
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) { // 100ms
01873         // timeout while checking
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     // still old state: check again
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     // acknowledge "old" slave state
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     // read new AL status
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) { // 100ms
02018         // timeout while checking
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     // reread new AL status
02027     ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
02028     ec_master_queue_datagram(fsm->master, datagram);
02029 }
02030 
02031 /******************************************************************************
02032  *  CoE state machine
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); // SDO request
02062     EC_WRITE_U8 (data + 2, (0x1 // size specified
02063                             | 0x1 << 5)); // Download request
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); // can not fail.
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); // can not fail.
02125         ec_master_queue_datagram(fsm->master, datagram);
02126         return;
02127     }
02128 
02129     // Fetch response
02130     ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
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 && // SDO request
02169         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
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 || // SDO response
02184         EC_READ_U8 (data + 2) >> 5 != 0x3 || // Download response
02185         EC_READ_U16(data + 3) != sdodata->index || // index
02186         EC_READ_U8 (data + 5) != sdodata->subindex) { // 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; // success
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  *  Common state functions
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 /*****************************************************************************/

Generated on Fri Sep 1 14:56:56 2006 for IgH EtherCAT master by  doxygen 1.4.6