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