mcxn947_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file mcxn947_eth_driver.c
3  * @brief NXP MCX N947 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "fsl_device_registers.h"
36 #include "fsl_clock.h"
37 #include "fsl_gpio.h"
38 #include "fsl_port.h"
39 #include "fsl_reset.h"
40 #include "core/net.h"
42 #include "debug.h"
43 
44 //Underlying network interface
45 static NetInterface *nicDriverInterface;
46 
47 //IAR EWARM compiler?
48 #if defined(__ICCARM__)
49 
50 //Transmit buffer
51 #pragma data_alignment = 4
53 //Receive buffer
54 #pragma data_alignment = 4
56 //Transmit DMA descriptors
57 #pragma data_alignment = 4
59 //Receive DMA descriptors
60 #pragma data_alignment = 4
62 
63 //Keil MDK-ARM or GCC compiler?
64 #else
65 
66 //Transmit buffer
68  __attribute__((aligned(4)));
69 //Receive buffer
71  __attribute__((aligned(4)));
72 //Transmit DMA descriptors
74  __attribute__((aligned(4)));
75 //Receive DMA descriptors
77  __attribute__((aligned(4)));
78 
79 #endif
80 
81 //Current transmit descriptor
82 static uint_t txIndex;
83 //Current receive descriptor
84 static uint_t rxIndex;
85 
86 
87 /**
88  * @brief MCX N947 Ethernet MAC driver
89  **/
90 
92 {
94  ETH_MTU,
105  TRUE,
106  TRUE,
107  TRUE,
108  FALSE
109 };
110 
111 
112 /**
113  * @brief MCX N947 Ethernet MAC initialization
114  * @param[in] interface Underlying network interface
115  * @return Error code
116  **/
117 
119 {
120  error_t error;
121  uint32_t temp;
122 
123  //Debug message
124  TRACE_INFO("Initializing MCX N947 Ethernet MAC...\r\n");
125 
126  //Save underlying network interface
127  nicDriverInterface = interface;
128 
129  //Attach NONE clock to ENETRMII
130  CLOCK_EnableClock(kCLOCK_InputMux);
131  CLOCK_AttachClk(kNONE_to_ENETRMII);
132 
133  //Enable ENET peripheral clock
134  CLOCK_EnableClock(kCLOCK_Enet);
135 
136  //Reset ENET module
137  SYSCON0->PRESETCTRL2 = SYSCON_PRESETCTRL2_ENET_RST_MASK;
138  SYSCON0->PRESETCTRL2 &= ~SYSCON_PRESETCTRL2_ENET_RST_MASK;
139 
140  //GPIO configuration
141  mcxn947EthInitGpio(interface);
142 
143  //Perform a software reset
144  ENET->DMA_MODE |= ENET_DMA_MODE_SWR_MASK;
145  //Wait for the reset to complete
146  while((ENET->DMA_MODE & ENET_DMA_MODE_SWR_MASK) != 0)
147  {
148  }
149 
150  //Adjust MDC clock range depending on CSR frequency
151  ENET->MAC_MDIO_ADDRESS = ENET_MAC_MDIO_ADDRESS_CR(4);
152 
153  //Valid Ethernet PHY or switch driver?
154  if(interface->phyDriver != NULL)
155  {
156  //Ethernet PHY initialization
157  error = interface->phyDriver->init(interface);
158  }
159  else if(interface->switchDriver != NULL)
160  {
161  //Ethernet switch initialization
162  error = interface->switchDriver->init(interface);
163  }
164  else
165  {
166  //The interface is not properly configured
167  error = ERROR_FAILURE;
168  }
169 
170  //Any error to report?
171  if(error)
172  {
173  return error;
174  }
175 
176  //Use default MAC configuration
177  ENET->MAC_CONFIGURATION = ENET_MAC_CONFIGURATION_GPSLCE_MASK |
178  ENET_MAC_CONFIGURATION_PS_MASK | ENET_MAC_CONFIGURATION_DO_MASK;
179 
180  //Set the maximum packet size that can be accepted
181  temp = ENET->MAC_EXT_CONFIGURATION & ~ENET_MAC_EXT_CONFIGURATION_GPSL_MASK;
182  ENET->MAC_EXT_CONFIGURATION = temp | MCXN947_ETH_RX_BUFFER_SIZE;
183 
184  //Set the MAC address of the station
185  ENET->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
186  ENET->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
187 
188  //Configure the receive filter
189  ENET->MAC_PACKET_FILTER = 0;
190 
191  //Disable flow control
192  ENET->MAC_TX_FLOW_CTRL_Q[0] = 0;
193  ENET->MAC_RX_FLOW_CTRL = 0;
194 
195  //Enable the first RX queue
196  ENET->MAC_RXQ_CTRL[0] = ENET_MAC_RXQ_CTRL_RXQ0EN(2);
197 
198  //Configure DMA operating mode
199  ENET->DMA_MODE = ENET_DMA_MODE_PR(0);
200  //Configure system bus mode
201  ENET->DMA_SYSBUS_MODE |= ENET_DMA_SYSBUS_MODE_AAL_MASK;
202 
203  //The DMA takes the descriptor table as contiguous
204  ENET->DMA_CH[0].DMA_CHX_CTRL = ENET_DMA_CH_DMA_CHX_CTRL_DSL(0);
205  //Configure TX features
206  ENET->DMA_CH[0].DMA_CHX_TX_CTRL = ENET_DMA_CH_DMA_CHX_TX_CTRL_TxPBL(32);
207 
208  //Configure RX features
209  ENET->DMA_CH[0].DMA_CHX_RX_CTRL = ENET_DMA_CH_DMA_CHX_RX_CTRL_RxPBL(32) |
210  ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ_13_Y(MCXN947_ETH_RX_BUFFER_SIZE / 4);
211 
212  //Enable store and forward mode for transmission
213  ENET->MTL_QUEUE[0].MTL_TXQX_OP_MODE |= ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TQS(7) |
214  ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TXQEN(2) |
215  ENET_MTL_QUEUE_MTL_TXQX_OP_MODE_TSF_MASK;
216 
217  //Enable store and forward mode for reception
218  ENET->MTL_QUEUE[0].MTL_RXQX_OP_MODE |= ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RQS(7) |
219  ENET_MTL_QUEUE_MTL_RXQX_OP_MODE_RSF_MASK;
220 
221  //Initialize DMA descriptor lists
222  mcxn947EthInitDmaDesc(interface);
223 
224  //Disable MAC interrupts
225  ENET->MAC_INTERRUPT_ENABLE = 0;
226 
227  //Enable the desired DMA interrupts
228  ENET->DMA_CH[0].DMA_CHX_INT_EN = ENET_DMA_CH_DMA_CHX_INT_EN_NIE_MASK |
229  ENET_DMA_CH_DMA_CHX_INT_EN_RIE_MASK | ENET_DMA_CH_DMA_CHX_INT_EN_TIE_MASK;
230 
231  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
232  NVIC_SetPriorityGrouping(MCXN947_ETH_IRQ_PRIORITY_GROUPING);
233 
234  //Configure Ethernet interrupt priority
235  NVIC_SetPriority(ETHERNET_IRQn, NVIC_EncodePriority(MCXN947_ETH_IRQ_PRIORITY_GROUPING,
237 
238  //Enable MAC transmission and reception
239  ENET->MAC_CONFIGURATION |= ENET_MAC_CONFIGURATION_TE_MASK |
240  ENET_MAC_CONFIGURATION_RE_MASK;
241 
242  //Enable DMA transmission and reception
243  ENET->DMA_CH[0].DMA_CHX_TX_CTRL |= ENET_DMA_CH_DMA_CHX_TX_CTRL_ST_MASK;
244  ENET->DMA_CH[0].DMA_CHX_RX_CTRL |= ENET_DMA_CH_DMA_CHX_RX_CTRL_SR_MASK;
245 
246  //Accept any packets from the upper layer
247  osSetEvent(&interface->nicTxEvent);
248 
249  //Successful initialization
250  return NO_ERROR;
251 }
252 
253 
254 /**
255  * @brief GPIO configuration
256  * @param[in] interface Underlying network interface
257  **/
258 
259 __weak_func void mcxn947EthInitGpio(NetInterface *interface)
260 {
261 //FRDM-MCXN947 evaluation board?
262 #if defined(USE_FRDM_MCXN947)
263  port_pin_config_t portPinConfig;
264  gpio_pin_config_t gpioPinConfig;
265 
266  //Enable PORT1 clock
267  CLOCK_EnableClock(kCLOCK_Port1);
268 
269  //Select RMII interface mode
270  SYSCON0->ENET_PHY_INTF_SEL |= SYSCON_ENET_PHY_INTF_SEL_PHY_SEL_MASK;
271 
272  //Configure RMII pins
273  portPinConfig.pullSelect = kPORT_PullDisable;
274  portPinConfig.pullValueSelect = kPORT_LowPullResistor;
275  portPinConfig.slewRate = kPORT_FastSlewRate;
276  portPinConfig.passiveFilterEnable = kPORT_PassiveFilterDisable;
277  portPinConfig.openDrainEnable = kPORT_OpenDrainDisable;
278  portPinConfig.driveStrength = kPORT_LowDriveStrength;
279  portPinConfig.mux = kPORT_MuxAlt9;
280  portPinConfig.inputBuffer = kPORT_InputBufferEnable;
281  portPinConfig.invertInput = kPORT_InputNormal;
282  portPinConfig.lockRegister = kPORT_UnlockRegister;
283 
284  //Configure PORT1_4 as ENET0_TX_CLK
285  PORT_SetPinConfig(PORT1, 4, &portPinConfig);
286  //Configure PORT1_5 as ENET0_TXEN
287  PORT_SetPinConfig(PORT1, 5, &portPinConfig);
288  //Configure PORT1_6 as ENET0_TXD0
289  PORT_SetPinConfig(PORT1, 6, &portPinConfig);
290  //Configure PORT1_7 as ENET0_TXD1
291  PORT_SetPinConfig(PORT1, 7, &portPinConfig);
292 
293  //Configure PORT1_13 as ENET0_RXDV
294  PORT_SetPinConfig(PORT1, 13, &portPinConfig);
295  //Configure PORT1_14 as ENET0_RXD0
296  PORT_SetPinConfig(PORT1, 14, &portPinConfig);
297  //Configure PORT1_15 as ENET0_RXD1
298  PORT_SetPinConfig(PORT1, 15, &portPinConfig);
299 
300  //Configure PORT1_20 as ENET0_MDC
301  PORT_SetPinConfig(PORT1, 20, &portPinConfig);
302  //Configure PORT1_21 as ENET0_MDIO
303  PORT_SetPinConfig(PORT1, 21, &portPinConfig);
304 
305  //Configure ENET_RST (P5_8) as an output
306  gpioPinConfig.pinDirection = kGPIO_DigitalOutput;
307  gpioPinConfig.outputLogic = 0;
308  GPIO_PinInit(GPIO5, 8, &gpioPinConfig);
309 
310  //Reset PHY transceiver (hard reset)
311  GPIO_PinWrite(GPIO5, 8, 0);
312  sleep(10);
313  GPIO_PinWrite(GPIO5, 8, 1);
314  sleep(10);
315 
316 //MCX-N9XX-EVK evaluation board?
317 #elif defined(USE_MCX_N9XX_EVK)
318  port_pin_config_t portPinConfig;
319 
320  //Enable PORT1 clock
321  CLOCK_EnableClock(kCLOCK_Port1);
322 
323  //Select RMII interface mode
324  SYSCON0->ENET_PHY_INTF_SEL |= SYSCON_ENET_PHY_INTF_SEL_PHY_SEL_MASK;
325 
326  //Configure RMII pins
327  portPinConfig.pullSelect = kPORT_PullDisable;
328  portPinConfig.pullValueSelect = kPORT_LowPullResistor;
329  portPinConfig.slewRate = kPORT_FastSlewRate;
330  portPinConfig.passiveFilterEnable = kPORT_PassiveFilterDisable;
331  portPinConfig.openDrainEnable = kPORT_OpenDrainDisable;
332  portPinConfig.driveStrength = kPORT_LowDriveStrength;
333  portPinConfig.mux = kPORT_MuxAlt9;
334  portPinConfig.inputBuffer = kPORT_InputBufferEnable;
335  portPinConfig.invertInput = kPORT_InputNormal;
336  portPinConfig.lockRegister = kPORT_UnlockRegister;
337 
338  //Configure PORT1_4 as ENET0_TX_CLK
339  PORT_SetPinConfig(PORT1, 4, &portPinConfig);
340  //Configure PORT1_5 as ENET0_TXEN
341  PORT_SetPinConfig(PORT1, 5, &portPinConfig);
342  //Configure PORT1_6 as ENET0_TXD0
343  PORT_SetPinConfig(PORT1, 6, &portPinConfig);
344  //Configure PORT1_7 as ENET0_TXD1
345  PORT_SetPinConfig(PORT1, 7, &portPinConfig);
346 
347  //Configure PORT1_13 as ENET0_RXDV
348  PORT_SetPinConfig(PORT1, 13, &portPinConfig);
349  //Configure PORT1_14 as ENET0_RXD0
350  PORT_SetPinConfig(PORT1, 14, &portPinConfig);
351  //Configure PORT1_15 as ENET0_RXD1
352  PORT_SetPinConfig(PORT1, 15, &portPinConfig);
353 
354  //Configure PORT1_20 as ENET0_MDC
355  PORT_SetPinConfig(PORT1, 20, &portPinConfig);
356  //Configure PORT1_21 as ENET0_MDIO
357  PORT_SetPinConfig(PORT1, 21, &portPinConfig);
358 #endif
359 }
360 
361 
362 /**
363  * @brief Initialize DMA descriptor lists
364  * @param[in] interface Underlying network interface
365  **/
366 
368 {
369  uint_t i;
370 
371  //Initialize TX DMA descriptor list
372  for(i = 0; i < MCXN947_ETH_TX_BUFFER_COUNT; i++)
373  {
374  //The descriptor is initially owned by the application
375  txDmaDesc[i].tdes0 = 0;
376  txDmaDesc[i].tdes1 = 0;
377  txDmaDesc[i].tdes2 = 0;
378  txDmaDesc[i].tdes3 = 0;
379  }
380 
381  //Initialize TX descriptor index
382  txIndex = 0;
383 
384  //Initialize RX DMA descriptor list
385  for(i = 0; i < MCXN947_ETH_RX_BUFFER_COUNT; i++)
386  {
387  //The descriptor is initially owned by the DMA
388  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
389  rxDmaDesc[i].rdes1 = 0;
390  rxDmaDesc[i].rdes2 = 0;
392  }
393 
394  //Initialize RX descriptor index
395  rxIndex = 0;
396 
397  //Start location of the TX descriptor list
398  ENET->DMA_CH[0].DMA_CHX_TXDESC_LIST_ADDR = (uint32_t) &txDmaDesc[0];
399  //Length of the transmit descriptor ring
400  ENET->DMA_CH[0].DMA_CHX_TXDESC_RING_LENGTH = MCXN947_ETH_TX_BUFFER_COUNT - 1;
401 
402  //Start location of the RX descriptor list
403  ENET->DMA_CH[0].DMA_CHX_RXDESC_LIST_ADDR = (uint32_t) &rxDmaDesc[0];
404  //Length of the receive descriptor ring
405  ENET->DMA_CH[0].DMA_CHX_RX_CONTROL2 = MCXN947_ETH_RX_BUFFER_COUNT - 1;
406 }
407 
408 
409 /**
410  * @brief MCX N947 Ethernet MAC timer handler
411  *
412  * This routine is periodically called by the TCP/IP stack to handle periodic
413  * operations such as polling the link state
414  *
415  * @param[in] interface Underlying network interface
416  **/
417 
418 void mcxn947EthTick(NetInterface *interface)
419 {
420  //Valid Ethernet PHY or switch driver?
421  if(interface->phyDriver != NULL)
422  {
423  //Handle periodic operations
424  interface->phyDriver->tick(interface);
425  }
426  else if(interface->switchDriver != NULL)
427  {
428  //Handle periodic operations
429  interface->switchDriver->tick(interface);
430  }
431  else
432  {
433  //Just for sanity
434  }
435 }
436 
437 
438 /**
439  * @brief Enable interrupts
440  * @param[in] interface Underlying network interface
441  **/
442 
444 {
445  //Enable Ethernet MAC interrupts
446  NVIC_EnableIRQ(ETHERNET_IRQn);
447 
448  //Valid Ethernet PHY or switch driver?
449  if(interface->phyDriver != NULL)
450  {
451  //Enable Ethernet PHY interrupts
452  interface->phyDriver->enableIrq(interface);
453  }
454  else if(interface->switchDriver != NULL)
455  {
456  //Enable Ethernet switch interrupts
457  interface->switchDriver->enableIrq(interface);
458  }
459  else
460  {
461  //Just for sanity
462  }
463 }
464 
465 
466 /**
467  * @brief Disable interrupts
468  * @param[in] interface Underlying network interface
469  **/
470 
472 {
473  //Disable Ethernet MAC interrupts
474  NVIC_DisableIRQ(ETHERNET_IRQn);
475 
476  //Valid Ethernet PHY or switch driver?
477  if(interface->phyDriver != NULL)
478  {
479  //Disable Ethernet PHY interrupts
480  interface->phyDriver->disableIrq(interface);
481  }
482  else if(interface->switchDriver != NULL)
483  {
484  //Disable Ethernet switch interrupts
485  interface->switchDriver->disableIrq(interface);
486  }
487  else
488  {
489  //Just for sanity
490  }
491 }
492 
493 
494 /**
495  * @brief MCX N947 Ethernet MAC interrupt service routine
496  **/
497 
499 {
500  bool_t flag;
501  uint32_t status;
502 
503  //Interrupt service routine prologue
504  osEnterIsr();
505 
506  //This flag will be set if a higher priority task must be woken
507  flag = FALSE;
508 
509  //Read DMA status register
510  status = ENET->DMA_CH[0].DMA_CHX_STAT;
511 
512  //Packet transmitted?
513  if((status & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0)
514  {
515  //Clear TI interrupt flag
516  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK;
517 
518  //Check whether the TX buffer is available for writing
519  if((txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN) == 0)
520  {
521  //Notify the TCP/IP stack that the transmitter is ready to send
522  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
523  }
524  }
525 
526  //Packet received?
527  if((status & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0)
528  {
529  //Clear RI interrupt flag
530  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK;
531 
532  //Set event flag
533  nicDriverInterface->nicEvent = TRUE;
534  //Notify the TCP/IP stack of the event
535  flag |= osSetEventFromIsr(&netEvent);
536  }
537 
538  //Clear NIS interrupt flag
539  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
540 
541  //Interrupt service routine epilogue
542  osExitIsr(flag);
543 }
544 
545 
546 /**
547  * @brief MCX N947 Ethernet MAC event handler
548  * @param[in] interface Underlying network interface
549  **/
550 
552 {
553  error_t error;
554 
555  //Process all pending packets
556  do
557  {
558  //Read incoming packet
559  error = mcxn947EthReceivePacket(interface);
560 
561  //No more data in the receive buffer?
562  } while(error != ERROR_BUFFER_EMPTY);
563 }
564 
565 
566 /**
567  * @brief Send a packet
568  * @param[in] interface Underlying network interface
569  * @param[in] buffer Multi-part buffer containing the data to send
570  * @param[in] offset Offset to the first data byte
571  * @param[in] ancillary Additional options passed to the stack along with
572  * the packet
573  * @return Error code
574  **/
575 
577  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
578 {
579  size_t length;
580 
581  //Retrieve the length of the packet
582  length = netBufferGetLength(buffer) - offset;
583 
584  //Check the frame length
586  {
587  //The transmitter can accept another packet
588  osSetEvent(&interface->nicTxEvent);
589  //Report an error
590  return ERROR_INVALID_LENGTH;
591  }
592 
593  //Make sure the current buffer is available for writing
594  if((txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN) != 0)
595  {
596  return ERROR_FAILURE;
597  }
598 
599  //Copy user data to the transmit buffer
600  netBufferRead(txBuffer[txIndex], buffer, offset, length);
601 
602  //Set the start address of the buffer
603  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
604  //Write the number of bytes to send
605  txDmaDesc[txIndex].tdes2 = ENET_TDES2_IOC | (length & ENET_TDES2_B1L);
606  //Give the ownership of the descriptor to the DMA
608 
609  //Clear TBU flag to resume processing
610  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TBU_MASK;
611  //Instruct the DMA to poll the transmit descriptor list
612  ENET->DMA_CH[0].DMA_CHX_TXDESC_TAIL_PTR = 0;
613 
614  //Increment index and wrap around if necessary
615  if(++txIndex >= MCXN947_ETH_TX_BUFFER_COUNT)
616  {
617  txIndex = 0;
618  }
619 
620  //Check whether the next buffer is available for writing
621  if((txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN) == 0)
622  {
623  //The transmitter can accept another packet
624  osSetEvent(&interface->nicTxEvent);
625  }
626 
627  //Data successfully written
628  return NO_ERROR;
629 }
630 
631 
632 /**
633  * @brief Receive a packet
634  * @param[in] interface Underlying network interface
635  * @return Error code
636  **/
637 
639 {
640  error_t error;
641  size_t n;
642  NetRxAncillary ancillary;
643 
644  //Current buffer available for reading?
645  if((rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_OWN) == 0)
646  {
647  //FD and LD flags should be set
648  if((rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_FD) != 0 &&
649  (rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_LD) != 0)
650  {
651  //Make sure no error occurred
652  if((rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_ES) == 0)
653  {
654  //Retrieve the length of the frame
655  n = rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_PL;
656  //Limit the number of data to read
658 
659  //Additional options can be passed to the stack along with the packet
660  ancillary = NET_DEFAULT_RX_ANCILLARY;
661 
662  //Pass the packet to the upper layer
663  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
664 
665  //Valid packet received
666  error = NO_ERROR;
667  }
668  else
669  {
670  //The received packet contains an error
671  error = ERROR_INVALID_PACKET;
672  }
673  }
674  else
675  {
676  //The packet is not valid
677  error = ERROR_INVALID_PACKET;
678  }
679 
680  //Set the start address of the buffer
681  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
682  //Give the ownership of the descriptor back to the DMA
684 
685  //Increment index and wrap around if necessary
686  if(++rxIndex >= MCXN947_ETH_RX_BUFFER_COUNT)
687  {
688  rxIndex = 0;
689  }
690  }
691  else
692  {
693  //No more data in the receive buffer
694  error = ERROR_BUFFER_EMPTY;
695  }
696 
697  //Clear RBU flag to resume processing
698  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK;
699  //Instruct the DMA to poll the receive descriptor list
700  ENET->DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR = 0;
701 
702  //Return status code
703  return error;
704 }
705 
706 
707 /**
708  * @brief Configure MAC address filtering
709  * @param[in] interface Underlying network interface
710  * @return Error code
711  **/
712 
714 {
715  uint_t i;
716  bool_t acceptMulticast;
717 
718  //Debug message
719  TRACE_DEBUG("Updating MAC filter...\r\n");
720 
721  //Set the MAC address of the station
722  ENET->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
723  ENET->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
724 
725  //This flag will be set if multicast addresses should be accepted
726  acceptMulticast = FALSE;
727 
728  //The MAC address filter contains the list of MAC addresses to accept
729  //when receiving an Ethernet frame
730  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
731  {
732  //Valid entry?
733  if(interface->macAddrFilter[i].refCount > 0)
734  {
735  //Accept multicast addresses
736  acceptMulticast = TRUE;
737  //We are done
738  break;
739  }
740  }
741 
742  //Enable or disable the reception of multicast frames
743  if(acceptMulticast)
744  {
745  ENET->MAC_PACKET_FILTER |= ENET_MAC_PACKET_FILTER_PM_MASK;
746  }
747  else
748  {
749  ENET->MAC_PACKET_FILTER &= ~ENET_MAC_PACKET_FILTER_PM_MASK;
750  }
751 
752  //Successful processing
753  return NO_ERROR;
754 }
755 
756 
757 /**
758  * @brief Adjust MAC configuration parameters for proper operation
759  * @param[in] interface Underlying network interface
760  * @return Error code
761  **/
762 
764 {
765  uint32_t config;
766 
767  //Read current MAC configuration
768  config = ENET->MAC_CONFIGURATION;
769 
770  //10BASE-T or 100BASE-TX operation mode?
771  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
772  {
773  config |= ENET_MAC_CONFIGURATION_FES_MASK;
774  }
775  else
776  {
777  config &= ~ENET_MAC_CONFIGURATION_FES_MASK;
778  }
779 
780  //Half-duplex or full-duplex mode?
781  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
782  {
783  config |= ENET_MAC_CONFIGURATION_DM_MASK;
784  }
785  else
786  {
787  config &= ~ENET_MAC_CONFIGURATION_DM_MASK;
788  }
789 
790  //Update MAC configuration register
791  ENET->MAC_CONFIGURATION = config;
792 
793  //Successful processing
794  return NO_ERROR;
795 }
796 
797 
798 /**
799  * @brief Write PHY register
800  * @param[in] opcode Access type (2 bits)
801  * @param[in] phyAddr PHY address (5 bits)
802  * @param[in] regAddr Register address (5 bits)
803  * @param[in] data Register value
804  **/
805 
806 void mcxn947EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
807  uint8_t regAddr, uint16_t data)
808 {
809  uint32_t temp;
810 
811  //Valid opcode?
812  if(opcode == SMI_OPCODE_WRITE)
813  {
814  //Take care not to alter MDC clock configuration
815  temp = ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_CR_MASK;
816 
817  //Set up a write operation
818  temp |= ENET_MAC_MDIO_ADDRESS_GOC_0_MASK |
819  ENET_MAC_MDIO_ADDRESS_GB_MASK;
820 
821  //PHY address
822  temp |= ENET_MAC_MDIO_ADDRESS_PA(phyAddr);
823  //Register address
824  temp |= ENET_MAC_MDIO_ADDRESS_RDA(regAddr);
825 
826  //Data to be written in the PHY register
827  ENET->MAC_MDIO_DATA = data & ENET_MAC_MDIO_DATA_GD_MASK;
828 
829  //Start a write operation
830  ENET->MAC_MDIO_ADDRESS = temp;
831  //Wait for the write to complete
832  while((ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_GB_MASK) != 0)
833  {
834  }
835  }
836  else
837  {
838  //The MAC peripheral only supports standard Clause 22 opcodes
839  }
840 }
841 
842 
843 /**
844  * @brief Read PHY register
845  * @param[in] opcode Access type (2 bits)
846  * @param[in] phyAddr PHY address (5 bits)
847  * @param[in] regAddr Register address (5 bits)
848  * @return Register value
849  **/
850 
851 uint16_t mcxn947EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
852  uint8_t regAddr)
853 {
854  uint16_t data;
855  uint32_t temp;
856 
857  //Valid opcode?
858  if(opcode == SMI_OPCODE_READ)
859  {
860  //Take care not to alter MDC clock configuration
861  temp = ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_CR_MASK;
862 
863  //Set up a read operation
864  temp |= ENET_MAC_MDIO_ADDRESS_GOC_1_MASK |
865  ENET_MAC_MDIO_ADDRESS_GOC_0_MASK | ENET_MAC_MDIO_ADDRESS_GB_MASK;
866 
867  //PHY address
868  temp |= ENET_MAC_MDIO_ADDRESS_PA(phyAddr);
869  //Register address
870  temp |= ENET_MAC_MDIO_ADDRESS_RDA(regAddr);
871 
872  //Start a read operation
873  ENET->MAC_MDIO_ADDRESS = temp;
874  //Wait for the read to complete
875  while((ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_GB_MASK) != 0)
876  {
877  }
878 
879  //Get register value
880  data = ENET->MAC_MDIO_DATA & ENET_MAC_MDIO_DATA_GD_MASK;
881  }
882  else
883  {
884  //The MAC peripheral only supports standard Clause 22 opcodes
885  data = 0;
886  }
887 
888  //Return the value of the PHY register
889  return data;
890 }
#define txDmaDesc
#define rxBuffer
#define txBuffer
#define rxDmaDesc
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint8_t opcode
Definition: dns_common.h:188
error_t
Error codes.
Definition: error.h:43
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define ENET_RDES3_FD
#define ENET_RDES3_BUF1V
#define ENET_RDES3_LD
#define ENET_TDES3_OWN
#define ENET_RDES3_IOC
#define ENET_TDES3_FD
#define ENET_RDES3_PL
#define ENET_TDES3_LD
#define ENET_RDES3_ES
#define ENET_RDES3_OWN
#define ENET_TDES2_B1L
#define ENET_TDES2_IOC
uint16_t mcxn947EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
void mcxn947EthEventHandler(NetInterface *interface)
MCX N947 Ethernet MAC event handler.
const NicDriver mcxn947EthDriver
MCX N947 Ethernet MAC driver.
void mcxn947EthEnableIrq(NetInterface *interface)
Enable interrupts.
error_t mcxn947EthReceivePacket(NetInterface *interface)
Receive a packet.
void mcxn947EthDisableIrq(NetInterface *interface)
Disable interrupts.
void mcxn947EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
__weak_func void mcxn947EthInitGpio(NetInterface *interface)
GPIO configuration.
void ETHERNET_IRQHandler(void)
MCX N947 Ethernet MAC interrupt service routine.
void mcxn947EthTick(NetInterface *interface)
MCX N947 Ethernet MAC timer handler.
error_t mcxn947EthInit(NetInterface *interface)
MCX N947 Ethernet MAC initialization.
error_t mcxn947EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
error_t mcxn947EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t mcxn947EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
void mcxn947EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
NXP MCX N947 Ethernet MAC driver.
#define MCXN947_ETH_TX_BUFFER_SIZE
#define MCXN947_ETH_IRQ_GROUP_PRIORITY
#define MCXN947_ETH_IRQ_PRIORITY_GROUPING
#define MCXN947_ETH_TX_BUFFER_COUNT
#define MCXN947_ETH_RX_BUFFER_SIZE
#define MCXN947_ETH_RX_BUFFER_COUNT
#define MCXN947_ETH_IRQ_SUB_PRIORITY
uint16_t regAddr
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:674
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
#define SMI_OPCODE_WRITE
Definition: nic.h:66
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define SMI_OPCODE_READ
Definition: nic.h:67
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define sleep(delay)
Definition: os_port.h:301
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define osEnterIsr()
#define osExitIsr(flag)
Receive descriptor.
Transmit descriptor.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
NIC driver.
Definition: nic.h:283
uint8_t length
Definition: tcp.h:368