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

fsm_sii.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: fsm_sii.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 "mailbox.h"
00043 #include "master.h"
00044 #include "fsm_sii.h"
00045 
00046 /*****************************************************************************/
00047 
00048 void ec_fsm_sii_start_reading(ec_fsm_sii_t *);
00049 void ec_fsm_sii_read_check(ec_fsm_sii_t *);
00050 void ec_fsm_sii_read_fetch(ec_fsm_sii_t *);
00051 void ec_fsm_sii_start_writing(ec_fsm_sii_t *);
00052 void ec_fsm_sii_write_check(ec_fsm_sii_t *);
00053 void ec_fsm_sii_write_check2(ec_fsm_sii_t *);
00054 void ec_fsm_sii_end(ec_fsm_sii_t *);
00055 void ec_fsm_sii_error(ec_fsm_sii_t *);
00056 
00057 /*****************************************************************************/
00058 
00063 void ec_fsm_sii_init(ec_fsm_sii_t *fsm, 
00064                      ec_datagram_t *datagram 
00065                      )
00066 {
00067     fsm->state = NULL;
00068     fsm->datagram = datagram;
00069 }
00070 
00071 /*****************************************************************************/
00072 
00077 void ec_fsm_sii_clear(ec_fsm_sii_t *fsm )
00078 {
00079 }
00080 
00081 /*****************************************************************************/
00082 
00087 void ec_fsm_sii_read(ec_fsm_sii_t *fsm, 
00088                      ec_slave_t *slave, 
00089                      uint16_t offset, 
00090                      ec_fsm_sii_addressing_t mode 
00091                      )
00092 {
00093     fsm->state = ec_fsm_sii_start_reading;
00094     fsm->slave = slave;
00095     fsm->offset = offset;
00096     fsm->mode = mode;
00097 }
00098 
00099 /*****************************************************************************/
00100 
00105 void ec_fsm_sii_write(ec_fsm_sii_t *fsm, 
00106                       ec_slave_t *slave, 
00107                       uint16_t offset, 
00108                       uint16_t *value, 
00109                       ec_fsm_sii_addressing_t mode 
00110                       )
00111 {
00112     fsm->state = ec_fsm_sii_start_writing;
00113     fsm->slave = slave;
00114     fsm->offset = offset;
00115     fsm->mode = mode;
00116     memcpy(fsm->value, value, 2);
00117 }
00118 
00119 /*****************************************************************************/
00120 
00126 int ec_fsm_sii_exec(ec_fsm_sii_t *fsm )
00127 {
00128     fsm->state(fsm);
00129 
00130     return fsm->state != ec_fsm_sii_end && fsm->state != ec_fsm_sii_error;
00131 }
00132 
00133 /*****************************************************************************/
00134 
00140 int ec_fsm_sii_success(ec_fsm_sii_t *fsm )
00141 {
00142     return fsm->state == ec_fsm_sii_end;
00143 }
00144 
00145 /******************************************************************************
00146  *  SII state machine
00147  *****************************************************************************/
00148 
00154 void ec_fsm_sii_start_reading(ec_fsm_sii_t *fsm )
00155 {
00156     ec_datagram_t *datagram = fsm->datagram;
00157 
00158     // initiate read operation
00159     switch (fsm->mode) {
00160         case EC_FSM_SII_POSITION:
00161             ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4);
00162             break;
00163         case EC_FSM_SII_NODE:
00164             ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4);
00165             break;
00166     }
00167 
00168     EC_WRITE_U8 (datagram->data,     0x00); // read-only access
00169     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
00170     EC_WRITE_U16(datagram->data + 2, fsm->offset);
00171     ec_master_queue_datagram(fsm->slave->master, datagram);
00172     fsm->state = ec_fsm_sii_read_check;
00173 }
00174 
00175 /*****************************************************************************/
00176 
00182 void ec_fsm_sii_read_check(ec_fsm_sii_t *fsm )
00183 {
00184     ec_datagram_t *datagram = fsm->datagram;
00185 
00186     if (datagram->state != EC_DATAGRAM_RECEIVED
00187         || datagram->working_counter != 1) {
00188         EC_ERR("SII: Reception of read datagram failed.\n");
00189         fsm->state = ec_fsm_sii_error;
00190         return;
00191     }
00192 
00193     fsm->cycles_start = datagram->cycles_sent;
00194     fsm->check_once_more = 1;
00195 
00196     // issue check/fetch datagram
00197     switch (fsm->mode) {
00198         case EC_FSM_SII_POSITION:
00199             ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
00200             break;
00201         case EC_FSM_SII_NODE:
00202             ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
00203             break;
00204     }
00205     ec_master_queue_datagram(fsm->slave->master, datagram);
00206     fsm->state = ec_fsm_sii_read_fetch;
00207 }
00208 
00209 /*****************************************************************************/
00210 
00216 void ec_fsm_sii_read_fetch(ec_fsm_sii_t *fsm )
00217 {
00218     ec_datagram_t *datagram = fsm->datagram;
00219 
00220     if (datagram->state != EC_DATAGRAM_RECEIVED
00221         || datagram->working_counter != 1) {
00222         EC_ERR("SII: Reception of check/fetch datagram failed.\n");
00223         fsm->state = ec_fsm_sii_error;
00224         return;
00225     }
00226 
00227     // check "busy bit"
00228     if (EC_READ_U8(datagram->data + 1) & 0x81) {
00229         // still busy... timeout?
00230         if (datagram->cycles_received
00231             - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) {
00232             if (!fsm->check_once_more) {
00233                 EC_ERR("SII: Read timeout.\n");
00234                 fsm->state = ec_fsm_sii_error;
00235 #if 0
00236                 EC_DBG("SII busy: %02X %02X %02X %02X\n",
00237                        EC_READ_U8(datagram->data + 0),
00238                        EC_READ_U8(datagram->data + 1),
00239                        EC_READ_U8(datagram->data + 2),
00240                        EC_READ_U8(datagram->data + 3));
00241 #endif
00242                 return;
00243             }
00244             fsm->check_once_more = 0;
00245         }
00246 
00247         // issue check/fetch datagram again
00248         switch (fsm->mode) {
00249             case EC_FSM_SII_POSITION:
00250                 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
00251                 break;
00252             case EC_FSM_SII_NODE:
00253                 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
00254                 break;
00255         }
00256         ec_master_queue_datagram(fsm->slave->master, datagram);
00257         return;
00258     }
00259 
00260 #if 0
00261     EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n",
00262            EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1),
00263            EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3),
00264            EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7),
00265            EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9));
00266 #endif
00267 
00268     // SII value received.
00269     memcpy(fsm->value, datagram->data + 6, 4);
00270     fsm->state = ec_fsm_sii_end;
00271 }
00272 
00273 /*****************************************************************************/
00274 
00280 void ec_fsm_sii_start_writing(ec_fsm_sii_t *fsm )
00281 {
00282     ec_datagram_t *datagram = fsm->datagram;
00283 
00284     // initiate write operation
00285     ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
00286     EC_WRITE_U8 (datagram->data,     0x01); // enable write access
00287     EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
00288     EC_WRITE_U32(datagram->data + 2, fsm->offset);
00289     memcpy(datagram->data + 6, fsm->value, 2);
00290     ec_master_queue_datagram(fsm->slave->master, datagram);
00291     fsm->state = ec_fsm_sii_write_check;
00292 }
00293 
00294 /*****************************************************************************/
00295 
00300 void ec_fsm_sii_write_check(ec_fsm_sii_t *fsm )
00301 {
00302     ec_datagram_t *datagram = fsm->datagram;
00303 
00304     if (datagram->state != EC_DATAGRAM_RECEIVED
00305         || datagram->working_counter != 1) {
00306         EC_ERR("SII: Reception of write datagram failed.\n");
00307         fsm->state = ec_fsm_sii_error;
00308         return;
00309     }
00310 
00311     fsm->cycles_start = datagram->cycles_sent;
00312     fsm->check_once_more = 1;
00313 
00314     // issue check/fetch datagram
00315     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
00316     ec_master_queue_datagram(fsm->slave->master, datagram);
00317     fsm->state = ec_fsm_sii_write_check2;
00318 }
00319 
00320 /*****************************************************************************/
00321 
00326 void ec_fsm_sii_write_check2(ec_fsm_sii_t *fsm )
00327 {
00328     ec_datagram_t *datagram = fsm->datagram;
00329 
00330     if (datagram->state != EC_DATAGRAM_RECEIVED
00331         || datagram->working_counter != 1) {
00332         EC_ERR("SII: Reception of write check datagram failed.\n");
00333         fsm->state = ec_fsm_sii_error;
00334         return;
00335     }
00336 
00337     if (EC_READ_U8(datagram->data + 1) & 0x82) {
00338         // still busy... timeout?
00339         if (datagram->cycles_received
00340             - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) {
00341             if (!fsm->check_once_more) {
00342                 EC_ERR("SII: Write timeout.\n");
00343                 fsm->state = ec_fsm_sii_error;
00344                 return;
00345             }
00346             fsm->check_once_more = 0;
00347         }
00348 
00349         // issue check/fetch datagram again
00350         ec_master_queue_datagram(fsm->slave->master, datagram);
00351         return;
00352     }
00353 
00354     if (EC_READ_U8(datagram->data + 1) & 0x40) {
00355         EC_ERR("SII: Write operation failed!\n");
00356         fsm->state = ec_fsm_sii_error;
00357         return;
00358     }
00359 
00360     // success
00361     fsm->state = ec_fsm_sii_end;
00362 }
00363 
00364 /*****************************************************************************/
00365 
00370 void ec_fsm_sii_error(ec_fsm_sii_t *fsm )
00371 {
00372 }
00373 
00374 /*****************************************************************************/
00375 
00380 void ec_fsm_sii_end(ec_fsm_sii_t *fsm )
00381 {
00382 }
00383 
00384 /*****************************************************************************/

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