ethercatsoe.c
Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatsoe.c
00005  * Version : 1.3.0
00006  * Date    : 24-02-2013
00007  * Copyright (C) 2005-2013 Speciaal Machinefabriek Ketels v.o.f.
00008  * Copyright (C) 2005-2013 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 "ethercat_soem/osal.h"
00050 #include "ethercat_soem/oshw.h"
00051 #include "ethercat_soem/ethercattype.h"
00052 #include "ethercat_soem/ethercatbase.h"
00053 #include "ethercat_soem/ethercatmain.h"
00054 #include "ethercat_soem/ethercatsoe.h"
00055 
00056 
00058 PACKED_BEGIN
00059 typedef struct 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 PACKED_END
00074 
00082 void ecx_SoEerror(ecx_contextt *context, uint16 Slave, uint16 idn, uint16 Error)
00083 {
00084    ec_errort Ec;
00085 
00086    Ec.Time = osal_current_time();
00087    Ec.Slave = Slave;
00088    Ec.Index = idn;
00089    Ec.SubIdx = 0;
00090    *(context->ecaterror) = TRUE;
00091    Ec.Etype = EC_ERR_TYPE_SOE_ERROR;
00092    Ec.ErrorCode = Error;
00093    ecx_pusherror(context, &Ec);
00094 }
00095 
00112 int ecx_SoEread(ecx_contextt *context, 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 = ecx_mbxreceive(context, 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(context->slavelist[slave].mbx_cnt);
00135    context->slavelist[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 = ecx_mbxsend(context, 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 = ecx_mbxreceive(context, 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) &&
00161                 (aSoEp->opCode == ECT_SOE_READRES) &&
00162                 (aSoEp->error == 0) &&
00163                 (aSoEp->driveNo == driveNo) &&
00164                 (aSoEp->elementflags == elementflags))
00165             {
00166                framedatasize = etohs(aSoEp->MbxHeader.length) - sizeof(ec_SoEt)  + sizeof(ec_mbxheadert);
00167                totalsize += framedatasize;
00168                /* Does parameter fit in parameter buffer ? */
00169                if (totalsize <= *psize)
00170                {
00171                   /* copy parameter data in parameter buffer */
00172                   memcpy(bp, mp, framedatasize);
00173                   /* increment buffer pointer */
00174                   bp += framedatasize;
00175                }
00176                else
00177                {
00178                   framedatasize -= totalsize - *psize;
00179                   totalsize = *psize;
00180                   /* copy parameter data in parameter buffer */
00181                   if (framedatasize > 0) memcpy(bp, mp, framedatasize);
00182                }   
00183 
00184                if (!aSoEp->incomplete)   
00185                {
00186                   NotLast = FALSE;
00187                   *psize = totalsize;
00188                }   
00189             }   
00190             /* other slave response */
00191             else
00192             {
00193                NotLast = FALSE;
00194                if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) &&
00195                    (aSoEp->opCode == ECT_SOE_READRES) &&
00196                    (aSoEp->error == 1))
00197                {
00198                   mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16));
00199                   errorcode = (uint16 *)mp;
00200                   ecx_SoEerror(context, slave, idn, *errorcode);
00201                }
00202                else
00203                {
00204                   ecx_packeterror(context, slave, idn, 0, 1); /* Unexpected frame returned */
00205                }
00206                wkc = 0;
00207             }
00208          }
00209          else
00210          {
00211             NotLast = FALSE;
00212             ecx_packeterror(context, slave, idn, 0, 4); /* no response */
00213          }   
00214       }   
00215    }
00216    return wkc;
00217 }
00218 
00234 int ecx_SoEwrite(ecx_contextt *context, uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout)
00235 {
00236    ec_SoEt *SoEp, *aSoEp;
00237    uint16 framedatasize, maxdata;
00238    int wkc;
00239    uint8 *mp;
00240    uint8 *hp;
00241    uint16 *errorcode;
00242    ec_mbxbuft MbxIn, MbxOut;
00243    uint8 cnt;
00244    boolean NotLast;
00245 
00246    ec_clearmbx(&MbxIn);
00247    /* Empty slave out mailbox if something is in. Timeout set to 0 */
00248    wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0);
00249    ec_clearmbx(&MbxOut);
00250    aSoEp = (ec_SoEt *)&MbxIn;
00251    SoEp = (ec_SoEt *)&MbxOut;
00252    SoEp->MbxHeader.address = htoes(0x0000);
00253    SoEp->MbxHeader.priority = 0x00;
00254    SoEp->opCode = ECT_SOE_WRITEREQ;
00255    SoEp->error = 0;
00256    SoEp->driveNo = driveNo;
00257    SoEp->elementflags = elementflags;
00258    hp = p;
00259    mp = (uint8 *)&MbxOut + sizeof(ec_SoEt);
00260    maxdata = context->slavelist[slave].mbx_l - sizeof(ec_SoEt);
00261    NotLast = TRUE;
00262    while (NotLast)
00263    {   
00264       framedatasize = psize;
00265       NotLast = FALSE;
00266       SoEp->idn = htoes(idn);
00267       SoEp->incomplete = 0;
00268       if (framedatasize > maxdata)
00269       {
00270          framedatasize = maxdata;  /*  segmented transfer needed  */
00271          NotLast = TRUE;
00272          SoEp->incomplete = 1;
00273          SoEp->fragmentsleft = psize / maxdata;
00274       }
00275       SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert) + framedatasize);
00276       /* get new mailbox counter, used for session handle */
00277       cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
00278       context->slavelist[slave].mbx_cnt = cnt;
00279       SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */
00280       /* copy parameter data to mailbox */
00281       memcpy(mp, hp, framedatasize);
00282       hp += framedatasize;
00283       psize -= framedatasize;
00284       /* send SoE request to slave */
00285       wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00286       if (wkc > 0) /* succeeded to place mailbox in slave ? */
00287       {
00288          if (!NotLast || !ecx_mbxempty(context, slave, timeout))
00289          {   
00290             /* clean mailboxbuffer */
00291             ec_clearmbx(&MbxIn);
00292             /* read slave response */
00293             wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout);
00294             if (wkc > 0) /* succeeded to read slave response ? */
00295             {
00296                NotLast = FALSE;
00297                /* slave response should be SoE, WriteRes */
00298                if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) &&
00299                    (aSoEp->opCode == ECT_SOE_WRITERES) &&
00300                    (aSoEp->error == 0) &&
00301                    (aSoEp->driveNo == driveNo) &&
00302                    (aSoEp->elementflags == elementflags))
00303                {
00304                   /* SoE write succeeded */
00305                }   
00306                /* other slave response */
00307                else
00308                {
00309                   if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) &&
00310                       (aSoEp->opCode == ECT_SOE_READRES) &&
00311                       (aSoEp->error == 1))
00312                   {
00313                      mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16));
00314                      errorcode = (uint16 *)mp;
00315                      ecx_SoEerror(context, slave, idn, *errorcode);
00316                   }
00317                   else
00318                   {
00319                      ecx_packeterror(context, slave, idn, 0, 1); /* Unexpected frame returned */
00320                   }
00321                   wkc = 0;
00322                }
00323             }
00324             else
00325             {
00326                ecx_packeterror(context, slave, idn, 0, 4); /* no response */
00327             }   
00328          }   
00329       }   
00330    }
00331    return wkc;
00332 }
00333 
00346 int ecx_readIDNmap(ecx_contextt *context, uint16 slave, int *Osize, int *Isize)
00347 {
00348    int retVal = 0;
00349    int   wkc;
00350    int psize;
00351    uint16 entries, itemcount;
00352    ec_SoEmappingt     SoEmapping;
00353    ec_SoEattributet   SoEattribute;
00354 
00355    *Isize = 0;
00356    *Osize = 0;
00357    psize = sizeof(SoEmapping);
00358    /* read output mapping via SoE */
00359    wkc = ecx_SoEread(context, slave, 0, EC_SOE_VALUE_B, EC_IDN_MDTCONFIG, &psize, &SoEmapping, EC_TIMEOUTRXM);
00360    if ((wkc > 0) && (psize >= 4) && ((entries = etohs(SoEmapping.currentlength) / 2) > 0) && (entries <= EC_SOE_MAXMAPPING))
00361    {
00362       /* command word (uint16) is always mapped but not in list */
00363       *Osize = 16; 
00364       for (itemcount = 0 ; itemcount < entries ; itemcount++)
00365       {
00366          psize = sizeof(SoEattribute);
00367          /* read attribute of each IDN in mapping list */
00368          wkc = ecx_SoEread(context, slave, 0, EC_SOE_ATTRIBUTE_B, SoEmapping.idn[itemcount], &psize, &SoEattribute, EC_TIMEOUTRXM);
00369          if ((wkc > 0) && (!SoEattribute.list))
00370          {
00371             /* length : 0 = 8bit, 1 = 16bit .... */
00372             *Osize += (int)8 << SoEattribute.length;
00373          }   
00374       }   
00375    }   
00376    psize = sizeof(SoEmapping);
00377    /* read input mapping via SoE */
00378    wkc = ecx_SoEread(context, slave, 0, EC_SOE_VALUE_B, EC_IDN_ATCONFIG, &psize, &SoEmapping, EC_TIMEOUTRXM);
00379    if ((wkc > 0) && (psize >= 4) && ((entries = etohs(SoEmapping.currentlength) / 2) > 0) && (entries <= EC_SOE_MAXMAPPING))
00380    {
00381       /* status word (uint16) is always mapped but not in list */
00382       *Isize = 16; 
00383       for (itemcount = 0 ; itemcount < entries ; itemcount++)
00384       {
00385          psize = sizeof(SoEattribute);
00386          /* read attribute of each IDN in mapping list */
00387          wkc = ecx_SoEread(context, slave, 0, EC_SOE_ATTRIBUTE_B, SoEmapping.idn[itemcount], &psize, &SoEattribute, EC_TIMEOUTRXM);
00388          if ((wkc > 0) && (!SoEattribute.list))
00389          {
00390             /* length : 0 = 8bit, 1 = 16bit .... */
00391             *Isize += (int)8 << SoEattribute.length;
00392          }   
00393       }   
00394    }   
00395 
00396    /* found some I/O bits ? */
00397    if ((*Isize > 0) || (*Osize > 0))
00398    {
00399       retVal = 1;
00400    }
00401    return retVal;
00402 }
00403 
00404 #ifdef EC_VER1
00405 int ec_SoEread(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout)
00406 {
00407    return ecx_SoEread(&ecx_context, slave, driveNo, elementflags, idn, psize, p, timeout);
00408 }
00409 
00410 int ec_SoEwrite(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout)
00411 {
00412    return ecx_SoEwrite(&ecx_context, slave, driveNo, elementflags, idn, psize, p, timeout);
00413 }
00414 
00415 int ec_readIDNmap(uint16 slave, int *Osize, int *Isize)
00416 {
00417    return ecx_readIDNmap(&ecx_context, slave, Osize, Isize);
00418 }
00419 #endif


ethercat_soem
Author(s): Arthur Ketels, M.J.G. van de Molengraft
autogenerated on Wed Aug 26 2015 11:32:40