ethercatsoe.c
Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatsoe.c
00005  * Version : 1.2.5
00006  * Date    : 09-04-2011
00007  * Copyright (C) 2005-2011 Speciaal Machinefabriek Ketels v.o.f.
00008  * Copyright (C) 2005-2011 Arthur Ketels
00009  * Copyright (C) 2008-2009 TU/e Technische Universiteit Eindhoven 
00010  * Thanks to Hidde Verhoef for testing and improving the SoE module
00011  *
00012  * SOEM is free software; you can redistribute it and/or modify it under
00013  * the terms of the GNU General Public License version 2 as published by the Free
00014  * Software Foundation.
00015  *
00016  * SOEM is distributed in the hope that it will be useful, but WITHOUT ANY
00017  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019  * for more details.
00020  *
00021  * As a special exception, if other files instantiate templates or use macros
00022  * or inline functions from this file, or you compile this file and link it
00023  * with other works to produce a work based on this file, this file does not
00024  * by itself cause the resulting work to be covered by the GNU General Public
00025  * License. However the source code for this file must still be made available
00026  * in accordance with section (3) of the GNU General Public License.
00027  *
00028  * This exception does not invalidate any other reasons why a work based on
00029  * this file might be covered by the GNU General Public License.
00030  *
00031  * The EtherCAT Technology, the trade name and logo “EtherCAT” are the intellectual
00032  * property of, and protected by Beckhoff Automation GmbH. You can use SOEM for
00033  * the sole purpose of creating, using and/or selling or otherwise distributing
00034  * an EtherCAT network master provided that an EtherCAT Master License is obtained
00035  * from Beckhoff Automation GmbH.
00036  *
00037  * In case you did not receive a copy of the EtherCAT Master License along with
00038  * SOEM write to Beckhoff Automation GmbH, Eiserstraße 5, D-33415 Verl, Germany
00039  * (www.beckhoff.com).
00040  */
00041 
00047 #include <stdio.h>
00048 #include <string.h>
00049 #include <sys/time.h>
00050 #include <unistd.h>
00051 #include <youbot_driver/soem/ethercattype.h>
00052 #include <youbot_driver/soem/nicdrv.h>
00053 #include <youbot_driver/soem/ethercatbase.h>
00054 #include <youbot_driver/soem/ethercatmain.h>
00055 #include <youbot_driver/soem/ethercatsoe.h>
00056 
00058 typedef struct
00059   PACKED
00060   {
00061     ec_mbxheadert MbxHeader;
00062     uint8 opCode :3;
00063     uint8 incomplete :1;
00064     uint8 error :1;
00065     uint8 driveNo :3;
00066     uint8 elementflags;
00067     union
00068     {
00069       uint16 idn;
00070       uint16 fragmentsleft;
00071     };
00072   } ec_SoEt;
00073 
00074   static ec_SoEmappingt SoEmapping;
00075   static ec_SoEattributet SoEattribute;
00076 
00083   void ec_SoEerror(uint16 Slave, uint16 idn, uint16 Error)
00084   {
00085     ec_errort Ec;
00086 
00087     gettimeofday(&Ec.Time, 0);
00088     Ec.Slave = Slave;
00089     Ec.Index = idn;
00090     Ec.SubIdx = 0;
00091     EcatError = TRUE;
00092     Ec.Etype = EC_ERR_TYPE_SOE_ERROR;
00093     Ec.ErrorCode = Error;
00094     ec_pusherror(&Ec);
00095   }
00096 
00112   int ec_SoEread(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout)
00113   {
00114     ec_SoEt *SoEp, *aSoEp;
00115     uint16 totalsize, framedatasize;
00116     int wkc;
00117     uint8 *bp;
00118     uint8 *mp;
00119     uint16 *errorcode;
00120     ec_mbxbuft MbxIn, MbxOut;
00121     uint8 cnt;
00122     boolean NotLast;
00123 
00124     ec_clearmbx(&MbxIn);
00125     /* Empty slave out mailbox if something is in. Timeout set to 0 */
00126     wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0);
00127     ec_clearmbx(&MbxOut);
00128     aSoEp = (ec_SoEt *)&MbxIn;
00129     SoEp = (ec_SoEt *)&MbxOut;
00130     SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert));
00131     SoEp->MbxHeader.address = htoes(0x0000);
00132     SoEp->MbxHeader.priority = 0x00;
00133     /* get new mailbox count value, used as session handle */
00134     cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00135     ec_slave[slave].mbx_cnt = cnt;
00136     SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */
00137     SoEp->opCode = ECT_SOE_READREQ;
00138     SoEp->incomplete = 0;
00139     SoEp->error = 0;
00140     SoEp->driveNo = driveNo;
00141     SoEp->elementflags = elementflags;
00142     SoEp->idn = htoes(idn);
00143     totalsize = 0;
00144     bp = p;
00145     mp = (uint8 *)&MbxIn + sizeof(ec_SoEt);
00146     NotLast = TRUE;
00147     /* send SoE request to slave */
00148     wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00149     if (wkc > 0) /* succeeded to place mailbox in slave ? */
00150     {
00151       while (NotLast)
00152       {
00153         /* clean mailboxbuffer */
00154         ec_clearmbx(&MbxIn);
00155         /* read slave response */
00156         wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout);
00157         if (wkc > 0) /* succeeded to read slave response ? */
00158         {
00159           /* slave response should be SoE, ReadRes */
00160           if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES)
00161               && (aSoEp->error == 0) && (aSoEp->driveNo == driveNo) && (aSoEp->elementflags == elementflags))
00162           {
00163             framedatasize = etohs(aSoEp->MbxHeader.length) - sizeof(ec_SoEt) + sizeof(ec_mbxheadert);
00164             totalsize += framedatasize;
00165             /* Does parameter fit in parameter buffer ? */
00166             if (totalsize <= *psize)
00167             {
00168               /* copy parameter data in parameter buffer */
00169               memcpy(bp, mp, framedatasize);
00170               /* increment buffer pointer */
00171               bp += framedatasize;
00172             }
00173             else
00174             {
00175               framedatasize -= totalsize - *psize;
00176               totalsize = *psize;
00177               /* copy parameter data in parameter buffer */
00178               if (framedatasize > 0)
00179                 memcpy(bp, mp, framedatasize);
00180             }
00181 
00182             if (!aSoEp->incomplete)
00183             {
00184               NotLast = FALSE;
00185               *psize = totalsize;
00186             }
00187           }
00188           /* other slave response */
00189           else
00190           {
00191             NotLast = FALSE;
00192             if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES)
00193                 && (aSoEp->error == 1))
00194             {
00195               mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16));
00196               errorcode = (uint16 *)mp;
00197               ec_SoEerror(slave, idn, *errorcode);
00198             }
00199             else
00200             {
00201               ec_packeterror(slave, idn, 0, 1); /* Unexpected frame returned */
00202             }
00203             wkc = 0;
00204           }
00205         }
00206         else
00207         {
00208           NotLast = FALSE;
00209           ec_packeterror(slave, idn, 0, 4); /* no response */
00210         }
00211       }
00212     }
00213     return wkc;
00214   }
00215 
00230   int ec_SoEwrite(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout)
00231   {
00232     ec_SoEt *SoEp, *aSoEp;
00233     uint16 framedatasize, maxdata;
00234     int wkc;
00235     uint8 *mp;
00236     uint8 *hp;
00237     uint16 *errorcode;
00238     ec_mbxbuft MbxIn, MbxOut;
00239     uint8 cnt;
00240     boolean NotLast;
00241 
00242     ec_clearmbx(&MbxIn);
00243     /* Empty slave out mailbox if something is in. Timeout set to 0 */
00244     wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0);
00245     ec_clearmbx(&MbxOut);
00246     aSoEp = (ec_SoEt *)&MbxIn;
00247     SoEp = (ec_SoEt *)&MbxOut;
00248     SoEp->MbxHeader.address = htoes(0x0000);
00249     SoEp->MbxHeader.priority = 0x00;
00250     SoEp->opCode = ECT_SOE_WRITEREQ;
00251     SoEp->error = 0;
00252     SoEp->driveNo = driveNo;
00253     SoEp->elementflags = elementflags;
00254     hp = p;
00255     mp = (uint8 *)&MbxOut + sizeof(ec_SoEt);
00256     maxdata = ec_slave[slave].mbx_l - sizeof(ec_SoEt);
00257     NotLast = TRUE;
00258     while (NotLast)
00259     {
00260       framedatasize = psize;
00261       NotLast = FALSE;
00262       SoEp->idn = htoes(idn);
00263       SoEp->incomplete = 0;
00264       if (framedatasize > maxdata)
00265       {
00266         framedatasize = maxdata; /*  segmented transfer needed  */
00267         NotLast = TRUE;
00268         SoEp->incomplete = 1;
00269         SoEp->fragmentsleft = psize / maxdata;
00270       }
00271       SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert) + framedatasize);
00272       /* get new mailbox counter, used for session handle */
00273       cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00274       ec_slave[slave].mbx_cnt = cnt;
00275       SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */
00276       /* copy parameter data to mailbox */
00277       memcpy(mp, hp, framedatasize);
00278       hp += framedatasize;
00279       psize -= framedatasize;
00280       /* send SoE request to slave */
00281       wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00282       if (wkc > 0) /* succeeded to place mailbox in slave ? */
00283       {
00284         if (!NotLast || !ec_mbxempty(slave, timeout))
00285         {
00286           /* clean mailboxbuffer */
00287           ec_clearmbx(&MbxIn);
00288           /* read slave response */
00289           wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout);
00290           if (wkc > 0) /* succeeded to read slave response ? */
00291           {
00292             NotLast = FALSE;
00293             /* slave response should be SoE, WriteRes */
00294             if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_WRITERES)
00295                 && (aSoEp->error == 0) && (aSoEp->driveNo == driveNo) && (aSoEp->elementflags == elementflags))
00296             {
00297               /* SoE write succeeded */
00298             }
00299             /* other slave response */
00300             else
00301             {
00302               if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES)
00303                   && (aSoEp->error == 1))
00304               {
00305                 mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16));
00306                 errorcode = (uint16 *)mp;
00307                 ec_SoEerror(slave, idn, *errorcode);
00308               }
00309               else
00310               {
00311                 ec_packeterror(slave, idn, 0, 1); /* Unexpected frame returned */
00312               }
00313               wkc = 0;
00314             }
00315           }
00316           else
00317           {
00318             ec_packeterror(slave, idn, 0, 4); /* no response */
00319           }
00320         }
00321       }
00322     }
00323     return wkc;
00324   }
00325 
00337   int ec_readIDNmap(uint16 slave, int *Osize, int *Isize)
00338   {
00339     int retVal = 0;
00340     int wkc;
00341     int psize;
00342     uint16 entries, itemcount;
00343 
00344     *Isize = 0;
00345     *Osize = 0;
00346     psize = sizeof(SoEmapping);
00347     /* read output mapping via SoE */
00348     wkc = ec_SoEread(slave, 0, EC_SOE_VALUE_B, EC_IDN_MDTCONFIG, &psize, &SoEmapping, EC_TIMEOUTRXM);
00349     if ((wkc > 0) && (psize >= 4) && ((entries = etohs(SoEmapping.currentlength) / 2) > 0)
00350         && (entries <= EC_SOE_MAXMAPPING))
00351     {
00352       /* command word (uint16) is always mapped but not in list */
00353       *Osize = 16;
00354       for (itemcount = 0; itemcount < entries; itemcount++)
00355       {
00356         psize = sizeof(SoEattribute);
00357         /* read attribute of each IDN in mapping list */
00358         wkc = ec_SoEread(slave, 0, EC_SOE_ATTRIBUTE_B, SoEmapping.idn[itemcount], &psize, &SoEattribute, EC_TIMEOUTRXM);
00359         if ((wkc > 0) && (!SoEattribute.list))
00360         {
00361           /* length : 0 = 8bit, 1 = 16bit .... */
00362           *Osize += (int)8 << SoEattribute.length;
00363         }
00364       }
00365     }
00366     psize = sizeof(SoEmapping);
00367     /* read input mapping via SoE */
00368     wkc = ec_SoEread(slave, 0, EC_SOE_VALUE_B, EC_IDN_ATCONFIG, &psize, &SoEmapping, EC_TIMEOUTRXM);
00369     if ((wkc > 0) && (psize >= 4) && ((entries = etohs(SoEmapping.currentlength) / 2) > 0)
00370         && (entries <= EC_SOE_MAXMAPPING))
00371     {
00372       /* status word (uint16) is always mapped but not in list */
00373       *Isize = 16;
00374       for (itemcount = 0; itemcount < entries; itemcount++)
00375       {
00376         psize = sizeof(SoEattribute);
00377         /* read attribute of each IDN in mapping list */
00378         wkc = ec_SoEread(slave, 0, EC_SOE_ATTRIBUTE_B, SoEmapping.idn[itemcount], &psize, &SoEattribute, EC_TIMEOUTRXM);
00379         if ((wkc > 0) && (!SoEattribute.list))
00380         {
00381           /* length : 0 = 8bit, 1 = 16bit .... */
00382           *Isize += (int)8 << SoEattribute.length;
00383         }
00384       }
00385     }
00386 
00387     /* found some I/O bits ? */
00388     if ((*Isize > 0) || (*Osize > 0))
00389     {
00390       retVal = 1;
00391     }
00392     return retVal;
00393   }


youbot_driver
Author(s): Jan Paulus
autogenerated on Mon Oct 6 2014 09:08:01