1 /*
2 * Copyright 2019-2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "fsl_enet_qos.h"
8 /*******************************************************************************
9 * Definitions
10 ******************************************************************************/
11
12 /* Component ID definition, used by tools. */
13 #ifndef FSL_COMPONENT_ID
14 #define FSL_COMPONENT_ID "platform.drivers.enet_qos"
15 #endif
16
17 /*! @brief Defines 10^9 nanosecond. */
18 #define ENET_QOS_NANOSECS_ONESECOND (1000000000U)
19 /*! @brief Defines 10^6 microsecond.*/
20 #define ENET_QOS_MICRSECS_ONESECOND (1000000U)
21
22 /*! @brief Rx buffer LSB ignore bits. */
23 #define ENET_QOS_RXBUFF_IGNORELSB_BITS (3U)
24 /*! @brief ENET FIFO size unit. */
25 #define ENET_QOS_FIFOSIZE_UNIT (256U)
26 /*! @brief ENET half-dulpex default IPG. */
27 #define ENET_QOS_HALFDUPLEX_DEFAULTIPG (4U)
28 /*! @brief ENET miminum ring length. */
29 #define ENET_QOS_MIN_RINGLEN (4U)
30 /*! @brief ENET wakeup filter numbers. */
31 #define ENET_QOS_WAKEUPFILTER_NUM (8U)
32 /*! @brief Requried systime timer frequency. */
33 #define ENET_QOS_SYSTIME_REQUIRED_CLK_MHZ (50U)
34 /*! @brief Ethernet VLAN tag length. */
35 #define ENET_QOS_FRAME_VLAN_TAGLEN 4U
36
37 /*! @brief AVB TYPE */
38 #define ENET_QOS_AVBTYPE 0x22F0U
39 #define ENET_QOS_HEAD_TYPE_OFFSET (12)
40 #define ENET_QOS_HEAD_AVBTYPE_OFFSET (16)
41
42 /*! @brief Defines the macro for converting constants from host byte order to network byte order. */
43 #define ENET_QOS_HTONS(n) __REV16(n)
44 #define ENET_QOS_HTONL(n) __REV(n)
45 #define ENET_QOS_NTOHS(n) __REV16(n)
46 #define ENET_QOS_NTOHL(n) __REV(n)
47
48 #define ENET_QOS_DMA_CHX_RX_CTRL_RBSZ
49 /*******************************************************************************
50 * Prototypes
51 ******************************************************************************/
52
53 /*! @brief Mask the cache management code if cache control is disabled. */
54 #if !defined(FSL_ETH_ENABLE_CACHE_CONTROL)
55 #define ENET_QOS_DcacheInvalidateByRange(address, sizeByte)
56 #else
57 #define ENET_QOS_DcacheInvalidateByRange(address, sizeByte) DCACHE_InvalidateByRange(address, sizeByte)
58 #endif
59
60 /*!
61 * @brief Increase the index in the ring.
62 *
63 * @param index The current index.
64 * @param max The size.
65 * @return the increased index.
66 */
67 static uint16_t ENET_QOS_IncreaseIndex(uint16_t index, uint16_t max);
68
69 /*!
70 * @brief Poll status flag.
71 *
72 * @param regAddr The register address to read out status
73 * @param mask The mask to operate the register value.
74 * @param readyStatus Indicate readyStatus for the field
75 * @retval kStatus_Success Poll readyStatus Success.
76 * @retval kStatus_ENET_QOS_Timeout Poll readyStatus timeout.
77 */
78 static status_t ENET_QOS_PollStatusFlag(volatile uint32_t *regAddr, uint32_t mask, uint32_t readyStatus);
79
80 /*!
81 * @brief Set ENET DMA controller with the configuration.
82 *
83 * @param base ENET peripheral base address.
84 * @param config ENET Mac configuration.
85 * @retval kStatus_Success ENET DMA controller has been configured successfully.
86 * @retval kStatus_InvalidArgument Could not set the provided configuration.
87 */
88 static status_t ENET_QOS_SetDMAControl(ENET_QOS_Type *base, const enet_qos_config_t *config);
89
90 /*!
91 * @brief Set ENET MAC controller with the configuration.
92 *
93 * @param base ENET peripheral base address.
94 * @param config ENET Mac configuration.
95 * @param macAddr ENET six-byte mac address.
96 * @retval kStatus_Success ENET MAC controller has been configured successfully.
97 * @retval kStatus_InvalidArgument Could not set the provided configuration.
98 */
99 static status_t ENET_QOS_SetMacControl(ENET_QOS_Type *base,
100 const enet_qos_config_t *config,
101 uint8_t *macAddr,
102 uint8_t macCount);
103 /*!
104 * @brief Set ENET MTL with the configuration.
105 *
106 * @param base ENET peripheral base address.
107 * @param config ENET Mac configuration.
108 */
109 static void ENET_QOS_SetMTL(ENET_QOS_Type *base, const enet_qos_config_t *config);
110
111 /*!
112 * @brief Set ENET DMA transmit buffer descriptors for one channel.
113 *
114 * @param base ENET peripheral base address.
115 * @param bufferConfig ENET buffer configuration.
116 * @param intTxEnable tx interrupt enable.
117 * @param channel The channel number, 0 , 1.
118 */
119 static status_t ENET_QOS_TxDescriptorsInit(ENET_QOS_Type *base,
120 const enet_qos_buffer_config_t *bufferConfig,
121 bool intTxEnable,
122 uint8_t channel);
123
124 /*!
125 * @brief Set ENET DMA receive buffer descriptors for one channel.
126 *
127 * @param base ENET peripheral base address.
128 * @param bufferConfig ENET buffer configuration.
129 * @param intRxEnable tx interrupt enable.
130 * @param channel The channel number, 0, 1.
131 */
132 static status_t ENET_QOS_RxDescriptorsInit(ENET_QOS_Type *base,
133 enet_qos_config_t *config,
134 const enet_qos_buffer_config_t *bufferConfig,
135 bool intRxEnable,
136 uint8_t channel);
137
138 /*!
139 * @brief Sets the ENET 1588 feature.
140 *
141 * Enable the enhacement 1588 buffer descriptor mode and start
142 * the 1588 timer.
143 *
144 * @param base ENET peripheral base address.
145 * @param config The ENET configuration.
146 * @param refClk_Hz The reference clock for ptp 1588.
147 */
148 static status_t ENET_QOS_SetPtp1588(ENET_QOS_Type *base, const enet_qos_config_t *config, uint32_t refClk_Hz);
149
150 /*!
151 * @brief Store the receive time-stamp for event PTP frame in the time-stamp buffer ring.
152 *
153 * @param base ENET peripheral base address.
154 * @param handle ENET handler.
155 * @param rxDesc The ENET receive descriptor pointer.
156 * @param channel The rx channel.
157 * @param ts The timestamp structure pointer.
158 */
159 static void ENET_QOS_StoreRxFrameTime(ENET_QOS_Type *base,
160 enet_qos_handle_t *handle,
161 enet_qos_rx_bd_struct_t *rxDesc,
162 // uint8_t channel,
163 enet_qos_ptp_time_t *ts);
164
165 /*!
166 * @brief Check if txDirtyRing available.
167 *
168 * @param txDirtyRing pointer to txDirtyRing
169 * @retval txDirty available status.
170 */
171 static inline bool ENET_QOS_TxDirtyRingAvailable(enet_qos_tx_dirty_ring_t *txDirtyRing);
172
173 /*!
174 * @brief Check if the given MII configuration is valid and allowed.
175 *
176 * @param mode MII mode
177 * @param speed MII speed
178 * @retval true if configuration is valid, false otherwise
179 */
180 static inline bool ENET_QOS_IsMIIConfigValid(enet_qos_mii_mode_t mode, enet_qos_mii_speed_t speed);
181
182 /*******************************************************************************
183 * Variables
184 ******************************************************************************/
185 /*! @brief Pointers to enet bases for each instance. */
186 static ENET_QOS_Type *const s_enetqosBases[] = ENET_QOS_BASE_PTRS;
187
188 /*! @brief Pointers to enet IRQ number for each instance. */
189 static const IRQn_Type s_enetqosIrqId[] = ENET_QOS_IRQS;
190
191 /* ENET ISR for transactional APIs. */
192 static enet_qos_isr_t s_enetqosIsr;
193
194 /*! @brief Pointers to enet handles for each instance. */
195 static enet_qos_handle_t *s_ENETHandle[ARRAY_SIZE(s_enetqosBases)] = {NULL};
196
197 /*! @brief Arrays of enet state structures for each instance. */
198 static enet_qos_state_t s_enetStates[ARRAY_SIZE(s_enetqosBases)] = {{}};
199
200 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
201 /*! @brief Pointers to enet clocks for each instance. */
202 const clock_ip_name_t s_enetqosClock[ARRAY_SIZE(s_enetqosBases)] = ENETQOS_CLOCKS;
203 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
204
205 /*******************************************************************************
206 * Code
207 ******************************************************************************/
208
ENET_QOS_PollStatusFlag(volatile uint32_t * regAddr,uint32_t mask,uint32_t readyStatus)209 static status_t ENET_QOS_PollStatusFlag(volatile uint32_t *regAddr, uint32_t mask, uint32_t readyStatus)
210 {
211 uint8_t retryTimes = 10U;
212 status_t result = kStatus_Success;
213
214 while ((readyStatus != (*regAddr & mask)) && (0U != retryTimes))
215 {
216 retryTimes--;
217 SDK_DelayAtLeastUs(1U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
218 }
219
220 if (retryTimes == 0U)
221 {
222 result = kStatus_ENET_QOS_Timeout;
223 }
224
225 return result;
226 }
227
228 /*!
229 * brief Sets the ENET AVB feature.
230 *
231 * ENET_QOS AVB feature configuration, set transmit bandwidth.
232 * This API is called when the AVB feature is required.
233 *
234 * param base ENET_QOS peripheral base address.
235 * param config The ENET_QOS AVB feature configuration structure.
236 * param queueIndex ENET_QOS queue index.
237 */
ENET_QOS_AVBConfigure(ENET_QOS_Type * base,const enet_qos_cbs_config_t * config,uint8_t queueIndex)238 void ENET_QOS_AVBConfigure(ENET_QOS_Type *base, const enet_qos_cbs_config_t *config, uint8_t queueIndex)
239 {
240 assert(config != NULL);
241
242 /* Enable AV algorithm */
243 base->MTL_QUEUE[queueIndex].MTL_TXQX_ETS_CTRL |= ENET_QOS_MTL_TXQX_ETS_CTRL_AVALG_MASK;
244 /* Configure send slope */
245 base->MTL_QUEUE[queueIndex].MTL_TXQX_SNDSLP_CRDT = config->sendSlope;
246 /* Configure idle slope (same register as tx weight) */
247 base->MTL_QUEUE[queueIndex].MTL_TXQX_QNTM_WGHT = config->idleSlope;
248 /* Configure high credit */
249 base->MTL_QUEUE[queueIndex].MTL_TXQX_HI_CRDT = config->highCredit;
250 /* Configure high credit */
251 base->MTL_QUEUE[queueIndex].MTL_TXQX_LO_CRDT = config->lowCredit;
252 }
253
ENET_QOS_IncreaseIndex(uint16_t index,uint16_t max)254 static uint16_t ENET_QOS_IncreaseIndex(uint16_t index, uint16_t max)
255 {
256 /* Increase the index. */
257 index++;
258 if (index >= max)
259 {
260 index = 0;
261 }
262 return index;
263 }
264
ENET_QOS_ReverseBits(uint32_t value)265 static uint32_t ENET_QOS_ReverseBits(uint32_t value)
266 {
267 value = ((value & 0x55555555UL) << 1U) | ((value >> 1U) & 0x55555555UL);
268 value = ((value & 0x33333333UL) << 2U) | ((value >> 2U) & 0x33333333UL);
269 value = ((value & 0x0F0F0F0FUL) << 4U) | ((value >> 4U) & 0x0F0F0F0FUL);
270
271 return (value >> 24U) | ((value >> 8U) & 0xFF00UL) | ((value & 0xFF00UL) << 8U) | (value << 24U);
272 }
273
ENET_QOS_SetDMAControl(ENET_QOS_Type * base,const enet_qos_config_t * config)274 static status_t ENET_QOS_SetDMAControl(ENET_QOS_Type *base, const enet_qos_config_t *config)
275 {
276 assert(config != NULL);
277
278 uint8_t index;
279 uint32_t reg;
280 uint32_t burstLen;
281
282 if (!ENET_QOS_IsMIIConfigValid(config->miiMode, config->miiSpeed))
283 {
284 return kStatus_InvalidArgument;
285 }
286
287 if (kENET_QOS_RmiiMode == config->miiMode)
288 {
289 /* Disable enet qos clock first. */
290 ENET_QOS_EnableClock(false);
291 }
292 else
293 {
294 /* Enable enet qos clock. */
295 ENET_QOS_EnableClock(true);
296 }
297
298 /* Set MII mode*/
299 ENET_QOS_SetSYSControl(config->miiMode);
300 s_enetStates[ENET_QOS_GetInstance(base)].miiMode = config->miiMode;
301
302 /* Reset first, The reset bit will automatically be cleared after complete. */
303 base->DMA_MODE |= ENET_QOS_DMA_MODE_SWR_MASK;
304 for (uint32_t i = 0U; i < 100UL; i++)
305 {
306 __NOP();
307 }
308 if (kENET_QOS_RmiiMode == config->miiMode)
309 {
310 /* Configure mac */
311 reg = ENET_QOS_MAC_CONFIGURATION_DM(config->miiDuplex) | (uint32_t)config->miiSpeed |
312 ENET_QOS_MAC_CONFIGURATION_S2KP(
313 ((config->specialControl & (uint32_t)kENET_QOS_8023AS2KPacket) != 0U) ? 1U : 0U);
314 if (config->miiDuplex == kENET_QOS_MiiHalfDuplex)
315 {
316 reg |= ENET_QOS_MAC_CONFIGURATION_IPG(ENET_QOS_HALFDUPLEX_DEFAULTIPG);
317 }
318 base->MAC_CONFIGURATION = reg;
319 /* Enable enet qos clock. */
320 ENET_QOS_EnableClock(true);
321 for (uint32_t i = 0U; i < 100UL; i++)
322 {
323 __NOP();
324 }
325 }
326 /* Wait for the complete */
327 while ((base->DMA_MODE & ENET_QOS_DMA_MODE_SWR_MASK) != 0U)
328 {
329 }
330
331 /* Set the burst length. */
332 for (index = 0; index < ENET_QOS_RING_NUM_MAX; index++)
333 {
334 burstLen = (uint32_t)kENET_QOS_BurstLen1;
335 if (config->multiqueueCfg != NULL)
336 {
337 burstLen = (uint32_t)config->multiqueueCfg->burstLen;
338 }
339 base->DMA_CH[index].DMA_CHX_CTRL = burstLen & ENET_QOS_DMA_CHX_CTRL_PBLx8_MASK;
340
341 reg = base->DMA_CH[index].DMA_CHX_TX_CTRL & ~ENET_QOS_DMA_CHX_TX_CTRL_TxPBL_MASK;
342 base->DMA_CH[index].DMA_CHX_TX_CTRL = reg | ENET_QOS_DMA_CHX_TX_CTRL_TxPBL(burstLen & 0x3FU);
343
344 reg = base->DMA_CH[index].DMA_CHX_RX_CTRL & ~ENET_QOS_DMA_CHX_RX_CTRL_RxPBL_MASK;
345 base->DMA_CH[index].DMA_CHX_RX_CTRL = reg | ENET_QOS_DMA_CHX_RX_CTRL_RxPBL(burstLen & 0x3FU);
346 }
347
348 return kStatus_Success;
349 }
350
ENET_QOS_SetMTL(ENET_QOS_Type * base,const enet_qos_config_t * config)351 static void ENET_QOS_SetMTL(ENET_QOS_Type *base, const enet_qos_config_t *config)
352 {
353 assert(config != NULL);
354
355 uint32_t txqOpreg = 0;
356 uint32_t rxqOpReg = 0;
357 enet_qos_multiqueue_config_t *multiqCfg = config->multiqueueCfg;
358 uint8_t index;
359
360 /* Set transmit operation mode. */
361 if ((config->specialControl & (uint32_t)kENET_QOS_StoreAndForward) != 0U)
362 {
363 txqOpreg = ENET_QOS_MTL_TXQX_OP_MODE_TSF_MASK;
364 rxqOpReg = ENET_QOS_MTL_RXQX_OP_MODE_RSF_MASK;
365 }
366 /* Set transmit operation mode. */
367 txqOpreg |= ENET_QOS_MTL_TXQX_OP_MODE_FTQ_MASK;
368 /* Set receive operation mode. */
369 rxqOpReg |= ENET_QOS_MTL_RXQX_OP_MODE_FUP_MASK | ENET_QOS_MTL_RXQX_OP_MODE_RFD(3U) |
370 ENET_QOS_MTL_RXQX_OP_MODE_RFA(1U) | ENET_QOS_MTL_RXQX_OP_MODE_EHFC_MASK;
371
372 if (multiqCfg == NULL)
373 {
374 txqOpreg |=
375 ENET_QOS_MTL_TXQX_OP_MODE_TQS(((uint32_t)ENET_QOS_MTL_TXFIFOSIZE / (uint32_t)ENET_QOS_FIFOSIZE_UNIT - 1U));
376 rxqOpReg |=
377 ENET_QOS_MTL_RXQX_OP_MODE_RQS(((uint32_t)ENET_QOS_MTL_RXFIFOSIZE / (uint32_t)ENET_QOS_FIFOSIZE_UNIT - 1U));
378 base->MTL_QUEUE[0].MTL_TXQX_OP_MODE = txqOpreg | ENET_QOS_MTL_TXQX_OP_MODE_TXQEN((uint32_t)kENET_QOS_DCB_Mode);
379 base->MTL_QUEUE[0].MTL_RXQX_OP_MODE = rxqOpReg;
380 }
381 else
382 {
383 /* Set the schedule/arbitration(set for multiple queues). */
384 base->MTL_OPERATION_MODE = ENET_QOS_MTL_OPERATION_MODE_SCHALG(multiqCfg->mtltxSche) |
385 ENET_QOS_MTL_OPERATION_MODE_RAA(multiqCfg->mtlrxSche);
386
387 for (index = 0; index < multiqCfg->txQueueUse; index++)
388 {
389 txqOpreg |= ENET_QOS_MTL_TXQX_OP_MODE_TQS(
390 ((uint32_t)ENET_QOS_MTL_TXFIFOSIZE / ((uint32_t)multiqCfg->txQueueUse * ENET_QOS_FIFOSIZE_UNIT)) - 1U);
391 base->MTL_QUEUE[index].MTL_TXQX_OP_MODE =
392 txqOpreg | ENET_QOS_MTL_TXQX_OP_MODE_TXQEN((uint32_t)multiqCfg->txQueueConfig[index].mode);
393 if (multiqCfg->txQueueConfig[index].mode == kENET_QOS_AVB_Mode)
394 {
395 ENET_QOS_AVBConfigure(base, multiqCfg->txQueueConfig[index].cbsConfig, index);
396 }
397 else
398 {
399 base->MTL_QUEUE[index].MTL_TXQX_QNTM_WGHT = multiqCfg->txQueueConfig[index].weight;
400 }
401 }
402
403 volatile uint32_t *mtlrxQuemapReg;
404 uint8_t configIndex;
405 for (index = 0; index < multiqCfg->rxQueueUse; index++)
406 {
407 rxqOpReg |= ENET_QOS_MTL_RXQX_OP_MODE_RQS(
408 ((uint32_t)ENET_QOS_MTL_RXFIFOSIZE / ((uint32_t)multiqCfg->rxQueueUse * ENET_QOS_FIFOSIZE_UNIT)) - 1U);
409 base->MTL_QUEUE[index].MTL_RXQX_OP_MODE = rxqOpReg;
410 mtlrxQuemapReg = (index < 4U) ? &base->MTL_RXQ_DMA_MAP0 : &base->MTL_RXQ_DMA_MAP1;
411 configIndex = (index & 0x3U);
412 *mtlrxQuemapReg &= ~((uint32_t)ENET_QOS_MTL_RXQ_DMA_MAP0_Q0MDMACH_MASK << (8U * configIndex));
413 *mtlrxQuemapReg |= (uint32_t)ENET_QOS_MTL_RXQ_DMA_MAP0_Q0MDMACH(multiqCfg->rxQueueConfig[index].mapChannel)
414 << (8U * configIndex);
415 }
416 }
417 }
418
ENET_QOS_SetMacControl(ENET_QOS_Type * base,const enet_qos_config_t * config,uint8_t * macAddr,uint8_t macCount)419 static status_t ENET_QOS_SetMacControl(ENET_QOS_Type *base,
420 const enet_qos_config_t *config,
421 uint8_t *macAddr,
422 uint8_t macCount)
423 {
424 assert(config != NULL);
425
426 uint32_t reg = 0;
427
428 if (!ENET_QOS_IsMIIConfigValid(config->miiMode, config->miiSpeed))
429 {
430 return kStatus_InvalidArgument;
431 }
432
433 /* Set Macaddr */
434 /* The dma channel 0 is set as to which the rx packet
435 * whose DA matches the MAC address content is routed. */
436 if (macAddr != NULL)
437 {
438 for (uint8_t i = 0; i < macCount; i++)
439 {
440 ENET_QOS_SetMacAddr(base, macAddr, i);
441 }
442 }
443
444 /* Set the receive filter. */
445 reg =
446 ENET_QOS_MAC_PACKET_FILTER_PR(((config->specialControl & (uint32_t)kENET_QOS_PromiscuousEnable) != 0U) ? 1U :
447 0U) |
448 ENET_QOS_MAC_PACKET_FILTER_DBF(((config->specialControl & (uint32_t)kENET_QOS_BroadCastRxDisable) != 0U) ? 1U :
449 0U) |
450 ENET_QOS_MAC_PACKET_FILTER_PM(((config->specialControl & (uint32_t)kENET_QOS_MulticastAllEnable) != 0U) ? 1U :
451 0U) |
452 ENET_QOS_MAC_PACKET_FILTER_HMC(((config->specialControl & (uint32_t)kENET_QOS_HashMulticastEnable) != 0U) ? 1U :
453 0U);
454 base->MAC_PACKET_FILTER = reg;
455 /* Flow control. */
456 if ((config->specialControl & (uint32_t)kENET_QOS_FlowControlEnable) != 0U)
457 {
458 base->MAC_RX_FLOW_CTRL = ENET_QOS_MAC_RX_FLOW_CTRL_RFE_MASK | ENET_QOS_MAC_RX_FLOW_CTRL_UP_MASK;
459 base->MAC_TX_FLOW_CTRL_Q[0] = ENET_QOS_MAC_TX_FLOW_CTRL_Q_PT(config->pauseDuration);
460 }
461
462 /* Set the 1us ticket. */
463 reg = config->csrClock_Hz / ENET_QOS_MICRSECS_ONESECOND - 1U;
464 base->MAC_ONEUS_TIC_COUNTER = ENET_QOS_MAC_ONEUS_TIC_COUNTER_TIC_1US_CNTR(reg);
465
466 /* Set the speed and duplex. */
467 reg = ENET_QOS_MAC_CONFIGURATION_DM(config->miiDuplex) | (uint32_t)config->miiSpeed |
468 ENET_QOS_MAC_CONFIGURATION_S2KP(((config->specialControl & (uint32_t)kENET_QOS_8023AS2KPacket) != 0U) ? 1U :
469 0U) |
470 ENET_QOS_MAC_CONFIGURATION_IPC(
471 ((config->specialControl & (uint32_t)kENET_QOS_RxChecksumOffloadEnable) != 0U) ? 1U : 0U);
472 if (config->miiDuplex == kENET_QOS_MiiHalfDuplex)
473 {
474 reg |= ENET_QOS_MAC_CONFIGURATION_IPG(ENET_QOS_HALFDUPLEX_DEFAULTIPG);
475 }
476 base->MAC_CONFIGURATION = reg;
477
478 if (config->multiqueueCfg != NULL)
479 {
480 reg = 0U;
481 uint8_t configIndex;
482 enet_qos_multiqueue_config_t *multiqCfg = config->multiqueueCfg;
483 uint32_t txQueuePrioMap0 = base->MAC_TXQ_PRTY_MAP0;
484 uint32_t txQueuePrioMap1 = base->MAC_TXQ_PRTY_MAP1;
485 uint32_t rxQueuePrioMap0 = base->MAC_RXQ_CTRL[2];
486 uint32_t rxQueuePrioMap1 = base->MAC_RXQ_CTRL[3];
487 uint32_t rxCtrlReg1 = base->MAC_RXQ_CTRL[1];
488
489 for (uint8_t index = 0U; index < multiqCfg->txQueueUse; index++)
490 {
491 configIndex = index & 0x3U;
492
493 /* Configure tx queue priority. */
494 if (index < 4U)
495 {
496 txQueuePrioMap0 &= ~((uint32_t)ENET_QOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK << (8U * configIndex));
497 txQueuePrioMap0 |= (uint32_t)ENET_QOS_MAC_TXQ_PRTY_MAP0_PSTQ0(multiqCfg->txQueueConfig[index].priority)
498 << (8U * configIndex);
499 }
500 else
501 {
502 txQueuePrioMap1 &= ~((uint32_t)ENET_QOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK << (8U * configIndex));
503 txQueuePrioMap1 |= (uint32_t)ENET_QOS_MAC_TXQ_PRTY_MAP0_PSTQ0(multiqCfg->txQueueConfig[index].priority)
504 << (8U * configIndex);
505 }
506 }
507
508 for (uint8_t index = 0U; index < multiqCfg->rxQueueUse; index++)
509 {
510 configIndex = index & 0x3U;
511
512 /* Configure rx queue priority. */
513 if (index < 4U)
514 {
515 rxQueuePrioMap0 &= ~((uint32_t)ENET_QOS_MAC_RXQ_CTRL_PSRQ0_MASK << (8U * configIndex));
516 rxQueuePrioMap0 |= (uint32_t)ENET_QOS_MAC_RXQ_CTRL_PSRQ0(multiqCfg->rxQueueConfig[index].priority)
517 << (8U * configIndex);
518 }
519 else
520 {
521 rxQueuePrioMap1 &= ~((uint32_t)ENET_QOS_MAC_RXQ_CTRL_PSRQ0_MASK << (8U * configIndex));
522 rxQueuePrioMap1 |= (uint32_t)ENET_QOS_MAC_RXQ_CTRL_PSRQ0(multiqCfg->rxQueueConfig[index].priority)
523 << (8U * configIndex);
524 }
525
526 /* Configure queue enable mode. */
527 reg |= ENET_QOS_MAC_RXQ_CTRL_RXQ0EN((uint32_t)multiqCfg->rxQueueConfig[index].mode) << (2U * index);
528
529 /* Configure rx queue routing */
530 if (((uint8_t)multiqCfg->rxQueueConfig[index].packetRoute & (uint8_t)kENET_QOS_PacketAVCPQ) != 0U)
531 {
532 rxCtrlReg1 &= ~ENET_QOS_MAC_RXQ_CTRL_AVCPQ_MASK;
533 rxCtrlReg1 |= (ENET_QOS_MAC_RXQ_CTRL_AVCPQ(index) | ENET_QOS_MAC_RXQ_CTRL_TACPQE_MASK);
534 }
535
536 if (((uint8_t)multiqCfg->rxQueueConfig[index].packetRoute & (uint8_t)kENET_QOS_PacketPTPQ) != 0U)
537 {
538 rxCtrlReg1 &= ~ENET_QOS_MAC_RXQ_CTRL_PTPQ_MASK;
539 rxCtrlReg1 |= ENET_QOS_MAC_RXQ_CTRL_PTPQ(index);
540 }
541
542 if (((uint8_t)multiqCfg->rxQueueConfig[index].packetRoute & (uint8_t)kENET_QOS_PacketDCBCPQ) != 0U)
543 {
544 rxCtrlReg1 &= ~ENET_QOS_MAC_RXQ_CTRL_DCBCPQ_MASK;
545 rxCtrlReg1 |= ENET_QOS_MAC_RXQ_CTRL_DCBCPQ(index);
546 }
547
548 if (((uint8_t)multiqCfg->rxQueueConfig[index].packetRoute & (uint8_t)kENET_QOS_PacketUPQ) != 0U)
549 {
550 rxCtrlReg1 &= ~ENET_QOS_MAC_RXQ_CTRL_UPQ_MASK;
551 rxCtrlReg1 |= ENET_QOS_MAC_RXQ_CTRL_UPQ(index);
552 }
553
554 if (((uint8_t)multiqCfg->rxQueueConfig[index].packetRoute & (uint8_t)kENET_QOS_PacketMCBCQ) != 0U)
555 {
556 rxCtrlReg1 &= ~ENET_QOS_MAC_RXQ_CTRL_MCBCQ_MASK;
557 rxCtrlReg1 |= (ENET_QOS_MAC_RXQ_CTRL_MCBCQ(index) | ENET_QOS_MAC_RXQ_CTRL_MCBCQEN_MASK);
558 }
559 }
560
561 base->MAC_TXQ_PRTY_MAP0 = txQueuePrioMap0;
562 base->MAC_TXQ_PRTY_MAP1 = txQueuePrioMap1;
563 base->MAC_RXQ_CTRL[2] = rxQueuePrioMap0;
564 base->MAC_RXQ_CTRL[3] = rxQueuePrioMap1;
565 base->MAC_RXQ_CTRL[1] = rxCtrlReg1;
566 }
567 else
568 {
569 /* Configure queue enable mode. */
570 reg = ENET_QOS_MAC_RXQ_CTRL_RXQ0EN((uint32_t)kENET_QOS_DCB_Mode);
571 }
572
573 /* Enable queue. */
574 base->MAC_RXQ_CTRL[0] = reg;
575
576 /* Mask MMC counters interrupts as we don't handle
577 * them in the interrupt handler.
578 */
579 base->MAC_MMC_RX_INTERRUPT_MASK = 0xFFFFFFFFU;
580 base->MAC_MMC_TX_INTERRUPT_MASK = 0xFFFFFFFFU;
581 base->MAC_MMC_IPC_RX_INTERRUPT_MASK = 0xFFFFFFFFU;
582 base->MAC_MMC_FPE_RX_INTERRUPT_MASK = 0xFFFFFFFFU;
583 base->MAC_MMC_FPE_TX_INTERRUPT_MASK = 0xFFFFFFFFU;
584
585 return kStatus_Success;
586 }
587
ENET_QOS_TxDescriptorsInit(ENET_QOS_Type * base,const enet_qos_buffer_config_t * bufferConfig,bool intTxEnable,uint8_t channel)588 static status_t ENET_QOS_TxDescriptorsInit(ENET_QOS_Type *base,
589 const enet_qos_buffer_config_t *bufferConfig,
590 bool intTxEnable,
591 uint8_t channel)
592 {
593 uint16_t j;
594 enet_qos_tx_bd_struct_t *txbdPtr;
595 uint32_t control = intTxEnable ? ENET_QOS_TXDESCRIP_RD_IOC_MASK : 0U;
596 const enet_qos_buffer_config_t *buffCfg = bufferConfig;
597 uint32_t txDescAddr, txDescTail;
598
599 if (buffCfg == NULL)
600 {
601 return kStatus_InvalidArgument;
602 }
603
604 /* Check the ring length. */
605 if (buffCfg->txRingLen < ENET_QOS_MIN_RINGLEN)
606 {
607 return kStatus_InvalidArgument;
608 }
609 /* Set the tx descriptor start/tail pointer, shall be word aligned. */
610 txDescAddr = (uint32_t)(uintptr_t)buffCfg->txDescStartAddrAlign & ENET_QOS_DMA_CHX_TXDESC_LIST_ADDR_TDESLA_MASK;
611 txDescTail = (uint32_t)(uintptr_t)buffCfg->txDescTailAddrAlign & ENET_QOS_DMA_CHX_TXDESC_TAIL_PTR_TDTP_MASK;
612 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
613 txDescAddr = MEMORY_ConvertMemoryMapAddress(txDescAddr, kMEMORY_Local2DMA);
614 txDescTail = MEMORY_ConvertMemoryMapAddress(txDescTail, kMEMORY_Local2DMA);
615 #endif
616 base->DMA_CH[channel].DMA_CHX_TXDESC_LIST_ADDR = txDescAddr;
617 base->DMA_CH[channel].DMA_CHX_TXDESC_TAIL_PTR = txDescTail;
618 /* Set the tx ring length. */
619 base->DMA_CH[channel].DMA_CHX_TXDESC_RING_LENGTH =
620 ((uint32_t)buffCfg->txRingLen - 1U) & ENET_QOS_DMA_CHX_TXDESC_RING_LENGTH_TDRL_MASK;
621
622 /* Init the txbdPtr to the transmit descriptor start address. */
623 txbdPtr = (enet_qos_tx_bd_struct_t *)(buffCfg->txDescStartAddrAlign);
624 for (j = 0; j < buffCfg->txRingLen; j++)
625 {
626 txbdPtr->buff1Addr = 0;
627 txbdPtr->buff2Addr = 0;
628 txbdPtr->buffLen = control;
629 txbdPtr->controlStat = 0;
630 txbdPtr++;
631 }
632
633 return kStatus_Success;
634 }
635
ENET_QOS_RxDescriptorsInit(ENET_QOS_Type * base,enet_qos_config_t * config,const enet_qos_buffer_config_t * bufferConfig,bool intRxEnable,uint8_t channel)636 static status_t ENET_QOS_RxDescriptorsInit(ENET_QOS_Type *base,
637 enet_qos_config_t *config,
638 const enet_qos_buffer_config_t *bufferConfig,
639 bool intRxEnable,
640 uint8_t channel)
641 {
642 uint16_t j;
643 uint32_t reg;
644 enet_qos_rx_bd_struct_t *rxbdPtr;
645 uint16_t index;
646 bool doubleBuffEnable = ((config->specialControl & (uint32_t)kENET_QOS_DescDoubleBuffer) != 0U) ? true : false;
647 const enet_qos_buffer_config_t *buffCfg = bufferConfig;
648 uint32_t control = ENET_QOS_RXDESCRIP_RD_BUFF1VALID_MASK;
649 uint32_t rxDescAddr, rxDescTail;
650
651 if (buffCfg == NULL)
652 {
653 return kStatus_InvalidArgument;
654 }
655
656 if (intRxEnable)
657 {
658 control |= ENET_QOS_RXDESCRIP_RD_IOC_MASK;
659 }
660
661 if (doubleBuffEnable)
662 {
663 control |= ENET_QOS_RXDESCRIP_RD_BUFF2VALID_MASK;
664 }
665
666 /* Not give ownership to DMA before Rx buffer is ready */
667 if ((config->rxBuffAlloc == NULL) || (config->rxBuffFree == NULL))
668 {
669 control |= ENET_QOS_RXDESCRIP_WR_OWN_MASK;
670 }
671
672 /* Check the ring length. */
673 if (buffCfg->rxRingLen < ENET_QOS_MIN_RINGLEN)
674 {
675 return kStatus_InvalidArgument;
676 }
677
678 /* Set the rx descriptor start/tail pointer, shall be word aligned. */
679 rxDescAddr = (uint32_t)(uintptr_t)buffCfg->rxDescStartAddrAlign & ENET_QOS_DMA_CHX_RXDESC_LIST_ADDR_RDESLA_MASK;
680 rxDescTail = (uint32_t)(uintptr_t)buffCfg->rxDescTailAddrAlign & ENET_QOS_DMA_CHX_RXDESC_TAIL_PTR_RDTP_MASK;
681 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
682 rxDescAddr = MEMORY_ConvertMemoryMapAddress(rxDescAddr, kMEMORY_Local2DMA);
683 rxDescTail = MEMORY_ConvertMemoryMapAddress(rxDescTail, kMEMORY_Local2DMA);
684 #endif
685 base->DMA_CH[channel].DMA_CHX_RXDESC_LIST_ADDR = rxDescAddr;
686 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = rxDescTail;
687 /* Register DMA_CHX_RXDESC_RING_LENGTH renamed to DMA_CHX_RX_CONTROL2 */
688 #if defined(ENET_QOS_DMA_CHX_RX_CONTROL2_COUNT) && ENET_QOS_DMA_CHX_RX_CONTROL2_COUNT
689 base->DMA_CH[channel].DMA_CHX_RX_CONTROL2 =
690 ((uint32_t)buffCfg->rxRingLen - 1U) & ENET_QOS_DMA_CHX_RX_CONTROL2_RDRL_MASK;
691 #else
692 base->DMA_CH[channel].DMA_CHX_RXDESC_RING_LENGTH =
693 ((uint32_t)buffCfg->rxRingLen - 1U) & ENET_QOS_DMA_CHX_RXDESC_RING_LENGTH_RDRL_MASK;
694 #endif
695 reg = base->DMA_CH[channel].DMA_CHX_RX_CTRL & ~ENET_QOS_DMA_CHX_RX_CTRL_RBSZ_13_y_MASK;
696 reg |= ENET_QOS_DMA_CHX_RX_CTRL_RBSZ_13_y(buffCfg->rxBuffSizeAlign >> ENET_QOS_RXBUFF_IGNORELSB_BITS);
697 base->DMA_CH[channel].DMA_CHX_RX_CTRL = reg;
698
699 /* Init the rxbdPtr to the receive descriptor start address. */
700 rxbdPtr = (enet_qos_rx_bd_struct_t *)(buffCfg->rxDescStartAddrAlign);
701 for (j = 0U; j < buffCfg->rxRingLen; j++)
702 {
703 if ((config->rxBuffAlloc == NULL) || (config->rxBuffFree == NULL))
704 {
705 if (doubleBuffEnable)
706 {
707 index = 2U * j;
708 }
709 else
710 {
711 index = j;
712 }
713
714 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
715 buffCfg->rxBufferStartAddr[index] =
716 MEMORY_ConvertMemoryMapAddress((uintptr_t)buffCfg->rxBufferStartAddr[index], kMEMORY_Local2DMA);
717 #endif
718 rxbdPtr->buff1Addr = buffCfg->rxBufferStartAddr[index];
719
720 /* The second buffer is set with 0 because it is not required for normal case. */
721 if (doubleBuffEnable)
722 {
723 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
724 buffCfg->rxBufferStartAddr[index + 1U] = MEMORY_ConvertMemoryMapAddress(
725 (uintptr_t)buffCfg->rxBufferStartAddr[index + 1U], kMEMORY_Local2DMA);
726 #endif
727 rxbdPtr->buff2Addr = buffCfg->rxBufferStartAddr[index + 1U];
728 }
729 else
730 {
731 rxbdPtr->buff2Addr = 0;
732 }
733 }
734
735 /* Set the valid and DMA own flag.*/
736 rxbdPtr->control = control;
737 rxbdPtr++;
738 }
739
740 return kStatus_Success;
741 }
742
ENET_QOS_SetPtp1588(ENET_QOS_Type * base,const enet_qos_config_t * config,uint32_t refClk_Hz)743 static status_t ENET_QOS_SetPtp1588(ENET_QOS_Type *base, const enet_qos_config_t *config, uint32_t refClk_Hz)
744 {
745 assert(config != NULL);
746 assert(config->ptpConfig != NULL);
747 assert(refClk_Hz != 0U);
748
749 uint32_t control = 0U;
750 status_t result = kStatus_Success;
751 enet_qos_ptp_config_t *ptpConfig = config->ptpConfig;
752 uint32_t ptpClk_Hz = refClk_Hz;
753 uint32_t ssInc, snsSinc;
754
755 /* Clear the timestamp interrupt first. */
756 base->MAC_INTERRUPT_ENABLE &= ~ENET_QOS_MAC_INTERRUPT_ENABLE_TSIE_MASK;
757
758 if (ptpConfig->fineUpdateEnable)
759 {
760 control |= ENET_QOS_MAC_TIMESTAMP_CONTROL_TSCFUPDT_MASK;
761 ptpClk_Hz = ptpConfig->systemTimeClock_Hz; /* PTP clock 50MHz. */
762 }
763
764 /* Enable the IEEE 1588 timestamping and snapshot for event message. */
765 control |= ENET_QOS_MAC_TIMESTAMP_CONTROL_TSENA_MASK | ENET_QOS_MAC_TIMESTAMP_CONTROL_TSIPV4ENA_MASK |
766 ENET_QOS_MAC_TIMESTAMP_CONTROL_TSIPV6ENA_MASK | ENET_QOS_MAC_TIMESTAMP_CONTROL_TSENALL_MASK |
767 ENET_QOS_MAC_TIMESTAMP_CONTROL_TSEVNTENA_MASK | ENET_QOS_MAC_TIMESTAMP_CONTROL_SNAPTYPSEL_MASK |
768 ENET_QOS_MAC_TIMESTAMP_CONTROL_TSCTRLSSR(ptpConfig->tsRollover);
769
770 if (ptpConfig->ptp1588V2Enable)
771 {
772 control |= ENET_QOS_MAC_TIMESTAMP_CONTROL_TSVER2ENA_MASK | ENET_QOS_MAC_TIMESTAMP_CONTROL_TSIPENA_MASK;
773 }
774
775 /* Initialize the sub-second increment register. */
776 if (ptpConfig->tsRollover == kENET_QOS_DigitalRollover)
777 {
778 ssInc = (uint32_t)(((uint64_t)ENET_QOS_NANOSECS_ONESECOND << 8U) / ptpClk_Hz);
779 }
780 else
781 {
782 ssInc = (uint32_t)((((uint64_t)ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_TSSS_MASK + 1U) << 8U) / ptpClk_Hz);
783 }
784
785 snsSinc = ssInc & 0xFFU;
786 ssInc = (ssInc >> 8U) & 0xFFU;
787
788 base->MAC_TIMESTAMP_CONTROL = control;
789
790 /* Initialize the system timer. */
791 base->MAC_SYSTEM_TIME_NANOSECONDS_UPDATE = 0;
792
793 /* Set the second.*/
794 base->MAC_SYSTEM_TIME_SECONDS_UPDATE = 0;
795 base->MAC_SYSTEM_TIME_HIGHER_WORD_SECONDS = 0;
796
797 /* Initialize the system timer. */
798 base->MAC_TIMESTAMP_CONTROL |= ENET_QOS_MAC_TIMESTAMP_CONTROL_TSINIT_MASK;
799
800 while ((base->MAC_TIMESTAMP_CONTROL & ENET_QOS_MAC_TIMESTAMP_CONTROL_TSINIT_MASK) != 0U)
801 {
802 }
803
804 base->MAC_SUB_SECOND_INCREMENT =
805 ENET_QOS_MAC_SUB_SECOND_INCREMENT_SSINC(ssInc) | ENET_QOS_MAC_SUB_SECOND_INCREMENT_SNSINC(snsSinc);
806
807 /* Set the initial added value for the fine update. */
808 if (ptpConfig->fineUpdateEnable)
809 {
810 result = ENET_QOS_Ptp1588CorrectTimerInFine(base, ptpConfig->defaultAddend);
811 }
812
813 return result;
814 }
815
ENET_QOS_TxDirtyRingAvailable(enet_qos_tx_dirty_ring_t * txDirtyRing)816 static inline bool ENET_QOS_TxDirtyRingAvailable(enet_qos_tx_dirty_ring_t *txDirtyRing)
817 {
818 return !txDirtyRing->isFull;
819 }
820
ENET_QOS_StoreRxFrameTime(ENET_QOS_Type * base,enet_qos_handle_t * handle,enet_qos_rx_bd_struct_t * rxDesc,enet_qos_ptp_time_t * ts)821 static void ENET_QOS_StoreRxFrameTime(ENET_QOS_Type *base,
822 enet_qos_handle_t *handle,
823 enet_qos_rx_bd_struct_t *rxDesc,
824 enet_qos_ptp_time_t *ts)
825 {
826 assert(ts != NULL);
827
828 uint32_t nanosecond;
829
830 /* Get transmit time stamp second. */
831 nanosecond = rxDesc->buff1Addr;
832 if ((base->MAC_TIMESTAMP_CONTROL & ENET_QOS_MAC_TIMESTAMP_CONTROL_TSCTRLSSR_MASK) == 0U)
833 {
834 /* Binary rollover, 0.465ns accuracy. */
835 nanosecond = (uint32_t)(((uint64_t)nanosecond * 465U) / 1000U);
836 }
837 ts->second = rxDesc->reserved;
838 ts->nanosecond = nanosecond;
839 }
840
ENET_QOS_IsMIIConfigValid(enet_qos_mii_mode_t mode,enet_qos_mii_speed_t speed)841 static inline bool ENET_QOS_IsMIIConfigValid(enet_qos_mii_mode_t mode, enet_qos_mii_speed_t speed)
842 {
843 /* Errata ERR050539: ENET_QOS does not support RMII 10Mbps mode */
844 #if defined(MIMXRT1171_SERIES) || defined(MIMXRT1172_SERIES) || defined(MIMXRT1173_cm7_SERIES) || \
845 defined(MIMXRT1173_cm4_SERIES) || defined(MIMXRT1175_cm7_SERIES) || defined(MIMXRT1175_cm4_SERIES) || \
846 defined(MIMXRT1176_cm7_SERIES) || defined(MIMXRT1176_cm4_SERIES)
847 if ((kENET_QOS_RmiiMode == mode) && (kENET_QOS_MiiSpeed10M == speed))
848 {
849 return false;
850 }
851 #endif /* MIMXRT117x_SERIES */
852
853 return true;
854 }
855
ENET_QOS_GetInstance(ENET_QOS_Type * base)856 uint32_t ENET_QOS_GetInstance(ENET_QOS_Type *base)
857 {
858 uint32_t instance;
859
860 /* Find the instance index from base address mappings. */
861 for (instance = 0; instance < ARRAY_SIZE(s_enetqosBases); instance++)
862 {
863 if (s_enetqosBases[instance] == base)
864 {
865 break;
866 }
867 }
868
869 assert(instance < ARRAY_SIZE(s_enetqosBases));
870
871 return instance;
872 }
873
874 /*!
875 * brief Gets the ENET default configuration structure.
876 *
877 * The purpose of this API is to get the default ENET configure
878 * structure for ENET_QOS_Init(). User may use the initialized
879 * structure unchanged in ENET_QOS_Init(), or modify some fields of the
880 * structure before calling ENET_QOS_Init().
881 * Example:
882 code
883 enet_qos_config_t config;
884 ENET_QOS_GetDefaultConfig(&config);
885 endcode
886 * param config The ENET mac controller configuration structure pointer.
887 */
ENET_QOS_GetDefaultConfig(enet_qos_config_t * config)888 void ENET_QOS_GetDefaultConfig(enet_qos_config_t *config)
889 {
890 /* Checks input parameter. */
891 assert(config != NULL);
892
893 /* Initializes the configure structure to zero. */
894 (void)memset(config, 0, sizeof(*config));
895
896 /* Sets RGMII mode, full duplex, 1000Mbps for MAC and PHY data interface. */
897 config->miiMode = kENET_QOS_RgmiiMode;
898 config->miiSpeed = kENET_QOS_MiiSpeed1000M;
899 config->miiDuplex = kENET_QOS_MiiFullDuplex;
900
901 /* Sets default configuration for other options. */
902 config->specialControl = 0;
903 config->multiqueueCfg = NULL;
904 config->pauseDuration = 0;
905
906 config->ptpConfig = NULL;
907 }
908
909 /*!
910 * brief Initializes the ENET module.
911 *
912 * This function set up the with ENET basic configuration.
913 *
914 * param base ENET peripheral base address.
915 * param config ENET mac configuration structure pointer.
916 * The "enet_qos_config_t" type mac configuration return from ENET_QOS_GetDefaultConfig
917 * can be used directly. It is also possible to verify the Mac configuration using other methods.
918 * param macAddr ENET mac address of Ethernet device. This MAC address should be
919 * provided.
920 * param refclkSrc_Hz ENET input reference clock.
921 */
ENET_QOS_Up(ENET_QOS_Type * base,const enet_qos_config_t * config,uint8_t * macAddr,uint8_t macCount,uint32_t refclkSrc_Hz)922 status_t ENET_QOS_Up(
923 ENET_QOS_Type *base, const enet_qos_config_t *config, uint8_t *macAddr, uint8_t macCount, uint32_t refclkSrc_Hz)
924 {
925 assert(config != NULL);
926 status_t result;
927
928 /* Initializes the ENET MDIO. */
929 ENET_QOS_SetSMI(base, refclkSrc_Hz);
930
931 /* Initializes the ENET MTL with basic function. */
932 ENET_QOS_SetMTL(base, config);
933
934 /* Initializes the ENET MAC with basic function. */
935 result = ENET_QOS_SetMacControl(base, config, macAddr, macCount);
936
937 return result;
938 }
939
940 /*!
941 * brief Initializes the ENET module.
942 *
943 * This function ungates the module clock and initializes it with the ENET basic
944 * configuration.
945 *
946 * param base ENET peripheral base address.
947 * param config ENET mac configuration structure pointer.
948 * The "enet_qos_config_t" type mac configuration return from ENET_QOS_GetDefaultConfig
949 * can be used directly. It is also possible to verify the Mac configuration using other methods.
950 * param macAddr ENET mac address of Ethernet device. This MAC address should be
951 * provided.
952 * param refclkSrc_Hz ENET input reference clock.
953 */
ENET_QOS_Init(ENET_QOS_Type * base,const enet_qos_config_t * config,uint8_t * macAddr,uint8_t macCount,uint32_t refclkSrc_Hz)954 status_t ENET_QOS_Init(
955 ENET_QOS_Type *base, const enet_qos_config_t *config, uint8_t *macAddr, uint8_t macCount, uint32_t refclkSrc_Hz)
956 {
957 assert(config != NULL);
958
959 status_t result = kStatus_Success;
960 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
961 uint32_t instance = ENET_QOS_GetInstance(base);
962
963 /* Ungate ENET clock. */
964 (void)CLOCK_EnableClock(s_enetqosClock[instance]);
965 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
966
967 /* Initializes the ENET DMA with basic function. */
968 result = ENET_QOS_SetDMAControl(base, config);
969 if (result != kStatus_Success)
970 {
971 return result;
972 }
973
974 result = ENET_QOS_Up(base, config, macAddr, macCount, refclkSrc_Hz);
975 if (result != kStatus_Success)
976 {
977 return result;
978 }
979
980 if (config->ptpConfig != NULL)
981 {
982 result = ENET_QOS_SetPtp1588(base, config, refclkSrc_Hz);
983 }
984
985 return result;
986 }
987
988 /*!
989 * brief Stops the ENET module.
990
991 * This function disables the ENET module.
992 *
993 * param base ENET peripheral base address.
994 */
ENET_QOS_Down(ENET_QOS_Type * base)995 void ENET_QOS_Down(ENET_QOS_Type *base)
996 {
997 enet_qos_handle_t *handle = s_ENETHandle[ENET_QOS_GetInstance(base)];
998 enet_qos_tx_bd_struct_t *txbdPtr;
999 uint8_t index;
1000 uint32_t primask, j;
1001 uint32_t txDescAddr;
1002
1003 /* Disable all interrupts */
1004 ENET_QOS_DisableInterrupts(base, 0xFF);
1005
1006 for (index = 0; index < handle->txQueueUse; index++)
1007 {
1008 enet_qos_tx_bd_ring_t *txBdRing = &handle->txBdRing[index];
1009 enet_qos_tx_dirty_ring_t *txDirtyRing = (enet_qos_tx_dirty_ring_t *)&handle->txDirtyRing[index];
1010
1011 /* Clear pending descriptors */
1012 if (handle->callback != NULL)
1013 {
1014 while (txBdRing->txDescUsed > 0U)
1015 {
1016 enet_qos_frame_info_t *txDirty = &txDirtyRing->txDirtyBase[txDirtyRing->txConsumIdx];
1017
1018 txDirty->isTsAvail = false;
1019
1020 handle->callback(base, handle, kENET_QOS_TxIntEvent, index, handle->userData);
1021
1022 primask = DisableGlobalIRQ();
1023 txBdRing->txDescUsed--;
1024 EnableGlobalIRQ(primask);
1025 }
1026 }
1027
1028 /* Disable Tx DMA */
1029 base->DMA_CH[index].DMA_CHX_TX_CTRL &= ~ENET_QOS_DMA_CHX_TX_CTRL_ST_MASK;
1030
1031 /* Flush Tx Queue */
1032 base->MTL_QUEUE[index].MTL_TXQX_OP_MODE |= ENET_QOS_MTL_TXQX_OP_MODE_FTQ_MASK;
1033
1034 /* Wait until Tx Queue is empty */
1035 while ((base->MTL_QUEUE[index].MTL_TXQX_DBG &
1036 (ENET_QOS_MTL_TXQX_DBG_TXQSTS_MASK | ENET_QOS_MTL_TXQX_DBG_PTXQ_MASK)) != 0U)
1037 {
1038 }
1039
1040 /* Reset hardware ring buffer */
1041 txDescAddr =
1042 (uint32_t)(uintptr_t)handle->txBdRing[index].txBdBase & ENET_QOS_DMA_CHX_TXDESC_LIST_ADDR_TDESLA_MASK;
1043 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1044 txDescAddr = MEMORY_ConvertMemoryMapAddress(txDescAddr, kMEMORY_Local2DMA);
1045 #endif
1046 base->DMA_CH[index].DMA_CHX_TXDESC_LIST_ADDR = txDescAddr;
1047
1048 /* Reset software ring buffer */
1049 handle->txBdRing[index].txGenIdx = 0;
1050 handle->txBdRing[index].txConsumIdx = 0;
1051 handle->txBdRing[index].txDescUsed = 0;
1052
1053 handle->txDirtyRing[index].txGenIdx = 0;
1054 handle->txDirtyRing[index].txConsumIdx = 0;
1055 handle->txDirtyRing[index].isFull = false;
1056
1057 txbdPtr = (enet_qos_tx_bd_struct_t *)(handle->txBdRing[index].txBdBase);
1058 for (j = 0; j < handle->txBdRing[index].txRingLen; j++)
1059 {
1060 txbdPtr->buff1Addr = 0;
1061 txbdPtr->buff2Addr = 0;
1062 txbdPtr->buffLen = 0;
1063 txbdPtr->controlStat = 0;
1064 txbdPtr++;
1065 }
1066 }
1067
1068 /* Disable MAC Rx/Tx */
1069 base->MAC_CONFIGURATION &= ~(ENET_QOS_MAC_CONFIGURATION_TE_MASK | ENET_QOS_MAC_CONFIGURATION_RE_MASK);
1070
1071 /* Disable Rx DMA */
1072 for (index = 0; index < handle->rxQueueUse; index++)
1073 {
1074 base->DMA_CH[index].DMA_CHX_RX_CTRL &= ~ENET_QOS_DMA_CHX_RX_CTRL_SR_MASK;
1075 }
1076 }
1077
1078 /*!
1079 * brief Deinitializes the ENET module.
1080
1081 * This function gates the module clock and disables the ENET module.
1082 *
1083 * param base ENET peripheral base address.
1084 */
ENET_QOS_Deinit(ENET_QOS_Type * base)1085 void ENET_QOS_Deinit(ENET_QOS_Type *base)
1086 {
1087 /* Reset first and wait for the complete
1088 * The reset bit will automatically be cleared after complete. */
1089 base->DMA_MODE |= ENET_QOS_DMA_MODE_SWR_MASK;
1090 while ((base->DMA_MODE & ENET_QOS_DMA_MODE_SWR_MASK) != 0U)
1091 {
1092 }
1093
1094 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1095 /* Disables the clock source. */
1096 (void)CLOCK_DisableClock(s_enetqosClock[ENET_QOS_GetInstance(base)]);
1097 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1098 }
1099
1100 /*!
1101 * brief Initialize for all ENET descriptors.
1102 *
1103 * note This function is do all tx/rx descriptors initialization. Because this API
1104 * read all interrupt registers first and then set the interrupt flag for all descriptos,
1105 * if the interrupt register is set. so the descriptor initialization should be called
1106 * after ENET_QOS_Init(), ENET_QOS_EnableInterrupts() and ENET_QOS_CreateHandler()(if transactional APIs
1107 * are used).
1108 *
1109 * param base ENET peripheral base address.
1110 * param config The configuration for ENET.
1111 * param bufferConfig All buffers configuration.
1112 */
ENET_QOS_DescriptorInit(ENET_QOS_Type * base,enet_qos_config_t * config,enet_qos_buffer_config_t * bufferConfig)1113 status_t ENET_QOS_DescriptorInit(ENET_QOS_Type *base, enet_qos_config_t *config, enet_qos_buffer_config_t *bufferConfig)
1114 {
1115 assert(config != NULL);
1116 assert(bufferConfig != NULL);
1117
1118 bool intTxEnable = false;
1119 bool intRxEnable = false;
1120 uint8_t ringNum = 1;
1121 uint8_t txQueueUse = 1;
1122 uint8_t rxQueueUse = 1;
1123 uint8_t channel;
1124
1125 if (config->multiqueueCfg != NULL)
1126 {
1127 ringNum = MAX(config->multiqueueCfg->txQueueUse, config->multiqueueCfg->rxQueueUse);
1128 txQueueUse = config->multiqueueCfg->txQueueUse;
1129 rxQueueUse = config->multiqueueCfg->rxQueueUse;
1130 }
1131
1132 for (channel = 0; channel < ringNum; channel++)
1133 {
1134 intRxEnable = ((base->DMA_CH[channel].DMA_CHX_INT_EN & ENET_QOS_DMA_CHX_INT_EN_RIE_MASK) != 0U) ? true : false;
1135 intTxEnable = ((base->DMA_CH[channel].DMA_CHX_INT_EN & ENET_QOS_DMA_CHX_INT_EN_TIE_MASK) != 0U) ? true : false;
1136
1137 if (channel < txQueueUse)
1138 {
1139 if ((ENET_QOS_TxDescriptorsInit(base, bufferConfig, intTxEnable, channel) != kStatus_Success))
1140 {
1141 return kStatus_Fail;
1142 }
1143 }
1144
1145 if (channel < rxQueueUse)
1146 {
1147 if ((ENET_QOS_RxDescriptorsInit(base, config, bufferConfig, intRxEnable, channel) != kStatus_Success))
1148 {
1149 return kStatus_Fail;
1150 }
1151 }
1152
1153 bufferConfig++;
1154 }
1155 return kStatus_Success;
1156 }
1157
1158 /*!
1159 * brief Allocates Rx buffers for all BDs.
1160 * It's used for zero copy Rx. In zero copy Rx case, Rx buffers are dynamic. This function
1161 * will populate initial buffers in all BDs for receiving. Then ENET_QOS_GetRxFrame() is used
1162 * to get Rx frame with zero copy, it will allocate new buffer to replace the buffer in BD taken
1163 * by application application should free those buffers after they're used.
1164 *
1165 * note This function should be called after ENET_QOS_CreateHandler() and buffer allocating callback
1166 * function should be ready.
1167 *
1168 * param base ENET_QOS peripheral base address.
1169 * param handle The ENET_QOS handler structure. This is the same handler pointer used in the ENET_QOS_Init.
1170 */
ENET_QOS_RxBufferAllocAll(ENET_QOS_Type * base,enet_qos_handle_t * handle)1171 status_t ENET_QOS_RxBufferAllocAll(ENET_QOS_Type *base, enet_qos_handle_t *handle)
1172 {
1173 status_t result = kStatus_Success;
1174 enet_qos_rx_bd_struct_t *rxbdPtr;
1175 uint32_t buffAddr;
1176 uint8_t channel;
1177 uint16_t index;
1178 uint16_t j;
1179
1180 if ((handle->rxBuffAlloc == NULL) || (handle->rxBuffFree == NULL))
1181 {
1182 return kStatus_ENET_QOS_InitMemoryFail;
1183 }
1184
1185 for (channel = 0; channel < handle->rxQueueUse; channel++)
1186 {
1187 /* Init the rxbdPtr to the receive descriptor start address. */
1188 rxbdPtr = handle->rxBdRing[channel].rxBdBase;
1189 for (j = 0U; j < handle->rxBdRing[channel].rxRingLen; j++)
1190 {
1191 if (handle->doubleBuffEnable)
1192 {
1193 index = 2U * j;
1194 }
1195 else
1196 {
1197 index = j;
1198 }
1199
1200 buffAddr = (uint32_t)(uintptr_t)(uint8_t *)handle->rxBuffAlloc(base, handle->userData, channel);
1201 if (buffAddr == 0U)
1202 {
1203 result = kStatus_ENET_QOS_InitMemoryFail;
1204 break;
1205 }
1206
1207 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1208 buffAddr = (uint32_t)MEMORY_ConvertMemoryMapAddress(buffAddr, kMEMORY_Local2DMA);
1209 #endif
1210 rxbdPtr->buff1Addr = buffAddr;
1211 handle->rxBufferStartAddr[channel][index] = buffAddr;
1212
1213 /* The second buffer is set with 0 because it is not required for normal case. */
1214 if (handle->doubleBuffEnable)
1215 {
1216 buffAddr = (uint32_t)(uintptr_t)(uint8_t *)handle->rxBuffAlloc(base, handle->userData, channel);
1217 if (buffAddr == 0U)
1218 {
1219 result = kStatus_ENET_QOS_InitMemoryFail;
1220 break;
1221 }
1222
1223 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1224 buffAddr = (uint32_t)MEMORY_ConvertMemoryMapAddress(buffAddr, kMEMORY_Local2DMA);
1225 #endif
1226 rxbdPtr->buff2Addr = buffAddr;
1227 handle->rxBufferStartAddr[channel][index + 1U] = buffAddr;
1228 }
1229 else
1230 {
1231 rxbdPtr->buff2Addr = 0;
1232 }
1233
1234 /* Set the valid and DMA own flag.*/
1235 rxbdPtr->control |= ENET_QOS_RXDESCRIP_WR_OWN_MASK;
1236 rxbdPtr++;
1237 }
1238 }
1239
1240 if (result == kStatus_ENET_QOS_InitMemoryFail)
1241 {
1242 ENET_QOS_RxBufferFreeAll(base, handle);
1243 }
1244
1245 return result;
1246 }
1247
1248 /*!
1249 * brief Frees Rx buffers in all BDs.
1250 * It's used for zero copy Rx. In zero copy Rx case, Rx buffers are dynamic. This function
1251 * will free left buffers in all BDs.
1252 *
1253 * param base ENET_QOS peripheral base address.
1254 * param handle The ENET_QOS handler structure. This is the same handler pointer used in the ENET_QOS_Init.
1255 */
ENET_QOS_RxBufferFreeAll(ENET_QOS_Type * base,enet_qos_handle_t * handle)1256 void ENET_QOS_RxBufferFreeAll(ENET_QOS_Type *base, enet_qos_handle_t *handle)
1257 {
1258 uint32_t buffAddr;
1259 uint8_t channel;
1260 uint16_t index;
1261 uint16_t j;
1262
1263 if (handle->rxBuffFree != NULL)
1264 {
1265 for (channel = 0; channel < handle->rxQueueUse; channel++)
1266 {
1267 for (j = 0U; j < handle->rxBdRing[channel].rxRingLen; j++)
1268 {
1269 if (handle->doubleBuffEnable)
1270 {
1271 index = 2U * j;
1272 }
1273 else
1274 {
1275 index = j;
1276 }
1277
1278 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1279 buffAddr = MEMORY_ConvertMemoryMapAddress((uintptr_t)handle->rxBufferStartAddr[channel][index],
1280 kMEMORY_DMA2Local);
1281 #else
1282 buffAddr = (uint32_t)handle->rxBufferStartAddr[channel][index];
1283 #endif
1284 if (buffAddr != 0U)
1285 {
1286 handle->rxBuffFree(base, (void *)(uint8_t *)(uintptr_t)buffAddr, handle->userData, channel);
1287 }
1288
1289 /* The second buffer is set with 0 because it is not required for normal case. */
1290 if (handle->doubleBuffEnable)
1291 {
1292 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1293 buffAddr = MEMORY_ConvertMemoryMapAddress((uintptr_t)handle->rxBufferStartAddr[channel][index + 1U],
1294 kMEMORY_DMA2Local);
1295 #else
1296 buffAddr = (uint32_t)handle->rxBufferStartAddr[channel][index + 1U];
1297 #endif
1298 if (buffAddr != 0U)
1299 {
1300 handle->rxBuffFree(base, (void *)(uint8_t *)(uintptr_t)buffAddr, handle->userData, channel);
1301 }
1302 }
1303 }
1304 }
1305 }
1306 }
1307
1308 /*!
1309 * brief Starts the ENET rx/tx.
1310 * This function enable the tx/rx and starts the rx/tx DMA.
1311 * This shall be set after ENET initialization and before
1312 * starting to receive the data.
1313 *
1314 * param base ENET peripheral base address.
1315 * param rxRingNum The number of the used rx rings. It shall not be
1316 * larger than the ENET_QOS_RING_NUM_MAX(2). If the ringNum is set with
1317 * 1, the ring 0 will be used.
1318 * param txRingNum The number of the used tx rings. It shall not be
1319 * larger than the ENET_QOS_RING_NUM_MAX(2). If the ringNum is set with
1320 * 1, the ring 0 will be used.
1321 *
1322 * note This must be called after all the ENET initilization.
1323 * And should be called when the ENET receive/transmit is required.
1324 */
ENET_QOS_StartRxTx(ENET_QOS_Type * base,uint8_t txRingNum,uint8_t rxRingNum)1325 void ENET_QOS_StartRxTx(ENET_QOS_Type *base, uint8_t txRingNum, uint8_t rxRingNum)
1326 {
1327 assert(txRingNum != 0U);
1328 assert(rxRingNum != 0U);
1329
1330 uint8_t index;
1331
1332 if (txRingNum > ENET_QOS_RING_NUM_MAX)
1333 {
1334 txRingNum = ENET_QOS_RING_NUM_MAX;
1335 }
1336 if (rxRingNum > ENET_QOS_RING_NUM_MAX)
1337 {
1338 rxRingNum = ENET_QOS_RING_NUM_MAX;
1339 }
1340 /* Start/Acive the DMA first. */
1341 for (index = 0; index < rxRingNum; index++)
1342 {
1343 base->DMA_CH[index].DMA_CHX_RX_CTRL |= ENET_QOS_DMA_CHX_RX_CTRL_SR_MASK;
1344 }
1345 for (index = 0; index < txRingNum; index++)
1346 {
1347 base->DMA_CH[index].DMA_CHX_TX_CTRL |= ENET_QOS_DMA_CHX_TX_CTRL_ST_MASK;
1348 }
1349
1350 /* Enable the RX and TX at same time. */
1351 base->MAC_CONFIGURATION |= (ENET_QOS_MAC_CONFIGURATION_TE_MASK | ENET_QOS_MAC_CONFIGURATION_RE_MASK);
1352 }
1353
1354 /*!
1355 * brief Enables the ENET DMA and MAC interrupts.
1356 *
1357 * This function enables the ENET interrupt according to the provided mask. The mask
1358 * is a logical OR of enet_qos_dma_interrupt_enable_t and enet_qos_mac_interrupt_enable_t.
1359 * For example, to enable the dma and mac interrupt, do the following.
1360 * code
1361 * ENET_QOS_EnableInterrupts(ENET, kENET_QOS_DmaRx | kENET_QOS_DmaTx | kENET_QOS_MacPmt);
1362 * endcode
1363 *
1364 * param base ENET peripheral base address.
1365 * param mask ENET interrupts to enable. This is a logical OR of both
1366 * enumeration :: enet_qos_dma_interrupt_enable_t and enet_qos_mac_interrupt_enable_t.
1367 */
ENET_QOS_EnableInterrupts(ENET_QOS_Type * base,uint32_t mask)1368 void ENET_QOS_EnableInterrupts(ENET_QOS_Type *base, uint32_t mask)
1369 {
1370 uint32_t interrupt = mask & 0xFFFFU;
1371 uint8_t index;
1372
1373 /* For dma interrupt. */
1374 if (interrupt != 0U)
1375 {
1376 for (index = 0; index < ENET_QOS_RING_NUM_MAX; index++)
1377 {
1378 /* Set for all abnormal interrupts. */
1379 if ((ENET_QOS_ABNORM_INT_MASK & interrupt) != 0U)
1380 {
1381 interrupt |= ENET_QOS_DMA_CHX_INT_EN_AIE_MASK;
1382 }
1383 /* Set for all normal interrupts. */
1384 if ((ENET_QOS_NORM_INT_MASK & interrupt) != 0U)
1385 {
1386 interrupt |= ENET_QOS_DMA_CHX_INT_EN_NIE_MASK;
1387 }
1388 base->DMA_CH[index].DMA_CHX_INT_EN = interrupt;
1389 }
1390 }
1391 interrupt = mask >> ENET_QOS_MACINT_ENUM_OFFSET;
1392 if (interrupt != 0U)
1393 {
1394 /* MAC interrupt */
1395 base->MAC_INTERRUPT_ENABLE |= interrupt;
1396 }
1397 }
1398
1399 /*!
1400 * brief Clears the ENET mac interrupt events status flag.
1401 *
1402 * This function clears enabled ENET interrupts according to the provided mask. The mask
1403 * is a logical OR of enumeration members. See the ref enet_qos_mac_interrupt_enable_t.
1404 * For example, to clear the TX frame interrupt and RX frame interrupt, do the following.
1405 * code
1406 * ENET_QOS_ClearMacInterruptStatus(ENET, kENET_QOS_MacPmt);
1407 * endcode
1408 *
1409 * param base ENET peripheral base address.
1410 * param mask ENET interrupt source to be cleared.
1411 * This is the logical OR of members of the enumeration :: enet_qos_mac_interrupt_enable_t.
1412 */
ENET_QOS_ClearMacInterruptStatus(ENET_QOS_Type * base,uint32_t mask)1413 void ENET_QOS_ClearMacInterruptStatus(ENET_QOS_Type *base, uint32_t mask)
1414 {
1415 volatile uint32_t dummy;
1416
1417 if ((mask & (uint32_t)kENET_QOS_MacTimestamp) != 0U)
1418 {
1419 dummy = base->MAC_TIMESTAMP_STATUS;
1420 }
1421 else if ((mask & (uint32_t)kENET_QOS_MacPmt) != 0U)
1422 {
1423 dummy = base->MAC_PMT_CONTROL_STATUS;
1424 }
1425 else
1426 {
1427 /* Add for avoid the misra 2004 rule 14.10 */
1428 }
1429 (void)dummy;
1430 }
1431
1432 /*!
1433 * brief Disables the ENET DMA and MAC interrupts.
1434 *
1435 * This function disables the ENET interrupt according to the provided mask. The mask
1436 * is a logical OR of enet_qos_dma_interrupt_enable_t and enet_qos_mac_interrupt_enable_t.
1437 * For example, to disable the dma and mac interrupt, do the following.
1438 * code
1439 * ENET_QOS_DisableInterrupts(ENET, kENET_QOS_DmaRx | kENET_QOS_DmaTx | kENET_QOS_MacPmt);
1440 * endcode
1441 *
1442 * param base ENET peripheral base address.
1443 * param mask ENET interrupts to disables. This is a logical OR of both
1444 * enumeration :: enet_qos_dma_interrupt_enable_t and enet_qos_mac_interrupt_enable_t.
1445 */
ENET_QOS_DisableInterrupts(ENET_QOS_Type * base,uint32_t mask)1446 void ENET_QOS_DisableInterrupts(ENET_QOS_Type *base, uint32_t mask)
1447 {
1448 uint32_t interrupt = mask & 0xFFFFU;
1449 uint8_t index;
1450
1451 /* For dma interrupt. */
1452 if (interrupt != 0U)
1453 {
1454 for (index = 0; index < ENET_QOS_RING_NUM_MAX; index++)
1455 {
1456 /* Set for all abnormal interrupts. */
1457 if ((ENET_QOS_ABNORM_INT_MASK & interrupt) != 0U)
1458 {
1459 interrupt |= ENET_QOS_DMA_CHX_INT_EN_AIE_MASK;
1460 }
1461 /* Set for all normal interrupts. */
1462 if ((ENET_QOS_NORM_INT_MASK & interrupt) != 0U)
1463 {
1464 interrupt |= ENET_QOS_DMA_CHX_INT_EN_NIE_MASK;
1465 }
1466 base->DMA_CH[index].DMA_CHX_INT_EN &= ~interrupt;
1467 }
1468 }
1469 interrupt = mask >> ENET_QOS_MACINT_ENUM_OFFSET;
1470 if (interrupt != 0U)
1471 {
1472 /* MAC interrupt */
1473 base->MAC_INTERRUPT_ENABLE &= ~interrupt;
1474 }
1475 }
1476
1477 /*!
1478 * @brief Set the second level IRQ handler, allow user to overwrite the default
1479 * second level weak IRQ handler.
1480 *
1481 * @param ISRHandler he handler to install.
1482 */
ENET_QOS_SetISRHandler(ENET_QOS_Type * base,enet_qos_isr_t ISRHandler)1483 void ENET_QOS_SetISRHandler(ENET_QOS_Type *base, enet_qos_isr_t ISRHandler)
1484 {
1485 /* Update IRQ entry. */
1486 s_enetqosIsr = ISRHandler;
1487 /* Enable NVIC. */
1488 (void)EnableIRQ(s_enetqosIrqId[ENET_QOS_GetInstance(base)]);
1489 }
1490
1491 /*!
1492 * brief Create ENET Handler
1493 *
1494 * This is a transactional API and it's provided to store all datas which are needed
1495 * during the whole transactional process. This API should not be used when you use
1496 * functional APIs to do data tx/rx. This is funtion will store many data/flag for
1497 * transactional use, so all configure API such as ENET_QOS_Init(), ENET_QOS_DescriptorInit(),
1498 * ENET_QOS_EnableInterrupts() etc.
1499 *
1500 * note as our transactional transmit API use the zero-copy transmit buffer.
1501 * so there are two thing we emphasize here:
1502 * 1. tx buffer free/requeue for application should be done in the tx
1503 * interrupt handler. Please set callback: kENET_QOS_TxIntEvent with tx buffer free/requeue
1504 * process APIs.
1505 * 2. the tx interrupt is forced to open.
1506 *
1507 * param base ENET peripheral base address.
1508 * param handle ENET handler.
1509 * param config ENET configuration.
1510 * param bufferConfig ENET buffer configuration.
1511 * param callback The callback function.
1512 * param userData The application data.
1513 */
ENET_QOS_CreateHandler(ENET_QOS_Type * base,enet_qos_handle_t * handle,enet_qos_config_t * config,enet_qos_buffer_config_t * bufferConfig,enet_qos_callback_t callback,void * userData)1514 void ENET_QOS_CreateHandler(ENET_QOS_Type *base,
1515 enet_qos_handle_t *handle,
1516 enet_qos_config_t *config,
1517 enet_qos_buffer_config_t *bufferConfig,
1518 enet_qos_callback_t callback,
1519 void *userData)
1520 {
1521 assert(config != NULL);
1522 assert(bufferConfig != NULL);
1523 assert(callback != NULL);
1524
1525 uint8_t ringNum = 1;
1526 uint8_t count = 0;
1527 uint32_t rxIntEnable = 0;
1528 uint8_t txQueueUse = 1;
1529 uint8_t rxQueueUse = 1;
1530 enet_qos_buffer_config_t *buffConfig = bufferConfig;
1531
1532 /* Store transfer parameters in handle pointer. */
1533 (void)memset(handle, 0, sizeof(enet_qos_handle_t));
1534
1535 if (config->multiqueueCfg != NULL)
1536 {
1537 txQueueUse = config->multiqueueCfg->txQueueUse;
1538 rxQueueUse = config->multiqueueCfg->rxQueueUse;
1539 ringNum = MAX(txQueueUse, rxQueueUse);
1540 }
1541
1542 handle->txQueueUse = txQueueUse;
1543 handle->rxQueueUse = rxQueueUse;
1544
1545 if ((config->specialControl & (uint32_t)kENET_QOS_DescDoubleBuffer) != 0U)
1546 {
1547 handle->doubleBuffEnable = true;
1548 }
1549
1550 for (count = 0; count < ringNum; count++)
1551 {
1552 if (count < txQueueUse)
1553 {
1554 handle->txBdRing[count].txBdBase = buffConfig->txDescStartAddrAlign;
1555 handle->txBdRing[count].txRingLen = buffConfig->txRingLen;
1556 handle->txBdRing[count].txGenIdx = 0;
1557 handle->txBdRing[count].txConsumIdx = 0;
1558 handle->txBdRing[count].txDescUsed = 0;
1559
1560 handle->txDirtyRing[count].txDirtyBase = buffConfig->txDirtyStartAddr;
1561 handle->txDirtyRing[count].txRingLen = buffConfig->txRingLen;
1562 handle->txDirtyRing[count].txGenIdx = 0;
1563 handle->txDirtyRing[count].txConsumIdx = 0;
1564
1565 /* Enable tx interrupt for use transactional API to do tx buffer free/requeue. */
1566 base->DMA_CH[count].DMA_CHX_INT_EN |= ENET_QOS_DMA_CHX_INT_EN_TIE_MASK | ENET_QOS_DMA_CHX_INT_EN_NIE_MASK;
1567 }
1568
1569 if (count < rxQueueUse)
1570 {
1571 handle->rxBdRing[count].rxBdBase = buffConfig->rxDescStartAddrAlign;
1572 handle->rxBdRing[count].rxGenIdx = 0;
1573 handle->rxBdRing[count].rxRingLen = buffConfig->rxRingLen;
1574 handle->rxBdRing[count].rxBuffSizeAlign = buffConfig->rxBuffSizeAlign;
1575
1576 /* Record rx buffer address for re-init Rx buffer descriptor */
1577 handle->rxBufferStartAddr[count] = buffConfig->rxBufferStartAddr;
1578
1579 /* Record rx buffer need cache maintain */
1580 handle->rxMaintainEnable[count] = buffConfig->rxBuffNeedMaintain;
1581
1582 /* Check if the rx interrrupt is enabled. */
1583 rxIntEnable |= (base->DMA_CH[count].DMA_CHX_INT_EN & ENET_QOS_DMA_CHX_INT_EN_RIE_MASK);
1584 }
1585
1586 buffConfig++;
1587 }
1588
1589 handle->rxintEnable = (rxIntEnable != 0U) ? true : false;
1590
1591 /* Save the handle pointer in the global variables. */
1592 s_ENETHandle[ENET_QOS_GetInstance(base)] = handle;
1593
1594 /* Set Rx alloc/free callback. */
1595 handle->rxBuffAlloc = config->rxBuffAlloc;
1596 handle->rxBuffFree = config->rxBuffFree;
1597
1598 /* Set callback and userData. */
1599 handle->callback = callback;
1600 handle->userData = userData;
1601
1602 /* Use default ENET_QOS_CommonIRQHandler as default weak IRQ handler. */
1603 ENET_QOS_SetISRHandler(base, ENET_QOS_CommonIRQHandler);
1604 }
1605
1606 /*!
1607 * brief Gets the ENET module Mac address.
1608 *
1609 * param base ENET peripheral base address.
1610 * param macAddr The six-byte Mac address pointer.
1611 * The pointer is allocated by application and input into the API.
1612 */
ENET_QOS_GetMacAddr(ENET_QOS_Type * base,uint8_t * macAddr,uint8_t index)1613 void ENET_QOS_GetMacAddr(ENET_QOS_Type *base, uint8_t *macAddr, uint8_t index)
1614 {
1615 assert(macAddr != NULL);
1616
1617 uint32_t address = base->MAC_ADDRESS[index].LOW;
1618
1619 /* Get from physical address lower register. */
1620 macAddr[2] = (uint8_t)(0xFFU & (address >> 24U));
1621 macAddr[3] = (uint8_t)(0xFFU & (address >> 16U));
1622 macAddr[4] = (uint8_t)(0xFFU & (address >> 8U));
1623 macAddr[5] = (uint8_t)(0xFFU & address);
1624
1625 /* Get from physical address high register. */
1626 address = base->MAC_ADDRESS[index].HIGH;
1627 macAddr[0] = (uint8_t)(0xFFU & (address >> 8U));
1628 macAddr[1] = (uint8_t)(0xFFU & address);
1629 }
1630
1631 /*!
1632 * brief Adds the ENET_QOS device to a multicast group.
1633 *
1634 * param base ENET_QOS peripheral base address.
1635 * param address The six-byte multicast group address which is provided by application.
1636 */
ENET_QOS_AddMulticastGroup(ENET_QOS_Type * base,uint8_t * address)1637 void ENET_QOS_AddMulticastGroup(ENET_QOS_Type *base, uint8_t *address)
1638 {
1639 assert(address != NULL);
1640
1641 enet_qos_handle_t *handle = s_ENETHandle[ENET_QOS_GetInstance(base)];
1642 uint32_t crc = 0xFFFFFFFFU;
1643 uint32_t count1 = 0;
1644 uint32_t count2 = 0;
1645
1646 /* Calculates the CRC-32 polynomial on the multicast group address. */
1647 for (count1 = 0; count1 < 6U; count1++)
1648 {
1649 uint8_t c = address[count1];
1650 for (count2 = 0; count2 < 0x08U; count2++)
1651 {
1652 if (((c ^ crc) & 1U) != 0U)
1653 {
1654 crc >>= 1U;
1655 c >>= 1U;
1656 crc ^= 0xEDB88320U;
1657 }
1658 else
1659 {
1660 crc >>= 1U;
1661 c >>= 1U;
1662 }
1663 }
1664 }
1665
1666 /* Calculate bitwise reverse value. */
1667 crc = ENET_QOS_ReverseBits(~crc);
1668
1669 /* Get highest 6 bits*/
1670 crc = crc >> 26U;
1671
1672 handle->multicastCount[crc]++;
1673
1674 if (0U != (crc & 0x20U))
1675 {
1676 base->MAC_HASH_TABLE_REG1 |= (1UL << (crc & 0x1FU));
1677 }
1678 else
1679 {
1680 base->MAC_HASH_TABLE_REG0 |= (1UL << (crc & 0x1FU));
1681 }
1682 }
1683
1684 /*!
1685 * brief Moves the ENET_QOS device from a multicast group.
1686 *
1687 * param base ENET_QOS peripheral base address.
1688 * param address The six-byte multicast group address which is provided by application.
1689 */
ENET_QOS_LeaveMulticastGroup(ENET_QOS_Type * base,uint8_t * address)1690 void ENET_QOS_LeaveMulticastGroup(ENET_QOS_Type *base, uint8_t *address)
1691 {
1692 assert(address != NULL);
1693
1694 enet_qos_handle_t *handle = s_ENETHandle[ENET_QOS_GetInstance(base)];
1695 uint32_t crc = 0xFFFFFFFFU;
1696 uint32_t count1 = 0;
1697 uint32_t count2 = 0;
1698
1699 /* Calculates the CRC-32 polynomial on the multicast group address. */
1700 for (count1 = 0; count1 < 6U; count1++)
1701 {
1702 uint8_t c = address[count1];
1703 for (count2 = 0; count2 < 0x08U; count2++)
1704 {
1705 if (((c ^ crc) & 1U) != 0U)
1706 {
1707 crc >>= 1U;
1708 c >>= 1U;
1709 crc ^= 0xEDB88320U;
1710 }
1711 else
1712 {
1713 crc >>= 1U;
1714 c >>= 1U;
1715 }
1716 }
1717 }
1718
1719 /* Calculate bitwise reverse value. */
1720 crc = ENET_QOS_ReverseBits(~crc);
1721
1722 /* Get highest 6 bits*/
1723 crc = crc >> 26U;
1724
1725 handle->multicastCount[crc]--;
1726
1727 /* Set the hash table if no collisions */
1728 if (0U == handle->multicastCount[crc])
1729 {
1730 if (0U != (crc & 0x20U))
1731 {
1732 base->MAC_HASH_TABLE_REG1 &= ~((1UL << (crc & 0x1FU)));
1733 }
1734 else
1735 {
1736 base->MAC_HASH_TABLE_REG0 &= ~((1UL << (crc & 0x1FU)));
1737 }
1738 }
1739 }
1740
1741 /*!
1742 * brief Sets the ENET MII speed and duplex.
1743 *
1744 * This API is provided to dynamically change the speed and duplex for MAC.
1745 *
1746 * param base ENET peripheral base address.
1747 * param speed The speed of the RMII mode.
1748 * param duplex The duplex of the RMII mode.
1749 * return kStatus_Success The ENET MII speed and duplex has been set successfully.
1750 * return kStatus_InvalidArgument Could not set the desired ENET MII speed and duplex combination.
1751 */
ENET_QOS_SetMII(ENET_QOS_Type * base,enet_qos_mii_speed_t speed,enet_qos_mii_duplex_t duplex)1752 status_t ENET_QOS_SetMII(ENET_QOS_Type *base, enet_qos_mii_speed_t speed, enet_qos_mii_duplex_t duplex)
1753 {
1754 uint32_t reg = base->MAC_CONFIGURATION & ~(ENET_QOS_MAC_CONFIGURATION_DM_MASK | ENET_QOS_MAC_CONFIGURATION_PS_MASK |
1755 ENET_QOS_MAC_CONFIGURATION_FES_MASK);
1756 enet_qos_mii_mode_t configured_mode = s_enetStates[ENET_QOS_GetInstance(base)].miiMode;
1757
1758 if (!ENET_QOS_IsMIIConfigValid(configured_mode, speed))
1759 {
1760 return kStatus_InvalidArgument;
1761 }
1762
1763 reg |= ENET_QOS_MAC_CONFIGURATION_DM(duplex) | (uint32_t)speed;
1764
1765 base->MAC_CONFIGURATION = reg;
1766
1767 return kStatus_Success;
1768 }
1769
1770 /*!
1771 * brief Sets the ENET SMI(serial management interface)- MII management interface.
1772 *
1773 * param base ENET peripheral base address.
1774 */
ENET_QOS_SetSMI(ENET_QOS_Type * base,uint32_t csrClock_Hz)1775 void ENET_QOS_SetSMI(ENET_QOS_Type *base, uint32_t csrClock_Hz)
1776 {
1777 uint32_t crDiv = 0;
1778 uint32_t srcClock_Hz = csrClock_Hz / 1000000U;
1779
1780 assert((srcClock_Hz >= 20U) && (srcClock_Hz < 800U));
1781
1782 if (srcClock_Hz < 35U)
1783 {
1784 crDiv = 2;
1785 }
1786 else if (srcClock_Hz < 60U)
1787 {
1788 crDiv = 3;
1789 }
1790 else if (srcClock_Hz < 100U)
1791 {
1792 crDiv = 0;
1793 }
1794 else if (srcClock_Hz < 150U)
1795 {
1796 crDiv = 1;
1797 }
1798 else if (srcClock_Hz < 250U)
1799 {
1800 crDiv = 4;
1801 }
1802 else if (srcClock_Hz < 300U)
1803 {
1804 crDiv = 5;
1805 }
1806 else if (srcClock_Hz < 500U)
1807 {
1808 crDiv = 6;
1809 }
1810 else if (srcClock_Hz < 800U)
1811 {
1812 crDiv = 7;
1813 }
1814 else
1815 {
1816 /* Empty else */
1817 }
1818
1819 base->MAC_MDIO_ADDRESS = ENET_QOS_MAC_MDIO_ADDRESS_CR(crDiv);
1820 }
1821
1822 /*!
1823 * @brief Sends the MDIO IEEE802.3 Clause 22 format write command.
1824 * After send command, user needs to check whether the transmission is over
1825 * with ENET_QOS_IsSMIBusy().
1826 *
1827 * @param base ENET peripheral base address.
1828 * @param phyAddr The PHY address.
1829 * @param regAddr The PHY register address.
1830 * @param data The data written to PHY.
1831 */
ENET_QOS_StartSMIWrite(ENET_QOS_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t data)1832 void ENET_QOS_StartSMIWrite(ENET_QOS_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1833 {
1834 uint32_t reg = base->MAC_MDIO_ADDRESS & ENET_QOS_MAC_MDIO_ADDRESS_CR_MASK;
1835
1836 /* Build MII write command. */
1837 base->MAC_MDIO_ADDRESS = reg | (uint32_t)kENET_QOS_MiiWriteFrame | ENET_QOS_MAC_MDIO_ADDRESS_PA(phyAddr) |
1838 ENET_QOS_MAC_MDIO_ADDRESS_RDA(regAddr);
1839 base->MAC_MDIO_DATA = data;
1840 base->MAC_MDIO_ADDRESS |= ENET_QOS_MAC_MDIO_ADDRESS_GB_MASK;
1841 }
1842
1843 /*!
1844 * @brief Sends the MDIO IEEE802.3 Clause 22 format read command.
1845 * After send command, user needs to check whether the transmission is over
1846 * with ENET_QOS_IsSMIBusy().
1847 *
1848 * @param base ENET peripheral base address.
1849 * @param phyAddr The PHY address.
1850 * @param regAddr The PHY register address.
1851 */
ENET_QOS_StartSMIRead(ENET_QOS_Type * base,uint8_t phyAddr,uint8_t regAddr)1852 void ENET_QOS_StartSMIRead(ENET_QOS_Type *base, uint8_t phyAddr, uint8_t regAddr)
1853 {
1854 uint32_t reg = base->MAC_MDIO_ADDRESS & ENET_QOS_MAC_MDIO_ADDRESS_CR_MASK;
1855
1856 /* Build MII read command. */
1857 base->MAC_MDIO_ADDRESS = reg | (uint32_t)kENET_QOS_MiiReadFrame | ENET_QOS_MAC_MDIO_ADDRESS_PA(phyAddr) |
1858 ENET_QOS_MAC_MDIO_ADDRESS_RDA(regAddr);
1859 base->MAC_MDIO_ADDRESS |= ENET_QOS_MAC_MDIO_ADDRESS_GB_MASK;
1860 }
1861
1862 /*!
1863 * @brief Sends the MDIO IEEE802.3 Clause 45 format write command.
1864 * After send command, user needs to check whether the transmission is over
1865 * with ENET_QOS_IsSMIBusy().
1866 *
1867 * @param base ENET peripheral base address.
1868 * @param portAddr The MDIO port address(PHY address).
1869 * @param devAddr The device address.
1870 * @param regAddr The PHY register address.
1871 * @param data The data written to PHY.
1872 */
ENET_QOS_StartExtC45SMIWrite(ENET_QOS_Type * base,uint8_t portAddr,uint8_t devAddr,uint16_t regAddr,uint16_t data)1873 void ENET_QOS_StartExtC45SMIWrite(
1874 ENET_QOS_Type *base, uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t data)
1875 {
1876 uint32_t reg = base->MAC_MDIO_ADDRESS & ENET_QOS_MAC_MDIO_ADDRESS_CR_MASK;
1877
1878 /* Build MII write command. */
1879 base->MAC_MDIO_ADDRESS = reg | ENET_QOS_MAC_MDIO_ADDRESS_C45E_MASK | (uint32_t)kENET_QOS_MiiWriteFrame |
1880 ENET_QOS_MAC_MDIO_ADDRESS_PA(portAddr) | ENET_QOS_MAC_MDIO_ADDRESS_RDA(devAddr);
1881 base->MAC_MDIO_DATA = data | ENET_QOS_MAC_MDIO_DATA_RA(regAddr);
1882 base->MAC_MDIO_ADDRESS |= ENET_QOS_MAC_MDIO_ADDRESS_GB_MASK;
1883 }
1884
1885 /*!
1886 * @brief Sends the MDIO IEEE802.3 Clause 45 format read command.
1887 * After send command, user needs to check whether the transmission is over
1888 * with ENET_QOS_IsSMIBusy().
1889 *
1890 * @param base ENET peripheral base address.
1891 * @param portAddr The MDIO port address(PHY address).
1892 * @param devAddr The device address.
1893 * @param regAddr The PHY register address.
1894 */
ENET_QOS_StartExtC45SMIRead(ENET_QOS_Type * base,uint8_t portAddr,uint8_t devAddr,uint16_t regAddr)1895 void ENET_QOS_StartExtC45SMIRead(ENET_QOS_Type *base, uint8_t portAddr, uint8_t devAddr, uint16_t regAddr)
1896 {
1897 uint32_t reg = base->MAC_MDIO_ADDRESS & ENET_QOS_MAC_MDIO_ADDRESS_CR_MASK;
1898
1899 /* Build MII read command. */
1900 base->MAC_MDIO_ADDRESS = reg | ENET_QOS_MAC_MDIO_ADDRESS_C45E_MASK | (uint32_t)kENET_QOS_MiiReadFrame |
1901 ENET_QOS_MAC_MDIO_ADDRESS_PA(portAddr) | ENET_QOS_MAC_MDIO_ADDRESS_RDA(devAddr);
1902 base->MAC_MDIO_DATA = ENET_QOS_MAC_MDIO_DATA_RA(regAddr);
1903 base->MAC_MDIO_ADDRESS |= ENET_QOS_MAC_MDIO_ADDRESS_GB_MASK;
1904 }
1905
ENET_QOS_MDIOWaitTransferOver(ENET_QOS_Type * base)1906 static status_t ENET_QOS_MDIOWaitTransferOver(ENET_QOS_Type *base)
1907 {
1908 status_t result = kStatus_Success;
1909 #ifdef ENET_QOS_MDIO_TIMEOUT_COUNT
1910 uint32_t counter;
1911 #endif
1912
1913 #ifdef ENET_QOS_MDIO_TIMEOUT_COUNT
1914 for (counter = ENET_QOS_MDIO_TIMEOUT_COUNT; counter > 0U; counter--)
1915 {
1916 if (!ENET_QOS_IsSMIBusy(base))
1917 {
1918 break;
1919 }
1920 }
1921 /* Check for timeout. */
1922 if (0U == counter)
1923 {
1924 result = kStatus_Timeout;
1925 }
1926 #else
1927 while (ENET_QOS_IsSMIBusy(base))
1928 {
1929 }
1930 #endif
1931 return result;
1932 }
1933
1934 /*!
1935 * @brief MDIO write with IEEE802.3 MDIO Clause 22 format.
1936 *
1937 * @param base ENET peripheral base address.
1938 * @param phyAddr The PHY address.
1939 * @param regAddr The PHY register.
1940 * @param data The data written to PHY.
1941 * @return kStatus_Success MDIO access succeeds.
1942 * @return kStatus_Timeout MDIO access timeout.
1943 */
ENET_QOS_MDIOWrite(ENET_QOS_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t data)1944 status_t ENET_QOS_MDIOWrite(ENET_QOS_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1945 {
1946 ENET_QOS_StartSMIWrite(base, phyAddr, regAddr, data);
1947
1948 return ENET_QOS_MDIOWaitTransferOver(base);
1949 }
1950
1951 /*!
1952 * @brief MDIO read with IEEE802.3 MDIO Clause 22 format.
1953 *
1954 * @param base ENET peripheral base address.
1955 * @param phyAddr The PHY address.
1956 * @param regAddr The PHY register.
1957 * @param pData The data read from PHY.
1958 * @return kStatus_Success MDIO access succeeds.
1959 * @return kStatus_Timeout MDIO access timeout.
1960 */
ENET_QOS_MDIORead(ENET_QOS_Type * base,uint8_t phyAddr,uint8_t regAddr,uint16_t * pData)1961 status_t ENET_QOS_MDIORead(ENET_QOS_Type *base, uint8_t phyAddr, uint8_t regAddr, uint16_t *pData)
1962 {
1963 assert(pData);
1964
1965 status_t result;
1966
1967 ENET_QOS_StartSMIRead(base, phyAddr, regAddr);
1968
1969 result = ENET_QOS_MDIOWaitTransferOver(base);
1970 if (result != kStatus_Success)
1971 {
1972 return result;
1973 }
1974 *pData = ENET_QOS_ReadSMIData(base);
1975
1976 return result;
1977 }
1978
1979 /*!
1980 * @brief MDIO write with IEEE802.3 Clause 45 format.
1981 *
1982 * @param base ENET peripheral base address.
1983 * @param portAddr The MDIO port address(PHY address).
1984 * @param devAddr The device address.
1985 * @param regAddr The PHY register address.
1986 * @param data The data written to PHY.
1987 * @return kStatus_Success MDIO access succeeds.
1988 * @return kStatus_Timeout MDIO access timeout.
1989 */
ENET_QOS_MDIOC45Write(ENET_QOS_Type * base,uint8_t portAddr,uint8_t devAddr,uint16_t regAddr,uint16_t data)1990 status_t ENET_QOS_MDIOC45Write(ENET_QOS_Type *base, uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t data)
1991 {
1992 ENET_QOS_StartExtC45SMIWrite(base, portAddr, devAddr, regAddr, data);
1993
1994 return ENET_QOS_MDIOWaitTransferOver(base);
1995 }
1996
1997 /*!
1998 * @brief MDIO read with IEEE802.3 Clause 45 format.
1999 *
2000 * @param base ENET peripheral base address.
2001 * @param portAddr The MDIO port address(PHY address).
2002 * @param devAddr The device address.
2003 * @param regAddr The PHY register address.
2004 * @param pData The data read from PHY.
2005 * @return kStatus_Success MDIO access succeeds.
2006 * @return kStatus_Timeout MDIO access timeout.
2007 */
ENET_QOS_MDIOC45Read(ENET_QOS_Type * base,uint8_t portAddr,uint8_t devAddr,uint16_t regAddr,uint16_t * pData)2008 status_t ENET_QOS_MDIOC45Read(ENET_QOS_Type *base, uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t *pData)
2009 {
2010 status_t result = kStatus_Success;
2011
2012 ENET_QOS_StartExtC45SMIRead(base, portAddr, devAddr, regAddr);
2013
2014 result = ENET_QOS_MDIOWaitTransferOver(base);
2015 if (result != kStatus_Success)
2016 {
2017 return result;
2018 }
2019 *pData = ENET_QOS_ReadSMIData(base);
2020
2021 return result;
2022 }
2023
2024 /*!
2025 * brief Set the MAC to enter into power down mode.
2026 * the remote power wake up frame and magic frame can wake up
2027 * the ENET from the power down mode.
2028 *
2029 * param base ENET peripheral base address.
2030 * param wakeFilter The wakeFilter provided to configure the wake up frame fitlter.
2031 * Set the wakeFilter to NULL is not required. But if you have the filter requirement,
2032 * please make sure the wakeFilter pointer shall be eight continous
2033 * 32-bits configuration.
2034 */
ENET_QOS_EnterPowerDown(ENET_QOS_Type * base,uint32_t * wakeFilter)2035 void ENET_QOS_EnterPowerDown(ENET_QOS_Type *base, uint32_t *wakeFilter)
2036 {
2037 uint8_t index;
2038 uint32_t *reg = wakeFilter;
2039
2040 /* Disable the tx dma. */
2041 base->DMA_CH[0].DMA_CHX_TX_CTRL &= ~ENET_QOS_DMA_CHX_TX_CTRL_ST_MASK;
2042 base->DMA_CH[1].DMA_CHX_TX_CTRL &= ~ENET_QOS_DMA_CHX_TX_CTRL_ST_MASK;
2043
2044 /* Disable the mac tx/rx. */
2045 base->MAC_CONFIGURATION &= ~(ENET_QOS_MAC_CONFIGURATION_RE_MASK | ENET_QOS_MAC_CONFIGURATION_TE_MASK);
2046 /* Enable the remote wakeup packet and enable the power down mode. */
2047 if (wakeFilter != NULL)
2048 {
2049 for (index = 0; index < ENET_QOS_WAKEUPFILTER_NUM; index++)
2050 {
2051 base->MAC_RWK_PACKET_FILTER = *reg;
2052 reg++;
2053 }
2054 }
2055 base->MAC_PMT_CONTROL_STATUS = ENET_QOS_MAC_PMT_CONTROL_STATUS_MGKPKTEN_MASK |
2056 ENET_QOS_MAC_PMT_CONTROL_STATUS_RWKPKTEN_MASK |
2057 ENET_QOS_MAC_PMT_CONTROL_STATUS_PWRDWN_MASK;
2058
2059 /* Enable the MAC rx. */
2060 base->MAC_CONFIGURATION |= ENET_QOS_MAC_CONFIGURATION_RE_MASK;
2061 }
2062
2063 /*!
2064 * brief Enable/Disable Rx parser, please notice that for enable/disable Rx Parser,
2065 * should better disable Receive first.
2066 *
2067 * param base ENET_QOS peripheral base address.
2068 * param enable Enable/Disable Rx parser function
2069 */
ENET_QOS_EnableRxParser(ENET_QOS_Type * base,bool enable)2070 status_t ENET_QOS_EnableRxParser(ENET_QOS_Type *base, bool enable)
2071 {
2072 status_t result = kStatus_Success;
2073
2074 if (enable)
2075 {
2076 base->MTL_OPERATION_MODE |= ENET_QOS_MTL_OPERATION_MODE_FRPE_MASK;
2077 }
2078 else
2079 {
2080 base->MTL_OPERATION_MODE &= ~ENET_QOS_MTL_OPERATION_MODE_FRPE_MASK;
2081 result = ENET_QOS_PollStatusFlag(&(base->MTL_RXP_CONTROL_STATUS), ENET_QOS_MTL_RXP_CONTROL_STATUS_RXPI_MASK,
2082 ENET_QOS_MTL_RXP_CONTROL_STATUS_RXPI_MASK);
2083 }
2084
2085 return result;
2086 }
2087
2088 /*!
2089 * brief Gets the size of the read frame.
2090 * This function gets a received frame size from the ENET buffer descriptors.
2091 * note The FCS of the frame is automatically removed by MAC and the size is the length without the FCS.
2092 * After calling ENET_QOS_GetRxFrameSize, ENET_QOS_ReadFrame() should be called to update the
2093 * receive buffers If the result is not "kStatus_ENET_QOS_RxFrameEmpty".
2094 *
2095 * param handle The ENET handler structure. This is the same handler pointer used in the ENET_QOS_Init.
2096 * param length The length of the valid frame received.
2097 * param channel The DMAC channel for the rx.
2098 * retval kStatus_ENET_QOS_RxFrameEmpty No frame received. Should not call ENET_QOS_ReadFrame to read frame.
2099 * retval kStatus_ENET_QOS_RxFrameError Data error happens. ENET_QOS_ReadFrame should be called with NULL data
2100 * and NULL length to update the receive buffers.
2101 * retval kStatus_Success Receive a frame Successfully then the ENET_QOS_ReadFrame
2102 * should be called with the right data buffer and the captured data length input.
2103 */
ENET_QOS_GetRxFrameSize(ENET_QOS_Type * base,enet_qos_handle_t * handle,uint32_t * length,uint8_t channel)2104 status_t ENET_QOS_GetRxFrameSize(ENET_QOS_Type *base, enet_qos_handle_t *handle, uint32_t *length, uint8_t channel)
2105 {
2106 assert(handle != NULL);
2107 assert(length != NULL);
2108
2109 enet_qos_rx_bd_ring_t *rxBdRing = (enet_qos_rx_bd_ring_t *)&handle->rxBdRing[channel];
2110 enet_qos_rx_bd_struct_t *rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
2111 uint16_t index = rxBdRing->rxGenIdx;
2112 uint32_t control = rxDesc->control;
2113
2114 /* Reset the length to zero. */
2115 *length = 0;
2116
2117 if ((control & ENET_QOS_RXDESCRIP_WR_OWN_MASK) != 0U)
2118 {
2119 return kStatus_ENET_QOS_RxFrameEmpty;
2120 }
2121 else
2122 {
2123 do
2124 {
2125 /* Application owns the buffer descriptor, get the length. */
2126 if ((control & ENET_QOS_RXDESCRIP_WR_LD_MASK) != 0U)
2127 {
2128 if ((control & ENET_QOS_RXDESCRIP_WR_ERRSUM_MASK) != 0U)
2129 {
2130 return kStatus_ENET_QOS_RxFrameError;
2131 }
2132 *length = (control & ENET_QOS_RXDESCRIP_WR_PACKETLEN_MASK) - ENET_QOS_FCS_LEN;
2133 return kStatus_Success;
2134 }
2135
2136 index = ENET_QOS_IncreaseIndex(index, rxBdRing->rxRingLen);
2137 rxDesc = &rxBdRing->rxBdBase[index];
2138 control = rxDesc->control;
2139 } while (index != rxBdRing->rxGenIdx);
2140
2141 return kStatus_ENET_QOS_RxFrameError;
2142 }
2143 }
2144
ENET_QOS_DropFrame(ENET_QOS_Type * base,enet_qos_handle_t * handle,uint8_t channel)2145 static void ENET_QOS_DropFrame(ENET_QOS_Type *base, enet_qos_handle_t *handle, uint8_t channel)
2146 {
2147 enet_qos_rx_bd_ring_t *rxBdRing = (enet_qos_rx_bd_ring_t *)&handle->rxBdRing[channel];
2148 enet_qos_rx_bd_struct_t *rxDesc;
2149 uint16_t index = rxBdRing->rxGenIdx;
2150 bool tsAvailable = false;
2151 uintptr_t buff1Addr = 0;
2152 uintptr_t buff2Addr = 0;
2153 uint32_t rxDescTail;
2154 uint32_t rdesc1;
2155 uint32_t rdesc3;
2156
2157 /* Not check DMA ownership here, assume there's at least one valid frame left in BD ring */
2158 do
2159 {
2160 /* Get the control flag. */
2161 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
2162 rdesc1 = rxDesc->reserved;
2163 rdesc3 = rxDesc->control;
2164
2165 if (!handle->doubleBuffEnable)
2166 {
2167 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
2168 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
2169 handle->doubleBuffEnable);
2170 }
2171 else
2172 {
2173 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
2174 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
2175 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
2176 handle->rxintEnable, handle->doubleBuffEnable);
2177 }
2178
2179 rxBdRing->rxGenIdx = ENET_QOS_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
2180
2181 /* Find the last buffer descriptor for the frame. */
2182 if ((rdesc3 & ENET_QOS_RXDESCRIP_WR_LD_MASK) != 0U)
2183 {
2184 if ((rdesc3 & ENET_QOS_RXDESCRIP_WR_RS1V_MASK) != 0U)
2185 {
2186 if ((rdesc1 & ENET_QOS_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
2187 {
2188 tsAvailable = true;
2189 }
2190 }
2191
2192 /* Reinit for the context descriptor which has been updated by DMA. */
2193 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
2194
2195 if (tsAvailable && ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_CTXT_MASK) != 0U))
2196 {
2197 if (!handle->doubleBuffEnable)
2198 {
2199 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
2200 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
2201 handle->doubleBuffEnable);
2202 }
2203 else
2204 {
2205 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
2206 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
2207 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
2208 handle->rxintEnable, handle->doubleBuffEnable);
2209 }
2210 rxBdRing->rxGenIdx = ENET_QOS_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
2211 }
2212 break;
2213 }
2214 } while (rxBdRing->rxGenIdx != index);
2215
2216 /* Always try to start receive, in case it had stopped */
2217 rxDescTail = (uint32_t)(uintptr_t)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
2218 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2219 rxDescTail = MEMORY_ConvertMemoryMapAddress(rxDescTail, kMEMORY_Local2DMA);
2220 #endif
2221 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = rxDescTail;
2222 base->DMA_CH[channel].DMA_CHX_RX_CTRL |= ENET_QOS_DMA_CHX_RX_CTRL_SR_MASK;
2223 }
2224
2225 /*!
2226 * brief Reads a frame from the ENET device.
2227 * This function reads a frame from the ENET DMA descriptors.
2228 * The ENET_QOS_GetRxFrameSize should be used to get the size of the prepared data buffer.
2229 * For example use rx dma channel 0:
2230 * code
2231 * uint32_t length;
2232 * enet_qos_handle_t g_handle;
2233 * enet_qos_ptp_time_t ts;
2234 * status = ENET_QOS_GetRxFrameSize(&g_handle, &length, 0);
2235 * if (length != 0)
2236 * {
2237 * uint8_t *data = memory allocate interface;
2238 * if (!data)
2239 * {
2240 * ENET_QOS_ReadFrame(ENET, &g_handle, NULL, 0, 0, &ts);
2241 * }
2242 * else
2243 * {
2244 * status = ENET_QOS_ReadFrame(ENET, &g_handle, data, length, 0, &ts);
2245 * }
2246 * }
2247 * else if (status == kStatus_ENET_QOS_RxFrameError)
2248 * {
2249 * ENET_QOS_ReadFrame(ENET, &g_handle, NULL, 0, 0, &ts);
2250 * }
2251 * endcode
2252 * param base ENET peripheral base address.
2253 * param handle The ENET handler structure. This is the same handler pointer used in the ENET_QOS_Init.
2254 * param data The data buffer provided by user to store the frame which memory size should be at least "length".
2255 * param length The size of the data buffer which is still the length of the received frame.
2256 * param channel The rx DMA channel. shall not be larger than 2.
2257 * return The execute status, successful or failure.
2258 */
ENET_QOS_ReadFrame(ENET_QOS_Type * base,enet_qos_handle_t * handle,uint8_t * data,uint32_t length,uint8_t channel,enet_qos_ptp_time_t * ts)2259 status_t ENET_QOS_ReadFrame(ENET_QOS_Type *base,
2260 enet_qos_handle_t *handle,
2261 uint8_t *data,
2262 uint32_t length,
2263 uint8_t channel,
2264 enet_qos_ptp_time_t *ts)
2265 {
2266 assert(handle != NULL);
2267 assert(channel < handle->rxQueueUse);
2268
2269 uint32_t len = 0;
2270 uint32_t offset = 0;
2271 uint32_t control;
2272 bool isLastBuff = false;
2273 enet_qos_rx_bd_ring_t *rxBdRing = (enet_qos_rx_bd_ring_t *)&handle->rxBdRing[channel];
2274 enet_qos_rx_bd_struct_t *rxDesc;
2275 status_t result = kStatus_Fail;
2276 uintptr_t buff1Addr = 0; /*!< Buffer 1 address */
2277 uintptr_t buff2Addr = 0; /*!< Buffer 2 or next descriptor address */
2278 uint32_t rxDescTail;
2279
2280 bool tsAvailable = false;
2281
2282 /* For data-NULL input, only update the buffer descriptor. */
2283 if (data == NULL)
2284 {
2285 ENET_QOS_DropFrame(base, handle, channel);
2286 result = kStatus_Success;
2287 }
2288 else
2289 {
2290 while (!isLastBuff)
2291 {
2292 /* The last buffer descriptor of a frame. */
2293 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
2294 control = rxDesc->control;
2295
2296 if (!handle->doubleBuffEnable)
2297 {
2298 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
2299 if (handle->rxMaintainEnable[channel])
2300 {
2301 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2302 /* Add the cache invalidate maintain. */
2303 ENET_QOS_DcacheInvalidateByRange(MEMORY_ConvertMemoryMapAddress(buff1Addr, kMEMORY_DMA2Local),
2304 rxBdRing->rxBuffSizeAlign);
2305 #else
2306 /* Add the cache invalidate maintain. */
2307 ENET_QOS_DcacheInvalidateByRange(buff1Addr, rxBdRing->rxBuffSizeAlign);
2308 #endif
2309 }
2310 }
2311 else
2312 {
2313 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
2314 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
2315 if (handle->rxMaintainEnable[channel])
2316 {
2317 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2318 /* Add the cache invalidate maintain. */
2319 ENET_QOS_DcacheInvalidateByRange(MEMORY_ConvertMemoryMapAddress(buff1Addr, kMEMORY_DMA2Local),
2320 rxBdRing->rxBuffSizeAlign);
2321 /* Add the cache invalidate maintain. */
2322 ENET_QOS_DcacheInvalidateByRange(MEMORY_ConvertMemoryMapAddress(buff2Addr, kMEMORY_DMA2Local),
2323 rxBdRing->rxBuffSizeAlign);
2324 #else
2325 /* Add the cache invalidate maintain. */
2326 ENET_QOS_DcacheInvalidateByRange(buff1Addr, rxBdRing->rxBuffSizeAlign);
2327 /* Add the cache invalidate maintain. */
2328 ENET_QOS_DcacheInvalidateByRange(buff2Addr, rxBdRing->rxBuffSizeAlign);
2329 #endif
2330 }
2331 }
2332
2333 rxBdRing->rxGenIdx = ENET_QOS_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
2334
2335 if ((control & ENET_QOS_RXDESCRIP_WR_LD_MASK) != 0U)
2336 {
2337 /* This is a valid frame. */
2338 isLastBuff = true;
2339
2340 /* Remove FCS */
2341 len = (control & ENET_QOS_RXDESCRIP_WR_PACKETLEN_MASK) - ENET_QOS_FCS_LEN;
2342
2343 if (length == len)
2344 {
2345 /* Copy the frame to user's buffer. */
2346 len -= offset;
2347
2348 if (len > rxBdRing->rxBuffSizeAlign)
2349 {
2350 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2351 (void)memcpy((void *)&data[offset],
2352 (void *)(uint8_t *)MEMORY_ConvertMemoryMapAddress(buff1Addr, kMEMORY_DMA2Local),
2353 rxBdRing->rxBuffSizeAlign);
2354 #else
2355 (void)memcpy((void *)&data[offset], (void *)(uint8_t *)buff1Addr, rxBdRing->rxBuffSizeAlign);
2356 #endif
2357 offset += rxBdRing->rxBuffSizeAlign;
2358 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2359 (void)memcpy((void *)&data[offset],
2360 (void *)(uint8_t *)MEMORY_ConvertMemoryMapAddress(buff2Addr, kMEMORY_DMA2Local),
2361 len - rxBdRing->rxBuffSizeAlign);
2362 #else
2363 (void)memcpy((void *)&data[offset], (void *)(uint8_t *)buff2Addr,
2364 len - rxBdRing->rxBuffSizeAlign);
2365 #endif
2366 }
2367 else
2368 {
2369 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2370 (void)memcpy((void *)&data[offset],
2371 (void *)(uint8_t *)MEMORY_ConvertMemoryMapAddress(buff1Addr, kMEMORY_DMA2Local),
2372 len);
2373 #else
2374 (void)memcpy((void *)&data[offset], (void *)(uint8_t *)buff1Addr, len);
2375 #endif
2376 }
2377
2378 result = kStatus_Success;
2379 }
2380
2381 if ((rxDesc->reserved & ENET_QOS_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
2382 {
2383 tsAvailable = true;
2384 }
2385 /* Updates the receive buffer descriptors. */
2386 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
2387 handle->rxintEnable, handle->doubleBuffEnable);
2388 /* Store the rx timestamp which is in the next buffer descriptor of the last
2389 * descriptor of a frame. */
2390 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
2391 control = rxDesc->control;
2392
2393 /* If tsAvailable is true, a context descriptor is expected but might not be yet
2394 * available.
2395 */
2396 if (tsAvailable)
2397 {
2398 uint8_t retryTimes = 10;
2399
2400 while (((control & ENET_QOS_RXDESCRIP_WR_OWN_MASK) != 0U) ||
2401 ((control & ENET_QOS_RXDESCRIP_WR_CTXT_MASK) == 0U))
2402 {
2403 SDK_DelayAtLeastUs(1U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2404 if (0U == retryTimes--)
2405 {
2406 assert(false);
2407 }
2408 control = rxDesc->control;
2409 }
2410
2411 /* Reinit for the context descriptor which has been updated by DMA. */
2412 if (NULL != ts)
2413 {
2414 ENET_QOS_StoreRxFrameTime(base, handle, rxDesc, ts);
2415 }
2416
2417 if (!handle->doubleBuffEnable)
2418 {
2419 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
2420 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
2421 handle->doubleBuffEnable);
2422 }
2423 else
2424 {
2425 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
2426 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
2427 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
2428 handle->rxintEnable, handle->doubleBuffEnable);
2429 }
2430 rxBdRing->rxGenIdx = ENET_QOS_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
2431 }
2432 }
2433 else
2434 {
2435 /* Store a frame on several buffer descriptors. */
2436 isLastBuff = false;
2437 /* Length check. */
2438 if (offset >= length)
2439 {
2440 /* Updates the receive buffer descriptors. */
2441 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
2442 handle->rxintEnable, handle->doubleBuffEnable);
2443 break;
2444 }
2445
2446 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2447 (void)memcpy((void *)&data[offset],
2448 (void *)(uint8_t *)MEMORY_ConvertMemoryMapAddress(buff1Addr, kMEMORY_DMA2Local),
2449 rxBdRing->rxBuffSizeAlign);
2450 #else
2451 (void)memcpy((void *)&data[offset], (void *)(uint8_t *)buff1Addr, rxBdRing->rxBuffSizeAlign);
2452 #endif
2453
2454 offset += rxBdRing->rxBuffSizeAlign;
2455 if (buff2Addr != 0U)
2456 {
2457 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2458 (void)memcpy((void *)&data[offset],
2459 (void *)(uint8_t *)MEMORY_ConvertMemoryMapAddress(buff2Addr, kMEMORY_DMA2Local),
2460 rxBdRing->rxBuffSizeAlign);
2461 #else
2462 (void)memcpy((void *)&data[offset], (void *)(uint8_t *)buff2Addr, rxBdRing->rxBuffSizeAlign);
2463 #endif
2464 offset += rxBdRing->rxBuffSizeAlign;
2465 }
2466
2467 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
2468 handle->rxintEnable, handle->doubleBuffEnable);
2469 }
2470 }
2471
2472 /* Always try to start receive, in case it had stopped */
2473 rxDescTail = (uint32_t)(uintptr_t)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
2474 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2475 rxDescTail = MEMORY_ConvertMemoryMapAddress(rxDescTail, kMEMORY_Local2DMA);
2476 #endif
2477 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = rxDescTail;
2478 base->DMA_CH[channel].DMA_CHX_RX_CTRL |= ENET_QOS_DMA_CHX_RX_CTRL_SR_MASK;
2479 }
2480
2481 return result;
2482 }
2483
2484 /*!
2485 * brief Updates the buffers and the own status for a given rx descriptor.
2486 * This function is a low level functional API to Updates the
2487 * buffers and the own status for a given rx descriptor.
2488 *
2489 * param rxDesc The given rx descriptor.
2490 * param buffer1 The first buffer address in the descriptor.
2491 * param buffer2 The second buffer address in the descriptor.
2492 * param intEnable Interrupt enable flag.
2493 * param doubleBuffEnable The double buffer enable flag.
2494 *
2495 * note This must be called after all the ENET initilization.
2496 * And should be called when the ENET receive/transmit is required.
2497 */
ENET_QOS_UpdateRxDescriptor(enet_qos_rx_bd_struct_t * rxDesc,void * buffer1,void * buffer2,bool intEnable,bool doubleBuffEnable)2498 void ENET_QOS_UpdateRxDescriptor(
2499 enet_qos_rx_bd_struct_t *rxDesc, void *buffer1, void *buffer2, bool intEnable, bool doubleBuffEnable)
2500 {
2501 assert(rxDesc != NULL);
2502 uint32_t control = ENET_QOS_RXDESCRIP_RD_OWN_MASK | ENET_QOS_RXDESCRIP_RD_BUFF1VALID_MASK;
2503
2504 if (intEnable)
2505 {
2506 control |= ENET_QOS_RXDESCRIP_RD_IOC_MASK;
2507 }
2508
2509 if (doubleBuffEnable)
2510 {
2511 control |= ENET_QOS_RXDESCRIP_RD_BUFF2VALID_MASK;
2512 }
2513
2514 /* Update the buffer if needed. */
2515 if (buffer1 != NULL)
2516 {
2517 rxDesc->buff1Addr = (uint32_t)(uintptr_t)(uint8_t *)buffer1;
2518 }
2519 if (buffer2 != NULL)
2520 {
2521 rxDesc->buff2Addr = (uint32_t)(uintptr_t)(uint8_t *)buffer2;
2522 }
2523 else
2524 {
2525 rxDesc->buff2Addr = 0;
2526 }
2527
2528 rxDesc->reserved = 0;
2529
2530 /* Add a data barrier to be sure that the address is written before the
2531 ownership bit status. */
2532 __DMB();
2533
2534 rxDesc->control = control;
2535 }
2536
2537 /*!
2538 * brief Setup a given tx descriptor.
2539 * This function is a low level functional API to setup or prepare
2540 * a given tx descriptor.
2541 *
2542 * param txDesc The given tx descriptor.
2543 * param buffer1 The first buffer address in the descriptor.
2544 * param bytes1 The bytes in the fist buffer.
2545 * param buffer2 The second buffer address in the descriptor.
2546 * param bytes1 The bytes in the second buffer.
2547 * param framelen The length of the frame to be transmitted.
2548 * param intEnable Interrupt enable flag.
2549 * param tsEnable The timestamp enable.
2550 * param flag The flag of this tx desciriptor, see "enet_qos_desc_flag" .
2551 * param slotNum The slot num used for AV only.
2552 *
2553 * note This must be called after all the ENET initilization.
2554 * And should be called when the ENET receive/transmit is required.
2555 * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
2556 * memory until the packet has been fully transmitted. The buffers
2557 * should be free or requeued in the transmit interrupt irq handler.
2558 */
ENET_QOS_SetupTxDescriptor(enet_qos_tx_bd_struct_t * txDesc,void * buffer1,uint32_t bytes1,void * buffer2,uint32_t bytes2,uint32_t framelen,bool intEnable,bool tsEnable,enet_qos_desc_flag flag,uint8_t slotNum)2559 void ENET_QOS_SetupTxDescriptor(enet_qos_tx_bd_struct_t *txDesc,
2560 void *buffer1,
2561 uint32_t bytes1,
2562 void *buffer2,
2563 uint32_t bytes2,
2564 uint32_t framelen,
2565 bool intEnable,
2566 bool tsEnable,
2567 enet_qos_desc_flag flag,
2568 uint8_t slotNum)
2569 {
2570 uint32_t control = ENET_QOS_TXDESCRIP_RD_BL1(bytes1) | ENET_QOS_TXDESCRIP_RD_BL2(bytes2);
2571
2572 if (tsEnable)
2573 {
2574 control |= ENET_QOS_TXDESCRIP_RD_TTSE_MASK;
2575 }
2576 else
2577 {
2578 control &= ~ENET_QOS_TXDESCRIP_RD_TTSE_MASK;
2579 }
2580
2581 if (intEnable)
2582 {
2583 control |= ENET_QOS_TXDESCRIP_RD_IOC_MASK;
2584 }
2585 else
2586 {
2587 control &= ~ENET_QOS_TXDESCRIP_RD_IOC_MASK;
2588 }
2589
2590 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2591 buffer1 = (void *)(uint8_t *)MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)buffer1, kMEMORY_Local2DMA);
2592 buffer2 = (void *)(uint8_t *)MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)buffer2, kMEMORY_Local2DMA);
2593 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
2594
2595 /* Preare the descriptor for transmit. */
2596 txDesc->buff1Addr = (uint32_t)(uintptr_t)(uint8_t *)buffer1;
2597 txDesc->buff2Addr = (uint32_t)(uintptr_t)(uint8_t *)buffer2;
2598 txDesc->buffLen = control;
2599
2600 /* Make sure all fields of descriptor are written before setting ownership */
2601 __DMB();
2602
2603 control = ENET_QOS_TXDESCRIP_RD_FL(framelen) | ENET_QOS_TXDESCRIP_RD_LDFD(flag) | ENET_QOS_TXDESCRIP_RD_OWN_MASK;
2604
2605 txDesc->controlStat = control;
2606
2607 /* Make sure the descriptor is written in memory (before MAC starts checking it) */
2608 __DSB();
2609 }
2610
2611 /*!
2612 * brief Configure a given tx descriptor.
2613 * This function is a low level functional API to setup or prepare
2614 * a given tx descriptor.
2615 *
2616 * param txDesc The given tx descriptor.
2617 * param config The tx descriptor configuration.
2618 *
2619 * note This must be called after all the ENET initilization.
2620 * And should be called when the ENET receive/transmit is required.
2621 * Transmit buffers are 'zero-copy' buffers, so the buffer must remain in
2622 * memory until the packet has been fully transmitted. The buffers
2623 * should be free or requeued in the transmit interrupt irq handler.
2624 */
ENET_QOS_ConfigTxDescriptor(enet_qos_tx_bd_struct_t * txDesc,enet_qos_tx_bd_config_struct_t * config)2625 static void ENET_QOS_ConfigTxDescriptor(enet_qos_tx_bd_struct_t *txDesc, enet_qos_tx_bd_config_struct_t *config)
2626 {
2627 uint32_t control = ENET_QOS_TXDESCRIP_RD_BL1(config->bytes1) | ENET_QOS_TXDESCRIP_RD_BL2(config->bytes2);
2628
2629 if (config->tsEnable)
2630 {
2631 control |= ENET_QOS_TXDESCRIP_RD_TTSE_MASK;
2632 }
2633 else
2634 {
2635 control &= ~ENET_QOS_TXDESCRIP_RD_TTSE_MASK;
2636 }
2637
2638 if (config->intEnable)
2639 {
2640 control |= ENET_QOS_TXDESCRIP_RD_IOC_MASK;
2641 }
2642 else
2643 {
2644 control &= ~ENET_QOS_TXDESCRIP_RD_IOC_MASK;
2645 }
2646
2647 /* Preare the descriptor for transmit. */
2648 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2649 txDesc->buff1Addr = MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)config->buffer1, kMEMORY_Local2DMA);
2650 txDesc->buff2Addr = MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)config->buffer2, kMEMORY_Local2DMA);
2651 #else
2652 txDesc->buff1Addr = (uint32_t)(uintptr_t)(uint8_t *)config->buffer1;
2653 txDesc->buff2Addr = (uint32_t)(uintptr_t)(uint8_t *)config->buffer2;
2654 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
2655 txDesc->buffLen = control;
2656
2657 /* Make sure all fields of descriptor are written before setting ownership */
2658 __DMB();
2659
2660 control = ENET_QOS_TXDESCRIP_RD_FL(config->framelen) | ENET_QOS_TXDESCRIP_RD_CIC(config->txOffloadOps) |
2661 ENET_QOS_TXDESCRIP_RD_LDFD(config->flag) | ENET_QOS_TXDESCRIP_RD_OWN_MASK;
2662
2663 txDesc->controlStat = control;
2664
2665 /* Make sure the descriptor is written in memory (before MAC starts checking it) */
2666 __DSB();
2667 }
2668
2669 /*!
2670 * brief Reclaim tx descriptors.
2671 * This function is used to update the tx descriptor status and
2672 * store the tx timestamp when the 1588 feature is enabled.
2673 * This is called by the transmit interupt IRQ handler after the
2674 * complete of a frame transmission.
2675 *
2676 * param base ENET peripheral base address.
2677 * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_QOS_Init.
2678 * param channel The tx DMA channnel.
2679 *
2680 */
ENET_QOS_ReclaimTxDescriptor(ENET_QOS_Type * base,enet_qos_handle_t * handle,uint8_t channel)2681 void ENET_QOS_ReclaimTxDescriptor(ENET_QOS_Type *base, enet_qos_handle_t *handle, uint8_t channel)
2682 {
2683 enet_qos_tx_bd_ring_t *txBdRing = &handle->txBdRing[channel];
2684 enet_qos_tx_bd_struct_t *txDesc = &txBdRing->txBdBase[txBdRing->txConsumIdx];
2685 enet_qos_tx_dirty_ring_t *txDirtyRing = (enet_qos_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2686 enet_qos_frame_info_t *txDirty = NULL;
2687 uint32_t control, primask;
2688
2689 control = txDesc->controlStat;
2690
2691 /* Need to update the first index for transmit buffer free. */
2692 while ((txBdRing->txDescUsed > 0U) && (0U == (control & ENET_QOS_TXDESCRIP_RD_OWN_MASK)))
2693 {
2694 if ((control & ENET_QOS_TXDESCRIP_RD_LD_MASK) != 0U)
2695 {
2696 if (ENET_QOS_TxDirtyRingAvailable(txDirtyRing))
2697 {
2698 txDirty = &txDirtyRing->txDirtyBase[txBdRing->txConsumIdx];
2699 txDirtyRing->txGenIdx = ENET_QOS_IncreaseIndex(txDirtyRing->txGenIdx, txDirtyRing->txRingLen);
2700 if (txDirtyRing->txGenIdx == txDirtyRing->txConsumIdx)
2701 {
2702 txDirtyRing->isFull = true;
2703 }
2704
2705 if ((control & ENET_QOS_TXDESCRIP_WB_TTSS_MASK) != 0U)
2706 {
2707 enet_qos_ptp_time_t *ts = &txDirty->timeStamp;
2708 uint32_t nanosecond;
2709 /* Get transmit time stamp second. */
2710 nanosecond = txDesc->buff1Addr;
2711 txDirty->isTsAvail = true;
2712 if (0U == (base->MAC_TIMESTAMP_CONTROL & ENET_QOS_MAC_TIMESTAMP_CONTROL_TSCTRLSSR_MASK))
2713 {
2714 /* Binary rollover, 0.465ns accuracy. */
2715 nanosecond = (nanosecond * 465U) / 1000U;
2716 }
2717 ts->second = txDesc->buff2Addr;
2718 ts->nanosecond = nanosecond;
2719 }
2720 else
2721 {
2722 txDirty->isTsAvail = false;
2723 }
2724 }
2725 }
2726
2727 /* For tx buffer free or requeue for each descriptor.
2728 * The tx interrupt callback should free/requeue the tx buffer. */
2729 if (handle->callback != NULL)
2730 {
2731 handle->callback(base, handle, kENET_QOS_TxIntEvent, channel, handle->userData);
2732 }
2733
2734 primask = DisableGlobalIRQ();
2735 txBdRing->txDescUsed--;
2736 EnableGlobalIRQ(primask);
2737
2738 /* Update the txConsumIdx/txDesc. */
2739 txBdRing->txConsumIdx = ENET_QOS_IncreaseIndex(txBdRing->txConsumIdx, txBdRing->txRingLen);
2740 txDesc = &txBdRing->txBdBase[txBdRing->txConsumIdx];
2741 control = txDesc->controlStat;
2742 }
2743 }
2744
2745 /*!
2746 * brief Transmits an ENET frame.
2747 * note The CRC is automatically appended to the data. Input the data
2748 * to send without the CRC.
2749 *
2750 * param base ENET peripheral base address.
2751 * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_QOS_Init.
2752 * param data The data buffer provided by user to be send.
2753 * param length The length of the data to be send.
2754 * param channel Channel to send the frame, same with queue index.
2755 * param isNeedTs True means save timestamp
2756 * param context pointer to user context to be kept in the tx dirty frame information.
2757 * param txOffloadOps The Tx frame checksum offload option.
2758 * retval kStatus_Success Send frame succeed.
2759 * retval kStatus_ENET_QOS_TxFrameBusy Transmit buffer descriptor is busy under transmission.
2760 * The transmit busy happens when the data send rate is over the MAC capacity.
2761 * The waiting mechanism is recommended to be added after each call return with
2762 * kStatus_ENET_QOS_TxFrameBusy.
2763 */
ENET_QOS_SendFrame(ENET_QOS_Type * base,enet_qos_handle_t * handle,uint8_t * data,uint32_t length,uint8_t channel,bool isNeedTs,void * context,enet_qos_tx_offload_t txOffloadOps)2764 status_t ENET_QOS_SendFrame(ENET_QOS_Type *base,
2765 enet_qos_handle_t *handle,
2766 uint8_t *data,
2767 uint32_t length,
2768 uint8_t channel,
2769 bool isNeedTs,
2770 void *context,
2771 enet_qos_tx_offload_t txOffloadOps)
2772 {
2773 assert(handle != NULL);
2774 assert(data != NULL);
2775 assert(channel < handle->txQueueUse);
2776
2777 enet_qos_tx_bd_config_struct_t txDescConfig;
2778 enet_qos_tx_bd_ring_t *txBdRing;
2779 enet_qos_tx_bd_struct_t *txDesc;
2780 enet_qos_tx_dirty_ring_t *txDirtyRing;
2781 enet_qos_frame_info_t *txDirty;
2782 uint32_t primask;
2783 uint32_t txDescTail;
2784
2785 #if (!defined(FSL_FEATURE_ENET_QOS_TX_OFFLOAD_QUEUE_SUPPORT_BITMAP)) || \
2786 (FSL_FEATURE_ENET_QOS_TX_OFFLOAD_QUEUE_SUPPORT_BITMAP == 0)
2787 assert(txOffloadOps == kENET_QOS_TxOffloadDisable);
2788 #else
2789 assert((txOffloadOps == kENET_QOS_TxOffloadDisable) ||
2790 (((uint32_t)FSL_FEATURE_ENET_QOS_TX_OFFLOAD_QUEUE_SUPPORT_BITMAP & ((uint32_t)1U << channel)) != 0U));
2791 #endif /* FSL_FEATURE_ENET_QOS_TX_OFFLOAD_QUEUE_SUPPORT_BITMAP == 0 */
2792
2793 if (length > 2U * ENET_QOS_TXDESCRIP_RD_BL1_MASK)
2794 {
2795 return kStatus_ENET_QOS_TxFrameOverLen;
2796 }
2797
2798 /* Check if the DMA owns the descriptor. */
2799 txBdRing = (enet_qos_tx_bd_ring_t *)&handle->txBdRing[channel];
2800 txDesc = &txBdRing->txBdBase[txBdRing->txGenIdx];
2801 if (txBdRing->txRingLen == txBdRing->txDescUsed)
2802 {
2803 return kStatus_ENET_QOS_TxFrameBusy;
2804 }
2805
2806 txDirtyRing = (enet_qos_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2807 txDirty = &txDirtyRing->txDirtyBase[txBdRing->txGenIdx];
2808 txDirty->context = context;
2809
2810 /* Fill the descriptor. */
2811 txDescConfig.framelen = length;
2812 txDescConfig.flag = kENET_QOS_FirstLastFlag;
2813 txDescConfig.intEnable = true;
2814 txDescConfig.tsEnable = isNeedTs;
2815 txDescConfig.txOffloadOps = txOffloadOps;
2816
2817 if (length <= ENET_QOS_TXDESCRIP_RD_BL1_MASK)
2818 {
2819 txDescConfig.buffer1 = data;
2820 txDescConfig.bytes1 = length;
2821 txDescConfig.buffer2 = NULL;
2822 txDescConfig.bytes2 = 0;
2823 }
2824 else
2825 {
2826 txDescConfig.buffer1 = data;
2827 txDescConfig.bytes1 = ENET_QOS_TXDESCRIP_RD_BL1_MASK;
2828 txDescConfig.buffer2 = &data[ENET_QOS_TXDESCRIP_RD_BL1_MASK];
2829 txDescConfig.bytes2 = length - ENET_QOS_TXDESCRIP_RD_BL1_MASK;
2830 }
2831 ENET_QOS_ConfigTxDescriptor(txDesc, &txDescConfig);
2832
2833 /* Increase the index. */
2834 txBdRing->txGenIdx = ENET_QOS_IncreaseIndex(txBdRing->txGenIdx, txBdRing->txRingLen);
2835 /* Disable interrupt first and then enable interrupt to avoid the race condition. */
2836 primask = DisableGlobalIRQ();
2837 txBdRing->txDescUsed++;
2838 EnableGlobalIRQ(primask);
2839
2840 /* Update the transmit tail address. */
2841 txDesc = &txBdRing->txBdBase[txBdRing->txGenIdx];
2842 if (txBdRing->txGenIdx == 0U)
2843 {
2844 txDesc = &txBdRing->txBdBase[txBdRing->txRingLen];
2845 }
2846 txDescTail = (uint32_t)(uintptr_t)txDesc & ~ENET_QOS_ADDR_ALIGNMENT;
2847 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
2848 txDescTail = MEMORY_ConvertMemoryMapAddress(txDescTail, kMEMORY_Local2DMA);
2849 #endif
2850 base->DMA_CH[channel].DMA_CHX_TXDESC_TAIL_PTR = txDescTail;
2851
2852 return kStatus_Success;
2853 }
2854
2855 /*!
2856 * brief Gets the sent frame.
2857 *
2858 * This function is used to get the sent frame for timestamp and buffer clean operation.
2859 *
2860 * param handle The ENET handler pointer.This is the same state pointer used in
2861 * ENET_QOS_Init.
2862 * param txFrame Input parameter, pointer to enet_qos_frame_info_t for saving read out frame information.
2863 * param channel Read out frame from specified channel.
2864 */
ENET_QOS_GetTxFrame(enet_qos_handle_t * handle,enet_qos_frame_info_t * txFrame,uint8_t channel)2865 void ENET_QOS_GetTxFrame(enet_qos_handle_t *handle, enet_qos_frame_info_t *txFrame, uint8_t channel)
2866 {
2867 assert(handle != NULL);
2868 assert(channel < handle->txQueueUse);
2869
2870 enet_qos_tx_dirty_ring_t *txDirtyRing = (enet_qos_tx_dirty_ring_t *)&handle->txDirtyRing[channel];
2871 enet_qos_frame_info_t *txDirty = &txDirtyRing->txDirtyBase[txDirtyRing->txConsumIdx];
2872
2873 (void)memcpy(txFrame, txDirty, sizeof(enet_qos_frame_info_t));
2874
2875 txDirtyRing->isFull = false;
2876 txDirtyRing->txConsumIdx = ENET_QOS_IncreaseIndex(txDirtyRing->txConsumIdx, txDirtyRing->txRingLen);
2877 }
2878
ENET_QOS_GetRxFrameErr(enet_qos_rx_bd_struct_t * rxDesc,enet_qos_rx_frame_error_t * rxFrameError)2879 static inline void ENET_QOS_GetRxFrameErr(enet_qos_rx_bd_struct_t *rxDesc, enet_qos_rx_frame_error_t *rxFrameError)
2880 {
2881 uint32_t rdes2 = rxDesc->buff2Addr;
2882 uint32_t rdes3 = rxDesc->control;
2883
2884 (void)memset(rxFrameError, 0, sizeof(enet_qos_rx_frame_error_t));
2885
2886 if ((rdes2 & ENET_QOS_RXDESCRIP_WR_SA_FAILURE_MASK) != 0U)
2887 {
2888 rxFrameError->rxSrcAddrFilterErr = true;
2889 }
2890 if ((rdes2 & ENET_QOS_RXDESCRIP_WR_DA_FAILURE_MASK) != 0U)
2891 {
2892 rxFrameError->rxDstAddrFilterErr = true;
2893 }
2894 if ((rdes3 & ENET_QOS_RXDESCRIP_WR_DE_MASK) != 0U)
2895 {
2896 rxFrameError->rxDstAddrFilterErr = true;
2897 }
2898 if ((rdes3 & ENET_QOS_RXDESCRIP_WR_RE_MASK) != 0U)
2899 {
2900 rxFrameError->rxReceiveErr = true;
2901 }
2902 if ((rdes3 & ENET_QOS_RXDESCRIP_WR_OE_MASK) != 0U)
2903 {
2904 rxFrameError->rxOverFlowErr = true;
2905 }
2906 if ((rdes3 & ENET_QOS_RXDESCRIP_WR_RWT_MASK) != 0U)
2907 {
2908 rxFrameError->rxWatchDogErr = true;
2909 }
2910 if ((rdes3 & ENET_QOS_RXDESCRIP_WR_GP_MASK) != 0U)
2911 {
2912 rxFrameError->rxGaintPacketErr = true;
2913 }
2914 if ((rdes3 & ENET_QOS_RXDESCRIP_WR_CRC_MASK) != 0U)
2915 {
2916 rxFrameError->rxCrcErr = true;
2917 }
2918 }
2919
2920 /*!
2921 * brief Receives one frame in specified BD ring with zero copy.
2922 *
2923 * This function will use the user-defined allocate and free callback. Every time application gets one frame through
2924 * this function, driver will allocate new buffers for the BDs whose buffers have been taken by application.
2925 * note This function will drop current frame and update related BDs as available for DMA if new buffers allocating
2926 * fails. Application must provide a memory pool including at least BD number + 1 buffers(+2 if enable double buffer)
2927 * to make this function work normally. If user calls this function in Rx interrupt handler, be careful that this
2928 * function makes Rx BD ready with allocating new buffer(normal) or updating current BD(out of memory). If there's
2929 * always new Rx frame input, Rx interrupt will be triggered forever. Application need to disable Rx interrupt according
2930 * to specific design in this case.
2931 *
2932 * param base ENET peripheral base address.
2933 * param handle The ENET handler pointer. This is the same handler pointer used in the ENET_Init.
2934 * param rxFrame The received frame information structure provided by user.
2935 * param ringId The ring index or ring number.
2936 * retval kStatus_Success Succeed to get one frame and allocate new memory for Rx buffer.
2937 * retval kStatus_ENET_QOS_RxFrameEmpty There's no Rx frame in the BD.
2938 * retval kStatus_ENET_QOS_RxFrameError There's issue in this receiving.
2939 * retval kStatus_ENET_QOS_RxFrameDrop There's no new buffer memory for BD, drop this frame.
2940 */
ENET_QOS_GetRxFrame(ENET_QOS_Type * base,enet_qos_handle_t * handle,enet_qos_rx_frame_struct_t * rxFrame,uint8_t channel)2941 status_t ENET_QOS_GetRxFrame(ENET_QOS_Type *base,
2942 enet_qos_handle_t *handle,
2943 enet_qos_rx_frame_struct_t *rxFrame,
2944 uint8_t channel)
2945 {
2946 assert(handle != NULL);
2947 assert(channel < handle->rxQueueUse);
2948
2949 enet_qos_rx_bd_ring_t *rxBdRing = (enet_qos_rx_bd_ring_t *)&handle->rxBdRing[channel];
2950 enet_qos_rx_bd_struct_t *rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
2951 uint16_t index = rxBdRing->rxGenIdx;
2952 status_t result = kStatus_Success;
2953 uintptr_t buff1Addr = 0;
2954 uintptr_t buff2Addr = 0;
2955 uint16_t buff1Len = 0;
2956 uint16_t buff2Len = 0;
2957 uint16_t offset = 0;
2958 void *newBuff1 = NULL;
2959 void *newBuff2 = NULL;
2960 bool isDrop = false;
2961 bool isLastBuff = false;
2962 bool tsAvailable = false;
2963 uint32_t rxDescTail;
2964
2965 /* Check the frame status. */
2966 do
2967 {
2968 if ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_OWN_MASK) != 0U)
2969 {
2970 /* There is at least one buffer owned by DMA. Make sure reception is enabled. */
2971 base->DMA_CH[channel].DMA_CHX_RX_CTRL |= ENET_QOS_DMA_CHX_RX_CTRL_SR_MASK;
2972
2973 result = kStatus_ENET_QOS_RxFrameEmpty;
2974 break;
2975 }
2976
2977 /* Check timestamp and error. */
2978 if ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_LD_MASK) != 0U)
2979 {
2980 if ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_RS1V_MASK) != 0U)
2981 {
2982 if ((rxDesc->reserved & ENET_QOS_RXDESCRIP_WR_PTPTSA_MASK) != 0U)
2983 {
2984 /* Context descriptor is expected but might not be yet available. */
2985 uint8_t retryTimes = 10;
2986
2987 while (((rxDesc->control & ENET_QOS_RXDESCRIP_WR_OWN_MASK) != 0U) ||
2988 ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_CTXT_MASK) == 0U))
2989 {
2990 /* Timsstamp value is not corrupted. */
2991 if ((rxDesc->buff1Addr != 0xFFFFFFFFU) && (rxDesc->buff2Addr != 0xFFFFFFFFU))
2992 {
2993 break;
2994 }
2995 if (retryTimes-- == 0U)
2996 {
2997 break;
2998 }
2999 }
3000
3001 if (retryTimes != 0U)
3002 {
3003 tsAvailable = true;
3004 }
3005 else
3006 {
3007 result = kStatus_ENET_QOS_RxFrameEmpty;
3008 break;
3009 }
3010 }
3011 }
3012
3013 /* Get the frame error if there is. */
3014 if ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_ERRSUM_MASK) != 0U)
3015 {
3016 ENET_QOS_GetRxFrameErr(rxDesc, &rxFrame->rxFrameError);
3017 result = kStatus_ENET_QOS_RxFrameError;
3018 }
3019 else if ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_PACKETLEN_MASK) == 0U)
3020 {
3021 result = kStatus_ENET_QOS_RxFrameEmpty;
3022 }
3023 else
3024 {
3025 /* Intentional empty */
3026 }
3027 break;
3028 }
3029
3030 index = ENET_QOS_IncreaseIndex(index, rxBdRing->rxRingLen);
3031 if (index == rxBdRing->rxGenIdx)
3032 {
3033 result = kStatus_ENET_QOS_RxFrameEmpty;
3034 break;
3035 }
3036 rxDesc = &rxBdRing->rxBdBase[index];
3037 } while (index != rxBdRing->rxGenIdx);
3038
3039 /* Drop the error frame and return error. */
3040 if (result != kStatus_Success)
3041 {
3042 if (result == kStatus_ENET_QOS_RxFrameError)
3043 {
3044 ENET_QOS_DropFrame(base, handle, channel);
3045 }
3046 return result;
3047 }
3048
3049 /* Get the valid frame */
3050 index = 0;
3051 do
3052 {
3053 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
3054
3055 /* Caculate the buffer and frame length. */
3056 if ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_LD_MASK) != 0U)
3057 {
3058 isLastBuff = true;
3059 rxFrame->totLen = (uint16_t)(rxDesc->control & ENET_QOS_RXDESCRIP_WR_PACKETLEN_MASK);
3060
3061 if (rxFrame->totLen - offset > (uint16_t)rxBdRing->rxBuffSizeAlign)
3062 {
3063 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
3064 if (handle->doubleBuffEnable)
3065 {
3066 buff2Len = rxFrame->totLen - offset - (uint16_t)rxBdRing->rxBuffSizeAlign - ENET_QOS_FCS_LEN;
3067 }
3068 }
3069 else
3070 {
3071 buff1Len = rxFrame->totLen - offset - ENET_QOS_FCS_LEN;
3072 }
3073 rxFrame->totLen -= ENET_QOS_FCS_LEN;
3074 }
3075 else
3076 {
3077 if (!handle->doubleBuffEnable)
3078 {
3079 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
3080 offset += buff1Len;
3081 }
3082 else
3083 {
3084 buff1Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
3085 buff2Len = (uint16_t)rxBdRing->rxBuffSizeAlign;
3086 offset += buff1Len + buff2Len;
3087 }
3088 }
3089
3090 /* Allocate new buffer to replace the buffer taken by application */
3091 newBuff1 = handle->rxBuffAlloc(base, handle->userData, channel);
3092 if (newBuff1 == NULL)
3093 {
3094 isDrop = true;
3095 }
3096 else if (handle->doubleBuffEnable && (buff2Len != 0U))
3097 {
3098 newBuff2 = handle->rxBuffAlloc(base, handle->userData, channel);
3099 if (newBuff2 == NULL)
3100 {
3101 handle->rxBuffFree(base, newBuff1, handle->userData, channel);
3102 isDrop = true;
3103 }
3104 }
3105 else
3106 {
3107 /* Intentional empty */
3108 }
3109
3110 if (!isDrop)
3111 {
3112 /* Get the frame data information into Rx frame structure. */
3113 if (!handle->doubleBuffEnable)
3114 {
3115 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
3116 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
3117 buff1Addr = MEMORY_ConvertMemoryMapAddress(buff1Addr, kMEMORY_DMA2Local);
3118 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
3119 if (handle->rxMaintainEnable[channel])
3120 {
3121 ENET_QOS_DcacheInvalidateByRange(buff1Addr, rxBdRing->rxBuffSizeAlign);
3122 }
3123 rxFrame->rxBuffArray[index].buffer = (void *)(uint8_t *)buff1Addr;
3124 rxFrame->rxBuffArray[index].length = buff1Len;
3125 index++;
3126 }
3127 else
3128 {
3129 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
3130 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
3131 buff1Addr = MEMORY_ConvertMemoryMapAddress(buff1Addr, kMEMORY_DMA2Local);
3132 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
3133 if (handle->rxMaintainEnable[channel])
3134 {
3135 ENET_QOS_DcacheInvalidateByRange(buff1Addr, rxBdRing->rxBuffSizeAlign);
3136 }
3137 rxFrame->rxBuffArray[index].buffer = (void *)(uint8_t *)buff1Addr;
3138 rxFrame->rxBuffArray[index].length = buff1Len;
3139 index++;
3140
3141 /* If there's no data in buffer2, not add it into rxFrame */
3142 if (buff2Len != 0U)
3143 {
3144 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
3145 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
3146 buff2Addr = MEMORY_ConvertMemoryMapAddress(buff2Addr, kMEMORY_DMA2Local);
3147 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
3148 if (handle->rxMaintainEnable[channel])
3149 {
3150 ENET_QOS_DcacheInvalidateByRange(buff2Addr, rxBdRing->rxBuffSizeAlign);
3151 }
3152 rxFrame->rxBuffArray[index].buffer = (void *)(uint8_t *)buff2Addr;
3153 rxFrame->rxBuffArray[index].length = buff2Len;
3154 index++;
3155 }
3156 }
3157
3158 /* Give new buffer from application to BD */
3159 if (!handle->doubleBuffEnable)
3160 {
3161 if (handle->rxMaintainEnable[channel])
3162 {
3163 ENET_QOS_DcacheInvalidateByRange((uintptr_t)(uint8_t *)newBuff1, rxBdRing->rxBuffSizeAlign);
3164 }
3165 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
3166 buff1Addr = MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)newBuff1, kMEMORY_Local2DMA);
3167 #else
3168 buff1Addr = (uintptr_t)(uint8_t *)newBuff1;
3169 #endif
3170 handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx] = buff1Addr;
3171 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
3172 handle->doubleBuffEnable);
3173 }
3174 else
3175 {
3176 if (handle->rxMaintainEnable[channel])
3177 {
3178 ENET_QOS_DcacheInvalidateByRange((uintptr_t)(uint8_t *)newBuff1, rxBdRing->rxBuffSizeAlign);
3179 }
3180 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
3181 buff1Addr = MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)newBuff1, kMEMORY_Local2DMA);
3182 #else
3183 buff1Addr = (uintptr_t)(uint8_t *)newBuff1;
3184 #endif
3185 handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx] = buff1Addr;
3186
3187 if (buff2Len != 0U)
3188 {
3189 if (handle->rxMaintainEnable[channel])
3190 {
3191 ENET_QOS_DcacheInvalidateByRange((uintptr_t)(uint8_t *)newBuff2, rxBdRing->rxBuffSizeAlign);
3192 }
3193 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
3194 buff2Addr =
3195 (uint32_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)newBuff2, kMEMORY_Local2DMA);
3196 #else
3197 buff2Addr = (uintptr_t)(uint8_t *)newBuff2;
3198 #endif
3199 handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U] = buff2Addr;
3200 }
3201 else
3202 {
3203 /* If there's no data in buffer2, keep it */
3204 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
3205 }
3206
3207 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
3208 handle->rxintEnable, handle->doubleBuffEnable);
3209 }
3210 rxBdRing->rxGenIdx = ENET_QOS_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
3211
3212 /* Update context BD if there is */
3213 if (isLastBuff && tsAvailable)
3214 {
3215 rxDesc = &rxBdRing->rxBdBase[rxBdRing->rxGenIdx];
3216 if ((rxDesc->control & ENET_QOS_RXDESCRIP_WR_CTXT_MASK) != 0U)
3217 {
3218 ENET_QOS_StoreRxFrameTime(base, handle, rxDesc, &rxFrame->rxAttribute.timestamp);
3219 rxFrame->rxAttribute.isTsAvail = true;
3220
3221 if (!handle->doubleBuffEnable)
3222 {
3223 buff1Addr = handle->rxBufferStartAddr[channel][rxBdRing->rxGenIdx];
3224 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, NULL, handle->rxintEnable,
3225 handle->doubleBuffEnable);
3226 }
3227 else
3228 {
3229 buff1Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx];
3230 buff2Addr = handle->rxBufferStartAddr[channel][2U * rxBdRing->rxGenIdx + 1U];
3231 ENET_QOS_UpdateRxDescriptor(rxDesc, (void *)(uint8_t *)buff1Addr, (void *)(uint8_t *)buff2Addr,
3232 handle->rxintEnable, handle->doubleBuffEnable);
3233 }
3234 rxBdRing->rxGenIdx = ENET_QOS_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
3235 }
3236 }
3237 /* Always try to start receive, in case it had stopped */
3238 rxDescTail = (uint32_t)(uintptr_t)&rxBdRing->rxBdBase[rxBdRing->rxRingLen];
3239 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
3240 rxDescTail = MEMORY_ConvertMemoryMapAddress(rxDescTail, kMEMORY_Local2DMA);
3241 #endif
3242 base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = rxDescTail;
3243 base->DMA_CH[channel].DMA_CHX_RX_CTRL |= ENET_QOS_DMA_CHX_RX_CTRL_SR_MASK;
3244 }
3245 else
3246 {
3247 /* Drop frame if there's no new buffer memory */
3248
3249 /* Free the incomplete frame buffers. */
3250 while (index-- != 0U)
3251 {
3252 handle->rxBuffFree(base, rxFrame->rxBuffArray[index].buffer, handle->userData, channel);
3253 }
3254
3255 /* Update all left BDs of this frame from current index. */
3256 ENET_QOS_DropFrame(base, handle, channel);
3257
3258 result = kStatus_ENET_QOS_RxFrameDrop;
3259 break;
3260 }
3261 } while (!isLastBuff);
3262
3263 return result;
3264 }
3265
3266 /*!
3267 * brief Gets the current ENET time from the PTP 1588 timer without IRQ disable.
3268 *
3269 * param base ENET peripheral base address.
3270 * param second The PTP 1588 system timer second.
3271 * param nanosecond The PTP 1588 system timer nanosecond.
3272 * For the unit of the nanosecond is 1ns. so the nanosecond is the real nanosecond.
3273 */
ENET_QOS_Ptp1588GetTimerNoIRQDisable(ENET_QOS_Type * base,uint64_t * second,uint32_t * nanosecond)3274 void ENET_QOS_Ptp1588GetTimerNoIRQDisable(ENET_QOS_Type *base, uint64_t *second, uint32_t *nanosecond)
3275 {
3276 assert(second != NULL);
3277 assert(nanosecond != NULL);
3278
3279 uint32_t high_sec[2];
3280 uint32_t sec[2];
3281
3282 /* Get the current PTP time. */
3283 /* Since register reads are not atomic, we need to check for wraps during the read */
3284 high_sec[1] = base->MAC_SYSTEM_TIME_HIGHER_WORD_SECONDS & ENET_QOS_MAC_SYSTEM_TIME_HIGHER_WORD_SECONDS_TSHWR_MASK;
3285
3286 do
3287 {
3288 high_sec[0] = high_sec[1];
3289
3290 sec[1] = base->MAC_SYSTEM_TIME_SECONDS;
3291
3292 do
3293 {
3294 sec[0] = sec[1];
3295 *nanosecond = base->MAC_SYSTEM_TIME_NANOSECONDS & ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_TSSS_MASK;
3296 sec[1] = base->MAC_SYSTEM_TIME_SECONDS;
3297 } while (sec[1] != sec[0]);
3298
3299 high_sec[1] =
3300 base->MAC_SYSTEM_TIME_HIGHER_WORD_SECONDS & ENET_QOS_MAC_SYSTEM_TIME_HIGHER_WORD_SECONDS_TSHWR_MASK;
3301 } while (high_sec[1] != high_sec[0]);
3302
3303 *second = ((uint64_t)high_sec[1] << 32U) | sec[1];
3304
3305 if ((base->MAC_TIMESTAMP_CONTROL & ENET_QOS_MAC_TIMESTAMP_CONTROL_TSCTRLSSR_MASK) == 0U)
3306 {
3307 /* Binary rollover, the unit of the increment is ~ 0.465 ns. */
3308 *nanosecond = (*nanosecond * 465U) / 1000U;
3309 }
3310 }
3311
3312 /*!
3313 * brief Gets the current ENET time from the PTP 1588 timer, get a more accurate value
3314 * with IRQ disabled during get timer.
3315 *
3316 * param base ENET peripheral base address.
3317 * param second The PTP 1588 system timer second.
3318 * param nanosecond The PTP 1588 system timer nanosecond.
3319 * For the unit of the nanosecond is 1ns. so the nanosecond is the real nanosecond.
3320 */
ENET_QOS_Ptp1588GetTimer(ENET_QOS_Type * base,uint64_t * second,uint32_t * nanosecond)3321 void ENET_QOS_Ptp1588GetTimer(ENET_QOS_Type *base, uint64_t *second, uint32_t *nanosecond)
3322 {
3323 uint32_t primask;
3324
3325 /* Disables the interrupt. */
3326 primask = DisableGlobalIRQ();
3327
3328 ENET_QOS_Ptp1588GetTimerNoIRQDisable(base, second, nanosecond);
3329
3330 /* Enables the interrupt. */
3331 EnableGlobalIRQ(primask);
3332 }
3333
3334 /*!
3335 * brief Coreect the ENET PTP 1588 timer in coarse method.
3336 *
3337 * param base ENET peripheral base address.
3338 * param operation The system time operation, refer to "enet_qos_systime_op"
3339 * param second The correction second.
3340 * param nanosecond The correction nanosecond.
3341 */
ENET_QOS_Ptp1588CorrectTimerInCoarse(ENET_QOS_Type * base,enet_qos_systime_op operation,uint32_t second,uint32_t nanosecond)3342 status_t ENET_QOS_Ptp1588CorrectTimerInCoarse(ENET_QOS_Type *base,
3343 enet_qos_systime_op operation,
3344 uint32_t second,
3345 uint32_t nanosecond)
3346 {
3347 uint32_t corrSecond = second;
3348 uint32_t corrNanosecond;
3349 status_t result = kStatus_Success;
3350
3351 /* Set the system timer. */
3352 if ((base->MAC_TIMESTAMP_CONTROL & ENET_QOS_MAC_TIMESTAMP_CONTROL_TSCTRLSSR_MASK) != 0U)
3353 {
3354 if (operation == kENET_QOS_SystimeSubtract)
3355 {
3356 /* Set with the complement of the sub-second. */
3357 corrSecond = ENET_QOS_MAC_SYSTEM_TIME_SECONDS_UPDATE_TSS_MASK - (second - 1U);
3358 corrNanosecond = ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_ADDSUB_MASK |
3359 ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_TSSS(ENET_QOS_NANOSECS_ONESECOND - nanosecond);
3360 }
3361 else
3362 {
3363 corrNanosecond = ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_TSSS(nanosecond);
3364 }
3365 }
3366 else
3367 {
3368 nanosecond = ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_TSSS_MASK / ENET_QOS_NANOSECS_ONESECOND * nanosecond;
3369 if (operation == kENET_QOS_SystimeSubtract)
3370 {
3371 /* Set with the complement of the sub-second. */
3372 corrSecond = ENET_QOS_MAC_SYSTEM_TIME_SECONDS_UPDATE_TSS_MASK - (second - 1U);
3373 corrNanosecond = ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_ADDSUB_MASK |
3374 ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_TSSS(
3375 ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_TSSS_MASK + 1U - nanosecond);
3376 }
3377 else
3378 {
3379 corrNanosecond = ENET_QOS_MAC_SYSTEM_TIME_NANOSECONDS_UPDATE_TSSS(nanosecond);
3380 }
3381 }
3382
3383 base->MAC_SYSTEM_TIME_SECONDS_UPDATE = corrSecond;
3384 base->MAC_SYSTEM_TIME_NANOSECONDS_UPDATE = corrNanosecond;
3385
3386 /* Update the timer. */
3387 base->MAC_TIMESTAMP_CONTROL |= ENET_QOS_MAC_TIMESTAMP_CONTROL_TSUPDT_MASK;
3388
3389 /* Wait for update finish */
3390 result = ENET_QOS_PollStatusFlag(&(base->MAC_TIMESTAMP_CONTROL), ENET_QOS_MAC_TIMESTAMP_CONTROL_TSUPDT_MASK, 0U);
3391
3392 return result;
3393 }
3394
3395 /*!
3396 * brief Correct the ENET PTP 1588 timer in fine method.
3397 *
3398 *
3399 * param base ENET peripheral base address.
3400 * param addend The addend value to be set in the fine method
3401 * note Should take refer to the chapter "System time correction" and
3402 * see the description for the "fine correction method".
3403 */
ENET_QOS_Ptp1588CorrectTimerInFine(ENET_QOS_Type * base,uint32_t addend)3404 status_t ENET_QOS_Ptp1588CorrectTimerInFine(ENET_QOS_Type *base, uint32_t addend)
3405 {
3406 status_t result = kStatus_Success;
3407
3408 base->MAC_TIMESTAMP_ADDEND = addend;
3409 base->MAC_TIMESTAMP_CONTROL |= ENET_QOS_MAC_TIMESTAMP_CONTROL_TSADDREG_MASK;
3410
3411 result = ENET_QOS_PollStatusFlag(&(base->MAC_TIMESTAMP_CONTROL), ENET_QOS_MAC_TIMESTAMP_CONTROL_TSADDREG_MASK, 0U);
3412
3413 return result;
3414 }
3415
3416 /*!
3417 * @brief Sets the ENET OQS PTP 1588 PPS target time registers.
3418 *
3419 * param base ENET QOS peripheral base address.
3420 * param instance The ENET QOS PTP PPS instance.
3421 * param seconds The target seconds.
3422 * param nanoseconds The target nanoseconds.
3423 */
ENET_QOS_Ptp1588PpsSetTrgtTime(ENET_QOS_Type * base,enet_qos_ptp_pps_instance_t instance,uint32_t seconds,uint32_t nanoseconds)3424 status_t ENET_QOS_Ptp1588PpsSetTrgtTime(ENET_QOS_Type *base,
3425 enet_qos_ptp_pps_instance_t instance,
3426 uint32_t seconds,
3427 uint32_t nanoseconds)
3428 {
3429 uint32_t *mac_pps_trgt_ns;
3430 uint32_t *mac_pps_trgt_s;
3431
3432 mac_pps_trgt_ns = (uint32_t *)((uintptr_t)&base->MAC_PPS0_TARGET_TIME_NANOSECONDS + 0x10U * (uint32_t)instance);
3433 mac_pps_trgt_s = (uint32_t *)((uintptr_t)&base->MAC_PPS0_TARGET_TIME_SECONDS + 0x10U * (uint32_t)instance);
3434
3435 if ((*mac_pps_trgt_ns & ENET_QOS_MAC_PPS0_TARGET_TIME_NANOSECONDS_TRGTBUSY0_MASK) != 0U)
3436 {
3437 return kStatus_ENET_QOS_TrgtBusy;
3438 }
3439
3440 *mac_pps_trgt_ns = ENET_QOS_MAC_PPS0_TARGET_TIME_NANOSECONDS_TTSL0(nanoseconds);
3441 *mac_pps_trgt_s = ENET_QOS_MAC_PPS0_TARGET_TIME_SECONDS_TSTRH0(seconds);
3442
3443 return kStatus_Success;
3444 }
3445
ENET_QOS_EstReadWriteWord(ENET_QOS_Type * base,uint32_t addr,uint32_t * data,uint8_t gcrr,uint8_t read,uint8_t dbgm)3446 static status_t ENET_QOS_EstReadWriteWord(
3447 ENET_QOS_Type *base, uint32_t addr, uint32_t *data, uint8_t gcrr, uint8_t read, uint8_t dbgm)
3448 {
3449 uint32_t ctrl;
3450 int retry = 10;
3451
3452 ctrl = ENET_QOS_MTL_EST_GCL_CONTROL_ADDR(addr) | ENET_QOS_MTL_EST_GCL_CONTROL_SRWO(1) |
3453 ENET_QOS_MTL_EST_GCL_CONTROL_DBGM(dbgm) | ENET_QOS_MTL_EST_GCL_CONTROL_GCRR(gcrr);
3454
3455 if (read != 0U)
3456 {
3457 ctrl |= ENET_QOS_MTL_EST_GCL_CONTROL_R1W0(1);
3458 }
3459 else
3460 {
3461 base->MTL_EST_GCL_DATA = *data;
3462 }
3463
3464 base->MTL_EST_GCL_CONTROL = ctrl;
3465
3466 while ((base->MTL_EST_GCL_CONTROL & ENET_QOS_MTL_EST_GCL_CONTROL_SRWO_MASK) != 0U)
3467 {
3468 if (retry-- < 0)
3469 {
3470 return kStatus_Timeout;
3471 }
3472 SDK_DelayAtLeastUs(1, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
3473 }
3474
3475 if (read != 0U)
3476 {
3477 *data = base->MTL_EST_GCL_DATA;
3478 }
3479
3480 if ((base->MTL_EST_GCL_CONTROL & ENET_QOS_MTL_EST_GCL_CONTROL_ERR0_MASK) != 0U)
3481 {
3482 return kStatus_ENET_QOS_Est_SwListWriteAbort;
3483 }
3484
3485 return kStatus_Success;
3486 }
3487
ENET_QOS_EstProgramWord(ENET_QOS_Type * base,uint32_t addr,uint32_t * data,uint8_t gcrr)3488 static status_t ENET_QOS_EstProgramWord(ENET_QOS_Type *base, uint32_t addr, uint32_t *data, uint8_t gcrr)
3489 {
3490 return ENET_QOS_EstReadWriteWord(base, addr, data, gcrr, 0, 0);
3491 }
3492
ENET_QOS_EstReadWord(ENET_QOS_Type * base,uint32_t addr,uint32_t * data,uint8_t gcrr,uint8_t dbgm)3493 static status_t ENET_QOS_EstReadWord(ENET_QOS_Type *base, uint32_t addr, uint32_t *data, uint8_t gcrr, uint8_t dbgm)
3494 {
3495 return ENET_QOS_EstReadWriteWord(base, addr, data, gcrr, 1, dbgm);
3496 }
3497
3498 /*!
3499 * @brief Program Gate Control List.
3500 *
3501 * This function is used to program the Enhanced Scheduled Transmisson. (IEEE802.1Qbv)
3502 *
3503 * @param base ENET peripheral base address..
3504 * @param gcl Pointer to the Gate Control List structure.
3505 * @param ptpClk_Hz frequency of the PTP clock.
3506 */
ENET_QOS_EstProgramGcl(ENET_QOS_Type * base,enet_qos_est_gcl_t * gcl,uint32_t ptpClk_Hz)3507 status_t ENET_QOS_EstProgramGcl(ENET_QOS_Type *base, enet_qos_est_gcl_t *gcl, uint32_t ptpClk_Hz)
3508 {
3509 assert(gcl != NULL);
3510 uint32_t i, control, data;
3511 enet_qos_est_gate_op_t *gateOp;
3512 status_t rc;
3513
3514 #define EST_MAX_INTERVAL ((1UL << ENET_QOS_EST_WID) - 1U)
3515 #define EST_MAX_GATE ((1UL << (32U - ENET_QOS_EST_WID)) - 1U)
3516
3517 if (!gcl->enable)
3518 {
3519 goto exit;
3520 }
3521
3522 /* Sanity checks */
3523 if (gcl->numEntries > ENET_QOS_EST_DEP)
3524 {
3525 return kStatus_ENET_QOS_Est_InvalidParameter;
3526 }
3527
3528 if (gcl->opList == NULL)
3529 {
3530 return kStatus_ENET_QOS_Est_InvalidParameter;
3531 }
3532
3533 gateOp = gcl->opList;
3534
3535 for (i = 0; i < gcl->numEntries; i++)
3536 {
3537 if (gateOp->interval > EST_MAX_INTERVAL)
3538 {
3539 return kStatus_ENET_QOS_Est_InvalidParameter;
3540 }
3541 if (gateOp->gate > EST_MAX_GATE)
3542 {
3543 return kStatus_ENET_QOS_Est_InvalidParameter;
3544 }
3545 gateOp++;
3546 }
3547
3548 /* Check if sw list is busy */
3549 if ((base->MTL_EST_CONTROL & ENET_QOS_MTL_EST_CONTROL_SSWL_MASK) != 0U)
3550 {
3551 return kStatus_ENET_QOS_Est_SwListBusy;
3552 }
3553
3554 gateOp = gcl->opList;
3555
3556 for (i = 0; i < gcl->numEntries; i++)
3557 {
3558 data = gateOp->interval | (gateOp->gate << ENET_QOS_EST_WID);
3559 rc = ENET_QOS_EstProgramWord(base, i, &data, 0);
3560 if (rc != kStatus_Success)
3561 {
3562 return rc;
3563 }
3564
3565 gateOp++;
3566 }
3567
3568 /* BTR High */
3569 data = (uint32_t)(gcl->baseTime >> 32U);
3570 rc = ENET_QOS_EstProgramWord(base, (uint32_t)kENET_QOS_Ets_btr_high, &data, 1U);
3571 if (rc != kStatus_Success)
3572 {
3573 return rc;
3574 }
3575
3576 /* BTR Low */
3577 data = (uint32_t)gcl->baseTime;
3578 rc = ENET_QOS_EstProgramWord(base, (uint32_t)kENET_QOS_Ets_btr_low, &data, 1);
3579 if (rc != kStatus_Success)
3580 {
3581 return rc;
3582 }
3583
3584 /* CTR High */
3585 data = (uint32_t)(gcl->cycleTime >> 32U);
3586 rc = ENET_QOS_EstProgramWord(base, (uint32_t)kENET_QOS_Ets_ctr_high, &data, 1);
3587 if (rc != kStatus_Success)
3588 {
3589 return rc;
3590 }
3591
3592 /* CTR Low */
3593 data = (uint32_t)gcl->cycleTime;
3594 rc = ENET_QOS_EstProgramWord(base, (uint32_t)kENET_QOS_Ets_ctr_low, &data, 1);
3595 if (rc != kStatus_Success)
3596 {
3597 return rc;
3598 }
3599
3600 /* TER */
3601 data = gcl->extTime;
3602 rc = ENET_QOS_EstProgramWord(base, (uint32_t)kENET_QOS_Ets_ter, &data, 1);
3603 if (rc != kStatus_Success)
3604 {
3605 return rc;
3606 }
3607
3608 /* LLR */
3609 data = gcl->numEntries;
3610 rc = ENET_QOS_EstProgramWord(base, (uint32_t)kENET_QOS_Ets_llr, &data, 1);
3611 if (rc != kStatus_Success)
3612 {
3613 return rc;
3614 }
3615
3616 exit:
3617 control = base->MTL_EST_CONTROL;
3618
3619 if (gcl->enable)
3620 {
3621 control &= ~ENET_QOS_MTL_EST_CONTROL_PTOV_MASK;
3622 control |= ENET_QOS_MTL_EST_CONTROL_SSWL_MASK | ENET_QOS_MTL_EST_CONTROL_EEST_MASK |
3623 ENET_QOS_MTL_EST_CONTROL_PTOV((1000000000U / ptpClk_Hz) * 6U);
3624 }
3625 else
3626 {
3627 control &= ~ENET_QOS_MTL_EST_CONTROL_EEST_MASK;
3628 }
3629
3630 base->MTL_EST_CONTROL = control;
3631
3632 return kStatus_Success;
3633 }
3634
3635 /*!
3636 * @brief Read Gate Control List.
3637 *
3638 * This function is used to read the Enhanced Scheduled Transmisson list. (IEEE802.1Qbv)
3639 *
3640 * @param base ENET peripheral base address..
3641 * @param gcl Pointer to the Gate Control List structure.
3642 * @param listLen length of the provided opList array in gcl structure.
3643 * @param hwList Boolean if True read HW list, false read SW list.
3644 */
ENET_QOS_EstReadGcl(ENET_QOS_Type * base,enet_qos_est_gcl_t * gcl,uint32_t listLen,bool hwList)3645 status_t ENET_QOS_EstReadGcl(ENET_QOS_Type *base, enet_qos_est_gcl_t *gcl, uint32_t listLen, bool hwList)
3646 {
3647 assert(gcl != NULL);
3648 assert(gcl->opList != NULL);
3649 uint8_t dbgm = 0;
3650 uint32_t data, i;
3651 enet_qos_est_gate_op_t *gateOp;
3652 status_t rc;
3653
3654 if (hwList == true)
3655 {
3656 dbgm = 1;
3657 }
3658
3659 /* LLR */
3660 rc = ENET_QOS_EstReadWord(base, (uint32_t)kENET_QOS_Ets_llr, &data, 1, dbgm);
3661 if (rc != kStatus_Success)
3662 {
3663 return rc;
3664 }
3665
3666 gcl->numEntries = data;
3667
3668 if (gcl->numEntries > listLen)
3669 {
3670 return kStatus_ENET_QOS_Est_InvalidParameter;
3671 }
3672
3673 /* BTR High */
3674 rc = ENET_QOS_EstReadWord(base, (uint32_t)kENET_QOS_Ets_btr_high, &data, 1, dbgm);
3675 if (rc != kStatus_Success)
3676 {
3677 return rc;
3678 }
3679
3680 gcl->baseTime = (uint64_t)data << 32U;
3681
3682 /* BTR Low */
3683 rc = ENET_QOS_EstReadWord(base, (uint32_t)kENET_QOS_Ets_btr_low, &data, 1, dbgm);
3684 if (rc != kStatus_Success)
3685 {
3686 return rc;
3687 }
3688
3689 gcl->baseTime |= data;
3690
3691 /* CTR High */
3692 rc = ENET_QOS_EstReadWord(base, (uint32_t)kENET_QOS_Ets_ctr_high, &data, 1, dbgm);
3693 if (rc != kStatus_Success)
3694 {
3695 return rc;
3696 }
3697
3698 gcl->cycleTime = (uint64_t)data << 32U;
3699
3700 /* CTR Low */
3701 rc = ENET_QOS_EstReadWord(base, (uint32_t)kENET_QOS_Ets_ctr_low, &data, 1, dbgm);
3702 if (rc != kStatus_Success)
3703 {
3704 return rc;
3705 }
3706
3707 gcl->cycleTime |= data;
3708
3709 /* TER */
3710 rc = ENET_QOS_EstReadWord(base, (uint32_t)kENET_QOS_Ets_ter, &data, 1, dbgm);
3711 if (rc != kStatus_Success)
3712 {
3713 return rc;
3714 }
3715
3716 gcl->extTime = data;
3717
3718 gateOp = gcl->opList;
3719
3720 for (i = 0; i < gcl->numEntries; i++)
3721 {
3722 rc = ENET_QOS_EstReadWord(base, i, &data, 0, dbgm);
3723 if (rc != kStatus_Success)
3724 {
3725 return rc;
3726 }
3727
3728 gateOp->interval = data & (EST_MAX_INTERVAL);
3729 gateOp->gate = data >> ENET_QOS_EST_WID;
3730 gateOp++;
3731 }
3732
3733 return kStatus_Success;
3734 }
3735
3736 /*!
3737 * brief Read flexible rx parser configuration at specified index.
3738 *
3739 * This function is used to read flexible rx parser configuration at specified index.
3740 *
3741 * param base ENET peripheral base address..
3742 * param rxpConfig The rx parser configuration pointer.
3743 * param entryIndex The rx parser entry index to read, start from 0.
3744 * retval kStatus_Success Configure rx parser success.
3745 * retval kStatus_ENET_QOS_Timeout Poll status flag timeout.
3746 */
ENET_QOS_ReadRxParser(ENET_QOS_Type * base,enet_qos_rxp_config_t * rxpConfig,uint16_t entryIndex)3747 status_t ENET_QOS_ReadRxParser(ENET_QOS_Type *base, enet_qos_rxp_config_t *rxpConfig, uint16_t entryIndex)
3748 {
3749 assert(rxpConfig != NULL);
3750 assert(entryIndex < ENET_QOS_RXP_ENTRY_COUNT);
3751
3752 uint32_t *dataPtr;
3753 uint8_t entrySize = sizeof(enet_qos_rxp_config_t) / sizeof(uint32_t);
3754 uint32_t value = 0U;
3755 status_t result = kStatus_Success;
3756
3757 /* Wait hardware not busy */
3758 result = ENET_QOS_PollStatusFlag(&(base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS),
3759 ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_STARTBUSY_MASK, 0U);
3760 if (kStatus_Success != result)
3761 {
3762 return result;
3763 }
3764
3765 for (uint8_t i = 0; i < entrySize; i++)
3766 {
3767 /* Read address. */
3768 value = ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_ADDR((uint32_t)entrySize * entryIndex + i);
3769
3770 /* Issue read command. */
3771 value &= ~ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_WRRDN_MASK;
3772 base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS = value;
3773
3774 /* Start Read */
3775 value |= ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_STARTBUSY_MASK;
3776 base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS = value;
3777
3778 /* Wait hardware not busy */
3779 result = ENET_QOS_PollStatusFlag(&base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS,
3780 ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_STARTBUSY_MASK, 0U);
3781 if (kStatus_Success != result)
3782 {
3783 return result;
3784 }
3785
3786 dataPtr = (uint32_t *)(void *)&rxpConfig[entryIndex];
3787 dataPtr = &dataPtr[i];
3788 /* Read data */
3789 *dataPtr = base->MTL_RXP_INDIRECT_ACC_DATA;
3790 }
3791
3792 return result;
3793 }
3794
3795 /*!
3796 * brief Configure flexible rx parser.
3797 *
3798 * This function is used to configure the flexible rx parser table.
3799 *
3800 * param base ENET peripheral base address..
3801 * param rxpConfig The rx parser configuration pointer.
3802 * param entryCount The rx parser entry count.
3803 * retval kStatus_Success Configure rx parser success.
3804 * retval kStatus_ENET_QOS_Timeout Poll status flag timeout.
3805 */
ENET_QOS_ConfigureRxParser(ENET_QOS_Type * base,enet_qos_rxp_config_t * rxpConfig,uint16_t entryCount)3806 status_t ENET_QOS_ConfigureRxParser(ENET_QOS_Type *base, enet_qos_rxp_config_t *rxpConfig, uint16_t entryCount)
3807 {
3808 assert(rxpConfig != NULL);
3809 assert(entryCount <= ENET_QOS_RXP_ENTRY_COUNT);
3810
3811 uint32_t *dataPtr;
3812 uint32_t entrySize = sizeof(enet_qos_rxp_config_t) / sizeof(uint32_t);
3813 uint32_t value = 0U;
3814 status_t result = kStatus_Success;
3815 bool enableRx = false;
3816
3817 /* Disable the MAC rx. */
3818 if (0U != (base->MAC_CONFIGURATION & ENET_QOS_MAC_CONFIGURATION_RE_MASK))
3819 {
3820 base->MAC_CONFIGURATION &= ~ENET_QOS_MAC_CONFIGURATION_RE_MASK;
3821 enableRx = true;
3822 }
3823
3824 /* Disable frame parser. */
3825 result = ENET_QOS_EnableRxParser(base, false);
3826
3827 if (kStatus_Success != result)
3828 {
3829 return result;
3830 }
3831
3832 for (uint8_t count = 0; count < entryCount; count++)
3833 {
3834 for (uint8_t i = 0; i < entrySize; i++)
3835 {
3836 /* Wait hardware not busy */
3837 result = ENET_QOS_PollStatusFlag(&base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS,
3838 ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_STARTBUSY_MASK, 0U);
3839 if (kStatus_Success != result)
3840 {
3841 return result;
3842 }
3843
3844 dataPtr = (uint32_t *)(void *)&rxpConfig[count];
3845 dataPtr = &dataPtr[i];
3846
3847 /* Write data before issue write command */
3848 base->MTL_RXP_INDIRECT_ACC_DATA = *dataPtr;
3849
3850 /* Write address and issue write command */
3851 value = ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_ADDR(entrySize * count + i);
3852 // base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS = value;
3853
3854 value |= ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_WRRDN_MASK;
3855 base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS = value;
3856
3857 /* Start write */
3858 value |= ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_STARTBUSY_MASK;
3859 base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS = value;
3860 }
3861 }
3862
3863 /* Wait hardware not busy */
3864 result = ENET_QOS_PollStatusFlag(&(base->MTL_RXP_INDIRECT_ACC_CONTROL_STATUS),
3865 ENET_QOS_MTL_RXP_INDIRECT_ACC_CONTROL_STATUS_STARTBUSY_MASK, 0U);
3866 if (kStatus_Success != result)
3867 {
3868 return result;
3869 }
3870
3871 /* Program NVE and NPE. */
3872 value = base->MTL_RXP_CONTROL_STATUS;
3873 value &= ~(ENET_QOS_MTL_RXP_CONTROL_STATUS_NVE_MASK | ENET_QOS_MTL_RXP_CONTROL_STATUS_NPE_MASK);
3874
3875 value |= ENET_QOS_MTL_RXP_CONTROL_STATUS_NPE((uint32_t)entryCount - 1U);
3876 if (entryCount < 3U)
3877 {
3878 value |= ENET_QOS_MTL_RXP_CONTROL_STATUS_NVE(2U);
3879 }
3880 else
3881 {
3882 value |= ENET_QOS_MTL_RXP_CONTROL_STATUS_NVE((uint32_t)entryCount - 1U);
3883 }
3884
3885 base->MTL_RXP_CONTROL_STATUS = value;
3886
3887 /* Enable frame parser. */
3888 result = ENET_QOS_EnableRxParser(base, true);
3889
3890 /* Enable Receive */
3891 if (enableRx)
3892 {
3893 base->MAC_CONFIGURATION |= ENET_QOS_MAC_CONFIGURATION_RE_MASK;
3894 }
3895
3896 return result;
3897 }
3898
3899 /*!
3900 * brief Gets statistical data in transfer.
3901 *
3902 * param base ENET_QOS peripheral base address.
3903 * param statistics The statistics structure pointer.
3904 */
ENET_QOS_GetStatistics(ENET_QOS_Type * base,enet_qos_transfer_stats_t * statistics)3905 void ENET_QOS_GetStatistics(ENET_QOS_Type *base, enet_qos_transfer_stats_t *statistics)
3906 {
3907 /* Rx statistics */
3908 statistics->statsRxFrameCount = base->MAC_RX_PACKETS_COUNT_GOOD_BAD;
3909 statistics->statsRxCrcErr = base->MAC_RX_CRC_ERROR_PACKETS;
3910 statistics->statsRxAlignErr = base->MAC_RX_ALIGNMENT_ERROR_PACKETS;
3911 statistics->statsRxLengthErr = base->MAC_RX_LENGTH_ERROR_PACKETS;
3912 statistics->statsRxFifoOverflowErr = base->MAC_RX_FIFO_OVERFLOW_PACKETS;
3913
3914 /* Tx statistics */
3915 statistics->statsTxFrameCount = base->MAC_TX_PACKET_COUNT_GOOD_BAD;
3916 statistics->statsTxFifoUnderRunErr = base->MAC_TX_UNDERFLOW_ERROR_PACKETS;
3917 }
3918
3919 /*!
3920 * brief The ENET IRQ handler.
3921 *
3922 * param base ENET peripheral base address.
3923 * param handle The ENET handler pointer.
3924 */
ENET_QOS_CommonIRQHandler(ENET_QOS_Type * base,enet_qos_handle_t * handle)3925 void ENET_QOS_CommonIRQHandler(ENET_QOS_Type *base, enet_qos_handle_t *handle)
3926 {
3927 /* Check for the interrupt source type. */
3928 /* DMA CHANNEL 0. */
3929 if ((base->DMA_INTERRUPT_STATUS & ENET_QOS_DMA_INTERRUPT_STATUS_DC0IS_MASK) != 0U)
3930 {
3931 uint32_t flag = base->DMA_CH[0].DMA_CHX_STAT;
3932 if ((flag & ENET_QOS_DMA_CHX_STAT_RI_MASK) != 0U)
3933 {
3934 base->DMA_CH[0].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_RI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
3935 if (handle->callback != NULL)
3936 {
3937 handle->callback(base, handle, kENET_QOS_RxIntEvent, 0, handle->userData);
3938 }
3939 }
3940 if ((flag & ENET_QOS_DMA_CHX_STAT_TI_MASK) != 0U)
3941 {
3942 base->DMA_CH[0].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_TI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
3943 ENET_QOS_ReclaimTxDescriptor(base, handle, 0);
3944 }
3945 }
3946
3947 /* DMA CHANNEL 1. */
3948 if ((base->DMA_INTERRUPT_STATUS & ENET_QOS_DMA_INTERRUPT_STATUS_DC1IS_MASK) != 0U)
3949 {
3950 uint32_t flag = base->DMA_CH[1].DMA_CHX_STAT;
3951 if ((flag & ENET_QOS_DMA_CHX_STAT_RI_MASK) != 0U)
3952 {
3953 base->DMA_CH[1].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_RI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
3954 if (handle->callback != NULL)
3955 {
3956 handle->callback(base, handle, kENET_QOS_RxIntEvent, 1, handle->userData);
3957 }
3958 }
3959 if ((flag & ENET_QOS_DMA_CHX_STAT_TI_MASK) != 0U)
3960 {
3961 base->DMA_CH[1].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_TI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
3962 ENET_QOS_ReclaimTxDescriptor(base, handle, 1);
3963 }
3964 }
3965
3966 /* DMA CHANNEL 2. */
3967 if ((base->DMA_INTERRUPT_STATUS & ENET_QOS_DMA_INTERRUPT_STATUS_DC2IS_MASK) != 0U)
3968 {
3969 uint32_t flag = base->DMA_CH[2].DMA_CHX_STAT;
3970 if ((flag & ENET_QOS_DMA_CHX_STAT_RI_MASK) != 0U)
3971 {
3972 base->DMA_CH[2].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_RI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
3973 if (handle->callback != NULL)
3974 {
3975 handle->callback(base, handle, kENET_QOS_RxIntEvent, 2, handle->userData);
3976 }
3977 }
3978 if ((flag & ENET_QOS_DMA_CHX_STAT_TI_MASK) != 0U)
3979 {
3980 base->DMA_CH[2].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_TI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
3981 ENET_QOS_ReclaimTxDescriptor(base, handle, 2);
3982 }
3983 }
3984
3985 /* DMA CHANNEL 3. */
3986 if ((base->DMA_INTERRUPT_STATUS & ENET_QOS_DMA_INTERRUPT_STATUS_DC3IS_MASK) != 0U)
3987 {
3988 uint32_t flag = base->DMA_CH[3].DMA_CHX_STAT;
3989 if ((flag & ENET_QOS_DMA_CHX_STAT_RI_MASK) != 0U)
3990 {
3991 base->DMA_CH[3].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_RI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
3992 if (handle->callback != NULL)
3993 {
3994 handle->callback(base, handle, kENET_QOS_RxIntEvent, 3, handle->userData);
3995 }
3996 }
3997 if ((flag & ENET_QOS_DMA_CHX_STAT_TI_MASK) != 0U)
3998 {
3999 base->DMA_CH[3].DMA_CHX_STAT = ENET_QOS_DMA_CHX_STAT_TI_MASK | ENET_QOS_DMA_CHX_STAT_NIS_MASK;
4000 ENET_QOS_ReclaimTxDescriptor(base, handle, 3);
4001 }
4002 }
4003
4004 /* MAC TIMESTAMP. */
4005 if ((base->DMA_INTERRUPT_STATUS & ENET_QOS_DMA_INTERRUPT_STATUS_MACIS_MASK) != 0U)
4006 {
4007 if ((base->MAC_INTERRUPT_STATUS & ENET_QOS_MAC_INTERRUPT_STATUS_TSIS_MASK) != 0U)
4008 {
4009 if (handle->callback != NULL)
4010 {
4011 handle->callback(base, handle, kENET_QOS_TimeStampIntEvent, 0, handle->userData);
4012 }
4013 }
4014 }
4015 SDK_ISR_EXIT_BARRIER;
4016 }
4017
4018 #if defined(ENET_QOS)
4019 void ENET_QOS_DriverIRQHandler(void);
ENET_QOS_DriverIRQHandler(void)4020 void ENET_QOS_DriverIRQHandler(void)
4021 {
4022 s_enetqosIsr(ENET_QOS, s_ENETHandle[0]);
4023 }
4024 #endif
4025
4026 #if defined(CONNECTIVITY__ENET_QOS)
4027 void CONNECTIVITY_EQOS_INT_DriverIRQHandler(void);
CONNECTIVITY_EQOS_INT_DriverIRQHandler(void)4028 void CONNECTIVITY_EQOS_INT_DriverIRQHandler(void)
4029 {
4030 s_enetqosIsr(CONNECTIVITY__ENET_QOS, s_ENETHandle[0]);
4031 }
4032 #endif
4033