mk7x_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file mk7x_eth_driver.c
3  * @brief Freescale Kinetis K70 Ethernet MAC controller
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NIC_TRACE_LEVEL
31 
32 //MK70F12 device?
33 #if defined(MK70F12)
34  #include "mk70f12.h"
35 //MK70F15 device?
36 #elif defined(MK70F15)
37  #include "mk70f15.h"
38 #endif
39 
40 //Dependencies
41 #include "core/net.h"
43 #include "debug.h"
44 
45 //Underlying network interface
46 static NetInterface *nicDriverInterface;
47 
48 //IAR EWARM compiler?
49 #if defined(__ICCARM__)
50 
51 //TX buffer
52 #pragma data_alignment = 16
54 //RX buffer
55 #pragma data_alignment = 16
57 //TX buffer descriptors
58 #pragma data_alignment = 16
59 static uint32_t txBufferDesc[MK7X_ETH_TX_BUFFER_COUNT][8];
60 //RX buffer descriptors
61 #pragma data_alignment = 16
62 static uint32_t rxBufferDesc[MK7X_ETH_RX_BUFFER_COUNT][8];
63 
64 //ARM or GCC compiler?
65 #else
66 
67 //TX buffer
69  __attribute__((aligned(16)));
70 //RX buffer
72  __attribute__((aligned(16)));
73 //TX buffer descriptors
74 static uint32_t txBufferDesc[MK7X_ETH_TX_BUFFER_COUNT][8]
75  __attribute__((aligned(16)));
76 //RX buffer descriptors
77 static uint32_t rxBufferDesc[MK7X_ETH_RX_BUFFER_COUNT][8]
78  __attribute__((aligned(16)));
79 
80 #endif
81 
82 //TX buffer index
83 static uint_t txBufferIndex;
84 //RX buffer index
85 static uint_t rxBufferIndex;
86 
87 
88 /**
89  * @brief Kinetis K7x Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief Kinetis K7x Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122  uint32_t value;
123 
124  //Debug message
125  TRACE_INFO("Initializing Kinetis K7x Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //Disable MPU
131  MPU->CESR &= ~MPU_CESR_VLD_MASK;
132 
133  //Enable external reference clock
134  OSC0->CR |= OSC_CR_ERCLKEN_MASK;
135  //Enable ENET peripheral clock
136  SIM->SCGC2 |= SIM_SCGC2_ENET_MASK;
137 
138  //GPIO configuration
139  mk7xEthInitGpio(interface);
140 
141  //Reset ENET module
142  ENET->ECR = ENET_ECR_RESET_MASK;
143  //Wait for the reset to complete
144  while(ENET->ECR & ENET_ECR_RESET_MASK);
145 
146  //Receive control register
147  ENET->RCR = ENET_RCR_MAX_FL(1518) | ENET_RCR_RMII_MODE_MASK |
148  ENET_RCR_MII_MODE_MASK;
149 
150  //Transmit control register
151  ENET->TCR = 0;
152  //Configure MDC clock frequency
153  ENET->MSCR = ENET_MSCR_MII_SPEED(59);
154 
155  //PHY transceiver initialization
156  error = interface->phyDriver->init(interface);
157  //Failed to initialize PHY transceiver?
158  if(error)
159  return error;
160 
161  //Set the MAC address (upper 16 bits)
162  value = interface->macAddr.b[5];
163  value |= (interface->macAddr.b[4] << 8);
164  ENET->PAUR = ENET_PAUR_PADDR2(value) | ENET_PAUR_TYPE(0x8808);
165 
166  //Set the MAC address (lower 32 bits)
167  value = interface->macAddr.b[3];
168  value |= (interface->macAddr.b[2] << 8);
169  value |= (interface->macAddr.b[1] << 16);
170  value |= (interface->macAddr.b[0] << 24);
171  ENET->PALR = ENET_PALR_PADDR1(value);
172 
173  //Hash table for unicast address filtering
174  ENET->IALR = 0;
175  ENET->IAUR = 0;
176  //Hash table for multicast address filtering
177  ENET->GALR = 0;
178  ENET->GAUR = 0;
179 
180  //Disable transmit accelerator functions
181  ENET->TACC = 0;
182  //Disable receive accelerator functions
183  ENET->RACC = 0;
184 
185  //Use enhanced buffer descriptors
186  ENET->ECR = ENET_ECR_DBSWP_MASK | ENET_ECR_EN1588_MASK;
187  //Clear MIC counters
188  ENET->MIBC = ENET_MIBC_MIB_CLEAR_MASK;
189 
190  //Initialize buffer descriptors
191  mk7xEthInitBufferDesc(interface);
192 
193  //Clear any pending interrupts
194  ENET->EIR = 0xFFFFFFFF;
195  //Enable desired interrupts
196  ENET->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK;
197 
198  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
199  NVIC_SetPriorityGrouping(MK7X_ETH_IRQ_PRIORITY_GROUPING);
200 
201  //Configure ENET transmit interrupt priority
202  NVIC_SetPriority(ENET_Transmit_IRQn, NVIC_EncodePriority(MK7X_ETH_IRQ_PRIORITY_GROUPING,
204 
205  //Configure ENET receive interrupt priority
206  NVIC_SetPriority(ENET_Receive_IRQn, NVIC_EncodePriority(MK7X_ETH_IRQ_PRIORITY_GROUPING,
208 
209  //Configure ENET error interrupt priority
210  NVIC_SetPriority(ENET_Error_IRQn, NVIC_EncodePriority(MK7X_ETH_IRQ_PRIORITY_GROUPING,
212 
213  //Enable Ethernet MAC
214  ENET->ECR |= ENET_ECR_ETHEREN_MASK;
215  //Instruct the DMA to poll the receive descriptor list
216  ENET->RDAR = ENET_RDAR_RDAR_MASK;
217 
218  //Accept any packets from the upper layer
219  osSetEvent(&interface->nicTxEvent);
220 
221  //Successful initialization
222  return NO_ERROR;
223 }
224 
225 
226 //TWR-K70F120M evaluation board?
227 #if defined(USE_TWR_K70F120M)
228 
229 /**
230  * @brief GPIO configuration
231  * @param[in] interface Underlying network interface
232  **/
233 
234 void mk7xEthInitGpio(NetInterface *interface)
235 {
236  //Enable PORTA and PORTB peripheral clocks
237  SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK;
238 
239  //Configure RMII0_RXER (PTA5)
240  PORTA->PCR[5] = PORT_PCR_MUX(4) | PORT_PCR_PE_MASK;
241  //Configure RMII0_RXD1 (PTA12)
242  PORTA->PCR[12] = PORT_PCR_MUX(4);
243  //Configure RMII0_RXD0 (PTA13)
244  PORTA->PCR[13] = PORT_PCR_MUX(4);
245  //Configure RMII0_CRS_DV (PTA14)
246  PORTA->PCR[14] = PORT_PCR_MUX(4);
247  //Configure RMII0_TXEN (PTA15)
248  PORTA->PCR[15] = PORT_PCR_MUX(4);
249  //Configure RMII0_TXD0 (PTA16)
250  PORTA->PCR[16] = PORT_PCR_MUX(4);
251  //Configure RMII0_TXD1 (PTA17)
252  PORTA->PCR[17] = PORT_PCR_MUX(4);
253 
254  //Configure RMII0_MDIO (PTB0)
255  PORTB->PCR[0] = PORT_PCR_MUX(4) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
256  //Configure RMII0_MDC (PTB1)
257  PORTB->PCR[1] = PORT_PCR_MUX(4);
258 }
259 
260 #endif
261 
262 
263 /**
264  * @brief Initialize buffer descriptors
265  * @param[in] interface Underlying network interface
266  **/
267 
269 {
270  uint_t i;
271  uint32_t address;
272 
273  //Clear TX and RX buffer descriptors
274  memset(txBufferDesc, 0, sizeof(txBufferDesc));
275  memset(rxBufferDesc, 0, sizeof(rxBufferDesc));
276 
277  //Initialize TX buffer descriptors
278  for(i = 0; i < MK7X_ETH_TX_BUFFER_COUNT; i++)
279  {
280  //Calculate the address of the current TX buffer
281  address = (uint32_t) txBuffer[i];
282  //Transmit buffer address
283  txBufferDesc[i][1] = address;
284  //Generate interrupts
285  txBufferDesc[i][2] = ENET_TBD2_INT;
286  }
287 
288  //Mark the last descriptor entry with the wrap flag
289  txBufferDesc[i - 1][0] |= ENET_TBD0_W;
290  //Initialize TX buffer index
291  txBufferIndex = 0;
292 
293  //Initialize RX buffer descriptors
294  for(i = 0; i < MK7X_ETH_RX_BUFFER_COUNT; i++)
295  {
296  //Calculate the address of the current RX buffer
297  address = (uint32_t) rxBuffer[i];
298  //The descriptor is initially owned by the DMA
299  rxBufferDesc[i][0] = ENET_RBD0_E;
300  //Receive buffer address
301  rxBufferDesc[i][1] = address;
302  //Generate interrupts
303  rxBufferDesc[i][2] = ENET_RBD2_INT;
304  }
305 
306  //Mark the last descriptor entry with the wrap flag
307  rxBufferDesc[i - 1][0] |= ENET_RBD0_W;
308  //Initialize RX buffer index
309  rxBufferIndex = 0;
310 
311  //Start location of the TX descriptor list
312  ENET->TDSR = (uint32_t) txBufferDesc;
313  //Start location of the RX descriptor list
314  ENET->RDSR = (uint32_t) rxBufferDesc;
315  //Maximum receive buffer size
316  ENET->MRBR = MK7X_ETH_RX_BUFFER_SIZE;
317 }
318 
319 
320 /**
321  * @brief Kinetis K7x Ethernet MAC timer handler
322  *
323  * This routine is periodically called by the TCP/IP stack to
324  * handle periodic operations such as polling the link state
325  *
326  * @param[in] interface Underlying network interface
327  **/
328 
329 void mk7xEthTick(NetInterface *interface)
330 {
331  //Handle periodic operations
332  interface->phyDriver->tick(interface);
333 }
334 
335 
336 /**
337  * @brief Enable interrupts
338  * @param[in] interface Underlying network interface
339  **/
340 
342 {
343  //Enable Ethernet MAC interrupts
344  NVIC_EnableIRQ(ENET_Transmit_IRQn);
345  NVIC_EnableIRQ(ENET_Receive_IRQn);
346  NVIC_EnableIRQ(ENET_Error_IRQn);
347 
348  //Enable Ethernet PHY interrupts
349  interface->phyDriver->enableIrq(interface);
350 }
351 
352 
353 /**
354  * @brief Disable interrupts
355  * @param[in] interface Underlying network interface
356  **/
357 
359 {
360  //Disable Ethernet MAC interrupts
361  NVIC_DisableIRQ(ENET_Transmit_IRQn);
362  NVIC_DisableIRQ(ENET_Receive_IRQn);
363  NVIC_DisableIRQ(ENET_Error_IRQn);
364 
365  //Disable Ethernet PHY interrupts
366  interface->phyDriver->disableIrq(interface);
367 }
368 
369 
370 /**
371  * @brief Ethernet MAC transmit interrupt
372  **/
373 
375 {
376  bool_t flag;
377 
378  //Enter interrupt service routine
379  osEnterIsr();
380 
381  //This flag will be set if a higher priority task must be woken
382  flag = FALSE;
383 
384  //A packet has been transmitted?
385  if(ENET->EIR & ENET_EIR_TXF_MASK)
386  {
387  //Clear TXF interrupt flag
388  ENET->EIR = ENET_EIR_TXF_MASK;
389 
390  //Check whether the TX buffer is available for writing
391  if(!(txBufferDesc[txBufferIndex][0] & ENET_TBD0_R))
392  {
393  //Notify the TCP/IP stack that the transmitter is ready to send
394  flag = osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
395  }
396 
397  //Instruct the DMA to poll the transmit descriptor list
398  ENET->TDAR = ENET_TDAR_TDAR_MASK;
399  }
400 
401  //Leave interrupt service routine
402  osExitIsr(flag);
403 }
404 
405 
406 /**
407  * @brief Ethernet MAC receive interrupt
408  **/
409 
411 {
412  bool_t flag;
413 
414  //Enter interrupt service routine
415  osEnterIsr();
416 
417  //This flag will be set if a higher priority task must be woken
418  flag = FALSE;
419 
420  //A packet has been received?
421  if(ENET->EIR & ENET_EIR_RXF_MASK)
422  {
423  //Disable RXF interrupt
424  ENET->EIMR &= ~ENET_EIMR_RXF_MASK;
425 
426  //Set event flag
427  nicDriverInterface->nicEvent = TRUE;
428  //Notify the TCP/IP stack of the event
429  flag = osSetEventFromIsr(&netEvent);
430  }
431 
432  //Leave interrupt service routine
433  osExitIsr(flag);
434 }
435 
436 
437 /**
438  * @brief Ethernet MAC error interrupt
439  **/
440 
442 {
443  bool_t flag;
444 
445  //Enter interrupt service routine
446  osEnterIsr();
447 
448  //This flag will be set if a higher priority task must be woken
449  flag = FALSE;
450 
451  //System bus error?
452  if(ENET->EIR & ENET_EIR_EBERR_MASK)
453  {
454  //Disable EBERR interrupt
455  ENET->EIMR &= ~ENET_EIMR_EBERR_MASK;
456 
457  //Set event flag
458  nicDriverInterface->nicEvent = TRUE;
459  //Notify the TCP/IP stack of the event
460  flag |= osSetEventFromIsr(&netEvent);
461  }
462 
463  //Leave interrupt service routine
464  osExitIsr(flag);
465 }
466 
467 
468 /**
469  * @brief Kinetis K7x Ethernet MAC event handler
470  * @param[in] interface Underlying network interface
471  **/
472 
474 {
475  error_t error;
476  uint32_t status;
477 
478  //Read interrupt event register
479  status = ENET->EIR;
480 
481  //Packet received?
482  if(status & ENET_EIR_RXF_MASK)
483  {
484  //Clear RXF interrupt flag
485  ENET->EIR = ENET_EIR_RXF_MASK;
486 
487  //Process all pending packets
488  do
489  {
490  //Read incoming packet
491  error = mk7xEthReceivePacket(interface);
492 
493  //No more data in the receive buffer?
494  } while(error != ERROR_BUFFER_EMPTY);
495  }
496 
497  //System bus error?
498  if(status & ENET_EIR_EBERR_MASK)
499  {
500  //Clear EBERR interrupt flag
501  ENET->EIR = ENET_EIR_EBERR_MASK;
502 
503  //Disable Ethernet MAC
504  ENET->ECR &= ~ENET_ECR_ETHEREN_MASK;
505  //Reset buffer descriptors
506  mk7xEthInitBufferDesc(interface);
507  //Resume normal operation
508  ENET->ECR |= ENET_ECR_ETHEREN_MASK;
509  //Instruct the DMA to poll the receive descriptor list
510  ENET->RDAR = ENET_RDAR_RDAR_MASK;
511  }
512 
513  //Re-enable Ethernet MAC interrupts
514  ENET->EIMR = ENET_EIMR_TXF_MASK | ENET_EIMR_RXF_MASK | ENET_EIMR_EBERR_MASK;
515 }
516 
517 
518 /**
519  * @brief Send a packet
520  * @param[in] interface Underlying network interface
521  * @param[in] buffer Multi-part buffer containing the data to send
522  * @param[in] offset Offset to the first data byte
523  * @return Error code
524  **/
525 
527  const NetBuffer *buffer, size_t offset)
528 {
529  size_t length;
530 
531  //Retrieve the length of the packet
532  length = netBufferGetLength(buffer) - offset;
533 
534  //Check the frame length
536  {
537  //The transmitter can accept another packet
538  osSetEvent(&interface->nicTxEvent);
539  //Report an error
540  return ERROR_INVALID_LENGTH;
541  }
542 
543  //Make sure the current buffer is available for writing
544  if(txBufferDesc[txBufferIndex][0] & ENET_TBD0_R)
545  return ERROR_FAILURE;
546 
547  //Copy user data to the transmit buffer
548  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
549 
550  //Clear BDU flag
551  txBufferDesc[txBufferIndex][4] = 0;
552 
553  //Check current index
554  if(txBufferIndex < (MK7X_ETH_TX_BUFFER_COUNT - 1))
555  {
556  //Give the ownership of the descriptor to the DMA engine
557  txBufferDesc[txBufferIndex][0] = ENET_TBD0_R | ENET_TBD0_L |
559 
560  //Point to the next buffer
561  txBufferIndex++;
562  }
563  else
564  {
565  //Give the ownership of the descriptor to the DMA engine
566  txBufferDesc[txBufferIndex][0] = ENET_TBD0_R | ENET_TBD0_W |
568 
569  //Wrap around
570  txBufferIndex = 0;
571  }
572 
573  //Instruct the DMA to poll the transmit descriptor list
574  ENET->TDAR = ENET_TDAR_TDAR_MASK;
575 
576  //Check whether the next buffer is available for writing
577  if(!(txBufferDesc[txBufferIndex][0] & ENET_TBD0_R))
578  {
579  //The transmitter can accept another packet
580  osSetEvent(&interface->nicTxEvent);
581  }
582 
583  //Successful processing
584  return NO_ERROR;
585 }
586 
587 
588 /**
589  * @brief Receive a packet
590  * @param[in] interface Underlying network interface
591  * @return Error code
592  **/
593 
595 {
596  error_t error;
597  size_t n;
598 
599  //Make sure the current buffer is available for reading
600  if(!(rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_E))
601  {
602  //The frame should not span multiple buffers
603  if(rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_L)
604  {
605  //Check whether an error occurred
606  if(!(rxBufferDesc[rxBufferIndex][0] & (ENET_RBD0_LG |
608  {
609  //Retrieve the length of the frame
610  n = rxBufferDesc[rxBufferIndex][0] & ENET_RBD0_DATA_LENGTH;
611  //Limit the number of data to read
613 
614  //Pass the packet to the upper layer
615  nicProcessPacket(interface, rxBuffer[rxBufferIndex], n);
616 
617  //Valid packet received
618  error = NO_ERROR;
619  }
620  else
621  {
622  //The received packet contains an error
623  error = ERROR_INVALID_PACKET;
624  }
625  }
626  else
627  {
628  //The packet is not valid
629  error = ERROR_INVALID_PACKET;
630  }
631 
632  //Clear BDU flag
633  rxBufferDesc[rxBufferIndex][4] = 0;
634 
635  //Check current index
636  if(rxBufferIndex < (MK7X_ETH_RX_BUFFER_COUNT - 1))
637  {
638  //Give the ownership of the descriptor back to the DMA engine
639  rxBufferDesc[rxBufferIndex][0] = ENET_RBD0_E;
640  //Point to the next buffer
641  rxBufferIndex++;
642  }
643  else
644  {
645  //Give the ownership of the descriptor back to the DMA engine
646  rxBufferDesc[rxBufferIndex][0] = ENET_RBD0_E | ENET_RBD0_W;
647  //Wrap around
648  rxBufferIndex = 0;
649  }
650 
651  //Instruct the DMA to poll the receive descriptor list
652  ENET->RDAR = ENET_RDAR_RDAR_MASK;
653  }
654  else
655  {
656  //No more data in the receive buffer
657  error = ERROR_BUFFER_EMPTY;
658  }
659 
660  //Return status code
661  return error;
662 }
663 
664 
665 /**
666  * @brief Configure MAC address filtering
667  * @param[in] interface Underlying network interface
668  * @return Error code
669  **/
670 
672 {
673  uint_t i;
674  uint_t k;
675  uint32_t crc;
676  uint32_t unicastHashTable[2];
677  uint32_t multicastHashTable[2];
678  MacFilterEntry *entry;
679 
680  //Debug message
681  TRACE_DEBUG("Updating Kinetis K7x hash table...\r\n");
682 
683  //Clear hash table (unicast address filtering)
684  unicastHashTable[0] = 0;
685  unicastHashTable[1] = 0;
686 
687  //Clear hash table (multicast address filtering)
688  multicastHashTable[0] = 0;
689  multicastHashTable[1] = 0;
690 
691  //The MAC address filter contains the list of MAC addresses to accept
692  //when receiving an Ethernet frame
693  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
694  {
695  //Point to the current entry
696  entry = &interface->macAddrFilter[i];
697 
698  //Valid entry?
699  if(entry->refCount > 0)
700  {
701  //Compute CRC over the current MAC address
702  crc = mk7xEthCalcCrc(&entry->addr, sizeof(MacAddr));
703 
704  //The upper 6 bits in the CRC register are used to index the
705  //contents of the hash table
706  k = (crc >> 26) & 0x3F;
707 
708  //Multicast address?
709  if(macIsMulticastAddr(&entry->addr))
710  {
711  //Update the multicast hash table
712  multicastHashTable[k / 32] |= (1 << (k % 32));
713  }
714  else
715  {
716  //Update the unicast hash table
717  unicastHashTable[k / 32] |= (1 << (k % 32));
718  }
719  }
720  }
721 
722  //Write the hash table (unicast address filtering)
723  ENET->IALR = unicastHashTable[0];
724  ENET->IAUR = unicastHashTable[1];
725 
726  //Write the hash table (multicast address filtering)
727  ENET->GALR = multicastHashTable[0];
728  ENET->GAUR = multicastHashTable[1];
729 
730  //Debug message
731  TRACE_DEBUG(" IALR = %08" PRIX32 "\r\n", ENET->IALR);
732  TRACE_DEBUG(" IAUR = %08" PRIX32 "\r\n", ENET->IAUR);
733  TRACE_DEBUG(" GALR = %08" PRIX32 "\r\n", ENET->GALR);
734  TRACE_DEBUG(" GAUR = %08" PRIX32 "\r\n", ENET->GAUR);
735 
736  //Successful processing
737  return NO_ERROR;
738 }
739 
740 
741 /**
742  * @brief Adjust MAC configuration parameters for proper operation
743  * @param[in] interface Underlying network interface
744  * @return Error code
745  **/
746 
748 {
749  //Disable Ethernet MAC while modifying configuration registers
750  ENET->ECR &= ~ENET_ECR_ETHEREN_MASK;
751 
752  //10BASE-T or 100BASE-TX operation mode?
753  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
754  {
755  //100 Mbps operation
756  ENET->RCR &= ~ENET_RCR_RMII_10T_MASK;
757  }
758  else
759  {
760  //10 Mbps operation
761  ENET->RCR |= ENET_RCR_RMII_10T_MASK;
762  }
763 
764  //Half-duplex or full-duplex mode?
765  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
766  {
767  //Full-duplex mode
768  ENET->TCR |= ENET_TCR_FDEN_MASK;
769  //Receive path operates independently of transmit
770  ENET->RCR &= ~ENET_RCR_DRT_MASK;
771  }
772  else
773  {
774  //Half-duplex mode
775  ENET->TCR &= ~ENET_TCR_FDEN_MASK;
776  //Disable reception of frames while transmitting
777  ENET->RCR |= ENET_RCR_DRT_MASK;
778  }
779 
780  //Reset buffer descriptors
781  mk7xEthInitBufferDesc(interface);
782 
783  //Re-enable Ethernet MAC
784  ENET->ECR |= ENET_ECR_ETHEREN_MASK;
785  //Instruct the DMA to poll the receive descriptor list
786  ENET->RDAR = ENET_RDAR_RDAR_MASK;
787 
788  //Successful processing
789  return NO_ERROR;
790 }
791 
792 
793 /**
794  * @brief Write PHY register
795  * @param[in] phyAddr PHY address
796  * @param[in] regAddr Register address
797  * @param[in] data Register value
798  **/
799 
800 void mk7xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
801 {
802  uint32_t value;
803 
804  //Set up a write operation
805  value = ENET_MMFR_ST(1) | ENET_MMFR_OP(1) | ENET_MMFR_TA(2);
806  //PHY address
807  value |= ENET_MMFR_PA(phyAddr);
808  //Register address
809  value |= ENET_MMFR_RA(regAddr);
810  //Register value
811  value |= ENET_MMFR_DATA(data);
812 
813  //Clear MII interrupt flag
814  ENET->EIR = ENET_EIR_MII_MASK;
815  //Start a write operation
816  ENET->MMFR = value;
817  //Wait for the write to complete
818  while(!(ENET->EIR & ENET_EIR_MII_MASK));
819 }
820 
821 
822 /**
823  * @brief Read PHY register
824  * @param[in] phyAddr PHY address
825  * @param[in] regAddr Register address
826  * @return Register value
827  **/
828 
829 uint16_t mk7xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
830 {
831  uint32_t value;
832 
833  //Set up a read operation
834  value = ENET_MMFR_ST(1) | ENET_MMFR_OP(2) | ENET_MMFR_TA(2);
835  //PHY address
836  value |= ENET_MMFR_PA(phyAddr);
837  //Register address
838  value |= ENET_MMFR_RA(regAddr);
839 
840  //Clear MII interrupt flag
841  ENET->EIR = ENET_EIR_MII_MASK;
842  //Start a read operation
843  ENET->MMFR = value;
844  //Wait for the read to complete
845  while(!(ENET->EIR & ENET_EIR_MII_MASK));
846 
847  //Return PHY register contents
848  return ENET->MMFR & ENET_MMFR_DATA_MASK;
849 }
850 
851 
852 /**
853  * @brief CRC calculation
854  * @param[in] data Pointer to the data over which to calculate the CRC
855  * @param[in] length Number of bytes to process
856  * @return Resulting CRC value
857  **/
858 
859 uint32_t mk7xEthCalcCrc(const void *data, size_t length)
860 {
861  uint_t i;
862  uint_t j;
863 
864  //Point to the data over which to calculate the CRC
865  const uint8_t *p = (uint8_t *) data;
866  //CRC preset value
867  uint32_t crc = 0xFFFFFFFF;
868 
869  //Loop through data
870  for(i = 0; i < length; i++)
871  {
872  //Update CRC value
873  crc ^= p[i];
874  //The message is processed bit by bit
875  for(j = 0; j < 8; j++)
876  {
877  if(crc & 0x00000001)
878  crc = (crc >> 1) ^ 0xEDB88320;
879  else
880  crc = crc >> 1;
881  }
882  }
883 
884  //Return CRC value
885  return crc;
886 }
MacAddr addr
MAC address.
Definition: ethernet.h:210
error_t mk7xEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
error_t mk7xEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
TCP/IP stack core.
void mk7xEthTick(NetInterface *interface)
Kinetis K7x Ethernet MAC timer handler.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
Generic error code.
Definition: error.h:43
#define ENET_RBD0_DATA_LENGTH
#define MK7X_ETH_RX_BUFFER_COUNT
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:98
#define MK7X_ETH_IRQ_PRIORITY_GROUPING
void mk7xEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define txBuffer
#define ENET_TBD0_TC
#define ENET_RBD0_TR
error_t mk7xEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define ENET_TBD2_INT
const NicDriver mk7xEthDriver
Kinetis K7x Ethernet MAC driver.
#define MK7X_ETH_IRQ_SUB_PRIORITY
#define ENET_TBD0_L
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
#define ENET_RBD0_W
#define MPU
#define ENET_TBD0_R
#define ENET_RBD0_CR
#define ENET_RBD0_NO
error_t mk7xEthInit(NetInterface *interface)
Kinetis K7x Ethernet MAC initialization.
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:670
void mk7xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ENET_RBD0_E
NIC driver.
Definition: nic.h:161
#define MK7X_ETH_RX_BUFFER_SIZE
void ENET_Receive_IRQHandler(void)
Ethernet MAC receive interrupt.
uint32_t mk7xEthCalcCrc(const void *data, size_t length)
CRC calculation.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
void ENET_Transmit_IRQHandler(void)
Ethernet MAC transmit interrupt.
#define MIN(a, b)
Definition: os_port.h:60
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define ENET_RBD0_LG
#define TRACE_INFO(...)
Definition: debug.h:86
#define MK7X_ETH_TX_BUFFER_SIZE
Freescale Kinetis K70 Ethernet MAC controller.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:82
Ethernet interface.
Definition: nic.h:69
#define ENET_TBD0_W
Success.
Definition: error.h:42
#define rxBuffer
Ipv6Addr address
OsEvent netEvent
Definition: net.c:72
void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:239
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:211
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define MPU_CESR_VLD_MASK
error_t
Error codes.
Definition: error.h:40
void mk7xEthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
#define ENET_RBD2_INT
unsigned int uint_t
Definition: compiler_port.h:43
void ENET_Error_IRQHandler(void)
Ethernet MAC error interrupt.
__start_packed struct @112 MacAddr
MAC address.
uint8_t data[]
Definition: dtls_misc.h:167
#define NetInterface
Definition: net.h:34
uint8_t value[]
Definition: dtls_misc.h:141
error_t mk7xEthReceivePacket(NetInterface *interface)
Receive a packet.
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
#define MK7X_ETH_TX_BUFFER_COUNT
void mk7xEthEventHandler(NetInterface *interface)
Kinetis K7x Ethernet MAC event handler.
#define osExitIsr(flag)
#define ENET_TBD0_DATA_LENGTH
#define osEnterIsr()
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
uint16_t mk7xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
#define ENET_RBD0_OV
void mk7xEthInitGpio(NetInterface *interface)
void mk7xEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define ENET_RBD0_L
MAC filter table entry.
Definition: ethernet.h:208
#define TRACE_DEBUG(...)
Definition: debug.h:98
#define MK7X_ETH_IRQ_GROUP_PRIORITY