/** * send_mbx send a message to a youbot motor slave. * * @param gripper 1 to address the gripper, 0 otherwise * @param instr_nr command number (GAP, SAP, ...) * @param param_nr type number * @param slave_nr slave index * @param bank_nr mostly zero. Motor or Bank number * @param value value to send and location to store result. * * @return 0 if Ok, -1 otherwise. */ int send_mbx(int gripper, uint8_t instr_nr, uint8_t param_nr, uint16_t slave_nr, uint8_t bank_nr, int32_t *value) { int ret=-1; char* msg; ec_mbxbuft mbx_out, mbx_in; mbx_out[0] = (gripper) ? 1 : 0; mbx_out[1] = instr_nr; mbx_out[2] = param_nr; mbx_out[3] = bank_nr; /* TODO: replace with htobe32 */ mbx_out[4] = (uint32)(*value >> 24); mbx_out[5] = (uint32)(*value >> 16); mbx_out[6] = (uint32)(*value >> 8); mbx_out[7] = (uint32)(*value & 0xff); /* DBG("sending send mbx (gripper:%d, instr_nr=%d, param_nr=%d, slave_nr=%d, bank_nr=%d, value=%d", */ /* gripper, instr_nr, param_nr, slave_nr, bank_nr, *value); */ if (ec_mbxsend(slave_nr, &mbx_out, EC_TIMEOUTTXM) <= 0) { ERR("failed to send mbx (gripper:%d, instr_nr=%d, param_nr=%d, slave_nr=%d, bank_nr=%d, value=%d", gripper, instr_nr, param_nr, slave_nr, bank_nr, *value); goto out; } if (ec_mbxreceive(slave_nr, &mbx_in, EC_TIMEOUTRXM) <= 0) { ERR("failed to receive mbx (gripper:%d, instr_nr=%d, param_nr=%d, slave_nr=%d, bank_nr=%d, value=%d", gripper, instr_nr, param_nr, slave_nr, bank_nr, *value); goto out; } *value = (mbx_in[4] << 24 | mbx_in[5] << 16 | mbx_in[6] << 8 | mbx_in[7]); switch(((int) mbx_in[2])) { case YB_MBX_STAT_OK: goto out_ok; case YB_MBX_STAT_INVALID_CMD: msg="invalid command"; break; case YB_MBX_STAT_WRONG_TYPE: msg="wrong type"; break; case YB_MBX_STAT_EINVAL: msg="invalid value"; break; case YB_MBX_STAT_EEPROM_LOCKED: msg="Configuration EEPROM locked"; break; case YB_MBX_STAT_CMD_UNAVAILABLE: msg="Command not available"; break; case YB_MBX_STAT_PARAM_PWDPROT: msg="Parameter is password protected"; break; default: msg="unkown error"; } if(((int) mbx_in[2]) != 100) { ERR("receiving mbx failed: module=%d, status=%d, command=%d, value=%d: %s.", mbx_in[1], mbx_in[2], mbx_in[3], *value, msg); goto out; } out_ok: ret=0; out: return ret; }
///sends the mailbox Messages which have been stored in the buffer ///@param mailboxMsg ethercat mailbox message bool EthercatMaster::sendMailboxMessage(const YouBotSlaveMailboxMsg& mailboxMsg) { // Bouml preserved body begin 00052F71 // LOG(trace) << "send mailbox message (buffer two) slave " << mailboxMsg.getSlaveNo(); mailboxBufferSend[0] = mailboxMsg.stctOutput.moduleAddress; mailboxBufferSend[1] = mailboxMsg.stctOutput.commandNumber; mailboxBufferSend[2] = mailboxMsg.stctOutput.typeNumber; mailboxBufferSend[3] = mailboxMsg.stctOutput.motorNumber; mailboxBufferSend[4] = mailboxMsg.stctOutput.value >> 24; mailboxBufferSend[5] = mailboxMsg.stctOutput.value >> 16; mailboxBufferSend[6] = mailboxMsg.stctOutput.value >> 8; mailboxBufferSend[7] = mailboxMsg.stctOutput.value & 0xff; if (ec_mbxsend(mailboxMsg.getSlaveNo(), &mailboxBufferSend, mailboxTimeout)) { return true; } else { return false; } // Bouml preserved body end 00052F71 }
/** SoE write, blocking. * * The IDN object of the selected slave and DriveNo is written. If a response * is larger than the mailbox size then the response is segmented. * * @param[in] slave = Slave number * @param[in] driveNo = Drive number in slave * @param[in] elementflags = Flags to select what properties of IDN are to be transfered. * @param[in] idn = IDN. * @param[in] psize = Size in bytes of parameter buffer. * @param[out] p = Pointer to parameter buffer * @param[in] timeout = Timeout in us, standard is EC_TIMEOUTRXM * @return Workcounter from last slave response */ int ec_SoEwrite(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout) { ec_SoEt *SoEp, *aSoEp; uint16 framedatasize, maxdata; int wkc; uint8 *mp; uint8 *hp; uint16 *errorcode; ec_mbxbuft MbxIn, MbxOut; uint8 cnt; boolean NotLast; ec_clearmbx(&MbxIn); /* Empty slave out mailbox if something is in. Timeout set to 0 */ wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0); ec_clearmbx(&MbxOut); aSoEp = (ec_SoEt *)&MbxIn; SoEp = (ec_SoEt *)&MbxOut; SoEp->MbxHeader.address = htoes(0x0000); SoEp->MbxHeader.priority = 0x00; SoEp->opCode = ECT_SOE_WRITEREQ; SoEp->error = 0; SoEp->driveNo = driveNo; SoEp->elementflags = elementflags; hp = p; mp = (uint8 *)&MbxOut + sizeof(ec_SoEt); maxdata = ec_slave[slave].mbx_l - sizeof(ec_SoEt); NotLast = TRUE; while (NotLast) { framedatasize = psize; NotLast = FALSE; SoEp->idn = htoes(idn); SoEp->incomplete = 0; if (framedatasize > maxdata) { framedatasize = maxdata; /* segmented transfer needed */ NotLast = TRUE; SoEp->incomplete = 1; SoEp->fragmentsleft = psize / maxdata; } SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert) + framedatasize); /* get new mailbox counter, used for session handle */ cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt); ec_slave[slave].mbx_cnt = cnt; SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */ /* copy parameter data to mailbox */ memcpy(mp, hp, framedatasize); hp += framedatasize; psize -= framedatasize; /* send SoE request to slave */ wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc > 0) /* succeeded to place mailbox in slave ? */ { if (!NotLast || !ec_mbxempty(slave, timeout)) { /* clean mailboxbuffer */ ec_clearmbx(&MbxIn); /* read slave response */ wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout); if (wkc > 0) /* succeeded to read slave response ? */ { NotLast = FALSE; /* slave response should be SoE, WriteRes */ if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_WRITERES) && (aSoEp->error == 0) && (aSoEp->driveNo == driveNo) && (aSoEp->elementflags == elementflags)) { /* SoE write succeeded */ } /* other slave response */ else { if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES) && (aSoEp->error == 1)) { mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16)); errorcode = (uint16 *)mp; ec_SoEerror(slave, idn, *errorcode); } else { ec_packeterror(slave, idn, 0, 1); /* Unexpected frame returned */ } wkc = 0; } } else { ec_packeterror(slave, idn, 0, 4); /* no response */ } } } } return wkc; }
/** SoE read, blocking. * * The IDN object of the selected slave and DriveNo is read. If a response * is larger than the mailbox size then the response is segmented. The function * will combine all segments and copy them to the parameter buffer. * * @param[in] slave = Slave number * @param[in] driveNo = Drive number in slave * @param[in] elementflags = Flags to select what properties of IDN are to be transfered. * @param[in] idn = IDN. * @param[in,out] psize = Size in bytes of parameter buffer, returns bytes read from SoE. * @param[out] p = Pointer to parameter buffer * @param[in] timeout = Timeout in us, standard is EC_TIMEOUTRXM * @return Workcounter from last slave response */ int ec_SoEread(uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout) { ec_SoEt *SoEp, *aSoEp; uint16 totalsize, framedatasize; int wkc; uint8 *bp; uint8 *mp; uint16 *errorcode; ec_mbxbuft MbxIn, MbxOut; uint8 cnt; boolean NotLast; ec_clearmbx(&MbxIn); /* Empty slave out mailbox if something is in. Timeout set to 0 */ wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0); ec_clearmbx(&MbxOut); aSoEp = (ec_SoEt *)&MbxIn; SoEp = (ec_SoEt *)&MbxOut; SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert)); SoEp->MbxHeader.address = htoes(0x0000); SoEp->MbxHeader.priority = 0x00; /* get new mailbox count value, used as session handle */ cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt); ec_slave[slave].mbx_cnt = cnt; SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */ SoEp->opCode = ECT_SOE_READREQ; SoEp->incomplete = 0; SoEp->error = 0; SoEp->driveNo = driveNo; SoEp->elementflags = elementflags; SoEp->idn = htoes(idn); totalsize = 0; bp = p; mp = (uint8 *)&MbxIn + sizeof(ec_SoEt); NotLast = TRUE; /* send SoE request to slave */ wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc > 0) /* succeeded to place mailbox in slave ? */ { while (NotLast) { /* clean mailboxbuffer */ ec_clearmbx(&MbxIn); /* read slave response */ wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout); if (wkc > 0) /* succeeded to read slave response ? */ { /* slave response should be SoE, ReadRes */ if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES) && (aSoEp->error == 0) && (aSoEp->driveNo == driveNo) && (aSoEp->elementflags == elementflags)) { framedatasize = etohs(aSoEp->MbxHeader.length) - sizeof(ec_SoEt) + sizeof(ec_mbxheadert); totalsize += framedatasize; /* Does parameter fit in parameter buffer ? */ if (totalsize <= *psize) { /* copy parameter data in parameter buffer */ memcpy(bp, mp, framedatasize); /* increment buffer pointer */ bp += framedatasize; } else { framedatasize -= totalsize - *psize; totalsize = *psize; /* copy parameter data in parameter buffer */ if (framedatasize > 0) memcpy(bp, mp, framedatasize); } if (!aSoEp->incomplete) { NotLast = FALSE; *psize = totalsize; } } /* other slave response */ else { NotLast = FALSE; if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES) && (aSoEp->error == 1)) { mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16)); errorcode = (uint16 *)mp; ec_SoEerror(slave, idn, *errorcode); } else { ec_packeterror(slave, idn, 0, 1); /* Unexpected frame returned */ } wkc = 0; } } else { NotLast = FALSE; ec_packeterror(slave, idn, 0, 4); /* no response */ } } } return wkc; }
/** FoE read, blocking. * * @param[in] slave = Slave number. * @param[in] filename = Filename of file to read. * @param[in] password = password. * @param[in,out] psize = Size in bytes of file buffer, returns bytes read from file. * @param[out] p = Pointer to file buffer * @param[in] timeout = Timeout in us, standard is EC_TIMEOUTRXM * @return Workcounter from last slave response */ int ec_FOEread(uint16 slave, char *filename, uint32 password, int *psize, void *p, int timeout) { ec_FOEt *FOEp, *aFOEp; int wkc; int32 dataread = 0; int32 buffersize, packetnumber, prevpacket = 0; uint16 fnsize, maxdata, segmentdata; ec_mbxbuft MbxIn, MbxOut; uint8 cnt; boolean worktodo; buffersize = *psize; ec_clearmbx(&MbxIn); /* Empty slave out mailbox if something is in. Timout set to 0 */ wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, 0); ec_clearmbx(&MbxOut); aFOEp = (ec_FOEt *)&MbxIn; FOEp = (ec_FOEt *)&MbxOut; fnsize = strlen(filename); maxdata = ec_slave[slave].mbx_l - 12; if (fnsize > maxdata) fnsize = maxdata; FOEp->MbxHeader.length = htoes(0x0006 + fnsize); FOEp->MbxHeader.address = htoes(0x0000); FOEp->MbxHeader.priority = 0x00; /* get new mailbox count value, used as session handle */ cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt); ec_slave[slave].mbx_cnt = cnt; FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */ FOEp->OpCode = ECT_FOE_READ; FOEp->Password = htoel(password); /* copy filename in mailbox */ memcpy(&FOEp->FileName[0], filename, fnsize); /* send FoE request to slave */ wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc > 0) /* succeeded to place mailbox in slave ? */ { do { worktodo = FALSE; /* clean mailboxbuffer */ ec_clearmbx(&MbxIn); /* read slave response */ wkc = ec_mbxreceive(slave, (ec_mbxbuft *)&MbxIn, timeout); if (wkc > 0) /* succeeded to read slave response ? */ { /* slave response should be FoE */ if ((aFOEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_FOE) { if(aFOEp->OpCode == ECT_FOE_DATA) { segmentdata = etohs(aFOEp->MbxHeader.length) - 0x0006; packetnumber = etohl(aFOEp->PacketNumber); if ((packetnumber == ++prevpacket) && (dataread + segmentdata <= buffersize)) { memcpy(p, &aFOEp->Data[0], segmentdata); dataread += segmentdata; p += segmentdata; if (segmentdata == maxdata) worktodo = TRUE; FOEp->MbxHeader.length = htoes(0x0006); FOEp->MbxHeader.address = htoes(0x0000); FOEp->MbxHeader.priority = 0x00; /* get new mailbox count value */ cnt = ec_nextmbxcnt(ec_slave[slave].mbx_cnt); ec_slave[slave].mbx_cnt = cnt; FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */ FOEp->OpCode = ECT_FOE_ACK; FOEp->PacketNumber = htoel(packetnumber); /* send FoE ack to slave */ wkc = ec_mbxsend(slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc <= 0) worktodo = FALSE; } else { /* FoE error */ wkc = -EC_ERR_TYPE_FOE_BUF2SMALL; } } else if(aFOEp->OpCode == ECT_FOE_ERROR) { /* FoE error */ wkc = -EC_ERR_TYPE_FOE_ERROR; } else { /* unexpected mailbox received */ wkc = -EC_ERR_TYPE_PACKET_ERROR; } } else { /* unexpected mailbox received */ wkc = -EC_ERR_TYPE_PACKET_ERROR; } *psize = dataread; } } while (worktodo); } return wkc; }