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