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