mcxn547_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file mcxn547_eth_driver.c
3  * @brief NXP MCX N547 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.4
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 N547 Ethernet MAC driver
89  **/
90 
92 {
94  ETH_MTU,
105  TRUE,
106  TRUE,
107  TRUE,
108  FALSE
109 };
110 
111 
112 /**
113  * @brief MCX N547 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 N547 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  mcxn547EthInitGpio(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 | MCXN547_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(MCXN547_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  mcxn547EthInitDmaDesc(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(MCXN547_ETH_IRQ_PRIORITY_GROUPING);
233 
234  //Configure Ethernet interrupt priority
235  NVIC_SetPriority(ETHERNET_IRQn, NVIC_EncodePriority(MCXN547_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 mcxn547EthInitGpio(NetInterface *interface)
260 {
261 //MCX-N5XX-EVK evaluation board?
262 #if defined(USE_MCX_N5XX_EVK)
263  port_pin_config_t portPinConfig;
264 
265  //Enable PORT1 clock
266  CLOCK_EnableClock(kCLOCK_Port1);
267 
268  //Select RMII interface mode
269  SYSCON0->ENET_PHY_INTF_SEL |= SYSCON_ENET_PHY_INTF_SEL_PHY_SEL_MASK;
270 
271  //Configure RMII pins
272  portPinConfig.pullSelect = kPORT_PullDisable;
273  portPinConfig.pullValueSelect = kPORT_LowPullResistor;
274  portPinConfig.slewRate = kPORT_FastSlewRate;
275  portPinConfig.passiveFilterEnable = kPORT_PassiveFilterDisable;
276  portPinConfig.openDrainEnable = kPORT_OpenDrainDisable;
277  portPinConfig.driveStrength = kPORT_LowDriveStrength;
278  portPinConfig.mux = kPORT_MuxAlt9;
279  portPinConfig.inputBuffer = kPORT_InputBufferEnable;
280  portPinConfig.invertInput = kPORT_InputNormal;
281  portPinConfig.lockRegister = kPORT_UnlockRegister;
282 
283  //Configure PORT1_4 as ENET0_TX_CLK
284  PORT_SetPinConfig(PORT1, 4, &portPinConfig);
285  //Configure PORT1_5 as ENET0_TXEN
286  PORT_SetPinConfig(PORT1, 5, &portPinConfig);
287  //Configure PORT1_6 as ENET0_TXD0
288  PORT_SetPinConfig(PORT1, 6, &portPinConfig);
289  //Configure PORT1_7 as ENET0_TXD1
290  PORT_SetPinConfig(PORT1, 7, &portPinConfig);
291 
292  //Configure PORT1_13 as ENET0_RXDV
293  PORT_SetPinConfig(PORT1, 13, &portPinConfig);
294  //Configure PORT1_14 as ENET0_RXD0
295  PORT_SetPinConfig(PORT1, 14, &portPinConfig);
296  //Configure PORT1_15 as ENET0_RXD1
297  PORT_SetPinConfig(PORT1, 15, &portPinConfig);
298 
299  //Configure PORT1_20 as ENET0_MDC
300  PORT_SetPinConfig(PORT1, 20, &portPinConfig);
301  //Configure PORT1_21 as ENET0_MDIO
302  PORT_SetPinConfig(PORT1, 21, &portPinConfig);
303 #endif
304 }
305 
306 
307 /**
308  * @brief Initialize DMA descriptor lists
309  * @param[in] interface Underlying network interface
310  **/
311 
313 {
314  uint_t i;
315 
316  //Initialize TX DMA descriptor list
317  for(i = 0; i < MCXN547_ETH_TX_BUFFER_COUNT; i++)
318  {
319  //The descriptor is initially owned by the application
320  txDmaDesc[i].tdes0 = 0;
321  txDmaDesc[i].tdes1 = 0;
322  txDmaDesc[i].tdes2 = 0;
323  txDmaDesc[i].tdes3 = 0;
324  }
325 
326  //Initialize TX descriptor index
327  txIndex = 0;
328 
329  //Initialize RX DMA descriptor list
330  for(i = 0; i < MCXN547_ETH_RX_BUFFER_COUNT; i++)
331  {
332  //The descriptor is initially owned by the DMA
333  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
334  rxDmaDesc[i].rdes1 = 0;
335  rxDmaDesc[i].rdes2 = 0;
337  }
338 
339  //Initialize RX descriptor index
340  rxIndex = 0;
341 
342  //Start location of the TX descriptor list
343  ENET->DMA_CH[0].DMA_CHX_TXDESC_LIST_ADDR = (uint32_t) &txDmaDesc[0];
344  //Length of the transmit descriptor ring
345  ENET->DMA_CH[0].DMA_CHX_TXDESC_RING_LENGTH = MCXN547_ETH_TX_BUFFER_COUNT - 1;
346 
347  //Start location of the RX descriptor list
348  ENET->DMA_CH[0].DMA_CHX_RXDESC_LIST_ADDR = (uint32_t) &rxDmaDesc[0];
349  //Length of the receive descriptor ring
350  ENET->DMA_CH[0].DMA_CHX_RX_CONTROL2 = MCXN547_ETH_RX_BUFFER_COUNT - 1;
351 }
352 
353 
354 /**
355  * @brief MCX N547 Ethernet MAC timer handler
356  *
357  * This routine is periodically called by the TCP/IP stack to handle periodic
358  * operations such as polling the link state
359  *
360  * @param[in] interface Underlying network interface
361  **/
362 
363 void mcxn547EthTick(NetInterface *interface)
364 {
365  //Valid Ethernet PHY or switch driver?
366  if(interface->phyDriver != NULL)
367  {
368  //Handle periodic operations
369  interface->phyDriver->tick(interface);
370  }
371  else if(interface->switchDriver != NULL)
372  {
373  //Handle periodic operations
374  interface->switchDriver->tick(interface);
375  }
376  else
377  {
378  //Just for sanity
379  }
380 }
381 
382 
383 /**
384  * @brief Enable interrupts
385  * @param[in] interface Underlying network interface
386  **/
387 
389 {
390  //Enable Ethernet MAC interrupts
391  NVIC_EnableIRQ(ETHERNET_IRQn);
392 
393  //Valid Ethernet PHY or switch driver?
394  if(interface->phyDriver != NULL)
395  {
396  //Enable Ethernet PHY interrupts
397  interface->phyDriver->enableIrq(interface);
398  }
399  else if(interface->switchDriver != NULL)
400  {
401  //Enable Ethernet switch interrupts
402  interface->switchDriver->enableIrq(interface);
403  }
404  else
405  {
406  //Just for sanity
407  }
408 }
409 
410 
411 /**
412  * @brief Disable interrupts
413  * @param[in] interface Underlying network interface
414  **/
415 
417 {
418  //Disable Ethernet MAC interrupts
419  NVIC_DisableIRQ(ETHERNET_IRQn);
420 
421  //Valid Ethernet PHY or switch driver?
422  if(interface->phyDriver != NULL)
423  {
424  //Disable Ethernet PHY interrupts
425  interface->phyDriver->disableIrq(interface);
426  }
427  else if(interface->switchDriver != NULL)
428  {
429  //Disable Ethernet switch interrupts
430  interface->switchDriver->disableIrq(interface);
431  }
432  else
433  {
434  //Just for sanity
435  }
436 }
437 
438 
439 /**
440  * @brief MCX N547 Ethernet MAC interrupt service routine
441  **/
442 
444 {
445  bool_t flag;
446  uint32_t status;
447 
448  //Interrupt service routine prologue
449  osEnterIsr();
450 
451  //This flag will be set if a higher priority task must be woken
452  flag = FALSE;
453 
454  //Read DMA status register
455  status = ENET->DMA_CH[0].DMA_CHX_STAT;
456 
457  //Packet transmitted?
458  if((status & ENET_DMA_CH_DMA_CHX_STAT_TI_MASK) != 0)
459  {
460  //Clear TI interrupt flag
461  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TI_MASK;
462 
463  //Check whether the TX buffer is available for writing
464  if((txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN) == 0)
465  {
466  //Notify the TCP/IP stack that the transmitter is ready to send
467  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
468  }
469  }
470 
471  //Packet received?
472  if((status & ENET_DMA_CH_DMA_CHX_STAT_RI_MASK) != 0)
473  {
474  //Clear RI interrupt flag
475  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RI_MASK;
476 
477  //Set event flag
478  nicDriverInterface->nicEvent = TRUE;
479  //Notify the TCP/IP stack of the event
480  flag |= osSetEventFromIsr(&netEvent);
481  }
482 
483  //Clear NIS interrupt flag
484  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_NIS_MASK;
485 
486  //Interrupt service routine epilogue
487  osExitIsr(flag);
488 }
489 
490 
491 /**
492  * @brief MCX N547 Ethernet MAC event handler
493  * @param[in] interface Underlying network interface
494  **/
495 
497 {
498  error_t error;
499 
500  //Process all pending packets
501  do
502  {
503  //Read incoming packet
504  error = mcxn547EthReceivePacket(interface);
505 
506  //No more data in the receive buffer?
507  } while(error != ERROR_BUFFER_EMPTY);
508 }
509 
510 
511 /**
512  * @brief Send a packet
513  * @param[in] interface Underlying network interface
514  * @param[in] buffer Multi-part buffer containing the data to send
515  * @param[in] offset Offset to the first data byte
516  * @param[in] ancillary Additional options passed to the stack along with
517  * the packet
518  * @return Error code
519  **/
520 
522  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
523 {
524  size_t length;
525 
526  //Retrieve the length of the packet
527  length = netBufferGetLength(buffer) - offset;
528 
529  //Check the frame length
531  {
532  //The transmitter can accept another packet
533  osSetEvent(&interface->nicTxEvent);
534  //Report an error
535  return ERROR_INVALID_LENGTH;
536  }
537 
538  //Make sure the current buffer is available for writing
539  if((txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN) != 0)
540  {
541  return ERROR_FAILURE;
542  }
543 
544  //Copy user data to the transmit buffer
545  netBufferRead(txBuffer[txIndex], buffer, offset, length);
546 
547  //Set the start address of the buffer
548  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
549  //Write the number of bytes to send
550  txDmaDesc[txIndex].tdes2 = ENET_TDES2_IOC | (length & ENET_TDES2_B1L);
551  //Give the ownership of the descriptor to the DMA
553 
554  //Clear TBU flag to resume processing
555  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_TBU_MASK;
556  //Instruct the DMA to poll the transmit descriptor list
557  ENET->DMA_CH[0].DMA_CHX_TXDESC_TAIL_PTR = 0;
558 
559  //Increment index and wrap around if necessary
560  if(++txIndex >= MCXN547_ETH_TX_BUFFER_COUNT)
561  {
562  txIndex = 0;
563  }
564 
565  //Check whether the next buffer is available for writing
566  if((txDmaDesc[txIndex].tdes3 & ENET_TDES3_OWN) == 0)
567  {
568  //The transmitter can accept another packet
569  osSetEvent(&interface->nicTxEvent);
570  }
571 
572  //Data successfully written
573  return NO_ERROR;
574 }
575 
576 
577 /**
578  * @brief Receive a packet
579  * @param[in] interface Underlying network interface
580  * @return Error code
581  **/
582 
584 {
585  error_t error;
586  size_t n;
587  NetRxAncillary ancillary;
588 
589  //Current buffer available for reading?
590  if((rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_OWN) == 0)
591  {
592  //FD and LD flags should be set
593  if((rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_FD) != 0 &&
594  (rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_LD) != 0)
595  {
596  //Make sure no error occurred
597  if((rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_ES) == 0)
598  {
599  //Retrieve the length of the frame
600  n = rxDmaDesc[rxIndex].rdes3 & ENET_RDES3_PL;
601  //Limit the number of data to read
603 
604  //Additional options can be passed to the stack along with the packet
605  ancillary = NET_DEFAULT_RX_ANCILLARY;
606 
607  //Pass the packet to the upper layer
608  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
609 
610  //Valid packet received
611  error = NO_ERROR;
612  }
613  else
614  {
615  //The received packet contains an error
616  error = ERROR_INVALID_PACKET;
617  }
618  }
619  else
620  {
621  //The packet is not valid
622  error = ERROR_INVALID_PACKET;
623  }
624 
625  //Set the start address of the buffer
626  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
627  //Give the ownership of the descriptor back to the DMA
629 
630  //Increment index and wrap around if necessary
631  if(++rxIndex >= MCXN547_ETH_RX_BUFFER_COUNT)
632  {
633  rxIndex = 0;
634  }
635  }
636  else
637  {
638  //No more data in the receive buffer
639  error = ERROR_BUFFER_EMPTY;
640  }
641 
642  //Clear RBU flag to resume processing
643  ENET->DMA_CH[0].DMA_CHX_STAT = ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK;
644  //Instruct the DMA to poll the receive descriptor list
645  ENET->DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR = 0;
646 
647  //Return status code
648  return error;
649 }
650 
651 
652 /**
653  * @brief Configure MAC address filtering
654  * @param[in] interface Underlying network interface
655  * @return Error code
656  **/
657 
659 {
660  uint_t i;
661  bool_t acceptMulticast;
662 
663  //Debug message
664  TRACE_DEBUG("Updating MAC filter...\r\n");
665 
666  //Set the MAC address of the station
667  ENET->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
668  ENET->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
669 
670  //This flag will be set if multicast addresses should be accepted
671  acceptMulticast = FALSE;
672 
673  //The MAC address filter contains the list of MAC addresses to accept
674  //when receiving an Ethernet frame
675  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
676  {
677  //Valid entry?
678  if(interface->macAddrFilter[i].refCount > 0)
679  {
680  //Accept multicast addresses
681  acceptMulticast = TRUE;
682  //We are done
683  break;
684  }
685  }
686 
687  //Enable or disable the reception of multicast frames
688  if(acceptMulticast)
689  {
690  ENET->MAC_PACKET_FILTER |= ENET_MAC_PACKET_FILTER_PM_MASK;
691  }
692  else
693  {
694  ENET->MAC_PACKET_FILTER &= ~ENET_MAC_PACKET_FILTER_PM_MASK;
695  }
696 
697  //Successful processing
698  return NO_ERROR;
699 }
700 
701 
702 /**
703  * @brief Adjust MAC configuration parameters for proper operation
704  * @param[in] interface Underlying network interface
705  * @return Error code
706  **/
707 
709 {
710  uint32_t config;
711 
712  //Read current MAC configuration
713  config = ENET->MAC_CONFIGURATION;
714 
715  //10BASE-T or 100BASE-TX operation mode?
716  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
717  {
718  config |= ENET_MAC_CONFIGURATION_FES_MASK;
719  }
720  else
721  {
722  config &= ~ENET_MAC_CONFIGURATION_FES_MASK;
723  }
724 
725  //Half-duplex or full-duplex mode?
726  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
727  {
728  config |= ENET_MAC_CONFIGURATION_DM_MASK;
729  }
730  else
731  {
732  config &= ~ENET_MAC_CONFIGURATION_DM_MASK;
733  }
734 
735  //Update MAC configuration register
736  ENET->MAC_CONFIGURATION = config;
737 
738  //Successful processing
739  return NO_ERROR;
740 }
741 
742 
743 /**
744  * @brief Write PHY register
745  * @param[in] opcode Access type (2 bits)
746  * @param[in] phyAddr PHY address (5 bits)
747  * @param[in] regAddr Register address (5 bits)
748  * @param[in] data Register value
749  **/
750 
751 void mcxn547EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
752  uint8_t regAddr, uint16_t data)
753 {
754  uint32_t temp;
755 
756  //Valid opcode?
757  if(opcode == SMI_OPCODE_WRITE)
758  {
759  //Take care not to alter MDC clock configuration
760  temp = ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_CR_MASK;
761  //Set up a write operation
762  temp |= ENET_MAC_MDIO_ADDRESS_GOC_0_MASK | ENET_MAC_MDIO_ADDRESS_GB_MASK;
763 
764  //PHY address
765  temp |= ENET_MAC_MDIO_ADDRESS_PA(phyAddr);
766  //Register address
767  temp |= ENET_MAC_MDIO_ADDRESS_RDA(regAddr);
768 
769  //Data to be written in the PHY register
770  ENET->MAC_MDIO_DATA = data & ENET_MAC_MDIO_DATA_GD_MASK;
771 
772  //Start a write operation
773  ENET->MAC_MDIO_ADDRESS = temp;
774  //Wait for the write to complete
775  while((ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_GB_MASK) != 0)
776  {
777  }
778  }
779  else
780  {
781  //The MAC peripheral only supports standard Clause 22 opcodes
782  }
783 }
784 
785 
786 /**
787  * @brief Read PHY register
788  * @param[in] opcode Access type (2 bits)
789  * @param[in] phyAddr PHY address (5 bits)
790  * @param[in] regAddr Register address (5 bits)
791  * @return Register value
792  **/
793 
794 uint16_t mcxn547EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
795  uint8_t regAddr)
796 {
797  uint16_t data;
798  uint32_t temp;
799 
800  //Valid opcode?
801  if(opcode == SMI_OPCODE_READ)
802  {
803  //Take care not to alter MDC clock configuration
804  temp = ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_CR_MASK;
805 
806  //Set up a read operation
807  temp |= ENET_MAC_MDIO_ADDRESS_GOC_1_MASK |
808  ENET_MAC_MDIO_ADDRESS_GOC_0_MASK | ENET_MAC_MDIO_ADDRESS_GB_MASK;
809 
810  //PHY address
811  temp |= ENET_MAC_MDIO_ADDRESS_PA(phyAddr);
812  //Register address
813  temp |= ENET_MAC_MDIO_ADDRESS_RDA(regAddr);
814 
815  //Start a read operation
816  ENET->MAC_MDIO_ADDRESS = temp;
817  //Wait for the read to complete
818  while((ENET->MAC_MDIO_ADDRESS & ENET_MAC_MDIO_ADDRESS_GB_MASK) != 0)
819  {
820  }
821 
822  //Get register value
823  data = ENET->MAC_MDIO_DATA & ENET_MAC_MDIO_DATA_GD_MASK;
824  }
825  else
826  {
827  //The MAC peripheral only supports standard Clause 22 opcodes
828  data = 0;
829  }
830 
831  //Return the value of the PHY register
832  return data;
833 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
#define netEvent
Definition: net_legacy.h:196
void mcxn547EthEventHandler(NetInterface *interface)
MCX N547 Ethernet MAC event handler.
Transmit descriptor.
uint16_t mcxn547EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
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:690
void mcxn547EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ENET_RDES3_OWN
#define ENET_RDES3_IOC
#define ENET_RDES3_ES
#define ENET_TDES2_IOC
#define ENET_RDES3_PL
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
#define ENET_RDES3_LD
uint8_t data[]
Definition: ethernet.h:222
error_t mcxn547EthInit(NetInterface *interface)
MCX N547 Ethernet MAC initialization.
void mcxn547EthTick(NetInterface *interface)
MCX N547 Ethernet MAC timer handler.
Receive descriptor.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define osExitIsr(flag)
#define ENET_RDES3_BUF1V
#define SMI_OPCODE_WRITE
Definition: nic.h:66
error_t mcxn547EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define ENET_TDES2_B1L
#define MCXN547_ETH_TX_BUFFER_SIZE
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:43
#define MCXN547_ETH_IRQ_PRIORITY_GROUPING
error_t mcxn547EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define MCXN547_ETH_TX_BUFFER_COUNT
#define txBuffer
#define MCXN547_ETH_RX_BUFFER_SIZE
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:140
#define NetInterface
Definition: net.h:36
#define MCXN547_ETH_IRQ_SUB_PRIORITY
const NicDriver mcxn547EthDriver
MCX N547 Ethernet MAC driver.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
#define MCXN547_ETH_RX_BUFFER_COUNT
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
error_t mcxn547EthReceivePacket(NetInterface *interface)
Receive a packet.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
#define rxBuffer
#define TRACE_DEBUG(...)
Definition: debug.h:107
void mcxn547EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint16_t regAddr
#define ENET_RDES3_FD
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
#define ENET_TDES3_OWN
#define ENET_TDES3_LD
#define osEnterIsr()
__weak_func void mcxn547EthInitGpio(NetInterface *interface)
GPIO configuration.
#define ENET_TDES3_FD
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void mcxn547EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
NXP MCX N547 Ethernet MAC driver.
unsigned int uint_t
Definition: compiler_port.h:50
error_t mcxn547EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define MCXN547_ETH_IRQ_GROUP_PRIORITY
void mcxn547EthEnableIrq(NetInterface *interface)
Enable interrupts.
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
void ETHERNET_IRQHandler(void)
MCX N547 Ethernet MAC interrupt service routine.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83