main.c
Go to the documentation of this file.
1 
10 #include <kern.h>
11 #include "ethercattype.h"
12 #include "nicdrv.h"
13 #include "ethercatbase.h"
14 #include "ethercatmain.h"
15 #include "ethercatcoe.h"
16 #include "ethercatfoe.h"
17 #include "ethercatconfig.h"
18 #include "ethercatprint.h"
19 #include "string.h"
20 #include <oshw.h>
21 #include <config.h>
22 
23 #include <defBF537.h>
24 
25 #define pPORTFIO_SET ((vuint16_t *)PORTFIO_SET)
26 #define pPORTFIO_CLEAR ((vuint16_t *)PORTFIO_CLEAR)
27 #define pPORTFIO_DIR ((vuint16_t *)PORTFIO_DIR)
28 
29 #define EK1100_1 1
30 #define EL4001_1 2
31 #define EL3061_1 3
32 #define EL1008_1 4
33 #define EL1008_2 5
34 #define EL2622_1 6
35 #define EL2622_2 7
36 #define EL2622_3 8
37 #define EL2622_4 9
38 #define NUMBER_OF_SLAVES 9
39 
40 
41 typedef struct
42 {
51 } in_EL1008_t;
52 
53 typedef struct
54 {
57 } out_EL2622_t;
58 
59 typedef struct
60 {
62 } out_EL4001_t;
63 
64 typedef struct
65 {
67 } in_EL3061_t;
68 
76 
78 {
79  /* Do we got expected number of slaves from config */
81  return 0;
82 
83  /* Verify slave by slave that it is correct*/
84  if (strcmp(ec_slave[EK1100_1].name,"EK1100"))
85  return 0;
86  else if (strcmp(ec_slave[EL4001_1].name,"EL4001"))
87  return 0;
88  else if (strcmp(ec_slave[EL3061_1].name,"EL3061"))
89  return 0;
90  else if (strcmp(ec_slave[EL1008_1].name,"EL1008"))
91  return 0;
92  else if (strcmp(ec_slave[EL1008_2].name,"EL1008"))
93  return 0;
94  else if (strcmp(ec_slave[EL2622_1].name,"EL2622"))
95  return 0;
96  else if (strcmp(ec_slave[EL2622_2].name,"EL2622"))
97  return 0;
98  else if (strcmp(ec_slave[EL2622_3].name,"EL2622"))
99  return 0;
100  else if (strcmp(ec_slave[EL2622_4].name,"EL2622"))
101  return 0;
102 
103  return 1;
104 }
105 
106 int32 get_input_int32(uint16 slave_no,uint8 module_index)
107 {
108  int32 return_value;
109  uint8 *data_ptr;
110  /* Get the IO map pointer from the ec_slave struct */
111  data_ptr = ec_slave[slave_no].inputs;
112  /* Move pointer to correct module index */
113  data_ptr += module_index * 4;
114  /* Read value byte by byte since all targets can't handle misaligned
115  * addresses
116  */
117  return_value = *data_ptr++;
118  return_value += (*data_ptr++ << 8);
119  return_value += (*data_ptr++ << 16);
120  return_value += (*data_ptr++ << 24);
121 
122  return return_value;
123 }
124 
125 void set_input_int32 (uint16 slave_no, uint8 module_index, int32 value)
126 {
127  uint8 *data_ptr;
128  /* Get the IO map pointer from the ec_slave struct */
129  data_ptr = ec_slave[slave_no].inputs;
130  /* Move pointer to correct module index */
131  data_ptr += module_index * 4;
132  /* Read value byte by byte since all targets can handle misaligned
133  * addresses
134  */
135  *data_ptr++ = (value >> 0) & 0xFF;
136  *data_ptr++ = (value >> 8) & 0xFF;
137  *data_ptr++ = (value >> 16) & 0xFF;
138  *data_ptr++ = (value >> 24) & 0xFF;
139 }
140 
141 uint8 get_input_bit (uint16 slave_no,uint8 module_index)
142 {
143  /* Get the the startbit position in slaves IO byte */
144  uint8 startbit = ec_slave[slave_no].Istartbit;
145  /* Mask bit and return boolean 0 or 1 */
146  if (*ec_slave[slave_no].inputs & BIT (module_index - 1 + startbit))
147  return 1;
148  else
149  return 0;
150 }
151 
152 int16 get_output_int16(uint16 slave_no,uint8 module_index)
153 {
154  int16 return_value;
155  uint8 *data_ptr;
156 
157  /* Get the IO map pointer from the ec_slave struct */
158  data_ptr = ec_slave[slave_no].outputs;
159  /* Move pointer to correct module index */
160  data_ptr += module_index * 2;
161  /* Read value byte by byte since all targets can handle misaligned
162  * addresses
163  */
164  return_value = *data_ptr++;
165  return_value += (*data_ptr++ << 8);
166 
167  return return_value;
168 }
169 
170 void set_output_int16 (uint16 slave_no, uint8 module_index, int16 value)
171 {
172  uint8 *data_ptr;
173  /* Get the IO map pointer from the ec_slave struct */
174  data_ptr = ec_slave[slave_no].outputs;
175  /* Move pointer to correct module index */
176  data_ptr += module_index * 2;
177  /* Read value byte by byte since all targets can handle misaligned
178  * addresses
179  */
180  *data_ptr++ = (value >> 0) & 0xFF;
181  *data_ptr++ = (value >> 8) & 0xFF;
182 }
183 
184 uint8 get_output_bit (uint16 slave_no,uint8 module_index)
185 {
186  /* Get the the startbit position in slaves IO byte */
187  uint8 startbit = ec_slave[slave_no].Ostartbit;
188  /* Mask bit and return boolean 0 or 1 */
189  if (*ec_slave[slave_no].outputs & BIT (module_index - 1 + startbit))
190  return 1;
191  else
192  return 0;
193 }
194 
195 void set_output_bit (uint16 slave_no, uint8 module_index, uint8 value)
196 {
197  /* Get the the startbit position in slaves IO byte */
198  uint8 startbit = ec_slave[slave_no].Ostartbit;
199  /* Set or Clear bit */
200  if (value == 0)
201  *ec_slave[slave_no].outputs &= ~(1 << (module_index - 1 + startbit));
202  else
203  *ec_slave[slave_no].outputs |= (1 << (module_index - 1 + startbit));
204 }
205 
206 
207 extern tt_sched_t * tt_sched[];
208 
209 char IOmap[128];
210 int dorun = 0;
211 
214 
215 void tt_error (uint32_t task_ix);
216 void tt_error (uint32_t task_ix)
217 {
218  error_counter++;
219 }
220 
221 static void my_cyclic_callback (void * arg)
222 {
223  while (1)
224  {
225  stats_get_load (&load1s, &load5s, &load10s);
226  rprintp ("Processor load was %d:%d:%d (1s:5s:10s) with TT errors: %d\n",
228  task_delay(20000);
229  }
230 }
231 
232 
233 void read_io (void * arg)
234 {
235  /* Function connected to cyclic TTOS task
236  * The function is executed cyclic according
237  * sceduel specified in schedule.tt
238  */
239  *pPORTFIO_SET = BIT (6);
240  /* Send and receive processdata
241  * Note that you need som synchronization
242  * case you modifey IO in local application
243  */
246  *pPORTFIO_CLEAR = BIT (6);
247 }
248 
249 
250 void simpletest(void *arg)
251 {
252 
253  char *ifname = arg;
254  int cnt, i, j;
255 
256  *pPORTFIO_DIR |= BIT (6);
257 
258  rprintp("Starting simple test\n");
259 
260  /* initialise SOEM */
261  if (ec_init(ifname))
262  {
263  rprintp("ec_init succeeded.\n");
264 
265  /* find and auto-config slaves */
266  if ( ec_config_init(FALSE) > 0 )
267  {
268  rprintp("%d slaves found and configured.\n",ec_slavecount);
269 
270  /* Check network setup */
271  if (network_configuration())
272  {
273  /* Run IO mapping */
275 
276  rprintp("Slaves mapped, state to SAFE_OP.\n");
277  /* wait for all slaves to reach SAFE_OP state */
279 
280  /* Print som information on the mapped network */
281  for( cnt = 1 ; cnt <= ec_slavecount ; cnt++)
282  {
283  rprintp("\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",
284  cnt, ec_slave[cnt].name, ec_slave[cnt].Obits, ec_slave[cnt].Ibits,
285  ec_slave[cnt].state, ec_slave[cnt].pdelay, ec_slave[cnt].hasdc);
286  rprintp(" Configured address: %x\n", ec_slave[cnt].configadr);
287  rprintp(" Outputs address: %x\n", ec_slave[cnt].outputs);
288  rprintp(" Inputs address: %x\n", ec_slave[cnt].inputs);
289 
290  for(j = 0 ; j < ec_slave[cnt].FMMUunused ; j++)
291  {
292  rprintp(" FMMU%1d Ls:%x Ll:%4d Lsb:%d Leb:%d Ps:%x Psb:%d Ty:%x Act:%x\n", j,
293  (int)ec_slave[cnt].FMMU[j].LogStart, ec_slave[cnt].FMMU[j].LogLength, ec_slave[cnt].FMMU[j].LogStartbit,
294  ec_slave[cnt].FMMU[j].LogEndbit, ec_slave[cnt].FMMU[j].PhysStart, ec_slave[cnt].FMMU[j].PhysStartBit,
295  ec_slave[cnt].FMMU[j].FMMUtype, ec_slave[cnt].FMMU[j].FMMUactive);
296  }
297  rprintp(" FMMUfunc 0:%d 1:%d 2:%d 3:%d\n",
298  ec_slave[cnt].FMMU0func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU3func);
299 
300  }
301 
302  rprintp("Request operational state for all slaves\n");
304  /* send one valid process data to make outputs in slaves happy*/
307  /* request OP state for all slaves */
308  ec_writestate(0);
309  /* wait for all slaves to reach OP state */
311  if (ec_slave[0].state == EC_STATE_OPERATIONAL )
312  {
313  rprintp("Operational state reached for all slaves.\n");
314  }
315  else
316  {
317  rprintp("Not all slaves reached operational state.\n");
318  ec_readstate();
319  for(i = 1; i<=ec_slavecount ; i++)
320  {
321  if(ec_slave[i].state != EC_STATE_OPERATIONAL)
322  {
323  rprintp("Slave %d State=0x%04x StatusCode=0x%04x\n",
324  i, ec_slave[i].state, ec_slave[i].ALstatuscode);
325  }
326  }
327  }
328 
329 
330  /* Simple blinking lamps BOX demo */
331  uint8 digout = 0;
332 
333  slave_EL4001_1.out1 = (int16)0x3FFF;
334  set_output_int16(EL4001_1,0,slave_EL4001_1.out1);
335 
336  task_spawn ("t_StatsPrint", my_cyclic_callback, 20, 1024, (void *)NULL);
337  tt_start_wait (tt_sched[0]);
338 
339  while(1)
340  {
341  dorun = 0;
342  slave_EL1008_1.in1 = get_input_bit(EL1008_1,1); // Start button
343  slave_EL1008_1.in2 = get_input_bit(EL1008_1,2); // Turnkey RIGHT
344  slave_EL1008_1.in3 = get_input_bit(EL1008_1,3); // Turnkey LEFT
345 
346  /* (Turnkey MIDDLE + Start button) OR Turnkey RIGHT OR Turnkey LEFT
347  Turnkey LEFT: Light positions bottom to top. Loop, slow operation.
348  Turnkey MIDDLE: Press start button to light positions bottom to top. No loop, fast operation.
349  Turnkey RIGHT: Light positions bottom to top. Loop, fast operation.
350  */
351  if (slave_EL1008_1.in1 || slave_EL1008_1.in2 || slave_EL1008_1.in3)
352  {
353  digout = 0;
354  /* *ec_slave[6].outputs = digout; */
355  /* set_output_bit(slave_name #,index as 1 output on module , value */
356  set_output_bit(EL2622_1,1,(digout & BIT (0))); /* Start button */
357  set_output_bit(EL2622_1,2,(digout & BIT (1))); /* Turnkey RIGHT */
358  set_output_bit(EL2622_2,1,(digout & BIT (2))); /* Turnkey LEFT */
359  set_output_bit(EL2622_2,2,(digout & BIT (3)));
360  set_output_bit(EL2622_3,1,(digout & BIT (4)));
361  set_output_bit(EL2622_3,2,(digout & BIT (5)));
362 
363  while(dorun < 95)
364  {
365  dorun++;
366 
367  if (slave_EL1008_1.in3)
368  task_delay(tick_from_ms(20));
369  else
370  task_delay(tick_from_ms(5));
371 
372  digout = (uint8) (digout | BIT((dorun / 16) & 0xFF));
373 
374  set_output_bit(EL2622_1,1,(digout & BIT (0))); /* LED1 */
375  set_output_bit(EL2622_1,2,(digout & BIT (1))); /* LED2 */
376  set_output_bit(EL2622_2,1,(digout & BIT (2))); /* LED3 */
377  set_output_bit(EL2622_2,2,(digout & BIT (3))); /* LED4 */
378  set_output_bit(EL2622_3,1,(digout & BIT (4))); /* LED5 */
379  set_output_bit(EL2622_3,2,(digout & BIT (5))); /* LED6 */
380 
381  slave_EL1008_1.in1 = get_input_bit(EL1008_1,2); /* Turnkey RIGHT */
382  slave_EL1008_1.in2 = get_input_bit(EL1008_1,3); /* Turnkey LEFT */
383  slave_EL3061_1.in1 = get_input_int32(EL3061_1,0); /* Read AI */
384  }
385  }
386  task_delay(tick_from_ms(2));
387 
388  }
389  }
390  else
391  {
392  rprintp("Mismatch of network units!\n");
393  }
394  }
395  else
396  {
397  rprintp("No slaves found!\n");
398  }
399  rprintp("End simple test, close socket\n");
400  /* stop SOEM, close socket */
401  ec_close();
402  }
403  else
404  {
405  rprintp("ec_init failed");
406  }
407  rprintp("End program\n");
408 }
409 
410 static void test_osal_timer_timeout_us (const uint32 timeout_us)
411 {
412  osal_timert timer;
413 
414  ASSERT (timeout_us > 4000);
415 
416  osal_timer_start (&timer, timeout_us);
417  ASSERT (osal_timer_is_expired (&timer) == false);
418  osal_usleep (timeout_us - 2000);
419  ASSERT (osal_timer_is_expired (&timer) == false);
420  osal_usleep (4000);
421  ASSERT (osal_timer_is_expired (&timer));
422 }
423 
424 static void test_osal_timer (void)
425 {
426  test_osal_timer_timeout_us (10*1000); /* 10ms */
427  test_osal_timer_timeout_us (100*1000); /* 100ms */
428  test_osal_timer_timeout_us (1000*1000); /* 1s */
429  test_osal_timer_timeout_us (2000*1000); /* 2s */
430 }
431 
432 #define USECS_PER_SEC 1000000
433 #define USECS_PER_TICK (USECS_PER_SEC / CFG_TICKS_PER_SECOND)
434 #ifndef ABS
435 #define ABS(x) ((x) < 0 ? -(x) : (x))
436 #endif
437 
438 static int32 time_difference_us (const ec_timet stop, const ec_timet start)
439 {
440  int32 difference_us;
441 
442  ASSERT (stop.sec >= start.sec);
443  if (stop.sec == start.sec)
444  {
445  ASSERT (stop.usec >= start.usec);
446  }
447 
448  difference_us = (stop.sec - start.sec) * USECS_PER_SEC;
449  difference_us += ((int32)stop.usec - (int32)start.usec);
450 
451  ASSERT (difference_us >= 0);
452  return difference_us;
453 }
454 
459 static void test_osal_current_time_for_delay_us (const int32 sleep_time_us)
460 {
461  ec_timet start;
462  ec_timet stop;
463  int32 measurement_us;
464  int32 deviation_us;
465  const int32 usleep_accuracy_us = USECS_PER_TICK;
466  boolean is_deviation_within_tolerance;
467 
468  start = osal_current_time ();
469  osal_usleep (sleep_time_us);
470  stop = osal_current_time ();
471 
472  measurement_us = time_difference_us (stop, start);
473  deviation_us = ABS (measurement_us - sleep_time_us);
474  is_deviation_within_tolerance = deviation_us <= usleep_accuracy_us;
475  ASSERT (is_deviation_within_tolerance);
476 }
477 
478 static void test_osal_current_time (void)
479 {
487  test_osal_current_time_for_delay_us (2 * 1000 * 1000); /* 2s */
488 }
489 
490 #include <lwip/inet.h>
491 
492 static void test_oshw_htons (void)
493 {
494  uint16 network;
495  uint16 host;
496 
497  host = 0x1234;
498  network = oshw_htons (host);
499  ASSERT (network == htons (host));
500 }
501 
502 static void test_oshw_ntohs (void)
503 {
504  uint16 host;
505  uint16 network;
506 
507  network = 0x1234;
508  host = oshw_ntohs (network);
509  ASSERT (host == ntohs (network));
510 }
511 
512 int main (void)
513 {
514  test_oshw_htons ();
515  test_oshw_ntohs ();
516  test_osal_timer ();
518 
519  rprintp("SOEM (Simple Open EtherCAT Master)\nSimple test\n");
520 
521  task_spawn ("simpletest", simpletest, 9, 8192, NULL);
522 
523  return (0);
524 }
525 
static void test_osal_timer_timeout_us(const uint32 timeout_us)
Definition: main.c:410
uint8 in3
Definition: main.c:45
uint8 in1
Definition: main.c:43
static void test_osal_timer(void)
Definition: main.c:424
static void test_osal_current_time_for_delay_us(const int32 sleep_time_us)
Definition: main.c:459
void osal_timer_start(osal_timert *self, uint32 timeout_usec)
Definition: linux/osal.c:63
uint8 FMMUunused
Definition: ethercatmain.h:258
int ec_readstate(void)
int ec_send_processdata(void)
#define EC_TIMEOUTSTATE
Definition: ethercattype.h:102
uint16 oshw_ntohs(uint16 network)
Definition: linux/oshw.c:48
PACKED_END ec_slavet ec_slave[EC_MAXSLAVE]
Definition: ethercatmain.c:104
uint8_t uint8
Definition: osal.h:33
int16 out1
Definition: main.c:61
uint32 usec
Definition: osal.h:56
uint8 * inputs
Definition: ethercatmain.h:170
static void test_oshw_htons(void)
Definition: main.c:492
int32 get_input_int32(uint16 slave_no, uint8 module_index)
Definition: main.c:106
static int32 time_difference_us(const ec_timet stop, const ec_timet start)
Definition: main.c:438
int ec_receive_processdata(int timeout)
uint8 get_output_bit(uint16 slave_no, uint8 module_index)
Definition: main.c:184
void set_output_bit(uint16 slave_no, uint8 module_index, uint8 value)
Definition: main.c:195
#define EL2622_3
Definition: main.c:36
uint8 in5
Definition: main.c:47
#define USECS_PER_TICK
Definition: main.c:433
#define NUMBER_OF_SLAVES
Definition: main.c:38
uint8 in6
Definition: main.c:48
uint16_t uint16
Definition: osal.h:34
uint8 * outputs
Definition: ethercatmain.h:162
uint8 Istartbit
Definition: ethercatmain.h:172
static void test_oshw_ntohs(void)
Definition: main.c:502
unsigned char uint8_t
Definition: stdint.h:78
void tt_error(uint32_t task_ix)
Definition: main.c:216
uint8 in4
Definition: main.c:46
#define EL2622_4
Definition: main.c:37
uint8 out1
Definition: main.c:55
General typedefs and defines for EtherCAT.
ec_timet osal_current_time(void)
Definition: linux/osal.c:52
Headerfile for ethercatcoe.c.
int ec_config_map(void *pIOmap)
out_EL2622_t slave_EL2622_1
Definition: main.c:73
#define EK1100_1
Definition: main.c:29
uint8 * digout
uint8 in8
Definition: main.c:50
#define ABS(x)
Definition: main.c:435
Definition: osal.h:53
in_EL3061_t slave_EL3061_1
Definition: main.c:70
int ec_init(char *ifname)
unsigned int uint32_t
Definition: stdint.h:80
uint8_t load10s
Definition: main.c:212
#define EL1008_1
Definition: main.c:32
in_EL1008_t slave_EL1008_2
Definition: main.c:72
Headerfile for ethercatfoe.c.
int32 in1
Definition: main.c:66
#define FALSE
Definition: osal.h:29
uint32 network_configuration(void)
Definition: main.c:77
in_EL1008_t slave_EL1008_1
Definition: main.c:71
void read_io(void *arg)
Definition: main.c:233
int32_t int32
Definition: osal.h:32
uint32_t error_counter
Definition: main.c:213
static void my_cyclic_callback(void *arg)
Definition: main.c:221
#define EL2622_1
Definition: main.c:34
out_EL4001_t slave_EL4001_1
Definition: main.c:69
uint16 oshw_htons(uint16 host)
Definition: linux/oshw.c:36
#define EC_TIMEOUTRET
Definition: ethercattype.h:90
int ec_writestate(uint16 slave)
uint8 in7
Definition: main.c:49
void set_input_int32(uint16 slave_no, uint8 module_index, int32 value)
Definition: main.c:125
int16 get_output_int16(uint16 slave_no, uint8 module_index)
Definition: main.c:152
#define EL4001_1
Definition: main.c:30
Headerfile for ethercatbase.c.
out_EL2622_t slave_EL2622_3
Definition: main.c:75
tt_sched_t * tt_sched[]
#define USECS_PER_SEC
Definition: main.c:432
#define EL2622_2
Definition: main.c:35
static void test_osal_current_time(void)
Definition: main.c:478
#define EL3061_1
Definition: main.c:31
#define pPORTFIO_CLEAR
Definition: main.c:26
uint8_t load5s
Definition: main.c:212
Headerfile for ethercatmain.c.
uint32 sec
Definition: osal.h:55
uint32_t uint32
Definition: osal.h:35
void simpletest(void *arg)
Definition: main.c:250
uint8 out2
Definition: main.c:56
int16_t int16
Definition: osal.h:31
uint16 state
Definition: ethercatmain.h:140
#define pPORTFIO_DIR
Definition: main.c:27
int osal_usleep(uint32 usec)
Definition: linux/osal.c:28
boolean osal_timer_is_expired(const osal_timert *self)
Definition: linux/osal.c:78
#define pPORTFIO_SET
Definition: main.c:25
void ec_close(void)
char IOmap[128]
Definition: main.c:209
void set_output_int16(uint16 slave_no, uint8 module_index, int16 value)
Definition: main.c:170
uint8 in2
Definition: main.c:44
uint16 ec_statecheck(uint16 slave, uint16 reqstate, int timeout)
out_EL2622_t slave_EL2622_2
Definition: main.c:74
int ec_slavecount
Definition: ethercatmain.c:106
Headerfile for ethercatconfig.c.
int dorun
Definition: main.c:210
int main(void)
Definition: main.c:512
#define EL1008_2
Definition: main.c:33
uint8 get_input_bit(uint16 slave_no, uint8 module_index)
Definition: main.c:141
int ec_config_init(uint8 usetable)
uint8_t load1s
Definition: main.c:212
Headerfile for ethercatprint.c.
uint8 Ostartbit
Definition: ethercatmain.h:164


soem
Author(s): Arthur Ketels and M.J.G. van den Molengraft
autogenerated on Sat Jun 8 2019 18:02:17