/** Generate and set EtherCAT datagram in a standard ethernet frame.
 *
 * @param[out] frame	    = framebuffer
 * @param[in] com			= command
 * @param[in] idx			= index used for TX and RX buffers
 * @param[in] ADP			= Address Position
 * @param[in] ADO			= Address Offset
 * @param[in] length		= length of datagram excluding EtherCAT header
 * @param[in] data			= databuffer to be copied in datagram
 * @return always 0
 */
int ec_setupdatagram(void *frame, uint8 com, uint8 idx, uint16 ADP, uint16 ADO, uint16 length, void *data)
{
	ec_comt *datagramP;
	uint8 *frameP;

	frameP = frame;
	/* Ethernet header is preset and fixed in frame buffers
	   EtherCAT header needs to be added after that */
	datagramP = (ec_comt*)&frameP[ETH_HEADERSIZE];
	datagramP->elength = htoes(EC_ECATTYPE + EC_HEADERSIZE + length);
	datagramP->command = com;
	datagramP->index = idx;
	datagramP->ADP = htoes(ADP);
	datagramP->ADO = htoes(ADO);
	datagramP->dlength = htoes(length);
	if (length > 0)
	{
		memcpy(&frameP[ETH_HEADERSIZE + EC_HEADERSIZE], data, length);
	}
	/* set WKC to zero */
	frameP[ETH_HEADERSIZE + EC_HEADERSIZE + length] = 0x00;
	frameP[ETH_HEADERSIZE + EC_HEADERSIZE + length + 1] = 0x00;
	/* set size of frame in buffer array */
	ec_txbuflength[idx] = ETH_HEADERSIZE + EC_HEADERSIZE + EC_WKCSIZE + length;

	return 0;
}
예제 #2
0
/** Recover slave.
 *
 * @param[in] slave	  = slave to recover
 * @return >0 if successful
 */
int ec_recover_slave(uint16 slave)
{
  int rval;
  uint16 ADPh, configadr;

  rval = 0;
  configadr = ec_slave[slave].configadr;
  /* clear possible slaves at EC_TEMPNODE */
  ec_FPWRw(EC_TEMPNODE, ECT_REG_STADR, htoes(0), 0);
  ADPh = (uint16)(1 - slave);
  /* set temporary node address of slave */
  if (ec_APWRw(ADPh, ECT_REG_STADR, htoes(EC_TEMPNODE), EC_TIMEOUTRET) <= 0)
    return 0; /* slave fails to respond */

  ec_slave[slave].configadr = EC_TEMPNODE; /* temporary config address */
  ec_eeprom2master(slave); /* set Eeprom control to master */

  /* check if slave is the same as configured before */
  if ((ec_FPRDw(EC_TEMPNODE, ECT_REG_ALIAS, EC_TIMEOUTRET) == ec_slave[slave].aliasadr)
      && (ec_readeeprom(slave, ECT_SII_ID, EC_TIMEOUTEEP) == ec_slave[slave].eep_id)
      && (ec_readeeprom(slave, ECT_SII_MANUF, EC_TIMEOUTEEP) == ec_slave[slave].eep_man)
      && (ec_readeeprom(slave, ECT_SII_REV, EC_TIMEOUTEEP) == ec_slave[slave].eep_rev))
  {
    rval = ec_FPWRw(EC_TEMPNODE, ECT_REG_STADR, htoes(configadr), EC_TIMEOUTRET);
    ec_slave[slave].configadr = configadr;
  }
  else
  {
    /* slave is not the expected one, remove config address*/
    ec_FPWRw(EC_TEMPNODE, ECT_REG_STADR, htoes(0), EC_TIMEOUTRET);
    ec_slave[slave].configadr = configadr;
  }

  return rval;
}
예제 #3
0
// Encoders
void read_Encoders(void){
  uint16_t                             encoder;

  encoder=*(int16_t*)ENC_1_BASE_ADDRESS;
  miso_packet.encoder_1=htoes(encoder);
  encoder=*(int16_t*)ENC_2_BASE_ADDRESS;
  miso_packet.encoder_2=htoes(encoder);
  encoder=*(int16_t*)ENC_3_BASE_ADDRESS;
  miso_packet.encoder_3=htoes(encoder);
}
예제 #4
0
/** Recover slave.
 *
 * @param[in]  context        = context struct
 * @param[in] slave   = slave to recover
 * @param[in] timeout = local timeout f.e. EC_TIMEOUTRET3
 * @return >0 if successful
 */
int ecx_recover_slave(ecx_contextt *context, uint16 slave, int timeout)
{
   int rval;
   uint16 ADPh, configadr, readadr, wkc;

   rval = 0;
   configadr = context->slavelist[slave].configadr;
   ADPh = (uint16)(1 - slave);
   /* check if we found another slave than the requested */
   readadr = 0xfffe;
   wkc = ecx_APRD(context->port, ADPh, ECT_REG_STADR, sizeof(readadr), &readadr, timeout);
   /* correct slave found, finished */
   if(readadr == configadr)
   {
       return 1;
   }
   /* only try if no config address*/
   if( (wkc > 0) && (readadr == 0))
   {
      /* clear possible slaves at EC_TEMPNODE */
      ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
      /* set temporary node address of slave */
      if(ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(EC_TEMPNODE) , timeout) <= 0)
      {   
         ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
         return 0; /* slave fails to respond */
      }
   
      context->slavelist[slave].configadr = EC_TEMPNODE; /* temporary config address */   
      ecx_eeprom2master(context, slave); /* set Eeprom control to master */         

      /* check if slave is the same as configured before */
      if ((ecx_FPRDw(context->port, EC_TEMPNODE, ECT_REG_ALIAS, timeout) == 
             context->slavelist[slave].aliasadr) &&
          (ecx_readeeprom(context, slave, ECT_SII_ID, EC_TIMEOUTEEP) == 
             context->slavelist[slave].eep_id) &&
          (ecx_readeeprom(context, slave, ECT_SII_MANUF, EC_TIMEOUTEEP) == 
             context->slavelist[slave].eep_man) &&
          (ecx_readeeprom(context, slave, ECT_SII_REV, EC_TIMEOUTEEP) == 
             context->slavelist[slave].eep_rev))
      {
         rval = ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(configadr) , timeout);
         context->slavelist[slave].configadr = configadr;
      }
      else
      {
         /* slave is not the expected one, remove config address*/
         ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , timeout);
         context->slavelist[slave].configadr = configadr;
      }
   }

   return rval;
}
예제 #5
0
void* EC_Header::set(void *ecatHeader, uint8 com, uint8 idx, uint16 ADP, uint16 ADO, uint16 length)
{
	EC_Header* self = static_cast<EC_Header*>(ecatHeader);
	self->elength_ = htoes(EC_ECATTYPE + sizeof(EC_Header)+length);
	self->command_ = com;
	self->index_ = idx;
	self->ADP_ = htoes(ADP);
	self->ADO_ = htoes(ADO);
	self->dlength_ = htoes(length);
	//return self + 1;
	return static_cast<uint8*>(ecatHeader) + sizeof(EC_Header);
}
예제 #6
0
/** Allocate and prepare a mailbox buffer for sending an error message. Take the first Idle
 * buffer from the end. Set Mailbox control state to be used for outbox and fill the mailbox
 * buffer with error information.
 *
 * @param[in] n   = Error number to be sent in mailbox error message.
 */
void MBX_error (uint16_t error)
{
   uint8_t MBXout;
   _MBXerr *mbxerr;
   MBXout = ESC_claimbuffer ();
   if (MBXout)
   {
      mbxerr = (_MBXerr *) & MBX[MBXout];
      mbxerr->mbxheader.length = htoes ((uint16_t) 0x04);
      mbxerr->mbxheader.mbxtype = MBXERR;
      mbxerr->type = htoes ((uint16_t) 0x01);
      mbxerr->detail = htoes (error);
      MBXcontrol[MBXout].state = MBXstate_outreq;
   }
}
예제 #7
0
/** Write AL Status Code to the ESC.
 *
 * @param[in] errornumber   = Write an by EtherCAT specified Error number register 0x134 AL Status Code
 */
void ESC_ALerror (uint16_t errornumber)
{
   uint16_t dummy;
   ESCvar.ALerror = errornumber;
   dummy = htoes (errornumber);
   ESC_write (ESCREG_ALERROR, &dummy, sizeof (dummy), (void *) &ESCvar.ALevent);
}
예제 #8
0
int exec_cmd(EcInitCmdDesc *CmdDesc, uint16 slave)
{int wkc,cnt = 0; 
char i; 
 uint32 data=0;
 
 uint16 retry,estat;
 
   retry=CmdDesc->retries;
      if (CmdDesc->ecHead.ADO==0x502||CmdDesc->ecHead.ADO==0x508)
	    {
		  
		  ec_eeprom2master(slave);
		 
         if (ec_eeprom_waitnotbusyAP(CmdDesc->ecHead.ADP, &estat, EC_TIMEOUTEEP))
	        {
		     if (estat & EC_ESTAT_EMASK) /* error bits are set */
		        {
			     estat = htoes(EC_ECMD_NOP); /* clear error bits */
			     wkc=ec_APWR(CmdDesc->ecHead.ADP, ECT_REG_EEPCTL, sizeof(estat), &estat, EC_TIMEOUTRET);
		        }
		
		    do
			wkc=EcatCmdReq(CmdDesc, &data, slave);
			while ((wkc <= 0) && (cnt++ < retry));
	        }
     
	    }
       EC_PRINT("Command: %s\n",CmdDesc->cmt);
 	 else 
	    {
		 do
		 {
예제 #9
0
/** Allocate and prepare a mailbox buffer. Take the first Idle buffer from the End.
 * Set Mailbox control state to be used for outbox and fill the mailbox buffer with
 * address master and mailbox next CNT value between 1-7.
 *
 * @return The index of Mailbox buffer prepared for outbox. IF no buffer is available return 0.
 */
uint8_t ESC_claimbuffer (void)
{
   _MBX *MB;
   uint8_t n = MBXBUFFERS - 1;
   while ((n > 0) && (MBXcontrol[n].state))
   {
      n--;
   }
   if (n)
   {
      MBXcontrol[n].state = MBXstate_outclaim;
      MB = &MBX[n];
      ESCvar.mbxcnt = (++ESCvar.mbxcnt) & 0x07;
      if (ESCvar.mbxcnt == 0)
      {
         ESCvar.mbxcnt = 1;
      }
      MB->header.address = htoes (0x0000);      // destination is master
      MB->header.channel = 0;
      MB->header.priority = 0;
      MB->header.mbxcnt = ESCvar.mbxcnt;
      ESCvar.txcue++;
   }
   return n;
}
예제 #10
0
/** Reconfigure slave.
 *
 * @param[in]  context        = context struct
 * @param[in] slave   = slave to reconfigure
 * @param[in] timeout = local timeout f.e. EC_TIMEOUTRET3
 * @return Slave state
 */
int ecx_reconfig_slave(ecx_contextt *context, uint16 slave, int timeout)
{
   int state, nSM, FMMUc;
   uint16 configadr;
   
   configadr = context->slavelist[slave].configadr;
   if (ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_INIT) , timeout) <= 0)
   {
      return 0;
   }
   state = 0;
   ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */         
   /* check state change init */
   state = ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE);
   if(state == EC_STATE_INIT)
   {
      /* program all enabled SM */
      for( nSM = 0 ; nSM < EC_MAXSM ; nSM++ )
      {   
         if (context->slavelist[slave].SM[nSM].StartAddr)
         {   
            ecx_FPWR(context->port, configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)),
               sizeof(ec_smt), &context->slavelist[slave].SM[nSM], timeout);
         }
      }
      ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP) , timeout);
      state = ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
      if( state == EC_STATE_PRE_OP)
      {
         /* execute special slave configuration hook Pre-Op to Safe-OP */
         if(context->slavelist[slave].PO2SOconfig) /* only if registered */
         {       
            context->slavelist[slave].PO2SOconfig(slave);         
         }
         ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , timeout); /* set safeop status */
         state = ecx_statecheck(context, slave, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE); /* check state change safe-op */
         /* program configured FMMU */
         for( FMMUc = 0 ; FMMUc < context->slavelist[slave].FMMUunused ; FMMUc++ )
         {   
            ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
               sizeof(ec_fmmut), &context->slavelist[slave].FMMU[FMMUc], timeout);
         }
      }
   }

   return state;      
}
예제 #11
0
/** Write AL Status to the ESC.
 *
 * @param[in] status   = Write current slave status to register 0x130 AL Status
 * reflecting actual state and error indication if present
 */
void ESC_ALstatus (uint8_t status)
{
   uint16_t dummy;
   ESCvar.ALstatus = status;
   dummy = htoes ((uint16_t) status);
   ESC_write (ESCREG_ALSTATUS, &dummy, sizeof (dummy),
              (void *) &ESCvar.ALevent);
}
예제 #12
0
/** EPP periodic task of ESC side EEPROM emulation.
 *
 */
void EEP_process (void)
{
   eep_stat_t stat;

   /* check for eeprom event */
   if ((ESCvar.ALevent & ESCREG_ALEVENT_EEP) == 0) {
     return;
   }

   while (1) {
      /* read eeprom status */
      ESC_read (ESCREG_EECONTSTAT, &stat, sizeof (eep_stat_t));
      stat.contstat.reg = etohs(stat.contstat.reg);
      stat.addr = etohl(stat.addr);

      /* check busy flag, exit if job finished */
      if (!stat.contstat.bits.busy) {
        return;
      }

      /* clear error bits */
      stat.contstat.bits.csumErr = 0;
      stat.contstat.bits.eeLoading = 0;
      stat.contstat.bits.ackErr = 0;
      stat.contstat.bits.wrErr = 0;

      /* process commands */
      switch (stat.contstat.bits.cmdReg) {
         case EEP_CMD_IDLE:
            break;

         case EEP_CMD_READ:
         case EEP_CMD_RELOAD:
            /* handle read request */
            if (EEP_read (stat.addr * sizeof(uint16_t), eep_buf, EEP_READ_SIZE) != 0) {
               stat.contstat.bits.ackErr = 1;
            } else {
               ESC_write (ESCREG_EEDATA, eep_buf, EEP_READ_SIZE);
            }
            break;

         case EEP_CMD_WRITE:
            /* handle write request */
            ESC_read (ESCREG_EEDATA, eep_buf, EEP_WRITE_SIZE);
            if (EEP_write (stat.addr * sizeof(uint16_t), eep_buf, EEP_WRITE_SIZE) != 0) {
               stat.contstat.bits.ackErr = 1;
            }
            break;

         default:
            stat.contstat.bits.ackErr = 1;
      }

      /* acknowledge command */
      stat.contstat.reg = htoes(stat.contstat.reg);
      ESC_write (ESCREG_EECONTSTAT, &stat.contstat.reg, sizeof(uint16_t));
   }
}
예제 #13
0
void update_PWM(void){
  int16_t                              pwm;

  pwm=htoes(mosi_packet.m_1);
  if(pwm>pwm_duty_limit)pwm=pwm_duty_limit;
  else if(pwm<-pwm_duty_limit)pwm=-pwm_duty_limit;
  pwmx_set_pulsewidth(drv_pwm_1,abs(pwm));
  (*IOp_DO).line.direction_1=(pwm<0);
  pwm=htoes(mosi_packet.m_2);
  if(pwm>pwm_duty_limit)pwm=pwm_duty_limit;
  else if(pwm<-pwm_duty_limit)pwm=-pwm_duty_limit;
  pwmx_set_pulsewidth(drv_pwm_2,abs(pwm));
  (*IOp_DO).line.direction_2=(pwm<0);
  pwm=htoes(mosi_packet.m_3);
  if(pwm>pwm_duty_limit)pwm=pwm_duty_limit;
  else if(pwm<-pwm_duty_limit)pwm=-pwm_duty_limit;
  pwmx_set_pulsewidth(drv_pwm_3,abs(pwm));
  (*IOp_DO).line.direction_3=(pwm<0);
}
예제 #14
0
파일: esc_coe.c 프로젝트: aton0511/SOES
/** Function for sending an SDO Abort reply.
 *
 * @param[in] index      = index of object causing abort reply
 * @param[in] sub-index  = sub-index of object causing abort reply
 * @param[in] abortcode  = abort code to send in reply
 */
void SDO_abort (uint16_t index, uint8_t subindex, uint32_t abortcode)
{
   uint8_t MBXout;
   _COEsdo *coeres;
   MBXout = ESC_claimbuffer ();
   if (MBXout)
   {
      coeres = (_COEsdo *) &MBX[MBXout];
      coeres->mbxheader.length = htoes (COE_DEFAULTLENGTH);
      coeres->mbxheader.mbxtype = MBXCOE;
      coeres->coeheader.numberservice =
         htoes ((0 & 0x01f) | (COE_SDOREQUEST << 12));
      coeres->index = htoes (index);
      coeres->subindex = subindex;
      coeres->command = COE_COMMAND_SDOABORT;
      coeres->size = htoel (abortcode);
      MBXcontrol[MBXout].state = MBXstate_outreq;
   }
}
예제 #15
0
void* EC_Header::add(void *ecatHeader, uint8 com, uint8 idx, boolean more, uint16 ADP, uint16 ADO, uint16 length, int prevlength)
{
	EC_Header* self = static_cast<EC_Header*>(ecatHeader);
	/* add new datagram to ethernet frame size */
	self->elength_ = htoes(etohs(self->elength_) + sizeof(EC_Header)+length);
	/* add "datagram follows" flag to previous subframe dlength */
	self->dlength_ = htoes(etohs(self->dlength_) | EC_DATAGRAMFOLLOWS);
	/* set new EtherCAT header position */

	size_t offset = (prevlength - sizeof(EtherNetHeader)) - sizeof(self->elength_);
	self = reinterpret_cast<EC_Header*>(static_cast<uint8*>(ecatHeader)+offset);
	self->command_ = com;
	self->index_ = idx;
	self->ADP_ = htoes(ADP);
	self->ADO_ = htoes(ADO);
	if (more)
	{
		/* this is not the last datagram to add */
		self->dlength_ = htoes(length | EC_DATAGRAMFOLLOWS);
	}
	else
	{
		/* this is the last datagram in the frame */
		self->dlength_ = htoes(length);
	}
	return reinterpret_cast<uint8*>(self)+sizeof(EC_Header);
}
예제 #16
0
/** Reconfigure slave.
 *
 * @param[in] slave	  = slave to reconfigure
 * @return Slave state
 */
int ec_reconfig_slave(uint16 slave)
{
  int state, nSM, FMMUc;
  uint16 configadr;

  configadr = ec_slave[slave].configadr;
  if (ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_INIT), EC_TIMEOUTRET) <= 0)
    return 0;
  state = 0;
  ec_eeprom2pdi(slave); /* set Eeprom control to PDI */
  /* check state change init */
  state = ec_statecheck(slave, EC_STATE_INIT, EC_TIMEOUTSTATE);
  if (state == EC_STATE_INIT)
  {
    /* program all enabled SM */
    for (nSM = 0; nSM < EC_MAXSM; nSM++)
    {
      if (ec_slave[slave].SM[nSM].StartAddr)
        ec_FPWR(configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)), sizeof(ec_smt), &ec_slave[slave].SM[nSM],
                EC_TIMEOUTRET);
    }
    /* program configured FMMU */
    for (FMMUc = 0; FMMUc < ec_slave[slave].FMMUunused; FMMUc++)
    {
      ec_FPWR(configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), sizeof(ec_fmmut), &ec_slave[slave].FMMU[FMMUc],
              EC_TIMEOUTRET);
    }
    ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP), EC_TIMEOUTRET);
    state = ec_statecheck(slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
    if (state == EC_STATE_PRE_OP)
    {
      ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP), EC_TIMEOUTRET); /* set safeop status */
      state = ec_statecheck(slave, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE); /* check state change safe-op */
    }
  }
  return state;
}
예제 #17
0
uint16_t FOE_send_ack()
{
    _FOE    *foembx;
    uint8_t mbxhandle;

    mbxhandle = ESC_claimbuffer();
    if(mbxhandle)
    {
        foembx = (_FOE*)&MBX[mbxhandle];
        foembx->mbxheader.length = htoes(FOEHSIZE);
        foembx->mbxheader.mbxtype = MBXFOE;
        foembx->foeheader.opcode = FOE_OP_ACK;
        foembx->foeheader.x.packetnumber = htoel(ESCvar.foepacket);
        MBXcontrol[mbxhandle].state = MBXstate_outreq;
        ESCvar.foepacket++;
        return 0;
    }
    else
        return FOE_ERR_PROGERROR;
}
예제 #18
0
void FOE_abort(uint32_t code)
{
    _FOE *foembx;
    uint8_t mbxhandle;

    if(code)
    {
        /* Send back an error packet. */
        mbxhandle = ESC_claimbuffer();
        if(mbxhandle)
        {
            foembx = (_FOE*)&MBX[mbxhandle];
            foembx->mbxheader.length = htoes(FOEHSIZE); /* Don't bother with error text for now. */
            foembx->mbxheader.mbxtype = MBXFOE;
            foembx->foeheader.opcode = FOE_OP_ERR;
            foembx->foeheader.x.errorcode = htoel(code);
            MBXcontrol[mbxhandle].state = MBXstate_outreq;
        }
        /* Nothing we can do if we can't get an outbound mailbox. */
    }
    FOE_init();
}
예제 #19
0
/* Sends an FoE data packet out, returning the number of data octets
 * written or an error number.
 * Error numbers will be greater than FOE_DATA_SIZE.*/
uint16_t FOE_send_data_packet()
{
    _FOE     *foembx;
    uint16_t data_len;
    uint8_t  mbxhandle;

    mbxhandle = ESC_claimbuffer();
    if(mbxhandle)
    {
        foembx = (_FOE*)&MBX[mbxhandle];
        data_len = FOE_fread(foembx->y.data, FOE_DATA_SIZE);
        foembx->mbxheader.length = htoes(data_len + FOEHSIZE);
        foembx->mbxheader.mbxtype = MBXFOE;
        foembx->foeheader.opcode = FOE_OP_DATA;
        foembx->foeheader.x.packetnumber = htoel(ESCvar.foepacket);
        /* Mark the outbound mailbox as filled. */
        MBXcontrol[mbxhandle].state = MBXstate_outreq;
        ESCvar.foepacket++;
        return data_len;
    }
    else
        return FOE_ERR_PROGERROR;
}
예제 #20
0
/** Add EtherCAT datagram to a standard ethernet frame with existing datagram(s).
 *
 * @param[out] frame	    = framebuffer
 * @param[in] com			= command
 * @param[in] idx			= index used for TX and RX buffers
 * @param[in] more			= TRUE if still more datagrams to follow
 * @param[in] ADP			= Address Position
 * @param[in] ADO			= Address Offset
 * @param[in] length		= length of datagram excluding EtherCAT header
 * @param[in] data			= databuffer to be copied in datagram
 * @return Offset to data in rx frame, usefull to retrieve data after RX.
 */
int ec_adddatagram(void *frame, uint8 com, uint8 idx, boolean more, uint16 ADP, uint16 ADO, uint16 length, void *data)
{
	ec_comt *datagramP;
	uint8 *frameP;
	uint16 prevlength;

	frameP = frame;
	/* copy previous frame size */
	prevlength = ec_txbuflength[idx];
	datagramP = (ec_comt*)&frameP[ETH_HEADERSIZE];
	/* add new datagram to ethernet frame size */
	datagramP->elength = htoes( etohs(datagramP->elength) + EC_HEADERSIZE + length );
	/* add "datagram follows" flag to previous subframe dlength */
	datagramP->dlength = htoes( etohs(datagramP->dlength) | EC_DATAGRAMFOLLOWS );
	/* set new EtherCAT header position */
	datagramP = (ec_comt*)&frameP[prevlength - EC_ELENGTHSIZE];
	datagramP->command = com;
	datagramP->index = idx;
	datagramP->ADP = htoes(ADP);
	datagramP->ADO = htoes(ADO);
	if (more)
	{
		/* this is not the last datagram to add */
		datagramP->dlength = htoes(length | EC_DATAGRAMFOLLOWS);
	}
	else
	{
		/* this is the last datagram in the frame */
		datagramP->dlength = htoes(length);
	}
	if (length > 0)
	{
		memcpy(&frameP[prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE], data, length);
	}
	/* set WKC to zero */
	frameP[prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE + length] = 0x00;
	frameP[prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE + length + 1] = 0x00;
	/* set size of frame in buffer array */
	ec_txbuflength[idx] = prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE + EC_WKCSIZE + length;

	/* return offset to data in rx frame
	   14 bytes smaller than tx frame due to stripping of ethernet header */
	return prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE - ETH_HEADERSIZE;
}
예제 #21
0
/** 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;
}	
예제 #22
0
/** 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;
}
예제 #23
0
/** 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;
}
예제 #24
0
/** Map all PDOs in one group of slaves to IOmap.
 *
 * @param[in]  context        = context struct
 * @param[out] pIOmap     = pointer to IOmap   
 * @param[in]  group      = group to map, 0 = all groups   
 * @return IOmap size
 */
int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
{
   uint16 slave, configadr;
   int Isize, Osize, BitCount, ByteCount, FMMUsize, FMMUdone;
   uint16 SMlength, EndAddr;
   uint8 BitPos;
   uint8 SMc, FMMUc;
   uint32 LogAddr = 0;
   uint32 oLogAddr = 0;
   uint32 diff;
   int nSM, rval;
   ec_eepromPDOt eepPDO;
   uint16 currentsegment = 0;
   uint32 segmentsize = 0;

   if ((*(context->slavecount) > 0) && (group < context->maxgroup))
   {   
      EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group);
      LogAddr = context->grouplist[group].logstartaddr;
      oLogAddr = LogAddr;
      BitPos = 0;
      context->grouplist[group].nsegments = 0;
      context->grouplist[group].outputsWKC = 0;
      context->grouplist[group].inputsWKC = 0;

      /* find output mapping of slave and program FMMU */
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         configadr = context->slavelist[slave].configadr;

         ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */

         EC_PRINT(" >Slave %d, configadr %x, state %2.2x\n",
                  slave, context->slavelist[slave].configadr, context->slavelist[slave].state);

         /* execute special slave configuration hook Pre-Op to Safe-OP */
         if(context->slavelist[slave].PO2SOconfig) /* only if registered */
         {
            context->slavelist[slave].PO2SOconfig(slave);         
         }
         if (!group || (group == context->slavelist[slave].group))
         {   
         
            /* if slave not found in configlist find IO mapping in slave self */
            if (!context->slavelist[slave].configindex)
            {
               Isize = 0;
               Osize = 0;
               if (context->slavelist[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */
               {
                  rval = 0;
                  if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
                     /* read PDO mapping via CoE and use Complete Access */
                  {
                     rval = ecx_readPDOmapCA(context, slave, &Osize, &Isize);
                  }
                  if (!rval) /* CA not available or not succeeded */
                  {
                     /* read PDO mapping via CoE */
                     rval = ecx_readPDOmap(context, slave, &Osize, &Isize);
                  }
                  EC_PRINT("  CoE Osize:%d Isize:%d\n", Osize, Isize);
               }
               if ((!Isize && !Osize) && (context->slavelist[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */
               {
                  /* read AT / MDT mapping via SoE */
                  rval = ecx_readIDNmap(context, slave, &Osize, &Isize);
                  context->slavelist[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
                  context->slavelist[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
                  EC_PRINT("  SoE Osize:%d Isize:%d\n", Osize, Isize);
               }
               if (!Isize && !Osize) /* find PDO mapping by SII */
               {
                  memset(&eepPDO, 0, sizeof(eepPDO));
                  Isize = (int)ecx_siiPDO(context, slave, &eepPDO, 0);
                  EC_PRINT("  SII Isize:%d\n", Isize);               
                  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
                  {   
                     if (eepPDO.SMbitsize[nSM] > 0)
                     {   
                        context->slavelist[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
                        context->slavelist[slave].SMtype[nSM] = 4;
                        EC_PRINT("    SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
                     }   
                  }   
                  Osize = (int)ecx_siiPDO(context, slave, &eepPDO, 1);
                  EC_PRINT("  SII Osize:%d\n", Osize);               
                  for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
                  {   
                     if (eepPDO.SMbitsize[nSM] > 0)
                     {   
                        context->slavelist[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
                        context->slavelist[slave].SMtype[nSM] = 3;
                        EC_PRINT("    SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
                     }   
                  }   
               }
               context->slavelist[slave].Obits = Osize;
               context->slavelist[slave].Ibits = Isize;
               EC_PRINT("     ISIZE:%d %d OSIZE:%d\n", 
                  context->slavelist[slave].Ibits, Isize,context->slavelist[slave].Obits);    
            }

            EC_PRINT("  SM programming\n");  
            if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[0].StartAddr)
            {
               ecx_FPWR(context->port, configadr, ECT_REG_SM0, 
                  sizeof(ec_smt), &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
               EC_PRINT("    SM0 Type:%d StartAddr:%4.4x Flags:%8.8x\n", 
                   context->slavelist[slave].SMtype[0], 
                   context->slavelist[slave].SM[0].StartAddr, 
                   context->slavelist[slave].SM[0].SMflags);   
            }
            if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[1].StartAddr)
            {
               ecx_FPWR(context->port, configadr, ECT_REG_SM1, 
                  sizeof(ec_smt), &context->slavelist[slave].SM[1], EC_TIMEOUTRET3);
               EC_PRINT("    SM1 Type:%d StartAddr:%4.4x Flags:%8.8x\n", 
                   context->slavelist[slave].SMtype[1], 
                   context->slavelist[slave].SM[1].StartAddr, 
                   context->slavelist[slave].SM[1].SMflags);   
            }
            /* program SM2 to SMx */
            for( nSM = 2 ; nSM < EC_MAXSM ; nSM++ )
            {   
               if (context->slavelist[slave].SM[nSM].StartAddr)
               {
                  /* check if SM length is zero -> clear enable flag */
                  if( context->slavelist[slave].SM[nSM].SMlength == 0) 
                  {
                     context->slavelist[slave].SM[nSM].SMflags = 
                        htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) & EC_SMENABLEMASK);
                  }
                  ecx_FPWR(context->port, configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)),
                     sizeof(ec_smt), &context->slavelist[slave].SM[nSM], EC_TIMEOUTRET3);
                  EC_PRINT("    SM%d Type:%d StartAddr:%4.4x Flags:%8.8x\n", nSM,
                      context->slavelist[slave].SMtype[nSM], 
                      context->slavelist[slave].SM[nSM].StartAddr, 
                      context->slavelist[slave].SM[nSM].SMflags);   
               }
            }
            if (context->slavelist[slave].Ibits > 7)
            {
               context->slavelist[slave].Ibytes = (context->slavelist[slave].Ibits + 7) / 8;
            }
            if (context->slavelist[slave].Obits > 7)
            {
               context->slavelist[slave].Obytes = (context->slavelist[slave].Obits + 7) / 8;
            }
            FMMUc = context->slavelist[slave].FMMUunused;
            SMc = 0;
            BitCount = 0;
            ByteCount = 0;
            EndAddr = 0;
            FMMUsize = 0;
            FMMUdone = 0;
            /* create output mapping */
            if (context->slavelist[slave].Obits)
            {
               EC_PRINT("  OUTPUT MAPPING\n");
               /* search for SM that contribute to the output mapping */
               while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Obits + 7) / 8)))
               {   
                  EC_PRINT("    FMMU %d\n", FMMUc);
                  while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;
                  EC_PRINT("      SM%d\n", SMc);
                  context->slavelist[slave].FMMU[FMMUc].PhysStart = 
                     context->slavelist[slave].SM[SMc].StartAddr;
                  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
                  ByteCount += SMlength;
                  BitCount += SMlength * 8;
                  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
                  while ( (BitCount < context->slavelist[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for output */
                  {
                     SMc++;
                     while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;
                     /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
                     if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr ) 
                     {
                        break;
                     }
                     EC_PRINT("      SM%d\n", SMc);
                     SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
                     ByteCount += SMlength;
                     BitCount += SMlength * 8;
                     EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;               
                  }   

                  /* bit oriented slave */
                  if (!context->slavelist[slave].Obytes)
                  {   
                     context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
                     context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
                     BitPos += context->slavelist[slave].Obits - 1;
                     if (BitPos > 7)
                     {
                        LogAddr++;
                        BitPos -= 8;
                     }   
                     FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
                     context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
                     context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
                     BitPos ++;
                     if (BitPos > 7)
                     {
                        LogAddr++;
                        BitPos -= 8;
                     }   
                  }
                  /* byte oriented slave */
                  else
                  {
                     if (BitPos)
                     {
                        LogAddr++;
                        BitPos = 0;
                     }   
                     context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
                     context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
                     BitPos = 7;
                     FMMUsize = ByteCount;
                     if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Obytes)
                     {
                        FMMUsize = context->slavelist[slave].Obytes - FMMUdone;
                     }
                     LogAddr += FMMUsize;
                     context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
                     context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
                     BitPos = 0;
                  }
                  FMMUdone += FMMUsize;
                  context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
                  context->slavelist[slave].FMMU[FMMUc].FMMUtype = 2;
                  context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
                  /* program FMMU for output */
                  ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
                     sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
                  context->grouplist[group].outputsWKC++;
                  if (!context->slavelist[slave].outputs)
                  {   
                     context->slavelist[slave].outputs = 
                        (uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
                     context->slavelist[slave].Ostartbit = 
                        context->slavelist[slave].FMMU[FMMUc].LogStartbit;
                     EC_PRINT("    slave %d Outputs %p startbit %d\n", 
                        slave, 
                        context->slavelist[slave].outputs, 
                        context->slavelist[slave].Ostartbit);
                  }
                  FMMUc++;
               }   
               context->slavelist[slave].FMMUunused = FMMUc;
               diff = LogAddr - oLogAddr;
               oLogAddr = LogAddr;
               if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
               {
                  context->grouplist[group].IOsegment[currentsegment] = segmentsize;
                  if (currentsegment < (EC_MAXIOSEGMENTS - 1))
                  {
                     currentsegment++;
                     segmentsize = diff;   
                  }
               }
               else
               {
                  segmentsize += diff;
               }
            }
         }   
      }
      if (BitPos)
      {
         LogAddr++;
         oLogAddr = LogAddr;
         BitPos = 0;
         if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
         {
            context->grouplist[group].IOsegment[currentsegment] = segmentsize;
            if (currentsegment < (EC_MAXIOSEGMENTS - 1))
            {
               currentsegment++;
               segmentsize = 1;   
            }
         }
         else
         {
            segmentsize += 1;
         }
      }   
      context->grouplist[group].outputs = pIOmap;
      context->grouplist[group].Obytes = LogAddr;
      context->grouplist[group].nsegments = currentsegment + 1;
      context->grouplist[group].Isegment = currentsegment;
      context->grouplist[group].Ioffset = segmentsize;
      if (!group)
      {   
         context->slavelist[0].outputs = pIOmap;
         context->slavelist[0].Obytes = LogAddr; /* store output bytes in master record */
      }   
      
      /* do input mapping of slave and program FMMUs */
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         configadr = context->slavelist[slave].configadr;
         FMMUc = context->slavelist[slave].FMMUunused;
         if (context->slavelist[slave].Obits) /* find free FMMU */
         {
            while ( context->slavelist[slave].FMMU[FMMUc].LogStart ) FMMUc++;
         }
         SMc = 0;
         BitCount = 0;
         ByteCount = 0;
         EndAddr = 0;
         FMMUsize = 0;
         FMMUdone = 0;
         /* create input mapping */
         if (context->slavelist[slave].Ibits)
         {
            EC_PRINT(" =Slave %d, INPUT MAPPING\n", slave);
            /* search for SM that contribute to the input mapping */
            while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Ibits + 7) / 8)))
            {   
               EC_PRINT("    FMMU %d\n", FMMUc);
               while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;
               EC_PRINT("      SM%d\n", SMc);
               context->slavelist[slave].FMMU[FMMUc].PhysStart = 
                  context->slavelist[slave].SM[SMc].StartAddr;
               SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
               ByteCount += SMlength;
               BitCount += SMlength * 8;
               EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
               while ( (BitCount < context->slavelist[slave].Ibits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for input */
               {
                  SMc++;
                  while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;
                  /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
                  if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr ) 
                  {
                     break;
                  }
                  EC_PRINT("      SM%d\n", SMc);
                  SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
                  ByteCount += SMlength;
                  BitCount += SMlength * 8;
                  EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;               
               }   

               /* bit oriented slave */
               if (!context->slavelist[slave].Ibytes)
               {   
                  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
                  context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
                  BitPos += context->slavelist[slave].Ibits - 1;
                  if (BitPos > 7)
                  {
                     LogAddr++;
                     BitPos -= 8;
                  }   
                  FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
                  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
                  context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
                  BitPos ++;
                  if (BitPos > 7)
                  {
                     LogAddr++;
                     BitPos -= 8;
                  }   
               }
               /* byte oriented slave */
               else
               {
                  if (BitPos)
                  {
                     LogAddr++;
                     BitPos = 0;
                  }   
                  context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
                  context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
                  BitPos = 7;
                  FMMUsize = ByteCount;
                  if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Ibytes)
                  {
                     FMMUsize = context->slavelist[slave].Ibytes - FMMUdone;
                  }
                  LogAddr += FMMUsize;
                  context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
                  context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
                  BitPos = 0;
               }
               FMMUdone += FMMUsize;
               if (context->slavelist[slave].FMMU[FMMUc].LogLength)
               {   
                  context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
                  context->slavelist[slave].FMMU[FMMUc].FMMUtype = 1;
                  context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
                  /* program FMMU for input */
                  ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), 
                     sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
                  /* add one for an input FMMU */
                  context->grouplist[group].inputsWKC++;
               }   
               if (!context->slavelist[slave].inputs)
               {   
                  context->slavelist[slave].inputs = 
                     (uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
                  context->slavelist[slave].Istartbit = 
                     context->slavelist[slave].FMMU[FMMUc].LogStartbit;
                  EC_PRINT("    Inputs %p startbit %d\n", 
                     context->slavelist[slave].inputs, 
                     context->slavelist[slave].Istartbit);
               }
               FMMUc++;
            }   
            context->slavelist[slave].FMMUunused = FMMUc;
            diff = LogAddr - oLogAddr;
            oLogAddr = LogAddr;
            if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
            {
               context->grouplist[group].IOsegment[currentsegment] = segmentsize;
               if (currentsegment < (EC_MAXIOSEGMENTS - 1))
               {
                  currentsegment++;
                  segmentsize = diff;   
               }
            }
            else
            {
               segmentsize += diff;
            }   
         }

         ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */         
         ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , EC_TIMEOUTRET3); /* set safeop status */
                  
         if (context->slavelist[slave].blockLRW)
         {    
            context->grouplist[group].blockLRW++;                     
         }
         context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
      }
      if (BitPos)
      {
         LogAddr++;
         oLogAddr = LogAddr;
         BitPos = 0;
         if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
         {
            context->grouplist[group].IOsegment[currentsegment] = segmentsize;
            if (currentsegment < (EC_MAXIOSEGMENTS - 1))
            {
               currentsegment++;
               segmentsize = 1;   
            }
         }
         else
         {
            segmentsize += 1;
         }
      }   
      context->grouplist[group].IOsegment[currentsegment] = segmentsize;
      context->grouplist[group].nsegments = currentsegment + 1;
      context->grouplist[group].inputs = (uint8 *)(pIOmap) + context->grouplist[group].Obytes;
      context->grouplist[group].Ibytes = LogAddr - context->grouplist[group].Obytes;
      if (!group)
      {   
         context->slavelist[0].inputs = (uint8 *)(pIOmap) + context->slavelist[0].Obytes;
         context->slavelist[0].Ibytes = LogAddr - context->slavelist[0].Obytes; /* store input bytes in master record */
      }   

      EC_PRINT("IOmapSize %d\n", LogAddr - context->grouplist[group].logstartaddr);      
   
      return (LogAddr - context->grouplist[group].logstartaddr);
   }
   
   return 0;
}   
예제 #25
0
/** Enumerate and init all slaves.
 *
 * @param[in]  context        = context struct
 * @param[in] usetable     = TRUE when using configtable to init slaves, FALSE otherwise
 * @return Workcounter of slave discover datagram = number of slaves found
 */
int ecx_config_init(ecx_contextt *context, uint8 usetable)
{
   uint16 w, slave, ADPh, configadr, ssigen;
   uint16 topology, estat;
   int16 topoc, slavec, aliasadr;
   uint8 b,h;
   uint8 zbuf[64];
   uint8 SMc;
   uint32 eedat;
   int wkc, cindex, nSM, lp;

   EC_PRINT("ec_config_init %d\n",usetable);
   *(context->slavecount) = 0;
   /* clean ec_slave array */
   memset(context->slavelist, 0x00, sizeof(ec_slavet) * context->maxslave);
   memset(&zbuf, 0x00, sizeof(zbuf));
   memset(context->grouplist, 0x00, sizeof(ec_groupt) * context->maxgroup);
   /* clear slave eeprom cache */
   ecx_siigetbyte(context, 0, EC_MAXEEPBUF);
   
   for(lp = 0; lp < context->maxgroup; lp++)
   {
      context->grouplist[lp].logstartaddr = lp << 16; /* default start address per group entry */
   }
   /* make special pre-init register writes to enable MAC[1] local administered bit *
    * setting for old netX100 slaves */
   b = 0x00;
   ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3);    /* Ignore Alias register */
   b = EC_STATE_INIT | EC_STATE_ACK;
   ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3);      /* Reset all slaves to Init */
   /* netX100 should now be happy */
   
   wkc = ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3);      /* Reset all slaves to Init */
   printf("wkc = %d\n",wkc);
   
   w = 0x0000;
   wkc = ecx_BRD(context->port, 0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE);   /* detect number of slaves */
   if (wkc > 0)
   {
      *(context->slavecount) = wkc;
      b = 0x00;
      ecx_BWR(context->port, 0x0000, ECT_REG_DLPORT, sizeof(b), &b, EC_TIMEOUTRET3);     /* deact loop manual */
      w = htoes(0x0004);
      ecx_BWR(context->port, 0x0000, ECT_REG_IRQMASK, sizeof(w), &w, EC_TIMEOUTRET3);    /* set IRQ mask */
      ecx_BWR(context->port, 0x0000, ECT_REG_RXERR, 8, &zbuf, EC_TIMEOUTRET3);           /* reset CRC counters */
      ecx_BWR(context->port, 0x0000, ECT_REG_FMMU0, 16 * 3, &zbuf, EC_TIMEOUTRET3);      /* reset FMMU's */
      ecx_BWR(context->port, 0x0000, ECT_REG_SM0, 8 * 4, &zbuf, EC_TIMEOUTRET3);         /* reset SyncM */
      ecx_BWR(context->port, 0x0000, ECT_REG_DCSYSTIME, 4, &zbuf, EC_TIMEOUTRET3);       /* reset system time+ofs */
      w = htoes(0x1000);
      ecx_BWR(context->port, 0x0000, ECT_REG_DCSPEEDCNT, sizeof(w), &w, EC_TIMEOUTRET3); /* DC speedstart */
      w = htoes(0x0c00);
      ecx_BWR(context->port, 0x0000, ECT_REG_DCTIMEFILT, sizeof(w), &w, EC_TIMEOUTRET3); /* DC filt expr */
      b = 0x00;
      ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3);    /* Ignore Alias register */
      b = EC_STATE_INIT | EC_STATE_ACK;
      ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3);      /* Reset all slaves to Init */
      b = 2;
      ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET3);    /* force Eeprom from PDI */
      b = 0;
      ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET3);    /* set Eeprom to master */
      
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         ADPh = (uint16)(1 - slave);
         context->slavelist[slave].Itype = 
            etohs(ecx_APRDw(context->port, ADPh, ECT_REG_PDICTL, EC_TIMEOUTRET3)); /* read interface type of slave */
         /* a node offset is used to improve readibility of network frames */
         /* this has no impact on the number of addressable slaves (auto wrap around) */
         ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(slave + EC_NODEOFFSET) , EC_TIMEOUTRET3); /* set node address of slave */
         if (slave == 1) 
         {
            b = 1; /* kill non ecat frames for first slave */
         }
         else 
         {
            b = 0; /* pass all frames for following slaves */
         }
         ecx_APWRw(context->port, ADPh, ECT_REG_DLCTL, htoes(b), EC_TIMEOUTRET3); /* set non ecat frame behaviour */
         configadr = etohs(ecx_APRDw(context->port, ADPh, ECT_REG_STADR, EC_TIMEOUTRET3));
         context->slavelist[slave].configadr = configadr;
         ecx_FPRD(context->port, configadr, ECT_REG_ALIAS, sizeof(aliasadr), &aliasadr, EC_TIMEOUTRET3);
         context->slavelist[slave].aliasadr = etohs(aliasadr);
         ecx_FPRD(context->port, configadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET3);
         estat = etohs(estat);
         if (estat & EC_ESTAT_R64) /* check if slave can read 8 byte chunks */
         {
            context->slavelist[slave].eep_8byte = 1;
         }
         ecx_readeeprom1(context, slave, ECT_SII_MANUF); /* Manuf */
      }
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         context->slavelist[slave].eep_man = 
            etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* Manuf */
         ecx_readeeprom1(context, slave, ECT_SII_ID); /* ID */
      }
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         context->slavelist[slave].eep_id = 
            etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* ID */
         ecx_readeeprom1(context, slave, ECT_SII_REV); /* revision */
      }
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         context->slavelist[slave].eep_rev = 
            etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* revision */
         ecx_readeeprom1(context, slave, ECT_SII_RXMBXADR); /* write mailbox address + mailboxsize */
      }
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         eedat = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* write mailbox address and mailboxsize */
         context->slavelist[slave].mbx_wo = (uint16)LO_WORD(eedat);
         context->slavelist[slave].mbx_l = (uint16)HI_WORD(eedat);
         if (context->slavelist[slave].mbx_l > 0) 
         {
            ecx_readeeprom1(context, slave, ECT_SII_TXMBXADR); /* read mailbox offset */
         }
      }
      for (slave = 1; slave <= *(context->slavecount); slave++)
      {
         if (context->slavelist[slave].mbx_l > 0) 
         {
            eedat = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* read mailbox offset */
            context->slavelist[slave].mbx_ro = (uint16)LO_WORD(eedat); /* read mailbox offset */
            context->slavelist[slave].mbx_rl = (uint16)HI_WORD(eedat); /*read mailbox length */
            if (context->slavelist[slave].mbx_rl == 0)
            {
               context->slavelist[slave].mbx_rl = context->slavelist[slave].mbx_l;
            }
         }
         configadr = context->slavelist[slave].configadr;
         if ((etohs(ecx_FPRDw(context->port, configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET3)) & 0x04) > 0)  /* Support DC? */
         {   
            context->slavelist[slave].hasdc = TRUE;
         }
         else
         {
            context->slavelist[slave].hasdc = FALSE;
         }
         topology = etohs(ecx_FPRDw(context->port, configadr, ECT_REG_DLSTAT, EC_TIMEOUTRET3)); /* extract topology from DL status */
         h = 0; 
         b = 0;
         if ((topology & 0x0300) == 0x0200) /* port0 open and communication established */
         {
            h++;
            b |= 0x01;
         }
         if ((topology & 0x0c00) == 0x0800) /* port1 open and communication established */
         {
            h++;
            b |= 0x02;
         }
         if ((topology & 0x3000) == 0x2000) /* port2 open and communication established */
         {
            h++;
            b |= 0x04;
         }
         if ((topology & 0xc000) == 0x8000) /* port3 open and communication established */
         {
            h++;
            b |= 0x08;
         }
         /* ptype = Physical type*/
         context->slavelist[slave].ptype = 
            LO_BYTE(etohs(ecx_FPRDw(context->port, configadr, ECT_REG_PORTDES, EC_TIMEOUTRET3)));
         context->slavelist[slave].topology = h;
         context->slavelist[slave].activeports = b;
         /* 0=no links, not possible             */
         /* 1=1 link  , end of line              */
         /* 2=2 links , one before and one after */
         /* 3=3 links , split point              */
         /* 4=4 links , cross point              */
         /* search for parent */
         context->slavelist[slave].parent = 0; /* parent is master */
         if (slave > 1)
         {
            topoc = 0; 
            slavec = slave - 1;
            do
            {
               topology = context->slavelist[slavec].topology;
               if (topology == 1)
               {
                  topoc--; /* endpoint found */
               }
               if (topology == 3)
               {
                  topoc++; /* split found */
               }
               if (topology == 4)
               {
                  topoc += 2; /* cross found */
               }
               if (((topoc >= 0) && (topology > 1)) ||
                   (slavec == 1)) /* parent found */
               {
                  context->slavelist[slave].parent = slavec;
                  slavec = 1;
               }
               slavec--;
            }
            while (slavec > 0);
         }

         w = ecx_statecheck(context, slave, EC_STATE_INIT,  EC_TIMEOUTSTATE); //* check state change Init */
   
         /* set default mailbox configuration if slave has mailbox */
         if (context->slavelist[slave].mbx_l>0)
         {   
            context->slavelist[slave].SMtype[0] = 1;
            context->slavelist[slave].SMtype[1] = 2;
            context->slavelist[slave].SMtype[2] = 3;
            context->slavelist[slave].SMtype[3] = 4;
            context->slavelist[slave].SM[0].StartAddr = htoes(context->slavelist[slave].mbx_wo);
            context->slavelist[slave].SM[0].SMlength = htoes(context->slavelist[slave].mbx_l);
            context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
            context->slavelist[slave].SM[1].StartAddr = htoes(context->slavelist[slave].mbx_ro);
            context->slavelist[slave].SM[1].SMlength = htoes(context->slavelist[slave].mbx_rl);
            context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
            context->slavelist[slave].mbx_proto = 
               ecx_readeeprom(context, slave, ECT_SII_MBXPROTO, EC_TIMEOUTEEP);
         }   
         cindex = 0;
         #ifdef EC_VER1
         /* use configuration table ? */
         if (usetable)
         {
            cindex = ec_findconfig( context->slavelist[slave].eep_man, context->slavelist[slave].eep_id );
            context->slavelist[slave].configindex= cindex;
         }
         /* slave found in configuration table ? */
         if (cindex)
         {
            context->slavelist[slave].Dtype = ec_configlist[cindex].Dtype;            
            strcpy(context->slavelist[slave].name ,ec_configlist[cindex].name);
            context->slavelist[slave].Ibits = ec_configlist[cindex].Ibits;
            context->slavelist[slave].Obits = ec_configlist[cindex].Obits;
            if (context->slavelist[slave].Obits)
            {
               context->slavelist[slave].FMMU0func = 1;
            }
            if (context->slavelist[slave].Ibits)
            {
               context->slavelist[slave].FMMU1func = 2;
            }
            context->slavelist[slave].FMMU[0].FMMUactive = ec_configlist[cindex].FM0ac;
            context->slavelist[slave].FMMU[1].FMMUactive = ec_configlist[cindex].FM1ac;
            context->slavelist[slave].SM[2].StartAddr = htoes(ec_configlist[cindex].SM2a);
            context->slavelist[slave].SM[2].SMflags = htoel(ec_configlist[cindex].SM2f);
            /* simple (no mailbox) output slave found ? */
            if (context->slavelist[slave].Obits && !context->slavelist[slave].SM[2].StartAddr)
            {
               context->slavelist[slave].SM[0].StartAddr = htoes(0x0f00);
               context->slavelist[slave].SM[0].SMlength = htoes((context->slavelist[slave].Obits + 7) / 8);
               context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTDOSM0);         
               context->slavelist[slave].FMMU[0].FMMUactive = 1;
               context->slavelist[slave].FMMU[0].FMMUtype = 2;
               context->slavelist[slave].SMtype[0] = 3;
            }
            /* complex output slave */
            else
            {
               context->slavelist[slave].SM[2].SMlength = htoes((context->slavelist[slave].Obits + 7) / 8);
               context->slavelist[slave].SMtype[2] = 3;
            }   
            context->slavelist[slave].SM[3].StartAddr = htoes(ec_configlist[cindex].SM3a);
            context->slavelist[slave].SM[3].SMflags = htoel(ec_configlist[cindex].SM3f);
            /* simple (no mailbox) input slave found ? */
            if (context->slavelist[slave].Ibits && !context->slavelist[slave].SM[3].StartAddr)
            {
               context->slavelist[slave].SM[1].StartAddr = htoes(0x1000);
               context->slavelist[slave].SM[1].SMlength = htoes((context->slavelist[slave].Ibits + 7) / 8);
               context->slavelist[slave].SM[1].SMflags = htoel(0x00000000);         
               context->slavelist[slave].FMMU[1].FMMUactive = 1;
               context->slavelist[slave].FMMU[1].FMMUtype = 1;
               context->slavelist[slave].SMtype[1] = 4;
            }
            /* complex input slave */
            else
            {
               context->slavelist[slave].SM[3].SMlength = htoes((context->slavelist[slave].Ibits + 7) / 8);
               context->slavelist[slave].SMtype[3] = 4;
            }   
         }
         /* slave not in configuration table, find out via SII */
         else
         #endif
         {
            ssigen = ecx_siifind(context, slave, ECT_SII_GENERAL);
            /* SII general section */
            if (ssigen)
            {
               context->slavelist[slave].CoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x07);
               context->slavelist[slave].FoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x08);
               context->slavelist[slave].EoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x09);
               context->slavelist[slave].SoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x0a);
               if((ecx_siigetbyte(context, slave, ssigen + 0x0d) & 0x02) > 0)
               {
                  context->slavelist[slave].blockLRW = 1;
                  context->slavelist[0].blockLRW++;                  
               }   
               context->slavelist[slave].Ebuscurrent = ecx_siigetbyte(context, slave, ssigen + 0x0e);
               context->slavelist[slave].Ebuscurrent += ecx_siigetbyte(context, slave, ssigen + 0x0f) << 8;
               context->slavelist[0].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
            }
            /* SII strings section */
            if (ecx_siifind(context, slave, ECT_SII_STRING) > 0)
            {
               ecx_siistring(context, context->slavelist[slave].name, slave, 1);
            }
            /* no name for slave found, use constructed name */
            else
            {
               sprintf(context->slavelist[slave].name, "? M:%8.8x I:%8.8x",
                       (unsigned int)context->slavelist[slave].eep_man, 
                       (unsigned int)context->slavelist[slave].eep_id);
            }
            /* SII SM section */
            nSM = ecx_siiSM(context, slave, context->eepSM);
            if (nSM>0)
            {   
               context->slavelist[slave].SM[0].StartAddr = htoes(context->eepSM->PhStart);
               context->slavelist[slave].SM[0].SMlength = htoes(context->eepSM->Plength);
               context->slavelist[slave].SM[0].SMflags = 
                  htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
               SMc = 1;
               while ((SMc < EC_MAXSM) &&  ecx_siiSMnext(context, slave, context->eepSM, SMc))
               {
                  context->slavelist[slave].SM[SMc].StartAddr = htoes(context->eepSM->PhStart);
                  context->slavelist[slave].SM[SMc].SMlength = htoes(context->eepSM->Plength);
                  context->slavelist[slave].SM[SMc].SMflags = 
                     htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
                  SMc++;
               }   
            }   
            /* SII FMMU section */
            if (ecx_siiFMMU(context, slave, context->eepFMMU))
            {
               if (context->eepFMMU->FMMU0 !=0xff) 
               {
                  context->slavelist[slave].FMMU0func = context->eepFMMU->FMMU0;
               }
               if (context->eepFMMU->FMMU1 !=0xff) 
               {
                  context->slavelist[slave].FMMU1func = context->eepFMMU->FMMU1;
               }
               if (context->eepFMMU->FMMU2 !=0xff) 
               {
                  context->slavelist[slave].FMMU2func = context->eepFMMU->FMMU2;
               }
               if (context->eepFMMU->FMMU3 !=0xff) 
               {
                  context->slavelist[slave].FMMU3func = context->eepFMMU->FMMU3;
               }
            }            
         }   

         if (context->slavelist[slave].mbx_l > 0)
         {
            if (context->slavelist[slave].SM[0].StartAddr == 0x0000) /* should never happen */
            {
               EC_PRINT("Slave %d has no proper mailbox in configuration, try default.\n", slave);
               context->slavelist[slave].SM[0].StartAddr = htoes(0x1000);
               context->slavelist[slave].SM[0].SMlength = htoes(0x0080);
               context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
               context->slavelist[slave].SMtype[0] = 1;               
            }         
            if (context->slavelist[slave].SM[1].StartAddr == 0x0000) /* should never happen */
            {
               EC_PRINT("Slave %d has no proper mailbox out configuration, try default.\n", slave);
               context->slavelist[slave].SM[1].StartAddr = htoes(0x1080);
               context->slavelist[slave].SM[1].SMlength = htoes(0x0080);
               context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
               context->slavelist[slave].SMtype[1] = 2;
            }         
            /* program SM0 mailbox in and SM1 mailbox out for slave */
            /* writing both SM in one datagram will solve timing issue in old NETX */
            ecx_FPWR(context->port, configadr, ECT_REG_SM0, sizeof(ec_smt) * 2, 
               &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
         } 
         /* request pre_op for slave */
         ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP | EC_STATE_ACK) , EC_TIMEOUTRET3); /* set preop status */
      }
   }   
   return wkc;
}
예제 #26
0
void update_DAC(void){
  write_DAC(0x00,(2048+htoes(mosi_packet.aout_1))<<4);
  write_DAC(0x02,(2048+htoes(mosi_packet.aout_2))<<4);
}
예제 #27
0
void read_ADC(void){
  uint16_t ADC;
  int16_t  ADC_current;

  miso_packet.digital_in.line.power_status=1;
  for(uint8_t i=0;i<16;i++){
    (*IOp_B).adc_enable=0;
    (*IOp_B).adc_address=i;
    ADC=((*(uint16_t*)ADC_1_BASE_ADDRESS)>>1)&0x0FFF;
    (*IOp_B).adc_enable=1;
    switch(i){
// No break needed
    case 0:
      miso_packet.force_1=htoes(ADC);
      break;
    case 1:
      miso_packet.pos_1=htoes(ADC);
      break;
    case 2:
      miso_packet.force_2=htoes(ADC);
      break;
    case 3:
      miso_packet.pos_2=htoes(ADC);
      break;
    case 4:
      miso_packet.force_3=htoes(ADC);
      break;
    case 5:
      miso_packet.pos_3=htoes(ADC);
      break;
    case 6:
      if(ADC<(1487*92/100))miso_packet.digital_in.line.power_status=0;
      else if(ADC>(1487*108/100))miso_packet.digital_in.line.power_status=0;
      break;
    case 7:
      if(ADC<(2046*91/100))miso_packet.digital_in.line.power_status=0;
      else if(ADC>(2046*109/100))miso_packet.digital_in.line.power_status=0;
      break;
    case 8:
// Check for 5V ADC
      if(ADC<(3071*90/100))miso_packet.digital_in.line.power_status=0;
      else if(ADC>(3071*110/100))miso_packet.digital_in.line.power_status=0;
      break;
    case 9:
      if(ADC<(2660*83/100))miso_packet.digital_in.line.power_status=0;
      else if(ADC>(2660*117/100))miso_packet.digital_in.line.power_status=0;
      break;
    case 10:
      if(ADC<(2729*83/100))miso_packet.digital_in.line.power_status=0;
      else if(ADC>(2729*117/100))miso_packet.digital_in.line.power_status=0;
      break;
    case 11:
      ADC_current=ADC;
      ADC_current-=2048;
      ADC_current*=2;
      miso_packet.current_1=htoes(ADC_current);
      break;
    case 12:
      ADC_current=ADC;
      ADC_current-=2048;
      miso_packet.current_2=htoes(ADC_current);
      break;
    case 13:
      ADC_current=ADC;
      ADC_current-=2048;
      miso_packet.current_3=htoes(ADC_current);
      break;
    case 14:
      miso_packet.spare_ai_1=htoes(ADC);
      break;
    case 15:
      miso_packet.spare_ai_2=htoes(ADC);
      break;
    }
  }
}
예제 #28
0
/** Enumerate and init all slaves.
 *
 * @param[in] usetable	  = TRUE when using configtable to init slaves, FALSE otherwise
 * @return Workcounter of slave discover datagram = number of slaves found
 */
int ec_config_init(uint8 usetable)
{
    uint16 w, slave, ADPh, configadr, mbx_wo, mbx_ro, mbx_l, ssigen;
    uint16 topology, estat;
    int16 topoc, slavec;
    uint8 b,h;
	uint8 zbuf[64];
	uint8 SMc;
	uint32 eedat;
	int wkc, cindex, nSM;

    ec_slavecount = 0;
	/* clean ec_slave array */
	memset(&ec_slave, 0x00, sizeof(ec_slave));
	memset(&zbuf, 0x00, sizeof(zbuf));
    w = 0x0000;
    wkc = ec_BRD(0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE);		/* detect number of slaves */

    if (wkc > 0)
    {
        ec_slavecount = wkc;
        b = 0x00;
        ec_BWR(0x0000, ECT_REG_DLPORT, sizeof(b), &b, EC_TIMEOUTRET);		/* deact loop manual */
        w = htoes(0x0004);
        ec_BWR(0x0000, ECT_REG_IRQMASK, sizeof(w), &w, EC_TIMEOUTRET);		/* set IRQ mask */
        ec_BWR(0x0000, ECT_REG_RXERR, 8, &zbuf, EC_TIMEOUTRET);  			/* reset CRC counters */
        ec_BWR(0x0000, ECT_REG_FMMU0, 16 * 3, &zbuf, EC_TIMEOUTRET);		/* reset FMMU's */
        ec_BWR(0x0000, ECT_REG_SM0, 8 * 4, &zbuf, EC_TIMEOUTRET);			/* reset SyncM */
        ec_BWR(0x0000, ECT_REG_DCSYSTIME, 4, &zbuf, EC_TIMEOUTRET); 		/* reset system time+ofs */
        w = htoes(0x1000);
        ec_BWR(0x0000, ECT_REG_DCSPEEDCNT, sizeof(w), &w, EC_TIMEOUTRET);   /* DC speedstart */
        w = htoes(0x0c00);
        ec_BWR(0x0000, ECT_REG_DCTIMEFILT, sizeof(w), &w, EC_TIMEOUTRET);   /* DC filt expr */
        b = 0x00;
        ec_BWR(0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET);		/* Ignore Alias register */
        b = EC_STATE_INIT | EC_STATE_ACK;
        ec_BWR(0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET);		/* Reset all slaves to Init */
		b = 2;
		ec_BWR(0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET); 		/* force Eeprom from PDI */
		b = 0;
		ec_BWR(0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET); 		/* set Eeprom to master */
		
        for (slave = 1; slave <= ec_slavecount; slave++)
        {
            ADPh = (uint16)(1 - slave);
            ec_slave[slave].Itype = etohs(ec_APRDw(ADPh, ECT_REG_PDICTL, EC_TIMEOUTRET)); /* read interface type of slave */
			/* a node offset is used to improve readibility of network frames */
			/* this has no impact on the number of addressable slaves (auto wrap around) */
            ec_APWRw(ADPh, ECT_REG_STADR, htoes(slave + EC_NODEOFFSET) , EC_TIMEOUTRET); /* set node address of slave */
            if (slave == 1) 
			{
				b = 1; /* kill non ecat frames for first slave */
			}
			else 
			{
				b = 0; /* pass all frames for following slaves */
			}
            ec_APWRw(ADPh, ECT_REG_DLCTL, htoes(b), EC_TIMEOUTRET); /* set non ecat frame behaviour */
            configadr = etohs(ec_APRDw(ADPh, ECT_REG_STADR, EC_TIMEOUTRET));
            ec_slave[slave].configadr = configadr;
		    ec_FPRD(configadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET);
			estat = etohs(estat);
			if ((estat & (1 << 6))) /* check if slave can read 8 byte chunks */
			{
				ec_slave[slave].eep_8byte = 1;
			}
            ec_readeeprom1(slave, ECT_SII_MANUF); /* Manuf */
        }
		for (slave = 1; slave <= ec_slavecount; slave++)
        {
            ec_slave[slave].eep_man = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* Manuf */
            ec_readeeprom1(slave, ECT_SII_ID); /* ID */
        }
        for (slave = 1; slave <= ec_slavecount; slave++)
        {
            ec_slave[slave].eep_id = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* ID */
            ec_readeeprom1(slave, ECT_SII_REV); /* revision */
        }
        for (slave = 1; slave <= ec_slavecount; slave++)
        {
            ec_slave[slave].eep_rev = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* revision */
            ec_readeeprom1(slave, ECT_SII_RXMBXADR); /* write mailbox address + mailboxsize */
        }
        for (slave = 1; slave <= ec_slavecount; slave++)
        {
            eedat = etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* write mailbox address and mailboxsize */
            ec_slave[slave].mbx_wo = (uint16)LO_WORD(eedat);
            ec_slave[slave].mbx_l = (uint16)HI_WORD(eedat);
			if (ec_slave[slave].mbx_l > 0) 
			{
	            ec_readeeprom1(slave, ECT_SII_TXMBXADR); /* read mailbox offset */
			}
        }
        for (slave = 1; slave <= ec_slavecount; slave++)
        {
			if (ec_slave[slave].mbx_l > 0) 
			{
	            ec_slave[slave].mbx_ro = (uint16)etohl(ec_readeeprom2(slave, EC_TIMEOUTEEP)); /* read mailbox offset */
			}
            configadr = ec_slave[slave].configadr;
            mbx_ro = ec_slave[slave].mbx_ro;
            mbx_wo = ec_slave[slave].mbx_wo;
            mbx_l = ec_slave[slave].mbx_l;
            if ((etohs(ec_FPRDw(configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET)) & 0x04) > 0)  /* Support DC? */
            {
                ec_slave[slave].hasdc = TRUE;
            }
            else
            {
                ec_slave[slave].hasdc = FALSE;
            }
            topology = etohs(ec_FPRDw(configadr, ECT_REG_DLSTAT, EC_TIMEOUTRET)); /* extract topology from DL status */
			h = 0; 
			b = 0;
            if ((topology & 0x0300) == 0x0200) /* port0 open and communication established */
            {
                h++;
				b |= 0x01;
            }
            if ((topology & 0x0c00) == 0x0800) /* port1 open and communication established */
            {
                h++;
				b |= 0x02;
            }
            if ((topology & 0x3000) == 0x2000) /* port2 open and communication established */
            {
                h++;
				b |= 0x04;
            }
            if ((topology & 0xc000) == 0x8000) /* port3 open and communication established */
            {
                h++;
				b |= 0x08;
            }
            /* ptype = Physical type*/
            ec_slave[slave].ptype = LO_BYTE(etohs(ec_FPRDw(configadr, ECT_REG_PORTDES, EC_TIMEOUTRET)));
            ec_slave[slave].topology = h;
			ec_slave[slave].activeports = b;
			/* 0=no links, not possible             */
            /* 1=1 link  , end of line              */
            /* 2=2 links , one before and one after */
            /* 3=3 links , split point              */
            /* 4=4 links , cross point              */
            /* search for parent */
            ec_slave[slave].parent = 0; /* parent is master */
            if (slave > 1)
            {
                topoc = 0; 
                slavec = slave - 1;
                do
                {
		            topology = ec_slave[slavec].topology;
                    if (topology == 1)
                    {
                        topoc--; /* endpoint found */
                    }
                    if (topology == 3)
                    {
                        topoc++; /* split found */
                    }
                    if (topology == 4)
                    {
                        topoc+=2; /* cross found */
                    }
                    if (((topoc >= 0) && (topology > 1)) ||
					    (slavec == 1)) /* parent found */
                    {
                        ec_slave[slave].parent = slavec;
                        slavec = 1;
                    }
					slavec--;
                }
                while (slavec > 0);
            }

            w = ec_statecheck(slave, EC_STATE_INIT,  EC_TIMEOUTSTATE); //* check state change Init */
	
			/* set default mailbox configuration if slave has mailbox */
			if (ec_slave[slave].mbx_l>0)
			{	
				ec_slave[slave].SMtype[0] = 0;
				ec_slave[slave].SMtype[1] = 1;
				ec_slave[slave].SMtype[2] = 2;
				ec_slave[slave].SMtype[3] = 3;
				ec_slave[slave].SM[0].StartAddr = htoes(ec_slave[slave].mbx_wo);
				ec_slave[slave].SM[0].SMlength = htoes(ec_slave[slave].mbx_l);
				ec_slave[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
				ec_slave[slave].SM[1].StartAddr = htoes(ec_slave[slave].mbx_ro);
				ec_slave[slave].SM[1].SMlength = htoes(ec_slave[slave].mbx_l);
				ec_slave[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
				ec_slave[slave].mbx_proto = ec_readeeprom (slave, ECT_SII_MBXPROTO, EC_TIMEOUTEEP);
			}	
			cindex = 0;
			/* use configuration table ? */
			if (usetable)
			{
				cindex = ec_findconfig( ec_slave[slave].eep_man, ec_slave[slave].eep_id );
				ec_slave[slave].configindex= cindex;
			}
			/* slave found in configuration table ? */
			if (cindex)
			{
				ec_slave[slave].Dtype = ec_configlist[cindex].Dtype;				
				strcpy(	ec_slave[slave].name ,ec_configlist[cindex].name);
				ec_slave[slave].Ibits = ec_configlist[cindex].Ibits;
				ec_slave[slave].Obits = ec_configlist[cindex].Obits;
				if (ec_slave[slave].Obits)
				{	
					ec_slave[slave].FMMU0func = 1;
				}	
				if (ec_slave[slave].Ibits)
				{	
					ec_slave[slave].FMMU1func = 2;
				}	
				ec_slave[slave].FMMU[0].FMMUactive = ec_configlist[cindex].FM0ac;
				ec_slave[slave].FMMU[1].FMMUactive = ec_configlist[cindex].FM1ac;
				ec_slave[slave].SM[2].StartAddr = htoes(ec_configlist[cindex].SM2a);
				ec_slave[slave].SM[2].SMflags = htoel(ec_configlist[cindex].SM2f);
				/* simple (no mailbox) output slave found ? */
				if (ec_slave[slave].Obits && !ec_slave[slave].SM[2].StartAddr)
				{
					ec_slave[slave].SM[0].StartAddr = htoes(0x0f00);
					ec_slave[slave].SM[0].SMlength = htoes((ec_slave[slave].Obits + 7) / 8);
					ec_slave[slave].SM[0].SMflags = htoel(EC_DEFAULTDOSM0);			
					ec_slave[slave].FMMU[0].FMMUactive = 1;
					ec_slave[slave].FMMU[0].FMMUtype = 2;
					ec_slave[slave].SMtype[0] = 2;
				}
				/* complex output slave */
				else
				{
					ec_slave[slave].SM[2].SMlength = htoes((ec_slave[slave].Obits + 7) / 8);
					ec_slave[slave].SMtype[2] = 2;
				}	
				ec_slave[slave].SM[3].StartAddr = htoes(ec_configlist[cindex].SM3a);
				ec_slave[slave].SM[3].SMflags = htoel(ec_configlist[cindex].SM3f);
				/* simple (no mailbox) input slave found ? */
				if (ec_slave[slave].Ibits && !ec_slave[slave].SM[3].StartAddr)
				{
					ec_slave[slave].SM[1].StartAddr = htoes(0x1000);
					ec_slave[slave].SM[1].SMlength = htoes((ec_slave[slave].Ibits + 7) / 8);
					ec_slave[slave].SM[1].SMflags = htoel(0x00000000);			
					ec_slave[slave].FMMU[1].FMMUactive = 1;
					ec_slave[slave].FMMU[1].FMMUtype = 1;
					ec_slave[slave].SMtype[1] = 3;
				}
				/* complex input slave */
				else
				{
					ec_slave[slave].SM[3].SMlength = htoes((ec_slave[slave].Ibits + 7) / 8);
					ec_slave[slave].SMtype[3] = 3;
				}	
			}
			/* slave not in configuration table, find out via SII */
			else
			{
				ssigen = ec_siifind(slave, ECT_SII_GENERAL);
				/* SII general section */
				if (ssigen)
                {
					ec_slave[slave].CoEdetails = ec_siigetbyte(slave, ssigen + 0x07);
					ec_slave[slave].FoEdetails = ec_siigetbyte(slave, ssigen + 0x08);
					ec_slave[slave].EoEdetails = ec_siigetbyte(slave, ssigen + 0x09);
					ec_slave[slave].SoEdetails = ec_siigetbyte(slave, ssigen + 0x0a);
					if((ec_siigetbyte(slave, ssigen + 0x0d) & 0x02) > 0)
					{
						ec_slave[slave].blockLRW = 1;
						ec_slave[0].blockLRW++;						
					}	
					ec_slave[slave].Ebuscurrent = ec_siigetbyte(slave, ssigen + 0x0e);
					ec_slave[slave].Ebuscurrent += ec_siigetbyte(slave, ssigen + 0x0f) << 8;
					ec_slave[0].Ebuscurrent += ec_slave[slave].Ebuscurrent;
                }
				/* SII strings section */
				if (ec_siifind(slave, ECT_SII_STRING) > 0)
                {
                    ec_siistring(ec_slave[slave].name, slave, 1);
                }
				/* no name for slave found, use constructed name */
                else
                {
                    sprintf(ec_slave[slave].name, "? M:%8.8x I:%8.8x",
                    (unsigned int)ec_slave[slave].eep_man, (unsigned int)ec_slave[slave].eep_id);
                }
				/* SII SM section */
				nSM = ec_siiSM (slave,&ec_SM);
				if (nSM>0)
				{	
					ec_slave[slave].SM[0].StartAddr = htoes(ec_SM.PhStart);
					ec_slave[slave].SM[0].SMlength = htoes(ec_SM.Plength);
					ec_slave[slave].SM[0].SMflags = htoel((ec_SM.Creg) + (ec_SM.Activate << 16));
					SMc = 1;
					while ((SMc < EC_MAXSM) &&  ec_siiSMnext(slave, &ec_SM, SMc))
					{
						ec_slave[slave].SM[SMc].StartAddr = htoes(ec_SM.PhStart);
						ec_slave[slave].SM[SMc].SMlength = htoes(ec_SM.Plength);
						ec_slave[slave].SM[SMc].SMflags = htoel((ec_SM.Creg) + (ec_SM.Activate << 16));
						SMc++;
					}	
				}	
				/* SII FMMU section */
                if (ec_siiFMMU(slave, &ec_FMMU))
				{
					if (ec_FMMU.FMMU0 !=0xff) 
						ec_slave[slave].FMMU0func = ec_FMMU.FMMU0;
					if (ec_FMMU.FMMU1 !=0xff) 
						ec_slave[slave].FMMU1func = ec_FMMU.FMMU1;
					if (ec_FMMU.FMMU2 !=0xff) 
						ec_slave[slave].FMMU2func = ec_FMMU.FMMU2;
					if (ec_FMMU.FMMU3 !=0xff) 
						ec_slave[slave].FMMU3func = ec_FMMU.FMMU3;
				}	
			}	

			if (ec_slave[slave].mbx_l > 0)
			{
				if (ec_slave[slave].SM[0].StartAddr == 0x0000) /* should never happen */
				{
					ec_slave[slave].SM[0].StartAddr = htoes(0x1000);
					ec_slave[slave].SM[0].SMlength = htoes(0x0080);
					ec_slave[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
					ec_slave[slave].SMtype[0] = 0;					
				}			
				if (ec_slave[slave].SM[1].StartAddr == 0x0000) /* should never happen */
				{
					ec_slave[slave].SM[1].StartAddr = htoes(0x1080);
					ec_slave[slave].SM[1].SMlength = htoes(0x0080);
					ec_slave[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
					ec_slave[slave].SMtype[1] = 1;
				}			
				/* program SM0 mailbox in for slave */
				ec_FPWR (configadr, ECT_REG_SM0, sizeof(ec_smt), &ec_slave[slave].SM[0], EC_TIMEOUTRET);
				/* program SM1 mailbox out for slave */
				// usleep(1000); // was needed for NETX (needs internal time after SM update)
				ec_FPWR (configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET);
			}	
			ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP | EC_STATE_ACK) , EC_TIMEOUTRET); /* set preop status */
		}
	}	
    return wkc;
}
예제 #29
0
/** Map all PDOs from slaves to IOmap.
 *
 * @param[out] pIOmap	  = pointer to IOmap	
 * @return IOmap size
 */
int ec_config_map(void *pIOmap)
{
    uint16 slave, configadr;
	int Isize, Osize, BitCount, ByteCount, FMMUsize, FMMUdone;
	uint16 SMlength;
    uint8 BitPos, EndAddr;
	uint8 SMc, FMMUc;
	uint32 LogAddr = 0;
	int nSM, rval;
	ec_eepromPDOt eepPDO;

	if (ec_slavecount > 0)
	{	
		LogAddr = 0;
		BitPos = 0;

		/* find output mapping of slave and program FMMU0 */
		for (slave = 1; slave <= ec_slavecount; slave++)
        {
            configadr = ec_slave[slave].configadr;

			ec_statecheck(slave, EC_STATE_PRE_OP,  EC_TIMEOUTSTATE); //* check state change pre-op */
			
			/* if slave not found in configlist find IO mapping in slave self */
			if (!ec_slave[slave].configindex)
			{
				Isize = 0;
				Osize = 0;
				if (ec_slave[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */
				{
					if (ec_slave[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
					{
						/* read PDO mapping via CoE and use Complete Access */
						rval = ec_readPDOmapCA(slave, &Osize, &Isize);
					}
					else
					{
						/* read PDO mapping via CoE */
						rval = ec_readPDOmap(slave, &Osize, &Isize);
					}	
					ec_slave[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
					ec_slave[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
				}
				if ((!Isize && !Osize) && (ec_slave[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */
				{
					/* read AT / MDT mapping via SoE */
					rval = ec_readIDNmap(slave, &Osize, &Isize);
					ec_slave[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
					ec_slave[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
				}
				if (!Isize && !Osize) /* find PDO mapping by SII */
				{
					Isize = ec_siiPDO (slave, &eepPDO, 0);
					for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
					{	
						if (eepPDO.SMbitsize[nSM] > 0)
						{	
							ec_slave[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
							ec_slave[slave].SMtype[nSM] = 3;
						}	
					}	
					Osize = ec_siiPDO (slave, &eepPDO, 1);
					for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
					{	
						if (eepPDO.SMbitsize[nSM] > 0)
						{	
							ec_slave[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
							ec_slave[slave].SMtype[nSM] = 2;
						}	
					}	
				}
				ec_slave[slave].Obits = Osize;
				ec_slave[slave].Ibits = Isize;
				
			}

			if (!ec_slave[slave].mbx_l && ec_slave[slave].SM[0].StartAddr)
			{
				ec_FPWR (configadr, ECT_REG_SM0, sizeof(ec_smt), &ec_slave[slave].SM[0], EC_TIMEOUTRET);
			}	
			if (!ec_slave[slave].mbx_l && ec_slave[slave].SM[1].StartAddr)
			{
				ec_FPWR (configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET);
			}	
			if (ec_slave[slave].SM[2].StartAddr)
			{
				/* check if SM length is zero -> clear enable flag */
				if( ec_slave[slave].SM[2].SMlength == 0) 
					ec_slave[slave].SM[2].SMflags = htoel( etohl(ec_slave[slave].SM[2].SMflags) & EC_SMENABLEMASK);
				ec_FPWR (configadr, ECT_REG_SM2, sizeof(ec_smt), &ec_slave[slave].SM[2], EC_TIMEOUTRET);
			}	
			// usleep(1000); // was needed for NETX (needs internal time after SM update)
			if (ec_slave[slave].SM[3].StartAddr)
			{
				/* check if SM length is zero -> clear enable flag */
				if( ec_slave[slave].SM[3].SMlength == 0)
					ec_slave[slave].SM[3].SMflags = htoel( etohl(ec_slave[slave].SM[3].SMflags) & EC_SMENABLEMASK);
				ec_FPWR (configadr, ECT_REG_SM3, sizeof(ec_smt), &ec_slave[slave].SM[3], EC_TIMEOUTRET);
			}	
			if (ec_slave[slave].Ibits > 7)
				ec_slave[slave].Ibytes = (ec_slave[slave].Ibits + 7) / 8;
			if (ec_slave[slave].Obits > 7)
				ec_slave[slave].Obytes = (ec_slave[slave].Obits + 7) / 8;

			FMMUc = 0;
			SMc = 0;
			BitCount = 0;
			ByteCount = 0;
			EndAddr = 0;
			FMMUsize = 0;
			FMMUdone = 0;
			/* create output mapping */
			if (ec_slave[slave].Obits)
			{
				/* search for SM that contribute to the output mapping */
				while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((ec_slave[slave].Obits + 7) / 8)))
				{	
					while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 2)) SMc++;
					ec_slave[slave].FMMU[FMMUc].PhysStart = ec_slave[slave].SM[SMc].StartAddr;
					SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
					ByteCount += SMlength;
					BitCount += SMlength * 8;
					EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;
					while ( (BitCount < ec_slave[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for output */
					{
						SMc++;
						while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 2)) SMc++;
						/* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
						if ( etohs(ec_slave[slave].SM[SMc].StartAddr) > EndAddr ) break;
						SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
						ByteCount += SMlength;
						BitCount += SMlength * 8;
						EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;					
					}	

					/* bit oriented slave */
					if (!ec_slave[slave].Obytes)
					{	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos += ec_slave[slave].Obits - 1;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
						FMMUsize = LogAddr - etohl(ec_slave[slave].FMMU[FMMUc].LogStart) + 1;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos ++;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
					}
					/* byte oriented slave */
					else
					{
						if (BitPos)
						{
							LogAddr++;
							BitPos = 0;
						}	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos = 7;
						FMMUsize = ByteCount;
						if ((FMMUsize + FMMUdone)> ec_slave[slave].Obytes)
							FMMUsize = ec_slave[slave].Obytes - FMMUdone;
						LogAddr += FMMUsize;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos = 0;
					}
					FMMUdone += FMMUsize;
					ec_slave[slave].FMMU[FMMUc].PhysStartBit = 0;
					ec_slave[slave].FMMU[FMMUc].FMMUtype = 2;
					ec_slave[slave].FMMU[FMMUc].FMMUactive = 1;
					/* program FMMU for output */
					ec_FPWR (configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), sizeof(ec_fmmut), 
					         &ec_slave[slave].FMMU[FMMUc], EC_TIMEOUTRET);
					if (!ec_slave[slave].outputs)
					{	
						ec_slave[slave].outputs = pIOmap + etohl(ec_slave[slave].FMMU[FMMUc].LogStart);
						ec_slave[slave].Ostartbit = ec_slave[slave].FMMU[FMMUc].LogStartbit;
					}
					FMMUc++;
				}	
			}
        }
		ec_slave[0].outputs = pIOmap;
		if (BitPos)
		{
			LogAddr++;
			BitPos = 0;
		}	
		ec_slave[0].Obytes = LogAddr; /* store output bytes in master record */
		
		/* do input mapping of slave and program FMMUs */
		for (slave = 1; slave <= ec_slavecount; slave++)
        {
            configadr = ec_slave[slave].configadr;
			FMMUc = 1;
			if (ec_slave[slave].Obits) /* find free FMMU */
			{	
				while ( ec_slave[slave].FMMU[FMMUc].LogStart ) FMMUc++;
			}
			SMc = 0;
			BitCount = 0;
			ByteCount = 0;
			EndAddr = 0;
			FMMUsize = 0;
			FMMUdone = 0;
			/* create input mapping */
			if (ec_slave[slave].Ibits)
			{
				/* search for SM that contribute to the input mapping */
				while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((ec_slave[slave].Ibits + 7) / 8)))
				{	
					while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 3)) SMc++;
					ec_slave[slave].FMMU[FMMUc].PhysStart = ec_slave[slave].SM[SMc].StartAddr;
					SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
					ByteCount += SMlength;
					BitCount += SMlength * 8;
					EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;
					while ( (BitCount < ec_slave[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for input */
					{
						SMc++;
						while ( (SMc < (EC_MAXSM - 1)) && (ec_slave[slave].SMtype[SMc] != 3)) SMc++;
						/* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
						if ( etohs(ec_slave[slave].SM[SMc].StartAddr) > EndAddr ) break;
						SMlength = etohs(ec_slave[slave].SM[SMc].SMlength);
						ByteCount += SMlength;
						BitCount += SMlength * 8;
						EndAddr = etohs(ec_slave[slave].SM[SMc].StartAddr) + SMlength;					
					}	

					/* bit oriented slave */
					if (!ec_slave[slave].Ibytes)
					{	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos += ec_slave[slave].Ibits - 1;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
						FMMUsize = LogAddr - etohl(ec_slave[slave].FMMU[FMMUc].LogStart) + 1;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos ++;
						if (BitPos > 7)
						{
							LogAddr++;
							BitPos -= 8;
						}	
					}
					/* byte oriented slave */
					else
					{
						if (BitPos)
						{
							LogAddr++;
							BitPos = 0;
						}	
						ec_slave[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
						ec_slave[slave].FMMU[FMMUc].LogStartbit = BitPos;
						BitPos = 7;
						FMMUsize = ByteCount;
						if ((FMMUsize + FMMUdone)> ec_slave[slave].Ibytes)
							FMMUsize = ec_slave[slave].Ibytes - FMMUdone;
						LogAddr += FMMUsize;
						ec_slave[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
						ec_slave[slave].FMMU[FMMUc].LogEndbit = BitPos;
						BitPos = 0;
					}
					FMMUdone += FMMUsize;
					if (ec_slave[slave].FMMU[FMMUc].LogLength)
					{	
						ec_slave[slave].FMMU[FMMUc].PhysStartBit = 0;
						ec_slave[slave].FMMU[FMMUc].FMMUtype = 1;
						ec_slave[slave].FMMU[FMMUc].FMMUactive = 1;
						/* program FMMU for input */
						ec_FPWR (configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), sizeof(ec_fmmut), 
						         &ec_slave[slave].FMMU[FMMUc], EC_TIMEOUTRET);
					}	
					if (!ec_slave[slave].inputs)
					{	
						ec_slave[slave].inputs = pIOmap + etohl(ec_slave[slave].FMMU[FMMUc].LogStart);
						ec_slave[slave].Istartbit = ec_slave[slave].FMMU[FMMUc].LogStartbit;
					}
					FMMUc++;
				}	
			}

			ec_eeprom2pdi(slave); /* set Eeprom control to PDI */			
			ec_FPWRw(configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , EC_TIMEOUTRET); /* set safeop status */
						
		}
		ec_slave[0].inputs = pIOmap + ec_slave[0].Obytes;
		if (BitPos)
		{
			LogAddr++;
			BitPos = 0;
		}	
		ec_slave[0].Ibytes = LogAddr - ec_slave[0].Obytes; /* store input bytes in master record */
		
	}
	return LogAddr;
}	
예제 #30
0
/** FoE write, blocking.
 * 
 * @param[in]  context        = context struct
 * @param[in]  slave      = Slave number.
 * @param[in]  filename   = Filename of file to write.
 * @param[in]  password   = password.
 * @param[in]  psize      = Size in bytes of file buffer.
 * @param[out] p          = Pointer to file buffer
 * @param[in]  timeout    = Timeout per mailbox cycle in us, standard is EC_TIMEOUTRXM
 * @return Workcounter from last slave response
 */
int ecx_FOEwrite(ecx_contextt *context, uint16 slave, char *filename, uint32 password, int psize, void *p, int timeout)
{
   ec_FOEt *FOEp, *aFOEp;
   int wkc;
   int32 packetnumber, sendpacket = 0;
   uint16 fnsize, maxdata;
   int segmentdata;
   ec_mbxbuft MbxIn, MbxOut;
   uint8 cnt;
   boolean worktodo, dofinalzero;
   int tsize;

   ec_clearmbx(&MbxIn);
   /* Empty slave out mailbox if something is in. Timout set to 0 */
   wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0);
   ec_clearmbx(&MbxOut);
   aFOEp = (ec_FOEt *)&MbxIn;
   FOEp = (ec_FOEt *)&MbxOut;
   dofinalzero = FALSE;
   fnsize = strlen(filename);
   maxdata = context->slavelist[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(context->slavelist[slave].mbx_cnt);
   context->slavelist[slave].mbx_cnt = cnt;
   FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
   FOEp->OpCode = ECT_FOE_WRITE;
   FOEp->Password = htoel(password);
   /* copy filename in mailbox */
   memcpy(&FOEp->FileName[0], filename, fnsize);
   /* send FoE request to slave */
   wkc = ecx_mbxsend(context, 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 = ecx_mbxreceive(context, 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)
            {
               switch (aFOEp->OpCode)
               {
                  case ECT_FOE_ACK:
                  {
                     packetnumber = etohl(aFOEp->PacketNumber);
                     if (packetnumber == sendpacket)
                     {
                        if (context->FOEhook)
                        {
                           context->FOEhook(slave, packetnumber, psize);
                        }
                        tsize = psize;
                        if (tsize > maxdata)
                        {
                           tsize = maxdata;
                        }
                        if(tsize || dofinalzero)
                        {
                           worktodo = TRUE; 
                           dofinalzero = FALSE;
                           segmentdata = tsize;
                           psize -= segmentdata;
                           /* if last packet was full size, add a zero size packet as final */
                           /* EOF is defined as packetsize < full packetsize */
                           if (!psize && (segmentdata == maxdata))
                           {
                              dofinalzero = TRUE;
                           }
                           FOEp->MbxHeader.length = htoes(0x0006 + segmentdata);
                           FOEp->MbxHeader.address = htoes(0x0000);
                           FOEp->MbxHeader.priority = 0x00;
                           /* get new mailbox count value */
                           cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
                           context->slavelist[slave].mbx_cnt = cnt;
                           FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
                           FOEp->OpCode = ECT_FOE_DATA;
                           sendpacket++;
                           FOEp->PacketNumber = htoel(sendpacket);
                           memcpy(&FOEp->Data[0], p, segmentdata);
                           p = (uint8 *)p + segmentdata;
                           /* send FoE data to slave */
                           wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
                           if (wkc <= 0)
                           {   
                              worktodo = FALSE;
                           }
                        }
                     }
                     else
                     {
                        /* FoE error */
                        wkc = -EC_ERR_TYPE_FOE_PACKETNUMBER;
                     }
                     break;
                  }
                  case ECT_FOE_BUSY:
                  {
                     /* resend if data has been send before */
                     /* otherwise ignore */
                     if (sendpacket)
                     {
                        if (!psize)
                        {
                           dofinalzero = TRUE;
                        }
                        psize += segmentdata;
                        p = (uint8 *)p - segmentdata;
                        --sendpacket;
                     }
                     break;
                  }
                  case ECT_FOE_ERROR:
                  {
                     /* FoE error */
                     wkc = -EC_ERR_TYPE_FOE_ERROR;
                     break;
                  }
                  default:
                  {
                     /* unexpected mailbox received */
                     wkc = -EC_ERR_TYPE_PACKET_ERROR;
                     break;
                  }
               }
            }
            else
            {
               /* unexpected mailbox received */
               wkc = -EC_ERR_TYPE_PACKET_ERROR;
            }
         }
      } while (worktodo);   
   }
   
   return wkc;
}