ethercatfoe.c

Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatfoe.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  *
00011  * SOEM is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the Free
00013  * Software Foundation.
00014  *
00015  * SOEM is distributed in the hope that it will be useful, but WITHOUT ANY
00016  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018  * for more details.
00019  *
00020  * As a special exception, if other files instantiate templates or use macros
00021  * or inline functions from this file, or you compile this file and link it
00022  * with other works to produce a work based on this file, this file does not
00023  * by itself cause the resulting work to be covered by the GNU General Public
00024  * License. However the source code for this file must still be made available
00025  * in accordance with section (3) of the GNU General Public License.
00026  *
00027  * This exception does not invalidate any other reasons why a work based on
00028  * this file might be covered by the GNU General Public License.
00029  *
00030  * The EtherCAT Technology, the trade name and logo “EtherCAT” are the intellectual
00031  * property of, and protected by Beckhoff Automation GmbH. You can use SOEM for
00032  * the sole purpose of creating, using and/or selling or otherwise distributing
00033  * an EtherCAT network master provided that an EtherCAT Master License is obtained
00034  * from Beckhoff Automation GmbH.
00035  *
00036  * In case you did not receive a copy of the EtherCAT Master License along with
00037  * SOEM write to Beckhoff Automation GmbH, Eiserstraße 5, D-33415 Verl, Germany
00038  * (www.beckhoff.com).
00039  *
00040  * 14-06-2010 : fixed bug in FOEread() by Torsten Bitterlich
00041  */
00042 
00043 /** \file 
00044  * \brief
00045  * File over EtherCAT (FoE) module.
00046  *
00047  * SDO read / write and SDO service functions
00048  */
00049 
00050 #include <stdio.h>
00051 #include <string.h>
00052 #include <sys/time.h>
00053 #include <unistd.h>
00054 #include "ethercattype.h"
00055 #include "nicdrv.h"
00056 #include "ethercatbase.h"
00057 #include "ethercatmain.h"
00058 #include "ethercatfoe.h"
00059 
00060 #define EC_MAXFOEDATA 512
00061 
00062 /** FOE structure.
00063  * Used for Read, Write, Data, Ack and Error mailbox packets.
00064  */
00065 typedef struct PACKED
00066 {
00067     ec_mbxheadert   MbxHeader;
00068   uint8     OpCode;
00069   uint8     Reserved;
00070   union
00071   { 
00072     uint32      Password;
00073     uint32      PacketNumber;
00074     uint32      ErrorCode;
00075   };
00076   union
00077   { 
00078     char      FileName[EC_MAXFOEDATA];
00079     uint8     Data[EC_MAXFOEDATA];
00080     char      ErrorText[EC_MAXFOEDATA];
00081   };  
00082 } ec_FOEt;
00083 
00084 /** FoE read, blocking.
00085  * 
00086  * @param[in]  slave    = Slave number.
00087  * @param[in]  filename   = Filename of file to read.
00088  * @param[in]  password     = password.
00089  * @param[in,out] psize   = Size in bytes of file buffer, returns bytes read from file.
00090  * @param[out] p      = Pointer to file buffer
00091  * @param[in]  timeout    = Timeout in us, standard is EC_TIMEOUTRXM
00092  * @return Workcounter from last slave response
00093  */
00094 int ec_FOEread(uint16 slave, char *filename, uint32 password, int *psize, void *p, int timeout)
00095 {
00096     ec_FOEt *FOEp, *aFOEp;
00097   int wkc;
00098     int32 dataread = 0;
00099   int32 buffersize, packetnumber, prevpacket = 0;
00100   uint16 fnsize, maxdata, segmentdata;
00101     ec_mbxbuft MbxIn, MbxOut;
00102     uint8 cnt;
00103     boolean worktodo;
00104 
00105   buffersize = *psize;
00106     ec_clearmbx(&MbxIn);
00107   /* Empty slave out mailbox if something is in. Timout set to 0 */
00108     wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0);
00109     ec_clearmbx(&MbxOut);
00110     aFOEp = (ec_FOEt *)&MbxIn;
00111     FOEp = (ec_FOEt *)&MbxOut;
00112   fnsize = strlen(filename);
00113   maxdata = ec_slave[slave].mbx_l - 12;
00114   if (fnsize > maxdata)
00115     fnsize = maxdata;
00116     FOEp->MbxHeader.length = htoes(0x0006 + fnsize);
00117     FOEp->MbxHeader.address = htoes(0x0000);
00118     FOEp->MbxHeader.priority = 0x00;
00119   /* get new mailbox count value, used as session handle */
00120     cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00121     ec_slave[slave].mbx_cnt = cnt;
00122     FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00123     FOEp->OpCode = ECT_FOE_READ;
00124     FOEp->Password = htoel(password);
00125   /* copy filename in mailbox */
00126   memcpy(&FOEp->FileName[0], filename, fnsize);
00127   /* send FoE request to slave */
00128     wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00129     if (wkc > 0) /* succeeded to place mailbox in slave ? */
00130     {
00131     do
00132     { 
00133       worktodo = FALSE;
00134       /* clean mailboxbuffer */
00135       ec_clearmbx(&MbxIn);
00136       /* read slave response */
00137       wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout);
00138       if (wkc > 0) /* succeeded to read slave response ? */
00139       {
00140         /* slave response should be FoE */
00141         if ((aFOEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_FOE)
00142         {
00143           if(aFOEp->OpCode == ECT_FOE_DATA)
00144           {
00145             segmentdata = etohs(aFOEp->MbxHeader.length) - 0x0006;
00146             packetnumber = etohl(aFOEp->PacketNumber);
00147             if ((packetnumber == ++prevpacket) && (dataread + segmentdata <= buffersize))
00148             {
00149               memcpy(p, &aFOEp->Data[0], segmentdata);
00150               dataread += segmentdata;
00151               p += segmentdata;
00152               if (segmentdata == maxdata)
00153                 worktodo = TRUE; 
00154               FOEp->MbxHeader.length = htoes(0x0006);
00155               FOEp->MbxHeader.address = htoes(0x0000);
00156               FOEp->MbxHeader.priority = 0x00;
00157               /* get new mailbox count value */
00158               cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00159               ec_slave[slave].mbx_cnt = cnt;
00160               FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00161               FOEp->OpCode = ECT_FOE_ACK;
00162               FOEp->PacketNumber = htoel(packetnumber);
00163               /* send FoE ack to slave */
00164               wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00165               if (wkc <= 0)
00166                 worktodo = FALSE;
00167             }
00168             else
00169             {
00170               /* FoE error */
00171               wkc = -EC_ERR_TYPE_FOE_BUF2SMALL;
00172             }
00173           }
00174           else
00175           if(aFOEp->OpCode == ECT_FOE_ERROR)
00176           {
00177             /* FoE error */
00178             wkc = -EC_ERR_TYPE_FOE_ERROR;
00179           }
00180           else
00181           {
00182             /* unexpected mailbox received */
00183             wkc = -EC_ERR_TYPE_PACKET_ERROR;
00184           }
00185         }
00186         else
00187         {
00188           /* unexpected mailbox received */
00189           wkc = -EC_ERR_TYPE_PACKET_ERROR;
00190         }
00191         *psize = dataread;
00192       }
00193     } while (worktodo); 
00194   }
00195   
00196   return wkc;
00197 } 
00198 
00199 /** FoE write, blocking.
00200  * 
00201  * @param[in]  slave    = Slave number.
00202  * @param[in]  filename   = Filename of file to write.
00203  * @param[in]  password     = password.
00204  * @param[in]  psize    = Size in bytes of file buffer.
00205  * @param[out] p      = Pointer to file buffer
00206  * @param[in]  timeout    = Timeout in us, standard is EC_TIMEOUTRXM
00207  * @return Workcounter from last slave response
00208  */
00209 int ec_FOEwrite(uint16 slave, char *filename, uint32 password, int psize, void *p, int timeout)
00210 {
00211     ec_FOEt *FOEp, *aFOEp;
00212   int wkc;
00213   int32 packetnumber, sendpacket = 0;
00214   uint16 fnsize, maxdata;
00215   int segmentdata;
00216     ec_mbxbuft MbxIn, MbxOut;
00217     uint8 cnt;
00218     boolean worktodo;
00219   int tsize;
00220 
00221     ec_clearmbx(&MbxIn);
00222   /* Empty slave out mailbox if something is in. Timout set to 0 */
00223     wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0);
00224     ec_clearmbx(&MbxOut);
00225     aFOEp = (ec_FOEt *)&MbxIn;
00226     FOEp = (ec_FOEt *)&MbxOut;
00227   fnsize = strlen(filename);
00228   maxdata = ec_slave[slave].mbx_l - 12;
00229   if (fnsize > maxdata)
00230     fnsize = maxdata;
00231     FOEp->MbxHeader.length = htoes(0x0006 + fnsize);
00232     FOEp->MbxHeader.address = htoes(0x0000);
00233     FOEp->MbxHeader.priority = 0x00;
00234   /* get new mailbox count value, used as session handle */
00235     cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00236     ec_slave[slave].mbx_cnt = cnt;
00237     FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00238     FOEp->OpCode = ECT_FOE_WRITE;
00239     FOEp->Password = htoel(password);
00240   /* copy filename in mailbox */
00241   memcpy(&FOEp->FileName[0], filename, fnsize);
00242   /* send FoE request to slave */
00243     wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00244     if (wkc > 0) /* succeeded to place mailbox in slave ? */
00245     {
00246     do
00247     { 
00248       worktodo = FALSE;
00249       /* clean mailboxbuffer */
00250       ec_clearmbx(&MbxIn);
00251       /* read slave response */
00252       wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout);
00253       if (wkc > 0) /* succeeded to read slave response ? */
00254       {
00255         /* slave response should be FoE */
00256         if ((aFOEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_FOE)
00257         {
00258           if(aFOEp->OpCode == ECT_FOE_ACK)
00259           {
00260             packetnumber = etohl(aFOEp->PacketNumber);
00261             if (packetnumber == sendpacket)
00262             {
00263               tsize = psize;
00264               if (tsize > maxdata)
00265               {
00266                 worktodo = TRUE; 
00267                 tsize = maxdata;
00268               } 
00269               segmentdata = tsize;
00270               psize -= segmentdata;
00271               FOEp->MbxHeader.length = htoes(0x0006 + segmentdata);
00272               FOEp->MbxHeader.address = htoes(0x0000);
00273               FOEp->MbxHeader.priority = 0x00;
00274               /* get new mailbox count value */
00275               cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00276               ec_slave[slave].mbx_cnt = cnt;
00277               FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00278               FOEp->OpCode = ECT_FOE_DATA;
00279               FOEp->PacketNumber = htoel(++sendpacket);
00280               memcpy(&FOEp->Data[0], p, segmentdata);
00281               p += segmentdata;
00282               /* send FoE data to slave */
00283               wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00284               if (wkc <= 0)
00285                 worktodo = FALSE;
00286             }
00287             else
00288             {
00289               /* FoE error */
00290               wkc = -EC_ERR_TYPE_FOE_PACKETNUMBER;
00291             }
00292           }
00293           else
00294           if(aFOEp->OpCode == ECT_FOE_ERROR)
00295           {
00296             /* FoE error */
00297             wkc = -EC_ERR_TYPE_FOE_ERROR;
00298           }
00299           else
00300           {
00301             /* unexpected mailbox received */
00302             wkc = -EC_ERR_TYPE_PACKET_ERROR;
00303           }
00304         }
00305         else
00306         {
00307           /* unexpected mailbox received */
00308           wkc = -EC_ERR_TYPE_PACKET_ERROR;
00309         }
00310       }
00311     } while (worktodo); 
00312   }
00313   
00314   return wkc;
00315 } 
Generated by  doxygen 1.6.3