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