| 
 | 1 | +#include <stddef.h>  | 
 | 2 | +#include "utypes.h"  | 
 | 3 | +#include "soes/esc.h"  | 
 | 4 | +#include "soes/esc_coe.h"  | 
 | 5 | +#include "soes/esc_foe.h"  | 
 | 6 | +#include "slave.h"  | 
 | 7 | + | 
 | 8 | +#ifndef EEP_EMULATION  | 
 | 9 | +#define EEP_EMULATION   0       /* Set to 1 for EEPROM emulation */  | 
 | 10 | +#endif  | 
 | 11 | + | 
 | 12 | +#define WATCHDOG_RESET_VALUE 150  | 
 | 13 | +#define DEFAULTTXPDOMAP    0x1a00  | 
 | 14 | +#define DEFAULTRXPDOMAP    0x1600  | 
 | 15 | +#define DEFAULTTXPDOITEMS  1  | 
 | 16 | +#define DEFAULTRXPDOITEMS  1  | 
 | 17 | + | 
 | 18 | +volatile _ESCvar  ESCvar;  | 
 | 19 | +_MBX              MBX[MBXBUFFERS];  | 
 | 20 | +_MBXcontrol       MBXcontrol[MBXBUFFERS];  | 
 | 21 | +uint8_t           MBXrun=0;  | 
 | 22 | +uint16_t          SM2_sml,SM3_sml;  | 
 | 23 | +_Rbuffer          Rb;  | 
 | 24 | +_Wbuffer          Wb;  | 
 | 25 | +_Cbuffer          Cb;  | 
 | 26 | +_App              App;  | 
 | 27 | +uint16_t          TXPDOsize,RXPDOsize;  | 
 | 28 | +uint16_t          txpdomap = DEFAULTTXPDOMAP;  | 
 | 29 | +uint16_t          rxpdomap = DEFAULTRXPDOMAP;  | 
 | 30 | +uint8_t           txpdoitems = DEFAULTTXPDOITEMS;  | 
 | 31 | +uint8_t           rxpdoitems = DEFAULTTXPDOITEMS;  | 
 | 32 | + | 
 | 33 | +static unsigned int watchdog = WATCHDOG_RESET_VALUE;  | 
 | 34 | +static void (*application_loop_callback)(void) = NULL;  | 
 | 35 | + | 
 | 36 | +/** Mandatory: Hook called from the slave stack SDO Download handler to act on  | 
 | 37 | + * user specified Index and Sub-index.  | 
 | 38 | + *  | 
 | 39 | + * @param[in] index      = index of SDO download request to handle  | 
 | 40 | + * @param[in] sub-index  = sub-index of SDO download request to handle  | 
 | 41 | + */  | 
 | 42 | +void ESC_objecthandler (uint16_t index, uint8_t subindex)  | 
 | 43 | +{  | 
 | 44 | +   switch (index)  | 
 | 45 | +   {  | 
 | 46 | +   case 0x1c12:  | 
 | 47 | +   {  | 
 | 48 | +      if (rxpdoitems > 1)  | 
 | 49 | +      {  | 
 | 50 | +         rxpdoitems = 1;  | 
 | 51 | +      }  | 
 | 52 | +      if ((rxpdomap != 0x1600) && (rxpdomap != 0x1601)  | 
 | 53 | +          && (rxpdomap != 0x0000))  | 
 | 54 | +      {  | 
 | 55 | +         rxpdomap = 0x1600;  | 
 | 56 | +      }  | 
 | 57 | +      RXPDOsize = SM2_sml = sizeRXPDO();  | 
 | 58 | +      break;  | 
 | 59 | +   }  | 
 | 60 | +   case 0x1c13:  | 
 | 61 | +   {  | 
 | 62 | +      if (txpdoitems > 1)  | 
 | 63 | +      {  | 
 | 64 | +         txpdoitems = 1;  | 
 | 65 | +      }  | 
 | 66 | +      if ((txpdomap != 0x1A00) && (txpdomap != 0x1A01)  | 
 | 67 | +          && (rxpdomap != 0x0000))  | 
 | 68 | +      {  | 
 | 69 | +         txpdomap = 0x1A00;  | 
 | 70 | +      }  | 
 | 71 | +      TXPDOsize = SM3_sml = sizeTXPDO();  | 
 | 72 | +      break;  | 
 | 73 | +   }  | 
 | 74 | +   /* Handle post-write of parameter values */  | 
 | 75 | +   case 0x8000:  | 
 | 76 | +   {  | 
 | 77 | +      cb_post_write_Parameters(subindex);  | 
 | 78 | +      break;  | 
 | 79 | +   }  | 
 | 80 | +   default:  | 
 | 81 | +      break;  | 
 | 82 | +   }  | 
 | 83 | +}  | 
 | 84 | + | 
 | 85 | +/** Mandatory: Hook called from the slave stack ESC_stopoutputs to act on state changes  | 
 | 86 | + * forcing us to stop outputs. Here we can set them to a safe state.  | 
 | 87 | + * set  | 
 | 88 | + */  | 
 | 89 | +void APP_safeoutput (void)  | 
 | 90 | +{  | 
 | 91 | +   DPRINT ("APP_safeoutput\n");  | 
 | 92 | + | 
 | 93 | +   // Set safe values for Wb.LEDs  | 
 | 94 | +   Wb.LEDs.LED0 = 0;  | 
 | 95 | +   Wb.LEDs.LED1 = 0;  | 
 | 96 | + | 
 | 97 | +}  | 
 | 98 | + | 
 | 99 | +/** Mandatory: Write local process data to Sync Manager 3, Master Inputs.  | 
 | 100 | + */  | 
 | 101 | +void TXPDO_update (void)  | 
 | 102 | +{  | 
 | 103 | +   ESC_write (SM3_sma, &Rb, TXPDOsize);  | 
 | 104 | +}  | 
 | 105 | +/** Mandatory: Read Sync Manager 2 to local process data, Master Outputs.  | 
 | 106 | + */  | 
 | 107 | +void RXPDO_update (void)  | 
 | 108 | +{  | 
 | 109 | +   ESC_read (SM2_sma, &Wb, RXPDOsize);  | 
 | 110 | +}  | 
 | 111 | + | 
 | 112 | +/** Mandatory: Function to update local I/O, call read ethercat outputs, call  | 
 | 113 | + * write ethercat inputs. Implement watch-dog counter to count-out if we have  | 
 | 114 | + * made state change affecting the App.state.  | 
 | 115 | + */  | 
 | 116 | +void DIG_process (void)  | 
 | 117 | +{  | 
 | 118 | +   if (watchdog > 0)  | 
 | 119 | +   {  | 
 | 120 | +      watchdog--;  | 
 | 121 | +   }  | 
 | 122 | +   if (App.state & APPSTATE_OUTPUT)  | 
 | 123 | +   {  | 
 | 124 | +      /* SM2 trigger ? */  | 
 | 125 | +      if (ESCvar.ALevent & ESCREG_ALEVENT_SM2)  | 
 | 126 | +      {  | 
 | 127 | +         ESCvar.ALevent &= ~ESCREG_ALEVENT_SM2;  | 
 | 128 | +         RXPDO_update();  | 
 | 129 | +         watchdog = WATCHDOG_RESET_VALUE;  | 
 | 130 | + | 
 | 131 | +         /* Set outputs */  | 
 | 132 | +         cb_set_LEDs();  | 
 | 133 | +      }  | 
 | 134 | +      if (watchdog == 0)  | 
 | 135 | +      {  | 
 | 136 | +         DPRINT("DIG_process watchdog expired\n");  | 
 | 137 | +         ESC_stopoutput();  | 
 | 138 | +         /* watchdog, invalid outputs */  | 
 | 139 | +         ESC_ALerror (ALERR_WATCHDOG);  | 
 | 140 | +         /* goto safe-op with error bit set */  | 
 | 141 | +         ESC_ALstatus (ESCsafeop | ESCerror);  | 
 | 142 | +      }  | 
 | 143 | +   }  | 
 | 144 | +   else  | 
 | 145 | +   {  | 
 | 146 | +      watchdog = WATCHDOG_RESET_VALUE;  | 
 | 147 | +   }  | 
 | 148 | +   if (App.state)  | 
 | 149 | +   {  | 
 | 150 | +      /* Update inputs */  | 
 | 151 | +      cb_get_Buttons();  | 
 | 152 | +      TXPDO_update();  | 
 | 153 | +   }  | 
 | 154 | +}  | 
 | 155 | + | 
 | 156 | +/********** TODO: Generic code beyond this point ***************/  | 
 | 157 | + | 
 | 158 | +static const char *spi_name = "/dev/lan9252";  | 
 | 159 | + | 
 | 160 | +/** Optional: Hook called after state change for application specific  | 
 | 161 | + * actions for specific state changes.  | 
 | 162 | + */  | 
 | 163 | +void post_state_change_hook (uint8_t * as, uint8_t * an)  | 
 | 164 | +{  | 
 | 165 | +#if 0  | 
 | 166 | +   /* Add specific step change hooks here */  | 
 | 167 | +   if ((*as == BOOT_TO_INIT) && (*an == ESCinit))  | 
 | 168 | +   {  | 
 | 169 | +      boot_inithook();  | 
 | 170 | +   }  | 
 | 171 | +   else if((*as == INIT_TO_BOOT) && (*an & ESCerror ) == 0)  | 
 | 172 | +   {  | 
 | 173 | +      init_boothook();  | 
 | 174 | +   }  | 
 | 175 | +#endif  | 
 | 176 | +}  | 
 | 177 | + | 
 | 178 | +/**  | 
 | 179 | + * Set callback run once every loop in the SOES application loop.  | 
 | 180 | + */  | 
 | 181 | +void set_application_loop_hook(void (*callback)(void))  | 
 | 182 | +{  | 
 | 183 | +   application_loop_callback = callback;  | 
 | 184 | +}  | 
 | 185 | + | 
 | 186 | +/**  | 
 | 187 | + * SOES main function. It should be called periodically.  | 
 | 188 | + * Reads the EtherCAT state and status. Responsible for I/O updates.  | 
 | 189 | + */  | 
 | 190 | +void soes (void)  | 
 | 191 | +{  | 
 | 192 | +   /* On init restore PDO mappings to default size */  | 
 | 193 | +   if((ESCvar.ALstatus & 0x0f) == ESCinit)  | 
 | 194 | +   {  | 
 | 195 | +      txpdomap = DEFAULTTXPDOMAP;  | 
 | 196 | +      rxpdomap = DEFAULTRXPDOMAP;  | 
 | 197 | +      txpdoitems = DEFAULTTXPDOITEMS;  | 
 | 198 | +      rxpdoitems = DEFAULTTXPDOITEMS;  | 
 | 199 | +   }  | 
 | 200 | + | 
 | 201 | +   /* Read local time from ESC */  | 
 | 202 | +   ESC_read (ESCREG_LOCALTIME, (void *) &ESCvar.Time, sizeof (ESCvar.Time));  | 
 | 203 | +   ESCvar.Time = etohl (ESCvar.Time);  | 
 | 204 | + | 
 | 205 | +   /* Check the state machine */  | 
 | 206 | +   ESC_state();  | 
 | 207 | + | 
 | 208 | +   /* Check mailboxes */  | 
 | 209 | +   if (ESC_mbxprocess())  | 
 | 210 | +   {  | 
 | 211 | +      ESC_coeprocess();  | 
 | 212 | +      ESC_foeprocess();  | 
 | 213 | +      ESC_xoeprocess();  | 
 | 214 | +   }  | 
 | 215 | +   DIG_process();  | 
 | 216 | +#if EEP_EMULATION  | 
 | 217 | +   EEP_process ();  | 
 | 218 | +   EEP_hw_process();  | 
 | 219 | +#endif  /* EEP_EMULATION */  | 
 | 220 | + | 
 | 221 | +   if (application_loop_callback != NULL)  | 
 | 222 | +   {  | 
 | 223 | +      (application_loop_callback)();  | 
 | 224 | +   }  | 
 | 225 | +}  | 
 | 226 | + | 
 | 227 | +/**  | 
 | 228 | + * Initialize the SOES stack.  | 
 | 229 | + */  | 
 | 230 | +void soes_init (void)  | 
 | 231 | +{  | 
 | 232 | +   DPRINT ("SOES (Simple Open EtherCAT Slave)\n");  | 
 | 233 | + | 
 | 234 | +   TXPDOsize = SM3_sml = sizeTXPDO();  | 
 | 235 | +   RXPDOsize = SM2_sml = sizeRXPDO();  | 
 | 236 | + | 
 | 237 | +   /* Setup post config hooks */  | 
 | 238 | +   static esc_cfg_t config =  | 
 | 239 | +   {  | 
 | 240 | +      .pre_state_change_hook = NULL,  | 
 | 241 | +      .post_state_change_hook = post_state_change_hook  | 
 | 242 | +   };  | 
 | 243 | +   ESC_config ((esc_cfg_t *)&config);  | 
 | 244 | + | 
 | 245 | +   ESC_reset();  | 
 | 246 | +   ESC_init ((void *)spi_name);  | 
 | 247 | + | 
 | 248 | +   /*  wait until ESC is started up */  | 
 | 249 | +   while ((ESCvar.DLstatus & 0x0001) == 0)  | 
 | 250 | +   {  | 
 | 251 | +      ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,  | 
 | 252 | +                sizeof (ESCvar.DLstatus));  | 
 | 253 | +      ESCvar.DLstatus = etohs (ESCvar.DLstatus);  | 
 | 254 | +   }  | 
 | 255 | + | 
 | 256 | +   /* Init FoE */  | 
 | 257 | +   FOE_init();  | 
 | 258 | + | 
 | 259 | +   /* reset ESC to init state */  | 
 | 260 | +   ESC_ALstatus (ESCinit);  | 
 | 261 | +   ESC_ALerror (ALERR_NONE);  | 
 | 262 | +   ESC_stopmbx();  | 
 | 263 | +   ESC_stopinput();  | 
 | 264 | +   ESC_stopoutput();  | 
 | 265 | +}  | 
0 commit comments