samv71_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file samv71_eth_driver.c
3  * @brief SAMV71 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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 2.5.0
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 "sam.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 = SAMV71_ETH_RAM_SECTION
51 //RX buffer
52 #pragma data_alignment = 8
53 #pragma location = SAMV71_ETH_RAM_SECTION
55 //TX buffer descriptors
56 #pragma data_alignment = 4
57 #pragma location = SAMV71_ETH_RAM_SECTION
59 //RX buffer descriptors
60 #pragma data_alignment = 4
61 #pragma location = SAMV71_ETH_RAM_SECTION
63 
64 //Dummy TX buffer
65 #pragma data_alignment = 8
66 #pragma location = SAMV71_ETH_RAM_SECTION
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 = SAMV71_ETH_RAM_SECTION
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 = SAMV71_ETH_RAM_SECTION
75 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT];
76 //Dummy RX buffer descriptors
77 #pragma data_alignment = 4
78 #pragma location = SAMV71_ETH_RAM_SECTION
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__(SAMV71_ETH_RAM_SECTION)));
87 //RX buffer
89  __attribute__((aligned(8), __section__(SAMV71_ETH_RAM_SECTION)));
90 //TX buffer descriptors
92  __attribute__((aligned(4), __section__(SAMV71_ETH_RAM_SECTION)));
93 //RX buffer descriptors
95  __attribute__((aligned(4), __section__(SAMV71_ETH_RAM_SECTION)));
96 
97 //Dummy TX buffer
99  __attribute__((aligned(8), __section__(SAMV71_ETH_RAM_SECTION)));
100 //Dummy RX buffer
101 static uint8_t dummyRxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE]
102  __attribute__((aligned(8), __section__(SAMV71_ETH_RAM_SECTION)));
103 //Dummy TX buffer descriptors
104 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]
105  __attribute__((aligned(4), __section__(SAMV71_ETH_RAM_SECTION)));
106 //Dummy RX buffer descriptors
107 static Samv71RxBufferDesc dummyRxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]
108  __attribute__((aligned(4), __section__(SAMV71_ETH_RAM_SECTION)));
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_REGS->PMC_PCER1 = (1 << (ID_GMAC - 32));
162 
163  //Disable transmit and receive circuits
164  GMAC_REGS->GMAC_NCR = 0;
165 
166  //GPIO configuration
167  samv71EthInitGpio(interface);
168 
169  //Configure MDC clock speed
170  GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK_MCK_96;
171  //Enable management port (MDC and MDIO)
172  GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk;
173 
174  //Valid Ethernet PHY or switch driver?
175  if(interface->phyDriver != NULL)
176  {
177  //Ethernet PHY initialization
178  error = interface->phyDriver->init(interface);
179  }
180  else if(interface->switchDriver != NULL)
181  {
182  //Ethernet switch initialization
183  error = interface->switchDriver->init(interface);
184  }
185  else
186  {
187  //The interface is not properly configured
188  error = ERROR_FAILURE;
189  }
190 
191  //Any error to report?
192  if(error)
193  {
194  return error;
195  }
196 
197  //Set the MAC address of the station
198  GMAC_REGS->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
199  GMAC_REGS->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
200 
201  //The MAC supports 3 additional addresses for unicast perfect filtering
202  GMAC_REGS->GMAC_SA[1].GMAC_SAB = 0;
203  GMAC_REGS->GMAC_SA[2].GMAC_SAB = 0;
204  GMAC_REGS->GMAC_SA[3].GMAC_SAB = 0;
205 
206  //Initialize hash table
207  GMAC_REGS->GMAC_HRB = 0;
208  GMAC_REGS->GMAC_HRT = 0;
209 
210  //Configure the receive filter
212 
213  //DMA configuration
215  GMAC_DCFGR_TXPBMS_Msk | GMAC_DCFGR_RXBMS_FULL | GMAC_DCFGR_FBLDO_INCR4;
216 
222 
223  //Initialize buffer descriptors
224  samv71EthInitBufferDesc(interface);
225 
226  //Clear transmit status register
230 
231  //Clear receive status register
234 
235  //First disable all GMAC interrupts
236  GMAC_REGS->GMAC_IDR = 0xFFFFFFFF;
237  GMAC_REGS->GMAC_IDRPQ[0] = 0xFFFFFFFF;
238  GMAC_REGS->GMAC_IDRPQ[1] = 0xFFFFFFFF;
239  GMAC_REGS->GMAC_IDRPQ[2] = 0xFFFFFFFF;
240  GMAC_REGS->GMAC_IDRPQ[3] = 0xFFFFFFFF;
241  GMAC_REGS->GMAC_IDRPQ[4] = 0xFFFFFFFF;
242 
243  //Only the desired ones are enabled
247 
248  //Read GMAC_ISR register to clear any pending interrupt
249  status = GMAC_REGS->GMAC_ISR;
250  status = GMAC_REGS->GMAC_ISRPQ[0];
251  status = GMAC_REGS->GMAC_ISRPQ[1];
252  status = GMAC_REGS->GMAC_ISRPQ[2];
253  status = GMAC_REGS->GMAC_ISRPQ[3];
254  status = GMAC_REGS->GMAC_ISRPQ[4];
255  (void) status;
256 
257  //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
258  NVIC_SetPriorityGrouping(SAMV71_ETH_IRQ_PRIORITY_GROUPING);
259 
260  //Configure GMAC interrupt priority
261  NVIC_SetPriority(GMAC_IRQn, NVIC_EncodePriority(SAMV71_ETH_IRQ_PRIORITY_GROUPING,
263 
264  //Enable the GMAC to transmit and receive data
266 
267  //Accept any packets from the upper layer
268  osSetEvent(&interface->nicTxEvent);
269 
270  //Successful initialization
271  return NO_ERROR;
272 }
273 
274 
275 /**
276  * @brief GPIO configuration
277  * @param[in] interface Underlying network interface
278  **/
279 
280 __weak_func void samv71EthInitGpio(NetInterface *interface)
281 {
282 //SAMV71-Xplained-Ultra evaluation board?
283 #if defined(USE_SAMV71_XPLAINED_ULTRA)
284  uint32_t mask;
285 
286  //Enable PIO peripheral clocks
287  PMC_REGS->PMC_PCER0 = (1 << ID_PIOC) | (1 << ID_PIOD);
288 
289  //Configure RMII pins
290  mask = PIO_PD9A_GMAC_GMDIO | PIO_PD8A_GMAC_GMDC |
291  PIO_PD7A_GMAC_GRXER | PIO_PD6A_GMAC_GRX1 | PIO_PD5A_GMAC_GRX0 |
292  PIO_PD4A_GMAC_GRXDV | PIO_PD3A_GMAC_GTX1 | PIO_PD2A_GMAC_GTX0 |
293  PIO_PD1A_GMAC_GTXEN | PIO_PD0A_GMAC_GTXCK;
294 
295  //Disable pull-up resistors on RMII pins
296  PIOD_REGS->PIO_PUDR = mask;
297  //Disable interrupts-on-change
298  PIOD_REGS->PIO_IDR = mask;
299  //Assign RMII pins to peripheral A function
300  PIOD_REGS->PIO_ABCDSR[0] &= ~mask;
301  PIOD_REGS->PIO_ABCDSR[1] &= ~mask;
302  //Disable the PIO from controlling the corresponding pins
303  PIOD_REGS->PIO_PDR = mask;
304 
305  //Select RMII operation mode
306  GMAC_REGS->GMAC_UR &= ~GMAC_UR_RMII_Msk;
307 
308  //Configure PHY_RESET as an output
309  PIOC_REGS->PIO_PER = PIO_PC10;
310  PIOC_REGS->PIO_OER = PIO_PC10;
311 
312  //Reset PHY transceiver
313  PIOC_REGS->PIO_CODR = PIO_PC10;
314  sleep(10);
315  PIOC_REGS->PIO_SODR = PIO_PC10;
316  sleep(10);
317 #endif
318 }
319 
320 
321 /**
322  * @brief Initialize buffer descriptors
323  * @param[in] interface Underlying network interface
324  **/
325 
327 {
328  uint_t i;
329  uint32_t address;
330 
331  //Initialize TX buffer descriptors
332  for(i = 0; i < SAMV71_ETH_TX_BUFFER_COUNT; i++)
333  {
334  //Calculate the address of the current TX buffer
335  address = (uint32_t) txBuffer[i];
336  //Write the address to the descriptor entry
337  txBufferDesc[i].address = address;
338  //Initialize status field
339  txBufferDesc[i].status = GMAC_TX_USED;
340  }
341 
342  //Mark the last descriptor entry with the wrap flag
343  txBufferDesc[i - 1].status |= GMAC_TX_WRAP;
344  //Initialize TX buffer index
345  txBufferIndex = 0;
346 
347  //Initialize RX buffer descriptors
348  for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++)
349  {
350  //Calculate the address of the current RX buffer
351  address = (uint32_t) rxBuffer[i];
352  //Write the address to the descriptor entry
353  rxBufferDesc[i].address = address & GMAC_RX_ADDRESS;
354  //Clear status field
355  rxBufferDesc[i].status = 0;
356  }
357 
358  //Mark the last descriptor entry with the wrap flag
359  rxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
360  //Initialize RX buffer index
361  rxBufferIndex = 0;
362 
363  //Initialize dummy TX buffer descriptors
364  for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++)
365  {
366  //Calculate the address of the current TX buffer
367  address = (uint32_t) dummyTxBuffer[i];
368  //Write the address to the descriptor entry
369  dummyTxBufferDesc[i].address = address;
370  //Initialize status field
371  dummyTxBufferDesc[i].status = GMAC_TX_USED;
372  }
373 
374  //Mark the last descriptor entry with the wrap flag
375  dummyTxBufferDesc[i - 1].status |= GMAC_TX_WRAP;
376 
377  //Initialize dummy RX buffer descriptors
378  for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++)
379  {
380  //Calculate the address of the current RX buffer
381  address = (uint32_t) dummyRxBuffer[i];
382  //Write the address to the descriptor entry
383  dummyRxBufferDesc[i].address = (address & GMAC_RX_ADDRESS) | GMAC_RX_OWNERSHIP;
384  //Clear status field
385  dummyRxBufferDesc[i].status = 0;
386  }
387 
388  //Mark the last descriptor entry with the wrap flag
389  dummyRxBufferDesc[i - 1].address |= GMAC_RX_WRAP;
390 
391  //Start location of the TX descriptor list
392  GMAC_REGS->GMAC_TBQB = (uint32_t) txBufferDesc;
393  GMAC_REGS->GMAC_TBQBAPQ[0] = (uint32_t) dummyTxBufferDesc;
394  GMAC_REGS->GMAC_TBQBAPQ[1] = (uint32_t) dummyTxBufferDesc;
395  GMAC_REGS->GMAC_TBQBAPQ[2] = (uint32_t) dummyTxBufferDesc;
396  GMAC_REGS->GMAC_TBQBAPQ[3] = (uint32_t) dummyTxBufferDesc;
397  GMAC_REGS->GMAC_TBQBAPQ[4] = (uint32_t) dummyTxBufferDesc;
398 
399  //Start location of the RX descriptor list
400  GMAC_REGS->GMAC_RBQB = (uint32_t) rxBufferDesc;
401  GMAC_REGS->GMAC_RBQBAPQ[0] = (uint32_t) dummyRxBufferDesc;
402  GMAC_REGS->GMAC_RBQBAPQ[1] = (uint32_t) dummyRxBufferDesc;
403  GMAC_REGS->GMAC_RBQBAPQ[2] = (uint32_t) dummyRxBufferDesc;
404  GMAC_REGS->GMAC_RBQBAPQ[3] = (uint32_t) dummyRxBufferDesc;
405  GMAC_REGS->GMAC_RBQBAPQ[4] = (uint32_t) dummyRxBufferDesc;
406 }
407 
408 
409 /**
410  * @brief SAMV71 Ethernet MAC timer handler
411  *
412  * This routine is periodically called by the TCP/IP stack to handle periodic
413  * operations such as polling the link state
414  *
415  * @param[in] interface Underlying network interface
416  **/
417 
418 void samv71EthTick(NetInterface *interface)
419 {
420  //Valid Ethernet PHY or switch driver?
421  if(interface->phyDriver != NULL)
422  {
423  //Handle periodic operations
424  interface->phyDriver->tick(interface);
425  }
426  else if(interface->switchDriver != NULL)
427  {
428  //Handle periodic operations
429  interface->switchDriver->tick(interface);
430  }
431  else
432  {
433  //Just for sanity
434  }
435 }
436 
437 
438 /**
439  * @brief Enable interrupts
440  * @param[in] interface Underlying network interface
441  **/
442 
444 {
445  //Enable Ethernet MAC interrupts
446  NVIC_EnableIRQ(GMAC_IRQn);
447 
448  //Valid Ethernet PHY or switch driver?
449  if(interface->phyDriver != NULL)
450  {
451  //Enable Ethernet PHY interrupts
452  interface->phyDriver->enableIrq(interface);
453  }
454  else if(interface->switchDriver != NULL)
455  {
456  //Enable Ethernet switch interrupts
457  interface->switchDriver->enableIrq(interface);
458  }
459  else
460  {
461  //Just for sanity
462  }
463 }
464 
465 
466 /**
467  * @brief Disable interrupts
468  * @param[in] interface Underlying network interface
469  **/
470 
472 {
473  //Disable Ethernet MAC interrupts
474  NVIC_DisableIRQ(GMAC_IRQn);
475 
476  //Valid Ethernet PHY or switch driver?
477  if(interface->phyDriver != NULL)
478  {
479  //Disable Ethernet PHY interrupts
480  interface->phyDriver->disableIrq(interface);
481  }
482  else if(interface->switchDriver != NULL)
483  {
484  //Disable Ethernet switch interrupts
485  interface->switchDriver->disableIrq(interface);
486  }
487  else
488  {
489  //Just for sanity
490  }
491 }
492 
493 
494 /**
495  * @brief SAMV71 Ethernet MAC interrupt service routine
496  **/
497 
498 void GMAC_Handler(void)
499 {
500  bool_t flag;
501  volatile uint32_t isr;
502  volatile uint32_t tsr;
503  volatile uint32_t rsr;
504 
505  //Interrupt service routine prologue
506  osEnterIsr();
507 
508  //This flag will be set if a higher priority task must be woken
509  flag = FALSE;
510 
511  //Each time the software reads GMAC_ISR, it has to check the contents
512  //of GMAC_TSR, GMAC_RSR and GMAC_NSR
513  isr = GMAC_REGS->GMAC_ISRPQ[0];
514  isr = GMAC_REGS->GMAC_ISRPQ[1];
515  isr = GMAC_REGS->GMAC_ISRPQ[2];
516  isr = GMAC_REGS->GMAC_ISRPQ[3];
517  isr = GMAC_REGS->GMAC_ISRPQ[4];
518  isr = GMAC_REGS->GMAC_ISR;
519  tsr = GMAC_REGS->GMAC_TSR;
520  rsr = GMAC_REGS->GMAC_RSR;
521  (void) isr;
522 
523  //Packet transmitted?
527  {
528  //Only clear TSR flags that are currently set
529  GMAC_REGS->GMAC_TSR = tsr;
530 
531  //Check whether the TX buffer is available for writing
532  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) != 0)
533  {
534  //Notify the TCP/IP stack that the transmitter is ready to send
535  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
536  }
537  }
538 
539  //Packet received?
541  GMAC_RSR_BNA_Msk)) != 0)
542  {
543  //Set event flag
544  nicDriverInterface->nicEvent = TRUE;
545  //Notify the TCP/IP stack of the event
546  flag |= osSetEventFromIsr(&netEvent);
547  }
548 
549  //Interrupt service routine epilogue
550  osExitIsr(flag);
551 }
552 
553 
554 /**
555  * @brief SAMV71 Ethernet MAC event handler
556  * @param[in] interface Underlying network interface
557  **/
558 
560 {
561  error_t error;
562  uint32_t rsr;
563 
564  //Read receive status
565  rsr = GMAC_REGS->GMAC_RSR;
566 
567  //Packet received?
569  GMAC_RSR_BNA_Msk)) != 0)
570  {
571  //Only clear RSR flags that are currently set
572  GMAC_REGS->GMAC_RSR = rsr;
573 
574  //Process all pending packets
575  do
576  {
577  //Read incoming packet
578  error = samv71EthReceivePacket(interface);
579 
580  //No more data in the receive buffer?
581  } while(error != ERROR_BUFFER_EMPTY);
582  }
583 }
584 
585 
586 /**
587  * @brief Send a packet
588  * @param[in] interface Underlying network interface
589  * @param[in] buffer Multi-part buffer containing the data to send
590  * @param[in] offset Offset to the first data byte
591  * @param[in] ancillary Additional options passed to the stack along with
592  * the packet
593  * @return Error code
594  **/
595 
597  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
598 {
599  size_t length;
600 
601  //Retrieve the length of the packet
602  length = netBufferGetLength(buffer) - offset;
603 
604  //Check the frame length
606  {
607  //The transmitter can accept another packet
608  osSetEvent(&interface->nicTxEvent);
609  //Report an error
610  return ERROR_INVALID_LENGTH;
611  }
612 
613  //Make sure the current buffer is available for writing
614  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) == 0)
615  {
616  return ERROR_FAILURE;
617  }
618 
619  //Copy user data to the transmit buffer
620  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
621 
622  //Set the necessary flags in the descriptor entry
623  if(txBufferIndex < (SAMV71_ETH_TX_BUFFER_COUNT - 1))
624  {
625  //Write the status word
626  txBufferDesc[txBufferIndex].status = GMAC_TX_LAST |
628 
629  //Point to the next buffer
630  txBufferIndex++;
631  }
632  else
633  {
634  //Write the status word
635  txBufferDesc[txBufferIndex].status = GMAC_TX_WRAP | GMAC_TX_LAST |
637 
638  //Wrap around
639  txBufferIndex = 0;
640  }
641 
642  //Data synchronization barrier
643  __DSB();
644 
645  //Set the TSTART bit to initiate transmission
646  GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk;
647 
648  //Check whether the next buffer is available for writing
649  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) != 0)
650  {
651  //The transmitter can accept another packet
652  osSetEvent(&interface->nicTxEvent);
653  }
654 
655  //Successful processing
656  return NO_ERROR;
657 }
658 
659 
660 /**
661  * @brief Receive a packet
662  * @param[in] interface Underlying network interface
663  * @return Error code
664  **/
665 
667 {
668  static uint32_t temp[ETH_MAX_FRAME_SIZE / 4];
669  error_t error;
670  uint_t i;
671  uint_t j;
672  uint_t sofIndex;
673  uint_t eofIndex;
674  size_t n;
675  size_t size;
676  size_t length;
677 
678  //Initialize variables
679  size = 0;
680  sofIndex = UINT_MAX;
681  eofIndex = UINT_MAX;
682 
683  //Search for SOF and EOF flags
684  for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++)
685  {
686  //Point to the current entry
687  j = rxBufferIndex + i;
688 
689  //Wrap around to the beginning of the buffer if necessary
691  {
693  }
694 
695  //No more entries to process?
696  if((rxBufferDesc[j].address & GMAC_RX_OWNERSHIP) == 0)
697  {
698  //Stop processing
699  break;
700  }
701 
702  //A valid SOF has been found?
703  if((rxBufferDesc[j].status & GMAC_RX_SOF) != 0)
704  {
705  //Save the position of the SOF
706  sofIndex = i;
707  }
708 
709  //A valid EOF has been found?
710  if((rxBufferDesc[j].status & GMAC_RX_EOF) != 0 && sofIndex != UINT_MAX)
711  {
712  //Save the position of the EOF
713  eofIndex = i;
714  //Retrieve the length of the frame
715  size = rxBufferDesc[j].status & GMAC_RX_LENGTH;
716  //Limit the number of data to read
717  size = MIN(size, ETH_MAX_FRAME_SIZE);
718  //Stop processing since we have reached the end of the frame
719  break;
720  }
721  }
722 
723  //Determine the number of entries to process
724  if(eofIndex != UINT_MAX)
725  {
726  j = eofIndex + 1;
727  }
728  else if(sofIndex != UINT_MAX)
729  {
730  j = sofIndex;
731  }
732  else
733  {
734  j = i;
735  }
736 
737  //Total number of bytes that have been copied from the receive buffer
738  length = 0;
739 
740  //Process incoming frame
741  for(i = 0; i < j; i++)
742  {
743  //Any data to copy from current buffer?
744  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
745  {
746  //Calculate the number of bytes to read at a time
748  //Copy data from receive buffer
749  osMemcpy((uint8_t *) temp + length, rxBuffer[rxBufferIndex], n);
750  //Update byte counters
751  length += n;
752  size -= n;
753  }
754 
755  //Mark the current buffer as free
756  rxBufferDesc[rxBufferIndex].address &= ~GMAC_RX_OWNERSHIP;
757 
758  //Point to the following entry
759  rxBufferIndex++;
760 
761  //Wrap around to the beginning of the buffer if necessary
762  if(rxBufferIndex >= SAMV71_ETH_RX_BUFFER_COUNT)
763  {
764  rxBufferIndex = 0;
765  }
766  }
767 
768  //Any packet to process?
769  if(length > 0)
770  {
771  NetRxAncillary ancillary;
772 
773  //Additional options can be passed to the stack along with the packet
774  ancillary = NET_DEFAULT_RX_ANCILLARY;
775 
776  //Pass the packet to the upper layer
777  nicProcessPacket(interface, (uint8_t *) temp, length, &ancillary);
778  //Valid packet received
779  error = NO_ERROR;
780  }
781  else
782  {
783  //No more data in the receive buffer
784  error = ERROR_BUFFER_EMPTY;
785  }
786 
787  //Return status code
788  return error;
789 }
790 
791 
792 /**
793  * @brief Configure MAC address filtering
794  * @param[in] interface Underlying network interface
795  * @return Error code
796  **/
797 
799 {
800  uint_t i;
801  uint_t j;
802  uint_t k;
803  uint8_t *p;
804  uint32_t hashTable[2];
805  MacAddr unicastMacAddr[3];
806  MacFilterEntry *entry;
807 
808  //Debug message
809  TRACE_DEBUG("Updating MAC filter...\r\n");
810 
811  //Set the MAC address of the station
812  GMAC_REGS->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
813  GMAC_REGS->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
814 
815  //The MAC supports 3 additional addresses for unicast perfect filtering
816  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
817  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
818  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
819 
820  //The hash table is used for multicast address filtering
821  hashTable[0] = 0;
822  hashTable[1] = 0;
823 
824  //The MAC address filter contains the list of MAC addresses to accept
825  //when receiving an Ethernet frame
826  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
827  {
828  //Point to the current entry
829  entry = &interface->macAddrFilter[i];
830 
831  //Valid entry?
832  if(entry->refCount > 0)
833  {
834  //Multicast address?
835  if(macIsMulticastAddr(&entry->addr))
836  {
837  //Point to the MAC address
838  p = entry->addr.b;
839 
840  //Apply the hash function
841  k = (p[0] >> 6) ^ p[0];
842  k ^= (p[1] >> 4) ^ (p[1] << 2);
843  k ^= (p[2] >> 2) ^ (p[2] << 4);
844  k ^= (p[3] >> 6) ^ p[3];
845  k ^= (p[4] >> 4) ^ (p[4] << 2);
846  k ^= (p[5] >> 2) ^ (p[5] << 4);
847 
848  //The hash value is reduced to a 6-bit index
849  k &= 0x3F;
850 
851  //Update hash table contents
852  hashTable[k / 32] |= (1 << (k % 32));
853  }
854  else
855  {
856  //Up to 3 additional MAC addresses can be specified
857  if(j < 3)
858  {
859  //Save the unicast address
860  unicastMacAddr[j] = entry->addr;
861  }
862  else
863  {
864  //Point to the MAC address
865  p = entry->addr.b;
866 
867  //Apply the hash function
868  k = (p[0] >> 6) ^ p[0];
869  k ^= (p[1] >> 4) ^ (p[1] << 2);
870  k ^= (p[2] >> 2) ^ (p[2] << 4);
871  k ^= (p[3] >> 6) ^ p[3];
872  k ^= (p[4] >> 4) ^ (p[4] << 2);
873  k ^= (p[5] >> 2) ^ (p[5] << 4);
874 
875  //The hash value is reduced to a 6-bit index
876  k &= 0x3F;
877 
878  //Update hash table contents
879  hashTable[k / 32] |= (1 << (k % 32));
880  }
881 
882  //Increment the number of unicast addresses
883  j++;
884  }
885  }
886  }
887 
888  //Configure the first unicast address filter
889  if(j >= 1)
890  {
891  //The address is activated when SAT register is written
892  GMAC_REGS->GMAC_SA[1].GMAC_SAB = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
893  GMAC_REGS->GMAC_SA[1].GMAC_SAT = unicastMacAddr[0].w[2];
894  }
895  else
896  {
897  //The address is deactivated when SAB register is written
898  GMAC_REGS->GMAC_SA[1].GMAC_SAB = 0;
899  }
900 
901  //Configure the second unicast address filter
902  if(j >= 2)
903  {
904  //The address is activated when SAT register is written
905  GMAC_REGS->GMAC_SA[2].GMAC_SAB = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
906  GMAC_REGS->GMAC_SA[2].GMAC_SAT = unicastMacAddr[1].w[2];
907  }
908  else
909  {
910  //The address is deactivated when SAB register is written
911  GMAC_REGS->GMAC_SA[2].GMAC_SAB = 0;
912  }
913 
914  //Configure the third unicast address filter
915  if(j >= 3)
916  {
917  //The address is activated when SAT register is written
918  GMAC_REGS->GMAC_SA[3].GMAC_SAB = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
919  GMAC_REGS->GMAC_SA[3].GMAC_SAT = unicastMacAddr[2].w[2];
920  }
921  else
922  {
923  //The address is deactivated when SAB register is written
924  GMAC_REGS->GMAC_SA[3].GMAC_SAB = 0;
925  }
926 
927  //The perfect MAC filter supports only 3 unicast addresses
928  if(j >= 4)
929  {
930  GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN_Msk;
931  }
932  else
933  {
934  GMAC_REGS->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN_Msk;
935  }
936 
937  //Configure the multicast hash table
938  GMAC_REGS->GMAC_HRB = hashTable[0];
939  GMAC_REGS->GMAC_HRT = hashTable[1];
940 
941  //Debug message
942  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", GMAC_REGS->GMAC_HRB);
943  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", GMAC_REGS->GMAC_HRT);
944 
945  //Successful processing
946  return NO_ERROR;
947 }
948 
949 
950 /**
951  * @brief Adjust MAC configuration parameters for proper operation
952  * @param[in] interface Underlying network interface
953  * @return Error code
954  **/
955 
957 {
958  uint32_t config;
959 
960  //Read network configuration register
961  config = GMAC_REGS->GMAC_NCFGR;
962 
963  //10BASE-T or 100BASE-TX operation mode?
964  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
965  {
966  config |= GMAC_NCFGR_SPD_Msk;
967  }
968  else
969  {
970  config &= ~GMAC_NCFGR_SPD_Msk;
971  }
972 
973  //Half-duplex or full-duplex mode?
974  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
975  {
976  config |= GMAC_NCFGR_FD_Msk;
977  }
978  else
979  {
980  config &= ~GMAC_NCFGR_FD_Msk;
981  }
982 
983  //Write configuration value back to NCFGR register
984  GMAC_REGS->GMAC_NCFGR = config;
985 
986  //Successful processing
987  return NO_ERROR;
988 }
989 
990 
991 /**
992  * @brief Write PHY register
993  * @param[in] opcode Access type (2 bits)
994  * @param[in] phyAddr PHY address (5 bits)
995  * @param[in] regAddr Register address (5 bits)
996  * @param[in] data Register value
997  **/
998 
999 void samv71EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
1000  uint8_t regAddr, uint16_t data)
1001 {
1002  uint32_t temp;
1003 
1004  //Valid opcode?
1005  if(opcode == SMI_OPCODE_WRITE)
1006  {
1007  //Set up a write operation
1008  temp = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2);
1009  //PHY address
1010  temp |= GMAC_MAN_PHYA(phyAddr);
1011  //Register address
1012  temp |= GMAC_MAN_REGA(regAddr);
1013  //Register value
1014  temp |= GMAC_MAN_DATA(data);
1015 
1016  //Start a write operation
1017  GMAC_REGS->GMAC_MAN = temp;
1018  //Wait for the write to complete
1019  while((GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk) == 0)
1020  {
1021  }
1022  }
1023  else
1024  {
1025  //The MAC peripheral only supports standard Clause 22 opcodes
1026  }
1027 }
1028 
1029 
1030 /**
1031  * @brief Read PHY register
1032  * @param[in] opcode Access type (2 bits)
1033  * @param[in] phyAddr PHY address (5 bits)
1034  * @param[in] regAddr Register address (5 bits)
1035  * @return Register value
1036  **/
1037 
1038 uint16_t samv71EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1039  uint8_t regAddr)
1040 {
1041  uint16_t data;
1042  uint32_t temp;
1043 
1044  //Valid opcode?
1045  if(opcode == SMI_OPCODE_READ)
1046  {
1047  //Set up a read operation
1048  temp = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2);
1049  //PHY address
1050  temp |= GMAC_MAN_PHYA(phyAddr);
1051  //Register address
1052  temp |= GMAC_MAN_REGA(regAddr);
1053 
1054  //Start a read operation
1055  GMAC_REGS->GMAC_MAN = temp;
1056  //Wait for the read to complete
1057  while((GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk) == 0)
1058  {
1059  }
1060 
1061  //Get register value
1062  data = GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk;
1063  }
1064  else
1065  {
1066  //The MAC peripheral only supports standard Clause 22 opcodes
1067  data = 0;
1068  }
1069 
1070  //Return the value of the PHY register
1071  return data;
1072 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define GMAC_NCFGR_MTIHEN_Msk
#define SAMV71_ETH_TX_BUFFER_SIZE
#define GMAC_IER_RLEX_Msk
#define SAMV71_ETH_DUMMY_BUFFER_SIZE
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:61
#define GMAC_TX_LENGTH
#define netEvent
Definition: net_legacy.h:196
void samv71EthEventHandler(NetInterface *interface)
SAMV71 Ethernet MAC event handler.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define GMAC_IER_HRESP_Msk
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:690
error_t samv71EthInit(NetInterface *interface)
SAMV71 Ethernet MAC initialization.
#define GMAC_NSR_IDLE_Msk
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint16_t samv71EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
uint8_t data[]
Definition: ethernet.h:222
#define sleep(delay)
Definition: os_port.h:310
#define GMAC_NCR_RXEN_Msk
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:110
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
void GMAC_Handler(void)
SAMV71 Ethernet MAC interrupt service routine.
#define GMAC_TSR_RLE_Msk
void samv71EthTick(NetInterface *interface)
SAMV71 Ethernet MAC timer handler.
#define GMAC_RX_WRAP
void samv71EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define GMAC_MAN_PHYA
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define GMAC_TSR_TFC_Msk
#define osExitIsr(flag)
#define SAMV71_ETH_IRQ_GROUP_PRIORITY
#define GMAC_RX_EOF
#define GMAC_MAN_DATA
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define GMAC_NCFGR_UNIHEN_Msk
#define GMAC_TSR_HRESP_Msk
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 GMAC_TX_USED
#define GMAC_MAN_OP
#define FALSE
Definition: os_port.h:46
#define GMAC_IRQn
#define GMAC_NCFGR_SPD_Msk
#define SAMV71_ETH_IRQ_PRIORITY_GROUPING
#define GMAC_TSR_TXGO_Msk
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
SAMV71 Ethernet MAC driver.
error_t
Error codes.
Definition: error.h:43
error_t samv71EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define GMAC_IER_RCOMP_Msk
#define GMAC_RX_ADDRESS
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
#define GMAC_RBSRPQ_RBS
MacAddr addr
MAC address.
Definition: ethernet.h:263
#define GMAC_NCR_MPE_Msk
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define SAMV71_ETH_TX_BUFFER_COUNT
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
Transmit buffer descriptor.
#define GMAC_TSR_TXCOMP_Msk
#define NetTxAncillary
Definition: net_misc.h:36
uint8_t mask
Definition: web_socket.h:319
#define GMAC_NCFGR_FD_Msk
#define SMI_OPCODE_READ
Definition: nic.h:67
#define GMAC_NCR_TXEN_Msk
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
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:63
#define SAMV71_ETH_RX_BUFFER_SIZE
#define GMAC_RSR_BNA_Msk
#define rxBuffer
#define SAMV71_ETH_IRQ_SUB_PRIORITY
#define GMAC_RX_SOF
#define GMAC_TSR_UBR_Msk
Receive buffer descriptor.
MacAddr
Definition: ethernet.h:195
#define SAMV71_ETH_DUMMY_BUFFER_COUNT
error_t samv71EthReceivePacket(NetInterface *interface)
Receive a packet.
#define GMAC_NCR_TSTART_Msk
#define GMAC_DCFGR_TXPBMS_Msk
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define GMAC_IER_TUR_Msk
#define SAMV71_ETH_RX_BUFFER_COUNT
void samv71EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define GMAC_REGS
uint16_t regAddr
error_t samv71EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define GMAC_RX_LENGTH
#define ETH_MTU
Definition: ethernet.h:116
#define GMAC_TX_LAST
uint8_t n
MAC filter table entry.
Definition: ethernet.h:262
#define GMAC_DCFGR_DRBS
Ipv6Addr address[]
Definition: ipv6.h:325
const NicDriver samv71EthDriver
SAMV71 Ethernet MAC driver.
#define osEnterIsr()
#define GMAC_IER_TFC_Msk
#define GMAC_IER_ROVR_Msk
__weak_func void samv71EthInitGpio(NetInterface *interface)
GPIO configuration.
#define GMAC_MAN_WTN
#define GMAC_RSR_HNO_Msk
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define GMAC_RSR_RXOVR_Msk
#define SAMV71_ETH_RAM_SECTION
#define GMAC_IER_TCOMP_Msk
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
error_t samv71EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define GMAC_RSR_REC_Msk
NIC driver.
Definition: nic.h:286
#define GMAC_RX_OWNERSHIP
#define GMAC_MAN_REGA
#define GMAC_NCFGR_MAXFS_Msk
#define GMAC_TSR_COL_Msk
#define GMAC_IER_RXUBR_Msk
#define GMAC_MAN_CLTTO_Msk
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define GMAC_MAN_DATA_Msk
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define GMAC_TX_WRAP
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83