Exemple #1
0
/**
 * Initialize the slave stack.
 */
void ecat_slv_init (esc_cfg_t * config)
{
   DPRINT ("Slave stack init started\n");

   ESCvar.TXPDOsize = ESCvar.ESC_SM3_sml = sizeOfPDO(TX_PDO_OBJIDX);
   ESCvar.RXPDOsize = ESCvar.ESC_SM2_sml = sizeOfPDO(RX_PDO_OBJIDX);

   /* Init watchdog */
   watchdog = config->watchdog_cnt;

   /* Call stack configuration */
   ESC_config (config);
   /* Call HW init */
   ESC_init (config);

   /*  wait until ESC is started up */
   while ((ESCvar.DLstatus & 0x0001) == 0)
   {
      ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,
                sizeof (ESCvar.DLstatus));
      ESCvar.DLstatus = etohs (ESCvar.DLstatus);
   }

   /* Init FoE */
   FOE_init();

   /* reset ESC to init state */
   ESC_ALstatus (ESCinit);
   ESC_ALerror (ALERR_NONE);
   ESC_stopmbx();
   ESC_stopinput();
   ESC_stopoutput();
}
Exemple #2
0
/** Function trying to enable start updating the process data inputs. It calls the check SM 2 & 3
 * routine, based on the result from there if enables or disables the Input SyncManager, in addition
 * it updates the ALStatusCode case something didn't pass the check.
 *
 * @param[in] state   = Requested state.
 * @return = state, incoming state request if every thing checks out OK. =state (PREOP | ERROR) if something isn't correct.
 */
uint8_t ESC_startinput (uint8_t state)
{
   state = ESC_checkSM23 (state);
   if (state != (ESCpreop | ESCerror))
   {
      ESC_SMenable (3);
      App.state = APPSTATE_INPUT;
   }
   else
   {
      ESC_SMdisable (2);
      ESC_SMdisable (3);
      if (ESCvar.SMtestresult & SMRESULT_ERRSM3)
      {
         ESC_ALerror (ALERR_INVALIDINPUTSM);
      }
      else
      {
         ESC_ALerror (ALERR_INVALIDOUTPUTSM);
      }
   }
   return state;
}
Exemple #3
0
/** Try to start bootstrap mailboxes for current ALControl state request by enabling SyncManager 0 and 1.
 * If all mailbox settings is correct we return incoming state request, otherwise
 * we return state Init with Error flag set and update local ALerror with code 0x16 Invalid
 * mailbox configuration.
 *
 * @param[in] state   = Current state request read from ALControl 0x0120
 * @return if all Mailbox values is correct we return incoming state, otherwise
 * we return state Init with Error flag set.
 */
uint8_t ESC_startmbxboot (uint8_t state)
{
   ESC_SMenable (0);
   ESC_SMenable (1);
   ESC_SMstatus (0);
   ESC_SMstatus (1);
   if ((state = ESC_checkmbxboot (state)) & ESCerror)
   {
      ESC_ALerror (ALERR_INVALIDBOOTMBXCONFIG);
      MBXrun = 0;
   }
   else
   {
      ESCvar.toggle = ESCvar.SM[1].ECrep;       //sync repeat request toggle state
      MBXrun = 1;
   }
   return state;
}
Exemple #4
0
/** Mandatory: Function to update local I/O, call read ethercat outputs, call
 * write ethercat inputs. Implement watch-dog counter to count-out if we have
 * made state change affecting the App.state.
 */
void DIG_process (void)
{
   if (wd_cnt)
   {
      wd_cnt--;
   }
   if (App.state & APPSTATE_OUTPUT)
   {
      /* SM2 trigger ? */
      if (ESCvar.ALevent & ESCREG_ALEVENT_SM2)
      {
         ESCvar.ALevent &= ~ESCREG_ALEVENT_SM2;
         RXPDO_update ();
         wd_cnt = WD_RESET;
         /* dummy output point */
         //gpio_set(GPIO_LED, Wb.LED & BIT(0));
      }
      if (!wd_cnt)
      {
         DPRINT("DIG_process watchdog tripped\n");
         ESC_stopoutput ();
         /* watchdog, invalid outputs */
         ESC_ALerror (ALERR_WATCHDOG);
         /* goto safe-op with error bit set */
         ESC_ALstatus (ESCsafeop | ESCerror);
      }
   }
   else
   {
      wd_cnt = WD_RESET;
   }
   if (App.state)
   {
      //Rb.button = gpio_get(GPIO_WAKEUP);
      Rb.button = (flash_drv_get_active_swap() && 0x8);
      Cb.reset_counter++;
      Rb.encoder =  Cb.reset_counter;
      TXPDO_update ();
   }
}
Exemple #5
0
/** SOES main loop. Start by initializing the stack software followed by
 * the application loop for cyclic read the EtherCAT state and staus, update
 * of I/O.
 */
void soes (void *arg)
{
   DPRINT ("SOES (Simple Open EtherCAT Slave)\n");

   TXPDOsize = SM3_sml = sizeTXPDO ();
   RXPDOsize = SM2_sml = sizeRXPDO ();

   /* Setup post config hooks */
   static esc_cfg_t config =
   {
      .pre_state_change_hook = NULL,
      .post_state_change_hook = post_state_change_hook
   };
   ESC_config ((esc_cfg_t *)&config);

   ESC_reset();
   ESC_init (spi_name);

   task_delay (tick_from_ms (200));

   /*  wait until ESC is started up */
   while ((ESCvar.DLstatus & 0x0001) == 0)
   {
      ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,
                sizeof (ESCvar.DLstatus));
      ESCvar.DLstatus = etohs (ESCvar.DLstatus);
   }

   /* Pre FoE to set up Application information */
   bootstrap_foe_init ();
   /* Init FoE */
   FOE_init();

   /* reset ESC to init state */
   ESC_ALstatus (ESCinit);
   ESC_ALerror (ALERR_NONE);
   ESC_stopmbx ();
   ESC_stopinput ();
   ESC_stopoutput ();

   DPRINT ("Application_loop GO\n");
   /* application run loop */
   while (1)
   {
      /* On init restore PDO mappings to default size */
      if((ESCvar.ALstatus & 0x0f) == ESCinit)
      {
         txpdomap = DEFAULTTXPDOMAP;
         rxpdomap = DEFAULTRXPDOMAP;
         txpdoitems = DEFAULTTXPDOITEMS;
         rxpdoitems = DEFAULTTXPDOITEMS;
      }
      /* Read local time from ESC*/
      ESC_read (ESCREG_LOCALTIME, (void *) &ESCvar.Time, sizeof (ESCvar.Time));
      ESCvar.Time = etohl (ESCvar.Time);

      /* Check the state machine */
      ESC_state ();

      /* If else to two separate execution paths
       * If we're running BOOSTRAP
       *  - MailBox
       *   - FoE
       * Else we're running normal execution
       *  - MailBox
       *   - CoE
       */
      if(local_boot_state)
      {
         if (ESC_mbxprocess ())
         {
            ESC_foeprocess ();
            ESC_xoeprocess ();
         }
         bootstrap_state ();
       }
      else
      {
         if (ESC_mbxprocess ())
         {
            ESC_coeprocess ();
            ESC_xoeprocess ();
         }
         DIG_process ();
      }
   };
}
Exemple #6
0
/** The state handler acting on ALControl Bit(0) and SyncManager Activation BIT(4)
 * events in the Al Event Request register 0x220.
 *
 */
void ESC_state (void)
{
   uint8_t ac, an, as, ax, ax23;
   uint8_t handle_smchanged = 0;

   /* Do we have a state change request pending */
   if (ESCvar.ALevent & ESCREG_ALEVENT_CONTROL)
   {
      ESC_read (ESCREG_ALCONTROL, (void *) &ESCvar.ALcontrol,
                sizeof (ESCvar.ALcontrol), (void *) &ESCvar.ALevent);
      ESCvar.ALcontrol = etohs (ESCvar.ALcontrol);
   }
   /* Have at least on Sync Manager  changed */
   else if (ESCvar.ALevent & ESCREG_ALEVENT_SMCHANGE)
   {
      handle_smchanged  = 1;
   }
   else
   {
      /* nothing to do */
      return;
   }
   /* Mask state request bits + Error ACK */
   ac = ESCvar.ALcontrol & ESCREG_AL_STATEMASK;
   as = ESCvar.ALstatus & ESCREG_AL_STATEMASK;
   an = as;
   if (((ac & ESCerror) || (ac == ESCinit)))
   {
      /* if error bit confirmed reset */
      ac &= ESCREG_AL_ERRACKMASK;
      an &= ESCREG_AL_ERRACKMASK;
   }
   /* Enter SM changed handling for all steps but Init and Boot when Mailboxes
    * is up and running
    */
   if (handle_smchanged && (as & ESCREG_AL_ALLBUTINITMASK) &&
       !(as == ESCboot) && MBXrun)
   {
      /* Validate Sync Managers, reading the Activation register will
       * acknowledge the SyncManager Activation event making us enter
       * this execution path.
       */
      ax = ESC_checkmbx (as);
      ax23 = ESC_checkSM23 (as);
      if ((an & ESCerror) && !(ac & ESCerror))
      {
         /* if in error then stay there */
         return;
      }
      /* Have we been forced to step down to INIT we will stop mailboxes,
       * update AL Status Code and exit ESC_state
       */
      if (ax == (ESCinit | ESCerror))
      {
         /* If we have activated Inputs and Outputs we need to disable them */
         if (App.state)
         {
            ESC_stopoutput ();
            ESC_stopinput ();
         }
         /* Stop mailboxes and update ALStatus code */
         ESC_stopmbx ();
         ESC_ALerror (ALERR_INVALIDMBXCONFIG);
         MBXrun = 0;
         ESC_ALstatus (ax);
         return;
      }
      /* Have we been forced to step down to PREOP we will stop inputs
       * and outputs, update AL Status Code and exit ESC_state
       */
      if ((App.state) && (ax23 == (ESCpreop | ESCerror)))
      {
         ESC_stopoutput ();
         ESC_stopinput ();
         if (ESCvar.SMtestresult & SMRESULT_ERRSM3)
         {
            ESC_ALerror (ALERR_INVALIDINPUTSM);
         }
         else
         {
            ESC_ALerror (ALERR_INVALIDOUTPUTSM);
         }
         ESC_ALstatus (ax23);
         return;
      }
   }

   /* Error state not acked, leave original */
   if ((an & ESCerror) && !(ac & ESCerror))
   {
      return;
   }

   /* Mask high bits ALcommand, low bits ALstatus */
   as = (ac << 4) | (as & 0x0f);

   /* Call post state change hook case it have been configured  */
   if ((esc_cfg != NULL) && esc_cfg->pre_state_change_hook)
   {
      esc_cfg->pre_state_change_hook (&as, &an);
   }

   /* Switch through the state change requested via AlControl from
    * current state read in AL status
    */
   switch (as)
   {
      case INIT_TO_INIT:
      case PREOP_TO_PREOP:
      case OP_TO_OP:
      {
         break;
      }
      case INIT_TO_PREOP:
      {
         /* get station address */
         ESC_address ();
         an = ESC_startmbx (ac);
         break;
      }
      case INIT_TO_BOOT:
      case BOOT_TO_BOOT:
      {
         /* get station address */
         ESC_address ();
         an = ESC_startmbxboot (ac);
         break;
      }
      case INIT_TO_SAFEOP:
      case INIT_TO_OP:
      {
         an = ESCinit | ESCerror;
         ESC_ALerror (ALERR_INVALIDSTATECHANGE);
         break;
      }
      case OP_TO_INIT:
      {
         ESC_stopoutput ();
      }
      case SAFEOP_TO_INIT:
      {
         ESC_stopinput ();
      }
      case PREOP_TO_INIT:
      {
         ESC_stopmbx ();
         an = ESCinit;
         break;
      }
      case BOOT_TO_INIT:
      {
         ESC_stopmbx ();
         an = ESCinit;
         break;
      }
      case PREOP_TO_BOOT:
      case BOOT_TO_PREOP:
      case BOOT_TO_SAFEOP:
      case BOOT_TO_OP:
      {
         an = ESCpreop | ESCerror;
         ESC_ALerror (ALERR_INVALIDSTATECHANGE);
         break;
      }
      case PREOP_TO_SAFEOP:
      case SAFEOP_TO_SAFEOP:
      {
         SM2_sml = sizeRXPDO ();
         SM3_sml = sizeTXPDO ();
         an = ESC_startinput (ac);
         if (an == ac)
         {
            ESC_SMenable (2);
         }
         break;
      }
      case PREOP_TO_OP:
      {
         an = ESCpreop | ESCerror;
         ESC_ALerror (ALERR_INVALIDSTATECHANGE);
         break;
      }
      case OP_TO_PREOP:
      {
         ESC_stopoutput ();
      }
      case SAFEOP_TO_PREOP:
      {
         ESC_stopinput ();
         an = ESCpreop;
         break;
      }
      case SAFEOP_TO_BOOT:
      {
         an = ESCsafeop | ESCerror;
         ESC_ALerror (ALERR_INVALIDSTATECHANGE);
         break;
      }
      case SAFEOP_TO_OP:
      {
         an = ESC_startoutput (ac);
         break;
      }
      case OP_TO_BOOT:
      {
         an = ESCsafeop | ESCerror;
         ESC_ALerror (ALERR_INVALIDSTATECHANGE);
         ESC_stopoutput ();
         break;
      }
      case OP_TO_SAFEOP:
      {
         an = ESCsafeop;
         ESC_stopoutput ();
         break;
      }
      default:
      {
         if (an == ESCop)
         {
            ESC_stopoutput ();
            an = ESCsafeop;
         }
         if (as == ESCsafeop)
         {
            ESC_stopinput ();
         }
         an |= ESCerror;
         ESC_ALerror (ALERR_UNKNOWNSTATE);
         break;
      }
   }

   /* Call post state change hook case it have been configured  */
   if ((esc_cfg != NULL) && esc_cfg->post_state_change_hook)
   {
      esc_cfg->post_state_change_hook (&as, &an);
   }

   if (!(an & ESCerror) && (ESCvar.ALerror))
   {
      /* clear error */
      ESC_ALerror (ALERR_NONE);
   }

   ESC_ALstatus (an);

}
Exemple #7
0
/** Mandatory: Function to update local I/O, call read ethercat outputs, call
 * write ethercat inputs. Implement watch-dog counter to count-out if we have
 * made state change affecting the App.state.
 */
void DIG_process (uint8_t flags)
{
   /* Handle watchdog */
   if((flags & DIG_PROCESS_WD_FLAG) > 0)
   {

      if (CC_ATOMIC_GET(watchdog) > 0)
      {
         CC_ATOMIC_SUB(watchdog, 1);
      }

      if ((CC_ATOMIC_GET(watchdog) <= 0) &&
          ((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0))
      {
         DPRINT("DIG_process watchdog expired\n");
         ESC_stopoutput();
         /* watchdog, invalid outputs */
         ESC_ALerror (ALERR_WATCHDOG);
         /* goto safe-op with error bit set */
         ESC_ALstatus (ESCsafeop | ESCerror);
      }
      else if(((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) == 0))
      {
         CC_ATOMIC_SET(watchdog, ESCvar.watchdogcnt);
      }
   }

   /* Handle Outputs */
   if ((flags & DIG_PROCESS_OUTPUTS_FLAG) > 0)
   {
      if(((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0) &&
         (ESCvar.ALevent & ESCREG_ALEVENT_SM2))
      {
         RXPDO_update();
         CC_ATOMIC_SET(watchdog, ESCvar.watchdogcnt);
         if(ESCvar.dcsync > 0)
         {
            CC_ATOMIC_ADD(ESCvar.synccounter, 1);
         }
         /* Set outputs */
         cb_set_LEDgroup0();
         cb_set_LEDgroup1();
      }
      else if (ESCvar.ALevent & ESCREG_ALEVENT_SM2)
      {
         RXPDO_update();
      }
   }

   /* Call application */
   if ((flags & DIG_PROCESS_APP_HOOK_FLAG) > 0)
   {

      if((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0)
      {
         CC_ATOMIC_SUB(ESCvar.synccounter, 1);
      }

      if((ESCvar.dcsync > 0) &&
            ((CC_ATOMIC_GET(ESCvar.synccounter) < -ESCvar.synccounterlimit) ||
             (CC_ATOMIC_GET(ESCvar.synccounter) > ESCvar.synccounterlimit)))
      {
         if((CC_ATOMIC_GET(ESCvar.App.state) & APPSTATE_OUTPUT) > 0)
         {
            DPRINT("sync error = %d\n", ESCvar.synccounter);
            ESC_stopoutput();
            /* Sync error */
            ESC_ALerror (ALERR_SYNCERROR);
            /* goto safe-op with error bit set */
            ESC_ALstatus (ESCsafeop | ESCerror);
            CC_ATOMIC_SET(ESCvar.synccounter, 0);
         }
      }
      /* Call application callback if set */
      if (ESCvar.application_hook != NULL)
      {
         (ESCvar.application_hook)();
      }
   }

   /* Handle Inputs */
   if ((flags & DIG_PROCESS_INPUTS_FLAG) > 0)
   {
      if(CC_ATOMIC_GET(ESCvar.App.state) > 0)
      {
         /* Update inputs */
         cb_get_Buttons();
         TXPDO_update();
      }
   }
}