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