linux/eepromtool/eepromtool.c
Go to the documentation of this file.
1 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include "ethercat.h"
22 
23 #define MAXBUF 524288
24 #define STDBUF 2048
25 #define MINBUF 128
26 #define CRCBUF 14
27 
28 #define MODE_NONE 0
29 #define MODE_READBIN 1
30 #define MODE_READINTEL 2
31 #define MODE_WRITEBIN 3
32 #define MODE_WRITEINTEL 4
33 #define MODE_WRITEALIAS 5
34 #define MODE_INFO 6
35 
36 #define MAXSLENGTH 256
37 
41 int os;
42 int slave;
43 int alias;
45 int wkc;
46 int mode;
48 
49 #define IHEXLENGTH 0x20
50 
51 void calc_crc(uint8 *crc, uint8 b)
52 {
53  int j;
54  *crc ^= b;
55  for(j = 0; j <= 7 ; j++ )
56  {
57  if(*crc & 0x80)
58  *crc = (*crc << 1) ^ 0x07;
59  else
60  *crc = (*crc << 1);
61  }
62 }
63 
65 {
66  int i;
67  uint8 crc;
68 
69  crc = 0xff;
70  for( i = 0 ; i <= 13 ; i++ )
71  {
72  calc_crc(&crc , *(buf++));
73  }
74  return (uint16)crc;
75 }
76 
77 int input_bin(char *fname, int *length)
78 {
79  FILE *fp;
80 
81  int cc = 0, c;
82 
83  fp = fopen(fname, "rb");
84  if(fp == NULL)
85  return 0;
86  while (((c = fgetc(fp)) != EOF) && (cc < MAXBUF))
87  ebuf[cc++] = (uint8)c;
88  *length = cc;
89  fclose(fp);
90 
91  return 1;
92 }
93 
94 int input_intelhex(char *fname, int *start, int *length)
95 {
96  FILE *fp;
97 
98  int c, sc, retval = 1;
99  int ll, ladr, lt, sn, i, lval;
100  int hstart, hlength, sum;
101 
102  fp = fopen(fname, "r");
103  if(fp == NULL)
104  return 0;
105  hstart = MAXBUF;
106  hlength = 0;
107  sum = 0;
108  do
109  {
110  memset(sline, 0x00, MAXSLENGTH);
111  sc = 0;
112  while (((c = fgetc(fp)) != EOF) && (c != 0x0A) && (sc < (MAXSLENGTH -1)))
113  sline[sc++] = (uint8)c;
114  if ((c != EOF) && ((sc < 11) || (sline[0] != ':')))
115  {
116  c = EOF;
117  retval = 0;
118  printf("Invalid Intel Hex format.\n");
119  }
120  if (c != EOF)
121  {
122  sn = sscanf(sline , ":%2x%4x%2x", &ll, &ladr, &lt);
123  if ((sn == 3) && ((ladr + ll) <= MAXBUF) && (lt == 0))
124  {
125  sum = ll + (ladr >> 8) + (ladr & 0xff) + lt;
126  if(ladr < hstart) hstart = ladr;
127  for(i = 0; i < ll ; i++)
128  {
129  sn = sscanf(&sline[9 + (i << 1)], "%2x", &lval);
130  ebuf[ladr + i] = (uint8)lval;
131  sum += (uint8)lval;
132  }
133  if(((ladr + ll) - hstart) > hlength)
134  hlength = (ladr + ll) - hstart;
135  sum = (0x100 - sum) & 0xff;
136  sn = sscanf(&sline[9 + (i << 1)], "%2x", &lval);
137  if (!sn || ((sum - lval) != 0))
138  {
139  c = EOF;
140  retval = 0;
141  printf("Invalid checksum.\n");
142  }
143  }
144  }
145  }
146  while (c != EOF);
147  if (retval)
148  {
149  *length = hlength;
150  *start = hstart;
151  }
152  fclose(fp);
153 
154  return retval;
155 }
156 
157 int output_bin(char *fname, int length)
158 {
159  FILE *fp;
160 
161  int cc;
162 
163  fp = fopen(fname, "wb");
164  if(fp == NULL)
165  return 0;
166  for (cc = 0 ; cc < length ; cc++)
167  fputc( ebuf[cc], fp);
168  fclose(fp);
169 
170  return 1;
171 }
172 
173 int output_intelhex(char *fname, int length)
174 {
175  FILE *fp;
176 
177  int cc = 0, ll, sum, i;
178 
179  fp = fopen(fname, "w");
180  if(fp == NULL)
181  return 0;
182  while (cc < length)
183  {
184  ll = length - cc;
185  if (ll > IHEXLENGTH) ll = IHEXLENGTH;
186  sum = ll + (cc >> 8) + (cc & 0xff);
187  fprintf(fp, ":%2.2X%4.4X00", ll, cc);
188  for (i = 0; i < ll; i++)
189  {
190  fprintf(fp, "%2.2X", ebuf[cc + i]);
191  sum += ebuf[cc + i];
192  }
193  fprintf(fp, "%2.2X\n", (0x100 - sum) & 0xff);
194  cc += ll;
195  }
196  fprintf(fp, ":00000001FF\n");
197  fclose(fp);
198 
199  return 1;
200 }
201 
202 int eeprom_read(int slave, int start, int length)
203 {
204  int i, ainc = 4;
205  uint16 estat, aiadr;
206  uint32 b4;
207  uint64 b8;
208  uint8 eepctl;
209 
210  if((ec_slavecount >= slave) && (slave > 0) && ((start + length) <= MAXBUF))
211  {
212  aiadr = 1 - slave;
213  eepctl = 2;
214  ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* force Eeprom from PDI */
215  eepctl = 0;
216  ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* set Eeprom to master */
217 
218  estat = 0x0000;
219  aiadr = 1 - slave;
220  ec_APRD(aiadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET); /* read eeprom status */
221  estat = etohs(estat);
222  if (estat & EC_ESTAT_R64)
223  {
224  ainc = 8;
225  for (i = start ; i < (start + length) ; i+=ainc)
226  {
227  b8 = ec_readeepromAP(aiadr, i >> 1 , EC_TIMEOUTEEP);
228  ebuf[i] = b8 & 0xFF;
229  ebuf[i+1] = (b8 >> 8) & 0xFF;
230  ebuf[i+2] = (b8 >> 16) & 0xFF;
231  ebuf[i+3] = (b8 >> 24) & 0xFF;
232  ebuf[i+4] = (b8 >> 32) & 0xFF;
233  ebuf[i+5] = (b8 >> 40) & 0xFF;
234  ebuf[i+6] = (b8 >> 48) & 0xFF;
235  ebuf[i+7] = (b8 >> 56) & 0xFF;
236  }
237  }
238  else
239  {
240  for (i = start ; i < (start + length) ; i+=ainc)
241  {
242  b4 = ec_readeepromAP(aiadr, i >> 1 , EC_TIMEOUTEEP) & 0xFFFFFFFF;
243  ebuf[i] = b4 & 0xFF;
244  ebuf[i+1] = (b4 >> 8) & 0xFF;
245  ebuf[i+2] = (b4 >> 16) & 0xFF;
246  ebuf[i+3] = (b4 >> 24) & 0xFF;
247  }
248  }
249 
250  return 1;
251  }
252 
253  return 0;
254 }
255 
256 int eeprom_write(int slave, int start, int length)
257 {
258  int i, dc = 0;
259  uint16 aiadr, *wbuf;
260  uint8 eepctl;
261 
262  if((ec_slavecount >= slave) && (slave > 0) && ((start + length) <= MAXBUF))
263  {
264  aiadr = 1 - slave;
265  eepctl = 2;
266  ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* force Eeprom from PDI */
267  eepctl = 0;
268  ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* set Eeprom to master */
269 
270  aiadr = 1 - slave;
271  wbuf = (uint16 *)&ebuf[0];
272  for (i = start ; i < (start + length) ; i+=2)
273  {
274  ec_writeeepromAP(aiadr, i >> 1 , *(wbuf + (i >> 1)), EC_TIMEOUTEEP);
275  if (++dc >= 100)
276  {
277  dc = 0;
278  printf(".");
279  fflush(stdout);
280  }
281  }
282 
283  return 1;
284  }
285 
286  return 0;
287 }
288 
290 {
291  uint16 aiadr;
292  uint8 eepctl;
293  int ret;
294 
295  if((ec_slavecount >= slave) && (slave > 0) && (alias <= 0xffff))
296  {
297  aiadr = 1 - slave;
298  eepctl = 2;
299  ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* force Eeprom from PDI */
300  eepctl = 0;
301  ec_APWR(aiadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl , EC_TIMEOUTRET); /* set Eeprom to master */
302 
303  ret = ec_writeeepromAP(aiadr, 0x04 , alias, EC_TIMEOUTEEP);
304  if (ret)
305  ret = ec_writeeepromAP(aiadr, 0x07 , crc, EC_TIMEOUTEEP);
306 
307  return ret;
308  }
309 
310  return 0;
311 }
312 
313 void eepromtool(char *ifname, int slave, int mode, char *fname)
314 {
315  int w, rc = 0, estart, esize;
316  uint16 *wbuf;
317 
318  /* initialise SOEM, bind socket to ifname */
319  if (ec_init(ifname))
320  {
321  printf("ec_init on %s succeeded.\n",ifname);
322 
323  w = 0x0000;
324  wkc = ec_BRD(0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE); /* detect number of slaves */
325  if (wkc > 0)
326  {
327  ec_slavecount = wkc;
328 
329  printf("%d slaves found.\n",ec_slavecount);
330  if((ec_slavecount >= slave) && (slave > 0))
331  {
332  if ((mode == MODE_INFO) || (mode == MODE_READBIN) || (mode == MODE_READINTEL))
333  {
334  tstart = osal_current_time();
335  eeprom_read(slave, 0x0000, MINBUF); // read first 128 bytes
336 
337  wbuf = (uint16 *)&ebuf[0];
338  printf("Slave %d data\n", slave);
339  printf(" PDI Control : %4.4X\n",*(wbuf + 0x00));
340  printf(" PDI Config : %4.4X\n",*(wbuf + 0x01));
341  printf(" Config Alias : %4.4X\n",*(wbuf + 0x04));
342  printf(" Checksum : %4.4X\n",*(wbuf + 0x07));
343  printf(" calculated : %4.4X\n",SIIcrc(&ebuf[0]));
344  printf(" Vendor ID : %8.8X\n",*(uint32 *)(wbuf + 0x08));
345  printf(" Product Code : %8.8X\n",*(uint32 *)(wbuf + 0x0A));
346  printf(" Revision Number : %8.8X\n",*(uint32 *)(wbuf + 0x0C));
347  printf(" Serial Number : %8.8X\n",*(uint32 *)(wbuf + 0x0E));
348  printf(" Mailbox Protocol : %4.4X\n",*(wbuf + 0x1C));
349  esize = (*(wbuf + 0x3E) + 1) * 128;
350  if (esize > MAXBUF) esize = MAXBUF;
351  printf(" Size : %4.4X = %d bytes\n",*(wbuf + 0x3E), esize);
352  printf(" Version : %4.4X\n",*(wbuf + 0x3F));
353  }
354  if ((mode == MODE_READBIN) || (mode == MODE_READINTEL))
355  {
356  if (esize > MINBUF)
357  eeprom_read(slave, MINBUF, esize - MINBUF); // read reminder
358 
359  tend = osal_current_time();
360  osal_time_diff(&tstart, &tend, &tdif);
361  if (mode == MODE_READINTEL) output_intelhex(fname, esize);
362  if (mode == MODE_READBIN) output_bin(fname, esize);
363 
364  printf("\nTotal EEPROM read time :%ldms\n", (tdif.usec+(tdif.sec*1000000L)) / 1000);
365  }
366  if ((mode == MODE_WRITEBIN) || (mode == MODE_WRITEINTEL))
367  {
368  estart = 0;
369  if (mode == MODE_WRITEINTEL) rc = input_intelhex(fname, &estart, &esize);
370  if (mode == MODE_WRITEBIN) rc = input_bin(fname, &esize);
371 
372  if (rc > 0)
373  {
374  wbuf = (uint16 *)&ebuf[0];
375  printf("Slave %d\n", slave);
376  printf(" Vendor ID : %8.8X\n",*(uint32 *)(wbuf + 0x08));
377  printf(" Product Code : %8.8X\n",*(uint32 *)(wbuf + 0x0A));
378  printf(" Revision Number : %8.8X\n",*(uint32 *)(wbuf + 0x0C));
379  printf(" Serial Number : %8.8X\n",*(uint32 *)(wbuf + 0x0E));
380 
381  printf("Busy");
382  fflush(stdout);
383  tstart = osal_current_time();
384  eeprom_write(slave, estart, esize);
385  tend = osal_current_time();
386  osal_time_diff(&tstart, &tend, &tdif);
387 
388  printf("\nTotal EEPROM write time :%ldms\n", (tdif.usec+(tdif.sec*1000000L)) / 1000);
389  }
390  else
391  printf("Error reading file, abort.\n");
392  }
393  if (mode == MODE_WRITEALIAS)
394  {
395  if( eeprom_read(slave, 0x0000, CRCBUF) ) // read first 14 bytes
396  {
397  wbuf = (uint16 *)&ebuf[0];
398  *(wbuf + 0x04) = alias;
399  if(eeprom_writealias(slave, alias, SIIcrc(&ebuf[0])))
400  {
401  printf("Alias %4.4X written successfully to slave %d\n", alias, slave);
402  }
403  else
404  {
405  printf("Alias not written\n");
406  }
407  }
408  else
409  {
410  printf("Could not read slave EEPROM");
411  }
412  }
413  }
414  else
415  {
416  printf("Slave number outside range.\n");
417  }
418  }
419  else
420  {
421  printf("No slaves found!\n");
422  }
423  printf("End, close socket\n");
424  /* stop SOEM, close socket */
425  ec_close();
426  }
427  else
428  {
429  printf("No socket connection on %s\nExcecute as root\n",ifname);
430  }
431 }
432 
433 int main(int argc, char *argv[])
434 {
435  printf("SOEM (Simple Open EtherCAT Master)\nEEPROM tool\n");
436 
437  mode = MODE_NONE;
438  if (argc > 3)
439  {
440  slave = atoi(argv[2]);
441  if ((strncmp(argv[3], "-i", sizeof("-i")) == 0)) mode = MODE_INFO;
442  if (argc > 4)
443  {
444  if ((strncmp(argv[3], "-r", sizeof("-r")) == 0)) mode = MODE_READBIN;
445  if ((strncmp(argv[3], "-ri", sizeof("-ri")) == 0)) mode = MODE_READINTEL;
446  if ((strncmp(argv[3], "-w", sizeof("-w")) == 0)) mode = MODE_WRITEBIN;
447  if ((strncmp(argv[3], "-wi", sizeof("-wi")) == 0)) mode = MODE_WRITEINTEL;
448  if ((strncmp(argv[3], "-walias", sizeof("-walias")) == 0))
449  {
451  alias = atoi(argv[4]);
452  }
453  }
454  /* start tool */
455  eepromtool(argv[1],slave,mode,argv[4]);
456  }
457  else
458  {
459  printf("Usage: eepromtool ifname slave OPTION fname|alias\n");
460  printf("ifname = eth0 for example\n");
461  printf("slave = slave number in EtherCAT order 1..n\n");
462  printf(" -i display EEPROM information\n");
463  printf(" -walias write slave alias\n");
464  printf(" -r read EEPROM, output binary format\n");
465  printf(" -ri read EEPROM, output Intel Hex format\n");
466  printf(" -w write EEPROM, input binary format\n");
467  printf(" -wi write EEPROM, input Intel Hex format\n");
468  }
469 
470  printf("End program\n");
471 
472  return (0);
473 }
int eeprom_read(int slave, int start, int length)
uint16 SIIcrc(uint8 *buf)
ec_timet tend
int eeprom_writealias(int slave, int alias, uint16 crc)
int ec_writeeepromAP(uint16 aiadr, uint16 eeproma, uint16 data, int timeout)
int ec_APWR(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:598
int ec_APRD(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:559
#define EC_TIMEOUTSAFE
Definition: ethercattype.h:68
#define IHEXLENGTH
uint8_t uint8
Definition: osal.h:28
uint32 usec
Definition: osal.h:39
int eeprom_write(int slave, int start, int length)
Headerfile for all ethercat headers.
#define CRCBUF
int ec_init(const char *ifname)
uint16_t uint16
Definition: osal.h:29
#define MODE_INFO
#define etohs(A)
Definition: ethercattype.h:536
uint8 ebuf[MAXBUF]
#define MAXBUF
int input_intelhex(char *fname, int *start, int *length)
ec_timet osal_current_time(void)
Definition: erika/osal.c:37
Definition: osal.h:36
int ec_BRD(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
Definition: ethercatbase.c:554
void eepromtool(char *ifname, int slave, int mode, char *fname)
int ec_slavecount
Definition: ethercatmain.c:69
void osal_time_diff(ec_timet *start, ec_timet *end, ec_timet *diff)
Definition: erika/osal.c:48
#define MODE_WRITEBIN
#define MODE_READINTEL
#define EC_TIMEOUTEEP
Definition: ethercattype.h:70
ec_timet tdif
int output_bin(char *fname, int length)
#define MODE_NONE
uint64_t uint64
Definition: osal.h:32
#define MINBUF
#define MAXSLENGTH
ec_timet tstart
#define EC_TIMEOUTRET
Definition: ethercattype.h:64
void calc_crc(uint8 *crc, uint8 b)
#define MODE_WRITEINTEL
int output_intelhex(char *fname, int length)
uint64 ec_readeepromAP(uint16 aiadr, uint16 eeproma, int timeout)
uint32 sec
Definition: osal.h:38
uint32_t uint32
Definition: osal.h:30
int input_bin(char *fname, int *length)
int main(int argc, char *argv[])
#define MODE_READBIN
void ec_close(void)
int ainc
char sline[MAXSLENGTH]
#define EC_ESTAT_R64
Definition: ethercattype.h:271
#define MODE_WRITEALIAS


soem
Author(s): Arthur Ketels and M.J.G. van den Molengraft
autogenerated on Mon Feb 28 2022 23:46:57