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