/** 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; }
/** 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; }
uint8 PrepareCycPacket(uint8 FrameIndex) { boolean more=TRUE; uint8 idx,cmd,i; uint8 *data; uint16 ADP, ADO; uint16 Datalength; uint16 IOoffset; CycFrame[FrameIndex].nInfo=ec_Frame[FrameIndex].NumCmd; CycFrame[FrameIndex].timeout=EC_TIMEOUTRET; //index idx=ec_getindex(); CycFrame[FrameIndex].nIdx=idx; //buffer CycFrame[FrameIndex].FrameBuffer=&ec_txbuf[idx]; CycFrame[FrameIndex].FrameStatus=&ec_rxbufstat[idx]; for (i=0;i<CycFrame[FrameIndex].nInfo;i++) { if (i==(CycFrame[FrameIndex].nInfo-1))//is the last command? more=FALSE; //cmd if (ec_Frame[FrameIndex].FrameCmds[i].state& ec_slave[0].state) cmd=ec_Frame[FrameIndex].FrameCmds[i].cmd; else cmd=EC_CMD_NOP; //length Datalength=ec_Frame[FrameIndex].FrameCmds[i].DataLength; CycFrame[FrameIndex].length[i]=Datalength; //data default data=(uint8 *)malloc(Datalength); memset(data, 0, Datalength); //IO map offset IOoffset=ec_Frame[FrameIndex].FrameCmds[i].Offs+DATAOFFS+FrameIndex*PROCOFFS; //(offset of the command in the frame) + (offset of data in the command) + (Number of Frame * 1536) //address & data switch (cmd) { case EC_CMD_LRD: ADP=LO_WORD(ec_Frame[FrameIndex].FrameCmds[i].laddr); ADO=HI_WORD(ec_Frame[FrameIndex].FrameCmds[i].laddr); CycFrame[FrameIndex].RXdatabuffer[i]=&InProc[IOoffset]; break; case EC_CMD_NOP: ADP=0x0000; ADO=0x0100; break; case EC_CMD_LRW: case EC_CMD_LWR: ADP=LO_WORD(ec_Frame[FrameIndex].FrameCmds[i].laddr); ADO=HI_WORD(ec_Frame[FrameIndex].FrameCmds[i].laddr); if (ec_slave[0].state==EC_STATE_OPERATIONAL) memcpy(data, &OutProc[IOoffset], Datalength); CycFrame[FrameIndex].TXdatabuffer[i]=&OutProc[IOoffset]; CycFrame[FrameIndex].RXdatabuffer[i]=&InProc[IOoffset]; break; default: ADP=ec_Frame[FrameIndex].FrameCmds[i].ADP; ADO=ec_Frame[FrameIndex].FrameCmds[i].ADO; break; } //expected wkc CycFrame[FrameIndex].ExpectedWKC[i]=ec_Frame[FrameIndex].FrameCmds[i].cnt; //build frame if (i==0) //the frame is empty? {ec_setupdatagram(&ec_txbuf[idx], cmd, idx, ADP, ADO, Datalength, data); CycFrame[FrameIndex].DataOffset[i]=DATAOFFS+2;} //in ec_rxbuf is stored the frame without Ethernet header (12 byte), //so data of first datagram are located after EtherCAT header(2 byte) //and datagram header (10 byte) else CycFrame[FrameIndex].DataOffset[i]=ec_adddatagram(&ec_txbuf[idx], cmd, idx, more, ADP, ADO, Datalength, data); free(data); } return idx; }