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