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