AnsweredAssumed Answered

fsl_enet for i.MX RT106x not able to handle ENET2

Question asked by Dirk Castelijns on Nov 14, 2019
Latest reply on Nov 17, 2019 by Daniel Chen

The fsl_enet drivers in the SDK for i.MX RT106x contain some array of data structures based on the number of ENET peripherals available. There is a mismatch in number of array elements which causes a HardFault when using ENET2.

 

Looking at fsl_enet.c, we see several arrays being declared:

 

/*! @brief Pointers to enet handles for each instance. */
static enet_handle_t *s_ENETHandle[FSL_FEATURE_SOC_ENET_COUNT] = {NULL};


/*! @brief Pointers to enet clocks for each instance. */
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
const clock_ip_name_t s_enetClock[] = ENET_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */

 

/*! @brief Pointers to enet transmit IRQ number for each instance. */
static const IRQn_Type s_enetTxIrqId[] = ENET_Transmit_IRQS;
/*! @brief Pointers to enet receive IRQ number for each instance. */
static const IRQn_Type s_enetRxIrqId[] = ENET_Receive_IRQS;
#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
/*! @brief Pointers to enet timestamp IRQ number for each instance. */
static const IRQn_Type s_enetTsIrqId[] = ENET_1588_Timer_IRQS;
#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
/*! @brief Pointers to enet error IRQ number for each instance. */
static const IRQn_Type s_enetErrIrqId[] = ENET_Error_IRQS;

/*! @brief Pointers to enet bases for each instance. */
static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS;

 

 

The s_ENETHandle[] array size is determined by FSL_FEATURE_SOC_ENET_COUNT defined in MIMXRT1062_features.h:

 

/* @brief ENET availability on the SoC. */
#define FSL_FEATURE_SOC_ENET_COUNT (2)

All the other array sizes are determine by macro's in MIMXRT1062.h:

/** Array initializer of ENET peripheral base addresses */
#define ENET_BASE_ADDRS { ENET_BASE, 0u, ENET2_BASE }
/** Array initializer of ENET peripheral base pointers */
#define ENET_BASE_PTRS { ENET, (ENET_Type *)0u, ENET2 }
/** Interrupt vectors for the ENET peripheral type */
#define ENET_Transmit_IRQS { ENET_IRQn, NotAvail_IRQn, ENET2_IRQn }
#define ENET_Receive_IRQS { ENET_IRQn, NotAvail_IRQn, ENET2_IRQn }
#define ENET_Error_IRQS { ENET_IRQn, NotAvail_IRQn, ENET2_IRQn }
#define ENET_1588_Timer_IRQS { ENET_1588_Timer_IRQn, NotAvail_IRQn, ENET2_1588_Timer_IRQn }

As you can see the macro expand to 3 elements while s_ENETHandle[] has only 2 elements. For some reason they left a gap between ENET and ENET2.  

 

At several places in fsl_enet.c the function ENET_GetInstance(base) is used to determine the index for one of the arrays above. Because this function iterates through s_enetBases[], the returned index can be 0 to 2 (because there are three elements).  All arrays can be accesses this way except for s_ENETHandle[] but this is done in several places in fsl_enet.c. For instance in ENET_SetHandler():

static void ENET_SetHandler(ENET_Type *base,
      enet_handle_t *handle,
      const enet_config_t *config,
      const enet_buffer_config_t *bufferConfig)
{
   uint8_t count;
   uint32_t instance = ENET_GetInstance(base);

   ...

   <removed part for clarity

   ...

   /* Save the handle pointer in the global variables. */
   s_ENETHandle[instance] = handle;

   ...

 

As you can imagine, things can go horribly wrong this way.

 

For now we got things working by setting FSL_FEATURE_SOC_ENET_COUNT to 3 but this is strange because the device has only 2 ENET's.

Outcomes