Add define USE_MBX to disable mailbox support

pull/165/head
iwoodsawyer 2021-05-03 22:13:18 -07:00
parent 1eb3389790
commit 64385e592c
7 changed files with 117 additions and 56 deletions

View File

@ -5,42 +5,55 @@
#define DYN_PDO_MAPPING 1 #define DYN_PDO_MAPPING 1
#define USE_MBX 0
#define USE_FOE 0 #define USE_FOE 0
#define USE_EOE 0 #define USE_EOE 0
#if USE_MBX
#define MBXSIZE 128
#define MBXSIZEBOOT 128
#else
#define MBXSIZE 0 #define MBXSIZE 0
#define MBXSIZEBOOT 0 #define MBXSIZEBOOT 0
#endif
#define MBXBUFFERS 3 #define MBXBUFFERS 3
#define MBX0_sma 0x1000 #define SM0_sma 0x1000
#define SM0_smc 0x64
#define SM0_act 1
#define SM1_sma 0x1200
#define SM1_smc 0x20
#define SM1_act 1
#define MBX0_sma SM0_sma
#define MBX0_sml MBXSIZE #define MBX0_sml MBXSIZE
#define MBX0_sme MBX0_sma+MBX0_sml-1 #define MBX0_sme MBX0_sma+MBX0_sml-1
#define MBX0_smc 0x64 #define MBX0_smc SM0_smc
#define MBX1_sma 0x1200 #define MBX1_sma SM1_sma
#define MBX1_sml MBXSIZE #define MBX1_sml MBXSIZE
#define MBX1_sme MBX1_sma+MBX1_sml-1 #define MBX1_sme MBX1_sma+MBX1_sml-1
#define MBX1_smc 0x20 #define MBX1_smc SM1_act
#define MBX0_sma_b 0x1000 #define MBX0_sma_b SM0_sma
#define MBX0_sml_b MBXSIZEBOOT #define MBX0_sml_b MBXSIZEBOOT
#define MBX0_sme_b MBX0_sma_b+MBX0_sml_b-1 #define MBX0_sme_b MBX0_sma_b+MBX0_sml_b-1
#define MBX0_smc_b 0x64 #define MBX0_smc_b SM0_smc
#define MBX1_sma_b 0x1200 #define MBX1_sma_b SM1_sma
#define MBX1_sml_b MBXSIZEBOOT #define MBX1_sml_b MBXSIZEBOOT
#define MBX1_sme_b MBX1_sma_b+MBX1_sml_b-1 #define MBX1_sme_b MBX1_sma_b+MBX1_sml_b-1
#define MBX1_smc_b 0x20 #define MBX1_smc_b SM1_act
#define SM2_sma 0x1000 #define SM2_sma SM0_sma
#define SM2_smc 0x64 #define SM2_smc SM0_smc
#define SM2_act 1 #define SM2_act SM0_act
#define SM3_sma 0x1200 #define SM3_sma SM1_sma
#define SM3_smc 0x20 #define SM3_smc SM1_smc
#define SM3_act 1 #define SM3_act SM1_act
#define MAX_RXPDO_SIZE 128 #define MAX_RXPDO_SIZE 128
#define MAX_TXPDO_SIZE 128 #define MAX_TXPDO_SIZE 128
#ifdef DYN_PDO_MAPPING #if DYN_PDO_MAPPING
#define MAX_MAPPINGS_SM2 1 #define MAX_MAPPINGS_SM2 1
#define MAX_MAPPINGS_SM3 1 #define MAX_MAPPINGS_SM3 1
#else #else

View File

@ -308,16 +308,11 @@ static const char acName1C00_03[] = "Communications type SM2";
static const char acName1C00_04[] = "Communications type SM3"; static const char acName1C00_04[] = "Communications type SM3";
static const char acName1C10[] = "Sync Manager 0 PDO Assignment"; static const char acName1C10[] = "Sync Manager 0 PDO Assignment";
static const char acName1C10_00[] = "Max SubIndex"; static const char acName1C10_00[] = "Max SubIndex";
//static const char acName1C10_01[] = "PDO Mapping"; static const char acName1C10_01[] = "PDO Mapping";
static const char acName1C11[] = "Sync Manager 1 PDO Assignment"; static const char acName1C11[] = "Sync Manager 1 PDO Assignment";
static const char acName1C11_00[] = "Max SubIndex"; static const char acName1C11_00[] = "Max SubIndex";
//static const char acName1C11_01[] = "PDO Mapping"; static const char acName1C11_01[] = "PDO Mapping";
static const char acName1C12[] = "Sync Manager 2 PDO Assignment";
static const char acName1C12_00[] = "Max SubIndex";
static const char acName1C12_01[] = "PDO Mapping";
static const char acName1C13[] = "Sync Manager 3 PDO Assignment";
static const char acName1C13_00[] = "Max SubIndex";
static const char acName1C13_01[] = "PDO Mapping";
const _objd SDO1000[] = const _objd SDO1000[] =
{ {
@ -636,30 +631,23 @@ const _objd SDO1A00[] =
const _objd SDO1C00[] = const _objd SDO1C00[] =
{ {
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_00, 4, NULL}, {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_00, 4, NULL},
{0x01, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_01, 0, NULL}, {0x01, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_01, 3, NULL},
{0x02, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_02, 0, NULL}, {0x02, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_02, 4, NULL},
{0x03, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_03, 3, NULL}, {0x03, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_03, 0, NULL},
{0x04, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_04, 4, NULL}, {0x04, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C00_04, 0, NULL},
}; };
const _objd SDO1C10[] = const _objd SDO1C10[] =
{ {
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C10_00, 0, NULL}, {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C10_00, 1, NULL},
{0x01, DTYPE_UNSIGNED16, 16, ATYPE_RO, acName1C10_01, 0x1600, NULL},
}; };
const _objd SDO1C11[] = const _objd SDO1C11[] =
{ {
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C11_00, 0, NULL}, {0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C11_00, 1, NULL},
}; {0x01, DTYPE_UNSIGNED16, 16, ATYPE_RO, acName1C11_01, 0x1A00, NULL},
const _objd SDO1C12[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C12_00, 1, NULL},
{0x01, DTYPE_UNSIGNED16, 16, ATYPE_RO, acName1C12_01, 0x1600, NULL},
};
const _objd SDO1C13[] =
{
{0x00, DTYPE_UNSIGNED8, 8, ATYPE_RO, acName1C13_00, 1, NULL},
{0x01, DTYPE_UNSIGNED16, 16, ATYPE_RO, acName1C13_01, 0x1A00, NULL},
}; };
const _objectlist SDOobjects[] = const _objectlist SDOobjects[] =
{ {
{0x1000, OTYPE_VAR, 0, 0, acName1000, SDO1000}, {0x1000, OTYPE_VAR, 0, 0, acName1000, SDO1000},
@ -670,9 +658,7 @@ const _objectlist SDOobjects[] =
{0x1600, OTYPE_RECORD, BYTE_NUM, 0, acName1600, SDO1600}, {0x1600, OTYPE_RECORD, BYTE_NUM, 0, acName1600, SDO1600},
{0x1A00, OTYPE_RECORD, BYTE_NUM, 0, acName1A00, SDO1A00}, {0x1A00, OTYPE_RECORD, BYTE_NUM, 0, acName1A00, SDO1A00},
{0x1C00, OTYPE_ARRAY, 4, 0, acName1C00, SDO1C00}, {0x1C00, OTYPE_ARRAY, 4, 0, acName1C00, SDO1C00},
{0x1C10, OTYPE_ARRAY, 0, 0, acName1C10, SDO1C10}, {0x1C10, OTYPE_ARRAY, 1, 0, acName1C10, SDO1C10},
{0x1C11, OTYPE_ARRAY, 0, 0, acName1C11, SDO1C11}, {0x1C11, OTYPE_ARRAY, 1, 0, acName1C11, SDO1C11},
{0x1C12, OTYPE_ARRAY, 1, 0, acName1C12, SDO1C12},
{0x1C13, OTYPE_ARRAY, 1, 0, acName1C13, SDO1C13},
{0xffff, 0xff, 0xff, 0xff, NULL, NULL} {0xffff, 0xff, 0xff, 0xff, NULL, NULL}
}; };

View File

@ -266,6 +266,7 @@ void ecat_slv_worker (uint32_t event_mask)
/* Check the SM activation event */ /* Check the SM activation event */
ESC_sm_act_event(); ESC_sm_act_event();
#if USE_MBX
/* Check mailboxes */ /* Check mailboxes */
while ((ESC_mbxprocess() > 0) || (ESCvar.txcue > 0)) while ((ESC_mbxprocess() > 0) || (ESCvar.txcue > 0))
{ {
@ -280,6 +281,7 @@ void ecat_slv_worker (uint32_t event_mask)
} }
#if USE_EOE #if USE_EOE
ESC_eoeprocess_tx(); ESC_eoeprocess_tx();
#endif
#endif #endif
/* Call emulated eeprom handler if set */ /* Call emulated eeprom handler if set */
if (ESCvar.esc_hw_eep_handler != NULL) if (ESCvar.esc_hw_eep_handler != NULL)
@ -310,6 +312,7 @@ void ecat_slv_poll (void)
/* Check the SM activation event */ /* Check the SM activation event */
ESC_sm_act_event(); ESC_sm_act_event();
#if USE_MBX
/* Check mailboxes */ /* Check mailboxes */
if (ESC_mbxprocess()) if (ESC_mbxprocess())
{ {
@ -324,6 +327,7 @@ void ecat_slv_poll (void)
} }
#if USE_EOE #if USE_EOE
ESC_eoeprocess_tx(); ESC_eoeprocess_tx();
#endif
#endif #endif
/* Call emulated eeprom handler if set */ /* Call emulated eeprom handler if set */
@ -379,7 +383,9 @@ void ecat_slv_init (esc_cfg_t * config)
/* reset ESC to init state */ /* reset ESC to init state */
ESC_ALstatus (ESCinit); ESC_ALstatus (ESCinit);
ESC_ALerror (ALERR_NONE); ESC_ALerror (ALERR_NONE);
#if USE_MBX
ESC_stopmbx (); ESC_stopmbx ();
#endif
ESC_stopinput (); ESC_stopinput ();
ESC_stopoutput (); ESC_stopoutput ();
/* Init Object Dictionary default values */ /* Init Object Dictionary default values */

View File

@ -686,8 +686,8 @@ void ESC_xoeprocess (void)
uint8_t ESC_checkSM23 (uint8_t state) uint8_t ESC_checkSM23 (uint8_t state)
{ {
_ESCsm2 *SM; _ESCsm2 *SM;
ESC_read (ESCREG_SM2, (void *) &ESCvar.SM[2], sizeof (ESCvar.SM[2])); ESC_read (ESCREG_SM2, (void *) &ESCvar.SM[SM2_IDX], sizeof (ESCvar.SM[SM2_IDX]));
SM = (_ESCsm2 *) & ESCvar.SM[2]; SM = (_ESCsm2 *) & ESCvar.SM[SM2_IDX];
if ((etohs (SM->PSA) != ESC_SM2_sma) || (etohs (SM->Length) != ESCvar.ESC_SM2_sml) if ((etohs (SM->PSA) != ESC_SM2_sma) || (etohs (SM->Length) != ESCvar.ESC_SM2_sml)
|| (SM->Command != ESC_SM2_smc) || !(SM->ActESC & ESC_SM2_act)) || (SM->Command != ESC_SM2_smc) || !(SM->ActESC & ESC_SM2_act))
{ {
@ -701,8 +701,8 @@ uint8_t ESC_checkSM23 (uint8_t state)
/* SM2 overlaps SM3, fail state change */ /* SM2 overlaps SM3, fail state change */
return (ESCpreop | ESCerror); return (ESCpreop | ESCerror);
} }
ESC_read (ESCREG_SM3, (void *) &ESCvar.SM[3], sizeof (ESCvar.SM[3])); ESC_read (ESCREG_SM3, (void *) &ESCvar.SM[SM3_IDX], sizeof (ESCvar.SM[SM3_IDX]));
SM = (_ESCsm2 *) & ESCvar.SM[3]; SM = (_ESCsm2 *) & ESCvar.SM[SM3_IDX];
if ((etohs (SM->PSA) != ESC_SM3_sma) || (etohs (SM->Length) != ESCvar.ESC_SM3_sml) if ((etohs (SM->PSA) != ESC_SM3_sma) || (etohs (SM->Length) != ESCvar.ESC_SM3_sml)
|| (SM->Command != ESC_SM3_smc) || !(SM->ActESC & ESC_SM3_act)) || (SM->Command != ESC_SM3_smc) || !(SM->ActESC & ESC_SM3_act))
{ {
@ -727,13 +727,13 @@ uint8_t ESC_startinput (uint8_t state)
if (state != (ESCpreop | ESCerror)) if (state != (ESCpreop | ESCerror))
{ {
ESC_SMenable (3); ESC_SMenable (SM3_IDX);
CC_ATOMIC_SET(ESCvar.App.state, APPSTATE_INPUT); CC_ATOMIC_SET(ESCvar.App.state, APPSTATE_INPUT);
} }
else else
{ {
ESC_SMdisable (2); ESC_SMdisable (SM2_IDX);
ESC_SMdisable (3); ESC_SMdisable (SM3_IDX);
if (ESCvar.SMtestresult & SMRESULT_ERRSM3) if (ESCvar.SMtestresult & SMRESULT_ERRSM3)
{ {
ESC_ALerror (ALERR_INVALIDINPUTSM); ESC_ALerror (ALERR_INVALIDINPUTSM);
@ -759,8 +759,8 @@ uint8_t ESC_startinput (uint8_t state)
ESC_ALerror (dc_check_result); ESC_ALerror (dc_check_result);
state = (ESCpreop | ESCerror); state = (ESCpreop | ESCerror);
ESC_SMdisable (2); ESC_SMdisable (SM2_IDX);
ESC_SMdisable (3); ESC_SMdisable (SM3_IDX);
CC_ATOMIC_SET(ESCvar.App.state, APPSTATE_IDLE); CC_ATOMIC_SET(ESCvar.App.state, APPSTATE_IDLE);
} }
else else
@ -790,8 +790,8 @@ uint8_t ESC_startinput (uint8_t state)
void ESC_stopinput (void) void ESC_stopinput (void)
{ {
CC_ATOMIC_SET(ESCvar.App.state, APPSTATE_IDLE); CC_ATOMIC_SET(ESCvar.App.state, APPSTATE_IDLE);
ESC_SMdisable (3); ESC_SMdisable (SM3_IDX);
ESC_SMdisable (2); ESC_SMdisable (SM2_IDX);
/* Call interrupt disable hook case it have been configured */ /* Call interrupt disable hook case it have been configured */
if ((ESCvar.use_interrupt != 0) && if ((ESCvar.use_interrupt != 0) &&
@ -813,7 +813,7 @@ void ESC_stopinput (void)
uint8_t ESC_startoutput (uint8_t state) uint8_t ESC_startoutput (uint8_t state)
{ {
ESC_SMenable (2); ESC_SMenable (SM2_IDX);
CC_ATOMIC_OR(ESCvar.App.state, APPSTATE_OUTPUT); CC_ATOMIC_OR(ESCvar.App.state, APPSTATE_OUTPUT);
return state; return state;
@ -827,7 +827,7 @@ uint8_t ESC_startoutput (uint8_t state)
void ESC_stopoutput (void) void ESC_stopoutput (void)
{ {
CC_ATOMIC_AND(ESCvar.App.state, APPSTATE_INPUT); CC_ATOMIC_AND(ESCvar.App.state, APPSTATE_INPUT);
ESC_SMdisable (2); ESC_SMdisable (SM2_IDX);
APP_safeoutput (); APP_safeoutput ();
} }
@ -866,7 +866,9 @@ void ESC_sm_act_event (void)
* acknowledge the SyncManager Activation event making us enter * acknowledge the SyncManager Activation event making us enter
* this execution path. * this execution path.
*/ */
#if USE_MBX
ax = ESC_checkmbx (as); ax = ESC_checkmbx (as);
#endif
ax23 = ESC_checkSM23 (as); ax23 = ESC_checkSM23 (as);
if ((an & ESCerror) && ((ac & ESCerror) == 0)) if ((an & ESCerror) && ((ac & ESCerror) == 0))
{ {
@ -875,6 +877,7 @@ void ESC_sm_act_event (void)
/* Have we been forced to step down to INIT we will stop mailboxes, /* Have we been forced to step down to INIT we will stop mailboxes,
* update AL Status Code and exit ESC_state * update AL Status Code and exit ESC_state
*/ */
#if USE_MBX
else if (ax == (ESCinit | ESCerror)) else if (ax == (ESCinit | ESCerror))
{ {
/* If we have activated Inputs and Outputs we need to disable them */ /* If we have activated Inputs and Outputs we need to disable them */
@ -890,6 +893,7 @@ void ESC_sm_act_event (void)
ESC_ALstatus (ax); ESC_ALstatus (ax);
return; return;
} }
#endif
/* Have we been forced to step down to PREOP we will stop inputs /* Have we been forced to step down to PREOP we will stop inputs
* and outputs, update AL Status Code and exit ESC_state * and outputs, update AL Status Code and exit ESC_state
*/ */
@ -981,7 +985,11 @@ void ESC_state (void)
{ {
/* get station address */ /* get station address */
ESC_address (); ESC_address ();
#if USE_MBX
an = ESC_startmbx (ac); an = ESC_startmbx (ac);
#else
an = ac;
#endif
break; break;
} }
case INIT_TO_BOOT: case INIT_TO_BOOT:
@ -989,7 +997,11 @@ void ESC_state (void)
{ {
/* get station address */ /* get station address */
ESC_address (); ESC_address ();
#if USE_MBX
an = ESC_startmbxboot (ac); an = ESC_startmbxboot (ac);
#else
an = ac;
#endif
break; break;
} }
case INIT_TO_SAFEOP: case INIT_TO_SAFEOP:
@ -1003,26 +1015,34 @@ void ESC_state (void)
{ {
ESC_stopoutput (); ESC_stopoutput ();
ESC_stopinput (); ESC_stopinput ();
#if USE_MBX
ESC_stopmbx (); ESC_stopmbx ();
#endif
an = ESCinit; an = ESCinit;
break; break;
} }
case SAFEOP_TO_INIT: case SAFEOP_TO_INIT:
{ {
ESC_stopinput (); ESC_stopinput ();
#if USE_MBX
ESC_stopmbx (); ESC_stopmbx ();
#endif
an = ESCinit; an = ESCinit;
break; break;
} }
case PREOP_TO_INIT: case PREOP_TO_INIT:
{ {
#if USE_MBX
ESC_stopmbx (); ESC_stopmbx ();
#endif
an = ESCinit; an = ESCinit;
break; break;
} }
case BOOT_TO_INIT: case BOOT_TO_INIT:
{ {
#if USE_MBX
ESC_stopmbx (); ESC_stopmbx ();
#endif
an = ESCinit; an = ESCinit;
break; break;
} }

View File

@ -33,8 +33,13 @@
#define ESCREG_ALEVENT_WD 0x0040 #define ESCREG_ALEVENT_WD 0x0040
#define ESCREG_ALEVENT_SM0 0x0100 #define ESCREG_ALEVENT_SM0 0x0100
#define ESCREG_ALEVENT_SM1 0x0200 #define ESCREG_ALEVENT_SM1 0x0200
#if USE_MBX
#define ESCREG_ALEVENT_SM2 0x0400 #define ESCREG_ALEVENT_SM2 0x0400
#define ESCREG_ALEVENT_SM3 0x0800 #define ESCREG_ALEVENT_SM3 0x0800
#else
#define ESCREG_ALEVENT_SM2 ESCREG_ALEVENT_SM0
#define ESCREG_ALEVENT_SM3 ESCREG_ALEVENT_SM1
#endif
#define ESCREG_WDSTATUS 0x0440 #define ESCREG_WDSTATUS 0x0440
#define ESCREG_EECONTSTAT 0x0502 #define ESCREG_EECONTSTAT 0x0502
#define ESCREG_EEDATA 0x0508 #define ESCREG_EEDATA 0x0508
@ -43,8 +48,13 @@
#define ESCREG_SM0ACTIVATE (ESCREG_SM0 + 6) #define ESCREG_SM0ACTIVATE (ESCREG_SM0 + 6)
#define ESCREG_SM0PDI (ESCREG_SM0 + 7) #define ESCREG_SM0PDI (ESCREG_SM0 + 7)
#define ESCREG_SM1 (ESCREG_SM0 + 0x08) #define ESCREG_SM1 (ESCREG_SM0 + 0x08)
#if USE_MBX
#define ESCREG_SM2 (ESCREG_SM0 + 0x10) #define ESCREG_SM2 (ESCREG_SM0 + 0x10)
#define ESCREG_SM3 (ESCREG_SM0 + 0x18) #define ESCREG_SM3 (ESCREG_SM0 + 0x18)
#else
#define ESCREG_SM2 ESCREG_SM0
#define ESCREG_SM3 ESCREG_SM1
#endif
#define ESCREG_LOCALTIME 0x0910 #define ESCREG_LOCALTIME 0x0910
#define ESCREG_LOCALTIME_OFFSET 0x0920 #define ESCREG_LOCALTIME_OFFSET 0x0920
#define ESCREG_SYNC_ACT 0x0981 #define ESCREG_SYNC_ACT 0x0981
@ -252,8 +262,23 @@
#define SMRESULT_ERRSM0 0x01 #define SMRESULT_ERRSM0 0x01
#define SMRESULT_ERRSM1 0x02 #define SMRESULT_ERRSM1 0x02
#if USE_MBX
#define SMRESULT_ERRSM2 0x04 #define SMRESULT_ERRSM2 0x04
#define SMRESULT_ERRSM3 0x08 #define SMRESULT_ERRSM3 0x08
#else
#define SMRESULT_ERRSM2 SMRESULT_ERRSM0
#define SMRESULT_ERRSM3 SMRESULT_ERRSM1
#endif
#define SM0_IDX 0
#define SM1_IDX 1
#if USE_MBX
#define SM2_IDX 2
#define SM3_IDX 3
#else
#define SM2_IDX SM0_IDX
#define SM3_IDX SM1_IDX
#endif
#define FOE_ERR_NOTDEFINED 0x8000 #define FOE_ERR_NOTDEFINED 0x8000
#define FOE_ERR_NOTFOUND 0x8001 #define FOE_ERR_NOTFOUND 0x8001

View File

@ -102,8 +102,13 @@ typedef struct
#define ATYPE_RW (ATYPE_RO | ATYPE_WO) #define ATYPE_RW (ATYPE_RO | ATYPE_WO)
#define ATYPE_RWpre (ATYPE_Wpre | ATYPE_RO) #define ATYPE_RWpre (ATYPE_Wpre | ATYPE_RO)
#if USE_MBX
#define TX_PDO_OBJIDX 0x1c13 #define TX_PDO_OBJIDX 0x1c13
#define RX_PDO_OBJIDX 0x1c12 #define RX_PDO_OBJIDX 0x1c12
#else
#define TX_PDO_OBJIDX 0x1c11
#define RX_PDO_OBJIDX 0x1c10
#endif
#define COMPLETE_ACCESS_FLAG (1 << 15) #define COMPLETE_ACCESS_FLAG (1 << 15)

View File

@ -9,6 +9,12 @@
/* User-defined options, Options defined here will override default values */ /* User-defined options, Options defined here will override default values */
#include "ecat_options.h" #include "ecat_options.h"
/* Mailbox support */
/* If disabled SM2 --> SM0, and SM3 --> SM1 */
#ifndef USE_MBX
#define USE_MBX 1
#endif
/* FoE support */ /* FoE support */
#ifndef USE_FOE #ifndef USE_FOE
#define USE_FOE 1 #define USE_FOE 1