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