mcxe247_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file mcxe247_eth_driver.c
3  * @brief NXP MCXE247 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.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 "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWARM compiler?
45 #if defined(__ICCARM__)
46 
47 //TX buffer
48 #pragma data_alignment = 16
50 //RX buffer
51 #pragma data_alignment = 16
53 //TX buffer descriptors
54 #pragma data_alignment = 16
55 static uint32_t txBufferDesc[MCXE247_ETH_TX_BUFFER_COUNT][8];
56 //RX buffer descriptors
57 #pragma data_alignment = 16
58 static uint32_t rxBufferDesc[MCXE247_ETH_RX_BUFFER_COUNT][8];
59 
60 //ARM or GCC compiler?
61 #else
62 
63 //TX buffer
65  __attribute__((aligned(16)));
66 //RX buffer
68  __attribute__((aligned(16)));
69 //TX buffer descriptors
70 static uint32_t txBufferDesc[MCXE247_ETH_TX_BUFFER_COUNT][8]
71  __attribute__((aligned(16)));
72 //RX buffer descriptors
73 static uint32_t rxBufferDesc[MCXE247_ETH_RX_BUFFER_COUNT][8]
74  __attribute__((aligned(16)));
75 
76 #endif
77 
78 //TX buffer index
79 static uint_t txBufferIndex;
80 //RX buffer index
81 static uint_t rxBufferIndex;
82 
83 
84 /**
85  * @brief MCXE247 Ethernet MAC driver
86  **/
87 
89 {
91  ETH_MTU,
102  TRUE,
103  TRUE,
104  TRUE,
105  FALSE
106 };
107 
108 
109 /**
110  * @brief MCXE247 Ethernet MAC initialization
111  * @param[in] interface Underlying network interface
112  * @return Error code
113  **/
114 
116 {
117  error_t error;
118  uint32_t value;
119 
120  //Debug message
121  TRACE_INFO("Initializing MCXE247 Ethernet MAC...\r\n");
122 
123  //Save underlying network interface
124  nicDriverInterface = interface;
125 
126  //Disable MPU
127  SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK;
128 
129  //Enable external reference clock
130  SIM->MISCTRL0 &= ~(SIM_MISCTRL0_RMII_CLK_SEL_MASK |
131  SIM_MISCTRL0_RMII_CLK_OBE_MASK);
132 
133  //Enable ENET peripheral clock
134  CLOCK_EnableClock(kCLOCK_Enet);
135 
136  //GPIO configuration
137  mcxe247EthInitGpio(interface);
138 
139  //Reset ENET module
140  ENET->ECR = ENET_ECR_RESET_MASK;
141  //Wait for the reset to complete
142  while((ENET->ECR & ENET_ECR_RESET_MASK) != 0)
143  {
144  }
145 
146  //Receive control register
147  ENET->RCR = ENET_RCR_MAX_FL(MCXE247_ETH_RX_BUFFER_SIZE) |
148  ENET_RCR_RMII_MODE_MASK | ENET_RCR_MII_MODE_MASK;
149 
150  //Transmit control register
151  ENET->TCR = 0;
152  //Configure MDC clock frequency
153  ENET->MSCR = ENET_MSCR_MII_SPEED(23);
154 
155  //Valid Ethernet PHY or switch driver?
156  if(interface->phyDriver != NULL)
157  {
158  //Ethernet PHY initialization
159  error = interface->phyDriver->init(interface);
160  }
161  else if(interface->switchDriver != NULL)
162  {
163  //Ethernet switch initialization
164  error = interface->switchDriver->init(interface);
165  }
166  else
167  {
168  //The interface is not properly configured
169  error = ERROR_FAILURE;
170  }
171 
172  //Any error to report?
173  if(error)
174  {
175  return error;
176  }
177 
178  //Set the MAC address of the station (upper 16 bits)
179  value = interface->macAddr.b[5];
180  value |= (interface->macAddr.b[4] << 8);
181  ENET->PAUR = ENET_PAUR_PADDR2(value) | ENET_PAUR_TYPE(0x8808);
182 
183  //Set the MAC address of the station (lower 32 bits)
184  value = interface->macAddr.b[3];
185  value |= (interface->macAddr.b[2] << 8);
186  value |= (interface->macAddr.b[1] << 16);
187  value |= (interface->macAddr.b[0] << 24);
188  ENET->PALR = ENET_PALR_PADDR1(value);
189 
190  //Hash table for unicast address filtering
191  ENET->IALR = 0;
192  ENET->IAUR = 0;
193  //Hash table for multicast address filtering
194  ENET->GALR = 0;
195  ENET->GAUR = 0;
196 
197  //Disable transmit accelerator functions
198  ENET->TACC = 0;
199  //Disable receive accelerator functions
200  ENET->RACC = 0;
201 
202  //Use enhanced buffer descriptors
203  ENET->ECR = ENET_ECR_DBSWP_MASK | ENET_ECR_EN1588_MASK;
204 
205  //Reset statistics counters
206  ENET->MIBC = ENET_MIBC_MIB_CLEAR_MASK;
207  ENET->MIBC = 0;
208 
209  //Initialize buffer descriptors
210  mcxe247EthInitBufferDesc(interface);
211 
212  //Clear any pending interrupts
213  ENET->EIR = 0xFFFFFFFF;
214  //Enable desired interrupts
215  ENET->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK;
216 
217  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
218  NVIC_SetPriorityGrouping(MCXE247_ETH_IRQ_PRIORITY_GROUPING);
219 
220  //Configure ENET transmit interrupt priority
221  NVIC_SetPriority(ENET_Transmit_IRQn, NVIC_EncodePriority(MCXE247_ETH_IRQ_PRIORITY_GROUPING,
223 
224  //Configure ENET receive interrupt priority
225  NVIC_SetPriority(ENET_Receive_IRQn, NVIC_EncodePriority(MCXE247_ETH_IRQ_PRIORITY_GROUPING,
227 
228  //Configure ENET error interrupt priority
229  NVIC_SetPriority(ENET_Error_IRQn, NVIC_EncodePriority(MCXE247_ETH_IRQ_PRIORITY_GROUPING,
231 
232  //Enable Ethernet MAC
233  ENET->ECR |= ENET_ECR_ETHEREN_MASK;
234  //Instruct the DMA to poll the receive descriptor list
235  ENET->RDAR = ENET_RDAR_RDAR_MASK;
236 
237  //Accept any packets from the upper layer
238  osSetEvent(&interface->nicTxEvent);
239 
240  //Successful initialization
241  return NO_ERROR;
242 }
243 
244 
245 /**
246  * @brief GPIO configuration
247  * @param[in] interface Underlying network interface
248  **/
249 
250 __weak_func void mcxe247EthInitGpio(NetInterface *interface)
251 {
252 //FRDM-MCXE247 evaluation board?
253 #if defined(USE_FRDM_MCXE247)
254  //Enable PORT clocks
255  CLOCK_EnableClock(kCLOCK_PortB);
256  CLOCK_EnableClock(kCLOCK_PortC);
257  CLOCK_EnableClock(kCLOCK_PortD);
258  CLOCK_EnableClock(kCLOCK_PortE);
259 
260  //Configure RMII_RXD1 (PTC0)
261  PORTC->PCR[0] = PORT_PCR_MUX(4);
262  //Configure RMII_RXD0 (PTC1)
263  PORTC->PCR[1] = PORT_PCR_MUX(5);
264  //Configure RMII_TXD0 (PTC2)
265  PORTC->PCR[2] = PORT_PCR_MUX(5);
266  //Configure RMII_CRS_DV (PTC17)
267  PORTC->PCR[17] = PORT_PCR_MUX(5);
268  //Configure RMII_TXD1 (PTD7)
269  PORTD->PCR[7] = PORT_PCR_MUX(5);
270  //Configure RMII_REF_CLK (PTD11)
271  PORTD->PCR[11] = PORT_PCR_MUX(5);
272  //Configure RMII_TXEN (PTD12)
273  PORTD->PCR[12] = PORT_PCR_MUX(5);
274 
275  //Configure RMII_MDIO (PTB4)
276  PORTB->PCR[4] = PORT_PCR_MUX(5) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
277  //Configure RMII_MDC (PTE8)
278  PORTE->PCR[8] = PORT_PCR_MUX(5);
279 
280  //Configure ENET_RESET (PTC3) as an output
281  PORTC->PCR[3] = PORT_PCR_MUX(1);
282  GPIOC->PDDR |= (1 << 3);
283 
284  //Reset PHY transceiver
285  GPIOC->PCOR |= (1 << 3);
286  sleep(10);
287  GPIOC->PSOR |= (1 << 3);
288  sleep(10);
289 #endif
290 }
291 
292 
293 /**
294  * @brief Initialize buffer descriptors
295  * @param[in] interface Underlying network interface
296  **/
297 
299 {
300  uint_t i;
301  uint32_t address;
302 
303  //Clear TX and RX buffer descriptors
304  osMemset(txBufferDesc, 0, sizeof(txBufferDesc));
305  osMemset(rxBufferDesc, 0, sizeof(rxBufferDesc));
306 
307  //Initialize TX buffer descriptors
308  for(i = 0; i < MCXE247_ETH_TX_BUFFER_COUNT; i++)
309  {
310  //Calculate the address of the current TX buffer
311  address = (uint32_t) txBuffer[i];
312  //Transmit buffer address
313  txBufferDesc[i][1] = address;
314  //Generate interrupts
315  txBufferDesc[i][2] = ENET_TBD2_INT;
316  }
317 
318  //Mark the last descriptor entry with the wrap flag
319  txBufferDesc[i - 1][0] |= ENET_TBD0_W;
320  //Initialize TX buffer index
321  txBufferIndex = 0;
322 
323  //Initialize RX buffer descriptors
324  for(i = 0; i < MCXE247_ETH_RX_BUFFER_COUNT; i++)
325  {
326  //Calculate the address of the current RX buffer
327  address = (uint32_t) rxBuffer[i];
328  //The descriptor is initially owned by the DMA
329  rxBufferDesc[i][0] = ENET_RBD0_E;
330  //Receive buffer address
331  rxBufferDesc[i][1] = address;
332  //Generate interrupts
333  rxBufferDesc[i][2] = ENET_RBD2_INT;
334  }
335 
336  //Mark the last descriptor entry with the wrap flag
337  rxBufferDesc[i - 1][0] |= ENET_RBD0_W;
338  //Initialize RX buffer index
339  rxBufferIndex = 0;
340 
341  //Start location of the TX descriptor list
342  ENET->TDSR = (uint32_t) txBufferDesc;
343  //Start location of the RX descriptor list
344  ENET->RDSR = (uint32_t) rxBufferDesc;
345  //Maximum receive buffer size
346  ENET->MRBR = MCXE247_ETH_RX_BUFFER_SIZE;
347 }
348 
349 
350 /**
351  * @brief MCXE247 Ethernet MAC timer handler
352  *
353  * This routine is periodically called by the TCP/IP stack to handle periodic
354  * operations such as polling the link state
355  *
356  * @param[in] interface Underlying network interface
357  **/
358 
359 void mcxe247EthTick(NetInterface *interface)
360 {
361  //Valid Ethernet PHY or switch driver?
362  if(interface->phyDriver != NULL)
363  {
364  //Handle periodic operations
365  interface->phyDriver->tick(interface);
366  }
367  else if(interface->switchDriver != NULL)
368  {
369  //Handle periodic operations
370  interface->switchDriver->tick(interface);
371  }
372  else
373  {
374  //Just for sanity
375  }
376 }
377 
378 
379 /**
380  * @brief Enable interrupts
381  * @param[in] interface Underlying network interface
382  **/
383 
385 {
386  //Enable Ethernet MAC interrupts
387  NVIC_EnableIRQ(ENET_Transmit_IRQn);
388  NVIC_EnableIRQ(ENET_Receive_IRQn);
389  NVIC_EnableIRQ(ENET_Error_IRQn);
390 
391  //Valid Ethernet PHY or switch driver?
392  if(interface->phyDriver != NULL)
393  {
394  //Enable Ethernet PHY interrupts
395  interface->phyDriver->enableIrq(interface);
396  }
397  else if(interface->switchDriver != NULL)
398  {
399  //Enable Ethernet switch interrupts
400  interface->switchDriver->enableIrq(interface);
401  }
402  else
403  {
404  //Just for sanity
405  }
406 }
407 
408 
409 /**
410  * @brief Disable interrupts
411  * @param[in] interface Underlying network interface
412  **/
413 
415 {
416  //Disable Ethernet MAC interrupts
417  NVIC_DisableIRQ(ENET_Transmit_IRQn);
418  NVIC_DisableIRQ(ENET_Receive_IRQn);
419  NVIC_DisableIRQ(ENET_Error_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 Ethernet MAC transmit interrupt
441  **/
442 
444 {
445  bool_t flag;
446 
447  //Interrupt service routine prologue
448  osEnterIsr();
449 
450  //This flag will be set if a higher priority task must be woken
451  flag = FALSE;
452 
453  //Packet transmitted?
454  if((ENET->EIR & ENET_EIR_TXF_MASK) != 0)
455  {
456  //Clear TXF interrupt flag
457  ENET->EIR = ENET_EIR_TXF_MASK;
458 
459  //Check whether the TX buffer is available for writing
460  if((txBufferDesc[txBufferIndex][0] & ENET_TBD0_R) == 0)
461  {
462  //Notify the TCP/IP stack that the transmitter is ready to send
463  flag = osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
464  }
465 
466  //Instruct the DMA to poll the transmit descriptor list
467  ENET->TDAR = ENET_TDAR_TDAR_MASK;
468  }
469 
470  //Interrupt service routine epilogue
471  osExitIsr(flag);
472 }
473 
474 
475 /**
476  * @brief Ethernet MAC receive interrupt
477  **/
478 
480 {
481  bool_t flag;
482 
483  //Interrupt service routine prologue
484  osEnterIsr();
485 
486  //This flag will be set if a higher priority task must be woken
487  flag = FALSE;
488 
489  //Packet received?
490  if((ENET->EIR & ENET_EIR_RXF_MASK) != 0)
491  {
492  //Disable RXF interrupt
493  ENET->EIMR &= ~ENET_EIMR_RXF_MASK;
494 
495  //Set event flag
496  nicDriverInterface->nicEvent = TRUE;
497  //Notify the TCP/IP stack of the event
498  flag = osSetEventFromIsr(&netEvent);
499  }
500 
501  //Interrupt service routine epilogue
502  osExitIsr(flag);
503 }
504 
505 
506 /**
507  * @brief Ethernet MAC error interrupt
508  **/
509 
511 {
512  bool_t flag;
513 
514  //Interrupt service routine prologue
515  osEnterIsr();
516 
517  //This flag will be set if a higher priority task must be woken
518  flag = FALSE;
519 
520  //System bus error?
521  if((ENET->EIR & ENET_EIR_EBERR_MASK) != 0)
522  {
523  //Disable EBERR interrupt
524  ENET->EIMR &= ~ENET_EIMR_EBERR_MASK;
525 
526  //Set event flag
527  nicDriverInterface->nicEvent = TRUE;
528  //Notify the TCP/IP stack of the event
529  flag |= osSetEventFromIsr(&netEvent);
530  }
531 
532  //Interrupt service routine epilogue
533  osExitIsr(flag);
534 }
535 
536 
537 /**
538  * @brief MCXE247 Ethernet MAC event handler
539  * @param[in] interface Underlying network interface
540  **/
541 
543 {
544  error_t error;
545  uint32_t status;
546 
547  //Read interrupt event register
548  status = ENET->EIR;
549 
550  //Packet received?
551  if((status & ENET_EIR_RXF_MASK) != 0)
552  {
553  //Clear RXF interrupt flag
554  ENET->EIR = ENET_EIR_RXF_MASK;
555 
556  //Process all pending packets
557  do
558  {
559  //Read incoming packet
560  error = mcxe247EthReceivePacket(interface);
561 
562  //No more data in the receive buffer?
563  } while(error != ERROR_BUFFER_EMPTY);
564  }
565 
566  //System bus error?
567  if((status & ENET_EIR_EBERR_MASK) != 0)
568  {
569  //Clear EBERR interrupt flag
570  ENET->EIR = ENET_EIR_EBERR_MASK;
571 
572  //Disable Ethernet MAC
573  ENET->ECR &= ~ENET_ECR_ETHEREN_MASK;
574  //Reset buffer descriptors
575  mcxe247EthInitBufferDesc(interface);
576  //Resume normal operation
577  ENET->ECR |= ENET_ECR_ETHEREN_MASK;
578  //Instruct the DMA to poll the receive descriptor list
579  ENET->RDAR = ENET_RDAR_RDAR_MASK;
580  }
581 
582  //Re-enable Ethernet MAC interrupts
583  ENET->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK;
584 }
585 
586 
587 /**
588  * @brief Send a packet
589  * @param[in] interface Underlying network interface
590  * @param[in] buffer Multi-part buffer containing the data to send
591  * @param[in] offset Offset to the first data byte
592  * @param[in] ancillary Additional options passed to the stack along with
593  * the packet
594  * @return Error code
595  **/
596 
598  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
599 {
600  size_t length;
601 
602  //Retrieve the length of the packet
603  length = netBufferGetLength(buffer) - offset;
604 
605  //Check the frame length
607  {
608  //The transmitter can accept another packet
609  osSetEvent(&interface->nicTxEvent);
610  //Report an error
611  return ERROR_INVALID_LENGTH;
612  }
613 
614  //Make sure the current buffer is available for writing
615  if((txBufferDesc[txBufferIndex][0] & ENET_TBD0_R) != 0)
616  {
617  return ERROR_FAILURE;
618  }
619 
620  //Copy user data to the transmit buffer
621  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
622 
623  //Clear BDU flag
624  txBufferDesc[txBufferIndex][4] = 0;
625 
626  //Check current index
627  if(txBufferIndex < (MCXE247_ETH_TX_BUFFER_COUNT - 1))
628  {
629  //Give the ownership of the descriptor to the DMA engine
630  txBufferDesc[txBufferIndex][0] = ENET_TBD0_R | ENET_TBD0_L |
632 
633  //Point to the next buffer
634  txBufferIndex++;
635  }
636  else
637  {
638  //Give the ownership of the descriptor to the DMA engine
639  txBufferDesc[txBufferIndex][0] = ENET_TBD0_R | ENET_TBD0_W |
641 
642  //Wrap around
643  txBufferIndex = 0;
644  }
645 
646  //Instruct the DMA to poll the transmit descriptor list
647  ENET->TDAR = ENET_TDAR_TDAR_MASK;
648 
649  //Check whether the next buffer is available for writing
650  if((txBufferDesc[txBufferIndex][0] & ENET_TBD0_R) == 0)
651  {
652  //The transmitter can accept another packet
653  osSetEvent(&interface->nicTxEvent);
654  }
655 
656  //Successful processing
657  return NO_ERROR;
658 }
659 
660 
661 /**
662  * @brief Receive a packet
663  * @param[in] interface Underlying network interface
664  * @return Error code
665  **/
666 
668 {
669  error_t error;
670  size_t n;
671  NetRxAncillary ancillary;
672 
673  //Current buffer available for reading?
674  if((rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_E) == 0)
675  {
676  //The frame should not span multiple buffers
677  if((rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_L) != 0)
678  {
679  //Check whether an error occurred
680  if((rxBufferDesc[rxBufferIndex][0] & (ENET_RBD0_LG | ENET_RBD0_NO |
682  {
683  //Retrieve the length of the frame
684  n = rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_DATA_LENGTH;
685  //Limit the number of data to read
687 
688  //Additional options can be passed to the stack along with the packet
689  ancillary = NET_DEFAULT_RX_ANCILLARY;
690 
691  //Pass the packet to the upper layer
692  nicProcessPacket(interface, rxBuffer[rxBufferIndex], n, &ancillary);
693 
694  //Valid packet received
695  error = NO_ERROR;
696  }
697  else
698  {
699  //The received packet contains an error
700  error = ERROR_INVALID_PACKET;
701  }
702  }
703  else
704  {
705  //The packet is not valid
706  error = ERROR_INVALID_PACKET;
707  }
708 
709  //Clear BDU flag
710  rxBufferDesc[rxBufferIndex][4] = 0;
711 
712  //Check current index
713  if(rxBufferIndex < (MCXE247_ETH_RX_BUFFER_COUNT - 1))
714  {
715  //Give the ownership of the descriptor back to the DMA engine
716  rxBufferDesc[rxBufferIndex][0] = ENET_RBD0_E;
717  //Point to the next buffer
718  rxBufferIndex++;
719  }
720  else
721  {
722  //Give the ownership of the descriptor back to the DMA engine
723  rxBufferDesc[rxBufferIndex][0] = ENET_RBD0_E | ENET_RBD0_W;
724  //Wrap around
725  rxBufferIndex = 0;
726  }
727 
728  //Instruct the DMA to poll the receive descriptor list
729  ENET->RDAR = ENET_RDAR_RDAR_MASK;
730  }
731  else
732  {
733  //No more data in the receive buffer
734  error = ERROR_BUFFER_EMPTY;
735  }
736 
737  //Return status code
738  return error;
739 }
740 
741 
742 /**
743  * @brief Configure MAC address filtering
744  * @param[in] interface Underlying network interface
745  * @return Error code
746  **/
747 
749 {
750  uint_t i;
751  uint_t k;
752  uint32_t crc;
753  uint32_t value;
754  uint32_t unicastHashTable[2];
755  uint32_t multicastHashTable[2];
756  MacFilterEntry *entry;
757 
758  //Debug message
759  TRACE_DEBUG("Updating MAC filter...\r\n");
760 
761  //Set the MAC address of the station (upper 16 bits)
762  value = interface->macAddr.b[5];
763  value |= (interface->macAddr.b[4] << 8);
764  ENET->PAUR = ENET_PAUR_PADDR2(value) | ENET_PAUR_TYPE(0x8808);
765 
766  //Set the MAC address of the station (lower 32 bits)
767  value = interface->macAddr.b[3];
768  value |= (interface->macAddr.b[2] << 8);
769  value |= (interface->macAddr.b[1] << 16);
770  value |= (interface->macAddr.b[0] << 24);
771  ENET->PALR = ENET_PALR_PADDR1(value);
772 
773  //Clear hash table (unicast address filtering)
774  unicastHashTable[0] = 0;
775  unicastHashTable[1] = 0;
776 
777  //Clear hash table (multicast address filtering)
778  multicastHashTable[0] = 0;
779  multicastHashTable[1] = 0;
780 
781  //The MAC address filter contains the list of MAC addresses to accept
782  //when receiving an Ethernet frame
783  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
784  {
785  //Point to the current entry
786  entry = &interface->macAddrFilter[i];
787 
788  //Valid entry?
789  if(entry->refCount > 0)
790  {
791  //Compute CRC over the current MAC address
792  crc = mcxe247EthCalcCrc(&entry->addr, sizeof(MacAddr));
793 
794  //The upper 6 bits in the CRC register are used to index the
795  //contents of the hash table
796  k = (crc >> 26) & 0x3F;
797 
798  //Multicast address?
799  if(macIsMulticastAddr(&entry->addr))
800  {
801  //Update the multicast hash table
802  multicastHashTable[k / 32] |= (1 << (k % 32));
803  }
804  else
805  {
806  //Update the unicast hash table
807  unicastHashTable[k / 32] |= (1 << (k % 32));
808  }
809  }
810  }
811 
812  //Write the hash table (unicast address filtering)
813  ENET->IALR = unicastHashTable[0];
814  ENET->IAUR = unicastHashTable[1];
815 
816  //Write the hash table (multicast address filtering)
817  ENET->GALR = multicastHashTable[0];
818  ENET->GAUR = multicastHashTable[1];
819 
820  //Debug message
821  TRACE_DEBUG(" IALR = %08" PRIX32 "\r\n", ENET->IALR);
822  TRACE_DEBUG(" IAUR = %08" PRIX32 "\r\n", ENET->IAUR);
823  TRACE_DEBUG(" GALR = %08" PRIX32 "\r\n", ENET->GALR);
824  TRACE_DEBUG(" GAUR = %08" PRIX32 "\r\n", ENET->GAUR);
825 
826  //Successful processing
827  return NO_ERROR;
828 }
829 
830 
831 /**
832  * @brief Adjust MAC configuration parameters for proper operation
833  * @param[in] interface Underlying network interface
834  * @return Error code
835  **/
836 
838 {
839  //Disable Ethernet MAC while modifying configuration registers
840  ENET->ECR &= ~ENET_ECR_ETHEREN_MASK;
841 
842  //10BASE-T or 100BASE-TX operation mode?
843  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
844  {
845  //100 Mbps operation
846  ENET->RCR &= ~ENET_RCR_RMII_10T_MASK;
847  }
848  else
849  {
850  //10 Mbps operation
851  ENET->RCR |= ENET_RCR_RMII_10T_MASK;
852  }
853 
854  //Half-duplex or full-duplex mode?
855  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
856  {
857  //Full-duplex mode
858  ENET->TCR |= ENET_TCR_FDEN_MASK;
859  //Receive path operates independently of transmit
860  ENET->RCR &= ~ENET_RCR_DRT_MASK;
861  }
862  else
863  {
864  //Half-duplex mode
865  ENET->TCR &= ~ENET_TCR_FDEN_MASK;
866  //Disable reception of frames while transmitting
867  ENET->RCR |= ENET_RCR_DRT_MASK;
868  }
869 
870  //Reset buffer descriptors
871  mcxe247EthInitBufferDesc(interface);
872 
873  //Re-enable Ethernet MAC
874  ENET->ECR |= ENET_ECR_ETHEREN_MASK;
875  //Instruct the DMA to poll the receive descriptor list
876  ENET->RDAR = ENET_RDAR_RDAR_MASK;
877 
878  //Successful processing
879  return NO_ERROR;
880 }
881 
882 
883 /**
884  * @brief Write PHY register
885  * @param[in] opcode Access type (2 bits)
886  * @param[in] phyAddr PHY address (5 bits)
887  * @param[in] regAddr Register address (5 bits)
888  * @param[in] data Register value
889  **/
890 
891 void mcxe247EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
892  uint8_t regAddr, uint16_t data)
893 {
894  uint32_t temp;
895 
896  //Valid opcode?
897  if(opcode == SMI_OPCODE_WRITE)
898  {
899  //Set up a write operation
900  temp = ENET_MMFR_ST(1) | ENET_MMFR_OP(1) | ENET_MMFR_TA(2);
901  //PHY address
902  temp |= ENET_MMFR_PA(phyAddr);
903  //Register address
904  temp |= ENET_MMFR_RA(regAddr);
905  //Register value
906  temp |= ENET_MMFR_DATA(data);
907 
908  //Clear MII interrupt flag
909  ENET->EIR = ENET_EIR_MII_MASK;
910  //Start a write operation
911  ENET->MMFR = temp;
912 
913  //Wait for the write to complete
914  while((ENET->EIR & ENET_EIR_MII_MASK) == 0)
915  {
916  }
917  }
918  else
919  {
920  //The MAC peripheral only supports standard Clause 22 opcodes
921  }
922 }
923 
924 
925 /**
926  * @brief Read PHY register
927  * @param[in] opcode Access type (2 bits)
928  * @param[in] phyAddr PHY address (5 bits)
929  * @param[in] regAddr Register address (5 bits)
930  * @return Register value
931  **/
932 
933 uint16_t mcxe247EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
934  uint8_t regAddr)
935 {
936  uint16_t data;
937  uint32_t temp;
938 
939  //Valid opcode?
940  if(opcode == SMI_OPCODE_READ)
941  {
942  //Set up a read operation
943  temp = ENET_MMFR_ST(1) | ENET_MMFR_OP(2) | ENET_MMFR_TA(2);
944  //PHY address
945  temp |= ENET_MMFR_PA(phyAddr);
946  //Register address
947  temp |= ENET_MMFR_RA(regAddr);
948 
949  //Clear MII interrupt flag
950  ENET->EIR = ENET_EIR_MII_MASK;
951  //Start a read operation
952  ENET->MMFR = temp;
953 
954  //Wait for the read to complete
955  while((ENET->EIR & ENET_EIR_MII_MASK) == 0)
956  {
957  }
958 
959  //Get register value
960  data = ENET->MMFR & ENET_MMFR_DATA_MASK;
961  }
962  else
963  {
964  //The MAC peripheral only supports standard Clause 22 opcodes
965  data = 0;
966  }
967 
968  //Return the value of the PHY register
969  return data;
970 }
971 
972 
973 /**
974  * @brief CRC calculation
975  * @param[in] data Pointer to the data over which to calculate the CRC
976  * @param[in] length Number of bytes to process
977  * @return Resulting CRC value
978  **/
979 
980 uint32_t mcxe247EthCalcCrc(const void *data, size_t length)
981 {
982  uint_t i;
983  uint_t j;
984  uint32_t crc;
985  const uint8_t *p;
986 
987  //Point to the data over which to calculate the CRC
988  p = (uint8_t *) data;
989  //CRC preset value
990  crc = 0xFFFFFFFF;
991 
992  //Loop through data
993  for(i = 0; i < length; i++)
994  {
995  //Update CRC value
996  crc ^= p[i];
997 
998  //The message is processed bit by bit
999  for(j = 0; j < 8; j++)
1000  {
1001  if((crc & 0x01) != 0)
1002  {
1003  crc = (crc >> 1) ^ 0xEDB88320;
1004  }
1005  else
1006  {
1007  crc = crc >> 1;
1008  }
1009  }
1010  }
1011 
1012  //Return CRC value
1013  return crc;
1014 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define MCXE247_ETH_IRQ_SUB_PRIORITY
uint8_t opcode
Definition: dns_common.h:191
#define MCXE247_ETH_IRQ_GROUP_PRIORITY
#define MCXE247_ETH_RX_BUFFER_SIZE
int bool_t
Definition: compiler_port.h:61
#define netEvent
Definition: net_legacy.h:196
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define ENET_TBD0_L
const NicDriver mcxe247EthDriver
MCXE247 Ethernet MAC driver.
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 mcxe247EthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
#define ENET_RBD0_DATA_LENGTH
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
error_t mcxe247EthInit(NetInterface *interface)
MCXE247 Ethernet MAC initialization.
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
#define sleep(delay)
Definition: os_port.h:310
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
NXP MCXE247 Ethernet MAC driver.
#define ENET_TBD0_DATA_LENGTH
#define ENET_TBD0_W
#define ENET_TBD0_TC
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 macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define MCXE247_ETH_IRQ_PRIORITY_GROUPING
#define MCXE247_ETH_TX_BUFFER_SIZE
#define ENET_RBD0_L
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:43
void ENET_Receive_IRQHandler(void)
Ethernet MAC receive interrupt.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
void mcxe247EthEventHandler(NetInterface *interface)
MCXE247 Ethernet MAC event handler.
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:265
#define MCXE247_ETH_TX_BUFFER_COUNT
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define ENET_RBD0_W
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
error_t mcxe247EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define ENET_RBD0_TR
uint32_t mcxe247EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
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
error_t mcxe247EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
MacAddr
Definition: ethernet.h:197
void mcxe247EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define ENET_RBD0_LG
void mcxe247EthTick(NetInterface *interface)
MCXE247 Ethernet MAC timer handler.
#define TRACE_DEBUG(...)
Definition: debug.h:119
void ENET_Error_IRQHandler(void)
Ethernet MAC error interrupt.
__weak_func void mcxe247EthInitGpio(NetInterface *interface)
GPIO configuration.
#define MCXE247_ETH_RX_BUFFER_COUNT
uint16_t regAddr
#define ENET_RBD0_CR
#define ENET_RBD0_OV
#define ETH_MTU
Definition: ethernet.h:116
uint16_t mcxe247EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
uint8_t n
error_t mcxe247EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
MAC filter table entry.
Definition: ethernet.h:264
void mcxe247EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
Ipv6Addr address[]
Definition: ipv6.h:325
#define osEnterIsr()
#define ENET_TBD0_R
void mcxe247EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint8_t value[]
Definition: tcp.h:376
#define ENET_TBD2_INT
#define ENET_RBD0_E
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void ENET_Transmit_IRQHandler(void)
Ethernet MAC transmit interrupt.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
error_t mcxe247EthReceivePacket(NetInterface *interface)
Receive a packet.
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define ENET_RBD0_NO
#define ENET_RBD2_INT
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83