ethercatcoe.c

Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatcoe.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 
00041 /** \file 
00042  * \brief
00043  * CAN over EtherCAT (CoE) module.
00044  *
00045  * SDO read / write and SDO service functions
00046  */
00047 
00048 #include <stdio.h>
00049 #include <string.h>
00050 #include <sys/time.h>
00051 #include <unistd.h>
00052 #include "ethercattype.h"
00053 #include "nicdrv.h"
00054 #include "ethercatbase.h"
00055 #include "ethercatmain.h"
00056 #include "ethercatcoe.h"
00057 
00058 /** SDO structure, not to be confused with EcSDOserviceT */
00059 typedef struct PACKED
00060 {
00061     ec_mbxheadert   MbxHeader;
00062     uint16          CANOpen;
00063     uint8           Command;
00064     uint16          Index;
00065     uint8           SubIndex;
00066     union
00067     {
00068         uint8   bdata[0x200]; /* variants for easy data access */
00069         uint16  wdata[0x100];
00070         uint32  ldata[0x80];
00071     };
00072 } ec_SDOt;
00073 
00074 /** SDO service structure */
00075 typedef struct PACKED 
00076 {
00077     ec_mbxheadert   MbxHeader;
00078     uint16          CANOpen;
00079     uint8           Opcode;
00080     uint8           Reserved;
00081     uint16          Fragments;
00082     union
00083     {
00084         uint8   bdata[0x200]; /* variants for easy data access */
00085         uint16  wdata[0x100];
00086         uint32  ldata[0x80];
00087     };
00088 } ec_SDOservicet;
00089 
00090 /** SyncManager Communication Type structure for CA */
00091 typedef struct PACKED
00092 {
00093   uint8   n;
00094   uint8   nu1;
00095   uint8   SMtype[EC_MAXSM];
00096 } ec_SMcommtypet; 
00097 
00098 /** SDO assign structure for CA */
00099 typedef struct PACKED
00100 {
00101   uint8   n;
00102   uint8   nu1;
00103   uint16  index[256];
00104 } ec_PDOassignt;  
00105 
00106 /** SDO description structure for CA */
00107 typedef struct PACKED
00108 {
00109   uint8   n;
00110   uint8   nu1;
00111   uint32  PDO[256];
00112 } ec_PDOdesct;  
00113 
00114 /** SyncManager Communication Type struct to store data of one slave */
00115 static ec_SMcommtypet ec_SMcommtype;
00116 /** PDO assign struct to store data of one slave */
00117 static ec_PDOassignt ec_PDOassign;
00118 /** PDO description struct to store data of one slave */
00119 static ec_PDOdesct ec_PDOdesc;
00120 
00121 /** Report SDO error.
00122  *
00123  * @param[in]  Slave    = Slave number
00124  * @param[in]  Index    = Index that generated error
00125  * @param[in]  SubIdx     = Subindex that generated error
00126  * @param[in]  AbortCode  = Abortcode, see EtherCAT documentation for list
00127  */
00128 void ec_SDOerror(uint16 Slave, uint16 Index, uint8 SubIdx, int32 AbortCode)
00129 {
00130     ec_errort Ec;
00131 
00132   gettimeofday(&Ec.Time, 0);
00133     Ec.Slave = Slave;
00134     Ec.Index = Index;
00135     Ec.SubIdx = SubIdx;
00136     EcatError = TRUE;
00137     Ec.Etype = EC_ERR_TYPE_SDO_ERROR;
00138     Ec.AbortCode = AbortCode;
00139     ec_pusherror(&Ec);
00140 }
00141 
00142 
00143 /** Report SDO info error
00144  *
00145  * @param[in]  Slave    = Slave number
00146  * @param[in]  Index    = Index that generated error
00147  * @param[in]  SubIdx     = Subindex that generated error
00148  * @param[in]  AbortCode  = Abortcode, see EtherCAT documentation for list
00149  */
00150 static void ec_SDOinfoerror(uint16 Slave, uint16 Index, uint8 SubIdx, int32 AbortCode)
00151 {
00152     ec_errort Ec;
00153 
00154     Ec.Slave = Slave;
00155     Ec.Index = Index;
00156     Ec.SubIdx = SubIdx;
00157     EcatError = TRUE;
00158     Ec.Etype = EC_ERR_TYPE_SDOINFO_ERROR;
00159     Ec.AbortCode = AbortCode;
00160     ec_pusherror(&Ec);
00161 }
00162 
00163 /** CoE SDO read, blocking. Single subindex or Complete Access.
00164  * 
00165  * Only a "normal" upload request is issued. If the requested parameter is <= 4bytes
00166  * then a "expedited" response is returned, otherwise a "normal" response. If a "normal"
00167  * response is larger than the mailbox size then the response is segmented. The function
00168  * will combine all segments and copy them to the parameter buffer.
00169  *
00170  * @param[in]  slave    = Slave number
00171  * @param[in]  index    = Index to read
00172  * @param[in]  subindex     = Subindex to read, must be 0 or 1 if CA is used.
00173  * @param[in]  CA     = FALSE = single subindex. TRUE = Complete Access, all subindexes read.
00174  * @param[in,out] psize   = Size in bytes of parameter buffer, returns bytes read from SDO.
00175  * @param[out] p      = Pointer to parameter buffer
00176  * @param[in]  timeout    = Timeout in us, standard is EC_TIMEOUTRXM
00177  * @return Workcounter from last slave response
00178  */
00179 int ec_SDOread(uint16 slave, uint16 index, uint8 subindex,
00180                boolean CA, int *psize, void *p, int timeout)
00181 {
00182     ec_SDOt *SDOp, *aSDOp;
00183     uint16 bytesize, Framedatasize;
00184   int wkc;
00185     int32 SDOlen;
00186     uint8 *bp;
00187     uint8 *hp;
00188     ec_mbxbuft MbxIn, MbxOut;
00189     uint8 cnt, toggle;
00190     boolean NotLast;
00191 
00192     ec_clearmbx(&MbxIn);
00193   /* Empty slave out mailbox if something is in. Timout set to 0 */
00194     wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0);
00195     ec_clearmbx(&MbxOut);
00196     aSDOp = (ec_SDOt *)&MbxIn;
00197     SDOp = (ec_SDOt *)&MbxOut;
00198     SDOp->MbxHeader.length = htoes(0x000a);
00199     SDOp->MbxHeader.address = htoes(0x0000);
00200     SDOp->MbxHeader.priority = 0x00;
00201   /* get new mailbox count value, used as session handle */
00202     cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00203     ec_slave[slave].mbx_cnt = cnt;
00204     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
00205     SDOp->CANOpen = htoes(0x000 + (ECT_COES_SDOREQ << 12)); /* number 9bits service upper 4 bits (SDO request) */
00206     if (CA)
00207         SDOp->Command = ECT_SDO_UP_REQ_CA; /* upload request complete access */
00208     else
00209         SDOp->Command = ECT_SDO_UP_REQ; /* upload request normal */
00210     SDOp->Index = htoes(index);
00211     if (CA && (subindex > 1))
00212         subindex = 1;
00213     SDOp->SubIndex = subindex;
00214     SDOp->ldata[0] = 0;
00215   /* send CoE request to slave */
00216     wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00217     if (wkc > 0) /* succeeded to place mailbox in slave ? */
00218     {
00219     /* clean mailboxbuffer */
00220         ec_clearmbx(&MbxIn);
00221     /* read slave response */
00222         wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout);
00223         if (wkc > 0) /* succeeded to read slave response ? */
00224         {
00225       /* slave response should be CoE, SDO response and the correct index */
00226             if (((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) &&
00227                 ((etohs(aSDOp->CANOpen) >> 12) == ECT_COES_SDORES) &&
00228                 (aSDOp->Index == SDOp->Index))
00229             {
00230                 if ((aSDOp->Command & 0x02) > 0)
00231                 { 
00232                     /* expedited frame response */
00233                     bytesize = 4 - ((aSDOp->Command >> 2) & 0x03);
00234                     if (*psize >= bytesize) /* parameter buffer big enough ? */
00235                     {
00236             /* copy parameter in parameter buffer */
00237                         memcpy(p, &aSDOp->ldata[0], bytesize);
00238             /* return the real parameter size */
00239                         *psize = bytesize;
00240                     }
00241                     else
00242                     {
00243                         wkc = 0;
00244                         ec_packeterror(slave, index, subindex, 3); /*  data container too small for type */
00245                     }
00246                 }
00247                 else
00248                 { /* normal frame response */
00249                     SDOlen = etohl(aSDOp->ldata[0]);
00250           /* Does parameter fit in parameter buffer ? */
00251                     if (SDOlen <= *psize)
00252                     {
00253                         bp = p; 
00254                         hp = p;
00255             /* calculate mailbox transfer size */
00256                         Framedatasize = (etohs(aSDOp->MbxHeader.length) - 10);
00257                         if (Framedatasize < SDOlen) /* transfer in segments? */
00258                         {
00259               /* copy parameter data in parameter buffer */
00260                             memcpy(hp, &aSDOp->ldata[1], Framedatasize);
00261               /* increment buffer pointer */
00262                             hp += Framedatasize;
00263                             *psize = Framedatasize;
00264                             NotLast = TRUE;
00265                             toggle= 0x00;
00266                             while (NotLast) /* segmented transfer */
00267                             {
00268                                 SDOp = (ec_SDOt *)&MbxOut;
00269                                 SDOp->MbxHeader.length = htoes(0x000a);
00270                                 SDOp->MbxHeader.address = htoes(0x0000);
00271                                 SDOp->MbxHeader.priority = 0x00;
00272                                 cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00273                                 ec_slave[slave].mbx_cnt = cnt;
00274                                 SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
00275                                 SDOp->CANOpen = htoes(0x000 + (ECT_COES_SDOREQ << 12)); /* number 9bits service upper 4 bits (SDO request) */
00276                                 SDOp->Command = ECT_SDO_SEG_UP_REQ + toggle; /* segment upload request */
00277                                 SDOp->Index = htoes(index);
00278                                 SDOp->SubIndex = subindex;
00279                                 SDOp->ldata[0] = 0;
00280                 /* send segmented upload request to slave */
00281                                 wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00282                 /* is mailbox transfered to slave ? */
00283                                 if (wkc > 0)
00284                                 {
00285                                     ec_clearmbx(&MbxIn);
00286                   /* read slave response */
00287                                     wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout);
00288                   /* has slave responded ? */
00289                                     if (wkc > 0)
00290                                     {
00291                     /* slave response should be CoE, SDO response */
00292                                         if ((((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) &&
00293                                             ((etohs(aSDOp->CANOpen) >> 12) == ECT_COES_SDORES) && 
00294                                             ((aSDOp->Command & 0xe0) == 0x00)))
00295                                         {
00296                       /* calculate mailbox transfer size */
00297                                             Framedatasize = etohs(aSDOp->MbxHeader.length) - 3;
00298                                             if ((aSDOp->Command & 0x01) > 0)
00299                                             { /* last segment */
00300                                                 NotLast = FALSE;
00301                                                 if (Framedatasize == 7)
00302                                                     /* substract unused bytes from frame */
00303                                                     Framedatasize = Framedatasize - ((aSDOp->Command & 0x0e) >> 1);
00304                         /* copy to parameter buffer */
00305                                                 memcpy(hp, &(aSDOp->Index), Framedatasize);
00306                                             }
00307                                             else /* segments follow */
00308                                             {
00309                         /* copy to parameter buffer */
00310                                                 memcpy(hp, &(aSDOp->Index), Framedatasize);
00311                         /* increment buffer pointer */
00312                                                 hp += Framedatasize;
00313                                             }
00314                       /* update parametersize */
00315                                             *psize += Framedatasize;
00316                                         }
00317                     /* unexpected frame returned from slave */
00318                                         else
00319                                         {
00320                                             NotLast = FALSE;
00321                                             if ((aSDOp->Command) == ECT_SDO_ABORT) /* SDO abort frame received */
00322                                                 ec_SDOerror(slave, index, subindex, etohl(aSDOp->ldata[0]));
00323                                             else
00324                                                 ec_packeterror(slave, index, subindex, 1); /* Unexpected frame returned */
00325                                             wkc = 0;
00326                                         }
00327                                     }
00328                                 }
00329                                 toggle = toggle ^ 0x10; /* toggle bit for segment request */
00330                             }
00331                         }
00332             /* non segmented transfer */
00333                         else
00334                         {
00335               /* copy to parameter buffer */
00336                             memcpy(bp, &aSDOp->ldata[1], SDOlen);
00337                             *psize = SDOlen;
00338                         }
00339                     }
00340           /* parameter buffer too small */
00341                     else
00342                     {
00343                         wkc = 0;
00344                         ec_packeterror(slave, index, subindex, 3); /*  data container too small for type */
00345                     }
00346                 }
00347             }
00348       /* other slave response */
00349             else
00350             {
00351                 if ((aSDOp->Command) == ECT_SDO_ABORT) /* SDO abort frame received */
00352                     ec_SDOerror(slave, index, subindex, etohl(aSDOp->ldata[0]));
00353                 else
00354                     ec_packeterror(slave, index, subindex, 1); /* Unexpected frame returned */
00355                 wkc = 0;
00356             }
00357         }
00358     }
00359     return wkc;
00360 }
00361 
00362 /** CoE SDO write, blocking. Single subindex or Complete Access.
00363  * 
00364  * Only a "normal" download request is issued. If the paramater is larger than
00365  * the mailbox size then the download is segmented. The function will split the
00366  * parameter data in segments and send them to the slave one by one.
00367  *
00368  * @param[in]  Slave    = Slave number
00369  * @param[in]  Index    = Index to write
00370  * @param[in]  SubIndex     = Subindex to write, must be 0 or 1 if CA is used.
00371  * @param[in]  CA     = FALSE = single subindex. TRUE = Complete Access, all subindexes written.
00372  * @param[in]  psize    = Size in bytes of parameter buffer.
00373  * @param[out] p      = Pointer to parameter buffer
00374  * @param[in]  Timeout    = Timeout in us, standard is EC_TIMEOUTRXM
00375  * @return Workcounter from last slave response
00376  */
00377 int ec_SDOwrite(uint16 Slave, uint16 Index, uint8 SubIndex,
00378     boolean CA, int psize, void *p, int Timeout)
00379 {
00380     ec_SDOt *SDOp, *aSDOp;
00381     int wkc, maxdata;
00382     ec_mbxbuft MbxIn, MbxOut;
00383     uint8 cnt, toggle;
00384     uint16 framedatasize;
00385     boolean  NotLast;
00386     uint8 *hp;
00387 
00388     ec_clearmbx(&MbxIn);
00389   /* Empty slave out mailbox if something is in. Timout set to 0 */
00390     wkc = ec_mbxreceive(Slave, (ec_mbxbuft *)&MbxIn, 0);
00391     ec_clearmbx(&MbxOut);
00392     aSDOp = (ec_SDOt *)&MbxIn;
00393     SDOp = (ec_SDOt *)&MbxOut;
00394     maxdata = ec_slave[Slave].mbx_l - 0x10; /* data section=mailbox size - 6 mbx - 2 CoE - 8 sdo req */
00395     framedatasize = psize;
00396     NotLast = FALSE;
00397     if (framedatasize > maxdata)
00398     {
00399         framedatasize = maxdata;  /*  segmented transfer needed  */
00400         NotLast = TRUE;
00401     }
00402     SDOp->MbxHeader.length = htoes(0x0a + framedatasize);
00403     SDOp->MbxHeader.address = htoes(0x0000);
00404     SDOp->MbxHeader.priority = 0x00;
00405   /* get new mailbox counter, used for session handle */
00406     cnt = ec_nextmbxcnt(ec_slave[Slave].mbx_cnt);
00407     ec_slave[Slave].mbx_cnt = cnt;
00408     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
00409     SDOp->CANOpen = htoes(0x000 + (ECT_COES_SDOREQ << 12)); /* number 9bits service upper 4 bits */
00410     if (CA)
00411         SDOp->Command = ECT_SDO_DOWN_INIT_CA; /* Complete Access, normal SDO init download transfer */
00412     else
00413         SDOp->Command = ECT_SDO_DOWN_INIT; /* normal SDO init download transfer */
00414     SDOp->Index = htoes(Index);
00415     SDOp->SubIndex = SubIndex;
00416     if (CA && (SubIndex > 1))
00417         SDOp->SubIndex = 1;
00418     SDOp->ldata[0] = htoel(psize);
00419     hp = p;
00420   /* copy parameter data to mailbox */
00421     memcpy(&SDOp->ldata[1], hp, framedatasize);
00422     hp += framedatasize;
00423     psize -= framedatasize;
00424   /* send mailbox SDO download request to slave */
00425     wkc = ec_mbxsend(Slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00426     if (wkc > 0)
00427     {
00428         ec_clearmbx(&MbxIn);
00429     /* read slave response */
00430         wkc = ec_mbxreceive(Slave, (ec_mbxbuft *)&MbxIn, Timeout);
00431         if (wkc > 0)
00432         {
00433       /* response should be CoE, SDO response, correct index and subindex */
00434             if (((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) && 
00435                 ((etohs(aSDOp->CANOpen) >> 12) == ECT_COES_SDORES) &&
00436                 (aSDOp->Index == SDOp->Index) &&
00437                 (aSDOp->SubIndex == SDOp->SubIndex))
00438             {
00439                 /* all ok */
00440                 maxdata += 7;
00441                 toggle = 0;
00442         /* repeat while segments left */
00443                 while (NotLast)
00444                 {
00445                     SDOp = (ec_SDOt *)&MbxOut;
00446                     framedatasize = psize;
00447                     NotLast = FALSE;
00448                     SDOp->Command = 0x01; /* last segment */
00449                     if (framedatasize > maxdata)
00450                     {
00451                         framedatasize = maxdata;  /*  more segments needed  */
00452                         NotLast = TRUE;
00453                         SDOp->Command = 0x00; /* segments follow */
00454                     }
00455                     if (!NotLast && (framedatasize < 7))
00456                     {
00457                         SDOp->MbxHeader.length = htoes(0x0a); /* minimum size */
00458                         SDOp->Command = 0x01 + ((7 - framedatasize) << 1); /* last segment reduced octets */
00459                     }
00460                     else
00461                         SDOp->MbxHeader.length = htoes(framedatasize + 3); /* data + 2 CoE + 1 SDO */
00462                     SDOp->MbxHeader.address = htoes(0x0000);
00463                     SDOp->MbxHeader.priority = 0x00;
00464           /* get new mailbox counter value */
00465                     cnt = ec_nextmbxcnt(ec_slave[Slave].mbx_cnt);
00466                     ec_slave[Slave].mbx_cnt = cnt;
00467                     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
00468                     SDOp->CANOpen = htoes(0x000 + (ECT_COES_SDOREQ << 12)); /* number 9bits service upper 4 bits (SDO request) */
00469                     SDOp->Command = SDOp->Command + toggle; /* add toggle bit to command byte */
00470           /* copy parameter data to mailbox */
00471                     memcpy(&SDOp->Index, hp, framedatasize);
00472           /* update parameter buffer pointer */
00473                     hp += framedatasize;
00474                     psize -= framedatasize;
00475           /* send SDO download request */
00476                     wkc = ec_mbxsend(Slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00477                     if (wkc > 0)
00478                     {
00479                         ec_clearmbx(&MbxIn);
00480             /* read slave response */
00481                         wkc = ec_mbxreceive(Slave, (ec_mbxbuft *)&MbxIn, Timeout);
00482                         if (wkc > 0)
00483                         {
00484                             if (((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) &&
00485                                 ((etohs(aSDOp->CANOpen) >> 12) == ECT_COES_SDORES) &&
00486                                 ((aSDOp->Command & 0xe0) == 0x20))
00487                             {
00488                                 /* all OK, nothing to do */
00489                             }
00490                             else
00491                             {
00492                                 if (aSDOp->Command == ECT_SDO_ABORT) /* SDO abort frame received */
00493                                     ec_SDOerror(Slave, Index, SubIndex, etohl(aSDOp->ldata[0]));
00494                                 else
00495                                     ec_packeterror(Slave, Index, SubIndex, 1); /* Unexpected frame returned */
00496                                 wkc = 0;
00497                                 NotLast = FALSE;
00498                             }
00499                         }
00500                     }
00501                     toggle = toggle ^ 0x10; /* toggle bit for segment request */
00502                 }
00503             }
00504       /* unexpected response from slave */
00505             else
00506             {
00507                 if (aSDOp->Command == ECT_SDO_ABORT) /* SDO abort frame received */
00508                     ec_SDOerror(Slave, Index, SubIndex, etohl(aSDOp->ldata[0]));
00509                 else
00510                     ec_packeterror(Slave, Index, SubIndex, 1); /* Unexpected frame returned */
00511                 wkc = 0;
00512             }
00513         }
00514     }
00515 
00516     return wkc;
00517 }
00518 
00519 /** CoE RxPDO write, blocking.
00520  * 
00521  * A RxPDO download request is issued.
00522  *
00523  * @param[in]  Slave    = Slave number
00524  * @param[in]  RxPDOnumber  = Related RxPDO number
00525  * @param[in]  psize    = Size in bytes of PDO buffer.
00526  * @param[out] p      = Pointer to PDO buffer
00527  * @return Workcounter from last slave response
00528  */
00529 int ec_RxPDO(uint16 Slave, uint16 RxPDOnumber , int psize, void *p)
00530 {
00531     ec_SDOt *SDOp;
00532     int wkc, maxdata;
00533     ec_mbxbuft MbxIn, MbxOut;
00534     uint8 cnt;
00535     uint16 framedatasize;
00536 
00537     ec_clearmbx(&MbxIn);
00538   /* Empty slave out mailbox if something is in. Timout set to 0 */
00539     wkc = ec_mbxreceive(Slave, (ec_mbxbuft *)&MbxIn, 0);
00540     ec_clearmbx(&MbxOut);
00541     SDOp = (ec_SDOt *)&MbxOut;
00542     maxdata = ec_slave[Slave].mbx_l - 0x08; /* data section=mailbox size - 6 mbx - 2 CoE */
00543     framedatasize = psize;
00544     if (framedatasize > maxdata)
00545         framedatasize = maxdata;  /*  limit transfer */
00546     SDOp->MbxHeader.length = htoes(0x02 + framedatasize);
00547     SDOp->MbxHeader.address = htoes(0x0000);
00548     SDOp->MbxHeader.priority = 0x00;
00549   /* get new mailbox counter, used for session handle */
00550     cnt = ec_nextmbxcnt(ec_slave[Slave].mbx_cnt);
00551     ec_slave[Slave].mbx_cnt = cnt;
00552     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
00553     SDOp->CANOpen = htoes((RxPDOnumber & 0x01ff) + (ECT_COES_RXPDO << 12)); /* number 9bits service upper 4 bits */
00554   /* copy PDO data to mailbox */
00555     memcpy(&SDOp->Command, p, framedatasize);
00556   /* send mailbox SDO download request to slave */
00557     wkc = ec_mbxsend(Slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00558 
00559     return wkc;
00560 }
00561 
00562 /** CoE TxPDO read remote request, blocking.
00563  * 
00564  * A RxPDO download request is issued.
00565  *
00566  * @param[in]  slave    = Slave number
00567  * @param[in]  TxPDOnumber  = Related TxPDO number
00568  * @param[in,out] psize   = Size in bytes of PDO buffer, returns bytes read from PDO.
00569  * @param[out] p      = Pointer to PDO buffer
00570  * @param[in]  timeout    = Timeout in us, standard is EC_TIMEOUTRXM
00571  * @return Workcounter from last slave response
00572  */
00573 int ec_TxPDO(uint16 slave, uint16 TxPDOnumber , int *psize, void *p, int timeout)
00574 {
00575     ec_SDOt *SDOp, *aSDOp;
00576     int wkc;
00577     ec_mbxbuft MbxIn, MbxOut;
00578     uint8 cnt;
00579     uint16 framedatasize;
00580 
00581     ec_clearmbx(&MbxIn);
00582   /* Empty slave out mailbox if something is in. Timout set to 0 */
00583     wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0);
00584     ec_clearmbx(&MbxOut);
00585     aSDOp = (ec_SDOt *)&MbxIn;
00586     SDOp = (ec_SDOt *)&MbxOut;
00587     SDOp->MbxHeader.length = htoes(0x02);
00588     SDOp->MbxHeader.address = htoes(0x0000);
00589     SDOp->MbxHeader.priority = 0x00;
00590   /* get new mailbox counter, used for session handle */
00591     cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt);
00592     ec_slave[slave].mbx_cnt = cnt;
00593     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
00594     SDOp->CANOpen = htoes((TxPDOnumber & 0x01ff) + (ECT_COES_TXPDO_RR << 12)); /* number 9bits service upper 4 bits */
00595     wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00596     if (wkc > 0)
00597     {
00598     /* clean mailboxbuffer */
00599         ec_clearmbx(&MbxIn);
00600     /* read slave response */
00601         wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout);
00602         if (wkc > 0) /* succeeded to read slave response ? */
00603         {
00604       /* slave response should be CoE, TxPDO */
00605             if (((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) &&
00606                 ((etohs(aSDOp->CANOpen) >> 12) == ECT_COES_TXPDO))
00607             {
00608         /* TxPDO response */
00609         framedatasize = (aSDOp->MbxHeader.length - 2);
00610         if (*psize >= framedatasize) /* parameter buffer big enough ? */
00611         {
00612           /* copy parameter in parameter buffer */
00613           memcpy(p, &aSDOp->Command, framedatasize);
00614           /* return the real parameter size */
00615           *psize = framedatasize;
00616         }
00617         /* parameter buffer too small */
00618         else
00619         {
00620           wkc = 0;
00621           ec_packeterror(slave, 0, 0, 3); /*  data container too small for type */
00622         }
00623       } 
00624       /* other slave response */
00625             else
00626             {
00627                 if ((aSDOp->Command) == ECT_SDO_ABORT) /* SDO abort frame received */
00628                     ec_SDOerror(slave, 0, 0, etohl(aSDOp->ldata[0]));
00629                 else
00630                     ec_packeterror(slave, 0, 0, 1); /* Unexpected frame returned */
00631                 wkc = 0;
00632             }
00633     }     
00634     }
00635 
00636     return wkc;
00637 }
00638 
00639 /** Read PDO assign structure */
00640 int ec_readPDOassign(uint16 Slave, uint16 PDOassign)
00641 {
00642     uint16 idxloop, nidx, subidxloop, rdat, idx, subidx;
00643   uint8 subcnt;
00644   int wkc, bsize = 0, rdl;
00645     int32 rdat2;
00646 
00647   rdl = sizeof(rdat); rdat = 0;
00648   /* read PDO assign subindex 0 ( = number of PDO's) */
00649     wkc = ec_SDOread(Slave, PDOassign, 0x00, FALSE, &rdl, &rdat, EC_TIMEOUTRXM);
00650   rdat = etohs(rdat);
00651   /* positive result from slave ? */
00652     if ((wkc > 0) && (rdat > 0))
00653     {
00654     /* number of available sub indexes */
00655         nidx = rdat;
00656         bsize = 0;
00657     /* read all PDO's */
00658         for (idxloop = 1; idxloop <= nidx; idxloop++)
00659         {
00660             rdl = sizeof(rdat); rdat = 0;
00661       /* read PDO assign */
00662             wkc = ec_SDOread(Slave, PDOassign, (uint8)idxloop, FALSE, &rdl, &rdat, EC_TIMEOUTRXM);
00663       /* result is index of PDO */
00664             idx = etohl(rdat);
00665             if (idx > 0)
00666             {
00667                 rdl = sizeof(subcnt); subcnt = 0;
00668         /* read number of subindexes of PDO */
00669                 wkc = ec_SDOread(Slave,idx, 0x00, FALSE, &rdl, &subcnt, EC_TIMEOUTRXM);
00670                 subidx = subcnt;
00671         /* for each subindex */
00672                 for (subidxloop = 1; subidxloop <= subidx; subidxloop++)
00673                 {
00674                     rdl = sizeof(rdat2); rdat2 = 0;
00675           /* read SDO that is mapped in PDO */
00676                     wkc = ec_SDOread(Slave, idx, (uint8)subidxloop, FALSE, &rdl, &rdat2, EC_TIMEOUTRXM);
00677           rdat2 = etohl(rdat2);
00678           /* extract bitlength of SDO */
00679           if (LO_BYTE(rdat2) < 0xff)
00680                       bsize += LO_BYTE(rdat2);
00681           else
00682           {
00683                       rdl = sizeof(rdat); rdat = htoes(0xff);
00684             /* read Object Entry in Object database */
00685 //            wkc = ec_readOEsingle(idx, (uint8)SubCount, pODlist, pOElist);
00686             bsize += etohs(rdat);           
00687           }
00688                 };
00689             };
00690         };
00691     };
00692   /* return total found bitlength (PDO) */
00693   return bsize;
00694 }
00695 
00696 /** Read PDO assign structure in Complete Access mode */
00697 int ec_readPDOassignCA(uint16 Slave, uint16 PDOassign)
00698 {
00699     uint16 idxloop, nidx, subidxloop, idx, subidx;
00700   int wkc, bsize = 0, rdl;
00701 
00702   /* find maximum size of PDOassign buffer */
00703     rdl = sizeof(ec_PDOassign); 
00704   ec_PDOassign.n=0;
00705   /* read rxPDOassign in CA mode, all subindexes are read in one struct */
00706     wkc = ec_SDOread(Slave, PDOassign, 0x00, TRUE, &rdl, &ec_PDOassign, EC_TIMEOUTRXM);
00707   /* positive result from slave ? */
00708   if ((wkc > 0) && (ec_PDOassign.n > 0))
00709     {
00710         nidx = ec_PDOassign.n;
00711         bsize = 0;
00712     /* for each PDO do */
00713         for (idxloop = 1; idxloop <= nidx; idxloop++)
00714         {
00715       /* get index from PDOassign struct */
00716       idx = etohs(ec_PDOassign.index[idxloop - 1]);
00717             if (idx > 0)
00718             {
00719                 rdl = sizeof(ec_PDOdesc); ec_PDOdesc.n = 0;
00720         /* read SDO's that are mapped in PDO, CA mode */
00721                 wkc = ec_SDOread(Slave,idx, 0x00, TRUE, &rdl, &ec_PDOdesc, EC_TIMEOUTRXM);
00722                 subidx = ec_PDOdesc.n;
00723         /* extract all bitlengths of SDO's */
00724                 for (subidxloop = 1; subidxloop <= subidx; subidxloop++)
00725                 {
00726                     bsize += LO_BYTE(etohl(ec_PDOdesc.PDO[subidxloop -1]));
00727                 };
00728             };
00729         };
00730     };
00731   /* return total found bitlength (PDO) */
00732     return bsize;
00733 }
00734 
00735 /** CoE read PDO mapping.
00736  *
00737  * CANopen has standard indexes defined for PDO mapping. This function
00738  * tries to read them and collect a full input and output mapping size
00739  * of designated slave.
00740  *
00741  * Principal structure in slave:\n
00742  * 1C00:00 is number of SM defined\n
00743  * 1C00:01 SM0 type -> 1C10\n
00744  * 1C00:02 SM1 type -> 1C11\n
00745  * 1C00:03 SM2 type -> 1C12\n
00746  * 1C00:04 SM4 type -> 1C13\n
00747  * Type 0 = unused, 1 = mailbox in, 2 = mailbox out,
00748  * 3 = outputs (RxPDO), 4 = inputs (TxPDO).
00749  *
00750  * 1C12:00 is number of PDO's defined for SM2\n
00751  * 1C12:01 PDO assign SDO #1 -> f.e. 1A00\n
00752  * 1C12:02 PDO assign SDO #2 -> f.e. 1A04\
00753  *
00754  * 1A00:00 is number of object defined for this PDO\n
00755  * 1A00:01 object mapping #1, f.e. 60100710 (SDO 6010 SI 07 bitlength 0x10)
00756  *
00757  * @param[in] Slave   = Slave number
00758  * @param[out] Osize  = Size in bits of output mapping (rxPDO) found
00759  * @param[out] Isize  = Size in bits of input mapping (txPDO) found
00760  * @return >0 if mapping succesful.
00761  */
00762 int ec_readPDOmap(uint16 Slave, int *Osize, int *Isize)
00763 {
00764   int wkc, rdl;
00765     int retVal = 0;
00766   uint8 nSM, iSM, tSM;
00767   int Tsize;
00768   uint8 SMt_bug_add;
00769   
00770   *Isize = 0;
00771   *Osize = 0;
00772   SMt_bug_add = 0;
00773     rdl = sizeof(nSM); nSM = 0;
00774   /* read SyncManager Communication Type object count */
00775     wkc = ec_SDOread(Slave, ECT_SDO_SMCOMMTYPE, 0x00, FALSE, &rdl, &nSM, EC_TIMEOUTRXM);
00776   /* positive result from slave ? */
00777     if ((wkc > 0) && (nSM > 2))
00778     {
00779     /* make nSM equal to number of defined SM */
00780     nSM--;
00781     /* limit to maximum number of SM defined, if true the slave can't be configured */
00782     if (nSM > EC_MAXSM)
00783       nSM = EC_MAXSM;
00784     /* iterate for every SM type defined */
00785     for (iSM = 2 ; iSM <= nSM ; iSM++)
00786     {
00787         rdl = sizeof(tSM); tSM = 0;
00788       /* read SyncManager Communication Type */
00789         wkc = ec_SDOread(Slave, ECT_SDO_SMCOMMTYPE, iSM + 1, FALSE, &rdl, &tSM, EC_TIMEOUTRXM);
00790       if (wkc > 0)
00791       {
00792 // start slave bug prevention code, remove if possible        
00793         if((iSM == 2) && (tSM == 2)) // SM2 has type 2 == mailbox out, this is a bug in the slave!
00794           SMt_bug_add = 1; // try to correct, this works if the types are 0 1 2 3 and should be 1 2 3 4
00795         if(tSM)
00796           tSM += SMt_bug_add; // only add if SMt > 0
00797 // end slave bug prevention code        
00798         
00799         ec_slave[Slave].SMtype[iSM] = tSM;
00800         /* check if SM is unused -> clear enable flag */
00801         if (tSM == 0)
00802           ec_slave[Slave].SM[iSM].SMflags = htoel( etohl(ec_slave[Slave].SM[iSM].SMflags) & EC_SMENABLEMASK);
00803         if ((tSM == 3) || (tSM == 4))
00804         {
00805           /* read the assign PDO */
00806           Tsize = ec_readPDOassign(Slave, ECT_SDO_PDOASSIGN + iSM );
00807           /* if a mapping is found */
00808           if (Tsize)
00809           {
00810             ec_slave[Slave].SM[iSM].SMlength = htoes((Tsize + 7) / 8);
00811             if (tSM == 3)
00812               /* we are doing outputs */
00813               *Osize += Tsize;
00814             else
00815               /* we are doing inputs */
00816               *Isize += Tsize;
00817           } 
00818         } 
00819       } 
00820     }
00821   }
00822 
00823   /* found some I/O bits ? */
00824     if ((*Isize > 0) || (*Osize > 0))
00825         retVal = 1;
00826     return retVal;
00827 }
00828 
00829 /** CoE read PDO mapping in Complete Access mode (CA).
00830  *
00831  * CANopen has standard indexes defined for PDO mapping. This function
00832  * tries to read them and collect a full input and output mapping size
00833  * of designated slave. Slave has to support CA, otherwise use ec_readPDOmap().
00834  *
00835  * @param[in] Slave   = Slave number
00836  * @param[out] Osize  = Size in bits of output mapping (rxPDO) found
00837  * @param[out] Isize  = Size in bits of input mapping (txPDO) found
00838  * @return >0 if mapping succesful.
00839  */
00840 int ec_readPDOmapCA(uint16 Slave, int *Osize, int *Isize)
00841 {
00842   int wkc, rdl;
00843     int retVal = 0;
00844   uint8 nSM, iSM, tSM;
00845   int Tsize;
00846   uint8 SMt_bug_add;
00847   
00848   *Isize = 0;
00849   *Osize = 0;
00850   SMt_bug_add = 0;
00851     rdl = sizeof(ec_SMcommtype); 
00852   ec_SMcommtype.n = 0;
00853   /* read SyncManager Communication Type object count Complete Access*/
00854     wkc = ec_SDOread(Slave, ECT_SDO_SMCOMMTYPE, 0x00, TRUE, &rdl, &ec_SMcommtype, EC_TIMEOUTRXM);
00855   /* positive result from slave ? */
00856     if ((wkc > 0) && (ec_SMcommtype.n > 2))
00857     {
00858     /* make nSM equal to number of defined SM */
00859     nSM = ec_SMcommtype.n - 1;
00860     /* limit to maximum number of SM defined, if true the slave can't be configured */
00861     if (nSM > EC_MAXSM)
00862       nSM = EC_MAXSM;
00863     /* iterate for every SM type defined */
00864     for (iSM = 2 ; iSM <= nSM ; iSM++)
00865     {
00866         tSM = ec_SMcommtype.SMtype[iSM];
00867 
00868 // start slave bug prevention code, remove if possible        
00869       if((iSM == 2) && (tSM == 2)) // SM2 has type 2 == mailbox out, this is a bug in the slave!
00870         SMt_bug_add = 1; // try to correct, this works if the types are 0 1 2 3 and should be 1 2 3 4
00871       if(tSM)
00872         tSM += SMt_bug_add; // only add if SMt > 0
00873 // end slave bug prevention code
00874       
00875       ec_slave[Slave].SMtype[iSM] = tSM;
00876       /* check if SM is unused -> clear enable flag */
00877       if (tSM == 0)
00878         ec_slave[Slave].SM[iSM].SMflags = htoel( etohl(ec_slave[Slave].SM[iSM].SMflags) & EC_SMENABLEMASK);
00879       if ((tSM == 3) || (tSM == 4))
00880       {
00881         /* read the assign PDO */
00882         Tsize = ec_readPDOassignCA(Slave, ECT_SDO_PDOASSIGN + iSM );
00883         /* if a mapping is found */
00884         if (Tsize)
00885         {
00886           ec_slave[Slave].SM[iSM].SMlength = htoes((Tsize + 7) / 8);
00887           if (tSM == 3)
00888             /* we are doing outputs */
00889             *Osize += Tsize;
00890           else
00891             /* we are doing inputs */
00892             *Isize += Tsize;
00893         } 
00894       } 
00895     }
00896   }
00897 
00898   /* found some I/O bits ? */
00899     if ((*Isize > 0) || (*Osize > 0))
00900         retVal = 1;
00901     return retVal;
00902 }
00903 
00904 /** CoE read Object Description List. 
00905  *
00906  * @param[in] Slave   = Slave number.
00907  * @param[out] pODlist  = resulting Object Description list.
00908  * @return Workcounter of slave response.
00909  */
00910 int ec_readODlist(uint16 Slave, ec_ODlistt *pODlist)
00911 {
00912     ec_SDOservicet *SDOp, *aSDOp;
00913     ec_mbxbuft MbxIn, MbxOut;
00914   int wkc;
00915     uint16 x, n, i, sp, offset;
00916     boolean stop;
00917     uint8 cnt;
00918     boolean First;
00919 
00920     pODlist->Slave = Slave;
00921     pODlist->Entries = 0;
00922     ec_clearmbx(&MbxIn);
00923   /* clear pending out mailbox in slave if available. Timeout is set to 0 */
00924     wkc = ec_mbxreceive(Slave, &MbxIn, 0);
00925     ec_clearmbx(&MbxOut);
00926     aSDOp = (ec_SDOservicet*)&MbxIn;
00927     SDOp = (ec_SDOservicet*)&MbxOut;
00928     SDOp->MbxHeader.length = htoes(0x0008);
00929     SDOp->MbxHeader.address = htoes(0x0000);
00930     SDOp->MbxHeader.priority = 0x00;
00931   /* Get new mailbox counter value */
00932     cnt = ec_nextmbxcnt(ec_slave[Slave].mbx_cnt);
00933     ec_slave[Slave].mbx_cnt = cnt;
00934     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
00935     SDOp->CANOpen = htoes(0x000 + (ECT_COES_SDOINFO << 12)); /* number 9bits service upper 4 bits */
00936     SDOp->Opcode = ECT_GET_ODLIST_REQ; /* get object description list request */
00937     SDOp->Reserved = 0;
00938     SDOp->Fragments = 0; /* fragments left */
00939     SDOp->wdata[0] = htoes(0x01); /* all objects */
00940   /* send get object description list request to slave */
00941     wkc = ec_mbxsend(Slave, &MbxOut, EC_TIMEOUTTXM);
00942   /* mailbox placed in slave ? */
00943     if (wkc > 0)
00944     {
00945         x = 0; 
00946         sp = 0;
00947         First = TRUE;
00948         offset = 1; /* offset to skip info header in first frame, otherwise set to 0 */
00949         do
00950         {
00951             stop = TRUE; /* assume this is last iteration */
00952             ec_clearmbx(&MbxIn);
00953       /* read slave response */
00954             wkc = ec_mbxreceive(Slave, &MbxIn, EC_TIMEOUTRXM);
00955       /* got response ? */
00956             if (wkc > 0)
00957             {
00958         /* response should be CoE and "get object description list response" */
00959                 if (((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) &&
00960                     ((aSDOp->Opcode & 0x7f) == ECT_GET_ODLIST_RES))
00961                 {
00962                     if (First)
00963             /* extract number of indexes from mailbox data size */
00964                         n = (etohs(aSDOp->MbxHeader.length) - (6 + 2)) / 2;
00965                     else
00966             /* extract number of indexes from mailbox data size */
00967                         n = (etohs(aSDOp->MbxHeader.length) - 6) / 2;
00968           /* check if indexes fit in buffer structure */
00969                     if ((sp + n) > EC_MAXODLIST)
00970                     {
00971                         n = EC_MAXODLIST + 1 - sp;
00972                         ec_SDOinfoerror(Slave, 0, 0, 0xf000000); /* Too many entries for master buffer */
00973                         stop = TRUE;
00974                     }
00975           /* trim to maximum number of ODlist entries defined */
00976                     if ((pODlist->Entries + n) > EC_MAXODLIST)
00977                         n = EC_MAXODLIST - pODlist->Entries;
00978                     pODlist->Entries += n;
00979           /* extract indexes one by one */
00980                     for (i = 0; i < n; i++)
00981                         pODlist->Index[sp + i] = etohs(aSDOp->wdata[i + offset]);
00982                     sp += n;
00983           /* check if more fragments will follow */
00984                     if (aSDOp->Fragments > 0)
00985                         stop = FALSE;
00986                     First = FALSE; 
00987                     offset = 0;
00988                 }
00989         /* got unexpected response from slave */
00990                 else
00991                 {
00992                     if ((aSDOp->Opcode &  0x7f) == ECT_SDOINFO_ERROR) /* SDO info error received */
00993                     {
00994                         ec_SDOinfoerror(Slave, 0, 0, etohl(aSDOp->ldata[0]));
00995                         stop = TRUE;
00996                     }
00997                     else
00998                         ec_packeterror(Slave, 0, 0, 1); /* Unexpected frame returned */
00999                     wkc = 0; 
01000                     x += 20;
01001                 }
01002             }
01003             x++;
01004         }
01005         while ((x <= 128) && !stop);
01006     }
01007     return wkc;
01008 }
01009 
01010 /** CoE read Object Description. Adds textual description to object indexes.
01011  *
01012  * @param[in] Item      = Item number in ODlist.
01013  * @param[in,out] pODlist   = referencing Object Description list.
01014  * @return Workcounter of slave response.
01015  */
01016 int ec_readODdescription(uint16 Item, ec_ODlistt *pODlist)
01017 {
01018     ec_SDOservicet *SDOp, *aSDOp;
01019   int wkc;
01020     uint16  n, Slave;
01021     ec_mbxbuft MbxIn, MbxOut;
01022     uint8 cnt;
01023 
01024     Slave = pODlist->Slave;
01025     pODlist->DataType[Item] = 0;
01026     pODlist->ObjectCode[Item] = 0;
01027     pODlist->MaxSub[Item] = 0;
01028     pODlist->Name[Item][0] = 0;
01029     ec_clearmbx(&MbxIn);
01030   /* clear pending out mailbox in slave if available. Timeout is set to 0 */
01031     wkc = ec_mbxreceive(Slave, &MbxIn, 0);
01032     ec_clearmbx(&MbxOut);
01033     aSDOp = (ec_SDOservicet*)&MbxIn;
01034     SDOp = (ec_SDOservicet*)&MbxOut;
01035     SDOp->MbxHeader.length = htoes(0x0008);
01036     SDOp->MbxHeader.address = htoes(0x0000);
01037     SDOp->MbxHeader.priority = 0x00;
01038   /* Get new mailbox counter value */
01039     cnt = ec_nextmbxcnt(ec_slave[Slave].mbx_cnt);
01040     ec_slave[Slave].mbx_cnt = cnt;
01041     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
01042     SDOp->CANOpen = htoes(0x000 + (ECT_COES_SDOINFO << 12)); /* number 9bits service upper 4 bits */
01043     SDOp->Opcode = ECT_GET_OD_REQ; /* get object description request */
01044     SDOp->Reserved = 0;
01045     SDOp->Fragments = 0; /* fragments left */
01046     SDOp->wdata[0] = htoes(pODlist->Index[Item]); /* Data of Index */
01047   /* send get object description request to slave */
01048     wkc = ec_mbxsend(Slave, &MbxOut, EC_TIMEOUTTXM);
01049   /* mailbox placed in slave ? */
01050     if (wkc > 0)
01051     {
01052         ec_clearmbx(&MbxIn);
01053     /* read slave response */
01054         wkc = ec_mbxreceive(Slave, &MbxIn, EC_TIMEOUTRXM);
01055     /* got response ? */
01056         if (wkc > 0)
01057         {
01058             if (((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) &&
01059                 ((aSDOp->Opcode & 0x7f) == ECT_GET_OD_RES))
01060             {
01061                 n = (etohs(aSDOp->MbxHeader.length) - 12); /* length of string(name of object) */
01062                 if (n > EC_MAXNAME)
01063                     n = EC_MAXNAME; /* max chars */
01064                 pODlist->DataType[Item] = etohs(aSDOp->wdata[1]);
01065                 pODlist->ObjectCode[Item] = aSDOp->bdata[5];
01066                 pODlist->MaxSub[Item] = aSDOp->bdata[4];
01067 
01068                 strncpy(pODlist->Name[Item] , (char *)&aSDOp->bdata[6], n);
01069         pODlist->Name[Item][n] = 0x00; /* String terminator */
01070             }
01071       /* got unexpected response from slave */
01072             else
01073             {
01074                 if (((aSDOp->Opcode & 0x7f) == ECT_SDOINFO_ERROR)) /* SDO info error received */
01075                     ec_SDOinfoerror(Slave,pODlist->Index[Item], 0, etohl(aSDOp->ldata[0]));
01076                 else
01077                     ec_packeterror(Slave,pODlist->Index[Item], 0, 1); /* Unexpected frame returned */
01078                 wkc = 0;
01079             }
01080         }
01081     }
01082     return wkc;
01083 }
01084 
01085 /** CoE read SDO service object entry, single subindex.
01086  * Used in ec_readOE().
01087  *
01088  * @param[in] Item      = Item in ODlist.
01089  * @param[in] SubI      = Subindex of item in ODlist.
01090  * @param[in] pODlist   = Object description list for reference.
01091  * @param[out] pOElist    = resulting object entry structure.
01092  * @return Workcounter of slave response.
01093  */
01094 static int ec_readOEsingle(uint16 Item, uint8 SubI, ec_ODlistt *pODlist, ec_OElistt *pOElist)
01095 {
01096     ec_SDOservicet *SDOp, *aSDOp;
01097     uint16 wkc, Index, Slave;
01098     int16 n;
01099     ec_mbxbuft MbxIn, MbxOut;
01100     uint8 cnt;
01101 
01102     wkc = 0;
01103     Slave = pODlist->Slave;
01104     Index = pODlist->Index[Item];
01105     ec_clearmbx(&MbxIn);
01106   /* clear pending out mailbox in slave if available. Timeout is set to 0 */
01107     wkc = ec_mbxreceive(Slave, &MbxIn, 0);
01108     ec_clearmbx(&MbxOut);
01109     aSDOp = (ec_SDOservicet*)&MbxIn;
01110     SDOp = (ec_SDOservicet*)&MbxOut;
01111     SDOp->MbxHeader.length = htoes(0x000a);
01112     SDOp->MbxHeader.address = htoes(0x0000);
01113     SDOp->MbxHeader.priority = 0x00;
01114   /* Get new mailbox counter value */
01115     cnt = ec_nextmbxcnt(ec_slave[Slave].mbx_cnt);
01116     ec_slave[Slave].mbx_cnt = cnt;
01117     SDOp->MbxHeader.mbxtype = ECT_MBXT_COE + (cnt << 4); /* CoE */
01118     SDOp->CANOpen = htoes(0x000 + (ECT_COES_SDOINFO << 12)); /* number 9bits service upper 4 bits */
01119     SDOp->Opcode = ECT_GET_OE_REQ; /* get object entry description request */
01120     SDOp->Reserved = 0;
01121     SDOp->Fragments = 0;    /* fragments left */
01122     SDOp->wdata[0] = htoes(Index);    /* Index */
01123     SDOp->bdata[2] = SubI;    /* SubIndex */
01124     SDOp->bdata[3] = 1 + 2 + 4; /* get access rights, object category, PDO */
01125   /* send get object entry description request to slave */
01126     wkc = ec_mbxsend(Slave, &MbxOut, EC_TIMEOUTTXM);
01127   /* mailbox placed in slave ? */
01128     if (wkc > 0)
01129     {
01130         ec_clearmbx(&MbxIn);
01131     /* read slave response */
01132         wkc = ec_mbxreceive(Slave, &MbxIn, EC_TIMEOUTRXM);
01133     /* got response ? */
01134         if (wkc > 0)
01135         {
01136             if (((aSDOp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_COE) &&
01137                 ((aSDOp->Opcode &  0x7f) == ECT_GET_OE_RES))
01138             {
01139                 pOElist->Entries++;
01140                 n = (etohs(aSDOp->MbxHeader.length) - 16); /* length of string(name of object) */
01141                 if (n > EC_MAXNAME)
01142                     n = EC_MAXNAME; /* max string length */
01143                 if (n < 0 )
01144                     n = 0;
01145                 pOElist->ValueInfo[SubI] = aSDOp->bdata[3];
01146                 pOElist->DataType[SubI] = etohs(aSDOp->wdata[2]);
01147                 pOElist->BitLength[SubI] = etohs(aSDOp->wdata[3]);
01148                 pOElist->ObjAccess[SubI] = etohs(aSDOp->wdata[4]);
01149 
01150                 strncpy(pOElist->Name[SubI] , (char *)&aSDOp->wdata[5], n);
01151         pOElist->Name[SubI][n] = 0x00; /* string terminator */
01152             }
01153       /* got unexpected response from slave */
01154             else
01155             {
01156                 if (((aSDOp->Opcode & 0x7f) == ECT_SDOINFO_ERROR)) /* SDO info error received */
01157                     ec_SDOinfoerror(Slave, Index, SubI, etohl(aSDOp->ldata[0]));
01158                 else
01159                     ec_packeterror(Slave, Index, SubI, 1); /* Unexpected frame returned */
01160                 wkc = 0;
01161             }
01162         }
01163     }
01164     return wkc;
01165 }
01166 
01167 /** CoE read SDO service object entry.
01168  *
01169  * @param[in] Item      = Item in ODlist.
01170  * @param[in] pODlist   = Object description list for reference.
01171  * @param[out] pOElist    = resulting object entry structure.
01172  * @return Workcounter of slave response.
01173  */
01174 int ec_readOE(uint16 Item, ec_ODlistt *pODlist, ec_OElistt *pOElist)
01175 {
01176     uint16 SubCount;
01177   int wkc;
01178     uint8 SubI;
01179 
01180     wkc = 0;
01181     pOElist->Entries = 0;
01182     SubI = pODlist->MaxSub[Item];
01183   /* for each entry found in ODlist */
01184     for (SubCount = 0; SubCount <= (SubI); SubCount++)
01185     /* read subindex of entry */
01186         wkc = ec_readOEsingle(Item, (uint8)SubCount, pODlist, pOElist);
01187     return wkc;
01188 }
Generated by  doxygen 1.6.3