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


soem
Author(s): Arthur Ketels and M.J.G. van den Molengraft
autogenerated on Sat Jun 27 2020 03:48:21