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