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