forked from OpenEtherCATsociety/SOEM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathec_master.c
362 lines (328 loc) · 13.8 KB
/
ec_master.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
/*****************************************************************************
*
* FILE NAME: ec_master.c
*
* DESCRIPTION: This is the main program module.
*
\*****************************************************************************/
#include <stdio.h>
/*****************************************************************************
*
* FUNCTION: main
*
* DESCRIPTION:
* This is the main program module.
*
\*****************************************************************************/
/** \file
* \brief Example code for Simple Open EtherCAT master
*
* Usage : slaveinfo [ifname] [-sdo] [-map]
* Ifname is NIC interface, f.e. eth0.
* Optional -sdo to display CoE object dictionary.
* Optional -map to display slave PDO mapping
*
* This shows the configured slave data.
*
* (c)Arthur Ketels 2010 - 2011
*/
#include <stdio.h>
#include <string.h>
#include <rt.h>
#include <traceapi.h>
#include "ethercat.h"
char IOmap[4096];
char IOmap2[4096];
/** Main slave data array.
* Each slave found on the network gets its own record.
* ec_slave[0] is reserved for the master. Structure gets filled
* in by the configuration function ec_config().
*/
ec_slavet ec_slave[EC_MAXSLAVE];
ec_slavet ec_slave2[EC_MAXSLAVE];
/** number of slaves found on the network */
int ec_slavecount;
int ec_slavecount2;
/** slave group structure */
ec_groupt ec_groups[EC_MAXGROUP];
ec_groupt ec_groups2[EC_MAXGROUP];
/** cache for EEPROM read functions */
static uint8 esibuf[EC_MAXEEPBUF];
static uint8 esibuf2[EC_MAXEEPBUF];
/** bitmap for filled cache buffer bytes */
static uint32 esimap[EC_MAXEEPBITMAP];
static uint32 esimap2[EC_MAXEEPBITMAP];
/** current slave for EEPROM cache buffer */
static ec_eringt ec_elist;
static ec_eringt ec_elist2;
static ec_idxstackT ec_idxstack;
static ec_idxstackT ec_idxstack2;
/** SyncManager Communication Type struct to store data of one slave */
static ec_SMcommtypet ec_SMcommtype;
static ec_SMcommtypet ec_SMcommtype2;
/** PDO assign struct to store data of one slave */
static ec_PDOassignt ec_PDOassign;
static ec_PDOassignt ec_PDOassign2;
/** PDO description struct to store data of one slave */
static ec_PDOdesct ec_PDOdesc;
static ec_PDOdesct ec_PDOdesc2;
/** buffer for EEPROM SM data */
static ec_eepromSMt ec_SM;
static ec_eepromSMt ec_SM2;
/** buffer for EEPROM FMMU data */
static ec_eepromFMMUt ec_FMMU;
static ec_eepromFMMUt ec_FMMU2;
/** Global variable TRUE if error available in error stack */
static boolean EcatError = FALSE;
static boolean EcatError2 = FALSE;
int64 ec_DCtime;
int64 ec_DCtime2;
static ecx_portt ecx_port;
static ecx_portt ecx_port2;
static ecx_contextt ctx [] = {
{
&ecx_port,
&ec_slave[0],
&ec_slavecount,
EC_MAXSLAVE,
&ec_groups[0],
EC_MAXGROUP,
&esibuf[0],
&esimap[0],
0,
&ec_elist,
&ec_idxstack,
&EcatError,
0,
0,
&ec_DCtime,
&ec_SMcommtype,
&ec_PDOassign,
&ec_PDOdesc,
&ec_SM,
&ec_FMMU
},
{
&ecx_port2,
&ec_slave2[0],
&ec_slavecount2,
EC_MAXSLAVE,
&ec_groups2[0],
EC_MAXGROUP,
&esibuf2[0],
&esimap2[0],
0,
&ec_elist2,
&ec_idxstack2,
&EcatError2,
0,
0,
&ec_DCtime2,
&ec_SMcommtype2,
&ec_PDOassign2,
&ec_PDOdesc2,
&ec_SM2,
&ec_FMMU2
}
};
void slaveinfo(char *ifname)
{
int cnt, i, j, nSM;
int ctx_count;
uint16 ssigen;
int expectedWKC[2];
int wkc_count;
int chk;
volatile int wkc[2];
boolean inOP;
printf("Starting slaveinfo\n");
/* initialise SOEM, bind socket to ifname */
if (ecx_init(&ctx[0],"ie1g1") && ecx_init(&ctx[1],"ie1g0"))
{
printf("ec_init on %s succeeded.\n",ifname);
/* find and auto-config slaves */
if ( ecx_config_init(&ctx[0],FALSE) > 0 && ecx_config_init(&ctx[1],FALSE) > 0 )
{
for (ctx_count = 0; ctx_count < 2; ctx_count++)
{
ecx_config_map_group(&ctx[ctx_count], IOmap, 0);
ecx_configdc(&ctx[ctx_count]);
while(*(ctx[ctx_count].ecaterror)) printf("%s", ecx_elist2string(&ctx[ctx_count]));
printf("%d slaves found and configured.\n",*(ctx[ctx_count].slavecount));
expectedWKC[ctx_count] = ( ctx[ctx_count].grouplist[0].outputsWKC * 2) + ctx[ctx_count].grouplist[0].inputsWKC;
printf("Calculated workcounter %d\n", expectedWKC[ctx_count]);
/* wait for all slaves to reach SAFE_OP state */
ecx_statecheck(&ctx[ctx_count],0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 3);
if (ctx[ctx_count].slavelist[ctx_count].state != EC_STATE_SAFE_OP )
{
printf("Not all slaves reached safe operational state.\n");
ecx_readstate(&ctx[ctx_count]);
for(i = 1; i <= *(ctx[ctx_count].slavecount) ; i++)
{
if(ctx[ctx_count].slavelist[i].state != EC_STATE_SAFE_OP)
{
printf("Slave %d State=%2x StatusCode=%4x : %s\n",
i, ctx[ctx_count].slavelist[i].state, ctx[ctx_count].slavelist[i].ALstatuscode, ec_ALstatuscode2string(ctx[ctx_count].slavelist[i].ALstatuscode));
}
}
}
ecx_readstate(&ctx[ctx_count]);
for( cnt = 1 ; cnt <= *(ctx[ctx_count].slavecount) ; cnt++)
{
printf("\nSlave:%d\n Name:%s\n Output size: %dbits\n Input size: %dbits\n State: %d\n Delay: %d[ns]\n Has DC: %d\n",
cnt, ctx[ctx_count].slavelist[cnt].name, ctx[ctx_count].slavelist[cnt].Obits, ctx[ctx_count].slavelist[cnt].Ibits,
ctx[ctx_count].slavelist[cnt].state, ctx[ctx_count].slavelist[cnt].pdelay, ctx[ctx_count].slavelist[cnt].hasdc);
if (ctx[ctx_count].slavelist[cnt].hasdc)
{
printf(" DCParentport:%d\n", ctx[ctx_count].slavelist[cnt].parentport);
}
printf(" Activeports:%d.%d.%d.%d\n", (ctx[ctx_count].slavelist[cnt].activeports & 0x01) > 0 ,
(ctx[ctx_count].slavelist[cnt].activeports & 0x02) > 0 ,
(ctx[ctx_count].slavelist[cnt].activeports & 0x04) > 0 ,
(ctx[ctx_count].slavelist[cnt].activeports & 0x08) > 0 );
printf(" Configured address: %4.4x\n", ctx[ctx_count].slavelist[cnt].configadr);
printf(" Man: %8.8x ID: %8.8x Rev: %8.8x\n", (int)ctx[ctx_count].slavelist[cnt].eep_man,
(int)ctx[ctx_count].slavelist[cnt].eep_id, (int)ctx[ctx_count].slavelist[cnt].eep_rev);
for(nSM = 0 ; nSM < EC_MAXSM ; nSM++)
{
if(ctx[ctx_count].slavelist[cnt].SM[nSM].StartAddr > 0)
printf(" SM%1d A:%4.4x L:%4d F:%8.8x Type:%d\n",nSM, ctx[ctx_count].slavelist[cnt].SM[nSM].StartAddr,
ctx[ctx_count].slavelist[cnt].SM[nSM].SMlength,(int)ctx[ctx_count].slavelist[cnt].SM[nSM].SMflags,
ctx[ctx_count].slavelist[cnt].SMtype[nSM]);
}
for(j = 0 ; j < ctx[ctx_count].slavelist[cnt].FMMUunused ; j++)
{
printf(" FMMU%1d Ls:%8.8x Ll:%4d Lsb:%d Leb:%d Ps:%4.4x Psb:%d Ty:%2.2x Act:%2.2x\n", j,
(int)ctx[ctx_count].slavelist[cnt].FMMU[j].LogStart, ctx[ctx_count].slavelist[cnt].FMMU[j].LogLength,
ctx[ctx_count].slavelist[cnt].FMMU[j].LogStartbit, ctx[ctx_count].slavelist[cnt].FMMU[j].LogEndbit,
ctx[ctx_count].slavelist[cnt].FMMU[j].PhysStart, ctx[ctx_count].slavelist[cnt].FMMU[j].PhysStartBit,
ctx[ctx_count].slavelist[cnt].FMMU[j].FMMUtype, ctx[ctx_count].slavelist[cnt].FMMU[j].FMMUactive);
}
printf(" FMMUfunc 0:%d 1:%d 2:%d 3:%d\n",
ctx[ctx_count].slavelist[cnt].FMMU0func, ctx[ctx_count].slavelist[cnt].FMMU1func, ctx[ctx_count].slavelist[cnt].FMMU2func,
ctx[ctx_count].slavelist[cnt].FMMU3func);
printf(" MBX length wr: %d rd: %d MBX protocols : %2.2x\n", ctx[ctx_count].slavelist[cnt].mbx_l,
ctx[ctx_count].slavelist[cnt].mbx_rl, ctx[ctx_count].slavelist[cnt].mbx_proto);
ssigen = ecx_siifind(&ctx[ctx_count], cnt, ECT_SII_GENERAL);
/* SII general section */
if (ssigen)
{
ctx[ctx_count].slavelist[cnt].CoEdetails = ecx_siigetbyte(&ctx[ctx_count], cnt, ssigen + 0x07);
ctx[ctx_count].slavelist[cnt].FoEdetails = ecx_siigetbyte(&ctx[ctx_count], cnt, ssigen + 0x08);
ctx[ctx_count].slavelist[cnt].EoEdetails = ecx_siigetbyte(&ctx[ctx_count], cnt, ssigen + 0x09);
ctx[ctx_count].slavelist[cnt].SoEdetails = ecx_siigetbyte(&ctx[ctx_count], cnt, ssigen + 0x0a);
if((ecx_siigetbyte(&ctx[ctx_count], cnt, ssigen + 0x0d) & 0x02) > 0)
{
ctx[ctx_count].slavelist[cnt].blockLRW = 1;
ctx[ctx_count].slavelist[0].blockLRW++;
}
ctx[ctx_count].slavelist[cnt].Ebuscurrent = ecx_siigetbyte(&ctx[ctx_count], cnt, ssigen + 0x0e);
ctx[ctx_count].slavelist[cnt].Ebuscurrent += ecx_siigetbyte(&ctx[ctx_count], cnt, ssigen + 0x0f) << 8;
ctx[ctx_count].slavelist[0].Ebuscurrent += ctx[ctx_count].slavelist[cnt].Ebuscurrent;
}
printf(" CoE details: %2.2x FoE details: %2.2x EoE details: %2.2x SoE details: %2.2x\n",
ctx[ctx_count].slavelist[cnt].CoEdetails, ctx[ctx_count].slavelist[cnt].FoEdetails, ctx[ctx_count].slavelist[cnt].EoEdetails, ctx[ctx_count].slavelist[cnt].SoEdetails);
printf(" Ebus current: %d[mA]\n only LRD/LWR:%d\n",
ctx[ctx_count].slavelist[cnt].Ebuscurrent, ctx[ctx_count].slavelist[cnt].blockLRW);
}
}
inOP = FALSE;
printf("Request operational state for all slaves\n");
expectedWKC[0] = (ctx[0].grouplist[0].outputsWKC * 2) + ctx[0].grouplist[0].inputsWKC;
expectedWKC[1] = (ctx[1].grouplist[0].outputsWKC * 2) + ctx[1].grouplist[0].inputsWKC;
printf("Calculated workcounter master 1 %d\n", expectedWKC[0]);
printf("Calculated workcounter master 2 %d\n", expectedWKC[1]);
ctx[0].slavelist[0].state = EC_STATE_OPERATIONAL;
ctx[1].slavelist[0].state = EC_STATE_OPERATIONAL;
/* send one valid process data to make outputs in slaves happy*/
ecx_send_processdata(&ctx[0]);
ecx_send_processdata(&ctx[1]);
ecx_receive_processdata(&ctx[0],EC_TIMEOUTRET);
ecx_receive_processdata(&ctx[1],EC_TIMEOUTRET);
/* request OP state for all slaves */
ecx_writestate(&ctx[0], 0);
ecx_writestate(&ctx[1], 0);
chk = 40;
/* wait for all slaves to reach OP state */
do
{
ecx_send_processdata(&ctx[0]);
ecx_send_processdata(&ctx[1]);
ecx_receive_processdata(&ctx[0],EC_TIMEOUTRET);
ecx_receive_processdata(&ctx[1],EC_TIMEOUTRET);
ecx_statecheck(&ctx[0],0, EC_STATE_OPERATIONAL, 50000);
ecx_statecheck(&ctx[1],0, EC_STATE_OPERATIONAL, 50000);
}
while (chk-- && (ctx[0].slavelist[0].state != EC_STATE_OPERATIONAL) && (ctx[1].slavelist[0].state != EC_STATE_OPERATIONAL));
*(ctx[0].slavelist[6].outputs) = 0xFF;
*(ctx[1].slavelist[1].outputs) = 0x0F;
if (ctx[0].slavelist[0].state == EC_STATE_OPERATIONAL && ctx[1].slavelist[0].state == EC_STATE_OPERATIONAL )
{
printf("Operational state reached for all slaves.\n");
/* cyclic loop */
start_RT_trace (1);
wkc_count = 0;
inOP = TRUE;
for(i = 1; i <= 10000; i++)
{
for (ctx_count = 0; ctx_count < 2; ctx_count++)
{
/* Receive processdata */
log_RT_event('R',(WORD)(1 + ctx_count * 10));
wkc[ctx_count] = ecx_receive_processdata(&ctx[ctx_count], 0);
log_RT_event('R',(WORD)(99 + ctx_count * 100));
}
for (ctx_count = 0; ctx_count < 2; ctx_count++)
{
/* Send processdata */
log_RT_event('S',(WORD)(1 + ctx_count * 10));
if (!ecx_send_processdata(&ctx[ctx_count]))
{
printf (" Frame no: %d on master %d,Not sentOK\n", i,ctx_count);
}
log_RT_event('S',(WORD)(99 + ctx_count * 100));
}
knRtSleep(1);
for (ctx_count = 0; ctx_count < 2; ctx_count++)
{
if(wkc[ctx_count] >= expectedWKC[ctx_count])
{
}
else
{
printf (" Frame no: %d on master %d , wc not wkc >= expectedWKC, %d\n",i, ctx_count, wkc[ctx_count]);
}
}
}
stop_RT_trace ();
inOP = FALSE;
}
}
else
{
printf("No slaves found!\n");
}
printf("End slaveinfo, close socket\n");
/* stop SOEM, close socket */
ecx_close(&ctx[0]);
ecx_close(&ctx[1]);
}
else
{
printf("No socket connection on %s\nExcecute as root\n",ifname);
}
}
void main(int argc, char* argv[])
{
printf("SOEM (Simple Open EtherCAT Master)\nSlaveinfo\n");
if (argc > 1)
{
/* start slaveinfo */
slaveinfo(argv[1]);
}
else
{
printf("Usage: slaveinfo ifname [options]\nifname = eth0 for example\nOptions :\n -sdo : print SDO info\n -map : print mapping\n");
}
printf("End program\n");
}