00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00053 #include <stdio.h>
00054 #include <string.h>
00055 #include <sys/time.h>
00056 #include <arpa/inet.h>
00057 #include <unistd.h>
00058 #include <youbot_driver/soem/ethercattype.h>
00059 #include <youbot_driver/soem/nicdrv.h>
00060 #include <youbot_driver/soem/ethercatbase.h>
00061 #include <youbot_driver/soem/ethercatmain.h>
00062
00064 #define EC_LOCALDELAY 200
00065
00067 typedef struct
00068 {
00069 uint8 pushed;
00070 uint8 pulled;
00071 uint8 idx[EC_MAXBUF];
00072 void *data[EC_MAXBUF];
00073 uint16 length[EC_MAXBUF];
00074 } ec_idxstackT;
00075
00077 typedef struct
00078 PACKED
00079 {
00080 uint16 comm;
00081 uint16 addr;
00082 uint16 d2;
00083 } ec_eepromt;
00084
00086 typedef struct
00087 {
00088 int16 head;
00089 int16 tail;
00090 ec_errort Error[EC_MAXELIST + 1];
00091 } ec_eringt;
00092
00094 typedef struct
00095 {
00096 ec_mbxheadert MbxHeader;
00097 uint16 CANOpen;
00098 uint16 ErrorCode;
00099 uint8 ErrorReg;
00100 uint8 bData;
00101 uint16 w1, w2;
00102 } ec_emcyt;
00103
00109 ec_slavet ec_slave[EC_MAXSLAVE];
00111 int ec_slavecount;
00113 ec_groupt ec_group[EC_MAXGROUP];
00114
00116 static uint8 esibuf[EC_MAXEEPBUF];
00118 static uint32 esimap[EC_MAXEEPBITMAP];
00120 static uint16 esislave = 0;
00121 static ec_eringt ec_elist;
00122 static ec_idxstackT ec_idxstack;
00123
00125 boolean EcatError = FALSE;
00126
00127 uint16 ec_DCtO;
00128 static uint16 ec_DCl;
00129 int64 ec_DCtime;
00130
00135 void ec_pusherror(const ec_errort *Ec)
00136 {
00137 ec_elist.Error[ec_elist.head] = *Ec;
00138 ec_elist.Error[ec_elist.head].Signal = TRUE;
00139 ec_elist.head++;
00140 if (ec_elist.head > EC_MAXELIST)
00141 ec_elist.head = 0;
00142 if (ec_elist.head == ec_elist.tail)
00143 ec_elist.tail++;
00144 if (ec_elist.tail > EC_MAXELIST)
00145 ec_elist.tail = 0;
00146 EcatError = TRUE;
00147 }
00148
00154 boolean ec_poperror(ec_errort *Ec)
00155 {
00156 boolean notEmpty = (ec_elist.head != ec_elist.tail);
00157
00158 *Ec = ec_elist.Error[ec_elist.tail];
00159 ec_elist.Error[ec_elist.tail].Signal = FALSE;
00160 if (notEmpty)
00161 {
00162 ec_elist.tail++;
00163 if (ec_elist.tail > EC_MAXELIST)
00164 ec_elist.tail = 0;
00165 }
00166 else
00167 EcatError = FALSE;
00168 return notEmpty;
00169 }
00170
00175 boolean ec_iserror(void)
00176 {
00177 return (ec_elist.head != ec_elist.tail);
00178 }
00179
00187 void ec_packeterror(uint16 Slave, uint16 Index, uint8 SubIdx, uint16 ErrorCode)
00188 {
00189 ec_errort Ec;
00190
00191 gettimeofday(&Ec.Time, 0);
00192 Ec.Slave = Slave;
00193 Ec.Index = Index;
00194 Ec.SubIdx = SubIdx;
00195 EcatError = TRUE;
00196 Ec.Etype = EC_ERR_TYPE_PACKET_ERROR;
00197 Ec.ErrorCode = ErrorCode;
00198 ec_pusherror(&Ec);
00199 }
00200
00210 static void ec_mbxemergencyerror(uint16 Slave, uint16 ErrorCode, uint16 ErrorReg, uint8 b1, uint16 w1, uint16 w2)
00211 {
00212 ec_errort Ec;
00213
00214 gettimeofday(&Ec.Time, 0);
00215 Ec.Slave = Slave;
00216 Ec.Index = 0;
00217 Ec.SubIdx = 0;
00218 Ec.Etype = EC_ERR_TYPE_EMERGENCY;
00219 Ec.ErrorCode = ErrorCode;
00220 Ec.ErrorReg = (uint8)ErrorReg;
00221 Ec.b1 = b1;
00222 Ec.w1 = w1;
00223 Ec.w2 = w2;
00224 ec_pusherror(&Ec);
00225 }
00226
00231 int ec_init(const char * ifname)
00232 {
00233 return ec_setupnic(ifname, FALSE);
00234 }
00235
00241 int ec_init_redundant(const char *ifname, const char *if2name)
00242 {
00243 int rval, zbuf;
00244 ec_etherheadert *ehp;
00245
00246 ec_setupnic(ifname, FALSE);
00247 rval = ec_setupnic(if2name, TRUE);
00248
00249 ehp = (ec_etherheadert *)&ec_txbuf2;
00250 ehp->sa1 = htons(secMAC[0]);
00251 zbuf = 0;
00252 ec_setupdatagram(&ec_txbuf2, EC_CMD_BRD, 0, 0x0000, 0x0000, 2, &zbuf);
00253 ec_txbuflength2 = ETH_HEADERSIZE+ EC_HEADERSIZE + EC_WKCSIZE + 2;
00254
00255 return rval;
00256 }
00257
00260 void ec_close(void)
00261 {
00262 ec_closenic();
00263 }
00264 ;
00265
00273 uint8 ec_siigetbyte(uint16 slave, uint16 address)
00274 {
00275 uint16 configadr, eadr;
00276 uint64 edat;
00277 uint16 mapw, mapb;
00278 int lp, cnt;
00279 uint8 retval;
00280
00281 retval = 0xff;
00282 if (slave != esislave)
00283 {
00284 memset(esimap, 0x00, EC_MAXEEPBITMAP);
00285 esislave = slave;
00286 }
00287 if (address < EC_MAXEEPBUF)
00288 {
00289 mapw = address >> 5;
00290 mapb = address - (mapw << 5);
00291 if (esimap[mapw] & (uint32)(1 << mapb))
00292 {
00293
00294 retval = esibuf[address];
00295 }
00296 else
00297 {
00298
00299 configadr = ec_slave[slave].configadr;
00300 ec_eeprom2master(slave);
00301 eadr = address >> 1;
00302 edat = ec_readeepromFP(configadr, eadr, EC_TIMEOUTEEP);
00303
00304 if (ec_slave[slave].eep_8byte)
00305 {
00306 put_unaligned64(edat, &esibuf[eadr << 1]);
00307 cnt = 8;
00308 }
00309
00310 else
00311 {
00312 put_unaligned32(edat, &esibuf[eadr << 1]);
00313 cnt = 4;
00314 }
00315
00316 mapw = eadr >> 4;
00317 mapb = (eadr << 1) - (mapw << 5);
00318 for (lp = 0; lp < cnt; lp++)
00319 {
00320
00321 esimap[mapw] |= (1 << mapb);
00322 mapb++;
00323 if (mapb > 31)
00324 {
00325 mapb = 0;
00326 mapw++;
00327 }
00328 }
00329 retval = esibuf[address];
00330 }
00331 }
00332
00333 return retval;
00334 }
00335
00341 int16 ec_siifind(uint16 slave, uint16 cat)
00342 {
00343 int16 a;
00344 uint16 p;
00345 uint8 eectl = ec_slave[slave].eep_pdi;
00346
00347 a = ECT_SII_START << 1;
00348
00349 p = ec_siigetbyte(slave, a++);
00350 p += (ec_siigetbyte(slave, a++) << 8);
00351
00352 while ((p != cat) && (p != 0xffff))
00353 {
00354
00355 p = ec_siigetbyte(slave, a++);
00356 p += (ec_siigetbyte(slave, a++) << 8);
00357
00358 a += p << 1;
00359
00360 p = ec_siigetbyte(slave, a++);
00361 p += (ec_siigetbyte(slave, a++) << 8);
00362 }
00363 if (p != cat)
00364 a = 0;
00365
00366 if (eectl)
00367 ec_eeprom2pdi(slave);
00368
00369 return a;
00370 }
00371
00377 void ec_siistring(char *str, uint16 slave, uint16 Sn)
00378 {
00379 uint16 a, i, j, l, n, ba;
00380 char *ptr;
00381 uint8 eectl = ec_slave[slave].eep_pdi;
00382
00383 ptr = str;
00384
00385 a = ec_siifind(slave, ECT_SII_STRING);
00386 if (a > 0)
00387 {
00388 ba = a + 2;
00389 n = ec_siigetbyte(slave, ba++);
00390 if (Sn <= n)
00391 {
00392 for (i = 1; i <= Sn; i++)
00393 {
00394 l = ec_siigetbyte(slave, ba++);
00395 ptr = str;
00396 for (j = 1; j <= l; j++)
00397 {
00398 *ptr = (char)ec_siigetbyte(slave, ba++);
00399 ptr++;
00400 }
00401 }
00402 *ptr = 0;
00403 }
00404 else
00405 {
00406 ptr = str;
00407 *ptr = 0;
00408 }
00409 }
00410 if (eectl)
00411 ec_eeprom2pdi(slave);
00412 }
00413
00419 uint16 ec_siiFMMU(uint16 slave, ec_eepromFMMUt* FMMU)
00420 {
00421 uint16 a;
00422 uint8 eectl = ec_slave[slave].eep_pdi;
00423
00424 FMMU->nFMMU = 0;
00425 FMMU->FMMU0 = 0;
00426 FMMU->FMMU1 = 0;
00427 FMMU->FMMU2 = 0;
00428 FMMU->FMMU3 = 0;
00429 FMMU->Startpos = ec_siifind(slave, ECT_SII_FMMU);
00430
00431 if (FMMU->Startpos > 0)
00432 {
00433 a = FMMU->Startpos;
00434 FMMU->nFMMU = ec_siigetbyte(slave, a++);
00435 FMMU->nFMMU += (ec_siigetbyte(slave, a++) << 8);
00436 FMMU->nFMMU *= 2;
00437 FMMU->FMMU0 = ec_siigetbyte(slave, a++);
00438 FMMU->FMMU1 = ec_siigetbyte(slave, a++);
00439 if (FMMU->nFMMU > 2)
00440 {
00441 FMMU->FMMU2 = ec_siigetbyte(slave, a++);
00442 FMMU->FMMU3 = ec_siigetbyte(slave, a++);
00443 }
00444 }
00445 if (eectl)
00446 ec_eeprom2pdi(slave);
00447 return FMMU->nFMMU;
00448 }
00449
00455 uint16 ec_siiSM(uint16 slave, ec_eepromSMt* SM)
00456 {
00457 uint16 a, w;
00458 uint8 eectl = ec_slave[slave].eep_pdi;
00459
00460 SM->nSM = 0;
00461
00462 SM->Startpos = ec_siifind(slave, ECT_SII_SM);
00463 if (SM->Startpos > 0)
00464 {
00465 a = SM->Startpos;
00466 w = ec_siigetbyte(slave, a++);
00467 w += (ec_siigetbyte(slave, a++) << 8);
00468 SM->nSM = (w / 4);
00469 SM->PhStart = ec_siigetbyte(slave, a++);
00470 SM->PhStart += (ec_siigetbyte(slave, a++) << 8);
00471 SM->Plength = ec_siigetbyte(slave, a++);
00472 SM->Plength += (ec_siigetbyte(slave, a++) << 8);
00473 SM->Creg = ec_siigetbyte(slave, a++);
00474 SM->Sreg = ec_siigetbyte(slave, a++);
00475 SM->Activate = ec_siigetbyte(slave, a++);
00476 SM->PDIctrl = ec_siigetbyte(slave, a++);
00477 }
00478 if (eectl)
00479 ec_eeprom2pdi(slave);
00480 return SM->nSM;
00481 }
00482
00489 uint16 ec_siiSMnext(uint16 slave, ec_eepromSMt* SM, uint16 n)
00490 {
00491 uint16 a;
00492 uint16 retVal = 0;
00493 uint8 eectl = ec_slave[slave].eep_pdi;
00494
00495 if (n < SM->nSM)
00496 {
00497 a = SM->Startpos + 2 + (n * 8);
00498 SM->PhStart = ec_siigetbyte(slave, a++);
00499 SM->PhStart += (ec_siigetbyte(slave, a++) << 8);
00500 SM->Plength = ec_siigetbyte(slave, a++);
00501 SM->Plength += (ec_siigetbyte(slave, a++) << 8);
00502 SM->Creg = ec_siigetbyte(slave, a++);
00503 SM->Sreg = ec_siigetbyte(slave, a++);
00504 SM->Activate = ec_siigetbyte(slave, a++);
00505 SM->PDIctrl = ec_siigetbyte(slave, a++);
00506 retVal = 1;
00507 }
00508 if (eectl)
00509 ec_eeprom2pdi(slave);
00510 return retVal;
00511 }
00512
00519 int ec_siiPDO(uint16 slave, ec_eepromPDOt* PDO, uint8 t)
00520 {
00521 uint16 a, w, c, e, er, Size;
00522 uint8 eectl = ec_slave[slave].eep_pdi;
00523
00524 Size = 0;
00525 PDO->nPDO = 0;
00526 PDO->Length = 0;
00527 PDO->Index[1] = 0;
00528 for (c = 0; c < EC_MAXSM; c++)
00529 PDO->SMbitsize[c] = 0;
00530 if (t > 1)
00531 t = 1;
00532 PDO->Startpos = ec_siifind(slave, ECT_SII_PDO + t);
00533 if (PDO->Startpos > 0)
00534 {
00535 a = PDO->Startpos;
00536 w = ec_siigetbyte(slave, a++);
00537 w += (ec_siigetbyte(slave, a++) << 8);
00538 PDO->Length = w;
00539 c = 1;
00540
00541 do
00542 {
00543 PDO->nPDO++;
00544 PDO->Index[PDO->nPDO] = ec_siigetbyte(slave, a++);
00545 PDO->Index[PDO->nPDO] += (ec_siigetbyte(slave, a++) << 8);
00546 PDO->BitSize[PDO->nPDO] = 0;
00547 c++;
00548 e = ec_siigetbyte(slave, a++);
00549 PDO->SyncM[PDO->nPDO] = ec_siigetbyte(slave, a++);
00550 a += 4;
00551 c += 2;
00552 if (PDO->SyncM[PDO->nPDO] < EC_MAXSM)
00553 {
00554
00555 for (er = 1; er <= e; er++)
00556 {
00557 c += 4;
00558 a += 5;
00559 PDO->BitSize[PDO->nPDO] += ec_siigetbyte(slave, a++);
00560 a += 2;
00561 }
00562 PDO->SMbitsize[PDO->SyncM[PDO->nPDO]] += PDO->BitSize[PDO->nPDO];
00563 Size += PDO->BitSize[PDO->nPDO];
00564 c++;
00565 }
00566 else
00567 {
00568 c += 4 * e;
00569 a += 8 * e;
00570 c++;
00571 }
00572 if (PDO->nPDO >= (EC_MAXEEPDO - 1))
00573 c = PDO->Length;
00574 } while (c < PDO->Length);
00575 }
00576 if (eectl)
00577 ec_eeprom2pdi(slave);
00578
00579 return (Size);
00580 }
00581
00585 int ec_readstate(void)
00586 {
00587 uint16 slave, configadr, lowest, rval;
00588 ec_alstatust slstat;
00589
00590 lowest = 0xff;
00591 ec_slave[0].ALstatuscode = 0;
00592 for (slave = 1; slave <= ec_slavecount; slave++)
00593 {
00594 configadr = ec_slave[slave].configadr;
00595 slstat.alstatus = 0;
00596 slstat.alstatuscode = 0;
00597 ec_FPRD(configadr, ECT_REG_ALSTAT, sizeof(slstat), &slstat, EC_TIMEOUTRET);
00598 rval = etohs(slstat.alstatus);
00599 ec_slave[slave].ALstatuscode = etohs(slstat.alstatuscode);
00600 if (rval < lowest)
00601 lowest = rval;
00602 ec_slave[slave].state = rval;
00603 ec_slave[0].ALstatuscode |= ec_slave[slave].ALstatuscode;
00604 }
00605 ec_slave[0].state = lowest;
00606
00607 return lowest;
00608 }
00609
00615 int ec_writestate(uint16 slave)
00616 {
00617 uint16 configadr, slstate;
00618
00619 if (slave == 0)
00620 {
00621 slstate = htoes(ec_slave[slave].state);
00622 ec_BWR(0, ECT_REG_ALCTL, sizeof(slstate), &slstate, EC_TIMEOUTRET);
00623 }
00624 else
00625 {
00626 configadr = ec_slave[slave].configadr;
00627 ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(ec_slave[slave].state), EC_TIMEOUTRET);
00628 }
00629 return 0;
00630 }
00631
00639 uint16 ec_statecheck(uint16 slave, uint16 reqstate, int timeout)
00640 {
00641 uint16 configadr, state, rval;
00642 struct timeval tv1, tv2, tve;
00643 ec_alstatust slstat;
00644
00645 if (slave > ec_slavecount)
00646 return 0;
00647 gettimeofday(&tv1, 0);
00648 tv2.tv_sec = 0;
00649 tv2.tv_usec = timeout;
00650 timeradd(&tv1, &tv2, &tve);
00651 configadr = ec_slave[slave].configadr;
00652 do
00653 {
00654 if (slave < 1)
00655 {
00656 rval = 0;
00657 ec_BRD(0, ECT_REG_ALSTAT, sizeof(rval), &rval, EC_TIMEOUTRET);
00658 rval = etohs(rval);
00659 }
00660 else
00661 {
00662 slstat.alstatus = 0;
00663 slstat.alstatuscode = 0;
00664 ec_FPRD(configadr, ECT_REG_ALSTAT, sizeof(slstat), &slstat, EC_TIMEOUTRET);
00665 rval = etohs(slstat.alstatus);
00666 ec_slave[slave].ALstatuscode = etohs(slstat.alstatuscode);
00667 }
00668 state = rval & 0x000f;
00669 if (state != reqstate)
00670 usleep(1000);
00671 gettimeofday(&tv2, 0);
00672 } while ((state != reqstate) && timercmp(&tv2, &tve, <));
00673 ec_slave[slave].state = rval;
00674
00675 return state;
00676 }
00677
00683 uint8 ec_nextmbxcnt(uint8 cnt)
00684 {
00685 cnt++;
00686 if (cnt > 7)
00687 cnt = 1;
00688 return cnt;
00689 }
00690
00694 void ec_clearmbx(ec_mbxbuft *Mbx)
00695 {
00696 memset(*Mbx, 0x00, EC_MAXMBX);
00697 }
00698
00704 int ec_mbxempty(uint16 slave, int timeout)
00705 {
00706 uint16 configadr;
00707 uint8 SMstat;
00708 int wkc;
00709 struct timeval tv1, tv2, tve;
00710
00711 gettimeofday(&tv1, 0);
00712 tv2.tv_sec = 0;
00713 tv2.tv_usec = timeout;
00714 timeradd(&tv1, &tv2, &tve);
00715 configadr = ec_slave[slave].configadr;
00716 do
00717 {
00718 wkc = ec_FPRD(configadr, ECT_REG_SM0STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00719 SMstat = etohs(SMstat);
00720 if (((SMstat & 0x08) != 0) && (timeout > EC_LOCALDELAY))
00721 usleep(EC_LOCALDELAY);
00722 gettimeofday(&tv2, 0);
00723 } while (((wkc <= 0) || ((SMstat & 0x08) != 0)) && timercmp(&tv2, &tve, <));
00724 if ((wkc > 0) && ((SMstat & 0x08) == 0))
00725 return 1;
00726 return 0;
00727 }
00728
00735 int ec_mbxsend(uint16 slave, ec_mbxbuft *mbx, int timeout)
00736 {
00737 uint16 mbxwo, mbxl, configadr;
00738 int wkc;
00739
00740 wkc = 0;
00741 configadr = ec_slave[slave].configadr;
00742 mbxl = ec_slave[slave].mbx_l;
00743 if (mbxl > 0)
00744 {
00745 if (ec_mbxempty(slave, timeout))
00746 {
00747 mbxwo = ec_slave[slave].mbx_wo;
00748
00749 wkc = ec_FPWR(configadr, mbxwo, mbxl, mbx, EC_TIMEOUTRET);
00750 }
00751 else
00752 wkc = 0;
00753 }
00754
00755 return wkc;
00756 }
00757
00765 int ec_mbxreceive(uint16 slave, ec_mbxbuft *mbx, int timeout)
00766 {
00767 uint16 mbxro, mbxl, configadr;
00768 int wkc = 0;
00769 int wkc2;
00770 uint16 SMstat;
00771 uint8 SMcontr;
00772 ec_mbxheadert *mbxh;
00773 ec_emcyt *EMp;
00774 struct timeval mtv1, mtv2, mtve;
00775
00776 configadr = ec_slave[slave].configadr;
00777 mbxl = ec_slave[slave].mbx_rl;
00778 if (mbxl > 0)
00779 {
00780 gettimeofday(&mtv1, 0);
00781 mtv2.tv_sec = 0;
00782 mtv2.tv_usec = timeout;
00783 timeradd(&mtv1, &mtv2, &mtve);
00784 wkc = 0;
00785 do
00786 {
00787 wkc = ec_FPRD(configadr, ECT_REG_SM1STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00788 SMstat = etohs(SMstat);
00789 if (((SMstat & 0x08) == 0) && (timeout > EC_LOCALDELAY))
00790 usleep(EC_LOCALDELAY);
00791 gettimeofday(&mtv2, 0);
00792 } while (((wkc <= 0) || ((SMstat & 0x08) == 0)) && timercmp(&mtv2, &mtve, <));
00793
00794 if ((wkc > 0) && ((SMstat & 0x08) > 0))
00795 {
00796 mbxro = ec_slave[slave].mbx_ro;
00797 mbxh = (ec_mbxheadert *)mbx;
00798 do
00799 {
00800 wkc = ec_FPRD(configadr, mbxro, mbxl, mbx, EC_TIMEOUTRET);
00801
00802 if ((wkc > 0) && ((mbxh->mbxtype & 0x0f) == 0x03))
00803 {
00804 EMp = (ec_emcyt *)mbx;
00805 if ((etohs(EMp->CANOpen) >> 12) == 0x01)
00806 {
00807 ec_mbxemergencyerror(slave, etohs(EMp->ErrorCode), EMp->ErrorReg, EMp->bData, etohs(EMp->w1),
00808 etohs(EMp->w2));
00809 wkc = 0;
00810 }
00811 }
00812 else
00813 {
00814 if (wkc <= 0)
00815 {
00816 SMstat ^= 0x0200;
00817 SMstat = htoes(SMstat);
00818 wkc2 = ec_FPWR(configadr, ECT_REG_SM1STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00819 SMstat = etohs(SMstat);
00820 do
00821 {
00822 wkc2 = ec_FPRD(configadr, ECT_REG_SM1CONTR, sizeof(SMcontr), &SMcontr, EC_TIMEOUTRET);
00823 gettimeofday(&mtv2, 0);
00824 } while (((wkc2 <= 0) || ((SMcontr & 0x02) != (HI_BYTE(SMstat) & 0x02))) && timercmp(&mtv2, &mtve, <));
00825 do
00826 {
00827 wkc2 = ec_FPRD(configadr, ECT_REG_SM1STAT, sizeof(SMstat), &SMstat, EC_TIMEOUTRET);
00828 SMstat = etohs(SMstat);
00829 if (((SMstat & 0x08) == 0) && (timeout > EC_LOCALDELAY))
00830 {
00831 usleep(EC_LOCALDELAY);
00832 }
00833 gettimeofday(&mtv2, 0);
00834 } while (((wkc2 <= 0) || ((SMstat & 0x08) == 0)) && timercmp(&mtv2, &mtve, <));
00835 }
00836 }
00837 } while ((wkc <= 0) && timercmp(&mtv2, &mtve, <));
00838 }
00839 else
00840 wkc = 0;
00841 }
00842
00843 return wkc;
00844 }
00845
00850 void ec_esidump(uint16 slave, uint8 *esibuf, uint8 test)
00851 {
00852 int address, incr;
00853 uint16 configadr;
00854 uint64 *p64;
00855 uint16 *p16;
00856 uint64 edat;
00857 uint8 eectl = ec_slave[slave].eep_pdi;
00858
00859 ec_eeprom2master(slave);
00860 configadr = ec_slave[slave].configadr;
00861 address = ECT_SII_START;
00862 p16 = (uint16*)esibuf;
00863 if (ec_slave[slave].eep_8byte)
00864 incr = 4;
00865 else
00866 incr = 2;
00867 do
00868 {
00869 edat = ec_readeepromFP(configadr, address, EC_TIMEOUTEEP);
00870 p64 = (uint64*)p16;
00871 *p64 = edat;
00872 p16 += incr;
00873 address += incr;
00874 } while ((address <= (EC_MAXEEPBUF >> 1)) && ((uint32)edat != 0xffffffff));
00875
00876 if (eectl)
00877 ec_eeprom2pdi(slave);
00878 }
00879
00886 uint32 ec_readeeprom(uint16 slave, uint16 eeproma, int timeout)
00887 {
00888 uint16 configadr;
00889
00890 ec_eeprom2master(slave);
00891 configadr = ec_slave[slave].configadr;
00892 return (ec_readeepromFP(configadr, eeproma, timeout));
00893 }
00894
00902 int ec_writeeeprom(uint16 slave, uint16 eeproma, uint16 data, int timeout)
00903 {
00904 uint16 configadr;
00905
00906 ec_eeprom2master(slave);
00907 configadr = ec_slave[slave].configadr;
00908 return (ec_writeeepromFP(configadr, eeproma, data, timeout));
00909 }
00910
00915 int ec_eeprom2master(uint16 slave)
00916 {
00917 int wkc = 1, cnt = 0;
00918 uint16 configadr;
00919 uint8 eepctl;
00920
00921 if (ec_slave[slave].eep_pdi)
00922 {
00923 configadr = ec_slave[slave].configadr;
00924 eepctl = 2;
00925 do
00926 {
00927 wkc = ec_FPWR(configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl, EC_TIMEOUTRET);
00928 } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
00929 eepctl = 0;
00930 cnt = 0;
00931 do
00932 {
00933 wkc = ec_FPWR(configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl, EC_TIMEOUTRET);
00934 } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
00935 ec_slave[slave].eep_pdi = 0;
00936 }
00937
00938 return wkc;
00939 }
00940
00945 int ec_eeprom2pdi(uint16 slave)
00946 {
00947 int wkc = 1, cnt = 0;
00948 uint16 configadr;
00949 uint8 eepctl;
00950
00951 if (!ec_slave[slave].eep_pdi)
00952 {
00953 configadr = ec_slave[slave].configadr;
00954 eepctl = 1;
00955 do
00956 {
00957 wkc = ec_FPWR(configadr, ECT_REG_EEPCFG, sizeof(eepctl), &eepctl, EC_TIMEOUTRET);
00958 } while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
00959 ec_slave[slave].eep_pdi = 1;
00960 }
00961
00962 return wkc;
00963 }
00964
00965 uint16 ec_eeprom_waitnotbusyAP(uint16 aiadr, uint16 *estat, int timeout)
00966 {
00967 int wkc, cnt = 0, retval = 0;
00968 struct timeval tv1, tv2, tve;
00969
00970 gettimeofday(&tv1, 0);
00971 tv2.tv_sec = 0;
00972 tv2.tv_usec = timeout;
00973 timeradd(&tv1, &tv2, &tve);
00974 do
00975 {
00976 if (cnt++)
00977 usleep(EC_LOCALDELAY);
00978 wkc = ec_APRD(aiadr, ECT_REG_EEPSTAT, sizeof(*estat), estat, EC_TIMEOUTRET);
00979 *estat = etohs(*estat);
00980 gettimeofday(&tv2, 0);
00981 } while (((wkc <= 0) || ((*estat & EC_ESTAT_BUSY) > 0)) && (timercmp(&tv2, &tve, <)));
00982 if ((*estat & EC_ESTAT_BUSY) == 0)
00983 retval = 1;
00984 return retval;
00985 }
00986
00993 uint64 ec_readeepromAP(uint16 aiadr, uint16 eeproma, int timeout)
00994 {
00995 uint16 estat;
00996 uint32 edat32;
00997 uint64 edat64;
00998 ec_eepromt ed;
00999 int wkc, cnt, nackcnt = 0;
01000 struct timeval tv1, tv2, tve;
01001
01002 gettimeofday(&tv1, 0);
01003 tv2.tv_sec = 0;
01004 tv2.tv_usec = timeout;
01005 timeradd(&tv1, &tv2, &tve);
01006 edat64 = 0;
01007 edat32 = 0;
01008 if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01009 {
01010 if (estat & EC_ESTAT_EMASK)
01011 {
01012 estat = htoes(EC_ECMD_NOP);
01013 wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01014 }
01015
01016 do
01017 {
01018 ed.comm = htoes(EC_ECMD_READ);
01019 ed.addr = htoes(eeproma);
01020 ed.d2 = 0x0000;
01021 cnt = 0;
01022 do
01023 wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01024 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01025 if (wkc)
01026 {
01027 usleep(EC_LOCALDELAY);
01028 estat = 0x0000;
01029 if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01030 {
01031 if (estat & EC_ESTAT_NACK)
01032 {
01033 nackcnt++;
01034 usleep(EC_LOCALDELAY * 5);
01035 }
01036 else
01037 {
01038 nackcnt = 0;
01039 if (estat & EC_ESTAT_R64)
01040 {
01041 cnt = 0;
01042 do
01043 wkc = ec_APRD(aiadr, ECT_REG_EEPDAT, sizeof(edat64), &edat64, EC_TIMEOUTRET);
01044 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01045 }
01046 else
01047 {
01048 cnt = 0;
01049 do
01050 wkc = ec_APRD(aiadr, ECT_REG_EEPDAT, sizeof(edat32), &edat32, EC_TIMEOUTRET);
01051 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01052 edat64 = (uint64)edat32;
01053 }
01054 }
01055 }
01056 }
01057 } while ((nackcnt > 0) && (nackcnt < 3));
01058 }
01059 return edat64;
01060 }
01061
01069 int ec_writeeepromAP(uint16 aiadr, uint16 eeproma, uint16 data, int timeout)
01070 {
01071 uint16 estat;
01072 ec_eepromt ed;
01073 int wkc, rval = 0, cnt = 0, nackcnt = 0;
01074 struct timeval tv1, tv2, tve;
01075
01076 gettimeofday(&tv1, 0);
01077 tv2.tv_sec = 0;
01078 tv2.tv_usec = timeout;
01079 timeradd(&tv1, &tv2, &tve);
01080 if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01081 {
01082 if (estat & EC_ESTAT_EMASK)
01083 {
01084 estat = htoes(EC_ECMD_NOP);
01085 wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01086 }
01087 do
01088 {
01089 cnt = 0;
01090 do
01091 wkc = ec_APWR(aiadr, ECT_REG_EEPDAT, sizeof(data), &data, EC_TIMEOUTRET);
01092 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01093
01094 ed.comm = EC_ECMD_WRITE;
01095 ed.addr = eeproma;
01096 ed.d2 = 0x0000;
01097 cnt = 0;
01098 do
01099 wkc = ec_APWR(aiadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01100 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01101 if (wkc)
01102 {
01103 usleep(EC_LOCALDELAY * 2);
01104 estat = 0x0000;
01105 if (ec_eeprom_waitnotbusyAP(aiadr, &estat, timeout))
01106 {
01107 if (estat & EC_ESTAT_NACK)
01108 {
01109 nackcnt++;
01110 usleep(EC_LOCALDELAY * 5);
01111 }
01112 else
01113 {
01114 nackcnt = 0;
01115 rval = 1;
01116 }
01117 }
01118 }
01119
01120 } while ((nackcnt > 0) && (nackcnt < 3));
01121 }
01122 return rval;
01123 }
01124
01125 uint16 ec_eeprom_waitnotbusyFP(uint16 configadr, uint16 *estat, int timeout)
01126 {
01127 int wkc, cnt = 0, retval = 0;
01128 struct timeval tv1, tv2, tve;
01129
01130 gettimeofday(&tv1, 0);
01131 tv2.tv_sec = 0;
01132 tv2.tv_usec = timeout;
01133 timeradd(&tv1, &tv2, &tve);
01134 do
01135 {
01136 if (cnt++)
01137 usleep(EC_LOCALDELAY);
01138 wkc = ec_FPRD(configadr, ECT_REG_EEPSTAT, sizeof(*estat), estat, EC_TIMEOUTRET);
01139 *estat = etohs(*estat);
01140 gettimeofday(&tv2, 0);
01141 } while (((wkc <= 0) || ((*estat & EC_ESTAT_BUSY) > 0)) && (timercmp(&tv2, &tve, <)));
01142 if ((*estat & EC_ESTAT_BUSY) == 0)
01143 retval = 1;
01144 return retval;
01145 }
01146
01153 uint64 ec_readeepromFP(uint16 configadr, uint16 eeproma, int timeout)
01154 {
01155 uint16 estat;
01156 uint32 edat32;
01157 uint64 edat64;
01158 ec_eepromt ed;
01159 int wkc, cnt, nackcnt = 0;
01160 struct timeval tv1, tv2, tve;
01161
01162 gettimeofday(&tv1, 0);
01163 tv2.tv_sec = 0;
01164 tv2.tv_usec = timeout;
01165 timeradd(&tv1, &tv2, &tve);
01166 edat64 = 0;
01167 edat32 = 0;
01168 if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01169 {
01170 if (estat & EC_ESTAT_EMASK)
01171 {
01172 estat = htoes(EC_ECMD_NOP);
01173 wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01174 }
01175
01176 do
01177 {
01178 ed.comm = htoes(EC_ECMD_READ);
01179 ed.addr = htoes(eeproma);
01180 ed.d2 = 0x0000;
01181 cnt = 0;
01182 do
01183 wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01184 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01185 if (wkc)
01186 {
01187 usleep(EC_LOCALDELAY);
01188 estat = 0x0000;
01189 if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01190 {
01191 if (estat & EC_ESTAT_NACK)
01192 {
01193 nackcnt++;
01194 usleep(EC_LOCALDELAY * 5);
01195 }
01196 else
01197 {
01198 nackcnt = 0;
01199 if (estat & EC_ESTAT_R64)
01200 {
01201 cnt = 0;
01202 do
01203 wkc = ec_FPRD(configadr, ECT_REG_EEPDAT, sizeof(edat64), &edat64, EC_TIMEOUTRET);
01204 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01205 }
01206 else
01207 {
01208 cnt = 0;
01209 do
01210 wkc = ec_FPRD(configadr, ECT_REG_EEPDAT, sizeof(edat32), &edat32, EC_TIMEOUTRET);
01211 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01212 edat64 = (uint64)edat32;
01213 }
01214 }
01215 }
01216 }
01217 } while ((nackcnt > 0) && (nackcnt < 3));
01218 }
01219 return edat64;
01220 }
01221
01229 int ec_writeeepromFP(uint16 configadr, uint16 eeproma, uint16 data, int timeout)
01230 {
01231 uint16 estat;
01232 ec_eepromt ed;
01233 int wkc, rval = 0, cnt = 0, nackcnt = 0;
01234 struct timeval tv1, tv2, tve;
01235
01236 gettimeofday(&tv1, 0);
01237 tv2.tv_sec = 0;
01238 tv2.tv_usec = timeout;
01239 timeradd(&tv1, &tv2, &tve);
01240 if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01241 {
01242 if (estat & EC_ESTAT_EMASK)
01243 {
01244 estat = htoes(EC_ECMD_NOP);
01245 wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01246 }
01247 do
01248 {
01249 cnt = 0;
01250 do
01251 wkc = ec_FPWR(configadr, ECT_REG_EEPDAT, sizeof(data), &data, EC_TIMEOUTRET);
01252 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01253 ed.comm = EC_ECMD_WRITE;
01254 ed.addr = eeproma;
01255 ed.d2 = 0x0000;
01256 cnt = 0;
01257 do
01258 wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01259 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01260 if (wkc)
01261 {
01262 usleep(EC_LOCALDELAY * 2);
01263 estat = 0x0000;
01264 if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01265 {
01266 if (estat & EC_ESTAT_NACK)
01267 {
01268 nackcnt++;
01269 usleep(EC_LOCALDELAY * 5);
01270 }
01271 else
01272 {
01273 nackcnt = 0;
01274 rval = 1;
01275 }
01276 }
01277 }
01278 } while ((nackcnt > 0) && (nackcnt < 3));
01279 }
01280 return rval;
01281 }
01282
01288 void ec_readeeprom1(uint16 slave, uint16 eeproma)
01289 {
01290 uint16 configadr, estat;
01291 ec_eepromt ed;
01292 int wkc, cnt = 0;
01293
01294 ec_eeprom2master(slave);
01295 configadr = ec_slave[slave].configadr;
01296 if (ec_eeprom_waitnotbusyFP(configadr, &estat, EC_TIMEOUTEEP))
01297 {
01298 if (estat & EC_ESTAT_EMASK)
01299 {
01300 estat = htoes(EC_ECMD_NOP);
01301 wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
01302 }
01303 ed.comm = htoes(EC_ECMD_READ);
01304 ed.addr = htoes(eeproma);
01305 ed.d2 = 0x0000;
01306 do
01307 wkc = ec_FPWR(configadr, ECT_REG_EEPCTL, sizeof(ed), &ed, EC_TIMEOUTRET);
01308 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01309 }
01310 }
01311
01318 uint32 ec_readeeprom2(uint16 slave, int timeout)
01319 {
01320 uint16 estat, configadr;
01321 uint32 edat;
01322 int wkc, cnt = 0;
01323 struct timeval tv1, tv2, tve;
01324
01325 gettimeofday(&tv1, 0);
01326 tv2.tv_sec = 0;
01327 tv2.tv_usec = timeout;
01328 timeradd(&tv1, &tv2, &tve);
01329 configadr = ec_slave[slave].configadr;
01330 edat = 0;
01331 estat = 0x0000;
01332 if (ec_eeprom_waitnotbusyFP(configadr, &estat, timeout))
01333 {
01334 do
01335 wkc = ec_FPRD(configadr, ECT_REG_EEPDAT, sizeof(edat), &edat, EC_TIMEOUTRET);
01336 while ((wkc <= 0) && (cnt++ < EC_DEFAULTRETRIES));
01337 }
01338
01339 return edat;
01340 }
01341
01347 static void ec_pushindex(uint8 idx, void *data, uint16 length)
01348 {
01349 if (ec_idxstack.pushed < EC_MAXBUF)
01350 {
01351 ec_idxstack.idx[ec_idxstack.pushed] = idx;
01352 ec_idxstack.data[ec_idxstack.pushed] = data;
01353 ec_idxstack.length[ec_idxstack.pushed] = length;
01354 ec_idxstack.pushed++;
01355 }
01356 }
01357
01361 static int ec_pullindex(void)
01362 {
01363 int rval = -1;
01364 if (ec_idxstack.pulled < ec_idxstack.pushed)
01365 {
01366 rval = ec_idxstack.pulled;
01367 ec_idxstack.pulled++;
01368 }
01369
01370 return rval;
01371 }
01372
01383 int ec_send_processdata_group(uint8 group)
01384 {
01385 uint32 LogAdr;
01386 uint16 w1, w2;
01387 int length, sublength;
01388 uint8 idx;
01389 int wkc;
01390 void* data;
01391 boolean first = FALSE;
01392 uint16 currentsegment = 0;
01393
01394 wkc = 0;
01395 if (ec_group[group].hasdc)
01396 first = TRUE;
01397 length = ec_group[group].Obytes + ec_group[group].Ibytes;
01398 LogAdr = ec_group[group].logstartaddr;
01399 if (length)
01400 {
01401 if (!group)
01402 {
01403 ec_idxstack.pushed = 0;
01404 ec_idxstack.pulled = 0;
01405 }
01406 wkc = 1;
01407
01408 if (ec_group[group].blockLRW)
01409 {
01410
01411 if (ec_group[group].Ibytes)
01412 {
01413 currentsegment = ec_group[group].Isegment;
01414 data = ec_group[group].inputs;
01415 length = ec_group[group].Ibytes;
01416 LogAdr += ec_group[group].Obytes;
01417
01418 do
01419 {
01420 if (currentsegment == ec_group[group].Isegment)
01421 sublength = ec_group[group].IOsegment[currentsegment++] - ec_group[group].Ioffset;
01422 else
01423 sublength = ec_group[group].IOsegment[currentsegment++];
01424
01425 idx = ec_getindex();
01426 w1 = LO_WORD(LogAdr);
01427 w2 = HI_WORD(LogAdr);
01428 ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LRD, idx, w1, w2, sublength, data);
01429
01430 ec_outframe_red(idx);
01431
01432 ec_pushindex(idx, data, sublength);
01433 length -= sublength;
01434 LogAdr += sublength;
01435 data += sublength;
01436 } while (length && (currentsegment < ec_group[group].nsegments));
01437 }
01438
01439 if (ec_group[group].Obytes)
01440 {
01441 data = ec_group[group].outputs;
01442 length = ec_group[group].Obytes;
01443 LogAdr = ec_group[group].logstartaddr;
01444 currentsegment = 0;
01445
01446 do
01447 {
01448 sublength = ec_group[group].IOsegment[currentsegment++];
01449 if ((length - sublength) < 0)
01450 sublength = length;
01451
01452 idx = ec_getindex();
01453 w1 = LO_WORD(LogAdr);
01454 w2 = HI_WORD(LogAdr);
01455 ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LWR, idx, w1, w2, sublength, data);
01456
01457 ec_outframe_red(idx);
01458
01459 ec_pushindex(idx, data, sublength);
01460 length -= sublength;
01461 LogAdr += sublength;
01462 data += sublength;
01463 } while (length && (currentsegment < ec_group[group].nsegments));
01464 }
01465 }
01466
01467 else
01468 {
01469 if (ec_group[group].Obytes)
01470 data = ec_group[group].outputs;
01471 else
01472 data = ec_group[group].inputs;
01473
01474 do
01475 {
01476 sublength = ec_group[group].IOsegment[currentsegment++];
01477
01478 idx = ec_getindex();
01479 w1 = LO_WORD(LogAdr);
01480 w2 = HI_WORD(LogAdr);
01481 ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LRW, idx, w1, w2, sublength, data);
01482 if (first)
01483 {
01484 ec_DCl = sublength;
01485
01486 ec_DCtO = ec_adddatagram(&ec_txbuf[idx], EC_CMD_FRMW, idx, FALSE,
01487 ec_slave[ec_group[group].DCnext].configadr, ECT_REG_DCSYSTIME, sizeof(ec_DCtime),
01488 &ec_DCtime);
01489 first = FALSE;
01490 }
01491
01492 ec_outframe_red(idx);
01493
01494 ec_pushindex(idx, data, sublength);
01495 length -= sublength;
01496 LogAdr += sublength;
01497 data += sublength;
01498 } while (length && (currentsegment < ec_group[group].nsegments));
01499 }
01500 }
01501
01502 return wkc;
01503 }
01504
01512 int ec_receive_processdata_group(uint8 group, int timeout)
01513 {
01514 int pos, idx;
01515 int wkc = 0, wkc2;
01516 boolean first = FALSE;
01517
01518 if (ec_group[group].hasdc)
01519 first = TRUE;
01520
01521 pos = ec_pullindex();
01522
01523 while (pos >= 0)
01524 {
01525 idx = ec_idxstack.idx[pos];
01526 wkc2 = ec_waitinframe(ec_idxstack.idx[pos], timeout);
01527
01528 if ((wkc2 > EC_NOFRAME) && ((ec_rxbuf[idx][EC_CMDOFFSET]==EC_CMD_LRD) || (ec_rxbuf[idx][EC_CMDOFFSET]==EC_CMD_LRW)))
01529 {
01530 if(first)
01531 {
01532 memcpy(ec_idxstack.data[pos], &ec_rxbuf[idx][EC_HEADERSIZE], ec_DCl);
01533 memcpy(&wkc, &ec_rxbuf[idx][EC_HEADERSIZE + ec_DCl], EC_WKCSIZE);
01534 wkc = etohs(wkc);
01535 memcpy(&ec_DCtime, &ec_rxbuf[idx][ec_DCtO], sizeof(ec_DCtime));
01536 ec_DCtime = etohll(ec_DCtime);
01537 first = FALSE;
01538 }
01539 else
01540 {
01541
01542 memcpy(ec_idxstack.data[pos], &ec_rxbuf[idx][EC_HEADERSIZE], ec_idxstack.length[pos]);
01543 wkc += wkc2;
01544 }
01545 }
01546
01547 ec_setbufstat(idx, EC_BUF_EMPTY);
01548
01549 pos = ec_pullindex();
01550 }
01551
01552 return wkc;
01553 }
01554
01555 int ec_send_processdata(void)
01556 {
01557 return ec_send_processdata_group(0);
01558 }
01559
01560 int ec_receive_processdata(int timeout)
01561 {
01562 return ec_receive_processdata_group(0, timeout);
01563 }