1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2023 NXP
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <math.h>
9 #include "fsl_enet.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.lpc_enet"
18 #endif
19
20 /*! @brief Defines 10^9 nanosecond. */
21 #define ENET_NANOSECS_ONESECOND (1000000000U)
22 /*! @brief Defines 10^6 microsecond.*/
23 #define ENET_MICRSECS_ONESECOND (1000000U)
24
25 /*! @brief Rx buffer LSB ignore bits. */
26 #define ENET_RXBUFF_IGNORELSB_BITS (2U)
27 /*! @brief ENET FIFO size unit. */
28 #define ENET_FIFOSIZE_UNIT (256U)
29 /*! @brief ENET half-dulpex default IPG. */
30 #define ENET_HALFDUPLEX_DEFAULTIPG (4U)
31 /*! @brief ENET miminum ring length. */
32 #define ENET_MIN_RINGLEN (4U)
33 /*! @brief ENET wakeup filter numbers. */
34 #define ENET_WAKEUPFILTER_NUM (8U)
35 /*! @brief Requried systime timer frequency. */
36 #define ENET_SYSTIME_REQUIRED_CLK_MHZ (50U)
37 /*! @brief Ethernet VLAN tag length. */
38 #define ENET_FRAME_VLAN_TAGLEN 4U
39
40 /*! @brief AVB TYPE */
41 #define ENET_AVBTYPE 0x22F0U
42 #define ENET_HEAD_TYPE_OFFSET (12)
43 #define ENET_HEAD_AVBTYPE_OFFSET (16)
44
45 /*! @brief Binary rollover mode count convert */
46 #define ENET_BINARY_ROLLOVER_SCALE(x) (uint32_t)((uint64_t)(x)*46566U / 100000U)
47
48 /*******************************************************************************
49 * Prototypes
50 ******************************************************************************/
51
52 /*!
53 * @brief Increase the index in the ring.
54 *
55 * @param index The current index.
56 * @param max The size.
57 * @return the increased index.
58 */
59 static uint16_t ENET_IncreaseIndex(uint16_t index, uint16_t max);
60
61 /*!
62 * @brief Set ENET system configuration.
63 * This function reset the ethernet module and set the phy selection.
64 * It should be called before any other ethernet operation.
65 *
66 * @param miiMode The MII/RMII mode for interface between the phy and ethernet.
67 */
68 static void ENET_SetSYSControl(enet_mii_mode_t miiMode);
69
70 /*!
71 * @brief Set ENET DMA controller with the configuration.
72 *
73 * @param base ENET peripheral base address.
74 * @param config ENET Mac configuration.
75 */
76 static void ENET_SetDMAControl(ENET_Type *base, const enet_config_t *config);
77
78 /*!
79 * @brief Set ENET MAC controller with the configuration.
80 *
81 * @param base ENET peripheral base address.
82 * @param config ENET Mac configuration.
83 * @param macAddr ENET six-byte mac address.
84 */
85 static void ENET_SetMacControl(ENET_Type *base, const enet_config_t *config, uint8_t *macAddr);
86 /*!
87 * @brief Set ENET MTL with the configuration.
88 *
89 * @param base ENET peripheral base address.
90 * @param config ENET Mac configuration.
91 */
92 static void ENET_SetMTL(ENET_Type *base, const enet_config_t *config);
93
94 /*!
95 * @brief Set ENET DMA transmit buffer descriptors for one channel.
96 *
97 * @param base ENET peripheral base address.
98 * @param bufferConfig ENET buffer configuration.
99 * @param channel The channel number, 0 , 1.
100 */
101 static status_t ENET_TxDescriptorsInit(ENET_Type *base, const enet_buffer_config_t *bufferConfig, uint8_t channel);
102
103 /*!
104 * @brief Set ENET DMA receive buffer descriptors for one channel.
105 *
106 * @param base ENET peripheral base address.
107 * @param config The ENET configuration.
108 * @param bufferConfig ENET buffer configuration.
109 * @param channel The channel number, 0 , 1.
110 */
111 static status_t ENET_RxDescriptorsInit(ENET_Type *base,
112 enet_config_t *config,
113 const enet_buffer_config_t *bufferConfig,
114 uint8_t channel);
115
116 /*!
117 * @brief Drop one frame in specified BD channel.
118 *
119 * @param base ENET peripheral base address.
120 * @param handle ENET handler.
121 * @param channel The channel number, 0 , 1.
122 */
123 static void ENET_DropFrame(ENET_Type *base, enet_handle_t *handle, uint8_t channel);
124
125 #ifdef ENET_PTP1588FEATURE_REQUIRED
126 /*!
127 * @brief Sets the ENET 1588 feature.
128 *
129 * Enable the enhacement 1588 buffer descriptor mode and start
130 * the 1588 timer.
131 *
132 * @param base ENET peripheral base address.
133 * @param config The ENET configuration.
134 * @param refClk_Hz The reference clock for ptp 1588.
135 */
136 static void ENET_SetPtp1588(ENET_Type *base, const enet_config_t *config, uint32_t refClk_Hz);
137 #endif /* ENET_PTP1588FEATURE_REQUIRED */
138
139 /*******************************************************************************
140 * Variables
141 ******************************************************************************/
142
143 /*! @brief Pointers to enet handles for each instance. */
144 static enet_handle_t *s_ENETHandle[FSL_FEATURE_SOC_LPC_ENET_COUNT] = {NULL};
145 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
146 /*! @brief Pointers to enet clocks for each instance. */
147 const clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_LPC_ENET_COUNT] = ETH_CLOCKS;
148 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
149
150 /*! @brief Pointers to enet bases for each instance. */
151 static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS;
152
153 /*! @brief Pointers to enet IRQ number for each instance. */
154 static const IRQn_Type s_enetIrqId[] = ENET_IRQS;
155
156 /* ENET ISR for transactional APIs. */
157 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
158 static enet_isr_t s_enetIsr = (enet_isr_t)DefaultISR;
159 #else
160 static enet_isr_t s_enetIsr;
161 #endif
162 /*******************************************************************************
163 * Code
164 ******************************************************************************/
ENET_IncreaseIndex(uint16_t index,uint16_t max)165 static uint16_t ENET_IncreaseIndex(uint16_t index, uint16_t max)
166 {
167 /* Increase the index. */
168 index++;
169 if (index >= max)
170 {
171 index = 0;
172 }
173 return index;
174 }
175
ENET_SetSYSControl(enet_mii_mode_t miiMode)176 static void ENET_SetSYSControl(enet_mii_mode_t miiMode)
177 {
178 #ifdef SYSCON_ETHPHYSEL_PHY_SEL_MASK
179 /* Reset first. */
180 SYSCON->PRESETCTRL[2] = SYSCON_PRESETCTRL_ETH_RST_MASK;
181 SYSCON->PRESETCTRL[2] &= ~SYSCON_PRESETCTRL_ETH_RST_MASK;
182 /* Set MII/RMII before the peripheral ethernet dma reset. */
183 SYSCON->ETHPHYSEL = (SYSCON->ETHPHYSEL & ~SYSCON_ETHPHYSEL_PHY_SEL_MASK) | SYSCON_ETHPHYSEL_PHY_SEL(miiMode);
184 #else
185 /* Reset first. */
186 SYSCON0->PRESETCTRL2 = SYSCON_PRESETCTRL2_ENET_RST_MASK;
187 SYSCON0->PRESETCTRL2 &= ~SYSCON_PRESETCTRL2_ENET_RST_MASK;
188 /* Set MII/RMII before the peripheral ethernet dma reset. */
189 SYSCON0->ENET_PHY_INTF_SEL = (SYSCON0->ENET_PHY_INTF_SEL & ~SYSCON_ENET_PHY_INTF_SEL_PHY_SEL_MASK) |
190 SYSCON_ENET_PHY_INTF_SEL_PHY_SEL(miiMode);
191 #endif
192 }
193
ENET_SetDMAControl(ENET_Type * base,const enet_config_t * config)194 static void ENET_SetDMAControl(ENET_Type *base, const enet_config_t *config)
195 {
196 assert(config);
197
198 uint8_t index;
199 uint32_t reg;
200 uint32_t burstLen;
201
202 /* Reset first and wait for the complete
203 * The reset bit will automatically be cleared after complete. */
204 base->DMA_MODE |= ENET_DMA_MODE_SWR_MASK;
205 while ((base->DMA_MODE & ENET_DMA_MODE_SWR_MASK) != 0U)
206 {
207 }
208
209 /* Set the burst length. */
210 for (index = 0; index < ENET_RING_NUM_MAX; index++)
211 {
212 burstLen = (uint32_t)kENET_BurstLen1;
213 if (config->multiqueueCfg != NULL)
214 {
215 burstLen = (uint32_t)config->multiqueueCfg->burstLen;
216 }
217 base->DMA_CH[index].DMA_CHX_CTRL = burstLen & ENET_DMA_CH_DMA_CHX_CTRL_PBLx8_MASK;
218
219 reg = base->DMA_CH[index].DMA_CHX_TX_CTRL & ~ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL_MASK;
220 base->DMA_CH[index].DMA_CHX_TX_CTRL = reg | ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL(burstLen & 0x3FU);
221
222 reg = base->DMA_CH[index].DMA_CHX_RX_CTRL & ~ENET_DMA_CH_DMA_CHX_RX_CTRL_RxPBL_MASK;
223 base->DMA_CH[index].DMA_CHX_RX_CTRL = reg | ENET_DMA_CH_DMA_CHX_RX_CTRL_RxPBL(burstLen & 0x3FU);
224 }
225 }
226
ENET_SetMTL(ENET_Type * base,const enet_config_t * config)227 static void ENET_SetMTL(ENET_Type *base, const enet_config_t *config)
228 {
229 assert(config);
230
231 uint32_t txqOpreg = 0;
232 uint32_t rxqOpReg = 0;
233 enet_multiqueue_config_t *multiqCfg = config->multiqueueCfg;
234 uint8_t index;
235
236 /* Set transmit operation mode. */
237 if ((config->specialControl & (uint16_t)kENET_StoreAndForward) != 0U)
238 {
239 txqOpreg = ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TSF_MASK;
240 rxqOpReg = ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RSF_MASK;
241 }
242 txqOpreg |= ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_FTQ_MASK |
243 ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TQS(ENET_MTL_TXFIFOSIZE / ENET_FIFOSIZE_UNIT - 1UL);
244 base->MTL_QUEUE[0].MTL_TXQX_OP_MODE = txqOpreg | ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TXQEN(2);
245 base->MTL_QUEUE[1].MTL_TXQX_OP_MODE = txqOpreg;
246
247 /* Set receive operation mode. */
248 rxqOpReg |= ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_FUP_MASK |
249 ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RQS(ENET_MTL_RXFIFOSIZE / ENET_FIFOSIZE_UNIT - 1UL);
250 base->MTL_QUEUE[0].MTL_RXQX_OP_MODE = rxqOpReg;
251
252 /* Set the schedule/arbitration(set for multiple queues). */
253 if (multiqCfg != NULL)
254 {
255 base->MTL_OP_MODE = ENET_MTL_OP_MODE_SCHALG(multiqCfg->mtltxSche) | ENET_MTL_OP_MODE_RAA(multiqCfg->mtlrxSche);
256 /* Set the Rx queue mapping to dma channel. */
257 base->MTL_RXQ_DMA_MAP = (uint32_t)multiqCfg->mtlrxQuemap;
258 /* Set the Tx/Rx queue operation mode for multi-queue. */
259 base->MTL_QUEUE[1].MTL_TXQX_OP_MODE |= ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TXQEN(2);
260 base->MTL_QUEUE[1].MTL_RXQX_OP_MODE = rxqOpReg;
261
262 /* Set the Tx/Rx queue weight. */
263 for (index = 0; index < ENET_RING_NUM_MAX; index++)
264 {
265 base->MTL_QUEUE[index].MTL_TXQX_QNTM_WGHT = multiqCfg->txqueweight[index];
266 base->MTL_QUEUE[index].MTL_RXQX_CTRL = ENET_MTL_QUEUE_MTL_RXQX_CTRL_RXQ_WEGT(multiqCfg->rxqueweight[index]);
267 }
268 }
269 }
270
ENET_SetMacControl(ENET_Type * base,const enet_config_t * config,uint8_t * macAddr)271 static void ENET_SetMacControl(ENET_Type *base, const enet_config_t *config, uint8_t *macAddr)
272 {
273 assert(config);
274
275 uint32_t reg = 0;
276
277 /* Set Macaddr */
278 /* The dma channel 0 is set as to which the Rx packet
279 * whose DA matches the MAC address content is routed. */
280 if (macAddr != NULL)
281 {
282 ENET_SetMacAddr(base, macAddr);
283 }
284
285 /* Set the receive filter. */
286 reg = ENET_MAC_FRAME_FILTER_PR(!((config->specialControl & (uint16_t)kENET_PromiscuousEnable) == 0U)) |
287 ENET_MAC_FRAME_FILTER_DBF(!((config->specialControl & (uint16_t)kENET_BroadCastRxDisable) == 0U)) |
288 ENET_MAC_FRAME_FILTER_PM(!((config->specialControl & (uint16_t)kENET_MulticastAllEnable) == 0U));
289 base->MAC_FRAME_FILTER = reg;
290 /* Flow control. */
291 if ((config->specialControl & (uint16_t)kENET_FlowControlEnable) != 0U)
292 {
293 base->MAC_RX_FLOW_CTRL = ENET_MAC_RX_FLOW_CTRL_RFE_MASK | ENET_MAC_RX_FLOW_CTRL_UP_MASK;
294 base->MAC_TX_FLOW_CTRL_Q[0] = ENET_MAC_TX_FLOW_CTRL_Q_PT(config->pauseDuration);
295 base->MAC_TX_FLOW_CTRL_Q[1] = ENET_MAC_TX_FLOW_CTRL_Q_PT(config->pauseDuration);
296 }
297
298 /* Set the 1us ticket. */
299 reg = CLOCK_GetCoreSysClkFreq() / ENET_MICRSECS_ONESECOND - 1U;
300 base->MAC_1US_TIC_COUNTR = ENET_MAC_1US_TIC_COUNTR_TIC_1US_CNTR(reg);
301
302 /* Set the speed and duplex. */
303 reg = ENET_MAC_CONFIG_ECRSFD_MASK | ENET_MAC_CONFIG_PS_MASK | ENET_MAC_CONFIG_DM(config->miiDuplex) |
304 ENET_MAC_CONFIG_FES(config->miiSpeed) |
305 ENET_MAC_CONFIG_S2KP((config->specialControl & (uint16_t)kENET_8023AS2KPacket) != 0U) |
306 ENET_MAC_CONFIG_IPC((config->specialControl & (uint16_t)kENET_RxChecksumOffloadEnable) != 0U);
307 if (config->miiDuplex == kENET_MiiHalfDuplex)
308 {
309 reg |= ENET_MAC_CONFIG_IPG(ENET_HALFDUPLEX_DEFAULTIPG);
310 }
311 base->MAC_CONFIG = reg;
312
313 /* Enable channel. */
314 base->MAC_RXQ_CTRL[0] = ENET_MAC_RXQ_CTRL_RXQ0EN(1) | ENET_MAC_RXQ_CTRL_RXQ1EN(1);
315 }
316
ENET_TxDescriptorsInit(ENET_Type * base,const enet_buffer_config_t * bufferConfig,uint8_t channel)317 static status_t ENET_TxDescriptorsInit(ENET_Type *base, const enet_buffer_config_t *bufferConfig, uint8_t channel)
318 {
319 uint16_t j;
320 enet_tx_bd_struct_t *txbdPtr;
321 const enet_buffer_config_t *buffCfg = bufferConfig;
322
323 if (buffCfg == NULL)
324 {
325 return kStatus_InvalidArgument;
326 }
327
328 /* Check the ring length. */
329 if (buffCfg->txRingLen < ENET_MIN_RINGLEN)
330 {
331 return kStatus_InvalidArgument;
332 }
333 /* Set the Tx descriptor start/tail pointer, shall be word aligned. */
334 base->DMA_CH[channel].DMA_CHX_TXDESC_LIST_ADDR =
335 (uint32_t)buffCfg->txDescStartAddrAlign & ENET_DMA_CH_DMA_CHX_TXDESC_LIST_ADDR_STL_MASK;
336 base->DMA_CH[channel].DMA_CHX_TXDESC_TAIL_PTR =
337 (uint32_t)buffCfg->txDescTailAddrAlign & ENET_DMA_CH_DMA_CHX_TXDESC_LIST_ADDR_STL_MASK;
338 /* Set the Tx ring length. */
339 base->DMA_CH[channel].DMA_CHX_TXDESC_RING_LENGTH =
340 ((uint32_t)buffCfg->txRingLen - 1U) & ENET_DMA_CH_DMA_CHX_TXDESC_RING_LENGTH_TDRL_MASK;
341
342 /* Init the txbdPtr to the transmit descriptor start address. */
343 txbdPtr = (enet_tx_bd_struct_t *)(buffCfg->txDescStartAddrAlign);
344 for (j = 0; j < buffCfg->txRingLen; j++)
345 {
346 txbdPtr->tdes0 = 0;
347 txbdPtr->tdes1 = 0;
348 txbdPtr->tdes2 = 0;
349 txbdPtr->tdes3 = 0;
350 txbdPtr++;
351 }
352
353 return kStatus_Success;
354 }
355
ENET_RxDescriptorsInit(ENET_Type * base,enet_config_t * config,const enet_buffer_config_t * bufferConfig,uint8_t channel)356 static status_t ENET_RxDescriptorsInit(ENET_Type *base,
357 enet_config_t *config,
358 const enet_buffer_config_t *bufferConfig,
359 uint8_t channel)
360 {
361 uint16_t j;
362 uint32_t reg;
363 enet_rx_bd_struct_t *rxbdPtr;
364 uint16_t index;
365 bool doubleBuffEnable = ((config->specialControl & (uint16_t)kENET_DescDoubleBuffer) != 0U) ? true : false;
366 const enet_buffer_config_t *buffCfg = bufferConfig;
367 uint32_t control = ENET_RXDESCRIP_RD_BUFF1VALID_MASK;
368
369 if (buffCfg == NULL)
370 {
371 return kStatus_InvalidArgument;
372 }
373
374 if (0U != (config->interrupt & (uint32_t)kENET_DmaRx))
375 {
376 control |= ENET_RXDESCRIP_RD_IOC_MASK;
377 }
378
379 if (doubleBuffEnable)
380 {
381 control |= ENET_RXDESCRIP_RD_BUFF2VALID_MASK;
382 }
383
384 /* Not give ownership to DMA before Rx buffer is ready */
385 if ((config->rxBuffAlloc == NULL) || (config->rxBuffFree == NULL))
386 {
387 control |= ENET_RXDESCRIP_WR_OWN_MASK;
388 }
389
390 /* Check the ring length. */
391 if (buffCfg->rxRingLen < ENET_MIN_RINGLEN)
392 {
393 return kStatus_InvalidArgument;
394 }
395
396 /* Set the Rx descriptor start/tail pointer, shall be word aligned. */
397 base->DMA_CH[channel].DMA_CHX_RXDESC_LIST_ADDR =
398 (uint32_t)buffCfg->rxDescStartAddrAlign & ENET_DMA_CH_DMA_CHX_RXDESC_LIST_ADDR_SRL_MASK;
399 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR =
400 (uint32_t)buffCfg->rxDescTailAddrAlign & ENET_DMA_CH_DMA_CHX_RXDESC_LIST_ADDR_SRL_MASK;
401 base->DMA_CH[channel].DMA_CHX_RXDESC_RING_LENGTH =
402 ((uint32_t)buffCfg->rxRingLen - 1U) & ENET_DMA_CH_DMA_CHX_RXDESC_RING_LENGTH_RDRL_MASK;
403 reg = base->DMA_CH[channel].DMA_CHX_RX_CTRL & ~ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ_MASK;
404 reg |= ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ(buffCfg->rxBuffSizeAlign >> ENET_RXBUFF_IGNORELSB_BITS);
405 base->DMA_CH[channel].DMA_CHX_RX_CTRL = reg;
406
407 /* Init the rxbdPtr to the receive descriptor start address. */
408 rxbdPtr = (enet_rx_bd_struct_t *)(buffCfg->rxDescStartAddrAlign);
409
410 for (j = 0; j < buffCfg->rxRingLen; j++)
411 {
412 if ((config->rxBuffAlloc == NULL) || (config->rxBuffFree == NULL))
413 {
414 if (doubleBuffEnable)
415 {
416 index = 2U * j;
417 }
418 else
419 {
420 index = j;
421 }
422 rxbdPtr->rdes0 = buffCfg->rxBufferStartAddr[index];
423 /* The second buffer is set with 0 because it is not required for normal case. */
424 if (doubleBuffEnable)
425 {
426 rxbdPtr->rdes2 = buffCfg->rxBufferStartAddr[index + 1U];
427 }
428 else
429 {
430 rxbdPtr->rdes2 = 0;
431 }
432 }
433
434 /* Set the valid and DMA own flag.*/
435 rxbdPtr->rdes3 = control;
436 rxbdPtr++;
437 }
438
439 return kStatus_Success;
440 }
441
442 #ifdef ENET_PTP1588FEATURE_REQUIRED
ENET_SetPtp1588(ENET_Type * base,const enet_config_t * config,uint32_t refClk_Hz)443 static void ENET_SetPtp1588(ENET_Type *base, const enet_config_t *config, uint32_t refClk_Hz)
444 {
445 assert(config);
446 assert(config->ptpConfig);
447 assert(refClk_Hz);
448
449 uint32_t control;
450 enet_ptp_config_t *ptpConfig = config->ptpConfig;
451
452 /* Clear the timestamp interrupt first. */
453 base->MAC_INTR_EN &= ~ENET_MAC_INTR_EN_TSIE_MASK;
454
455 if (ptpConfig->fineUpdateEnable)
456 {
457 base->MAC_TIMESTAMP_CTRL |= ENET_MAC_TIMESTAMP_CTRL_TSCFUPDT_MASK;
458 /* Set the initial added value for the fine update. */
459 control = 100000000U / (refClk_Hz / ENET_MICRSECS_ONESECOND / ENET_SYSTIME_REQUIRED_CLK_MHZ);
460 base->MAC_SYS_TIMESTMP_ADDEND = control;
461 base->MAC_TIMESTAMP_CTRL |= ENET_MAC_TIMESTAMP_CTRL_TADDREG_MASK;
462 while ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TADDREG_MASK) != 0U)
463 {
464 }
465 }
466
467 /* Enable the IEEE 1588 timestamping and snapshot for event message. */
468 control = ENET_MAC_TIMESTAMP_CTRL_TSENA_MASK | ENET_MAC_TIMESTAMP_CTRL_TSIPV4ENA_MASK |
469 ENET_MAC_TIMESTAMP_CTRL_TSIPV6ENA_MASK | ENET_MAC_TIMESTAMP_CTRL_TSENALL_MASK |
470 ENET_MAC_TIMESTAMP_CTRL_TSEVTENA_MASK | ENET_MAC_TIMESTAMP_CTRL_SNAPTYPSEL_MASK |
471 ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR(ptpConfig->tsRollover);
472
473 if (ptpConfig->ptp1588V2Enable)
474 {
475 control |= ENET_MAC_TIMESTAMP_CTRL_TSVER2ENA_MASK | ENET_MAC_TIMESTAMP_CTRL_TSIPENA_MASK;
476 }
477
478 /* Initialize the sub-second increment register. */
479 if (ptpConfig->tsRollover != kENET_BinaryRollover)
480 {
481 base->MAC_SUB_SCND_INCR = ENET_MAC_SUB_SCND_INCR_SSINC(ENET_NANOSECS_ONESECOND / refClk_Hz);
482 base->MAC_SYS_TIME_NSCND_UPD = 0;
483 }
484 else
485 {
486 /* round up. */
487 uint32_t data = ENET_MAC_SYS_TIME_NSCND_TSSS_MASK / refClk_Hz;
488 base->MAC_SUB_SCND_INCR = ENET_MAC_SUB_SCND_INCR_SSINC(data);
489 base->MAC_SYS_TIME_NSCND_UPD = 0;
490 }
491 /* Set the second.*/
492 base->MAC_SYS_TIME_SCND_UPD = 0;
493 base->MAC_SYS_TIME_HWORD_SCND = 0;
494
495 /* Initialize the system timer. */
496 base->MAC_TIMESTAMP_CTRL = control | ENET_MAC_TIMESTAMP_CTRL_TSINIT_MASK;
497 }
498 #endif /* ENET_PTP1588FEATURE_REQUIRED */
499
ENET_GetInstance(ENET_Type * base)500 uint32_t ENET_GetInstance(ENET_Type *base)
501 {
502 uint32_t instance;
503
504 /* Find the instance index from base address mappings. */
505 for (instance = 0U; instance < (uint32_t)FSL_FEATURE_SOC_LPC_ENET_COUNT; instance++)
506 {
507 if (s_enetBases[instance] == base)
508 {
509 break;
510 }
511 }
512
513 assert(instance < (uint32_t)FSL_FEATURE_SOC_LPC_ENET_COUNT);
514
515 return instance;
516 }
517
518 /*!
519 * brief Gets the ENET default configuration structure.
520 *
521 * The purpose of this API is to get the default ENET configure
522 * structure for ENET_Init(). User may use the initialized
523 * structure unchanged in ENET_Init(), or modify some fields of the
524 * structure before calling ENET_Init().
525 * Example:
526 code
527 enet_config_t config;
528 ENET_GetDefaultConfig(&config);
529 endcode
530 * param config The ENET mac controller configuration structure pointer.
531 */
ENET_GetDefaultConfig(enet_config_t * config)532 void ENET_GetDefaultConfig(enet_config_t *config)
533 {
534 /* Checks input parameter. */
535 assert(config);
536
537 /* Initializes the configure structure to zero. */
538 (void)memset(config, 0, sizeof(*config));
539
540 /* Sets MII mode, full duplex, 100Mbps for MAC and PHY data interface. */
541 config->miiMode = kENET_RmiiMode;
542 config->miiSpeed = kENET_MiiSpeed100M;
543 config->miiDuplex = kENET_MiiFullDuplex;
544
545 /* Sets default configuration for other options. */
546 config->specialControl = 0U;
547 config->multiqueueCfg = NULL;
548 config->pauseDuration = 0;
549
550 #ifdef ENET_PTP1588FEATURE_REQUIRED
551 config->ptpConfig = NULL;
552 #endif /* ENET_PTP1588FEATURE_REQUIRED */
553 }
554
555 /*!
556 * brief Initializes the ENET module.
557 *
558 * This function ungates the module clock and initializes it with the ENET basic
559 * configuration.
560 * note As our transactional transmit API use the zero-copy transmit buffer.
561 * So there are two thing we emphasize here:
562 * 1. Tx buffer free/requeue for application should be done in the Tx
563 * interrupt handler. Please set callback: kENET_TxIntEvent with Tx buffer free/requeue
564 * process APIs.
565 * 2. The Tx interrupt is forced to open.
566 *
567 * param base ENET peripheral base address.
568 * param config ENET mac configuration structure pointer.
569 * The "enet_config_t" type mac configuration return from ENET_GetDefaultConfig
570 * can be used directly. It is also possible to verify the Mac configuration using other methods.
571 * param macAddr ENET mac address of Ethernet device. This MAC address should be
572 * provided.
573 * param refclkSrc_Hz ENET input reference clock.
574 */
ENET_Init(ENET_Type * base,const enet_config_t * config,uint8_t * macAddr,uint32_t refclkSrc_Hz)575 void ENET_Init(ENET_Type *base, const enet_config_t *config, uint8_t *macAddr, uint32_t refclkSrc_Hz)
576 {
577 assert(config);
578
579 uint32_t instance = ENET_GetInstance(base);
580 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
581 /* Ungate ENET clock. */
582 CLOCK_EnableClock(s_enetClock[instance]);
583 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
584 /* System configure fistly. */
585 ENET_SetSYSControl(config->miiMode);
586
587 /* Initializes the ENET DMA with basic function. */
588 ENET_SetDMAControl(base, config);
589
590 /* Initializes the ENET MTL with basic function. */
591 ENET_SetMTL(base, config);
592
593 /* Initializes the ENET MAC with basic function. */
594 ENET_SetMacControl(base, config, macAddr);
595
596 #ifdef ENET_PTP1588FEATURE_REQUIRED
597 ENET_SetPtp1588(base, config, refclkSrc_Hz);
598 #endif /* ENET_PTP1588FEATURE_REQUIRED */
599
600 /* Force to enable Tx interrupt for use transactional API to do Tx buffer free/requeue. */
601 ENET_EnableInterrupts(base, (config->interrupt | (uint32_t)kENET_DmaTx));
602 }
603
604 /*!
605 * brief Deinitializes the ENET module.
606
607 * This function gates the module clock and disables the ENET module.
608 *
609 * param base ENET peripheral base address.
610 */
ENET_Deinit(ENET_Type * base)611 void ENET_Deinit(ENET_Type *base)
612 {
613 /* Reset first and wait for the complete
614 * The reset bit will automatically be cleared after complete. */
615 base->DMA_MODE |= ENET_DMA_MODE_SWR_MASK;
616 while ((base->DMA_MODE & ENET_DMA_MODE_SWR_MASK) != 0U)
617 {
618 }
619
620 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
621 /* Disables the clock source. */
622 CLOCK_DisableClock(s_enetClock[ENET_GetInstance(base)]);
623 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
624 }
625
626 /*!
627 * brief Initialize for all ENET descriptors.
628 *
629 * note This function finishes all Tx/Rx descriptors initialization. The descriptor initialization
630 * should be called after ENET_Init().
631 *
632 * param base ENET peripheral base address.
633 * param config The configuration for ENET.
634 * param bufferConfig All buffers configuration.
635 */
ENET_DescriptorInit(ENET_Type * base,enet_config_t * config,enet_buffer_config_t * bufferConfig)636 status_t ENET_DescriptorInit(ENET_Type *base, enet_config_t *config, enet_buffer_config_t *bufferConfig)
637 {
638 assert(config);
639 assert(bufferConfig);
640
641 uint8_t ringNum = config->multiqueueCfg == NULL ? 1U : 2U;
642 uint8_t channel;
643
644 for (channel = 0; channel < ringNum; channel++)
645 {
646 if (ENET_TxDescriptorsInit(base, bufferConfig, channel) != kStatus_Success)
647 {
648 return kStatus_Fail;
649 }
650
651 if (ENET_RxDescriptorsInit(base, config, bufferConfig, channel) != kStatus_Success)
652 {
653 return kStatus_Fail;
654 }
655
656 bufferConfig++;
657 }
658 return kStatus_Success;
659 }
660
661 /*!
662 * brief Starts the ENET Tx/Rx.
663 * This function enable the Tx/Rx and starts the Tx/Rx DMA.
664 * This shall be set after ENET initialization and before
665 * starting to receive the data.
666 *
667 * param base ENET peripheral base address.
668 * param rxRingNum The number of the used Rx rings. It shall not be
669 * larger than the ENET_RING_NUM_MAX(2). If the ringNum is set with
670 * 1, the ring 0 will be used.
671 * param txRingNum The number of the used Tx rings. It shall not be
672 * larger than the ENET_RING_NUM_MAX(2). If the ringNum is set with
673 * 1, the ring 0 will be used.
674 *
675 * note This must be called after all the ENET initilization.
676 * And should be called when the ENET receive/transmit is required.
677 */
ENET_StartRxTx(ENET_Type * base,uint8_t txRingNum,uint8_t rxRingNum)678 void ENET_StartRxTx(ENET_Type *base, uint8_t txRingNum, uint8_t rxRingNum)
679 {
680 assert(txRingNum);
681 assert(rxRingNum);
682
683 uint8_t index;
684
685 if (txRingNum > ENET_RING_NUM_MAX)
686 {
687 txRingNum = ENET_RING_NUM_MAX;
688 }
689 if (rxRingNum > ENET_RING_NUM_MAX)
690 {
691 rxRingNum = ENET_RING_NUM_MAX;
692 }
693 /* Start/Acive the DMA first. */
694 for (index = 0; index < rxRingNum; index++)
695 {
696 base->DMA_CH[index].DMA_CHX_RX_CTRL |= ENET_DMA_CH_DMA_CHX_RX_CTRL_SR_MASK;
697 }
698 for (index = 0; index < txRingNum; index++)
699 {
700 base->DMA_CH[index].DMA_CHX_TX_CTRL |= ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
701 }
702
703 /* Enable the RX and TX at same time. */
704 base->MAC_CONFIG |= (ENET_MAC_CONFIG_TE_MASK | ENET_MAC_CONFIG_RE_MASK);
705 }
706
707 /*!
708 * brief Set the second level IRQ handler
709 *
710 * param base ENET peripheral base address.
711 * param ISRHandler The handler to install.
712 */
ENET_SetISRHandler(ENET_Type * base,enet_isr_t ISRHandler)713 void ENET_SetISRHandler(ENET_Type *base, enet_isr_t ISRHandler)
714 {
715 s_enetIsr = ISRHandler;
716 (void)EnableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
717 }
718
719 /*!
720 * brief Enables the ENET DMA and MAC interrupts.
721 *
722 * This function enables the ENET interrupt according to the provided mask. The mask
723 * is a logical OR of enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
724 * For example, to enable the dma and mac interrupt, do the following.
725 * code
726 * ENET_EnableInterrupts(ENET, kENET_DmaRx | kENET_DmaTx | kENET_MacPmt);
727 * endcode
728 *
729 * param base ENET peripheral base address.
730 * param mask ENET interrupts to enable. This is a logical OR of both
731 * enumeration :: enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
732 */
ENET_EnableInterrupts(ENET_Type * base,uint32_t mask)733 void ENET_EnableInterrupts(ENET_Type *base, uint32_t mask)
734 {
735 uint32_t interrupt = mask & 0xFFFFU;
736 uint8_t index;
737
738 /* For dma interrupt. */
739 if (interrupt != 0U)
740 {
741 for (index = 0; index < ENET_RING_NUM_MAX; index++)
742 {
743 /* Set for all abnormal interrupts. */
744 if ((ENET_ABNORM_INT_MASK & interrupt) != 0U)
745 {
746 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_AIE_MASK;
747 }
748 /* Set for all normal interrupts. */
749 if ((ENET_NORM_INT_MASK & interrupt) != 0U)
750 {
751 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_NIE_MASK;
752 }
753 base->DMA_CH[index].DMA_CHX_INT_EN = interrupt;
754 }
755 }
756 interrupt = mask >> ENET_MACINT_ENUM_OFFSET;
757 if (interrupt != 0U)
758 {
759 /* MAC interrupt */
760 base->MAC_INTR_EN |= interrupt;
761 }
762 }
763
764 /*!
765 * brief Clears the ENET mac interrupt events status flag.
766 *
767 * This function clears enabled ENET interrupts according to the provided mask. The mask
768 * is a logical OR of enumeration members. See the ref enet_mac_interrupt_enable_t.
769 * For example, to clear the TX frame interrupt and RX frame interrupt, do the following.
770 * code
771 * ENET_ClearMacInterruptStatus(ENET, kENET_MacPmt);
772 * endcode
773 *
774 * param base ENET peripheral base address.
775 * param mask ENET interrupt source to be cleared.
776 * This is the logical OR of members of the enumeration :: enet_mac_interrupt_enable_t.
777 */
ENET_ClearMacInterruptStatus(ENET_Type * base,uint32_t mask)778 void ENET_ClearMacInterruptStatus(ENET_Type *base, uint32_t mask)
779 {
780 volatile uint32_t dummy;
781
782 if ((mask & (uint32_t)kENET_MacTimestamp) != 0U)
783 {
784 dummy = base->MAC_SYS_TIMESTMP_STAT;
785 }
786 else if ((mask & (uint32_t)kENET_MacPmt) != 0U)
787 {
788 dummy = base->MAC_PMT_CRTL_STAT;
789 }
790 else
791 {
792 /* Add for avoid the misra 2004 rule 14.10 */
793 }
794 (void)dummy;
795 }
796
797 /*!
798 * brief Disables the ENET DMA and MAC interrupts.
799 *
800 * This function disables the ENET interrupt according to the provided mask. The mask
801 * is a logical OR of enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
802 * For example, to disable the dma and mac interrupt, do the following.
803 * code
804 * ENET_DisableInterrupts(ENET, kENET_DmaRx | kENET_DmaTx | kENET_MacPmt);
805 * endcode
806 *
807 * param base ENET peripheral base address.
808 * param mask ENET interrupts to disables. This is a logical OR of both
809 * enumeration :: enet_dma_interrupt_enable_t and enet_mac_interrupt_enable_t.
810 */
ENET_DisableInterrupts(ENET_Type * base,uint32_t mask)811 void ENET_DisableInterrupts(ENET_Type *base, uint32_t mask)
812 {
813 uint32_t interrupt = mask & 0xFFFFU;
814 uint8_t index;
815
816 /* For dma interrupt. */
817 if (interrupt != 0U)
818 {
819 for (index = 0; index < ENET_RING_NUM_MAX; index++)
820 {
821 /* Set for all abnormal interrupts. */
822 if ((ENET_ABNORM_INT_MASK & interrupt) != 0U)
823 {
824 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_AIE_MASK;
825 }
826 /* Set for all normal interrupts. */
827 if ((ENET_NORM_INT_MASK & interrupt) != 0U)
828 {
829 interrupt |= ENET_DMA_CH_DMA_CHX_INT_EN_NIE_MASK;
830 }
831 base->DMA_CH[index].DMA_CHX_INT_EN &= ~interrupt;
832 }
833 }
834 interrupt = mask >> ENET_MACINT_ENUM_OFFSET;
835 if (interrupt != 0U)
836 {
837 /* MAC interrupt */
838 base->MAC_INTR_EN &= ~interrupt;
839 }
840 }
841
842 /*!
843 * brief Create ENET Handler
844 *
845 * This is a transactional API and it's provided to store all datas which are needed
846 * during the whole transactional process. This API should not be used when you use
847 * functional APIs to do data Tx/Rx. This is funtion will store many data/flag for
848 * transactional use.
849 *
850 * param base ENET peripheral base address.
851 * param handle ENET handler.
852 * param config ENET configuration.
853 * param bufferConfig ENET buffer configuration.
854 * param callback The callback function.
855 * param userData The application data.
856 */
ENET_CreateHandler(ENET_Type * base,enet_handle_t * handle,enet_config_t * config,enet_buffer_config_t * bufferConfig,enet_callback_t callback,void * userData)857 void ENET_CreateHandler(ENET_Type *base,
858 enet_handle_t *handle,
859 enet_config_t *config,
860 enet_buffer_config_t *bufferConfig,
861 enet_callback_t callback,
862 void *userData)
863 {
864 assert(config);
865 assert(bufferConfig);
866 assert(callback);
867
868 uint8_t ringNum = 1;
869 uint8_t count = 0;
870 uint8_t rxIntEnable = 0;
871 enet_buffer_config_t *buffConfig = bufferConfig;
872 uint32_t txFifoSize;
873 uint32_t pbl;
874
875 /* Store transfer parameters in handle pointer. */
876 (void)memset(handle, 0, sizeof(enet_handle_t));
877 if ((config->specialControl & (uint32_t)kENET_DescDoubleBuffer) != 0U)
878 {
879 handle->doubleBuffEnable = true;
880 }
881 if (config->multiqueueCfg != NULL)
882 {
883 ringNum = 2;
884 handle->multiQueEnable = true;
885 }
886 for (count = 0; count < ringNum; count++)
887 {
888 handle->rxBdRing[count].rxBdBase = buffConfig->rxDescStartAddrAlign;
889 handle->rxBdRing[count].rxGenIdx = 0;
890 handle->rxBdRing[count].rxRingLen = buffConfig->rxRingLen;
891 handle->rxBdRing[count].rxBuffSizeAlign = buffConfig->rxBuffSizeAlign;
892
893 handle->txBdRing[count].txBdBase = buffConfig->txDescStartAddrAlign;
894 handle->txBdRing[count].txRingLen = buffConfig->txRingLen;
895 handle->txBdRing[count].txGenIdx = 0;
896 handle->txBdRing[count].txConsumIdx = 0;
897 handle->txBdRing[count].txDescUsed = 0;
898
899 handle->txDirtyRing[count].txDirtyBase = buffConfig->txDirtyStartAddr;
900 handle->txDirtyRing[count].txRingLen = buffConfig->txRingLen;
901 handle->txDirtyRing[count].txGenIdx = 0;
902 handle->txDirtyRing[count].txConsumIdx = 0;
903
904 handle->rxBufferStartAddr[count] = buffConfig->rxBufferStartAddr;
905
906 /* Check if the Rx interrrupt is enabled. */
907 rxIntEnable |= (uint8_t)(uint32_t)(base->DMA_CH[count].DMA_CHX_INT_EN & ENET_DMA_CH_DMA_CHX_INT_EN_RIE_MASK);
908
909 /* Calculate the reserved space for Tx in certain cases. */
910 if (0U != (base->MTL_QUEUE[count].MTL_TXQX_OP_MODE & ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TSF_MASK))
911 {
912 pbl = (base->DMA_CH[count].DMA_CHX_TX_CTRL & ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL_MASK) >>
913 ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL_SHIFT;
914 pbl = ((base->DMA_CH[count].DMA_CHX_CTRL & ENET_DMA_CH_DMA_CHX_CTRL_PBLx8_MASK) != 0U) ? (8U * pbl) : pbl;
915 txFifoSize = (uint32_t)pow(
916 (double)2, (double)(uint32_t)(((base->MAC_HW_FEAT[1] & ENET_MAC_HW_FEAT_TXFIFOSIZE_MASK) >> ENET_MAC_HW_FEAT_TXFIFOSIZE_SHIFT) +
917 7U));
918 handle->txLenLimitation[count] = txFifoSize - (pbl + 6U) * (32U / 8U);
919 }
920
921 buffConfig++;
922 }
923
924 handle->rxintEnable = (rxIntEnable != 0U);
925
926 /* Save the handle pointer in the global variables. */
927 s_ENETHandle[ENET_GetInstance(base)] = handle;
928
929 /* Set Rx alloc/free callback. */
930 handle->rxBuffAlloc = config->rxBuffAlloc;
931 handle->rxBuffFree = config->rxBuffFree;
932
933 /* Set callback and userData. */
934 handle->callback = callback;
935 handle->userData = userData;
936
937 /* Set up interrupt and its handler. */
938 ENET_SetISRHandler(base, ENET_IRQHandler);
939 }
940
941 /*!
942 * brief Gets the ENET module Mac address.
943 *
944 * param base ENET peripheral base address.
945 * param macAddr The six-byte Mac address pointer.
946 * The pointer is allocated by application and input into the API.
947 */
ENET_GetMacAddr(ENET_Type * base,uint8_t * macAddr)948 void ENET_GetMacAddr(ENET_Type *base, uint8_t *macAddr)
949 {
950 assert(macAddr);
951
952 uint32_t address = base->MAC_ADDR_LOW;
953
954 /* Get from physical address lower register. */
955 macAddr[2] = (uint8_t)(0xFFU & (address >> 24U));
956 macAddr[3] = (uint8_t)(0xFFU & (address >> 16U));
957 macAddr[4] = (uint8_t)(0xFFU & (address >> 8U));
958 macAddr[5] = (uint8_t)(0xFFU & address);
959
960 /* Get from physical address high register. */
961 address = base->MAC_ADDR_HIGH;
962 macAddr[0] = (uint8_t)(0xFFU & (address >> 8U));
963 macAddr[1] = (uint8_t)(0xFFU & address);
964 }
965
966 /*!
967 * brief Sets the ENET SMI(serial management interface)- MII management interface.
968 *
969 * param base ENET peripheral base address.
970 */
ENET_SetSMI(ENET_Type * base)971 void ENET_SetSMI(ENET_Type *base)
972 {
973 uint32_t crDiv = 0;
974 uint32_t srcClock_Hz = CLOCK_GetCoreSysClkFreq() / 1000000U;
975
976 assert((srcClock_Hz >= 20U) && (srcClock_Hz < 250U));
977
978 if (srcClock_Hz < 35U)
979 {
980 crDiv = 2;
981 }
982 else if (srcClock_Hz < 60U)
983 {
984 crDiv = 3;
985 }
986 else if (srcClock_Hz < 100U)
987 {
988 crDiv = 0;
989 }
990 else if (srcClock_Hz < 150U)
991 {
992 crDiv = 1;
993 }
994 else if (srcClock_Hz < 250U)
995 {
996 crDiv = 4;
997 }
998 else
999 {
1000 /* Intentional empty */
1001 }
1002
1003 base->MAC_MDIO_ADDR = ENET_MAC_MDIO_ADDR_CR(crDiv);
1004 }
1005
1006 /*!
1007 * brief Starts a SMI write command.
1008 * support both MDIO IEEE802.3 Clause 22 and clause 45.
1009 *
1010 * param base ENET peripheral base address.
1011 * param phyAddr The PHY address.
1012 * param regAddr The PHY register.
1013 * param data The data written to PHY.
1014 */
ENET_StartSMIWrite(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t data)1015 void ENET_StartSMIWrite(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1016 {
1017 uint32_t reg = base->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
1018
1019 /* Build MII write command. */
1020 base->MAC_MDIO_ADDR = reg | ENET_MAC_MDIO_ADDR_MOC(kENET_MiiWriteFrame) | ENET_MAC_MDIO_ADDR_PA(phyAddr) |
1021 ENET_MAC_MDIO_ADDR_RDA(regAddr);
1022 base->MAC_MDIO_DATA = data;
1023 base->MAC_MDIO_ADDR |= ENET_MAC_MDIO_ADDR_MB_MASK;
1024 }
1025
1026 /*!
1027 * brief Starts an SMI read command.
1028 * support both MDIO IEEE802.3 Clause 22 and clause 45.
1029 *
1030 * param base ENET peripheral base address.
1031 * param phyAddr The PHY address.
1032 * param regAddr The PHY register.
1033 */
ENET_StartSMIRead(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr)1034 void ENET_StartSMIRead(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr)
1035 {
1036 uint32_t reg = base->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
1037
1038 /* Build MII read command. */
1039 base->MAC_MDIO_ADDR = reg | ENET_MAC_MDIO_ADDR_MOC(kENET_MiiReadFrame) | ENET_MAC_MDIO_ADDR_PA(phyAddr) |
1040 ENET_MAC_MDIO_ADDR_RDA(regAddr);
1041 base->MAC_MDIO_ADDR |= ENET_MAC_MDIO_ADDR_MB_MASK;
1042 }
1043
ENET_QOS_MDIOWaitTransferOver(ENET_Type * base)1044 static status_t ENET_QOS_MDIOWaitTransferOver(ENET_Type *base)
1045 {
1046 status_t result = kStatus_Success;
1047 #ifdef ENET_MDIO_TIMEOUT_COUNT
1048 uint32_t counter;
1049 #endif
1050
1051 #ifdef ENET_QOS_MDIO_TIMEOUT_COUNT
1052 for (counter = ENET_MDIO_TIMEOUT_COUNT; counter > 0U; counter--)
1053 {
1054 if (!ENET_IsSMIBusy(base))
1055 {
1056 break;
1057 }
1058 }
1059 /* Check for timeout. */
1060 if (0U == counter)
1061 {
1062 result = kStatus_Timeout;
1063 }
1064 #else
1065 while (ENET_IsSMIBusy(base))
1066 {
1067 }
1068 #endif
1069 return result;
1070 }
1071
1072 /*!
1073 * @brief MDIO write.
1074 *
1075 * @param base ENET peripheral base address.
1076 * @param phyAddr The PHY address.
1077 * @param regAddr The PHY register.
1078 * @param data The data written to PHY.
1079 * @return kStatus_Success MDIO access succeeds.
1080 * @return kStatus_Timeout MDIO access timeout.
1081 */
ENET_MDIOWrite(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t data)1082 status_t ENET_MDIOWrite(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1083 {
1084 ENET_StartSMIWrite(base, phyAddr, regAddr, data);
1085
1086 return ENET_QOS_MDIOWaitTransferOver(base);
1087 }
1088
1089 /*!
1090 * @brief MDIO read.
1091 *
1092 * @param base ENET peripheral base address.
1093 * @param phyAddr The PHY address.
1094 * @param regAddr The PHY register.
1095 * @param pData The data read from PHY.
1096 * @return kStatus_Success MDIO access succeeds.
1097 * @return kStatus_Timeout MDIO access timeout.
1098 */
ENET_MDIORead(ENET_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t * pData)1099 status_t ENET_MDIORead(ENET_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t *pData)
1100 {
1101 assert(pData);
1102
1103 status_t result;
1104
1105 ENET_StartSMIRead(base, phyAddr, regAddr);
1106
1107 result = ENET_QOS_MDIOWaitTransferOver(base);
1108 if (result != kStatus_Success)
1109 {
1110 return result;
1111 }
1112 *pData = ENET_ReadSMIData(base);
1113
1114 return result;
1115 }
1116
1117 /*!
1118 * brief Set the MAC to enter into power down mode.
1119 * the remote power wake up frame and magic frame can wake up
1120 * the ENET from the power down mode.
1121 *
1122 * param base ENET peripheral base address.
1123 * param wakeFilter The wakeFilter provided to configure the wake up frame fitlter.
1124 * Set the wakeFilter to NULL is not required. But if you have the filter requirement,
1125 * please make sure the wakeFilter pointer shall be eight continous
1126 * 32-bits configuration.
1127 */
ENET_EnterPowerDown(ENET_Type * base,uint32_t * wakeFilter)1128 void ENET_EnterPowerDown(ENET_Type *base, uint32_t *wakeFilter)
1129 {
1130 uint8_t index;
1131 uint32_t *reg = wakeFilter;
1132
1133 /* Disable the Tx dma. */
1134 base->DMA_CH[0].DMA_CHX_TX_CTRL &= ~ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
1135 base->DMA_CH[1].DMA_CHX_TX_CTRL &= ~ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
1136
1137 /* Disable the mac Tx/Rx. */
1138 base->MAC_CONFIG &= ~(ENET_MAC_CONFIG_RE_MASK | ENET_MAC_CONFIG_TE_MASK);
1139 /* Enable the remote wakeup packet and enable the power down mode. */
1140 if (wakeFilter != NULL)
1141 {
1142 for (index = 0; index < ENET_WAKEUPFILTER_NUM; index++)
1143 {
1144 base->MAC_RWAKE_FRFLT = *reg;
1145 reg++;
1146 }
1147 }
1148 base->MAC_PMT_CRTL_STAT = ENET_MAC_PMT_CRTL_STAT_MGKPKTEN_MASK | ENET_MAC_PMT_CRTL_STAT_RWKPKTEN_MASK |
1149 ENET_MAC_PMT_CRTL_STAT_PWRDWN_MASK;
1150
1151 /* Enable the MAC Rx. */
1152 base->MAC_CONFIG |= ENET_MAC_CONFIG_RE_MASK;
1153 }
1154
1155 /*!
1156 * brief Gets the size of the read frame.
1157 * This function gets a received frame size from the ENET buffer descriptors.
1158 * note The FCS of the frame is automatically removed by MAC and the size is the length without the FCS.
1159 * After calling ENET_GetRxFrameSize, ENET_ReadFrame() should be called to update the
1160 * receive buffers If the result is not "kStatus_ENET_RxFrameEmpty".
1161 *
1162 * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1163 * param length The length of the valid frame received.
1164 * param channel The DMAC channel for the Rx.
1165 * retval kStatus_ENET_RxFrameEmpty No frame received. Should not call ENET_ReadFrame to read frame.
1166 * retval kStatus_ENET_RxFrameError Data error happens. ENET_ReadFrame should be called with NULL data
1167 * and NULL length to update the receive buffers.
1168 * retval kStatus_Success Receive a frame Successfully then the ENET_ReadFrame
1169 * should be called with the right data buffer and the captured data length input.
1170 */
ENET_GetRxFrameSize(ENET_Type * base,enet_handle_t * handle,uint32_t * length,uint8_t channel)1171 status_t ENET_GetRxFrameSize(ENET_Type *base, enet_handle_t *handle, uint32_t *length, uint8_t channel)
1172 {
1173 assert(handle);
1174 assert(length);
1175
1176 enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1177 enet_rx_bd_struct_t *rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
1178 uint16_t index = rxBdRing->rxGenIdx;
1179
1180 /* Reset the length to zero. */
1181 *length = 0;
1182
1183 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_OWN_MASK) != 0U)
1184 {
1185 return kStatus_ENET_RxFrameEmpty;
1186 }
1187 else
1188 {
1189 do
1190 {
1191 /* Application owns the buffer descriptor, get the length. */
1192 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1193 {
1194 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_ERRSUM_MASK) != 0U)
1195 {
1196 return kStatus_ENET_RxFrameError;
1197 }
1198 *length = (rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - ENET_FCS_LEN;
1199 return kStatus_Success;
1200 }
1201
1202 index = ENET_IncreaseIndex(index, rxBdRing->rxRingLen);
1203 rxDesc = rxBdRing->rxBdBase + index;
1204 } while (index != rxBdRing->rxGenIdx);
1205
1206 return kStatus_ENET_RxFrameError;
1207 }
1208 }
1209
1210 /*!
1211 * brief Reads a frame from the ENET device.
1212 * This function reads a frame from the ENET DMA descriptors.
1213 * The ENET_GetRxFrameSize should be used to get the size of the prepared data buffer.
1214 * For example use Rx dma channel 0:
1215 * code
1216 * uint32_t length;
1217 * enet_handle_t g_handle;
1218 * Comment: Get the received frame size firstly.
1219 * status = ENET_GetRxFrameSize(&g_handle, &length, 0);
1220 * if (length != 0)
1221 * {
1222 * Comment: Allocate memory here with the size of "length"
1223 * uint8_t *data = memory allocate interface;
1224 * if (!data)
1225 * {
1226 * ENET_ReadFrame(ENET, &g_handle, NULL, 0, 0);
1227 * }
1228 * else
1229 * {
1230 * status = ENET_ReadFrame(ENET, &g_handle, data, length, 0);
1231 * }
1232 * }
1233 * else if (status == kStatus_ENET_RxFrameError)
1234 * {
1235 * Comment: Update the received buffer when a error frame is received.
1236 * ENET_ReadFrame(ENET, &g_handle, NULL, 0, 0);
1237 * }
1238 * endcode
1239 * param base ENET peripheral base address.
1240 * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1241 * param data The data buffer provided by user to store the frame which memory size should be at least "length".
1242 * param length The size of the data buffer which is still the length of the received frame.
1243 * param channel The Rx DMA channel. shall not be larger than 2.
1244 * param timestamp The timestamp address to store received timestamp.
1245 * return The execute status, successful or failure.
1246 */
ENET_ReadFrame(ENET_Type * base,enet_handle_t * handle,uint8_t * data,uint32_t length,uint8_t channel,enet_ptp_time_t * timestamp)1247 status_t ENET_ReadFrame(
1248 ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length, uint8_t channel, enet_ptp_time_t *timestamp)
1249 {
1250 assert(handle);
1251
1252 enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1253 uint32_t len = 0;
1254 uint32_t offset = 0;
1255 bool isLastBuff = false;
1256 status_t result = kStatus_Fail;
1257 bool suspend = false;
1258 enet_rx_bd_struct_t *rxDesc;
1259 #ifdef ENET_PTP1588FEATURE_REQUIRED
1260 uint32_t buffer;
1261 uint32_t bufferAdd;
1262 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1263
1264 /* Suspend and command for Rx. */
1265 if ((base->DMA_CH[channel].DMA_CHX_STAT & ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK) != 0U)
1266 {
1267 suspend = true;
1268 }
1269
1270 /* For data-NULL input, only update the buffer descriptor. */
1271 if (data == NULL)
1272 {
1273 ENET_DropFrame(base, handle, channel);
1274 result = kStatus_Success;
1275 }
1276 else
1277 {
1278 while (!isLastBuff)
1279 {
1280 /* The last buffer descriptor of a frame. */
1281 rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
1282 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1283
1284 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1285 {
1286 /* This is a valid frame. */
1287 isLastBuff = true;
1288 if (length == ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - ENET_FCS_LEN))
1289 {
1290 /* Copy the frame to user's buffer. */
1291 len = length - offset;
1292 if (len > rxBdRing->rxBuffSizeAlign)
1293 {
1294 (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes0,
1295 rxBdRing->rxBuffSizeAlign);
1296 offset += rxBdRing->rxBuffSizeAlign;
1297 (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes2,
1298 len - rxBdRing->rxBuffSizeAlign);
1299 }
1300 else
1301 {
1302 (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes0,
1303 len);
1304 }
1305
1306 result = kStatus_Success;
1307 }
1308
1309 /* Updates the receive buffer descriptors. */
1310 ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1311 #ifdef ENET_PTP1588FEATURE_REQUIRED
1312 /* Store the Rx timestamp which is in the next buffer descriptor of the last
1313 * descriptor of a frame. */
1314 rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
1315
1316 /* Reinit for the context descritor which has been updated by DMA. */
1317 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_CTXT_MASK) != 0U)
1318 {
1319 if (timestamp != NULL)
1320 {
1321 uint32_t timerCount;
1322
1323 /* Get receive frame timestamp. */
1324 timestamp->second = rxDesc->rdes1;
1325 timerCount = rxDesc->rdes0;
1326 if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) == 0U)
1327 {
1328 /* Binary rollover. */
1329 timestamp->nanosecond = ENET_BINARY_ROLLOVER_SCALE(timerCount);
1330 }
1331 else
1332 {
1333 timestamp->nanosecond = timerCount;
1334 }
1335 }
1336
1337 if (!handle->doubleBuffEnable)
1338 {
1339 buffer = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1340 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buffer, NULL, handle->rxintEnable,
1341 handle->doubleBuffEnable);
1342 }
1343 else
1344 {
1345 buffer = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1346 bufferAdd = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1347 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buffer, (void *)(uint32_t *)bufferAdd,
1348 handle->rxintEnable, handle->doubleBuffEnable);
1349 }
1350 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1351 }
1352 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR;
1353 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1354 }
1355 else
1356 {
1357 /* Store a frame on several buffer descriptors. */
1358 isLastBuff = false;
1359 /* Length check. */
1360 if (offset >= length)
1361 {
1362 /* Updates the receive buffer descriptors. */
1363 ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1364 break;
1365 }
1366
1367 (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes0,
1368 rxBdRing->rxBuffSizeAlign);
1369 offset += rxBdRing->rxBuffSizeAlign;
1370 if (((rxDesc->rdes2) != 0U) && (handle->doubleBuffEnable))
1371 {
1372 (void)memcpy((void *)(uint32_t *)(uint32_t)(data + offset), (void *)(uint32_t *)rxDesc->rdes2,
1373 rxBdRing->rxBuffSizeAlign);
1374 offset += rxBdRing->rxBuffSizeAlign;
1375 }
1376
1377 /* Updates the receive buffer descriptors. */
1378 ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1379 }
1380 }
1381 }
1382
1383 /* Set command for Rx when it is suspend. */
1384 if (suspend)
1385 {
1386 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR;
1387 }
1388
1389 return result;
1390 }
1391
1392 /*!
1393 * brief Updates the buffers and the own status for a given Rx descriptor.
1394 * This function is a low level functional API to Updates the
1395 * buffers and the own status for a given Rx descriptor.
1396 *
1397 * param rxDesc The given Rx descriptor.
1398 * param buffer1 The first buffer address in the descriptor.
1399 * param buffer2 The second buffer address in the descriptor.
1400 * param intEnable Interrupt enable flag.
1401 * param doubleBuffEnable The double buffer enable flag.
1402 *
1403 * note This must be called after all the ENET initilization.
1404 * And should be called when the ENET receive/transmit is required.
1405 */
ENET_UpdateRxDescriptor(enet_rx_bd_struct_t * rxDesc,void * buffer1,void * buffer2,bool intEnable,bool doubleBuffEnable)1406 void ENET_UpdateRxDescriptor(
1407 enet_rx_bd_struct_t *rxDesc, void *buffer1, void *buffer2, bool intEnable, bool doubleBuffEnable)
1408 {
1409 assert(rxDesc);
1410 uint32_t control = ENET_RXDESCRIP_RD_OWN_MASK | ENET_RXDESCRIP_RD_BUFF1VALID_MASK;
1411
1412 if (intEnable)
1413 {
1414 control |= ENET_RXDESCRIP_RD_IOC_MASK;
1415 }
1416
1417 if (doubleBuffEnable)
1418 {
1419 control |= ENET_RXDESCRIP_RD_BUFF2VALID_MASK;
1420 }
1421
1422 /* Update the buffer if needed. */
1423 if (buffer1 != NULL)
1424 {
1425 rxDesc->rdes0 = (uint32_t)(uint32_t *)buffer1;
1426 }
1427 if (buffer2 != NULL)
1428 {
1429 rxDesc->rdes2 = (uint32_t)(uint32_t *)buffer2;
1430 }
1431 else
1432 {
1433 rxDesc->rdes2 = 0;
1434 }
1435
1436 rxDesc->rdes1 = 0;
1437 rxDesc->rdes3 = control;
1438 }
1439
1440 /*!
1441 * brief Allocates Rx buffers for all BDs.
1442 * It's used for zero copy Rx. In zero copy Rx case, Rx buffers are dynamic. This function
1443 * will populate initial buffers in all BDs for receiving. Then ENET_GetRxFrame() is used
1444 * to get Rx frame with zero copy, it will allocate new buffer to replace the buffer in BD taken
1445 * by application, application should free those buffers after they're used.
1446 *
1447 * note This function should be called after ENET_CreateHandler() and buffer allocating callback
1448 * function should be ready.
1449 *
1450 * param base ENET peripheral base address.
1451 * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1452 */
ENET_RxBufferAllocAll(ENET_Type * base,enet_handle_t * handle)1453 status_t ENET_RxBufferAllocAll(ENET_Type *base, enet_handle_t *handle)
1454 {
1455 status_t result = kStatus_Success;
1456 enet_rx_bd_struct_t *rxbdPtr;
1457 uint32_t buffAddr;
1458 uint8_t channel;
1459 uint16_t index;
1460 uint16_t j;
1461 uint8_t ringNum = (handle->multiQueEnable) ? 2U : 1U;
1462
1463 if ((handle->rxBuffAlloc == NULL) || (handle->rxBuffFree == NULL))
1464 {
1465 return kStatus_ENET_InitMemoryFail;
1466 }
1467
1468 for (channel = 0; channel < ringNum; channel++)
1469 {
1470 /* Init the rxbdPtr to the receive descriptor start address. */
1471 rxbdPtr = handle->rxBdRing[channel].rxBdBase;
1472 for (j = 0U; j < handle->rxBdRing[channel].rxRingLen; j++)
1473 {
1474 if (handle->doubleBuffEnable)
1475 {
1476 index = 2U * j;
1477 }
1478 else
1479 {
1480 index = j;
1481 }
1482
1483 buffAddr = (uint32_t)(uint32_t *)handle->rxBuffAlloc(base, handle->userData, channel);
1484 if (buffAddr == 0U)
1485 {
1486 result = kStatus_ENET_InitMemoryFail;
1487 break;
1488 }
1489
1490 rxbdPtr->rdes0 = buffAddr;
1491 handle->rxBufferStartAddr[channel][index] = buffAddr;
1492
1493 /* The second buffer is set with 0 because it is not required for normal case. */
1494 if (handle->doubleBuffEnable)
1495 {
1496 buffAddr = (uint32_t)(uint32_t *)handle->rxBuffAlloc(base, handle->userData, channel);
1497 if (buffAddr == 0U)
1498 {
1499 result = kStatus_ENET_InitMemoryFail;
1500 break;
1501 }
1502
1503 rxbdPtr->rdes2 = buffAddr;
1504 handle->rxBufferStartAddr[channel][index + 1U] = buffAddr;
1505 }
1506 else
1507 {
1508 rxbdPtr->rdes2 = 0;
1509 }
1510
1511 /* Set the valid and DMA own flag.*/
1512 rxbdPtr->rdes3 |= ENET_RXDESCRIP_WR_OWN_MASK;
1513 rxbdPtr++;
1514 }
1515 }
1516
1517 if (result == kStatus_ENET_InitMemoryFail)
1518 {
1519 ENET_RxBufferFreeAll(base, handle);
1520 }
1521
1522 return result;
1523 }
1524
1525 /*!
1526 * brief Frees Rx buffers in all BDs.
1527 * It's used for zero copy Rx. In zero copy Rx case, Rx buffers are dynamic. This function
1528 * frees left buffers in all BDs.
1529 *
1530 * param base ENET peripheral base address.
1531 * param handle The ENET handler structure. This is the same handler pointer used in the ENET_Init.
1532 */
ENET_RxBufferFreeAll(ENET_Type * base,enet_handle_t * handle)1533 void ENET_RxBufferFreeAll(ENET_Type *base, enet_handle_t *handle)
1534 {
1535 uint8_t ringNum = (handle->multiQueEnable) ? 2U : 1U;
1536 uint8_t channel;
1537 uint32_t buffAddr;
1538 uint16_t index;
1539 uint16_t j;
1540
1541 if (handle->rxBuffFree != NULL)
1542 {
1543 for (channel = 0; channel < ringNum; channel++)
1544 {
1545 for (j = 0U; j < handle->rxBdRing[channel].rxRingLen; j++)
1546 {
1547 index = (handle->doubleBuffEnable) ? (2U * j) : j;
1548
1549 buffAddr = (uint32_t)handle->rxBufferStartAddr[channel][index];
1550 if (buffAddr != 0U)
1551 {
1552 handle->rxBuffFree(base, (void *)(uint32_t *)buffAddr, handle->userData, channel);
1553 }
1554
1555 /* The second buffer is set with 0 because it is not required for normal case. */
1556 if (handle->doubleBuffEnable)
1557 {
1558 buffAddr = (uint32_t)handle->rxBufferStartAddr[channel][index + 1U];
1559 if (buffAddr != 0U)
1560 {
1561 handle->rxBuffFree(base, (void *)(uint32_t *)buffAddr, handle->userData, channel);
1562 }
1563 }
1564 }
1565 }
1566 }
1567 }
1568
ENET_GetRxFrameErr(enet_rx_bd_struct_t * rxDesc,enet_rx_frame_error_t * rxFrameError)1569 static inline void ENET_GetRxFrameErr(enet_rx_bd_struct_t *rxDesc, enet_rx_frame_error_t *rxFrameError)
1570 {
1571 uint32_t rdes3 = rxDesc->rdes3;
1572 union _frame_error
1573 {
1574 uint32_t data;
1575 enet_rx_frame_error_t frameError;
1576 };
1577 union _frame_error error;
1578
1579 (void)memset((void *)&error.frameError, 0, sizeof(enet_rx_frame_error_t));
1580
1581 error.data = ENET_FRAME_RX_ERROR_BITS(rdes3);
1582 }
1583
ENET_DropFrame(ENET_Type * base,enet_handle_t * handle,uint8_t channel)1584 static void ENET_DropFrame(ENET_Type *base, enet_handle_t *handle, uint8_t channel)
1585 {
1586 enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1587 enet_rx_bd_struct_t *rxDesc;
1588 uint16_t index = rxBdRing->rxGenIdx;
1589 #ifdef ENET_PTP1588FEATURE_REQUIRED
1590 bool tsAvailable = false;
1591 uint32_t buff1Addr = 0;
1592 uint32_t buff2Addr = 0;
1593 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1594
1595 /* Not check DMA ownership here, assume there's at least one valid frame left in BD ring */
1596 do
1597 {
1598 /* Update the BD to idle status. */
1599 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1600 ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
1601 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1602
1603 /* Find the last buffer descriptor for the frame. */
1604 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1605 {
1606 #ifdef ENET_PTP1588FEATURE_REQUIRED
1607 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_RS1V_MASK) != 0U)
1608 {
1609 if ((rxDesc->rdes1 & ENET_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
1610 {
1611 tsAvailable = true;
1612 }
1613 }
1614
1615 /* Reinit for the context descriptor which has been updated by DMA. */
1616 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1617
1618 if (tsAvailable && ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_CTXT_MASK) != 0U))
1619 {
1620 if (!handle->doubleBuffEnable)
1621 {
1622 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1623 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
1624 handle->doubleBuffEnable);
1625 }
1626 else
1627 {
1628 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1629 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1630 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
1631 handle->rxintEnable, handle->doubleBuffEnable);
1632 }
1633 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1634 }
1635 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1636 break;
1637 }
1638 } while (rxBdRing->rxGenIdx != index);
1639
1640 /* Always try to start receive, in case it had stopped */
1641 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = (uint32_t)(uint8_t *)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
1642 }
1643
1644 /*!
1645 * brief Receives one frame in specified BD ring with zero copy.
1646 *
1647 * This function will use the user-defined allocate and free callback. Every time application gets one frame through
1648 * this function, driver will allocate new buffers for the BDs whose buffers have been taken by application.
1649 * note This function will drop current frame and update related BDs as available for DMA if new buffers allocating
1650 * fails. Application must provide a memory pool including at least BD number + 1 buffers(+2 if enable double buffer)
1651 * to make this function work normally. If user calls this function in Rx interrupt handler, be careful that this
1652 * function makes Rx BD ready with allocating new buffer(normal) or updating current BD(out of memory). If there's
1653 * always new Rx frame input, Rx interrupt will be triggered forever. Application need to disable Rx interrupt according
1654 * to specific design in this case.
1655 *
1656 * param base ENET peripheral base address.
1657 * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
1658 * param rxFrame The received frame information structure provided by user.
1659 * param channel The Rx DMA channel. Shall not be larger than 2.
1660 * retval kStatus_Success Succeed to get one frame and allocate new memory for Rx buffer.
1661 * retval kStatus_ENET_RxFrameEmpty There's no Rx frame in the BD.
1662 * retval kStatus_ENET_RxFrameError There's issue in this receiving. In this function, issue frame will be dropped.
1663 * retval kStatus_ENET_RxFrameDrop There's no new buffer memory for BD, dropped this frame.
1664 */
ENET_GetRxFrame(ENET_Type * base,enet_handle_t * handle,enet_rx_frame_struct_t * rxFrame,uint8_t channel)1665 status_t ENET_GetRxFrame(ENET_Type *base, enet_handle_t *handle, enet_rx_frame_struct_t *rxFrame, uint8_t channel)
1666 {
1667 assert(handle != NULL);
1668 assert(channel < ENET_RING_NUM_MAX);
1669
1670 enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
1671 enet_rx_bd_struct_t *rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1672 uint16_t index = rxBdRing->rxGenIdx;
1673 status_t result = kStatus_Success;
1674 uint32_t buff1Addr = 0;
1675 uint32_t buff2Addr = 0;
1676 uint16_t buff1Len = 0;
1677 uint16_t buff2Len = 0;
1678 uint16_t offset = 0;
1679 void *newBuff1 = NULL;
1680 void *newBuff2 = NULL;
1681 bool isDrop = false;
1682 bool isLastBuff = false;
1683 #ifdef ENET_PTP1588FEATURE_REQUIRED
1684 bool tsAvailable = false;
1685 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1686
1687 /* Check the frame status. */
1688 do
1689 {
1690 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_OWN_MASK) != 0U)
1691 {
1692 result = kStatus_ENET_RxFrameEmpty;
1693 break;
1694 }
1695
1696 /* Check timestamp and error. */
1697 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1698 {
1699 #ifdef ENET_PTP1588FEATURE_REQUIRED
1700 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_RS1V_MASK) != 0U)
1701 {
1702 if ((rxDesc->rdes1 & ENET_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
1703 {
1704 tsAvailable = true;
1705 }
1706 }
1707 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1708
1709 /* Get the frame error if there is. */
1710 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_ERRSUM_MASK) != 0U)
1711 {
1712 ENET_GetRxFrameErr(rxDesc, &rxFrame->rxFrameError);
1713 result = kStatus_ENET_RxFrameError;
1714 }
1715 else if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK) == 0U)
1716 {
1717 result = kStatus_ENET_RxFrameEmpty;
1718 }
1719 else
1720 {
1721 /* Intentional empty */
1722 }
1723 break;
1724 }
1725
1726 index = ENET_IncreaseIndex(index, rxBdRing->rxRingLen);
1727 if (index == rxBdRing->rxGenIdx)
1728 {
1729 result = kStatus_ENET_RxFrameEmpty;
1730 break;
1731 }
1732 rxDesc = &rxBdRing->rxBdBase[index];
1733 } while (index != rxBdRing->rxGenIdx);
1734
1735 /* Drop the error frame and return error. */
1736 if (result != kStatus_Success)
1737 {
1738 if (result == kStatus_ENET_RxFrameError)
1739 {
1740 ENET_DropFrame(base, handle, channel);
1741 }
1742 return result;
1743 }
1744
1745 /* Get the valid frame */
1746 index = 0;
1747 do
1748 {
1749 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1750
1751 /* Calculate the buffer and frame length. */
1752 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_LD_MASK) != 0U)
1753 {
1754 isLastBuff = true;
1755 rxFrame->totLen = (uint16_t)(rxDesc->rdes3 & ENET_RXDESCRIP_WR_PACKETLEN_MASK);
1756
1757 if (rxFrame->totLen - offset > (uint16_t)rxBdRing->rxBuffSizeAlign)
1758 {
1759 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1760 if (handle->doubleBuffEnable)
1761 {
1762 buff2Len = rxFrame->totLen - offset - (uint16_t)rxBdRing->rxBuffSizeAlign - ENET_FCS_LEN;
1763 }
1764 }
1765 else
1766 {
1767 buff1Len = rxFrame->totLen - offset - ENET_FCS_LEN;
1768 }
1769 rxFrame->totLen -= ENET_FCS_LEN;
1770 }
1771 else
1772 {
1773 if (!handle->doubleBuffEnable)
1774 {
1775 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1776 offset += buff1Len;
1777 }
1778 else
1779 {
1780 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1781 buff2Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
1782 offset += buff1Len + buff2Len;
1783 }
1784 }
1785
1786 /* Allocate new buffer to replace the buffer taken by application */
1787 newBuff1 = handle->rxBuffAlloc(base, handle->userData, channel);
1788 if (newBuff1 == NULL)
1789 {
1790 isDrop = true;
1791 }
1792 else if (handle->doubleBuffEnable && (buff2Len != 0U))
1793 {
1794 newBuff2 = handle->rxBuffAlloc(base, handle->userData, channel);
1795 if (newBuff2 == NULL)
1796 {
1797 handle->rxBuffFree(base, newBuff1, handle->userData, channel);
1798 isDrop = true;
1799 }
1800 }
1801 else
1802 {
1803 /* Intentional empty */
1804 }
1805
1806 if (!isDrop)
1807 {
1808 /* Get the frame data information into Rx frame structure. */
1809 if (!handle->doubleBuffEnable)
1810 {
1811 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1812 rxFrame->rxBuffArray[index].buffer = (void *)(uint32_t *)buff1Addr;
1813 rxFrame->rxBuffArray[index].length = buff1Len;
1814 index++;
1815 }
1816 else
1817 {
1818 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1819 rxFrame->rxBuffArray[index].buffer = (void *)(uint32_t *)buff1Addr;
1820 rxFrame->rxBuffArray[index].length = buff1Len;
1821 index++;
1822
1823 /* If there's no data in buffer2, not add it into rxFrame */
1824 if (buff2Len != 0U)
1825 {
1826 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1827 rxFrame->rxBuffArray[index].buffer = (void *)(uint32_t *)buff2Addr;
1828 rxFrame->rxBuffArray[index].length = buff2Len;
1829 index++;
1830 }
1831 }
1832
1833 /* Give new buffer from application to BD */
1834 if (!handle->doubleBuffEnable)
1835 {
1836 buff1Addr = (uint32_t)(uint32_t *)newBuff1;
1837 handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx] = buff1Addr;
1838 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buff1Addr, NULL, handle->rxintEnable,
1839 handle->doubleBuffEnable);
1840 }
1841 else
1842 {
1843 buff1Addr = (uint32_t)(uint32_t *)newBuff1;
1844 handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx] = buff1Addr;
1845
1846 if (buff2Len != 0U)
1847 {
1848 buff2Addr = (uint32_t)(uint32_t *)newBuff2;
1849 handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U] = buff2Addr;
1850 }
1851 else
1852 {
1853 /* If there's no data in buffer2, keep it */
1854 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1855 }
1856
1857 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint32_t *)buff1Addr, (void *)(uint32_t *)buff2Addr,
1858 handle->rxintEnable, handle->doubleBuffEnable);
1859 }
1860 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1861
1862 #ifdef ENET_PTP1588FEATURE_REQUIRED
1863 /* Update context BD if there is */
1864 if (isLastBuff && tsAvailable)
1865 {
1866 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
1867 if ((rxDesc->rdes3 & ENET_RXDESCRIP_WR_CTXT_MASK) != 0U)
1868 {
1869 uint32_t timerCount;
1870
1871 /* Get receive frame timestamp. */
1872 rxFrame->rxAttribute.timestamp.second = rxDesc->rdes1;
1873 timerCount = rxDesc->rdes0;
1874 if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) == 0U)
1875 {
1876 /* Binary rollover. */
1877 rxFrame->rxAttribute.timestamp.nanosecond = ENET_BINARY_ROLLOVER_SCALE(timerCount);
1878 }
1879 else
1880 {
1881 rxFrame->rxAttribute.timestamp.nanosecond = timerCount;
1882 }
1883 rxFrame->rxAttribute.isTsAvail = true;
1884
1885 if (!handle->doubleBuffEnable)
1886 {
1887 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
1888 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
1889 handle->doubleBuffEnable);
1890 }
1891 else
1892 {
1893 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
1894 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
1895 ENET_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
1896 handle->rxintEnable, handle->doubleBuffEnable);
1897 }
1898 rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
1899 }
1900 }
1901 #else
1902 rxFrame->rxAttribute.isTsAvail = false;
1903 #endif /* ENET_PTP1588FEATURE_REQUIRED */
1904
1905 /* Always try to start receive, in case it had stopped */
1906 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR =
1907 (uint32_t)(uint8_t *)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
1908 }
1909 else
1910 {
1911 /* Drop frame if there's no new buffer memory */
1912
1913 /* Free the incomplete frame buffers. */
1914 while (index-- != 0U)
1915 {
1916 handle->rxBuffFree(base, &rxFrame->rxBuffArray[index].buffer, handle->userData, channel);
1917 }
1918
1919 /* Update all left BDs of this frame from current index. */
1920 ENET_DropFrame(base, handle, channel);
1921
1922 result = kStatus_ENET_RxFrameDrop;
1923 break;
1924 }
1925 } while (!isLastBuff);
1926
1927 return result;
1928 }
1929
1930 /*!
1931 * brief Setup a given Tx descriptor.
1932 * This function is a low level functional API to setup or prepare
1933 * a given Tx descriptor.
1934 *
1935 * param txDesc The given Tx descriptor.
1936 * param buffer1 The first buffer address in the descriptor.
1937 * param bytes1 The bytes in the fist buffer.
1938 * param buffer2 The second buffer address in the descriptor.
1939 * param bytes2 The bytes in the second buffer.
1940 * param framelen The length of the frame to be transmitted.
1941 * param intEnable Interrupt enable flag.
1942 * param tsEnable The timestamp enable.
1943 * param flag The flag of this Tx desciriptor, see "enet_desc_flag_t" .
1944 * param slotNum The slot num used for AV mode only.
1945 *
1946 * note This must be called after all the ENET initilization.
1947 * And should be called when the ENET receive/transmit is required.
1948 * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
1949 * memory until the packet has been fully transmitted. The buffers
1950 * should be free or requeued in the transmit interrupt irq handler.
1951 */
ENET_SetupTxDescriptor(enet_tx_bd_struct_t * txDesc,void * buffer1,uint32_t bytes1,void * buffer2,uint32_t bytes2,uint32_t framelen,bool intEnable,bool tsEnable,enet_desc_flag_t flag,uint8_t slotNum)1952 void ENET_SetupTxDescriptor(enet_tx_bd_struct_t *txDesc,
1953 void *buffer1,
1954 uint32_t bytes1,
1955 void *buffer2,
1956 uint32_t bytes2,
1957 uint32_t framelen,
1958 bool intEnable,
1959 bool tsEnable,
1960 enet_desc_flag_t flag,
1961 uint8_t slotNum)
1962 {
1963 uint32_t control = ENET_TXDESCRIP_RD_BL1(bytes1) | ENET_TXDESCRIP_RD_BL2(bytes2);
1964
1965 if ((flag == kENET_FirstFlagOnly) || (flag == kENET_FirstLastFlag))
1966 {
1967 if (tsEnable)
1968 {
1969 control |= ENET_TXDESCRIP_RD_TTSE_MASK;
1970 }
1971 else
1972 {
1973 control &= ~ENET_TXDESCRIP_RD_TTSE_MASK;
1974 }
1975 }
1976
1977 if (intEnable)
1978 {
1979 control |= ENET_TXDESCRIP_RD_IOC_MASK;
1980 }
1981 else
1982 {
1983 control &= ~ENET_TXDESCRIP_RD_IOC_MASK;
1984 }
1985
1986 /* Preare the descriptor for transmit. */
1987 txDesc->tdes0 = (uint32_t)(uint32_t *)buffer1;
1988 txDesc->tdes1 = (uint32_t)(uint32_t *)buffer2;
1989 txDesc->tdes2 = control;
1990
1991 control = ENET_TXDESCRIP_RD_SLOT(slotNum) | ENET_TXDESCRIP_RD_FL(framelen) | ENET_TXDESCRIP_RD_LDFD(flag) |
1992 ENET_TXDESCRIP_RD_OWN_MASK;
1993
1994 txDesc->tdes3 = control;
1995 }
1996
1997 /*!
1998 * brief Configure a given Tx descriptor.
1999 * This function is a low level functional API to setup or prepare
2000 * a given Tx descriptor.
2001 *
2002 * param txDesc The given Tx descriptor.
2003 * param config The Tx descriptor configuration.
2004 *
2005 * note This must be called after all the ENET initilization.
2006 * And should be called when the ENET receive/transmit is required.
2007 * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
2008 * memory until the packet has been fully transmitted. The buffers
2009 * should be free or requeued in the transmit interrupt irq handler.
2010 */
ENET_ConfigTxDescriptor(enet_tx_bd_struct_t * txDesc,enet_tx_bd_config_struct_t * config)2011 static void ENET_ConfigTxDescriptor(enet_tx_bd_struct_t *txDesc, enet_tx_bd_config_struct_t *config)
2012 {
2013 uint32_t control = ENET_TXDESCRIP_RD_BL1(config->bytes1) | ENET_TXDESCRIP_RD_BL2(config->bytes2);
2014 enet_tx_offload_t txOffloadMode = kENET_TxOffloadDisable;
2015
2016 if ((config->flag == kENET_FirstFlagOnly) || (config->flag == kENET_FirstLastFlag))
2017 {
2018 if (config->tsEnable)
2019 {
2020 control |= ENET_TXDESCRIP_RD_TTSE_MASK;
2021 }
2022 else
2023 {
2024 control &= ~ENET_TXDESCRIP_RD_TTSE_MASK;
2025 }
2026 txOffloadMode = config->txOffloadOps;
2027 }
2028
2029 if (config->intEnable)
2030 {
2031 control |= ENET_TXDESCRIP_RD_IOC_MASK;
2032 }
2033 else
2034 {
2035 control &= ~ENET_TXDESCRIP_RD_IOC_MASK;
2036 }
2037
2038 /* Preare the descriptor for transmit. */
2039 txDesc->tdes0 = (uint32_t)(uint32_t *)config->buffer1;
2040 txDesc->tdes1 = (uint32_t)(uint32_t *)config->buffer2;
2041 txDesc->tdes2 = control;
2042
2043 control = ENET_TXDESCRIP_RD_SLOT(config->slotNum) | ENET_TXDESCRIP_RD_FL(config->framelen) |
2044 ENET_TXDESCRIP_RD_CIC(txOffloadMode) | ENET_TXDESCRIP_RD_LDFD(config->flag) | ENET_TXDESCRIP_RD_OWN_MASK;
2045
2046 txDesc->tdes3 = control;
2047 }
2048
2049 /*!
2050 * brief Reclaim Tx descriptors.
2051 * This function is used to update the Tx descriptor status and
2052 * store the Tx timestamp when the 1588 feature is enabled.
2053 * This is called by the transmit interupt IRQ handler after the
2054 * complete of a frame transmission.
2055 *
2056 * param base ENET peripheral base address.
2057 * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
2058 * param channel The Tx DMA channnel.
2059 *
2060 */
ENET_ReclaimTxDescriptor(ENET_Type * base,enet_handle_t * handle,uint8_t channel)2061 void ENET_ReclaimTxDescriptor(ENET_Type *base, enet_handle_t *handle, uint8_t channel)
2062 {
2063 enet_tx_bd_ring_t *txBdRing = &handle->txBdRing[channel];
2064 enet_tx_bd_struct_t *txDesc = txBdRing->txBdBase + txBdRing->txConsumIdx;
2065 enet_tx_dirty_ring_t *txDirtyRing = (enet_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2066 enet_tx_reclaim_info_t *txDirty = NULL;
2067
2068 /* Need to update the first index for transmit buffer free. */
2069 while ((txBdRing->txDescUsed > 0U) && ((txDesc->tdes3 & ENET_TXDESCRIP_RD_OWN_MASK) == 0U))
2070 {
2071 if ((txDesc->tdes3 & ENET_TXDESCRIP_RD_LD_MASK) != 0U)
2072 {
2073 txDirty = &txDirtyRing->txDirtyBase[txDirtyRing->txConsumIdx];
2074 txDirtyRing->txConsumIdx = ENET_IncreaseIndex(txDirtyRing->txConsumIdx, txDirtyRing->txRingLen);
2075 txDirty->isTsAvail = false;
2076
2077 #ifdef ENET_PTP1588FEATURE_REQUIRED
2078 uint32_t nanosecond = 0;
2079
2080 if ((txDesc->tdes3 & ENET_TXDESCRIP_WB_TTSS_MASK) != 0U)
2081 {
2082 /* Get transmit time stamp second. */
2083 nanosecond = txDesc->tdes0;
2084 if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) == 0U)
2085 {
2086 /* Binary rollover. */
2087 txDirty->timeStamp.nanosecond = ENET_BINARY_ROLLOVER_SCALE(nanosecond);
2088 }
2089 else
2090 {
2091 txDirty->timeStamp.nanosecond = nanosecond;
2092 }
2093 txDirty->timeStamp.second = txDesc->tdes1;
2094 txDirty->isTsAvail = true;
2095 }
2096 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2097 /* For Tx buffer free or requeue for each descriptor.
2098 * The Tx interrupt callback should free/requeue the Tx buffer. */
2099 if (handle->callback != NULL)
2100 {
2101 handle->callback(base, handle, kENET_TxIntEvent, channel, txDirty, handle->userData);
2102 }
2103 }
2104
2105 /* Update the used Tx descriptor count. */
2106 txBdRing->txDescUsed--;
2107
2108 /* Update the txConsumIdx/txDesc. */
2109 txBdRing->txConsumIdx = ENET_IncreaseIndex(txBdRing->txConsumIdx, txBdRing->txRingLen);
2110 txDesc = txBdRing->txBdBase + txBdRing->txConsumIdx;
2111 }
2112 }
2113
2114 /*!
2115 * brief Transmits an ENET frame.
2116 * note The CRC is automatically appended to the data. Input the data
2117 * to send without the CRC. This API uses input buffer for Tx, application
2118 * should reclaim the buffer after Tx is over.
2119 *
2120 * param base ENET peripheral base address.
2121 * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
2122 * param txFrame The Tx frame structure.
2123 * param channel Channel to send the frame, same with queue index.
2124 * retval kStatus_Success Send frame succeed.
2125 * retval kStatus_ENET_TxFrameBusy Transmit buffer descriptor is busy under transmission.
2126 * The transmit busy happens when the data send rate is over the MAC capacity.
2127 * The waiting mechanism is recommended to be added after each call return with kStatus_ENET_TxFrameBusy.
2128 * Also need to pay attention to reclaim Tx frame after Tx is over.
2129 * retval kStatus_ENET_TxFrameOverLen Transmit frme length exceeds the 0x3FFF limit defined by the driver.
2130 */
ENET_SendFrame(ENET_Type * base,enet_handle_t * handle,enet_tx_frame_struct_t * txFrame,uint8_t channel)2131 status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, enet_tx_frame_struct_t *txFrame, uint8_t channel)
2132 {
2133 assert(handle);
2134 assert(handle->txDirtyRing[channel].txDirtyBase != NULL);
2135 assert(txFrame);
2136 assert(txFrame->txBuffNum != 0U);
2137 assert(txFrame->txBuffArray != NULL);
2138
2139 enet_tx_bd_ring_t *txBdRing = (enet_tx_bd_ring_t *)&handle->txBdRing[channel];
2140 enet_tx_dirty_ring_t *txDirtyRing = (enet_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2141 enet_tx_reclaim_info_t *txDirty = &txDirtyRing->txDirtyBase[txDirtyRing->txGenIdx];
2142 enet_buffer_struct_t *txBuff = txFrame->txBuffArray;
2143 uint32_t frameLen = 0;
2144 uint32_t index = 0;
2145 enet_tx_bd_struct_t *txDesc;
2146 enet_desc_flag_t descFlag;
2147 uint32_t leftBuffNum;
2148
2149 /* Calculate total frame length and the Tx buffer number if it's scattered. */
2150 for (index = 0; index < txFrame->txBuffNum; index++)
2151 {
2152 frameLen += txBuff[index].length;
2153 }
2154
2155 /* Here use maximum length of single buffer in hardware as transmit length limitation, cause it's long enough.
2156 * And it simplifies the check of buffer length. There's no need to check each buffer length. */
2157 if (frameLen > ENET_FRAME_TX_LEN_LIMITATION)
2158 {
2159 return kStatus_ENET_TxFrameOverLen;
2160 }
2161
2162 /* Check Tx FIFO whether can store enough frame data. */
2163 if (0U != handle->txLenLimitation[channel])
2164 {
2165 if (frameLen > handle->txLenLimitation[channel])
2166 {
2167 return kStatus_ENET_TxFrameOverLen;
2168 }
2169 }
2170
2171 /* Check whether the available BD number is enough for Tx data buffer. */
2172 if (txFrame->txBuffNum > (((uint32_t)txBdRing->txRingLen - (uint32_t)txBdRing->txDescUsed) * 2U))
2173 {
2174 return kStatus_ENET_TxFrameBusy;
2175 }
2176
2177 /* Update the context in Tx dirty ring for reclaim */
2178 txDirty->context = txFrame->context;
2179 txDirtyRing->txGenIdx = ENET_IncreaseIndex(txDirtyRing->txGenIdx, txDirtyRing->txRingLen);
2180
2181 index = 0;
2182 leftBuffNum = txFrame->txBuffNum;
2183 do
2184 {
2185 txDesc = &txBdRing->txBdBase[txBdRing->txGenIdx];
2186
2187 /* Get the right flag for current BD */
2188 if (leftBuffNum == txFrame->txBuffNum)
2189 {
2190 descFlag = (leftBuffNum > 2U) ? kENET_FirstFlagOnly : kENET_FirstLastFlag;
2191 }
2192 else
2193 {
2194 descFlag = (leftBuffNum > 2U) ? kENET_MiddleFlag : kENET_LastFlagOnly;
2195 }
2196
2197 enet_tx_bd_config_struct_t txDescConfig = {0};
2198
2199 txDescConfig.framelen = frameLen;
2200 txDescConfig.intEnable = (bool)txFrame->txConfig.intEnable;
2201 txDescConfig.tsEnable = (bool)txFrame->txConfig.tsEnable;
2202 txDescConfig.txOffloadOps = txFrame->txConfig.txOffloadOps;
2203 txDescConfig.flag = descFlag;
2204 txDescConfig.slotNum = txFrame->txConfig.slotNum;
2205
2206 /* Fill the descriptor. */
2207 txDescConfig.buffer1 = txBuff[index].buffer;
2208 txDescConfig.bytes1 = txBuff[index].length;
2209 if (leftBuffNum < 2U)
2210 {
2211 txDescConfig.buffer2 = NULL;
2212 txDescConfig.bytes2 = 0;
2213 leftBuffNum--;
2214 }
2215 else
2216 {
2217 txDescConfig.buffer2 = txBuff[index + 1U].buffer;
2218 txDescConfig.bytes2 = txBuff[index + 1U].length;
2219 index += 2U;
2220 leftBuffNum -= 2U;
2221 }
2222 ENET_ConfigTxDescriptor(txDesc, &txDescConfig);
2223
2224 /* Increase the index. */
2225 txBdRing->txGenIdx = ENET_IncreaseIndex(txBdRing->txGenIdx, txBdRing->txRingLen);
2226
2227 /* Disable interrupt first and then enable interrupt to avoid the race condition. */
2228 (void)DisableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
2229 txBdRing->txDescUsed++;
2230 (void)EnableIRQ(s_enetIrqId[ENET_GetInstance(base)]);
2231 } while (leftBuffNum != 0U);
2232
2233 /* Update the transmit tail address. */
2234 txDesc = (txBdRing->txGenIdx == 0U) ? (&txBdRing->txBdBase[txBdRing->txRingLen]) :
2235 (&txBdRing->txBdBase[txBdRing->txGenIdx]);
2236 base->DMA_CH[channel].DMA_CHX_TXDESC_TAIL_PTR = (uint32_t)txDesc & ~ENET_ADDR_ALIGNMENT;
2237
2238 return kStatus_Success;
2239 }
2240
2241 #ifdef ENET_PTP1588FEATURE_REQUIRED
2242 /*!
2243 * brief Gets the current ENET time from the PTP 1588 timer.
2244 * Interrupts are not disabled.
2245 *
2246 * param base ENET peripheral base address.
2247 * param second The PTP 1588 system timer second.
2248 * param nanosecond The PTP 1588 system timer nanosecond.
2249 */
ENET_Ptp1588GetTimerNoIrqDisable(ENET_Type * base,uint64_t * second,uint32_t * nanosecond)2250 void ENET_Ptp1588GetTimerNoIrqDisable(ENET_Type *base, uint64_t *second, uint32_t *nanosecond)
2251 {
2252 assert(second);
2253 assert(nanosecond);
2254
2255 /* Get the current PTP time. */
2256 *second = (((uint64_t)base->MAC_SYS_TIME_HWORD_SCND & ENET_MAC_SYS_TIME_HWORD_SCND_TSHWR_MASK) << 32U) |
2257 base->MAC_SYS_TIME_SCND;
2258 *nanosecond = base->MAC_SYS_TIME_NSCND & ENET_MAC_SYS_TIME_NSCND_TSSS_MASK;
2259 if (!((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) != 0U))
2260 {
2261 /* Binary rollover, the unit of the increment is ~ 0.466 ns. */
2262 *nanosecond = ENET_BINARY_ROLLOVER_SCALE(*nanosecond);
2263 }
2264 }
2265
2266 /*!
2267 * brief Gets the current ENET time from the PTP 1588 timer.
2268 *
2269 * param base ENET peripheral base address.
2270 * param second The PTP 1588 system timer second.
2271 * param nanosecond The PTP 1588 system timer nanosecond.
2272 * For the unit of the nanosecond is 1ns. So the nanosecond is the real nanosecond.
2273 */
ENET_Ptp1588GetTimer(ENET_Type * base,uint64_t * second,uint32_t * nanosecond)2274 void ENET_Ptp1588GetTimer(ENET_Type *base, uint64_t *second, uint32_t *nanosecond)
2275 {
2276 assert(second);
2277 assert(nanosecond);
2278
2279 uint32_t primask;
2280
2281 /* Disables the interrupt. */
2282 primask = DisableGlobalIRQ();
2283
2284 ENET_Ptp1588GetTimerNoIrqDisable(base, second, nanosecond);
2285
2286 /* Enables the interrupt. */
2287 EnableGlobalIRQ(primask);
2288 }
2289
2290 /*!
2291 * brief Correct the ENET PTP 1588 timer in coarse method.
2292 *
2293 * param base ENET peripheral base address.
2294 * param operation The system time operation, refer to "enet_systime_op_t"
2295 * param second The correction second.
2296 * param nanosecond The correction nanosecond.
2297 */
ENET_Ptp1588CorrectTimerInCoarse(ENET_Type * base,enet_systime_op_t operation,uint32_t second,uint32_t nanosecond)2298 void ENET_Ptp1588CorrectTimerInCoarse(ENET_Type *base,
2299 enet_systime_op_t operation,
2300 uint32_t second,
2301 uint32_t nanosecond)
2302 {
2303 uint32_t corrSecond = second;
2304 uint32_t corrNanosecond;
2305
2306 /* Set the system timer. */
2307 if ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSCTRLSSR_MASK) != 0U)
2308 {
2309 if (operation == kENET_SystimeSubtract)
2310 {
2311 /* Set with the complement of the sub-second. */
2312 corrSecond = ENET_MAC_SYS_TIME_SCND_UPD_TSS_MASK - (second - 1U);
2313 corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_ADDSUB_MASK |
2314 ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(ENET_NANOSECS_ONESECOND - nanosecond);
2315 }
2316 else
2317 {
2318 corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(nanosecond);
2319 }
2320 }
2321 else
2322 {
2323 nanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS_MASK / ENET_NANOSECS_ONESECOND * nanosecond;
2324 if (operation == kENET_SystimeSubtract)
2325 {
2326 /* Set with the complement of the sub-second. */
2327 corrSecond = ENET_MAC_SYS_TIME_SCND_UPD_TSS_MASK - (second - 1U);
2328 corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_ADDSUB_MASK |
2329 ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(ENET_MAC_SYS_TIME_NSCND_UPD_TSSS_MASK + 1U - nanosecond);
2330 }
2331 else
2332 {
2333 corrNanosecond = ENET_MAC_SYS_TIME_NSCND_UPD_TSSS(nanosecond);
2334 }
2335 }
2336
2337 base->MAC_SYS_TIME_SCND_UPD = corrSecond;
2338 base->MAC_SYS_TIME_NSCND_UPD = corrNanosecond;
2339
2340 /* Update the timer. */
2341 base->MAC_TIMESTAMP_CTRL |= ENET_MAC_TIMESTAMP_CTRL_TSUPDT_MASK;
2342 while ((base->MAC_TIMESTAMP_CTRL & ENET_MAC_TIMESTAMP_CTRL_TSUPDT_MASK) != 0U)
2343 {
2344 }
2345 }
2346 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2347
2348 /*!
2349 * brief The ENET IRQ handler.
2350 *
2351 * param base ENET peripheral base address.
2352 * param handle The ENET handler pointer.
2353 */
ENET_IRQHandler(ENET_Type * base,enet_handle_t * handle)2354 void ENET_IRQHandler(ENET_Type *base, enet_handle_t *handle)
2355 {
2356 /* Check for the interrupt source type. */
2357 /* DMA CHANNEL 0. */
2358 if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_DC0IS_MASK) != 0U)
2359 {
2360 uint32_t flag = base->DMA_CH[0].DMA_CHX_STAT;
2361 if ((flag & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0U)
2362 {
2363 base->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2364 if (handle->callback != NULL)
2365 {
2366 handle->callback(base, handle, kENET_RxIntEvent, 0, NULL, handle->userData);
2367 }
2368 }
2369 if ((flag & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0U)
2370 {
2371 base->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2372 ENET_ReclaimTxDescriptor(base, handle, 0);
2373 }
2374 }
2375
2376 /* DMA CHANNEL 1. */
2377 if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_DC1IS_MASK) != 0U)
2378 {
2379 uint32_t flag = base->DMA_CH[1].DMA_CHX_STAT;
2380 if ((flag & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0U)
2381 {
2382 base->DMA_CH[1].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2383 if (handle->callback != NULL)
2384 {
2385 handle->callback(base, handle, kENET_RxIntEvent, 1, NULL, handle->userData);
2386 }
2387 }
2388 if ((flag & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0U)
2389 {
2390 base->DMA_CH[1].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK | ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
2391 ENET_ReclaimTxDescriptor(base, handle, 1);
2392 }
2393 }
2394
2395 #ifdef ENET_PTP1588FEATURE_REQUIRED
2396 /* MAC TIMESTAMP. */
2397 if ((base->DMA_INTR_STAT & ENET_DMA_INTR_STAT_MACIS_MASK) != 0U)
2398 {
2399 if ((base->MAC_INTR_STAT & ENET_MAC_INTR_STAT_TSIS_MASK) != 0U)
2400 {
2401 if (handle->callback != NULL)
2402 {
2403 handle->callback(base, handle, kENET_TimeStampIntEvent, 0, NULL, handle->userData);
2404 }
2405 }
2406 }
2407 #endif /* ENET_PTP1588FEATURE_REQUIRED */
2408 SDK_ISR_EXIT_BARRIER;
2409 }
2410
2411 void ETHERNET_DriverIRQHandler(void);
ETHERNET_DriverIRQHandler(void)2412 void ETHERNET_DriverIRQHandler(void)
2413 {
2414 s_enetIsr(ENET, s_ENETHandle[0]);
2415 SDK_ISR_EXIT_BARRIER;
2416 }
2417