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  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <limits.h>
36 #include "samv71.h"
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWARM compiler?
45 #if defined(__ICCARM__)
46 
47 //TX buffer
48 #pragma data_alignment = 8
49 #pragma location = ".ram_no_cache"
51 //RX buffer
52 #pragma data_alignment = 8
53 #pragma location = ".ram_no_cache"
55 //TX buffer descriptors
56 #pragma data_alignment = 4
57 #pragma location = ".ram_no_cache"
59 //RX buffer descriptors
60 #pragma data_alignment = 4
61 #pragma location = ".ram_no_cache"
63 
64 //Dummy TX buffer
65 #pragma data_alignment = 8
66 #pragma location = ".ram_no_cache"
67 static uint8_t dummyTxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE];
68 //Dummy RX buffer
69 #pragma data_alignment = 8
70 #pragma location = ".ram_no_cache"
71 static uint8_t dummyRxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE];
72 //Dummy TX buffer descriptors
73 #pragma data_alignment = 4
74 #pragma location = ".ram_no_cache"
75 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT];
76 //Dummy RX buffer descriptors
77 #pragma data_alignment = 4
78 #pragma location = ".ram_no_cache"
79 static Samv71RxBufferDesc dummyRxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT];
80 
81 //Keil MDK-ARM or GCC compiler?
82 #else
83 
84 //TX buffer
86  __attribute__((aligned(8), __section__(".ram_no_cache")));
87 //RX buffer
89  __attribute__((aligned(8), __section__(".ram_no_cache")));
90 //TX buffer descriptors
92  __attribute__((aligned(4), __section__(".ram_no_cache")));
93 //RX buffer descriptors
95  __attribute__((aligned(4), __section__(".ram_no_cache")));
96 
97 //Dummy TX buffer
99  __attribute__((aligned(8), __section__(".ram_no_cache")));
100 //Dummy RX buffer
101 static uint8_t dummyRxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE]
102  __attribute__((aligned(8), __section__(".ram_no_cache")));
103 //Dummy TX buffer descriptors
104 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]
105  __attribute__((aligned(4), __section__(".ram_no_cache")));
106 //Dummy RX buffer descriptors
107 static Samv71RxBufferDesc dummyRxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]
108  __attribute__((aligned(4), __section__(".ram_no_cache")));
109 
110 #endif
111 
112 //TX buffer index
113 static uint_t txBufferIndex;
114 //RX buffer index
115 static uint_t rxBufferIndex;
116 
117 
118 /**
119  * @brief SAMV71 Ethernet MAC driver
120  **/
121 
123 {
125  ETH_MTU,
136  TRUE,
137  TRUE,
138  TRUE,
139  FALSE
140 };
141 
142 
143 /**
144  * @brief SAMV71 Ethernet MAC initialization
145  * @param[in] interface Underlying network interface
146  * @return Error code
147  **/
148 
150 {
151  error_t error;
152  volatile uint32_t status;
153 
154  //Debug message
155  TRACE_INFO("Initializing SAMV71 Ethernet MAC...\r\n");
156 
157  //Save underlying network interface
158  nicDriverInterface = interface;
159 
160  //Enable GMAC peripheral clock
161  PMC->PMC_PCER1 = (1 << (ID_GMAC - 32));
162 
163  //Disable transmit and receive circuits
164  GMAC->GMAC_NCR = 0;
165 
166  //GPIO configuration
167  samv71EthInitGpio(interface);
168 
169  //Configure MDC clock speed
170  GMAC->GMAC_NCFGR = GMAC_NCFGR_CLK_MCK_96;
171  //Enable management port (MDC and MDIO)
172  GMAC->GMAC_NCR |= GMAC_NCR_MPE;
173 
174  //PHY transceiver initialization
175  error = interface->phyDriver->init(interface);
176  //Failed to initialize PHY transceiver?
177  if(error)
178  return error;
179 
180  //Set the MAC address of the station
181  GMAC->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
182  GMAC->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
183 
184  //The MAC supports 3 additional addresses for unicast perfect filtering
185  GMAC->GMAC_SA[1].GMAC_SAB = 0;
186  GMAC->GMAC_SA[2].GMAC_SAB = 0;
187  GMAC->GMAC_SA[3].GMAC_SAB = 0;
188 
189  //Initialize hash table
190  GMAC->GMAC_HRB = 0;
191  GMAC->GMAC_HRT = 0;
192 
193  //Configure the receive filter
194  GMAC->GMAC_NCFGR |= GMAC_NCFGR_MAXFS | GMAC_NCFGR_MTIHEN;
195 
196  //DMA configuration
197  GMAC->GMAC_DCFGR = GMAC_DCFGR_DRBS(SAMV71_ETH_RX_BUFFER_SIZE / 64) |
198  GMAC_DCFGR_TXPBMS | GMAC_DCFGR_RXBMS_FULL | GMAC_DCFGR_FBLDO_INCR4;
199 
200  GMAC->GMAC_RBSRPQ[0] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
201  GMAC->GMAC_RBSRPQ[1] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
202  GMAC->GMAC_RBSRPQ[2] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
203  GMAC->GMAC_RBSRPQ[3] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
204  GMAC->GMAC_RBSRPQ[4] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64);
205 
206  //Initialize buffer descriptors
207  samv71EthInitBufferDesc(interface);
208 
209  //Clear transmit status register
210  GMAC->GMAC_TSR = GMAC_TSR_HRESP | GMAC_TSR_TXCOMP | GMAC_TSR_TFC |
211  GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR;
212  //Clear receive status register
213  GMAC->GMAC_RSR = GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA;
214 
215  //First disable all GMAC interrupts
216  GMAC->GMAC_IDR = 0xFFFFFFFF;
217  GMAC->GMAC_IDRPQ[0] = 0xFFFFFFFF;
218  GMAC->GMAC_IDRPQ[1] = 0xFFFFFFFF;
219  GMAC->GMAC_IDRPQ[2] = 0xFFFFFFFF;
220  GMAC->GMAC_IDRPQ[3] = 0xFFFFFFFF;
221  GMAC->GMAC_IDRPQ[4] = 0xFFFFFFFF;
222 
223  //Only the desired ones are enabled
224  GMAC->GMAC_IER = GMAC_IER_HRESP | GMAC_IER_ROVR | GMAC_IER_TCOMP | GMAC_IER_TFC |
225  GMAC_IER_RLEX | GMAC_IER_TUR | GMAC_IER_RXUBR | GMAC_IER_RCOMP;
226 
227  //Read GMAC ISR register to clear any pending interrupt
228  status = GMAC->GMAC_ISR;
229 
230  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
231  NVIC_SetPriorityGrouping(SAMV71_ETH_IRQ_PRIORITY_GROUPING);
232 
233  //Configure GMAC interrupt priority
234  NVIC_SetPriority(GMAC_IRQn, NVIC_EncodePriority(SAMV71_ETH_IRQ_PRIORITY_GROUPING,
236 
237  //Enable the GMAC to transmit and receive data
238  GMAC->GMAC_NCR |= GMAC_NCR_TXEN | GMAC_NCR_RXEN;
239 
240  //Accept any packets from the upper layer
241  osSetEvent(&interface->nicTxEvent);
242 
243  //Successful initialization
244  return NO_ERROR;
245 }
246 
247 
248 //SAMV71-Xplained-Ultra evaluation board?
249 #if defined(USE_SAMV71_XPLAINED_ULTRA)
250 
251 /**
252  * @brief GPIO configuration
253  * @param[in] interface Underlying network interface
254  **/
255 
256 void samv71EthInitGpio(NetInterface *interface)
257 {
258  //Enable PIO peripheral clocks
259  PMC->PMC_PCER0 = (1 << ID_PIOC) | (1 << ID_PIOD);
260 
261  //Disable pull-up resistors on RMII pins
262  PIOD->PIO_PUDR = GMAC_RMII_MASK;
263  //Disable interrupts-on-change
264  PIOD->PIO_IDR = GMAC_RMII_MASK;
265  //Assign RMII pins to peripheral A function
266  PIOD->PIO_ABCDSR[0] &= ~GMAC_RMII_MASK;
267  PIOD->PIO_ABCDSR[1] &= ~GMAC_RMII_MASK;
268  //Disable the PIO from controlling the corresponding pins
269  PIOD->PIO_PDR = GMAC_RMII_MASK;
270 
271  //Select RMII operation mode
272  GMAC->GMAC_UR &= ~GMAC_UR_RMII;
273 
274  //Configure PHY_RESET as an output
275  PIOC->PIO_PER = PIO_PC10;
276  PIOC->PIO_OER = PIO_PC10;
277 
278  //Reset PHY transceiver
279  PIOC->PIO_CODR = PIO_PC10;
280  sleep(10);
281  PIOC->PIO_SODR = PIO_PC10;
282  sleep(10);
283 }
284 
285 #endif
286 
287 
288 /**
289  * @brief Initialize buffer descriptors
290  * @param[in] interface Underlying network interface
291  **/
292 
294 {
295  uint_t i;
296  uint32_t address;
297 
298  //Initialize TX buffer descriptors
299  for(i = 0; i < SAMV71_ETH_TX_BUFFER_COUNT; i++)
300  {
301  //Calculate the address of the current TX buffer
302  address = (uint32_t) txBuffer[i];
303  //Write the address to the descriptor entry
304  txBufferDesc[i].address = address;
305  //Initialize status field
306  txBufferDesc[i].status = GMAC_TX_USED;
307  }
308 
309  //Mark the last descriptor entry with the wrap flag
310  txBufferDesc[i - 1].status |= GMAC_TX_WRAP;
311  //Initialize TX buffer index
312  txBufferIndex = 0;
313 
314  //Initialize RX buffer descriptors
315  for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++)
316  {
317  //Calculate the address of the current RX buffer
318  address = (uint32_t) rxBuffer[i];
319  //Write the address to the descriptor entry
320  rxBufferDesc[i].address = address & GMAC_RX_ADDRESS;
321  //Clear status field
322  rxBufferDesc[i].status = 0;
323  }
324 
325  //Mark the last descriptor entry with the wrap flag
326  rxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
327  //Initialize RX buffer index
328  rxBufferIndex = 0;
329 
330  //Initialize dummy TX buffer descriptors
331  for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++)
332  {
333  //Calculate the address of the current TX buffer
334  address = (uint32_t) dummyTxBuffer[i];
335  //Write the address to the descriptor entry
336  dummyTxBufferDesc[i].address = address;
337  //Initialize status field
338  dummyTxBufferDesc[i].status = GMAC_TX_USED;
339  }
340 
341  //Mark the last descriptor entry with the wrap flag
342  dummyTxBufferDesc[i - 1].status |= GMAC_TX_WRAP;
343 
344  //Initialize dummy RX buffer descriptors
345  for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++)
346  {
347  //Calculate the address of the current RX buffer
348  address = (uint32_t) dummyRxBuffer[i];
349  //Write the address to the descriptor entry
350  dummyRxBufferDesc[i].address = (address & GMAC_RX_ADDRESS) | GMAC_RX_OWNERSHIP;
351  //Clear status field
352  dummyRxBufferDesc[i].status = 0;
353  }
354 
355  //Mark the last descriptor entry with the wrap flag
356  dummyRxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
357 
358  //Start location of the TX descriptor list
359  GMAC->GMAC_TBQB = (uint32_t) txBufferDesc;
360  GMAC->GMAC_TBQBAPQ[0] = (uint32_t) dummyTxBufferDesc;
361  GMAC->GMAC_TBQBAPQ[1] = (uint32_t) dummyTxBufferDesc;
362  GMAC->GMAC_TBQBAPQ[2] = (uint32_t) dummyTxBufferDesc;
363  GMAC->GMAC_TBQBAPQ[3] = (uint32_t) dummyTxBufferDesc;
364  GMAC->GMAC_TBQBAPQ[4] = (uint32_t) dummyTxBufferDesc;
365 
366  //Start location of the RX descriptor list
367  GMAC->GMAC_RBQB = (uint32_t) rxBufferDesc;
368  GMAC->GMAC_RBQBAPQ[0] = (uint32_t) dummyRxBufferDesc;
369  GMAC->GMAC_RBQBAPQ[1] = (uint32_t) dummyRxBufferDesc;
370  GMAC->GMAC_RBQBAPQ[2] = (uint32_t) dummyRxBufferDesc;
371  GMAC->GMAC_RBQBAPQ[3] = (uint32_t) dummyRxBufferDesc;
372  GMAC->GMAC_RBQBAPQ[4] = (uint32_t) dummyRxBufferDesc;
373 }
374 
375 
376 /**
377  * @brief SAMV71 Ethernet MAC timer handler
378  *
379  * This routine is periodically called by the TCP/IP stack to
380  * handle periodic operations such as polling the link state
381  *
382  * @param[in] interface Underlying network interface
383  **/
384 
385 void samv71EthTick(NetInterface *interface)
386 {
387  //Handle periodic operations
388  interface->phyDriver->tick(interface);
389 }
390 
391 
392 /**
393  * @brief Enable interrupts
394  * @param[in] interface Underlying network interface
395  **/
396 
398 {
399  //Enable Ethernet MAC interrupts
400  NVIC_EnableIRQ(GMAC_IRQn);
401  //Enable Ethernet PHY interrupts
402  interface->phyDriver->enableIrq(interface);
403 }
404 
405 
406 /**
407  * @brief Disable interrupts
408  * @param[in] interface Underlying network interface
409  **/
410 
412 {
413  //Disable Ethernet MAC interrupts
414  NVIC_DisableIRQ(GMAC_IRQn);
415  //Disable Ethernet PHY interrupts
416  interface->phyDriver->disableIrq(interface);
417 }
418 
419 
420 /**
421  * @brief SAMV71 Ethernet MAC interrupt service routine
422  **/
423 
424 void GMAC_Handler(void)
425 {
426  bool_t flag;
427  volatile uint32_t isr;
428  volatile uint32_t tsr;
429  volatile uint32_t rsr;
430 
431  //Interrupt service routine prologue
432  osEnterIsr();
433 
434  //This flag will be set if a higher priority task must be woken
435  flag = FALSE;
436 
437  //Each time the software reads GMAC_ISR, it has to check the
438  //contents of GMAC_TSR, GMAC_RSR and GMAC_NSR
439  isr = GMAC->GMAC_ISRPQ[0];
440  isr = GMAC->GMAC_ISRPQ[1];
441  isr = GMAC->GMAC_ISRPQ[2];
442  isr = GMAC->GMAC_ISRPQ[3];
443  isr = GMAC->GMAC_ISRPQ[4];
444  isr = GMAC->GMAC_ISR;
445  tsr = GMAC->GMAC_TSR;
446  rsr = GMAC->GMAC_RSR;
447 
448  //A packet has been transmitted?
449  if(tsr & (GMAC_TSR_HRESP | GMAC_TSR_TXCOMP | GMAC_TSR_TFC |
450  GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR))
451  {
452  //Only clear TSR flags that are currently set
453  GMAC->GMAC_TSR = tsr;
454 
455  //Check whether the TX buffer is available for writing
456  if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED)
457  {
458  //Notify the TCP/IP stack that the transmitter is ready to send
459  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
460  }
461  }
462 
463  //A packet has been received?
464  if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA))
465  {
466  //Set event flag
467  nicDriverInterface->nicEvent = TRUE;
468  //Notify the TCP/IP stack of the event
469  flag |= osSetEventFromIsr(&netEvent);
470  }
471 
472  //Interrupt service routine epilogue
473  osExitIsr(flag);
474 }
475 
476 
477 /**
478  * @brief SAMV71 Ethernet MAC event handler
479  * @param[in] interface Underlying network interface
480  **/
481 
483 {
484  error_t error;
485  uint32_t rsr;
486 
487  //Read receive status
488  rsr = GMAC->GMAC_RSR;
489 
490  //Packet received?
491  if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA))
492  {
493  //Only clear RSR flags that are currently set
494  GMAC->GMAC_RSR = rsr;
495 
496  //Process all pending packets
497  do
498  {
499  //Read incoming packet
500  error = samv71EthReceivePacket(interface);
501 
502  //No more data in the receive buffer?
503  } while(error != ERROR_BUFFER_EMPTY);
504  }
505 }
506 
507 
508 /**
509  * @brief Send a packet
510  * @param[in] interface Underlying network interface
511  * @param[in] buffer Multi-part buffer containing the data to send
512  * @param[in] offset Offset to the first data byte
513  * @return Error code
514  **/
515 
517  const NetBuffer *buffer, size_t offset)
518 {
519  static uint8_t temp[SAMV71_ETH_TX_BUFFER_SIZE];
520  size_t length;
521 
522  //Retrieve the length of the packet
523  length = netBufferGetLength(buffer) - offset;
524 
525  //Check the frame length
527  {
528  //The transmitter can accept another packet
529  osSetEvent(&interface->nicTxEvent);
530  //Report an error
531  return ERROR_INVALID_LENGTH;
532  }
533 
534  //Make sure the current buffer is available for writing
535  if(!(txBufferDesc[txBufferIndex].status & GMAC_TX_USED))
536  return ERROR_FAILURE;
537 
538  //Copy user data to the transmit buffer
539  netBufferRead(temp, buffer, offset, length);
540  memcpy(txBuffer[txBufferIndex], temp, (length + 3) & ~3UL);
541 
542  //Set the necessary flags in the descriptor entry
543  if(txBufferIndex < (SAMV71_ETH_TX_BUFFER_COUNT - 1))
544  {
545  //Write the status word
546  txBufferDesc[txBufferIndex].status =
548 
549  //Point to the next buffer
550  txBufferIndex++;
551  }
552  else
553  {
554  //Write the status word
555  txBufferDesc[txBufferIndex].status = GMAC_TX_WRAP |
557 
558  //Wrap around
559  txBufferIndex = 0;
560  }
561 
562  //Data synchronization barrier
563  __DSB();
564 
565  //Set the TSTART bit to initiate transmission
566  GMAC->GMAC_NCR |= GMAC_NCR_TSTART;
567 
568  //Check whether the next buffer is available for writing
569  if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED)
570  {
571  //The transmitter can accept another packet
572  osSetEvent(&interface->nicTxEvent);
573  }
574 
575  //Successful processing
576  return NO_ERROR;
577 }
578 
579 
580 /**
581  * @brief Receive a packet
582  * @param[in] interface Underlying network interface
583  * @return Error code
584  **/
585 
587 {
588  static uint8_t temp[ETH_MAX_FRAME_SIZE];
589  error_t error;
590  uint_t i;
591  uint_t j;
592  uint_t sofIndex;
593  uint_t eofIndex;
594  size_t n;
595  size_t size;
596  size_t length;
597 
598  //Initialize SOF and EOF indices
599  sofIndex = UINT_MAX;
600  eofIndex = UINT_MAX;
601 
602  //Search for SOF and EOF flags
603  for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++)
604  {
605  //Point to the current entry
606  j = rxBufferIndex + i;
607 
608  //Wrap around to the beginning of the buffer if necessary
611 
612  //No more entries to process?
613  if(!(rxBufferDesc[j].address & GMAC_RX_OWNERSHIP))
614  {
615  //Stop processing
616  break;
617  }
618  //A valid SOF has been found?
619  if(rxBufferDesc[j].status & GMAC_RX_SOF)
620  {
621  //Save the position of the SOF
622  sofIndex = i;
623  }
624  //A valid EOF has been found?
625  if((rxBufferDesc[j].status & GMAC_RX_EOF) && sofIndex != UINT_MAX)
626  {
627  //Save the position of the EOF
628  eofIndex = i;
629  //Retrieve the length of the frame
630  size = rxBufferDesc[j].status & GMAC_RX_LENGTH;
631  //Limit the number of data to read
632  size = MIN(size, ETH_MAX_FRAME_SIZE);
633  //Stop processing since we have reached the end of the frame
634  break;
635  }
636  }
637 
638  //Determine the number of entries to process
639  if(eofIndex != UINT_MAX)
640  j = eofIndex + 1;
641  else if(sofIndex != UINT_MAX)
642  j = sofIndex;
643  else
644  j = i;
645 
646  //Total number of bytes that have been copied from the receive buffer
647  length = 0;
648 
649  //Process incoming frame
650  for(i = 0; i < j; i++)
651  {
652  //Any data to copy from current buffer?
653  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
654  {
655  //Calculate the number of bytes to read at a time
657  //Copy data from receive buffer
658  memcpy(temp + length, rxBuffer[rxBufferIndex], (n + 3) & ~3UL);
659  //Update byte counters
660  length += n;
661  size -= n;
662  }
663 
664  //Mark the current buffer as free
665  rxBufferDesc[rxBufferIndex].address &= ~GMAC_RX_OWNERSHIP;
666 
667  //Point to the following entry
668  rxBufferIndex++;
669 
670  //Wrap around to the beginning of the buffer if necessary
671  if(rxBufferIndex >= SAMV71_ETH_RX_BUFFER_COUNT)
672  rxBufferIndex = 0;
673  }
674 
675  //Any packet to process?
676  if(length > 0)
677  {
678  //Pass the packet to the upper layer
679  nicProcessPacket(interface, temp, length);
680  //Valid packet received
681  error = NO_ERROR;
682  }
683  else
684  {
685  //No more data in the receive buffer
686  error = ERROR_BUFFER_EMPTY;
687  }
688 
689  //Return status code
690  return error;
691 }
692 
693 
694 /**
695  * @brief Configure MAC address filtering
696  * @param[in] interface Underlying network interface
697  * @return Error code
698  **/
699 
701 {
702  uint_t i;
703  uint_t j;
704  uint_t k;
705  uint8_t *p;
706  uint32_t hashTable[2];
707  MacAddr unicastMacAddr[3];
708  MacFilterEntry *entry;
709 
710  //Debug message
711  TRACE_DEBUG("Updating MAC filter...\r\n");
712 
713  //Set the MAC address of the station
714  GMAC->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
715  GMAC->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
716 
717  //The MAC supports 3 additional addresses for unicast perfect filtering
718  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
719  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
720  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
721 
722  //The hash table is used for multicast address filtering
723  hashTable[0] = 0;
724  hashTable[1] = 0;
725 
726  //The MAC address filter contains the list of MAC addresses to accept
727  //when receiving an Ethernet frame
728  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
729  {
730  //Point to the current entry
731  entry = &interface->macAddrFilter[i];
732 
733  //Valid entry?
734  if(entry->refCount > 0)
735  {
736  //Multicast address?
737  if(macIsMulticastAddr(&entry->addr))
738  {
739  //Point to the MAC address
740  p = entry->addr.b;
741 
742  //Apply the hash function
743  k = (p[0] >> 6) ^ p[0];
744  k ^= (p[1] >> 4) ^ (p[1] << 2);
745  k ^= (p[2] >> 2) ^ (p[2] << 4);
746  k ^= (p[3] >> 6) ^ p[3];
747  k ^= (p[4] >> 4) ^ (p[4] << 2);
748  k ^= (p[5] >> 2) ^ (p[5] << 4);
749 
750  //The hash value is reduced to a 6-bit index
751  k &= 0x3F;
752 
753  //Update hash table contents
754  hashTable[k / 32] |= (1 << (k % 32));
755  }
756  else
757  {
758  //Up to 3 additional MAC addresses can be specified
759  if(j < 3)
760  {
761  //Save the unicast address
762  unicastMacAddr[j] = entry->addr;
763  }
764  else
765  {
766  //Point to the MAC address
767  p = entry->addr.b;
768 
769  //Apply the hash function
770  k = (p[0] >> 6) ^ p[0];
771  k ^= (p[1] >> 4) ^ (p[1] << 2);
772  k ^= (p[2] >> 2) ^ (p[2] << 4);
773  k ^= (p[3] >> 6) ^ p[3];
774  k ^= (p[4] >> 4) ^ (p[4] << 2);
775  k ^= (p[5] >> 2) ^ (p[5] << 4);
776 
777  //The hash value is reduced to a 6-bit index
778  k &= 0x3F;
779 
780  //Update hash table contents
781  hashTable[k / 32] |= (1 << (k % 32));
782  }
783 
784  //Increment the number of unicast addresses
785  j++;
786  }
787  }
788  }
789 
790  //Configure the first unicast address filter
791  if(j >= 1)
792  {
793  //The address is activated when SAT register is written
794  GMAC->GMAC_SA[1].GMAC_SAB = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
795  GMAC->GMAC_SA[1].GMAC_SAT = unicastMacAddr[0].w[2];
796  }
797  else
798  {
799  //The address is deactivated when SAB register is written
800  GMAC->GMAC_SA[1].GMAC_SAB = 0;
801  }
802 
803  //Configure the second unicast address filter
804  if(j >= 2)
805  {
806  //The address is activated when SAT register is written
807  GMAC->GMAC_SA[2].GMAC_SAB = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
808  GMAC->GMAC_SA[2].GMAC_SAT = unicastMacAddr[1].w[2];
809  }
810  else
811  {
812  //The address is deactivated when SAB register is written
813  GMAC->GMAC_SA[2].GMAC_SAB = 0;
814  }
815 
816  //Configure the third unicast address filter
817  if(j >= 3)
818  {
819  //The address is activated when SAT register is written
820  GMAC->GMAC_SA[3].GMAC_SAB = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
821  GMAC->GMAC_SA[3].GMAC_SAT = unicastMacAddr[2].w[2];
822  }
823  else
824  {
825  //The address is deactivated when SAB register is written
826  GMAC->GMAC_SA[3].GMAC_SAB = 0;
827  }
828 
829  //The perfect MAC filter supports only 3 unicast addresses
830  if(j >= 4)
831  GMAC->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;
832  else
833  GMAC->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;
834 
835  //Configure the multicast address filter
836  GMAC->GMAC_HRB = hashTable[0];
837  GMAC->GMAC_HRT = hashTable[1];
838 
839  //Debug message
840  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", GMAC->GMAC_HRB);
841  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", GMAC->GMAC_HRT);
842 
843  //Successful processing
844  return NO_ERROR;
845 }
846 
847 
848 /**
849  * @brief Adjust MAC configuration parameters for proper operation
850  * @param[in] interface Underlying network interface
851  * @return Error code
852  **/
853 
855 {
856  uint32_t config;
857 
858  //Read network configuration register
859  config = GMAC->GMAC_NCFGR;
860 
861  //10BASE-T or 100BASE-TX operation mode?
862  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
863  config |= GMAC_NCFGR_SPD;
864  else
865  config &= ~GMAC_NCFGR_SPD;
866 
867  //Half-duplex or full-duplex mode?
868  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
869  config |= GMAC_NCFGR_FD;
870  else
871  config &= ~GMAC_NCFGR_FD;
872 
873  //Write configuration value back to NCFGR register
874  GMAC->GMAC_NCFGR = config;
875 
876  //Successful processing
877  return NO_ERROR;
878 }
879 
880 
881 /**
882  * @brief Write PHY register
883  * @param[in] opcode Access type (2 bits)
884  * @param[in] phyAddr PHY address (5 bits)
885  * @param[in] regAddr Register address (5 bits)
886  * @param[in] data Register value
887  **/
888 
889 void samv71EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
890  uint8_t regAddr, uint16_t data)
891 {
892  uint32_t temp;
893 
894  //Valid opcode?
895  if(opcode == SMI_OPCODE_WRITE)
896  {
897  //Set up a write operation
898  temp = GMAC_MAN_CLTTO | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2);
899  //PHY address
900  temp |= GMAC_MAN_PHYA(phyAddr);
901  //Register address
902  temp |= GMAC_MAN_REGA(regAddr);
903  //Register value
904  temp |= GMAC_MAN_DATA(data);
905 
906  //Start a write operation
907  GMAC->GMAC_MAN = temp;
908  //Wait for the write to complete
909  while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE))
910  {
911  }
912  }
913  else
914  {
915  //The MAC peripheral only supports standard Clause 22 opcodes
916  }
917 }
918 
919 
920 /**
921  * @brief Read PHY register
922  * @param[in] opcode Access type (2 bits)
923  * @param[in] phyAddr PHY address (5 bits)
924  * @param[in] regAddr Register address (5 bits)
925  * @return Register value
926  **/
927 
928 uint16_t samv71EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
929  uint8_t regAddr)
930 {
931  uint16_t data;
932  uint32_t temp;
933 
934  //Valid opcode?
935  if(opcode == SMI_OPCODE_READ)
936  {
937  //Set up a read operation
938  temp = GMAC_MAN_CLTTO | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2);
939  //PHY address
940  temp |= GMAC_MAN_PHYA(phyAddr);
941  //Register address
942  temp |= GMAC_MAN_REGA(regAddr);
943 
944  //Start a read operation
945  GMAC->GMAC_MAN = temp;
946  //Wait for the read to complete
947  while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE))
948  {
949  }
950 
951  //Get register value
952  data = GMAC->GMAC_MAN & GMAC_MAN_DATA_Msk;
953  }
954  else
955  {
956  //The MAC peripheral only supports standard Clause 22 opcodes
957  data = 0;
958  }
959 
960  //Return the value of the PHY register
961  return data;
962 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define SAMV71_ETH_TX_BUFFER_SIZE
#define SAMV71_ETH_DUMMY_BUFFER_SIZE
uint8_t length
Definition: dtls_misc.h:149
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
void samv71EthEventHandler(NetInterface *interface)
SAMV71 Ethernet MAC event handler.
#define GMAC_TX_WRAP
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:119
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
error_t samv71EthInit(NetInterface *interface)
SAMV71 Ethernet MAC initialization.
uint8_t p
Definition: ndp.h:298
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define TRUE
Definition: os_port.h:50
uint16_t samv71EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define sleep(delay)
Definition: os_port.h:131
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:89
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
void GMAC_Handler(void)
SAMV71 Ethernet MAC interrupt service routine.
#define GMAC_TX_LENGTH
void samv71EthTick(NetInterface *interface)
SAMV71 Ethernet MAC timer handler.
#define GMAC_TX_LAST
void samv71EthEnableIrq(NetInterface *interface)
Enable interrupts.
void samv71EthInitGpio(NetInterface *interface)
#define GMAC_RMII_MASK
#define GMAC_RX_WRAP
#define GMAC_RX_OWNERSHIP
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:110
#define osExitIsr(flag)
#define SAMV71_ETH_IRQ_GROUP_PRIORITY
#define SMI_OPCODE_WRITE
Definition: nic.h:62
void samv71EthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
void samv71EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define FALSE
Definition: os_port.h:46
#define SAMV71_ETH_IRQ_PRIORITY_GROUPING
SAMV71 Ethernet MAC controller.
error_t
Error codes.
Definition: error.h:42
error_t samv71EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define GMAC_RX_SOF
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
error_t samv71EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:222
@ ERROR_INVALID_LENGTH
Definition: error.h:109
#define SAMV71_ETH_TX_BUFFER_COUNT
@ ERROR_BUFFER_EMPTY
Definition: error.h:139
Transmit buffer descriptor.
#define GMAC_RX_EOF
OsEvent netEvent
Definition: net.c:77
#define SMI_OPCODE_READ
Definition: nic.h:63
#define TRACE_INFO(...)
Definition: debug.h:94
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:62
#define SAMV71_ETH_RX_BUFFER_SIZE
#define rxBuffer
#define SAMV71_ETH_IRQ_SUB_PRIORITY
Receive buffer descriptor.
#define SAMV71_ETH_DUMMY_BUFFER_COUNT
error_t samv71EthReceivePacket(NetInterface *interface)
Receive a packet.
#define GMAC_RX_LENGTH
#define TRACE_DEBUG(...)
Definition: debug.h:106
#define SAMV71_ETH_RX_BUFFER_COUNT
void samv71EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint16_t regAddr
error_t samv71EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
MAC filter table entry.
Definition: ethernet.h:220
const NicDriver samv71EthDriver
SAMV71 Ethernet MAC driver.
#define osEnterIsr()
Ipv6Addr address
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:106
#define GMAC_TX_USED
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
NIC driver.
Definition: nic.h:179
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define GMAC_RX_ADDRESS
__start_packed struct @108 MacAddr
MAC address.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:79