samv71_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file samv71_eth_driver.c
3  * @brief SAMV71 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 //Dependencies
33 #include <limits.h>
34 #include "samv71.h"
35 #include "core/net.h"
37 #include "debug.h"
38 
39 //Underlying network interface
40 static NetInterface *nicDriverInterface;
41 
42 //IAR EWARM compiler?
43 #if defined(__ICCARM__)
44 
45 //TX buffer
46 #pragma data_alignment = 8
47 #pragma location = ".ram_no_cache"
49 //RX buffer
50 #pragma data_alignment = 8
51 #pragma location = ".ram_no_cache"
53 //TX buffer descriptors
54 #pragma data_alignment = 4
55 #pragma location = ".ram_no_cache"
57 //RX buffer descriptors
58 #pragma data_alignment = 4
59 #pragma location = ".ram_no_cache"
61 
62 //Dummy TX buffer
63 #pragma data_alignment = 8
64 #pragma location = ".ram_no_cache"
65 static uint8_t dummyTxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE];
66 //Dummy RX buffer
67 #pragma data_alignment = 8
68 #pragma location = ".ram_no_cache"
69 static uint8_t dummyRxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE];
70 //Dummy TX buffer descriptors
71 #pragma data_alignment = 4
72 #pragma location = ".ram_no_cache"
73 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT];
74 //Dummy RX buffer descriptors
75 #pragma data_alignment = 4
76 #pragma location = ".ram_no_cache"
77 static Samv71RxBufferDesc dummyRxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT];
78 
79 //Keil MDK-ARM or GCC compiler?
80 #else
81 
82 //TX buffer
84  __attribute__((aligned(8), __section__(".ram_no_cache")));
85 //RX buffer
87  __attribute__((aligned(8), __section__(".ram_no_cache")));
88 //TX buffer descriptors
90  __attribute__((aligned(4), __section__(".ram_no_cache")));
91 //RX buffer descriptors
93  __attribute__((aligned(4), __section__(".ram_no_cache")));
94 
95 //Dummy TX buffer
97  __attribute__((aligned(8), __section__(".ram_no_cache")));
98 //Dummy RX buffer
100  __attribute__((aligned(8), __section__(".ram_no_cache")));
101 //Dummy TX buffer descriptors
102 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]
103  __attribute__((aligned(4), __section__(".ram_no_cache")));
104 //Dummy RX buffer descriptors
105 static Samv71RxBufferDesc dummyRxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]
106  __attribute__((aligned(4), __section__(".ram_no_cache")));
107 
108 #endif
109 
110 //TX buffer index
111 static uint_t txBufferIndex;
112 //RX buffer index
113 static uint_t rxBufferIndex;
114 
115 
116 /**
117  * @brief SAMV71 Ethernet MAC driver
118  **/
119 
121 {
123  ETH_MTU,
134  TRUE,
135  TRUE,
136  TRUE,
137  FALSE
138 };
139 
140 
141 /**
142  * @brief SAMV71 Ethernet MAC initialization
143  * @param[in] interface Underlying network interface
144  * @return Error code
145  **/
146 
148 {
149  error_t error;
150  volatile uint32_t status;
151 
152  //Debug message
153  TRACE_INFO("Initializing SAMV71 Ethernet MAC...\r\n");
154 
155  //Save underlying network interface
156  nicDriverInterface = interface;
157 
158  //Enable GMAC peripheral clock
159  PMC->PMC_PCER1 = (1 << (ID_GMAC - 32));
160 
161  //GPIO configuration
162  samv71EthInitGpio(interface);
163 
164  //Configure MDC clock speed
165  GMAC->GMAC_NCFGR = GMAC_NCFGR_CLK_MCK_96;
166  //Enable management port (MDC and MDIO)
167  GMAC->GMAC_NCR |= GMAC_NCR_MPE;
168 
169  //PHY transceiver initialization
170  error = interface->phyDriver->init(interface);
171  //Failed to initialize PHY transceiver?
172  if(error)
173  return error;
174 
175  //Set the MAC address
176  GMAC->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
177  GMAC->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
178 
179  //Configure the receive filter
180  GMAC->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN | GMAC_NCFGR_MTIHEN;
181 
182  //DMA configuration
183  GMAC->GMAC_DCFGR = GMAC_DCFGR_DRBS(SAMV71_ETH_RX_BUFFER_SIZE / 64) |
184  GMAC_DCFGR_TXPBMS | GMAC_DCFGR_RXBMS_FULL | GMAC_DCFGR_FBLDO_INCR4;
185 
186  GMAC->GMAC_RBSRPQ[0] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
187  GMAC->GMAC_RBSRPQ[1] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
188  GMAC->GMAC_RBSRPQ[2] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
189  GMAC->GMAC_RBSRPQ[3] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
190  GMAC->GMAC_RBSRPQ[4] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
191 
192  //Initialize hash table
193  GMAC->GMAC_HRB = 0;
194  GMAC->GMAC_HRT = 0;
195 
196  //Initialize buffer descriptors
197  samv71EthInitBufferDesc(interface);
198 
199  //Clear transmit status register
200  GMAC->GMAC_TSR = GMAC_TSR_HRESP | GMAC_TSR_TXCOMP | GMAC_TSR_TFC |
201  GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR;
202  //Clear receive status register
203  GMAC->GMAC_RSR = GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA;
204 
205  //First disable all GMAC interrupts
206  GMAC->GMAC_IDR = 0xFFFFFFFF;
207  GMAC->GMAC_IDRPQ[0] = 0xFFFFFFFF;
208  GMAC->GMAC_IDRPQ[1] = 0xFFFFFFFF;
209  GMAC->GMAC_IDRPQ[2] = 0xFFFFFFFF;
210  GMAC->GMAC_IDRPQ[3] = 0xFFFFFFFF;
211  GMAC->GMAC_IDRPQ[4] = 0xFFFFFFFF;
212 
213  //Only the desired ones are enabled
214  GMAC->GMAC_IER = GMAC_IER_HRESP | GMAC_IER_ROVR | GMAC_IER_TCOMP | GMAC_IER_TFC |
215  GMAC_IER_RLEX | GMAC_IER_TUR | GMAC_IER_RXUBR | GMAC_IER_RCOMP;
216 
217  //Read GMAC ISR register to clear any pending interrupt
218  status = GMAC->GMAC_ISR;
219 
220  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
221  NVIC_SetPriorityGrouping(SAMV71_ETH_IRQ_PRIORITY_GROUPING);
222 
223  //Configure GMAC interrupt priority
224  NVIC_SetPriority(GMAC_IRQn, NVIC_EncodePriority(SAMV71_ETH_IRQ_PRIORITY_GROUPING,
226 
227  //Enable the GMAC to transmit and receive data
228  GMAC->GMAC_NCR |= GMAC_NCR_TXEN | GMAC_NCR_RXEN;
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 //SAMV71-Xplained-Ultra evaluation board?
239 #if defined(USE_SAMV71_XPLAINED_ULTRA)
240 
241 /**
242  * @brief GPIO configuration
243  * @param[in] interface Underlying network interface
244  **/
245 
246 void samv71EthInitGpio(NetInterface *interface)
247 {
248  //Enable PIO peripheral clocks
249  PMC->PMC_PCER0 = (1 << ID_PIOC) | (1 << ID_PIOD);
250 
251  //Disable pull-up resistors on RMII pins
252  PIOD->PIO_PUDR = GMAC_RMII_MASK;
253  //Disable interrupts-on-change
254  PIOD->PIO_IDR = GMAC_RMII_MASK;
255  //Assign RMII pins to peripheral A function
256  PIOD->PIO_ABCDSR[0] &= ~GMAC_RMII_MASK;
257  PIOD->PIO_ABCDSR[1] &= ~GMAC_RMII_MASK;
258  //Disable the PIO from controlling the corresponding pins
259  PIOD->PIO_PDR = GMAC_RMII_MASK;
260 
261  //Select RMII operation mode
262  GMAC->GMAC_UR &= ~GMAC_UR_RMII;
263 
264  //Configure PHY_RESET as an output
265  PIOC->PIO_PER = PIO_PC10;
266  PIOC->PIO_OER = PIO_PC10;
267 
268  //Reset PHY transceiver
269  PIOC->PIO_CODR = PIO_PC10;
270  sleep(10);
271 
272  //Take the PHY transceiver out of reset
273  PIOC->PIO_SODR = PIO_PC10;
274  sleep(10);
275 }
276 
277 #endif
278 
279 
280 /**
281  * @brief Initialize buffer descriptors
282  * @param[in] interface Underlying network interface
283  **/
284 
286 {
287  uint_t i;
288  uint32_t address;
289 
290  //Initialize TX buffer descriptors
291  for(i = 0; i < SAMV71_ETH_TX_BUFFER_COUNT; i++)
292  {
293  //Calculate the address of the current TX buffer
294  address = (uint32_t) txBuffer[i];
295  //Write the address to the descriptor entry
296  txBufferDesc[i].address = address;
297  //Initialize status field
298  txBufferDesc[i].status = GMAC_TX_USED;
299  }
300 
301  //Mark the last descriptor entry with the wrap flag
302  txBufferDesc[i - 1].status |= GMAC_TX_WRAP;
303  //Initialize TX buffer index
304  txBufferIndex = 0;
305 
306  //Initialize RX buffer descriptors
307  for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++)
308  {
309  //Calculate the address of the current RX buffer
310  address = (uint32_t) rxBuffer[i];
311  //Write the address to the descriptor entry
312  rxBufferDesc[i].address = address & GMAC_RX_ADDRESS;
313  //Clear status field
314  rxBufferDesc[i].status = 0;
315  }
316 
317  //Mark the last descriptor entry with the wrap flag
318  rxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
319  //Initialize RX buffer index
320  rxBufferIndex = 0;
321 
322  //Initialize dummy TX buffer descriptors
323  for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++)
324  {
325  //Calculate the address of the current TX buffer
326  address = (uint32_t) dummyTxBuffer[i];
327  //Write the address to the descriptor entry
328  dummyTxBufferDesc[i].address = address;
329  //Initialize status field
330  dummyTxBufferDesc[i].status = GMAC_TX_USED;
331  }
332 
333  //Mark the last descriptor entry with the wrap flag
334  dummyTxBufferDesc[i - 1].status |= GMAC_TX_WRAP;
335 
336  //Initialize dummy RX buffer descriptors
337  for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++)
338  {
339  //Calculate the address of the current RX buffer
340  address = (uint32_t) dummyRxBuffer[i];
341  //Write the address to the descriptor entry
342  dummyRxBufferDesc[i].address = (address & GMAC_RX_ADDRESS) | GMAC_RX_OWNERSHIP;
343  //Clear status field
344  dummyRxBufferDesc[i].status = 0;
345  }
346 
347  //Mark the last descriptor entry with the wrap flag
348  dummyRxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
349 
350  //Start location of the TX descriptor list
351  GMAC->GMAC_TBQB = (uint32_t) txBufferDesc;
352  GMAC->GMAC_TBQBAPQ[0] = (uint32_t) dummyTxBufferDesc;
353  GMAC->GMAC_TBQBAPQ[1] = (uint32_t) dummyTxBufferDesc;
354  GMAC->GMAC_TBQBAPQ[2] = (uint32_t) dummyTxBufferDesc;
355  GMAC->GMAC_TBQBAPQ[3] = (uint32_t) dummyTxBufferDesc;
356  GMAC->GMAC_TBQBAPQ[4] = (uint32_t) dummyTxBufferDesc;
357 
358  //Start location of the RX descriptor list
359  GMAC->GMAC_RBQB = (uint32_t) rxBufferDesc;
360  GMAC->GMAC_RBQBAPQ[0] = (uint32_t) dummyRxBufferDesc;
361  GMAC->GMAC_RBQBAPQ[1] = (uint32_t) dummyRxBufferDesc;
362  GMAC->GMAC_RBQBAPQ[2] = (uint32_t) dummyRxBufferDesc;
363  GMAC->GMAC_RBQBAPQ[3] = (uint32_t) dummyRxBufferDesc;
364  GMAC->GMAC_RBQBAPQ[4] = (uint32_t) dummyRxBufferDesc;
365 }
366 
367 
368 /**
369  * @brief SAMV71 Ethernet MAC timer handler
370  *
371  * This routine is periodically called by the TCP/IP stack to
372  * handle periodic operations such as polling the link state
373  *
374  * @param[in] interface Underlying network interface
375  **/
376 
377 void samv71EthTick(NetInterface *interface)
378 {
379  //Handle periodic operations
380  interface->phyDriver->tick(interface);
381 }
382 
383 
384 /**
385  * @brief Enable interrupts
386  * @param[in] interface Underlying network interface
387  **/
388 
390 {
391  //Enable Ethernet MAC interrupts
392  NVIC_EnableIRQ(GMAC_IRQn);
393  //Enable Ethernet PHY interrupts
394  interface->phyDriver->enableIrq(interface);
395 }
396 
397 
398 /**
399  * @brief Disable interrupts
400  * @param[in] interface Underlying network interface
401  **/
402 
404 {
405  //Disable Ethernet MAC interrupts
406  NVIC_DisableIRQ(GMAC_IRQn);
407  //Disable Ethernet PHY interrupts
408  interface->phyDriver->disableIrq(interface);
409 }
410 
411 
412 /**
413  * @brief SAMV71 Ethernet MAC interrupt service routine
414  **/
415 
416 void GMAC_Handler(void)
417 {
418  bool_t flag;
419  volatile uint32_t isr;
420  volatile uint32_t tsr;
421  volatile uint32_t rsr;
422 
423  //Enter interrupt service routine
424  osEnterIsr();
425 
426  //This flag will be set if a higher priority task must be woken
427  flag = FALSE;
428 
429  //Each time the software reads GMAC_ISR, it has to check the
430  //contents of GMAC_TSR, GMAC_RSR and GMAC_NSR
431  isr = GMAC->GMAC_ISRPQ[0];
432  isr = GMAC->GMAC_ISRPQ[1];
433  isr = GMAC->GMAC_ISRPQ[2];
434  isr = GMAC->GMAC_ISRPQ[3];
435  isr = GMAC->GMAC_ISRPQ[4];
436  isr = GMAC->GMAC_ISR;
437  tsr = GMAC->GMAC_TSR;
438  rsr = GMAC->GMAC_RSR;
439 
440  //A packet has been transmitted?
441  if(tsr & (GMAC_TSR_HRESP | GMAC_TSR_TXCOMP | GMAC_TSR_TFC |
442  GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR))
443  {
444  //Only clear TSR flags that are currently set
445  GMAC->GMAC_TSR = tsr;
446 
447  //Check whether the TX buffer is available for writing
448  if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED)
449  {
450  //Notify the TCP/IP stack that the transmitter is ready to send
451  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
452  }
453  }
454 
455  //A packet has been received?
456  if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA))
457  {
458  //Set event flag
459  nicDriverInterface->nicEvent = TRUE;
460  //Notify the TCP/IP stack of the event
461  flag |= osSetEventFromIsr(&netEvent);
462  }
463 
464  //Leave interrupt service routine
465  osExitIsr(flag);
466 }
467 
468 
469 /**
470  * @brief SAMV71 Ethernet MAC event handler
471  * @param[in] interface Underlying network interface
472  **/
473 
475 {
476  error_t error;
477  uint32_t rsr;
478 
479  //Read receive status
480  rsr = GMAC->GMAC_RSR;
481 
482  //Packet received?
483  if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA))
484  {
485  //Only clear RSR flags that are currently set
486  GMAC->GMAC_RSR = rsr;
487 
488  //Process all pending packets
489  do
490  {
491  //Read incoming packet
492  error = samv71EthReceivePacket(interface);
493 
494  //No more data in the receive buffer?
495  } while(error != ERROR_BUFFER_EMPTY);
496  }
497 }
498 
499 
500 /**
501  * @brief Send a packet
502  * @param[in] interface Underlying network interface
503  * @param[in] buffer Multi-part buffer containing the data to send
504  * @param[in] offset Offset to the first data byte
505  * @return Error code
506  **/
507 
509  const NetBuffer *buffer, size_t offset)
510 {
511  static uint8_t temp[SAMV71_ETH_TX_BUFFER_SIZE];
512  size_t length;
513 
514  //Retrieve the length of the packet
515  length = netBufferGetLength(buffer) - offset;
516 
517  //Check the frame length
519  {
520  //The transmitter can accept another packet
521  osSetEvent(&interface->nicTxEvent);
522  //Report an error
523  return ERROR_INVALID_LENGTH;
524  }
525 
526  //Make sure the current buffer is available for writing
527  if(!(txBufferDesc[txBufferIndex].status & GMAC_TX_USED))
528  return ERROR_FAILURE;
529 
530  //Copy user data to the transmit buffer
531  netBufferRead(temp, buffer, offset, length);
532  memcpy(txBuffer[txBufferIndex], temp, (length + 3) & ~3UL);
533 
534  //Set the necessary flags in the descriptor entry
535  if(txBufferIndex < (SAMV71_ETH_TX_BUFFER_COUNT - 1))
536  {
537  //Write the status word
538  txBufferDesc[txBufferIndex].status =
540 
541  //Point to the next buffer
542  txBufferIndex++;
543  }
544  else
545  {
546  //Write the status word
547  txBufferDesc[txBufferIndex].status = GMAC_TX_WRAP |
549 
550  //Wrap around
551  txBufferIndex = 0;
552  }
553 
554  //Data synchronization barrier
555  __DSB();
556 
557  //Set the TSTART bit to initiate transmission
558  GMAC->GMAC_NCR |= GMAC_NCR_TSTART;
559 
560  //Check whether the next buffer is available for writing
561  if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED)
562  {
563  //The transmitter can accept another packet
564  osSetEvent(&interface->nicTxEvent);
565  }
566 
567  //Successful processing
568  return NO_ERROR;
569 }
570 
571 
572 /**
573  * @brief Receive a packet
574  * @param[in] interface Underlying network interface
575  * @return Error code
576  **/
577 
579 {
580  static uint8_t temp[ETH_MAX_FRAME_SIZE];
581  error_t error;
582  uint_t i;
583  uint_t j;
584  uint_t sofIndex;
585  uint_t eofIndex;
586  size_t n;
587  size_t size;
588  size_t length;
589 
590  //Initialize SOF and EOF indices
591  sofIndex = UINT_MAX;
592  eofIndex = UINT_MAX;
593 
594  //Search for SOF and EOF flags
595  for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++)
596  {
597  //Point to the current entry
598  j = rxBufferIndex + i;
599 
600  //Wrap around to the beginning of the buffer if necessary
603 
604  //No more entries to process?
605  if(!(rxBufferDesc[j].address & GMAC_RX_OWNERSHIP))
606  {
607  //Stop processing
608  break;
609  }
610  //A valid SOF has been found?
611  if(rxBufferDesc[j].status & GMAC_RX_SOF)
612  {
613  //Save the position of the SOF
614  sofIndex = i;
615  }
616  //A valid EOF has been found?
617  if((rxBufferDesc[j].status & GMAC_RX_EOF) && sofIndex != UINT_MAX)
618  {
619  //Save the position of the EOF
620  eofIndex = i;
621  //Retrieve the length of the frame
622  size = rxBufferDesc[j].status & GMAC_RX_LENGTH;
623  //Limit the number of data to read
624  size = MIN(size, ETH_MAX_FRAME_SIZE);
625  //Stop processing since we have reached the end of the frame
626  break;
627  }
628  }
629 
630  //Determine the number of entries to process
631  if(eofIndex != UINT_MAX)
632  j = eofIndex + 1;
633  else if(sofIndex != UINT_MAX)
634  j = sofIndex;
635  else
636  j = i;
637 
638  //Total number of bytes that have been copied from the receive buffer
639  length = 0;
640 
641  //Process incoming frame
642  for(i = 0; i < j; i++)
643  {
644  //Any data to copy from current buffer?
645  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
646  {
647  //Calculate the number of bytes to read at a time
649  //Copy data from receive buffer
650  memcpy(temp + length, rxBuffer[rxBufferIndex], (n + 3) & ~3UL);
651  //Update byte counters
652  length += n;
653  size -= n;
654  }
655 
656  //Mark the current buffer as free
657  rxBufferDesc[rxBufferIndex].address &= ~GMAC_RX_OWNERSHIP;
658 
659  //Point to the following entry
660  rxBufferIndex++;
661 
662  //Wrap around to the beginning of the buffer if necessary
663  if(rxBufferIndex >= SAMV71_ETH_RX_BUFFER_COUNT)
664  rxBufferIndex = 0;
665  }
666 
667  //Any packet to process?
668  if(length > 0)
669  {
670  //Pass the packet to the upper layer
671  nicProcessPacket(interface, temp, length);
672  //Valid packet received
673  error = NO_ERROR;
674  }
675  else
676  {
677  //No more data in the receive buffer
678  error = ERROR_BUFFER_EMPTY;
679  }
680 
681  //Return status code
682  return error;
683 }
684 
685 
686 /**
687  * @brief Configure MAC address filtering
688  * @param[in] interface Underlying network interface
689  * @return Error code
690  **/
691 
693 {
694  uint_t i;
695  uint_t k;
696  uint8_t *p;
697  uint32_t hashTable[2];
698  MacFilterEntry *entry;
699 
700  //Debug message
701  TRACE_DEBUG("Updating SAMV71 hash table...\r\n");
702 
703  //Clear hash table
704  hashTable[0] = 0;
705  hashTable[1] = 0;
706 
707  //The MAC address filter contains the list of MAC addresses to accept
708  //when receiving an Ethernet frame
709  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
710  {
711  //Point to the current entry
712  entry = &interface->macAddrFilter[i];
713 
714  //Valid entry?
715  if(entry->refCount > 0)
716  {
717  //Point to the MAC address
718  p = entry->addr.b;
719 
720  //Apply the hash function
721  k = (p[0] >> 6) ^ p[0];
722  k ^= (p[1] >> 4) ^ (p[1] << 2);
723  k ^= (p[2] >> 2) ^ (p[2] << 4);
724  k ^= (p[3] >> 6) ^ p[3];
725  k ^= (p[4] >> 4) ^ (p[4] << 2);
726  k ^= (p[5] >> 2) ^ (p[5] << 4);
727 
728  //The hash value is reduced to a 6-bit index
729  k &= 0x3F;
730 
731  //Update hash table contents
732  hashTable[k / 32] |= (1 << (k % 32));
733  }
734  }
735 
736  //Write the hash table
737  GMAC->GMAC_HRB = hashTable[0];
738  GMAC->GMAC_HRT = hashTable[1];
739 
740  //Debug message
741  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", GMAC->GMAC_HRB);
742  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", GMAC->GMAC_HRT);
743 
744  //Successful processing
745  return NO_ERROR;
746 }
747 
748 
749 /**
750  * @brief Adjust MAC configuration parameters for proper operation
751  * @param[in] interface Underlying network interface
752  * @return Error code
753  **/
754 
756 {
757  uint32_t config;
758 
759  //Read network configuration register
760  config = GMAC->GMAC_NCFGR;
761 
762  //10BASE-T or 100BASE-TX operation mode?
763  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
764  config |= GMAC_NCFGR_SPD;
765  else
766  config &= ~GMAC_NCFGR_SPD;
767 
768  //Half-duplex or full-duplex mode?
769  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
770  config |= GMAC_NCFGR_FD;
771  else
772  config &= ~GMAC_NCFGR_FD;
773 
774  //Write configuration value back to NCFGR register
775  GMAC->GMAC_NCFGR = config;
776 
777  //Successful processing
778  return NO_ERROR;
779 }
780 
781 
782 /**
783  * @brief Write PHY register
784  * @param[in] phyAddr PHY address
785  * @param[in] regAddr Register address
786  * @param[in] data Register value
787  **/
788 
789 void samv71EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
790 {
791  uint32_t value;
792 
793  //Set up a write operation
794  value = GMAC_MAN_CLTTO | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2);
795  //PHY address
796  value |= GMAC_MAN_PHYA(phyAddr);
797  //Register address
798  value |= GMAC_MAN_REGA(regAddr);
799  //Register value
800  value |= GMAC_MAN_DATA(data);
801 
802  //Start a write operation
803  GMAC->GMAC_MAN = value;
804  //Wait for the write to complete
805  while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE));
806 }
807 
808 
809 /**
810  * @brief Read PHY register
811  * @param[in] phyAddr PHY address
812  * @param[in] regAddr Register address
813  * @return Register value
814  **/
815 
816 uint16_t samv71EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
817 {
818  uint32_t value;
819 
820  //Set up a read operation
821  value = GMAC_MAN_CLTTO | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2);
822  //PHY address
823  value |= GMAC_MAN_PHYA(phyAddr);
824  //Register address
825  value |= GMAC_MAN_REGA(regAddr);
826 
827  //Start a read operation
828  GMAC->GMAC_MAN = value;
829  //Wait for the read to complete
830  while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE));
831 
832  //Return PHY register contents
833  return GMAC->GMAC_MAN & GMAC_MAN_DATA_Msk;
834 }
#define GMAC_RX_SOF
void samv71EthTick(NetInterface *interface)
SAMV71 Ethernet MAC timer handler.
MacAddr addr
MAC address.
Definition: ethernet.h:210
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:80
#define SAMV71_ETH_IRQ_PRIORITY_GROUPING
TCP/IP stack core.
#define SAMV71_ETH_IRQ_GROUP_PRIORITY
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
#define GMAC_RX_EOF
Generic error code.
Definition: error.h:43
Transmit buffer descriptor.
void samv71EthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
#define txBuffer
uint16_t samv71EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define GMAC_TX_USED
Receive buffer descriptor.
#define sleep(delay)
Definition: os_port.h:126
#define SAMV71_ETH_TX_BUFFER_SIZE
#define SAMV71_ETH_DUMMY_BUFFER_SIZE
#define GMAC_TX_WRAP
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
#define SAMV71_ETH_DUMMY_BUFFER_COUNT
#define SAMV71_ETH_RX_BUFFER_COUNT
SAMV71 Ethernet MAC controller.
#define GMAC_TX_LAST
const NicDriver samv71EthDriver
SAMV71 Ethernet MAC driver.
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:670
void samv71EthDisableIrq(NetInterface *interface)
Disable interrupts.
NIC driver.
Definition: nic.h:161
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define MIN(a, b)
Definition: os_port.h:60
#define GMAC_RX_OWNERSHIP
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define GMAC_RX_ADDRESS
void samv71EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t samv71EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define TRACE_INFO(...)
Definition: debug.h:86
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:82
Ethernet interface.
Definition: nic.h:69
#define SAMV71_ETH_TX_BUFFER_COUNT
Success.
Definition: error.h:42
#define GMAC_RX_WRAP
#define rxBuffer
Ipv6Addr address
error_t samv71EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
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.
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
#define SAMV71_ETH_RX_BUFFER_SIZE
uint8_t data[]
Definition: dtls_misc.h:167
#define NetInterface
Definition: net.h:34
uint8_t value[]
Definition: dtls_misc.h:141
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
error_t samv71EthInit(NetInterface *interface)
SAMV71 Ethernet MAC initialization.
#define osExitIsr(flag)
#define SAMV71_ETH_IRQ_SUB_PRIORITY
#define osEnterIsr()
#define GMAC_RX_LENGTH
error_t samv71EthReceivePacket(NetInterface *interface)
Receive a packet.
#define GMAC_TX_LENGTH
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
void GMAC_Handler(void)
SAMV71 Ethernet MAC interrupt service routine.
void samv71EthEventHandler(NetInterface *interface)
SAMV71 Ethernet MAC event handler.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
error_t samv71EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
MAC filter table entry.
Definition: ethernet.h:208
void samv71EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define GMAC_RMII_MASK
#define TRACE_DEBUG(...)
Definition: debug.h:98
void samv71EthInitGpio(NetInterface *interface)