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

fsm_coe.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: fsm_coe.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 "master.h"
00043 #include "mailbox.h"
00044 #include "fsm_coe.h"
00045 
00046 /*****************************************************************************/
00047 
00048 void ec_fsm_coe_dict_start(ec_fsm_coe_t *);
00049 void ec_fsm_coe_dict_request(ec_fsm_coe_t *);
00050 void ec_fsm_coe_dict_check(ec_fsm_coe_t *);
00051 void ec_fsm_coe_dict_response(ec_fsm_coe_t *);
00052 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *);
00053 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *);
00054 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *);
00055 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *);
00056 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *);
00057 void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *);
00058 
00059 void ec_fsm_coe_down_start(ec_fsm_coe_t *);
00060 void ec_fsm_coe_down_request(ec_fsm_coe_t *);
00061 void ec_fsm_coe_down_check(ec_fsm_coe_t *);
00062 void ec_fsm_coe_down_response(ec_fsm_coe_t *);
00063 
00064 void ec_fsm_coe_up_start(ec_fsm_coe_t *);
00065 void ec_fsm_coe_up_request(ec_fsm_coe_t *);
00066 void ec_fsm_coe_up_check(ec_fsm_coe_t *);
00067 void ec_fsm_coe_up_response(ec_fsm_coe_t *);
00068 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *);
00069 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *);
00070 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *);
00071 
00072 void ec_fsm_coe_end(ec_fsm_coe_t *);
00073 void ec_fsm_coe_error(ec_fsm_coe_t *);
00074 
00075 /*****************************************************************************/
00076 
00084 const ec_code_msg_t sdo_abort_messages[] = {
00085     {0x05030000, "Toggle bit not changed"},
00086     {0x05040000, "SDO protocol timeout"},
00087     {0x05040001, "Client/Server command specifier not valid or unknown"},
00088     {0x05040005, "Out of memory"},
00089     {0x06010000, "Unsupported access to an object"},
00090     {0x06010001, "Attempt to read a write-only object"},
00091     {0x06010002, "Attempt to write a read-only object"},
00092     {0x06020000, "This object does not exist in the object directory"},
00093     {0x06040041, "The object cannot be mapped into the PDO"},
00094     {0x06040042, "The number and length of the objects to be mapped would"
00095      " exceed the PDO length"},
00096     {0x06040043, "General parameter incompatibility reason"},
00097     {0x06040047, "Gerneral internal incompatibility in device"},
00098     {0x06060000, "Access failure due to a hardware error"},
00099     {0x06070010, "Data type does not match, length of service parameter does"
00100      " not match"},
00101     {0x06070012, "Data type does not match, length of service parameter too"
00102      " high"},
00103     {0x06070013, "Data type does not match, length of service parameter too"
00104      " low"},
00105     {0x06090011, "Subindex does not exist"},
00106     {0x06090030, "Value range of parameter exceeded"},
00107     {0x06090031, "Value of parameter written too high"},
00108     {0x06090032, "Value of parameter written too low"},
00109     {0x06090036, "Maximum value is less than minimum value"},
00110     {0x08000000, "General error"},
00111     {0x08000020, "Data cannot be transferred or stored to the application"},
00112     {0x08000021, "Data cannot be transferred or stored to the application"
00113      " because of local control"},
00114     {0x08000022, "Data cannot be transferred or stored to the application"
00115      " because of the present device state"},
00116     {0x08000023, "Object dictionary dynamic generation fails or no object"
00117      " dictionary is present"},
00118     {}
00119 };
00120 
00121 /*****************************************************************************/
00122 
00127 void ec_canopen_abort_msg(uint32_t abort_code)
00128 {
00129     const ec_code_msg_t *abort_msg;
00130 
00131     for (abort_msg = sdo_abort_messages; abort_msg->code; abort_msg++) {
00132         if (abort_msg->code == abort_code) {
00133             EC_ERR("SDO abort message 0x%08X: \"%s\".\n",
00134                    abort_msg->code, abort_msg->message);
00135             return;
00136         }
00137     }
00138 
00139     EC_ERR("Unknown SDO abort code 0x%08X.\n", abort_code);
00140 }
00141 
00142 /*****************************************************************************/
00143 
00148 void ec_fsm_coe_init(ec_fsm_coe_t *fsm, 
00149                      ec_datagram_t *datagram 
00150                      )
00151 {
00152     fsm->state = NULL;
00153     fsm->datagram = datagram;
00154 }
00155 
00156 /*****************************************************************************/
00157 
00162 void ec_fsm_coe_clear(ec_fsm_coe_t *fsm )
00163 {
00164 }
00165 
00166 /*****************************************************************************/
00167 
00172 void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm, 
00173                            ec_slave_t *slave 
00174                            )
00175 {
00176     fsm->slave = slave;
00177     fsm->state = ec_fsm_coe_dict_start;
00178 }
00179 
00180 /*****************************************************************************/
00181 
00186 void ec_fsm_coe_download(ec_fsm_coe_t *fsm, 
00187                          ec_slave_t *slave, 
00188                          ec_sdo_data_t *sdodata 
00189                          )
00190 {
00191     fsm->slave = slave;
00192     fsm->sdodata = sdodata;
00193     fsm->state = ec_fsm_coe_down_start;
00194 }
00195 
00196 /*****************************************************************************/
00197 
00202 void ec_fsm_coe_upload(ec_fsm_coe_t *fsm, 
00203                        ec_slave_t *slave, 
00204                        ec_sdo_request_t *request 
00205                        )
00206 {
00207     fsm->slave = slave;
00208     fsm->request = request;
00209     fsm->state = ec_fsm_coe_up_start;
00210 }
00211 
00212 /*****************************************************************************/
00213 
00219 int ec_fsm_coe_exec(ec_fsm_coe_t *fsm )
00220 {
00221     fsm->state(fsm);
00222 
00223     return fsm->state != ec_fsm_coe_end && fsm->state != ec_fsm_coe_error;
00224 }
00225 
00226 /*****************************************************************************/
00227 
00233 int ec_fsm_coe_success(ec_fsm_coe_t *fsm )
00234 {
00235     return fsm->state == ec_fsm_coe_end;
00236 }
00237 
00238 /******************************************************************************
00239  *  CoE dictionary state machine
00240  *****************************************************************************/
00241 
00246 void ec_fsm_coe_dict_start(ec_fsm_coe_t *fsm )
00247 {
00248     ec_datagram_t *datagram = fsm->datagram;
00249     ec_slave_t *slave = fsm->slave;
00250     uint8_t *data;
00251 
00252     if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8))) {
00253         fsm->state = ec_fsm_coe_error;
00254         return;
00255     }
00256 
00257     EC_WRITE_U16(data, 0x8 << 12); // SDO information
00258     EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request
00259     EC_WRITE_U8 (data + 3, 0x00);
00260     EC_WRITE_U16(data + 4, 0x0000);
00261     EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs!
00262 
00263     ec_master_queue_datagram(fsm->slave->master, datagram);
00264     fsm->state = ec_fsm_coe_dict_request;
00265 }
00266 
00267 /*****************************************************************************/
00268 
00273 void ec_fsm_coe_dict_request(ec_fsm_coe_t *fsm )
00274 {
00275     ec_datagram_t *datagram = fsm->datagram;
00276     ec_slave_t *slave = fsm->slave;
00277 
00278     if (datagram->state != EC_DATAGRAM_RECEIVED
00279         || datagram->working_counter != 1) {
00280         fsm->state = ec_fsm_coe_error;
00281         EC_ERR("Reception of CoE dictionary request failed on slave %i.\n",
00282                slave->ring_position);
00283         return;
00284     }
00285 
00286     fsm->cycles_start = datagram->cycles_sent;
00287 
00288     ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00289     ec_master_queue_datagram(fsm->slave->master, datagram);
00290     fsm->state = ec_fsm_coe_dict_check;
00291 }
00292 
00293 /*****************************************************************************/
00294 
00299 void ec_fsm_coe_dict_check(ec_fsm_coe_t *fsm )
00300 {
00301     ec_datagram_t *datagram = fsm->datagram;
00302     ec_slave_t *slave = fsm->slave;
00303 
00304     if (datagram->state != EC_DATAGRAM_RECEIVED
00305         || datagram->working_counter != 1) {
00306         fsm->state = ec_fsm_coe_error;
00307         EC_ERR("Reception of CoE mailbox check datagram failed on slave %i.\n",
00308                slave->ring_position);
00309         return;
00310     }
00311 
00312     if (!ec_slave_mbox_check(datagram)) {
00313         if (datagram->cycles_received
00314             - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00315             fsm->state = ec_fsm_coe_error;
00316             EC_ERR("Timeout while checking SDO dictionary on slave %i.\n",
00317                    slave->ring_position);
00318             return;
00319         }
00320 
00321         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00322         ec_master_queue_datagram(fsm->slave->master, datagram);
00323         return;
00324     }
00325 
00326     // Fetch response
00327     ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
00328     ec_master_queue_datagram(fsm->slave->master, datagram);
00329     fsm->state = ec_fsm_coe_dict_response;
00330 }
00331 
00332 /*****************************************************************************/
00333 
00338 void ec_fsm_coe_dict_response(ec_fsm_coe_t *fsm )
00339 {
00340     ec_datagram_t *datagram = fsm->datagram;
00341     ec_slave_t *slave = fsm->slave;
00342     uint8_t *data, mbox_prot;
00343     size_t rec_size;
00344     unsigned int sdo_count, i;
00345     uint16_t sdo_index;
00346     ec_sdo_t *sdo;
00347 
00348     if (datagram->state != EC_DATAGRAM_RECEIVED
00349         || datagram->working_counter != 1) {
00350         fsm->state = ec_fsm_coe_error;
00351         EC_ERR("Reception of CoE dictionary response failed on slave %i.\n",
00352                slave->ring_position);
00353         return;
00354     }
00355 
00356     if (!(data = ec_slave_mbox_fetch(slave, datagram,
00357                      &mbox_prot, &rec_size))) {
00358         fsm->state = ec_fsm_coe_error;
00359         return;
00360     }
00361 
00362     if (mbox_prot != 0x03) { // CoE
00363         EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00364         fsm->state = ec_fsm_coe_error;
00365     return;
00366     }
00367 
00368     if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
00369         (EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response
00370         EC_ERR("SDO information error response at slave %i!\n",
00371                slave->ring_position);
00372         ec_canopen_abort_msg(EC_READ_U32(data + 6));
00373         fsm->state = ec_fsm_coe_error;
00374     return;
00375     }
00376 
00377     if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
00378         (EC_READ_U8 (data + 2) & 0x7F) != 0x02) { // Get OD List response
00379         EC_ERR("Invalid SDO list response at slave %i!\n",
00380                slave->ring_position);
00381         ec_print_data(data, rec_size);
00382         fsm->state = ec_fsm_coe_error;
00383     return;
00384     }
00385 
00386     if (rec_size < 8) {
00387         EC_ERR("Invalid data size!\n");
00388         ec_print_data(data, rec_size);
00389         fsm->state = ec_fsm_coe_error;
00390     return;
00391     }
00392 
00393     sdo_count = (rec_size - 8) / 2;
00394 
00395     for (i = 0; i < sdo_count; i++) {
00396         sdo_index = EC_READ_U16(data + 8 + i * 2);
00397         if (!sdo_index) {
00398             if (slave->master->debug_level)
00399                 EC_WARN("SDO dictionary of slave %i contains index 0x0000.\n",
00400                         slave->ring_position);
00401             continue;
00402         }
00403 
00404         if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_ATOMIC))) {
00405             EC_ERR("Failed to allocate memory for SDO!\n");
00406             fsm->state = ec_fsm_coe_error;
00407             return;
00408         }
00409 
00410         if (ec_sdo_init(sdo, sdo_index, slave)) {
00411             EC_ERR("Failed to init SDO!\n");
00412             fsm->state = ec_fsm_coe_error;
00413             return;
00414         }
00415 
00416         list_add_tail(&sdo->list, &slave->sdo_dictionary);
00417     }
00418 
00419     if (EC_READ_U8(data + 2) & 0x80) { // more messages waiting. check again.
00420         fsm->cycles_start = datagram->cycles_sent;
00421         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00422         ec_master_queue_datagram(fsm->slave->master, datagram);
00423         fsm->state = ec_fsm_coe_dict_check;
00424         return;
00425     }
00426 
00427     if (list_empty(&slave->sdo_dictionary)) {
00428         // no SDOs in dictionary. finished.
00429         fsm->state = ec_fsm_coe_end; // success
00430         return;
00431     }
00432 
00433     // fetch SDO descriptions
00434     fsm->sdo = list_entry(slave->sdo_dictionary.next, ec_sdo_t, list);
00435 
00436     if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8))) {
00437         fsm->state = ec_fsm_coe_error;
00438         return;
00439     }
00440 
00441     EC_WRITE_U16(data, 0x8 << 12); // SDO information
00442     EC_WRITE_U8 (data + 2, 0x03); // Get object description request
00443     EC_WRITE_U8 (data + 3, 0x00);
00444     EC_WRITE_U16(data + 4, 0x0000);
00445     EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index
00446 
00447     ec_master_queue_datagram(fsm->slave->master, datagram);
00448     fsm->state = ec_fsm_coe_dict_desc_request;
00449 }
00450 
00451 /*****************************************************************************/
00452 
00457 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *fsm )
00458 {
00459     ec_datagram_t *datagram = fsm->datagram;
00460     ec_slave_t *slave = fsm->slave;
00461 
00462     if (datagram->state != EC_DATAGRAM_RECEIVED
00463         || datagram->working_counter != 1) {
00464         fsm->state = ec_fsm_coe_error;
00465         EC_ERR("Reception of CoE SDO description"
00466                " request failed on slave %i.\n", slave->ring_position);
00467         return;
00468     }
00469 
00470     fsm->cycles_start = datagram->cycles_sent;
00471 
00472     ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00473     ec_master_queue_datagram(fsm->slave->master, datagram);
00474     fsm->state = ec_fsm_coe_dict_desc_check;
00475 }
00476 
00477 /*****************************************************************************/
00478 
00483 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *fsm )
00484 {
00485     ec_datagram_t *datagram = fsm->datagram;
00486     ec_slave_t *slave = fsm->slave;
00487 
00488     if (datagram->state != EC_DATAGRAM_RECEIVED
00489         || datagram->working_counter != 1) {
00490         fsm->state = ec_fsm_coe_error;
00491         EC_ERR("Reception of CoE mailbox check datagram failed on slave %i.\n",
00492                slave->ring_position);
00493         return;
00494     }
00495 
00496     if (!ec_slave_mbox_check(datagram)) {
00497         if (datagram->cycles_received
00498             - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00499             fsm->state = ec_fsm_coe_error;
00500             EC_ERR("Timeout while checking SDO description on slave %i.\n",
00501                    slave->ring_position);
00502             return;
00503         }
00504 
00505         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00506         ec_master_queue_datagram(fsm->slave->master, datagram);
00507         return;
00508     }
00509 
00510     // Fetch response
00511     ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
00512     ec_master_queue_datagram(fsm->slave->master, datagram);
00513     fsm->state = ec_fsm_coe_dict_desc_response;
00514 }
00515 
00516 /*****************************************************************************/
00517 
00522 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *fsm)
00524 {
00525     ec_datagram_t *datagram = fsm->datagram;
00526     ec_slave_t *slave = fsm->slave;
00527     ec_sdo_t *sdo = fsm->sdo;
00528     uint8_t *data, mbox_prot;
00529     size_t rec_size, name_size;
00530 
00531     if (datagram->state != EC_DATAGRAM_RECEIVED
00532         || datagram->working_counter != 1) {
00533         fsm->state = ec_fsm_coe_error;
00534         EC_ERR("Reception of CoE SDO description"
00535                "response failed on slave %i.\n", slave->ring_position);
00536         return;
00537     }
00538 
00539     if (!(data = ec_slave_mbox_fetch(slave, datagram,
00540                      &mbox_prot, &rec_size))) {
00541         fsm->state = ec_fsm_coe_error;
00542         return;
00543     }
00544 
00545     if (mbox_prot != 0x03) { // CoE
00546         EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00547         fsm->state = ec_fsm_coe_error;
00548     return;
00549     }
00550 
00551     if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
00552         (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
00553         EC_ERR("SDO information error response at slave %i while"
00554                " fetching SDO 0x%04X!\n", slave->ring_position,
00555                sdo->index);
00556         ec_canopen_abort_msg(EC_READ_U32(data + 6));
00557         fsm->state = ec_fsm_coe_error;
00558     return;
00559     }
00560 
00561     if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
00562         (EC_READ_U8 (data + 2) & 0x7F) != 0x04 || // Object desc. response
00563         EC_READ_U16(data + 6) != sdo->index) { // SDO index
00564         EC_ERR("Invalid object description response at slave %i while"
00565                " fetching SDO 0x%04X!\n", slave->ring_position,
00566                sdo->index);
00567         ec_print_data(data, rec_size);
00568         fsm->state = ec_fsm_coe_error;
00569     return;
00570     }
00571 
00572     if (rec_size < 12) {
00573         EC_ERR("Invalid data size!\n");
00574         ec_print_data(data, rec_size);
00575         fsm->state = ec_fsm_coe_error;
00576     return;
00577     }
00578 
00579     sdo->subindices = EC_READ_U8(data + 10);
00580     sdo->object_code = EC_READ_U8(data + 11);
00581 
00582     name_size = rec_size - 12;
00583     if (name_size) {
00584         if (!(sdo->name = kmalloc(name_size + 1, GFP_ATOMIC))) {
00585             EC_ERR("Failed to allocate SDO name!\n");
00586             fsm->state = ec_fsm_coe_error;
00587             return;
00588         }
00589 
00590         memcpy(sdo->name, data + 12, name_size);
00591         sdo->name[name_size] = 0;
00592     }
00593 
00594     if (EC_READ_U8(data + 2) & 0x80) {
00595         EC_ERR("Fragment follows (not implemented)!\n");
00596         fsm->state = ec_fsm_coe_error;
00597     return;
00598     }
00599 
00600     // start fetching entries
00601 
00602     fsm->subindex = 0;
00603 
00604     if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10))) {
00605         fsm->state = ec_fsm_coe_error;
00606         return;
00607     }
00608 
00609     EC_WRITE_U16(data, 0x8 << 12); // SDO information
00610     EC_WRITE_U8 (data + 2, 0x05); // Get entry description request
00611     EC_WRITE_U8 (data + 3, 0x00);
00612     EC_WRITE_U16(data + 4, 0x0000);
00613     EC_WRITE_U16(data + 6, sdo->index); // SDO index
00614     EC_WRITE_U8 (data + 8, fsm->subindex); // SDO subindex
00615     EC_WRITE_U8 (data + 9, 0x00); // value info (no values)
00616 
00617     ec_master_queue_datagram(fsm->slave->master, datagram);
00618     fsm->state = ec_fsm_coe_dict_entry_request;
00619 }
00620 
00621 /*****************************************************************************/
00622 
00627 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *fsm)
00629 {
00630     ec_datagram_t *datagram = fsm->datagram;
00631     ec_slave_t *slave = fsm->slave;
00632 
00633     if (datagram->state != EC_DATAGRAM_RECEIVED
00634         || datagram->working_counter != 1) {
00635         fsm->state = ec_fsm_coe_error;
00636         EC_ERR("Reception of CoE SDO entry request failed on slave %i.\n",
00637                slave->ring_position);
00638         return;
00639     }
00640 
00641     fsm->cycles_start = datagram->cycles_sent;
00642 
00643     ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00644     ec_master_queue_datagram(fsm->slave->master, datagram);
00645     fsm->state = ec_fsm_coe_dict_entry_check;
00646 }
00647 
00648 /*****************************************************************************/
00649 
00654 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *fsm)
00656 {
00657     ec_datagram_t *datagram = fsm->datagram;
00658     ec_slave_t *slave = fsm->slave;
00659 
00660     if (datagram->state != EC_DATAGRAM_RECEIVED
00661         || datagram->working_counter != 1) {
00662         fsm->state = ec_fsm_coe_error;
00663         EC_ERR("Reception of CoE mailbox check datagram failed on slave %i.\n",
00664                slave->ring_position);
00665         return;
00666     }
00667 
00668     if (!ec_slave_mbox_check(datagram)) {
00669         if (datagram->cycles_received
00670             - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00671             fsm->state = ec_fsm_coe_error;
00672             EC_ERR("Timeout while checking SDO entry on slave %i.\n",
00673                    slave->ring_position);
00674             return;
00675         }
00676 
00677         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00678         ec_master_queue_datagram(fsm->slave->master, datagram);
00679         return;
00680     }
00681 
00682     // Fetch response
00683     ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
00684     ec_master_queue_datagram(fsm->slave->master, datagram);
00685     fsm->state = ec_fsm_coe_dict_entry_response;
00686 }
00687 
00688 /*****************************************************************************/
00689 
00694 void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *fsm)
00696 {
00697     ec_datagram_t *datagram = fsm->datagram;
00698     ec_slave_t *slave = fsm->slave;
00699     ec_sdo_t *sdo = fsm->sdo;
00700     uint8_t *data, mbox_prot;
00701     size_t rec_size, data_size;
00702     ec_sdo_entry_t *entry;
00703 
00704     if (datagram->state != EC_DATAGRAM_RECEIVED
00705         || datagram->working_counter != 1) {
00706         fsm->state = ec_fsm_coe_error;
00707         EC_ERR("Reception of CoE SDO description"
00708                " response failed on slave %i.\n", slave->ring_position);
00709         return;
00710     }
00711 
00712     if (!(data = ec_slave_mbox_fetch(slave, datagram,
00713                      &mbox_prot, &rec_size))) {
00714         fsm->state = ec_fsm_coe_error;
00715         return;
00716     }
00717 
00718     if (mbox_prot != 0x03) { // CoE
00719         EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00720         fsm->state = ec_fsm_coe_error;
00721     return;
00722     }
00723 
00724     if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
00725         (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
00726         EC_ERR("SDO information error response at slave %i while"
00727                " fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
00728                sdo->index, fsm->subindex);
00729         ec_canopen_abort_msg(EC_READ_U32(data + 6));
00730         fsm->state = ec_fsm_coe_error;
00731     return;
00732     }
00733 
00734     if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
00735         (EC_READ_U8(data + 2) & 0x7F) != 0x06 || // Entry desc. response
00736         EC_READ_U16(data + 6) != sdo->index || // SDO index
00737         EC_READ_U8(data + 8) != fsm->subindex) { // SDO subindex
00738         EC_ERR("Invalid entry description response at slave %i while"
00739                " fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
00740                sdo->index, fsm->subindex);
00741         ec_print_data(data, rec_size);
00742         fsm->state = ec_fsm_coe_error;
00743     return;
00744     }
00745 
00746     if (rec_size < 16) {
00747         EC_ERR("Invalid data size!\n");
00748         ec_print_data(data, rec_size);
00749         fsm->state = ec_fsm_coe_error;
00750     return;
00751     }
00752 
00753     data_size = rec_size - 16;
00754 
00755     if (!(entry = (ec_sdo_entry_t *)
00756           kmalloc(sizeof(ec_sdo_entry_t), GFP_ATOMIC))) {
00757         EC_ERR("Failed to allocate entry!\n");
00758         fsm->state = ec_fsm_coe_error;
00759     return;
00760     }
00761 
00762     if (ec_sdo_entry_init(entry, fsm->subindex, sdo)) {
00763         EC_ERR("Failed to init entry!\n");
00764         fsm->state = ec_fsm_coe_error;
00765     return;
00766     }
00767 
00768     entry->data_type = EC_READ_U16(data + 10);
00769     entry->bit_length = EC_READ_U16(data + 12);
00770 
00771     if (data_size) {
00772         uint8_t *desc;
00773         if (!(desc = kmalloc(data_size + 1, GFP_ATOMIC))) {
00774             EC_ERR("Failed to allocate SDO entry name!\n");
00775             fsm->state = ec_fsm_coe_error;
00776             return;
00777         }
00778         memcpy(desc, data + 16, data_size);
00779         desc[data_size] = 0;
00780         entry->description = desc;
00781     }
00782 
00783     list_add_tail(&entry->list, &sdo->entries);
00784 
00785     if (fsm->subindex < sdo->subindices) {
00786         fsm->subindex++;
00787 
00788         if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10))) {
00789             fsm->state = ec_fsm_coe_error;
00790             return;
00791         }
00792 
00793         EC_WRITE_U16(data, 0x8 << 12); // SDO information
00794         EC_WRITE_U8 (data + 2, 0x05); // Get entry description request
00795         EC_WRITE_U8 (data + 3, 0x00);
00796         EC_WRITE_U16(data + 4, 0x0000);
00797         EC_WRITE_U16(data + 6, sdo->index); // SDO index
00798         EC_WRITE_U8 (data + 8, fsm->subindex); // SDO subindex
00799         EC_WRITE_U8 (data + 9, 0x00); // value info (no values)
00800 
00801         ec_master_queue_datagram(fsm->slave->master, datagram);
00802         fsm->state = ec_fsm_coe_dict_entry_request;
00803         return;
00804     }
00805 
00806     // another SDO description to fetch?
00807     if (fsm->sdo->list.next != &slave->sdo_dictionary) {
00808         fsm->sdo = list_entry(fsm->sdo->list.next, ec_sdo_t, list);
00809 
00810         if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8))) {
00811             fsm->state = ec_fsm_coe_error;
00812             return;
00813         }
00814 
00815         EC_WRITE_U16(data, 0x8 << 12); // SDO information
00816         EC_WRITE_U8 (data + 2, 0x03); // Get object description request
00817         EC_WRITE_U8 (data + 3, 0x00);
00818         EC_WRITE_U16(data + 4, 0x0000);
00819         EC_WRITE_U16(data + 6, fsm->sdo->index); // SDO index
00820 
00821         ec_master_queue_datagram(fsm->slave->master, datagram);
00822         fsm->state = ec_fsm_coe_dict_desc_request;
00823         return;
00824     }
00825 
00826     fsm->state = ec_fsm_coe_end;
00827 }
00828 
00829 /******************************************************************************
00830  *  CoE state machine
00831  *****************************************************************************/
00832 
00837 void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm )
00838 {
00839     ec_datagram_t *datagram = fsm->datagram;
00840     ec_slave_t *slave = fsm->slave;
00841     ec_sdo_data_t *sdodata = fsm->sdodata;
00842     uint8_t *data;
00843 
00844     if (fsm->slave->master->debug_level)
00845         EC_DBG("Downloading SDO 0x%04X:%i to slave %i.\n",
00846                sdodata->index, sdodata->subindex, slave->ring_position);
00847 
00848     if (slave->sii_rx_mailbox_size < 6 + 10 + sdodata->size) {
00849         EC_ERR("SDO fragmenting not supported yet!\n");
00850         fsm->state = ec_fsm_coe_error;
00851         return;
00852     }
00853 
00854     if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
00855                                             sdodata->size + 10))) {
00856         fsm->state = ec_fsm_coe_error;
00857         return;
00858     }
00859 
00860     EC_WRITE_U16(data, 0x2 << 12); // SDO request
00861     EC_WRITE_U8 (data + 2, (0x1 // size specified
00862                             | 0x1 << 5)); // Download request
00863     EC_WRITE_U16(data + 3, sdodata->index);
00864     EC_WRITE_U8 (data + 5, sdodata->subindex);
00865     EC_WRITE_U32(data + 6, sdodata->size);
00866     memcpy(data + 10, sdodata->data, sdodata->size);
00867 
00868     ec_master_queue_datagram(fsm->slave->master, datagram);
00869     fsm->state = ec_fsm_coe_down_request;
00870 }
00871 
00872 /*****************************************************************************/
00873 
00878 void ec_fsm_coe_down_request(ec_fsm_coe_t *fsm )
00879 {
00880     ec_datagram_t *datagram = fsm->datagram;
00881     ec_slave_t *slave = fsm->slave;
00882 
00883     if (datagram->state != EC_DATAGRAM_RECEIVED
00884         || datagram->working_counter != 1) {
00885         fsm->state = ec_fsm_coe_error;
00886         EC_ERR("Reception of CoE download request failed.\n");
00887         return;
00888     }
00889 
00890     fsm->cycles_start = datagram->cycles_sent;
00891 
00892     ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00893     ec_master_queue_datagram(fsm->slave->master, datagram);
00894     fsm->state = ec_fsm_coe_down_check;
00895 }
00896 
00897 /*****************************************************************************/
00898 
00903 void ec_fsm_coe_down_check(ec_fsm_coe_t *fsm )
00904 {
00905     ec_datagram_t *datagram = fsm->datagram;
00906     ec_slave_t *slave = fsm->slave;
00907 
00908     if (datagram->state != EC_DATAGRAM_RECEIVED
00909         || datagram->working_counter != 1) {
00910         fsm->state = ec_fsm_coe_error;
00911         EC_ERR("Reception of CoE mailbox check datagram failed.\n");
00912         return;
00913     }
00914 
00915     if (!ec_slave_mbox_check(datagram)) {
00916         if (datagram->cycles_received
00917             - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00918             fsm->state = ec_fsm_coe_error;
00919             EC_ERR("Timeout while checking SDO configuration on slave %i.\n",
00920                    slave->ring_position);
00921             return;
00922         }
00923 
00924         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
00925         ec_master_queue_datagram(fsm->slave->master, datagram);
00926         return;
00927     }
00928 
00929     // Fetch response
00930     ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
00931     ec_master_queue_datagram(fsm->slave->master, datagram);
00932     fsm->state = ec_fsm_coe_down_response;
00933 }
00934 
00935 /*****************************************************************************/
00936 
00941 void ec_fsm_coe_down_response(ec_fsm_coe_t *fsm )
00942 {
00943     ec_datagram_t *datagram = fsm->datagram;
00944     ec_slave_t *slave = fsm->slave;
00945     uint8_t *data, mbox_prot;
00946     size_t rec_size;
00947     ec_sdo_data_t *sdodata = fsm->sdodata;
00948 
00949     if (datagram->state != EC_DATAGRAM_RECEIVED
00950         || datagram->working_counter != 1) {
00951         fsm->state = ec_fsm_coe_error;
00952         EC_ERR("Reception of CoE download response failed.\n");
00953         return;
00954     }
00955 
00956     if (!(data = ec_slave_mbox_fetch(slave, datagram,
00957                      &mbox_prot, &rec_size))) {
00958         fsm->state = ec_fsm_coe_error;
00959         return;
00960     }
00961 
00962     if (mbox_prot != 0x03) { // CoE
00963         EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00964         fsm->state = ec_fsm_coe_error;
00965     return;
00966     }
00967 
00968     if (rec_size < 6) {
00969         fsm->state = ec_fsm_coe_error;
00970         EC_ERR("Received data is too small (%i bytes):\n", rec_size);
00971         ec_print_data(data, rec_size);
00972         return;
00973     }
00974 
00975     if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
00976         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
00977         fsm->state = ec_fsm_coe_error;
00978         EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
00979                sdodata->index, sdodata->subindex, sdodata->size,
00980                slave->ring_position);
00981         if (rec_size < 10) {
00982             EC_ERR("Incomplete Abort command:\n");
00983             ec_print_data(data, rec_size);
00984         }
00985         else
00986             ec_canopen_abort_msg(EC_READ_U32(data + 6));
00987         return;
00988     }
00989 
00990     if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
00991         EC_READ_U8 (data + 2) >> 5 != 0x3 || // Download response
00992         EC_READ_U16(data + 3) != sdodata->index || // index
00993         EC_READ_U8 (data + 5) != sdodata->subindex) { // subindex
00994         fsm->state = ec_fsm_coe_error;
00995         EC_ERR("SDO download 0x%04X:%X (%i bytes) failed:\n",
00996                sdodata->index, sdodata->subindex, sdodata->size);
00997         EC_ERR("Invalid SDO download response at slave %i!\n",
00998                slave->ring_position);
00999         ec_print_data(data, rec_size);
01000         return;
01001     }
01002 
01003     fsm->state = ec_fsm_coe_end; // success
01004 }
01005 
01006 /*****************************************************************************/
01007 
01012 void ec_fsm_coe_up_start(ec_fsm_coe_t *fsm )
01013 {
01014     ec_datagram_t *datagram = fsm->datagram;
01015     ec_slave_t *slave = fsm->slave;
01016     ec_master_t *master = slave->master;
01017     ec_sdo_request_t *request = fsm->request;
01018     ec_sdo_t *sdo = request->sdo;
01019     ec_sdo_entry_t *entry = request->entry;
01020     uint8_t *data;
01021 
01022     if (master->debug_level)
01023         EC_DBG("Uploading SDO 0x%04X:%i from slave %i.\n",
01024                sdo->index, entry->subindex, slave->ring_position);
01025 
01026     if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10))) {
01027         fsm->state = ec_fsm_coe_error;
01028         return;
01029     }
01030 
01031     EC_WRITE_U16(data, 0x2 << 12); // SDO request
01032     EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request
01033     EC_WRITE_U16(data + 3, sdo->index);
01034     EC_WRITE_U8 (data + 5, entry->subindex);
01035     memset(data + 6, 0x00, 4);
01036 
01037     if (master->debug_level) {
01038         EC_DBG("Upload request:\n");
01039         ec_print_data(data, 10);
01040     }
01041 
01042     ec_master_queue_datagram(fsm->slave->master, datagram);
01043     fsm->state = ec_fsm_coe_up_request;
01044 }
01045 
01046 /*****************************************************************************/
01047 
01052 void ec_fsm_coe_up_request(ec_fsm_coe_t *fsm )
01053 {
01054     ec_datagram_t *datagram = fsm->datagram;
01055     ec_slave_t *slave = fsm->slave;
01056 
01057     if (datagram->state != EC_DATAGRAM_RECEIVED
01058         || datagram->working_counter != 1) {
01059         fsm->state = ec_fsm_coe_error;
01060         EC_ERR("Reception of CoE upload request failed.\n");
01061         return;
01062     }
01063 
01064     fsm->cycles_start = datagram->cycles_sent;
01065 
01066     ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
01067     ec_master_queue_datagram(fsm->slave->master, datagram);
01068     fsm->state = ec_fsm_coe_up_check;
01069 }
01070 
01071 /*****************************************************************************/
01072 
01077 void ec_fsm_coe_up_check(ec_fsm_coe_t *fsm )
01078 {
01079     ec_datagram_t *datagram = fsm->datagram;
01080     ec_slave_t *slave = fsm->slave;
01081 
01082     if (datagram->state != EC_DATAGRAM_RECEIVED
01083         || datagram->working_counter != 1) {
01084         fsm->state = ec_fsm_coe_error;
01085         EC_ERR("Reception of CoE mailbox check datagram failed.\n");
01086         return;
01087     }
01088 
01089     if (!ec_slave_mbox_check(datagram)) {
01090         if (datagram->cycles_received
01091             - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
01092             fsm->state = ec_fsm_coe_error;
01093             EC_ERR("Timeout while checking SDO upload on slave %i.\n",
01094                    slave->ring_position);
01095             return;
01096         }
01097 
01098         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
01099         ec_master_queue_datagram(fsm->slave->master, datagram);
01100         return;
01101     }
01102 
01103     // Fetch response
01104     ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
01105     ec_master_queue_datagram(fsm->slave->master, datagram);
01106     fsm->state = ec_fsm_coe_up_response;
01107 }
01108 
01109 /*****************************************************************************/
01110 
01115 void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm )
01116 {
01117     ec_datagram_t *datagram = fsm->datagram;
01118     ec_slave_t *slave = fsm->slave;
01119     ec_master_t *master = slave->master;
01120     uint8_t *data, mbox_prot;
01121     size_t rec_size, data_size;
01122     ec_sdo_request_t *request = fsm->request;
01123     ec_sdo_t *sdo = request->sdo;
01124     ec_sdo_entry_t *entry = request->entry;
01125     uint32_t complete_size;
01126     unsigned int expedited, size_specified;
01127 
01128     if (datagram->state != EC_DATAGRAM_RECEIVED
01129         || datagram->working_counter != 1) {
01130         fsm->state = ec_fsm_coe_error;
01131         EC_ERR("Reception of CoE upload response failed.\n");
01132         return;
01133     }
01134 
01135     if (!(data = ec_slave_mbox_fetch(slave, datagram,
01136                      &mbox_prot, &rec_size))) {
01137         fsm->state = ec_fsm_coe_error;
01138         return;
01139     }
01140 
01141     if (master->debug_level) {
01142         EC_DBG("Upload response:\n");
01143         ec_print_data(data, rec_size);
01144     }
01145 
01146     if (mbox_prot != 0x03) { // CoE
01147         EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
01148         fsm->state = ec_fsm_coe_error;
01149     return;
01150     }
01151 
01152     if (rec_size < 10) {
01153         EC_ERR("Received currupted SDO upload response!\n");
01154         ec_print_data(data, rec_size);
01155         fsm->state = ec_fsm_coe_error;
01156     return;
01157     }
01158 
01159     if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
01160         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
01161         EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
01162                sdo->index, entry->subindex, slave->ring_position);
01163         ec_canopen_abort_msg(EC_READ_U32(data + 6));
01164         fsm->state = ec_fsm_coe_error;
01165     return;
01166     }
01167 
01168     if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
01169         EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response
01170         EC_READ_U16(data + 3) != sdo->index || // index
01171         EC_READ_U8 (data + 5) != entry->subindex) { // subindex
01172         EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo->index, entry->subindex);
01173         EC_ERR("Invalid SDO upload response at slave %i!\n",
01174                slave->ring_position);
01175         ec_print_data(data, rec_size);
01176         fsm->state = ec_fsm_coe_error;
01177     return;
01178     }
01179 
01180     data_size = rec_size - 10;
01181     expedited = EC_READ_U8(data + 2) & 0x02;
01182 
01183     if (expedited) {
01184         size_specified = EC_READ_U8(data + 2) & 0x01;
01185         if (size_specified) {
01186             complete_size = 4 - ((EC_READ_U8(data + 2) & 0x0C) >> 2);
01187         }
01188         else {
01189             complete_size = 4;
01190         }
01191     }
01192     else {
01193         complete_size = EC_READ_U32(data + 6);
01194     }
01195 
01196     if (request->data) {
01197         kfree(request->data);
01198         request->data = NULL;
01199     }
01200     request->size = 0;
01201 
01202     if (complete_size) {
01203         if (!(request->data = (uint8_t *)
01204               kmalloc(complete_size + 1, GFP_ATOMIC))) {
01205             EC_ERR("Failed to allocate %i bytes of SDO data!\n",
01206                    complete_size);
01207             fsm->state = ec_fsm_coe_error;
01208             return;
01209         }
01210         request->data[complete_size] = 0x00; // just to be sure...
01211     }
01212 
01213     if (expedited) {
01214         memcpy(request->data, data + 6, complete_size);
01215         request->size = complete_size;
01216     }
01217     else {
01218         memcpy(request->data, data + 10, data_size);
01219         request->size = data_size;
01220         fsm->toggle = 0;
01221 
01222         if (data_size < complete_size) {
01223             EC_WARN("SDO data incomplete (%i / %i).\n",
01224                     data_size, complete_size);
01225 
01226             if (!(data = ec_slave_mbox_prepare_send(slave, datagram,
01227                                                     0x03, 3))) {
01228                 fsm->state = ec_fsm_coe_error;
01229                 return;
01230             }
01231 
01232             EC_WRITE_U16(data, 0x2 << 12); // SDO request
01233             EC_WRITE_U8 (data + 2, (fsm->toggle << 4 // toggle
01234                                     | 0x3 << 5)); // upload segment request
01235 
01236             if (master->debug_level) {
01237                 EC_DBG("Upload segment request:\n");
01238                 ec_print_data(data, 3);
01239             }
01240 
01241             ec_master_queue_datagram(fsm->slave->master, datagram);
01242             fsm->state = ec_fsm_coe_up_seg_request;
01243             return;
01244         }
01245     }
01246 
01247     fsm->state = ec_fsm_coe_end; // success
01248 }
01249 
01250 /*****************************************************************************/
01251 
01256 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *fsm )
01257 {
01258     ec_datagram_t *datagram = fsm->datagram;
01259     ec_slave_t *slave = fsm->slave;
01260 
01261     if (datagram->state != EC_DATAGRAM_RECEIVED
01262         || datagram->working_counter != 1) {
01263         fsm->state = ec_fsm_coe_error;
01264         EC_ERR("Reception of CoE upload segment request failed.\n");
01265         return;
01266     }
01267 
01268     fsm->cycles_start = datagram->cycles_sent;
01269 
01270     ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
01271     ec_master_queue_datagram(fsm->slave->master, datagram);
01272     fsm->state = ec_fsm_coe_up_seg_check;
01273 }
01274 
01275 /*****************************************************************************/
01276 
01281 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *fsm )
01282 {
01283     ec_datagram_t *datagram = fsm->datagram;
01284     ec_slave_t *slave = fsm->slave;
01285 
01286     if (datagram->state != EC_DATAGRAM_RECEIVED
01287         || datagram->working_counter != 1) {
01288         fsm->state = ec_fsm_coe_error;
01289         EC_ERR("Reception of CoE mailbox check datagram failed.\n");
01290         return;
01291     }
01292 
01293     if (!ec_slave_mbox_check(datagram)) {
01294         if (datagram->cycles_received
01295             - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
01296             fsm->state = ec_fsm_coe_error;
01297             EC_ERR("Timeout while checking SDO upload segment on slave %i.\n",
01298                    slave->ring_position);
01299             return;
01300         }
01301 
01302         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
01303         ec_master_queue_datagram(fsm->slave->master, datagram);
01304         return;
01305     }
01306 
01307     // Fetch response
01308     ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
01309     ec_master_queue_datagram(fsm->slave->master, datagram);
01310     fsm->state = ec_fsm_coe_up_seg_response;
01311 }
01312 
01313 /*****************************************************************************/
01314 
01319 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm )
01320 {
01321     ec_datagram_t *datagram = fsm->datagram;
01322     ec_slave_t *slave = fsm->slave;
01323     ec_master_t *master = slave->master;
01324     uint8_t *data, mbox_prot;
01325     size_t rec_size, data_size;
01326     ec_sdo_request_t *request = fsm->request;
01327     ec_sdo_t *sdo = request->sdo;
01328     ec_sdo_entry_t *entry = request->entry;
01329     uint32_t seg_size;
01330     unsigned int last_segment;
01331 
01332     if (datagram->state != EC_DATAGRAM_RECEIVED
01333         || datagram->working_counter != 1) {
01334         fsm->state = ec_fsm_coe_error;
01335         EC_ERR("Reception of CoE upload segment response failed.\n");
01336         return;
01337     }
01338 
01339     if (!(data = ec_slave_mbox_fetch(slave, datagram,
01340                      &mbox_prot, &rec_size))) {
01341         fsm->state = ec_fsm_coe_error;
01342         return;
01343     }
01344 
01345     if (master->debug_level) {
01346         EC_DBG("Upload segment response:\n");
01347         ec_print_data(data, rec_size);
01348     }
01349 
01350     if (mbox_prot != 0x03) { // CoE
01351         EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
01352         fsm->state = ec_fsm_coe_error;
01353     return;
01354     }
01355 
01356     if (rec_size < 10) {
01357         EC_ERR("Received currupted SDO upload segment response!\n");
01358         ec_print_data(data, rec_size);
01359         fsm->state = ec_fsm_coe_error;
01360     return;
01361     }
01362 
01363     if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
01364         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
01365         EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
01366                sdo->index, entry->subindex, slave->ring_position);
01367         ec_canopen_abort_msg(EC_READ_U32(data + 6));
01368         fsm->state = ec_fsm_coe_error;
01369     return;
01370     }
01371 
01372     if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
01373         EC_READ_U8 (data + 2) >> 5 != 0x0) { // upload segment response
01374         EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo->index, entry->subindex);
01375         EC_ERR("Invalid SDO upload segment response at slave %i!\n",
01376                slave->ring_position);
01377         ec_print_data(data, rec_size);
01378         fsm->state = ec_fsm_coe_error;
01379     return;
01380     }
01381 
01382     last_segment = EC_READ_U8(data + 2) & 0x01;
01383     seg_size = (EC_READ_U8(data + 2) & 0xE) >> 1;
01384     data_size = rec_size - 10;
01385 
01386     if (data_size != seg_size) {
01387         EC_WARN("SDO segment data invalid (%i / %i)"
01388                 " - Fragmenting not implemented.\n",
01389                 data_size, seg_size);
01390     }
01391 
01392     memcpy(request->data + request->size, data + 10, data_size);
01393     request->size += data_size;
01394 
01395     if (!last_segment) {
01396         fsm->toggle = !fsm->toggle;
01397 
01398         if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 3))) {
01399             fsm->state = ec_fsm_coe_error;
01400             return;
01401         }
01402 
01403         EC_WRITE_U16(data, 0x2 << 12); // SDO request
01404         EC_WRITE_U8 (data + 2, (fsm->toggle << 4 // toggle
01405                                 | 0x3 << 5)); // upload segment request
01406 
01407         if (master->debug_level) {
01408             EC_DBG("Upload segment request:\n");
01409             ec_print_data(data, 3);
01410         }
01411 
01412         ec_master_queue_datagram(fsm->slave->master, datagram);
01413         fsm->state = ec_fsm_coe_up_seg_request;
01414         return;
01415     }
01416 
01417     fsm->state = ec_fsm_coe_end; // success
01418 }
01419 
01420 /*****************************************************************************/
01421 
01426 void ec_fsm_coe_error(ec_fsm_coe_t *fsm )
01427 {
01428 }
01429 
01430 /*****************************************************************************/
01431 
01436 void ec_fsm_coe_end(ec_fsm_coe_t *fsm )
01437 {
01438 }
01439 
01440 /*****************************************************************************/

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