sama5d3_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file sama5d3_eth_driver.c
3  * @brief SAMA5D3 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 "sama5d3x.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 = ".ram_no_cache"
51 //RX buffer
52 #pragma data_alignment = 8
53 #pragma location = ".ram_no_cache"
55 //TX buffer descriptors
56 #pragma data_alignment = 8
57 #pragma location = ".ram_no_cache"
59 //RX buffer descriptors
60 #pragma data_alignment = 8
61 #pragma location = ".ram_no_cache"
63 
64 //GCC compiler?
65 #else
66 
67 //TX buffer
69  __attribute__((aligned(8), __section__(".ram_no_cache")));
70 //RX buffer
72  __attribute__((aligned(8), __section__(".ram_no_cache")));
73 //TX buffer descriptors
75  __attribute__((aligned(8), __section__(".ram_no_cache")));
76 //RX buffer descriptors
78  __attribute__((aligned(8), __section__(".ram_no_cache")));
79 
80 #endif
81 
82 //TX buffer index
83 static uint_t txBufferIndex;
84 //RX buffer index
85 static uint_t rxBufferIndex;
86 
87 
88 /**
89  * @brief SAMA5D3 Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief SAMA5D3 Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122  volatile uint32_t status;
123 
124  //Debug message
125  TRACE_INFO("Initializing SAMA5D3 Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //Enable EMAC peripheral clock
131  PMC->PMC_PCER1 = (1 << (ID_EMAC - 32));
132  //Enable IRQ controller peripheral clock
133  PMC->PMC_PCER1 = (1 << (ID_IRQ - 32));
134 
135  //Disable transmit and receive circuits
136  EMAC->EMAC_NCR = 0;
137 
138  //GPIO configuration
139  sama5d3EthInitGpio(interface);
140 
141  //Configure MDC clock speed
142  EMAC->EMAC_NCFGR = EMAC_NCFGR_CLK_MCK_64;
143  //Enable management port (MDC and MDIO)
144  EMAC->EMAC_NCR |= EMAC_NCR_MPE;
145 
146  //PHY transceiver initialization
147  error = interface->phyDriver->init(interface);
148  //Failed to initialize PHY transceiver?
149  if(error)
150  return error;
151 
152  //Set the MAC address of the station
153  EMAC->EMAC_SA[0].EMAC_SAxB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
154  EMAC->EMAC_SA[0].EMAC_SAxT = interface->macAddr.w[2];
155 
156  //The MAC supports 3 additional addresses for unicast perfect filtering
157  EMAC->EMAC_SA[1].EMAC_SAxB = 0;
158  EMAC->EMAC_SA[2].EMAC_SAxB = 0;
159  EMAC->EMAC_SA[3].EMAC_SAxB = 0;
160 
161  //Initialize hash table
162  EMAC->EMAC_HRB = 0;
163  EMAC->EMAC_HRT = 0;
164 
165  //Configure the receive filter
166  EMAC->EMAC_NCFGR |= EMAC_NCFGR_BIG | EMAC_NCFGR_MTI;
167 
168  //Initialize buffer descriptors
169  sama5d3EthInitBufferDesc(interface);
170 
171  //Clear transmit status register
172  EMAC->EMAC_TSR = EMAC_TSR_UND | EMAC_TSR_COMP | EMAC_TSR_BEX |
173  EMAC_TSR_TGO | EMAC_TSR_RLES | EMAC_TSR_COL | EMAC_TSR_UBR;
174  //Clear receive status register
175  EMAC->EMAC_RSR = EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA;
176 
177  //First disable all EMAC interrupts
178  EMAC->EMAC_IDR = 0xFFFFFFFF;
179  //Only the desired ones are enabled
180  EMAC->EMAC_IER = EMAC_IER_ROVR | EMAC_IER_TCOMP | EMAC_IER_TXERR |
181  EMAC_IER_RLE | EMAC_IER_TUND | EMAC_IER_RXUBR | EMAC_IER_RCOMP;
182 
183  //Read EMAC ISR register to clear any pending interrupt
184  status = EMAC->EMAC_ISR;
185 
186  //Configure interrupt controller
187  AIC->AIC_SSR = ID_EMAC;
188  AIC->AIC_SMR = AIC_SMR_SRCTYPE_INT_LEVEL_SENSITIVE | AIC_SMR_PRIOR(SAMA5D3_ETH_IRQ_PRIORITY);
189  AIC->AIC_SVR = (uint32_t) sama5d3EthIrqHandler;
190 
191  //Enable the EMAC to transmit and receive data
192  EMAC->EMAC_NCR |= EMAC_NCR_TE | EMAC_NCR_RE;
193 
194  //Accept any packets from the upper layer
195  osSetEvent(&interface->nicTxEvent);
196 
197  //Successful initialization
198  return NO_ERROR;
199 }
200 
201 
202 //SAMA5D3-Xplained or SAMA5D3-EDS evaluation board?
203 #if defined(USE_SAMA5D3_XPLAINED) || defined(USE_SAMA5D3_EDS)
204 
205 /**
206  * @brief GPIO configuration
207  * @param[in] interface Underlying network interface
208  **/
209 
210 void sama5d3EthInitGpio(NetInterface *interface)
211 {
212  //Enable PIO peripheral clock
213  PMC->PMC_PCER0 = (1 << ID_PIOC);
214 
215  //Disable pull-up resistors on RMII pins
216  PIOC->PIO_PUDR = EMAC_RMII_MASK;
217  //Disable interrupts-on-change
218  PIOC->PIO_IDR = EMAC_RMII_MASK;
219  //Assign RMII pins to peripheral A function
220  PIOC->PIO_ABCDSR[0] &= ~EMAC_RMII_MASK;
221  PIOC->PIO_ABCDSR[1] &= ~EMAC_RMII_MASK;
222  //Disable the PIO from controlling the corresponding pins
223  PIOC->PIO_PDR = EMAC_RMII_MASK;
224 
225  //Select RMII operation mode and enable transceiver clock
226  EMAC->EMAC_USRIO = EMAC_USRIO_CLKEN | EMAC_USRIO_RMII;
227 }
228 
229 #endif
230 
231 
232 /**
233  * @brief Initialize buffer descriptors
234  * @param[in] interface Underlying network interface
235  **/
236 
238 {
239  uint_t i;
240  uint32_t address;
241 
242  //Initialize TX buffer descriptors
243  for(i = 0; i < SAMA5D3_ETH_TX_BUFFER_COUNT; i++)
244  {
245  //Calculate the address of the current TX buffer
246  address = (uint32_t) txBuffer[i];
247  //Write the address to the descriptor entry
248  txBufferDesc[i].address = address;
249  //Initialize status field
250  txBufferDesc[i].status = EMAC_TX_USED;
251  }
252 
253  //Mark the last descriptor entry with the wrap flag
254  txBufferDesc[i - 1].status |= EMAC_TX_WRAP;
255  //Initialize TX buffer index
256  txBufferIndex = 0;
257 
258  //Initialize RX buffer descriptors
259  for(i = 0; i < SAMA5D3_ETH_RX_BUFFER_COUNT; i++)
260  {
261  //Calculate the address of the current RX buffer
262  address = (uint32_t) rxBuffer[i];
263  //Write the address to the descriptor entry
264  rxBufferDesc[i].address = address & EMAC_RX_ADDRESS;
265  //Clear status field
266  rxBufferDesc[i].status = 0;
267  }
268 
269  //Mark the last descriptor entry with the wrap flag
270  rxBufferDesc[i - 1].address |= EMAC_RX_WRAP;
271  //Initialize RX buffer index
272  rxBufferIndex = 0;
273 
274  //Start location of the TX descriptor list
275  EMAC->EMAC_TBQP = (uint32_t) txBufferDesc;
276  //Start location of the RX descriptor list
277  EMAC->EMAC_RBQP = (uint32_t) rxBufferDesc;
278 }
279 
280 
281 /**
282  * @brief SAMA5D3 Ethernet MAC timer handler
283  *
284  * This routine is periodically called by the TCP/IP stack to
285  * handle periodic operations such as polling the link state
286  *
287  * @param[in] interface Underlying network interface
288  **/
289 
290 void sama5d3EthTick(NetInterface *interface)
291 {
292  //Handle periodic operations
293  interface->phyDriver->tick(interface);
294 }
295 
296 
297 /**
298  * @brief Enable interrupts
299  * @param[in] interface Underlying network interface
300  **/
301 
303 {
304  //Enable Ethernet MAC interrupts
305  AIC->AIC_SSR = ID_EMAC;
306  AIC->AIC_IECR = AIC_IECR_INTEN;
307 
308  //Enable Ethernet PHY interrupts
309  interface->phyDriver->enableIrq(interface);
310 }
311 
312 
313 /**
314  * @brief Disable interrupts
315  * @param[in] interface Underlying network interface
316  **/
317 
319 {
320  //Disable Ethernet MAC interrupts
321  AIC->AIC_SSR = ID_EMAC;
322  AIC->AIC_IDCR = AIC_IDCR_INTD;
323 
324  //Disable Ethernet PHY interrupts
325  interface->phyDriver->disableIrq(interface);
326 }
327 
328 
329 /**
330  * @brief SAMA5D3 Ethernet MAC interrupt service routine
331  **/
332 
334 {
335  bool_t flag;
336  volatile uint32_t isr;
337  volatile uint32_t tsr;
338  volatile uint32_t rsr;
339 
340  //Interrupt service routine prologue
341  osEnterIsr();
342 
343  //This flag will be set if a higher priority task must be woken
344  flag = FALSE;
345 
346  //Each time the software reads EMAC_ISR, it has to check the
347  //contents of EMAC_TSR, EMAC_RSR and EMAC_NSR
348  isr = EMAC->EMAC_ISR;
349  tsr = EMAC->EMAC_TSR;
350  rsr = EMAC->EMAC_RSR;
351 
352  //A packet has been transmitted?
353  if(tsr & (EMAC_TSR_UND | EMAC_TSR_COMP | EMAC_TSR_BEX |
354  EMAC_TSR_TGO | EMAC_TSR_RLES | EMAC_TSR_COL | EMAC_TSR_UBR))
355  {
356  //Only clear TSR flags that are currently set
357  EMAC->EMAC_TSR = tsr;
358 
359  //Check whether the TX buffer is available for writing
360  if(txBufferDesc[txBufferIndex].status & EMAC_TX_USED)
361  {
362  //Notify the TCP/IP stack that the transmitter is ready to send
363  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
364  }
365  }
366 
367  //A packet has been received?
368  if(rsr & (EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA))
369  {
370  //Set event flag
371  nicDriverInterface->nicEvent = TRUE;
372  //Notify the TCP/IP stack of the event
373  flag |= osSetEventFromIsr(&netEvent);
374  }
375 
376  //Write AIC_EOICR register before exiting
377  AIC->AIC_EOICR = 0;
378 
379  //Interrupt service routine epilogue
380  osExitIsr(flag);
381 }
382 
383 
384 /**
385  * @brief SAMA5D3 Ethernet MAC event handler
386  * @param[in] interface Underlying network interface
387  **/
388 
390 {
391  error_t error;
392  uint32_t rsr;
393 
394  //Read receive status
395  rsr = EMAC->EMAC_RSR;
396 
397  //Packet received?
398  if(rsr & (EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA))
399  {
400  //Only clear RSR flags that are currently set
401  EMAC->EMAC_RSR = rsr;
402 
403  //Process all pending packets
404  do
405  {
406  //Read incoming packet
407  error = sama5d3EthReceivePacket(interface);
408 
409  //No more data in the receive buffer?
410  } while(error != ERROR_BUFFER_EMPTY);
411  }
412 }
413 
414 
415 /**
416  * @brief Send a packet
417  * @param[in] interface Underlying network interface
418  * @param[in] buffer Multi-part buffer containing the data to send
419  * @param[in] offset Offset to the first data byte
420  * @return Error code
421  **/
422 
424  const NetBuffer *buffer, size_t offset)
425 {
426  size_t length;
427 
428  //Retrieve the length of the packet
429  length = netBufferGetLength(buffer) - offset;
430 
431  //Check the frame length
433  {
434  //The transmitter can accept another packet
435  osSetEvent(&interface->nicTxEvent);
436  //Report an error
437  return ERROR_INVALID_LENGTH;
438  }
439 
440  //Make sure the current buffer is available for writing
441  if(!(txBufferDesc[txBufferIndex].status & EMAC_TX_USED))
442  return ERROR_FAILURE;
443 
444  //Copy user data to the transmit buffer
445  netBufferRead(txBuffer[txBufferIndex], buffer, offset, length);
446 
447  //Set the necessary flags in the descriptor entry
448  if(txBufferIndex < (SAMA5D3_ETH_TX_BUFFER_COUNT - 1))
449  {
450  //Write the status word
451  txBufferDesc[txBufferIndex].status =
453 
454  //Point to the next buffer
455  txBufferIndex++;
456  }
457  else
458  {
459  //Write the status word
460  txBufferDesc[txBufferIndex].status = EMAC_TX_WRAP |
462 
463  //Wrap around
464  txBufferIndex = 0;
465  }
466 
467  //Set the TSTART bit to initiate transmission
468  EMAC->EMAC_NCR |= EMAC_NCR_TSTART;
469 
470  //Check whether the next buffer is available for writing
471  if(txBufferDesc[txBufferIndex].status & EMAC_TX_USED)
472  {
473  //The transmitter can accept another packet
474  osSetEvent(&interface->nicTxEvent);
475  }
476 
477  //Successful processing
478  return NO_ERROR;
479 }
480 
481 
482 /**
483  * @brief Receive a packet
484  * @param[in] interface Underlying network interface
485  * @return Error code
486  **/
487 
489 {
490  static uint8_t temp[ETH_MAX_FRAME_SIZE];
491  error_t error;
492  uint_t i;
493  uint_t j;
494  uint_t sofIndex;
495  uint_t eofIndex;
496  size_t n;
497  size_t size;
498  size_t length;
499 
500  //Initialize SOF and EOF indices
501  sofIndex = UINT_MAX;
502  eofIndex = UINT_MAX;
503 
504  //Search for SOF and EOF flags
505  for(i = 0; i < SAMA5D3_ETH_RX_BUFFER_COUNT; i++)
506  {
507  //Point to the current entry
508  j = rxBufferIndex + i;
509 
510  //Wrap around to the beginning of the buffer if necessary
513 
514  //No more entries to process?
515  if(!(rxBufferDesc[j].address & EMAC_RX_OWNERSHIP))
516  {
517  //Stop processing
518  break;
519  }
520  //A valid SOF has been found?
521  if(rxBufferDesc[j].status & EMAC_RX_SOF)
522  {
523  //Save the position of the SOF
524  sofIndex = i;
525  }
526  //A valid EOF has been found?
527  if((rxBufferDesc[j].status & EMAC_RX_EOF) && sofIndex != UINT_MAX)
528  {
529  //Save the position of the EOF
530  eofIndex = i;
531  //Retrieve the length of the frame
532  size = rxBufferDesc[j].status & EMAC_RX_LENGTH;
533  //Limit the number of data to read
534  size = MIN(size, ETH_MAX_FRAME_SIZE);
535  //Stop processing since we have reached the end of the frame
536  break;
537  }
538  }
539 
540  //Determine the number of entries to process
541  if(eofIndex != UINT_MAX)
542  j = eofIndex + 1;
543  else if(sofIndex != UINT_MAX)
544  j = sofIndex;
545  else
546  j = i;
547 
548  //Total number of bytes that have been copied from the receive buffer
549  length = 0;
550 
551  //Process incoming frame
552  for(i = 0; i < j; i++)
553  {
554  //Any data to copy from current buffer?
555  if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex)
556  {
557  //Calculate the number of bytes to read at a time
559  //Copy data from receive buffer
560  memcpy(temp + length, rxBuffer[rxBufferIndex], n);
561  //Update byte counters
562  length += n;
563  size -= n;
564  }
565 
566  //Mark the current buffer as free
567  rxBufferDesc[rxBufferIndex].address &= ~EMAC_RX_OWNERSHIP;
568 
569  //Point to the following entry
570  rxBufferIndex++;
571 
572  //Wrap around to the beginning of the buffer if necessary
573  if(rxBufferIndex >= SAMA5D3_ETH_RX_BUFFER_COUNT)
574  rxBufferIndex = 0;
575  }
576 
577  //Any packet to process?
578  if(length > 0)
579  {
580  //Pass the packet to the upper layer
581  nicProcessPacket(interface, temp, length);
582  //Valid packet received
583  error = NO_ERROR;
584  }
585  else
586  {
587  //No more data in the receive buffer
588  error = ERROR_BUFFER_EMPTY;
589  }
590 
591  //Return status code
592  return error;
593 }
594 
595 
596 /**
597  * @brief Configure MAC address filtering
598  * @param[in] interface Underlying network interface
599  * @return Error code
600  **/
601 
603 {
604  uint_t i;
605  uint_t j;
606  uint_t k;
607  uint8_t *p;
608  uint32_t hashTable[2];
609  MacAddr unicastMacAddr[3];
610  MacFilterEntry *entry;
611 
612  //Debug message
613  TRACE_DEBUG("Updating MAC filter...\r\n");
614 
615  //Set the MAC address of the station
616  EMAC->EMAC_SA[0].EMAC_SAxB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
617  EMAC->EMAC_SA[0].EMAC_SAxT = interface->macAddr.w[2];
618 
619  //The MAC supports 3 additional addresses for unicast perfect filtering
620  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
621  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
622  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
623 
624  //The hash table is used for multicast address filtering
625  hashTable[0] = 0;
626  hashTable[1] = 0;
627 
628  //The MAC address filter contains the list of MAC addresses to accept
629  //when receiving an Ethernet frame
630  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
631  {
632  //Point to the current entry
633  entry = &interface->macAddrFilter[i];
634 
635  //Valid entry?
636  if(entry->refCount > 0)
637  {
638  //Multicast address?
639  if(macIsMulticastAddr(&entry->addr))
640  {
641  //Point to the MAC address
642  p = entry->addr.b;
643 
644  //Apply the hash function
645  k = (p[0] >> 6) ^ p[0];
646  k ^= (p[1] >> 4) ^ (p[1] << 2);
647  k ^= (p[2] >> 2) ^ (p[2] << 4);
648  k ^= (p[3] >> 6) ^ p[3];
649  k ^= (p[4] >> 4) ^ (p[4] << 2);
650  k ^= (p[5] >> 2) ^ (p[5] << 4);
651 
652  //The hash value is reduced to a 6-bit index
653  k &= 0x3F;
654 
655  //Update hash table contents
656  hashTable[k / 32] |= (1 << (k % 32));
657  }
658  else
659  {
660  //Up to 3 additional MAC addresses can be specified
661  if(j < 3)
662  {
663  //Save the unicast address
664  unicastMacAddr[j] = entry->addr;
665  }
666  else
667  {
668  //Point to the MAC address
669  p = entry->addr.b;
670 
671  //Apply the hash function
672  k = (p[0] >> 6) ^ p[0];
673  k ^= (p[1] >> 4) ^ (p[1] << 2);
674  k ^= (p[2] >> 2) ^ (p[2] << 4);
675  k ^= (p[3] >> 6) ^ p[3];
676  k ^= (p[4] >> 4) ^ (p[4] << 2);
677  k ^= (p[5] >> 2) ^ (p[5] << 4);
678 
679  //The hash value is reduced to a 6-bit index
680  k &= 0x3F;
681 
682  //Update hash table contents
683  hashTable[k / 32] |= (1 << (k % 32));
684  }
685 
686  //Increment the number of unicast addresses
687  j++;
688  }
689  }
690  }
691 
692  //Configure the first unicast address filter
693  if(j >= 1)
694  {
695  //The address is activated when SAT register is written
696  EMAC->EMAC_SA[1].EMAC_SAxB = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
697  EMAC->EMAC_SA[1].EMAC_SAxT = unicastMacAddr[0].w[2];
698  }
699  else
700  {
701  //The address is deactivated when SAB register is written
702  EMAC->EMAC_SA[1].EMAC_SAxB = 0;
703  }
704 
705  //Configure the second unicast address filter
706  if(j >= 2)
707  {
708  //The address is activated when SAT register is written
709  EMAC->EMAC_SA[2].EMAC_SAxB = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
710  EMAC->EMAC_SA[2].EMAC_SAxT = unicastMacAddr[1].w[2];
711  }
712  else
713  {
714  //The address is deactivated when SAB register is written
715  EMAC->EMAC_SA[2].EMAC_SAxB = 0;
716  }
717 
718  //Configure the third unicast address filter
719  if(j >= 3)
720  {
721  //The address is activated when SAT register is written
722  EMAC->EMAC_SA[3].EMAC_SAxB = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
723  EMAC->EMAC_SA[3].EMAC_SAxT = unicastMacAddr[2].w[2];
724  }
725  else
726  {
727  //The address is deactivated when SAB register is written
728  EMAC->EMAC_SA[3].EMAC_SAxB = 0;
729  }
730 
731  //The perfect MAC filter supports only 3 unicast addresses
732  if(j >= 4)
733  EMAC->EMAC_NCFGR |= EMAC_NCFGR_UNI;
734  else
735  EMAC->EMAC_NCFGR &= ~EMAC_NCFGR_UNI;
736 
737  //Configure the multicast address filter
738  EMAC->EMAC_HRB = hashTable[0];
739  EMAC->EMAC_HRT = hashTable[1];
740 
741  //Debug message
742  TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", EMAC->EMAC_HRB);
743  TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", EMAC->EMAC_HRT);
744 
745  //Successful processing
746  return NO_ERROR;
747 }
748 
749 
750 /**
751  * @brief Adjust MAC configuration parameters for proper operation
752  * @param[in] interface Underlying network interface
753  * @return Error code
754  **/
755 
757 {
758  uint32_t config;
759 
760  //Read network configuration register
761  config = EMAC->EMAC_NCFGR;
762 
763  //10BASE-T or 100BASE-TX operation mode?
764  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
765  config |= EMAC_NCFGR_SPD;
766  else
767  config &= ~EMAC_NCFGR_SPD;
768 
769  //Half-duplex or full-duplex mode?
770  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
771  config |= EMAC_NCFGR_FD;
772  else
773  config &= ~EMAC_NCFGR_FD;
774 
775  //Write configuration value back to NCFGR register
776  EMAC->EMAC_NCFGR = config;
777 
778  //Successful processing
779  return NO_ERROR;
780 }
781 
782 
783 /**
784  * @brief Write PHY register
785  * @param[in] opcode Access type (2 bits)
786  * @param[in] phyAddr PHY address (5 bits)
787  * @param[in] regAddr Register address (5 bits)
788  * @param[in] data Register value
789  **/
790 
791 void sama5d3EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
792  uint8_t regAddr, uint16_t data)
793 {
794  uint32_t temp;
795 
796  //Valid opcode?
797  if(opcode == SMI_OPCODE_WRITE)
798  {
799  //Set up a write operation
800  temp = EMAC_MAN_SOF(1) | EMAC_MAN_RW(1) | EMAC_MAN_CODE(2);
801  //PHY address
802  temp |= EMAC_MAN_PHYA(phyAddr);
803  //Register address
804  temp |= EMAC_MAN_REGA(regAddr);
805  //Register value
806  temp |= EMAC_MAN_DATA(data);
807 
808  //Start a write operation
809  EMAC->EMAC_MAN = temp;
810  //Wait for the write to complete
811  while(!(EMAC->EMAC_NSR & EMAC_NSR_IDLE))
812  {
813  }
814  }
815  else
816  {
817  //The MAC peripheral only supports standard Clause 22 opcodes
818  }
819 }
820 
821 
822 /**
823  * @brief Read PHY register
824  * @param[in] opcode Access type (2 bits)
825  * @param[in] phyAddr PHY address (5 bits)
826  * @param[in] regAddr Register address (5 bits)
827  * @return Register value
828  **/
829 
830 uint16_t sama5d3EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
831  uint8_t regAddr)
832 {
833  uint16_t data;
834  uint32_t temp;
835 
836  //Valid opcode?
837  if(opcode == SMI_OPCODE_READ)
838  {
839  //Set up a read operation
840  temp = EMAC_MAN_SOF(1) | EMAC_MAN_RW(2) | EMAC_MAN_CODE(2);
841  //PHY address
842  temp |= EMAC_MAN_PHYA(phyAddr);
843  //Register address
844  temp |= EMAC_MAN_REGA(regAddr);
845 
846  //Start a read operation
847  EMAC->EMAC_MAN = temp;
848  //Wait for the read to complete
849  while(!(EMAC->EMAC_NSR & EMAC_NSR_IDLE))
850  {
851  }
852 
853  //Get register value
854  data = EMAC->EMAC_MAN & EMAC_MAN_DATA_Msk;
855  }
856  else
857  {
858  //The MAC peripheral only supports standard Clause 22 opcodes
859  data = 0;
860  }
861 
862  //Return the value of the PHY register
863  return data;
864 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
error_t sama5d3EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
uint8_t length
Definition: dtls_misc.h:149
error_t sama5d3EthReceivePacket(NetInterface *interface)
Receive a packet.
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
@ 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
void sama5d3EthEventHandler(NetInterface *interface)
SAMA5D3 Ethernet MAC event handler.
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 EMAC_RX_WRAP
#define TRUE
Definition: os_port.h:50
error_t sama5d3EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:89
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
#define EMAC_RX_EOF
#define EMAC_RX_OWNERSHIP
#define SAMA5D3_ETH_RX_BUFFER_COUNT
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:110
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:62
#define EMAC_RX_LENGTH
#define SAMA5D3_ETH_TX_BUFFER_SIZE
void sama5d3EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define SAMA5D3_ETH_TX_BUFFER_COUNT
#define FALSE
Definition: os_port.h:46
void sama5d3EthTick(NetInterface *interface)
SAMA5D3 Ethernet MAC timer handler.
#define EMAC_TX_LENGTH
uint16_t sama5d3EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t
Error codes.
Definition: error.h:42
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:222
@ ERROR_INVALID_LENGTH
Definition: error.h:109
@ ERROR_BUFFER_EMPTY
Definition: error.h:139
OsEvent netEvent
Definition: net.c:77
#define SMI_OPCODE_READ
Definition: nic.h:63
#define TRACE_INFO(...)
Definition: debug.h:94
void sama5d3EthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptors.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
const NicDriver sama5d3EthDriver
SAMA5D3 Ethernet MAC driver.
#define MIN(a, b)
Definition: os_port.h:62
#define rxBuffer
#define EMAC_RMII_MASK
#define TRACE_DEBUG(...)
Definition: debug.h:106
error_t sama5d3EthInit(NetInterface *interface)
SAMA5D3 Ethernet MAC initialization.
uint16_t regAddr
#define EMAC_TX_USED
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
MAC filter table entry.
Definition: ethernet.h:220
#define SAMA5D3_ETH_IRQ_PRIORITY
#define osEnterIsr()
#define EMAC_RX_ADDRESS
void sama5d3EthInitGpio(NetInterface *interface)
#define EMAC_TX_WRAP
#define EMAC_RX_SOF
#define SAMA5D3_ETH_RX_BUFFER_SIZE
Ipv6Addr address
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void sama5d3EthEnableIrq(NetInterface *interface)
Enable interrupts.
Transmit buffer descriptor.
SAMA5D3 Ethernet MAC controller.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:106
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
NIC driver.
Definition: nic.h:179
void sama5d3EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t sama5d3EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
Receive buffer descriptor.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
void sama5d3EthIrqHandler(void)
SAMA5D3 Ethernet MAC interrupt service routine.
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
__start_packed struct @108 MacAddr
MAC address.
#define EMAC_TX_LAST
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:79