ethercatsoe.c
Go to the documentation of this file.
1 /*
2  * Licensed under the GNU General Public License version 2 with exceptions. See
3  * LICENSE file in the project root for full license information
4  */
5 
11 #include <stdio.h>
12 #include <string.h>
13 #include "osal.h"
14 #include "oshw.h"
15 #include "ethercattype.h"
16 #include "ethercatbase.h"
17 #include "ethercatmain.h"
18 #include "ethercatsoe.h"
19 
20 #define EC_SOE_MAX_DRIVES 8
21 
24 typedef struct PACKED
25 {
32  union
33  {
36  };
37 } ec_SoEt;
39 
47 void ecx_SoEerror(ecx_contextt *context, uint16 Slave, uint16 idn, uint16 Error)
48 {
49  ec_errort Ec;
50 
51  memset(&Ec, 0, sizeof(Ec));
52  Ec.Time = osal_current_time();
53  Ec.Slave = Slave;
54  Ec.Index = idn;
55  Ec.SubIdx = 0;
56  *(context->ecaterror) = TRUE;
58  Ec.ErrorCode = Error;
59  ecx_pusherror(context, &Ec);
60 }
61 
78 int ecx_SoEread(ecx_contextt *context, uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout)
79 {
80  ec_SoEt *SoEp, *aSoEp;
81  uint16 totalsize, framedatasize;
82  int wkc;
83  uint8 *bp;
84  uint8 *mp;
85  uint16 *errorcode;
86  ec_mbxbuft MbxIn, MbxOut;
87  uint8 cnt;
88  boolean NotLast;
89 
90  ec_clearmbx(&MbxIn);
91  /* Empty slave out mailbox if something is in. Timeout set to 0 */
92  wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0);
93  ec_clearmbx(&MbxOut);
94  aSoEp = (ec_SoEt *)&MbxIn;
95  SoEp = (ec_SoEt *)&MbxOut;
96  SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert));
97  SoEp->MbxHeader.address = htoes(0x0000);
98  SoEp->MbxHeader.priority = 0x00;
99  /* get new mailbox count value, used as session handle */
100  cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
101  context->slavelist[slave].mbx_cnt = cnt;
102  SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */
103  SoEp->opCode = ECT_SOE_READREQ;
104  SoEp->incomplete = 0;
105  SoEp->error = 0;
106  SoEp->driveNo = driveNo;
107  SoEp->elementflags = elementflags;
108  SoEp->idn = htoes(idn);
109  totalsize = 0;
110  bp = p;
111  mp = (uint8 *)&MbxIn + sizeof(ec_SoEt);
112  NotLast = TRUE;
113  /* send SoE request to slave */
114  wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
115  if (wkc > 0) /* succeeded to place mailbox in slave ? */
116  {
117  while (NotLast)
118  {
119  /* clean mailboxbuffer */
120  ec_clearmbx(&MbxIn);
121  /* read slave response */
122  wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout);
123  if (wkc > 0) /* succeeded to read slave response ? */
124  {
125  /* slave response should be SoE, ReadRes */
126  if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) &&
127  (aSoEp->opCode == ECT_SOE_READRES) &&
128  (aSoEp->error == 0) &&
129  (aSoEp->driveNo == driveNo) &&
130  (aSoEp->elementflags == elementflags))
131  {
132  framedatasize = etohs(aSoEp->MbxHeader.length) - sizeof(ec_SoEt) + sizeof(ec_mbxheadert);
133  totalsize += framedatasize;
134  /* Does parameter fit in parameter buffer ? */
135  if (totalsize <= *psize)
136  {
137  /* copy parameter data in parameter buffer */
138  memcpy(bp, mp, framedatasize);
139  /* increment buffer pointer */
140  bp += framedatasize;
141  }
142  else
143  {
144  framedatasize -= totalsize - *psize;
145  totalsize = *psize;
146  /* copy parameter data in parameter buffer */
147  if (framedatasize > 0) memcpy(bp, mp, framedatasize);
148  }
149 
150  if (!aSoEp->incomplete)
151  {
152  NotLast = FALSE;
153  *psize = totalsize;
154  }
155  }
156  /* other slave response */
157  else
158  {
159  NotLast = FALSE;
160  if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) &&
161  (aSoEp->opCode == ECT_SOE_READRES) &&
162  (aSoEp->error == 1))
163  {
164  mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16));
165  errorcode = (uint16 *)mp;
166  ecx_SoEerror(context, slave, idn, *errorcode);
167  }
168  else
169  {
170  ecx_packeterror(context, slave, idn, 0, 1); /* Unexpected frame returned */
171  }
172  wkc = 0;
173  }
174  }
175  else
176  {
177  NotLast = FALSE;
178  ecx_packeterror(context, slave, idn, 0, 4); /* no response */
179  }
180  }
181  }
182  return wkc;
183 }
184 
200 int ecx_SoEwrite(ecx_contextt *context, uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout)
201 {
202  ec_SoEt *SoEp, *aSoEp;
203  uint16 framedatasize, maxdata;
204  int wkc;
205  uint8 *mp;
206  uint8 *hp;
207  uint16 *errorcode;
208  ec_mbxbuft MbxIn, MbxOut;
209  uint8 cnt;
210  boolean NotLast;
211 
212  ec_clearmbx(&MbxIn);
213  /* Empty slave out mailbox if something is in. Timeout set to 0 */
214  wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0);
215  ec_clearmbx(&MbxOut);
216  aSoEp = (ec_SoEt *)&MbxIn;
217  SoEp = (ec_SoEt *)&MbxOut;
218  SoEp->MbxHeader.address = htoes(0x0000);
219  SoEp->MbxHeader.priority = 0x00;
220  SoEp->opCode = ECT_SOE_WRITEREQ;
221  SoEp->error = 0;
222  SoEp->driveNo = driveNo;
223  SoEp->elementflags = elementflags;
224  hp = p;
225  mp = (uint8 *)&MbxOut + sizeof(ec_SoEt);
226  maxdata = context->slavelist[slave].mbx_l - sizeof(ec_SoEt);
227  NotLast = TRUE;
228  while (NotLast)
229  {
230  framedatasize = psize;
231  NotLast = FALSE;
232  SoEp->idn = htoes(idn);
233  SoEp->incomplete = 0;
234  if (framedatasize > maxdata)
235  {
236  framedatasize = maxdata; /* segmented transfer needed */
237  NotLast = TRUE;
238  SoEp->incomplete = 1;
239  SoEp->fragmentsleft = psize / maxdata;
240  }
241  SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert) + framedatasize);
242  /* get new mailbox counter, used for session handle */
243  cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
244  context->slavelist[slave].mbx_cnt = cnt;
245  SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */
246  /* copy parameter data to mailbox */
247  memcpy(mp, hp, framedatasize);
248  hp += framedatasize;
249  psize -= framedatasize;
250  /* send SoE request to slave */
251  wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
252  if (wkc > 0) /* succeeded to place mailbox in slave ? */
253  {
254  if (!NotLast || !ecx_mbxempty(context, slave, timeout))
255  {
256  /* clean mailboxbuffer */
257  ec_clearmbx(&MbxIn);
258  /* read slave response */
259  wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout);
260  if (wkc > 0) /* succeeded to read slave response ? */
261  {
262  NotLast = FALSE;
263  /* slave response should be SoE, WriteRes */
264  if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) &&
265  (aSoEp->opCode == ECT_SOE_WRITERES) &&
266  (aSoEp->error == 0) &&
267  (aSoEp->driveNo == driveNo) &&
268  (aSoEp->elementflags == elementflags))
269  {
270  /* SoE write succeeded */
271  }
272  /* other slave response */
273  else
274  {
275  if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) &&
276  (aSoEp->opCode == ECT_SOE_READRES) &&
277  (aSoEp->error == 1))
278  {
279  mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16));
280  errorcode = (uint16 *)mp;
281  ecx_SoEerror(context, slave, idn, *errorcode);
282  }
283  else
284  {
285  ecx_packeterror(context, slave, idn, 0, 1); /* Unexpected frame returned */
286  }
287  wkc = 0;
288  }
289  }
290  else
291  {
292  ecx_packeterror(context, slave, idn, 0, 4); /* no response */
293  }
294  }
295  }
296  }
297  return wkc;
298 }
299 
312 int ecx_readIDNmap(ecx_contextt *context, uint16 slave, int *Osize, int *Isize)
313 {
314  int retVal = 0;
315  int wkc;
316  int psize;
317  int driveNr;
318  uint16 entries, itemcount;
319  ec_SoEmappingt SoEmapping;
320  ec_SoEattributet SoEattribute;
321 
322  *Isize = 0;
323  *Osize = 0;
324  for(driveNr = 0; driveNr < EC_SOE_MAX_DRIVES; driveNr++)
325  {
326  psize = sizeof(SoEmapping);
327  /* read output mapping via SoE */
328  wkc = ecx_SoEread(context, slave, driveNr, EC_SOE_VALUE_B, EC_IDN_MDTCONFIG, &psize, &SoEmapping, EC_TIMEOUTRXM);
329  if ((wkc > 0) && (psize >= 4) && ((entries = etohs(SoEmapping.currentlength) / 2) > 0) && (entries <= EC_SOE_MAXMAPPING))
330  {
331  /* command word (uint16) is always mapped but not in list */
332  *Osize = 16;
333  for (itemcount = 0 ; itemcount < entries ; itemcount++)
334  {
335  psize = sizeof(SoEattribute);
336  /* read attribute of each IDN in mapping list */
337  wkc = ecx_SoEread(context, slave, driveNr, EC_SOE_ATTRIBUTE_B, SoEmapping.idn[itemcount], &psize, &SoEattribute, EC_TIMEOUTRXM);
338  if ((wkc > 0) && (!SoEattribute.list))
339  {
340  /* length : 0 = 8bit, 1 = 16bit .... */
341  *Osize += (int)8 << SoEattribute.length;
342  }
343  }
344  }
345  psize = sizeof(SoEmapping);
346  /* read input mapping via SoE */
347  wkc = ecx_SoEread(context, slave, driveNr, EC_SOE_VALUE_B, EC_IDN_ATCONFIG, &psize, &SoEmapping, EC_TIMEOUTRXM);
348  if ((wkc > 0) && (psize >= 4) && ((entries = etohs(SoEmapping.currentlength) / 2) > 0) && (entries <= EC_SOE_MAXMAPPING))
349  {
350  /* status word (uint16) is always mapped but not in list */
351  *Isize = 16;
352  for (itemcount = 0 ; itemcount < entries ; itemcount++)
353  {
354  psize = sizeof(SoEattribute);
355  /* read attribute of each IDN in mapping list */
356  wkc = ecx_SoEread(context, slave, driveNr, EC_SOE_ATTRIBUTE_B, SoEmapping.idn[itemcount], &psize, &SoEattribute, EC_TIMEOUTRXM);
357  if ((wkc > 0) && (!SoEattribute.list))
358  {
359  /* length : 0 = 8bit, 1 = 16bit .... */
360  *Isize += (int)8 << SoEattribute.length;
361  }
362  }
363  }
364  }
365 
366  /* found some I/O bits ? */
367  if ((*Isize > 0) || (*Osize > 0))
368  {
369  retVal = 1;
370  }
371  return retVal;
372 }
373 
374 #ifdef EC_VER1
375 int ec_SoEread(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout)
376 {
377  return ecx_SoEread(&ecx_context, slave, driveNo, elementflags, idn, psize, p, timeout);
378 }
379 
380 int ec_SoEwrite(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout)
381 {
382  return ecx_SoEwrite(&ecx_context, slave, driveNo, elementflags, idn, psize, p, timeout);
383 }
384 
385 int ec_readIDNmap(uint16 slave, int *Osize, int *Isize)
386 {
387  return ecx_readIDNmap(&ecx_context, slave, Osize, Isize);
388 }
389 #endif
wkc
int wkc
Definition: aliastool.c:47
slave
int slave
Definition: aliastool.c:44
ec_slave::mbx_cnt
uint8 mbx_cnt
Definition: ethercatmain.h:167
ec_SoEattributet
PACKED_BEGIN struct PACKED ec_SoEattributet
ECT_SOE_READRES
@ ECT_SOE_READRES
Definition: ethercattype.h:383
etohs
#define etohs(A)
Definition: ethercattype.h:536
ecx_context::ecaterror
boolean * ecaterror
Definition: ethercatmain.h:409
EC_SOE_MAX_DRIVES
#define EC_SOE_MAX_DRIVES
Definition: ethercatsoe.c:20
ec_mbxbuft
uint8 ec_mbxbuft[EC_MAXMBX+1]
Definition: ethercatmain.h:312
ECT_SOE_WRITEREQ
@ ECT_SOE_WRITEREQ
Definition: ethercattype.h:384
ethercatmain.h
Headerfile for ethercatmain.c.
osal_current_time
ec_timet osal_current_time(void)
Definition: erika/osal.c:37
ec_SoEread
int ec_SoEread(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout)
Definition: ethercatsoe.c:375
EC_TIMEOUTRXM
#define EC_TIMEOUTRXM
Definition: ethercattype.h:74
ec_SoEt
PACKED_BEGIN struct PACKED ec_SoEt
EC_ERR_TYPE_SOE_ERROR
@ EC_ERR_TYPE_SOE_ERROR
Definition: ethercattype.h:471
PACKED::incomplete
uint8 incomplete
Definition: ethercatsoe.c:28
EC_SOE_VALUE_B
#define EC_SOE_VALUE_B
Definition: ethercatsoe.h:25
ec_errort::SubIdx
uint8 SubIdx
Definition: ethercattype.h:489
EC_SOE_MAXMAPPING
#define EC_SOE_MAXMAPPING
Definition: ethercatsoe.h:29
ec_mbxheadert
PACKED_BEGIN struct PACKED ec_mbxheader ec_mbxheadert
ecx_SoEerror
PACKED_END void ecx_SoEerror(ecx_contextt *context, uint16 Slave, uint16 idn, uint16 Error)
Definition: ethercatsoe.c:47
uint8
uint8_t uint8
Definition: osal.h:28
ec_errort::Etype
ec_err_type Etype
Definition: ethercattype.h:491
ethercatbase.h
Headerfile for ethercatbase.c.
PACKED_END
#define PACKED_END
Definition: erika/osal_defs.h:30
ec_clearmbx
void ec_clearmbx(ec_mbxbuft *Mbx)
Definition: ethercatmain.c:921
PACKED_BEGIN
#define PACKED_BEGIN
Definition: erika/osal_defs.h:28
PACKED::elementflags
uint8 elementflags
Definition: ethercatsoe.c:31
ecx_SoEread
int ecx_SoEread(ecx_contextt *context, uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout)
Definition: ethercatsoe.c:78
PACKED
Definition: ethercatcoe.c:24
osal.h
EC_IDN_ATCONFIG
#define EC_IDN_ATCONFIG
Definition: ethercatsoe.h:32
PACKED::driveNo
uint8 driveNo
Definition: ethercatsoe.c:30
ecx_mbxsend
int ecx_mbxsend(ecx_contextt *context, uint16 slave, ec_mbxbuft *mbx, int timeout)
Definition: ethercatmain.c:968
PACKED::idn
uint16 idn
Definition: ethercatsoe.c:34
ec_errort::Slave
uint16 Slave
Definition: ethercattype.h:485
htoes
#define htoes(A)
Definition: ethercattype.h:533
PACKED::error
uint8 error
Definition: ethercatsoe.c:29
PACKED::fragmentsleft
uint16 fragmentsleft
Definition: ethercatsoe.c:35
EC_TIMEOUTTXM
#define EC_TIMEOUTTXM
Definition: ethercattype.h:72
ec_errort
Definition: ethercattype.h:478
uint16
uint16_t uint16
Definition: osal.h:29
ECT_MBXT_SOE
@ ECT_MBXT_SOE
Definition: ethercattype.h:326
ec_errort::ErrorCode
uint16 ErrorCode
Definition: ethercattype.h:499
ecx_mbxreceive
int ecx_mbxreceive(ecx_contextt *context, uint16 slave, ec_mbxbuft *mbx, int timeout)
Definition: ethercatmain.c:1001
ec_errort::Time
ec_timet Time
Definition: ethercattype.h:481
TRUE
#define TRUE
Definition: osal.h:19
ecx_context::slavelist
ec_slavet * slavelist
Definition: ethercatmain.h:389
ECT_SOE_READREQ
@ ECT_SOE_READREQ
Definition: ethercattype.h:382
ecx_mbxempty
int ecx_mbxempty(ecx_contextt *context, uint16 slave, int timeout)
Definition: ethercatmain.c:932
ec_errort::Index
uint16 Index
Definition: ethercattype.h:487
ECT_SOE_WRITERES
@ ECT_SOE_WRITERES
Definition: ethercattype.h:385
FALSE
#define FALSE
Definition: osal.h:22
ecx_context
Definition: ethercatmain.h:384
ethercatsoe.h
Headerfile for ethercatsoe.c.
ecx_readIDNmap
int ecx_readIDNmap(ecx_contextt *context, uint16 slave, int *Osize, int *Isize)
Definition: ethercatsoe.c:312
ecx_SoEwrite
int ecx_SoEwrite(ecx_contextt *context, uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout)
Definition: ethercatsoe.c:200
ecx_pusherror
void ecx_pusherror(ecx_contextt *context, const ec_errort *Ec)
Definition: ethercatmain.c:154
ec_SoEwrite
int ec_SoEwrite(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout)
Definition: ethercatsoe.c:380
PACKED::opCode
uint8 opCode
Definition: ethercatsoe.c:27
ec_SoEmappingt
PACKED_END PACKED_BEGIN struct PACKED ec_SoEmappingt
ec_nextmbxcnt
uint8 ec_nextmbxcnt(uint8 cnt)
Definition: ethercatmain.c:907
ethercattype.h
General typedefs and defines for EtherCAT.
ec_readIDNmap
int ec_readIDNmap(uint16 slave, int *Osize, int *Isize)
Definition: ethercatsoe.c:385
ec_slave::mbx_l
uint16 mbx_l
Definition: ethercatmain.h:157
EC_SOE_ATTRIBUTE_B
#define EC_SOE_ATTRIBUTE_B
Definition: ethercatsoe.h:21
ecx_packeterror
void ecx_packeterror(ecx_contextt *context, uint16 Slave, uint16 Index, uint8 SubIdx, uint16 ErrorCode)
Definition: ethercatmain.c:219
EC_IDN_MDTCONFIG
#define EC_IDN_MDTCONFIG
Definition: ethercatsoe.h:31
PACKED::MbxHeader
ec_mbxheadert MbxHeader
Definition: ethercatcoe.c:26


soem
Author(s): Arthur Ketels and M.J.G. van den Molengraft
autogenerated on Wed Mar 2 2022 01:01:49