/** LRW "logical memory read / write" primitive plus Clock Distribution. Blocking. * Frame consists of two datagrams, one LRW and one FPRMW. * * @param[in] LogAdr = Logical memory address * @param[in] length = length of databuffer * @param[in,out] data = databuffer to write to and read from slave. * @param[in] DCrs = Distributed Clock reference slave address. * @param[out] DCtime = DC time read from reference slave. * @param[in] timeout = timeout in us, standard is EC_TIMEOUTRET * @return Workcounter or EC_NOFRAME */ int ec_LRWDC(uint32 LogAdr, uint16 length, void *data, uint16 DCrs, int64 *DCtime, int timeout) { uint16 DCtO; uint8 idx; int wkc; uint64 DCtE; idx = ec_getindex(); /* LRW in first datagram */ ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LRW, idx, LO_WORD(LogAdr), HI_WORD(LogAdr), length, data); /* FPRMW in second datagram */ DCtE = htoell(*DCtime); DCtO = ec_adddatagram(&ec_txbuf[idx], EC_CMD_FRMW, idx, FALSE, DCrs, ECT_REG_DCSYSTIME, sizeof(DCtime), &DCtE); wkc = ec_srconfirm(idx, timeout); if ((wkc > 0) && (ec_rxbuf[idx][EC_CMDOFFSET] == EC_CMD_LRW)) { memcpy(data, &ec_rxbuf[idx][EC_HEADERSIZE], length); memcpy(&wkc, &ec_rxbuf[idx][EC_HEADERSIZE + length], EC_WKCSIZE); memcpy(&DCtE, &ec_rxbuf[idx][DCtO], sizeof(*DCtime)); *DCtime = etohll(DCtE); } ec_setbufstat(idx, EC_BUF_EMPTY); return wkc; }
/** LWR "logical memory write" primitive. Blocking. * * @param[in] LogAdr = Logical memory address * @param[in] length = length of databuffer * @param[in] data = databuffer to write to slave. * @param[in] timeout = timeout in us, standard is EC_TIMEOUTRET * @return Workcounter or EC_NOFRAME */ int ec_LWR(uint32 LogAdr, uint16 length, void *data, int timeout) { uint8 idx; int wkc; idx = ec_getindex(); ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LWR, idx, LO_WORD(LogAdr), HI_WORD(LogAdr), length, data); wkc = ec_srconfirm(idx, timeout); ec_setbufstat(idx, EC_BUF_EMPTY); return wkc; }
/** FPWR "configured address write" primitive. Blocking. * * @param[in] ADP = Address Position, slave that has address writes. * @param[in] ADO = Address Offset, slave memory address * @param[in] length = length of databuffer * @param[in] data = databuffer to write to slave. * @param[in] timeout = timeout in us, standard is EC_TIMEOUTRET * @return Workcounter or EC_NOFRAME */ int ec_FPWR(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout) { int wkc; uint8 idx; idx = ec_getindex(); ec_setupdatagram(&ec_txbuf[idx], EC_CMD_FPWR, idx, ADP, ADO, length, data); wkc = ec_srconfirm(idx, timeout); ec_setbufstat(idx, EC_BUF_EMPTY); return wkc; }
/** LRD "logical memory read" primitive. Blocking. * * @param[in] LogAdr = Logical memory address * @param[in] length = length of bytes to read from slave. * @param[out] data = databuffer to read from slave. * @param[in] timeout = timeout in us, standard is EC_TIMEOUTRET * @return Workcounter or EC_NOFRAME */ int ec_LRD(uint32 LogAdr, uint16 length, void *data, int timeout) { uint8 idx; int wkc; idx = ec_getindex(); ec_setupdatagram(&ec_txbuf[idx], EC_CMD_LRD, idx, LO_WORD(LogAdr), HI_WORD(LogAdr), length, data); wkc = ec_srconfirm(idx, timeout); if ((wkc > 0) && (ec_rxbuf[idx][EC_CMDOFFSET]==EC_CMD_LRD)) { memcpy(data, &ec_rxbuf[idx][EC_HEADERSIZE], length); } ec_setbufstat(idx, EC_BUF_EMPTY); return wkc; }
/** FPRD "configured address read" primitive. Blocking. * * @param[in] ADP = Address Position, slave that has address reads. * @param[in] ADO = Address Offset, slave memory address * @param[in] length = length of databuffer * @param[out] data = databuffer to put slave data in * @param[in] timeout = timeout in us, standard is EC_TIMEOUTRET * @return Workcounter or EC_NOFRAME */ int ec_FPRD(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout) { int wkc; uint8 idx; idx = ec_getindex(); ec_setupdatagram(&ec_txbuf[idx], EC_CMD_FPRD, idx, ADP, ADO, length, data); wkc = ec_srconfirm(idx, timeout); if (wkc > 0) { memcpy(data, &ec_rxbuf[idx][EC_HEADERSIZE], length); } ec_setbufstat(idx, EC_BUF_EMPTY); return wkc; }
/** BRW "broadcast write" primitive. Blocking. * * @param[in] ADP = Address Position, normally 0 * @param[in] ADO = Address Offset, slave memory address * @param[in] length = length of databuffer * @param[in] data = databuffer to be written to slaves * @param[in] timeout = timeout in us, standard is EC_TIMEOUTRET * @return Workcounter or EC_NOFRAME */ int ec_BWR(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout) { uint8 idx; int wkc; /* get fresh index */ idx = ec_getindex(); /* setup datagram */ ec_setupdatagram(&ec_txbuf[idx], EC_CMD_BWR, idx, ADP, ADO, length, data); /* send data and wait for answer */ wkc = ec_srconfirm (idx, timeout); /* clear buffer status */ ec_setbufstat(idx, EC_BUF_EMPTY); return wkc; }
int ec_receive_cyclic_packet( int timeout) { int pos, idx; int wkc = 0, wkc2, i, WKCoffset, FrameOffset; uint8 NumCmd; /* get first index */ pos = ec_MY_pullindex(); /* read the same number of frames as send */ while (pos >= 0) { idx = ec_MY_idxstack.idx[pos]; NumCmd=ec_MY_idxstack.NumCmd[pos]; //receive packet and check last wkc (BRD command) wkc2 = ec_waitinframe(idx, timeout); if (wkc2 != ec_MY_idxstack.ExpectedWKC[pos][NumCmd-1]) return -1; //check other wkc (if any) if (ec_MY_idxstack.NumCmd[pos]>1) for (i=0; i<(NumCmd-1);i++) { WKCoffset=ec_MY_idxstack.dataoffset[pos][i]+ec_MY_idxstack.length[pos][i]; wkc=ec_rxbuf[idx][WKCoffset]; if (wkc != ec_MY_idxstack.ExpectedWKC[pos][i]) return -1; } /* check if there is input data in frame */ FrameOffset=EC_CMDOFFSET; for (i=0; i<ec_MY_idxstack.NumCmd[pos];i++) { if((ec_rxbuf[idx][FrameOffset]==EC_CMD_LRD) || (ec_rxbuf[idx][FrameOffset]==EC_CMD_LRW)) /* copy input data back to process data buffer */ memcpy(ec_MY_idxstack.databuffer[pos][i], &ec_rxbuf[idx][ ec_MY_idxstack.dataoffset[pos][i] ], ec_MY_idxstack.length[pos][i]); /*find the position of the next command: end of this datagram (dataoffset+datalength+wkc)*/ FrameOffset=ec_MY_idxstack.dataoffset[pos][i]+ec_MY_idxstack.length[pos][i]+EC_WKCSIZE; } /* release buffer */ ec_setbufstat(idx, EC_BUF_EMPTY); /* get next index */ pos = ec_MY_pullindex(); } return 1; }
/** BRD "broadcast read" primitive. Blocking. * * @param[in] ADP = Address Position, normally 0 * @param[in] ADO = Address Offset, slave memory address * @param[in] length = length of databuffer * @param[out] data = databuffer to put slave data in * @param[in] timeout = timeout in us, standard is EC_TIMEOUTRET * @return Workcounter or EC_NOFRAME */ int ec_BRD(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout) { uint8 idx; int wkc; /* get fresh index */ idx=ec_getindex(); /* setup datagram */ ec_setupdatagram(&ec_txbuf[idx], EC_CMD_BRD, idx, ADP, ADO, length, data); /* send data and wait for answer */ wkc = ec_srconfirm (idx, timeout); if (wkc > 0) { /* copy datagram to data buffer */ memcpy(data, &ec_rxbuf[idx][EC_HEADERSIZE], length); } /* clear buffer status */ ec_setbufstat(idx, EC_BUF_EMPTY); return wkc; }