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.4
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  size_t length;
592 
593  //Retrieve the length of the packet
594  length = netBufferGetLength(buffer) - offset;
595 
596  //Check the frame length
598  {
599  //The transmitter can accept another packet
600  osSetEvent(&interface->nicTxEvent);
601  //Report an error
602  return ERROR_INVALID_LENGTH;
603  }
604 
605  //Make sure the current buffer is available for writing
606  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) == 0)
607  {
608  return ERROR_FAILURE;
609  }
610 
611  //Copy user data to the transmit buffer
612  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
613 
614  //Set the necessary flags in the descriptor entry
615  if(txBufferIndex < (SAMV71_ETH_TX_BUFFER_COUNT - 1))
616  {
617  //Write the status word
618  txBufferDesc[txBufferIndex].status = GMAC_TX_LAST |
620 
621  //Point to the next buffer
622  txBufferIndex++;
623  }
624  else
625  {
626  //Write the status word
627  txBufferDesc[txBufferIndex].status = GMAC_TX_WRAP | GMAC_TX_LAST |
629 
630  //Wrap around
631  txBufferIndex = 0;
632  }
633 
634  //Data synchronization barrier
635  __DSB();
636 
637  //Set the TSTART bit to initiate transmission
638  GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk;
639 
640  //Check whether the next buffer is available for writing
641  if((txBufferDesc[txBufferIndex].status & GMAC_TX_USED) != 0)
642  {
643  //The transmitter can accept another packet
644  osSetEvent(&interface->nicTxEvent);
645  }
646 
647  //Successful processing
648  return NO_ERROR;
649 }
650 
651 
652 /**
653  * @brief Receive a packet
654  * @param[in] interface Underlying network interface
655  * @return Error code
656  **/
657 
659 {
660  static uint32_t temp[ETH_MAX_FRAME_SIZE / 4];
661  error_t error;
662  uint_t i;
663  uint_t j;
664  uint_t sofIndex;
665  uint_t eofIndex;
666  size_t n;
667  size_t size;
668  size_t length;
669 
670  //Initialize variables
671  size = 0;
672  sofIndex = UINT_MAX;
673  eofIndex = UINT_MAX;
674 
675  //Search for SOF and EOF flags
676  for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++)
677  {
678  //Point to the current entry
679  j = rxBufferIndex + i;
680 
681  //Wrap around to the beginning of the buffer if necessary
683  {
685  }
686 
687  //No more entries to process?
688  if((rxBufferDesc[j].address & GMAC_RX_OWNERSHIP) == 0)
689  {
690  //Stop processing
691  break;
692  }
693 
694  //A valid SOF has been found?
695  if((rxBufferDesc[j].status & GMAC_RX_SOF) != 0)
696  {
697  //Save the position of the SOF
698  sofIndex = i;
699  }
700 
701  //A valid EOF has been found?
702  if((rxBufferDesc[j].status & GMAC_RX_EOF) != 0 && sofIndex != UINT_MAX)
703  {
704  //Save the position of the EOF
705  eofIndex = i;
706  //Retrieve the length of the frame
707  size = rxBufferDesc[j].status & GMAC_RX_LENGTH;
708  //Limit the number of data to read
709  size = MIN(size, ETH_MAX_FRAME_SIZE);
710  //Stop processing since we have reached the end of the frame
711  break;
712  }
713  }
714 
715  //Determine the number of entries to process
716  if(eofIndex != UINT_MAX)
717  {
718  j = eofIndex + 1;
719  }
720  else if(sofIndex != UINT_MAX)
721  {
722  j = sofIndex;
723  }
724  else
725  {
726  j = i;
727  }
728 
729  //Total number of bytes that have been copied from the receive buffer
730  length = 0;
731 
732  //Process incoming frame
733  for(i = 0; i < j; i++)
734  {
735  //Any data to copy from current buffer?
736  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
737  {
738  //Calculate the number of bytes to read at a time
740  //Copy data from receive buffer
741  osMemcpy((uint8_t *) temp + length, rxBuffer[rxBufferIndex], n);
742  //Update byte counters
743  length += n;
744  size -= n;
745  }
746 
747  //Mark the current buffer as free
748  rxBufferDesc[rxBufferIndex].address &= ~GMAC_RX_OWNERSHIP;
749 
750  //Point to the following entry
751  rxBufferIndex++;
752 
753  //Wrap around to the beginning of the buffer if necessary
754  if(rxBufferIndex >= SAMV71_ETH_RX_BUFFER_COUNT)
755  {
756  rxBufferIndex = 0;
757  }
758  }
759 
760  //Any packet to process?
761  if(length > 0)
762  {
763  NetRxAncillary ancillary;
764 
765  //Additional options can be passed to the stack along with the packet
766  ancillary = NET_DEFAULT_RX_ANCILLARY;
767 
768  //Pass the packet to the upper layer
769  nicProcessPacket(interface, (uint8_t *) temp, length, &ancillary);
770  //Valid packet received
771  error = NO_ERROR;
772  }
773  else
774  {
775  //No more data in the receive buffer
776  error = ERROR_BUFFER_EMPTY;
777  }
778 
779  //Return status code
780  return error;
781 }
782 
783 
784 /**
785  * @brief Configure MAC address filtering
786  * @param[in] interface Underlying network interface
787  * @return Error code
788  **/
789 
791 {
792  uint_t i;
793  uint_t j;
794  uint_t k;
795  uint8_t *p;
796  uint32_t hashTable[2];
797  MacAddr unicastMacAddr[3];
798  MacFilterEntry *entry;
799 
800  //Debug message
801  TRACE_DEBUG("Updating MAC filter...\r\n");
802 
803  //Set the MAC address of the station
804  GMAC_REGS->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
805  GMAC_REGS->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2];
806 
807  //The MAC supports 3 additional addresses for unicast perfect filtering
808  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
809  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
810  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
811 
812  //The hash table is used for multicast address filtering
813  hashTable[0] = 0;
814  hashTable[1] = 0;
815 
816  //The MAC address filter contains the list of MAC addresses to accept
817  //when receiving an Ethernet frame
818  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
819  {
820  //Point to the current entry
821  entry = &interface->macAddrFilter[i];
822 
823  //Valid entry?
824  if(entry->refCount > 0)
825  {
826  //Multicast address?
827  if(macIsMulticastAddr(&entry->addr))
828  {
829  //Point to the MAC address
830  p = entry->addr.b;
831 
832  //Apply the hash function
833  k = (p[0] >> 6) ^ p[0];
834  k ^= (p[1] >> 4) ^ (p[1] << 2);
835  k ^= (p[2] >> 2) ^ (p[2] << 4);
836  k ^= (p[3] >> 6) ^ p[3];
837  k ^= (p[4] >> 4) ^ (p[4] << 2);
838  k ^= (p[5] >> 2) ^ (p[5] << 4);
839 
840  //The hash value is reduced to a 6-bit index
841  k &= 0x3F;
842 
843  //Update hash table contents
844  hashTable[k / 32] |= (1 << (k % 32));
845  }
846  else
847  {
848  //Up to 3 additional MAC addresses can be specified
849  if(j < 3)
850  {
851  //Save the unicast address
852  unicastMacAddr[j] = entry->addr;
853  }
854  else
855  {
856  //Point to the MAC address
857  p = entry->addr.b;
858 
859  //Apply the hash function
860  k = (p[0] >> 6) ^ p[0];
861  k ^= (p[1] >> 4) ^ (p[1] << 2);
862  k ^= (p[2] >> 2) ^ (p[2] << 4);
863  k ^= (p[3] >> 6) ^ p[3];
864  k ^= (p[4] >> 4) ^ (p[4] << 2);
865  k ^= (p[5] >> 2) ^ (p[5] << 4);
866 
867  //The hash value is reduced to a 6-bit index
868  k &= 0x3F;
869 
870  //Update hash table contents
871  hashTable[k / 32] |= (1 << (k % 32));
872  }
873 
874  //Increment the number of unicast addresses
875  j++;
876  }
877  }
878  }
879 
880  //Configure the first unicast address filter
881  if(j >= 1)
882  {
883  //The address is activated when SAT register is written
884  GMAC_REGS->GMAC_SA[1].GMAC_SAB = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
885  GMAC_REGS->GMAC_SA[1].GMAC_SAT = unicastMacAddr[0].w[2];
886  }
887  else
888  {
889  //The address is deactivated when SAB register is written
890  GMAC_REGS->GMAC_SA[1].GMAC_SAB = 0;
891  }
892 
893  //Configure the second unicast address filter
894  if(j >= 2)
895  {
896  //The address is activated when SAT register is written
897  GMAC_REGS->GMAC_SA[2].GMAC_SAB = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
898  GMAC_REGS->GMAC_SA[2].GMAC_SAT = unicastMacAddr[1].w[2];
899  }
900  else
901  {
902  //The address is deactivated when SAB register is written
903  GMAC_REGS->GMAC_SA[2].GMAC_SAB = 0;
904  }
905 
906  //Configure the third unicast address filter
907  if(j >= 3)
908  {
909  //The address is activated when SAT register is written
910  GMAC_REGS->GMAC_SA[3].GMAC_SAB = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
911  GMAC_REGS->GMAC_SA[3].GMAC_SAT = unicastMacAddr[2].w[2];
912  }
913  else
914  {
915  //The address is deactivated when SAB register is written
916  GMAC_REGS->GMAC_SA[3].GMAC_SAB = 0;
917  }
918 
919  //The perfect MAC filter supports only 3 unicast addresses
920  if(j >= 4)
921  {
922  GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN_Msk;
923  }
924  else
925  {
926  GMAC_REGS->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN_Msk;
927  }
928 
929  //Configure the multicast hash table
930  GMAC_REGS->GMAC_HRB = hashTable[0];
931  GMAC_REGS->GMAC_HRT = hashTable[1];
932 
933  //Debug message
934  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", GMAC_REGS->GMAC_HRB);
935  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", GMAC_REGS->GMAC_HRT);
936 
937  //Successful processing
938  return NO_ERROR;
939 }
940 
941 
942 /**
943  * @brief Adjust MAC configuration parameters for proper operation
944  * @param[in] interface Underlying network interface
945  * @return Error code
946  **/
947 
949 {
950  uint32_t config;
951 
952  //Read network configuration register
953  config = GMAC_REGS->GMAC_NCFGR;
954 
955  //10BASE-T or 100BASE-TX operation mode?
956  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
957  {
958  config |= GMAC_NCFGR_SPD_Msk;
959  }
960  else
961  {
962  config &= ~GMAC_NCFGR_SPD_Msk;
963  }
964 
965  //Half-duplex or full-duplex mode?
966  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
967  {
968  config |= GMAC_NCFGR_FD_Msk;
969  }
970  else
971  {
972  config &= ~GMAC_NCFGR_FD_Msk;
973  }
974 
975  //Write configuration value back to NCFGR register
976  GMAC_REGS->GMAC_NCFGR = config;
977 
978  //Successful processing
979  return NO_ERROR;
980 }
981 
982 
983 /**
984  * @brief Write PHY register
985  * @param[in] opcode Access type (2 bits)
986  * @param[in] phyAddr PHY address (5 bits)
987  * @param[in] regAddr Register address (5 bits)
988  * @param[in] data Register value
989  **/
990 
991 void samv71EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
992  uint8_t regAddr, uint16_t data)
993 {
994  uint32_t temp;
995 
996  //Valid opcode?
997  if(opcode == SMI_OPCODE_WRITE)
998  {
999  //Set up a write operation
1000  temp = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2);
1001  //PHY address
1002  temp |= GMAC_MAN_PHYA(phyAddr);
1003  //Register address
1004  temp |= GMAC_MAN_REGA(regAddr);
1005  //Register value
1006  temp |= GMAC_MAN_DATA(data);
1007 
1008  //Start a write operation
1009  GMAC_REGS->GMAC_MAN = temp;
1010  //Wait for the write to complete
1011  while((GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk) == 0)
1012  {
1013  }
1014  }
1015  else
1016  {
1017  //The MAC peripheral only supports standard Clause 22 opcodes
1018  }
1019 }
1020 
1021 
1022 /**
1023  * @brief Read PHY register
1024  * @param[in] opcode Access type (2 bits)
1025  * @param[in] phyAddr PHY address (5 bits)
1026  * @param[in] regAddr Register address (5 bits)
1027  * @return Register value
1028  **/
1029 
1030 uint16_t samv71EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1031  uint8_t regAddr)
1032 {
1033  uint16_t data;
1034  uint32_t temp;
1035 
1036  //Valid opcode?
1037  if(opcode == SMI_OPCODE_READ)
1038  {
1039  //Set up a read operation
1040  temp = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2);
1041  //PHY address
1042  temp |= GMAC_MAN_PHYA(phyAddr);
1043  //Register address
1044  temp |= GMAC_MAN_REGA(regAddr);
1045 
1046  //Start a read operation
1047  GMAC_REGS->GMAC_MAN = temp;
1048  //Wait for the read to complete
1049  while((GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk) == 0)
1050  {
1051  }
1052 
1053  //Get register value
1054  data = GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk;
1055  }
1056  else
1057  {
1058  //The MAC peripheral only supports standard Clause 22 opcodes
1059  data = 0;
1060  }
1061 
1062  //Return the value of the PHY register
1063  return data;
1064 }
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 opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
#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
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.
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:307
#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.
void samv71EthTick(NetInterface *interface)
SAMV71 Ethernet MAC timer handler.
#define GMAC_RX_WRAP
void samv71EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define GMAC_RMII_MASK
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 osExitIsr(flag)
#define SAMV71_ETH_IRQ_GROUP_PRIORITY
#define GMAC_RX_EOF
#define SMI_OPCODE_WRITE
Definition: nic.h:66
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 FALSE
Definition: os_port.h:46
#define SAMV71_ETH_IRQ_PRIORITY_GROUPING
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
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_RX_ADDRESS
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define SAMV71_ETH_TX_BUFFER_COUNT
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
Transmit buffer descriptor.
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
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 rxBuffer
#define SAMV71_ETH_IRQ_SUB_PRIORITY
#define GMAC_RX_SOF
Receive buffer descriptor.
MacAddr
Definition: ethernet.h:195
#define SAMV71_ETH_DUMMY_BUFFER_COUNT
error_t samv71EthReceivePacket(NetInterface *interface)
Receive a packet.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#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 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
Ipv6Addr address[]
Definition: ipv6.h:325
const NicDriver samv71EthDriver
SAMV71 Ethernet MAC driver.
#define osEnterIsr()
__weak_func void samv71EthInitGpio(NetInterface *interface)
GPIO configuration.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define SAMV71_ETH_RAM_SECTION
@ 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:50
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define GMAC_RX_OWNERSHIP
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ 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