m467_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file m467_eth_driver.c
3  * @brief Nuvoton M467 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "m460.h"
36 #include "core/net.h"
38 #include "debug.h"
39 
40 //Underlying network interface
41 static NetInterface *nicDriverInterface;
42 
43 //IAR EWARM compiler?
44 #if defined(__ICCARM__)
45 
46 //Transmit buffer
47 #pragma data_alignment = 4
49 //Receive buffer
50 #pragma data_alignment = 4
52 //Transmit DMA descriptors
53 #pragma data_alignment = 4
55 //Receive DMA descriptors
56 #pragma data_alignment = 4
58 
59 //Keil MDK-ARM or GCC compiler?
60 #else
61 
62 //Transmit buffer
64  __attribute__((aligned(4)));
65 //Receive buffer
67  __attribute__((aligned(4)));
68 //Transmit DMA descriptors
70  __attribute__((aligned(4)));
71 //Receive DMA descriptors
73  __attribute__((aligned(4)));
74 
75 #endif
76 
77 //Pointer to the current TX DMA descriptor
78 static M467TxDmaDesc *txCurDmaDesc;
79 //Pointer to the current RX DMA descriptor
80 static M467RxDmaDesc *rxCurDmaDesc;
81 
82 
83 /**
84  * @brief M467 Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief M467 Ethernet MAC initialization
110  * @param[in] interface Underlying network interface
111  * @return Error code
112  **/
113 
115 {
116  error_t error;
117 
118  //Debug message
119  TRACE_INFO("Initializing M467 Ethernet MAC...\r\n");
120 
121  //Save underlying network interface
122  nicDriverInterface = interface;
123 
124  //GPIO configuration
125  m467EthInitGpio(interface);
126 
127  //Reset EMAC module
128  SYS_ResetModule(EMAC0_RST);
129  //Enable EMAC clock
130  CLK_EnableModuleClock(EMAC0_MODULE);
131 
132  //Perform a software reset
134  //Wait for the reset to complete
135  while((EMAC_BUS_MODE & EMAC_BUS_MODE_SWR) != 0)
136  {
137  }
138 
139  //Adjust MDC clock range depending on CSR frequency
141 
142  //Valid Ethernet PHY or switch driver?
143  if(interface->phyDriver != NULL)
144  {
145  //Ethernet PHY initialization
146  error = interface->phyDriver->init(interface);
147  }
148  else if(interface->switchDriver != NULL)
149  {
150  //Ethernet switch initialization
151  error = interface->switchDriver->init(interface);
152  }
153  else
154  {
155  //The interface is not properly configured
156  error = ERROR_FAILURE;
157  }
158 
159  //Any error to report?
160  if(error)
161  {
162  return error;
163  }
164 
165  //Use default MAC configuration
167 
168  //Configure MAC address filtering
169  m467EthUpdateMacAddrFilter(interface);
170 
171  //Disable flow control
172  EMAC_FLOW_CONTROL = 0;
173  //Enable store and forward mode
175 
176  //Configure DMA bus mode
179 
180  //Initialize DMA descriptor lists
181  m467EthInitDmaDesc(interface);
182 
183  //Disable MAC interrupts
185  //Enable the desired DMA interrupts
188 
189  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
190  NVIC_SetPriorityGrouping(M467_ETH_IRQ_PRIORITY_GROUPING);
191 
192  //Configure Ethernet interrupt priority
193  NVIC_SetPriority(EMAC0_TXRX_IRQn, NVIC_EncodePriority(M467_ETH_IRQ_PRIORITY_GROUPING,
195 
196  //Enable MAC transmission and reception
198  //Enable DMA transmission and reception
200 
201  //Accept any packets from the upper layer
202  osSetEvent(&interface->nicTxEvent);
203 
204  //Successful initialization
205  return NO_ERROR;
206 }
207 
208 
209 /**
210  * @brief GPIO configuration
211  * @param[in] interface Underlying network interface
212  **/
213 
214 __weak_func void m467EthInitGpio(NetInterface *interface)
215 {
216 //NuMaker-IoT-M467 evaluation board?
217 #if defined(USE_NUMAKER_IOT_M467)
218  uint32_t temp;
219 
220  //Enable GPIO clocks
221  CLK->AHBCLK0 |= CLK_AHBCLK0_GPACKEN_Msk;
222  CLK->AHBCLK0 |= CLK_AHBCLK0_GPCCKEN_Msk;
223  CLK->AHBCLK0 |= CLK_AHBCLK0_GPECKEN_Msk;
224 
225  //Configure EMAC_RMII_RXERR (PA.6)
226  SET_EMAC0_RMII_RXERR_PA6();
227  //Configure EMAC_RMII_CRSDV (PA.7)
228  SET_EMAC0_RMII_CRSDV_PA7();
229  //Configure EMAC_RMII_RXD1 (PC.6)
230  SET_EMAC0_RMII_RXD1_PC6();
231  //Configure EMAC_RMII_RXD0 (PC.7)
232  SET_EMAC0_RMII_RXD0_PC7();
233  //Configure EMAC_RMII_REFCLK (PC.8)
234  SET_EMAC0_RMII_REFCLK_PC8();
235  //Configure EMAC_RMII_MDC (PE.8)
236  SET_EMAC0_RMII_MDC_PE8();
237  //Configure EMAC_RMII_MDIO (PE.9)
238  SET_EMAC0_RMII_MDIO_PE9();
239  //Configure EMAC_RMII_TXD0 (PE.10)
240  SET_EMAC0_RMII_TXD0_PE10();
241  //Configure EMAC_RMII_TXD1 (PE.11)
242  SET_EMAC0_RMII_TXD1_PE11();
243  //Configure EMAC_RMII_TXEN (PE.12)
244  SET_EMAC0_RMII_TXEN_PE12();
245 
246  //Enable high slew rate on RMII output pins
247  temp = PE->SLEWCTL;
248  temp = (temp & ~GPIO_SLEWCTL_HSREN10_Msk) | (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos);
249  temp = (temp & ~GPIO_SLEWCTL_HSREN11_Msk) | (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos);
250  temp = (temp & ~GPIO_SLEWCTL_HSREN12_Msk) | (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos);
251  PE->SLEWCTL = temp;
252 #endif
253 }
254 
255 
256 /**
257  * @brief Initialize DMA descriptor lists
258  * @param[in] interface Underlying network interface
259  **/
260 
262 {
263  uint_t i;
264 
265  //Initialize TX DMA descriptor list
266  for(i = 0; i < M467_ETH_TX_BUFFER_COUNT; i++)
267  {
268  //Use chain structure rather than ring structure
270  //Initialize transmit buffer size
271  txDmaDesc[i].tdes1 = 0;
272  //Transmit buffer address
273  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
274  //Next descriptor address
275  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
276  //Reserved fields
277  txDmaDesc[i].tdes4 = 0;
278  txDmaDesc[i].tdes5 = 0;
279  //Transmit frame time stamp
280  txDmaDesc[i].tdes6 = 0;
281  txDmaDesc[i].tdes7 = 0;
282  }
283 
284  //The last descriptor is chained to the first entry
285  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
286  //Point to the very first descriptor
287  txCurDmaDesc = &txDmaDesc[0];
288 
289  //Initialize RX DMA descriptor list
290  for(i = 0; i < M467_ETH_RX_BUFFER_COUNT; i++)
291  {
292  //The descriptor is initially owned by the DMA
293  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
294  //Use chain structure rather than ring structure
296  //Receive buffer address
297  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
298  //Next descriptor address
299  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
300  //Extended status
301  rxDmaDesc[i].rdes4 = 0;
302  //Reserved field
303  rxDmaDesc[i].rdes5 = 0;
304  //Receive frame time stamp
305  rxDmaDesc[i].rdes6 = 0;
306  rxDmaDesc[i].rdes7 = 0;
307  }
308 
309  //The last descriptor is chained to the first entry
310  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
311  //Point to the very first descriptor
312  rxCurDmaDesc = &rxDmaDesc[0];
313 
314  //Start location of the TX descriptor list
316  //Start location of the RX descriptor list
318 }
319 
320 
321 /**
322  * @brief M467 Ethernet MAC timer handler
323  *
324  * This routine is periodically called by the TCP/IP stack to handle periodic
325  * operations such as polling the link state
326  *
327  * @param[in] interface Underlying network interface
328  **/
329 
330 void m467EthTick(NetInterface *interface)
331 {
332  //Valid Ethernet PHY or switch driver?
333  if(interface->phyDriver != NULL)
334  {
335  //Handle periodic operations
336  interface->phyDriver->tick(interface);
337  }
338  else if(interface->switchDriver != NULL)
339  {
340  //Handle periodic operations
341  interface->switchDriver->tick(interface);
342  }
343  else
344  {
345  //Just for sanity
346  }
347 }
348 
349 
350 /**
351  * @brief Enable interrupts
352  * @param[in] interface Underlying network interface
353  **/
354 
356 {
357  //Enable Ethernet MAC interrupts
358  NVIC_EnableIRQ(EMAC0_TXRX_IRQn);
359 
360  //Valid Ethernet PHY or switch driver?
361  if(interface->phyDriver != NULL)
362  {
363  //Enable Ethernet PHY interrupts
364  interface->phyDriver->enableIrq(interface);
365  }
366  else if(interface->switchDriver != NULL)
367  {
368  //Enable Ethernet switch interrupts
369  interface->switchDriver->enableIrq(interface);
370  }
371  else
372  {
373  //Just for sanity
374  }
375 }
376 
377 
378 /**
379  * @brief Disable interrupts
380  * @param[in] interface Underlying network interface
381  **/
382 
384 {
385  //Disable Ethernet MAC interrupts
386  NVIC_DisableIRQ(EMAC0_TXRX_IRQn);
387 
388  //Valid Ethernet PHY or switch driver?
389  if(interface->phyDriver != NULL)
390  {
391  //Disable Ethernet PHY interrupts
392  interface->phyDriver->disableIrq(interface);
393  }
394  else if(interface->switchDriver != NULL)
395  {
396  //Disable Ethernet switch interrupts
397  interface->switchDriver->disableIrq(interface);
398  }
399  else
400  {
401  //Just for sanity
402  }
403 }
404 
405 
406 /**
407  * @brief M467 Ethernet MAC interrupt service routine
408  **/
409 
411 {
412  bool_t flag;
413  uint32_t status;
414 
415  //Interrupt service routine prologue
416  osEnterIsr();
417 
418  //This flag will be set if a higher priority task must be woken
419  flag = FALSE;
420 
421  //Read DMA status register
422  status = EMAC_STATUS;
423 
424  //Packet transmitted?
425  if((status & EMAC_STATUS_TI) != 0)
426  {
427  //Clear TI interrupt flag
429 
430  //Check whether the TX buffer is available for writing
431  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
432  {
433  //Notify the TCP/IP stack that the transmitter is ready to send
434  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
435  }
436  }
437 
438  //Packet received?
439  if((status & EMAC_STATUS_RI) != 0)
440  {
441  //Clear RI interrupt flag
443 
444  //Set event flag
445  nicDriverInterface->nicEvent = TRUE;
446  //Notify the TCP/IP stack of the event
447  flag |= osSetEventFromIsr(&netEvent);
448  }
449 
450  //Clear NIS interrupt flag
452 
453  //Interrupt service routine epilogue
454  osExitIsr(flag);
455 }
456 
457 
458 /**
459  * @brief M467 Ethernet MAC event handler
460  * @param[in] interface Underlying network interface
461  **/
462 
464 {
465  error_t error;
466 
467  //Process all pending packets
468  do
469  {
470  //Read incoming packet
471  error = m467EthReceivePacket(interface);
472 
473  //No more data in the receive buffer?
474  } while(error != ERROR_BUFFER_EMPTY);
475 }
476 
477 
478 /**
479  * @brief Send a packet
480  * @param[in] interface Underlying network interface
481  * @param[in] buffer Multi-part buffer containing the data to send
482  * @param[in] offset Offset to the first data byte
483  * @param[in] ancillary Additional options passed to the stack along with
484  * the packet
485  * @return Error code
486  **/
487 
489  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
490 {
491  size_t length;
492 
493  //Retrieve the length of the packet
494  length = netBufferGetLength(buffer) - offset;
495 
496  //Check the frame length
498  {
499  //The transmitter can accept another packet
500  osSetEvent(&interface->nicTxEvent);
501  //Report an error
502  return ERROR_INVALID_LENGTH;
503  }
504 
505  //Make sure the current buffer is available for writing
506  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) != 0)
507  {
508  return ERROR_FAILURE;
509  }
510 
511  //Copy user data to the transmit buffer
512  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
513 
514  //Write the number of bytes to send
515  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
516  //Set LS and FS flags as the data fits in a single buffer
517  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
518  //Give the ownership of the descriptor to the DMA
519  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
520 
521  //Clear TU flag to resume processing
523  //Instruct the DMA to poll the transmit descriptor list
525 
526  //Point to the next descriptor in the list
527  txCurDmaDesc = (M467TxDmaDesc *) txCurDmaDesc->tdes3;
528 
529  //Check whether the next buffer is available for writing
530  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
531  {
532  //The transmitter can accept another packet
533  osSetEvent(&interface->nicTxEvent);
534  }
535 
536  //Data successfully written
537  return NO_ERROR;
538 }
539 
540 
541 /**
542  * @brief Receive a packet
543  * @param[in] interface Underlying network interface
544  * @return Error code
545  **/
546 
548 {
549  error_t error;
550  size_t n;
551  NetRxAncillary ancillary;
552 
553  //Current buffer available for reading?
554  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN) == 0)
555  {
556  //FS and LS flags should be set
557  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) != 0 &&
558  (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS) != 0)
559  {
560  //Make sure no error occurred
561  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_ES) == 0)
562  {
563  //Retrieve the length of the frame
564  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
565  //Limit the number of data to read
567 
568  //Additional options can be passed to the stack along with the packet
569  ancillary = NET_DEFAULT_RX_ANCILLARY;
570 
571  //Pass the packet to the upper layer
572  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
573  &ancillary);
574 
575  //Valid packet received
576  error = NO_ERROR;
577  }
578  else
579  {
580  //The received packet contains an error
581  error = ERROR_INVALID_PACKET;
582  }
583  }
584  else
585  {
586  //The packet is not valid
587  error = ERROR_INVALID_PACKET;
588  }
589 
590  //Give the ownership of the descriptor back to the DMA
591  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
592  //Point to the next descriptor in the list
593  rxCurDmaDesc = (M467RxDmaDesc *) rxCurDmaDesc->rdes3;
594  }
595  else
596  {
597  //No more data in the receive buffer
598  error = ERROR_BUFFER_EMPTY;
599  }
600 
601  //Clear RU flag to resume processing
603  //Instruct the DMA to poll the receive descriptor list
605 
606  //Return status code
607  return error;
608 }
609 
610 
611 /**
612  * @brief Configure MAC address filtering
613  * @param[in] interface Underlying network interface
614  * @return Error code
615  **/
616 
618 {
619  uint_t i;
620  uint_t j;
621  bool_t acceptMulticast;
622  MacAddr unicastMacAddr[3];
623  MacFilterEntry *entry;
624 
625  //Debug message
626  TRACE_DEBUG("Updating MAC filter...\r\n");
627 
628  //Set the MAC address of the station
629  EMAC_MAC_ADDR0_HIGH = interface->macAddr.w[2];
630  EMAC_MAC_ADDR0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
631 
632  //The MAC supports 3 additional addresses for unicast perfect filtering
633  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
634  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
635  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
636 
637  //This flag will be set if multicast addresses should be accepted
638  acceptMulticast = FALSE;
639 
640  //The MAC address filter contains the list of MAC addresses to accept
641  //when receiving an Ethernet frame
642  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
643  {
644  //Point to the current entry
645  entry = &interface->macAddrFilter[i];
646 
647  //Valid entry?
648  if(entry->refCount > 0)
649  {
650  //Multicast address?
651  if(macIsMulticastAddr(&entry->addr))
652  {
653  //Accept multicast addresses
654  acceptMulticast = TRUE;
655  }
656  else
657  {
658  //Up to 3 additional MAC addresses can be specified
659  if(j < 3)
660  {
661  //Save the unicast address
662  unicastMacAddr[j++] = entry->addr;
663  }
664  }
665  }
666  }
667 
668  //Configure the first unicast address filter
669  if(j >= 1)
670  {
671  EMAC_MAC_ADDR1_HIGH = unicastMacAddr[0].w[2] | EMAC_MAC_ADDR1_HIGH_AE;
672  EMAC_MAC_ADDR1_LOW = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
673  }
674  else
675  {
677  EMAC_MAC_ADDR1_LOW = 0;
678  }
679 
680  //Configure the second unicast address filter
681  if(j >= 2)
682  {
683  EMAC_MAC_ADDR2_HIGH = unicastMacAddr[1].w[2] | EMAC_MAC_ADDR2_HIGH_AE;
684  EMAC_MAC_ADDR2_LOW = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
685  }
686  else
687  {
689  EMAC_MAC_ADDR2_LOW = 0;
690  }
691 
692  //Configure the third unicast address filter
693  if(j >= 3)
694  {
695  EMAC_MAC_ADDR3_HIGH = unicastMacAddr[2].w[2] | EMAC_MAC_ADDR3_HIGH_AE;
696  EMAC_MAC_ADDR3_LOW = unicastMacAddr[2].w[0] | (unicastMacAddr[0].w[2] << 16);
697  }
698  else
699  {
701  EMAC_MAC_ADDR3_LOW = 0;
702  }
703 
704  //Enable or disable the reception of multicast frames
705  if(acceptMulticast)
706  {
708  }
709  else
710  {
712  }
713 
714  //Successful processing
715  return NO_ERROR;
716 }
717 
718 
719 /**
720  * @brief Adjust MAC configuration parameters for proper operation
721  * @param[in] interface Underlying network interface
722  * @return Error code
723  **/
724 
726 {
727  uint32_t config;
728 
729  //Read current MAC configuration
730  config = EMAC_MAC_CONFIG;
731 
732  //10BASE-T or 100BASE-TX operation mode?
733  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
734  {
735  config |= EMAC_MAC_CONFIG_FES;
736  }
737  else
738  {
739  config &= ~EMAC_MAC_CONFIG_FES;
740  }
741 
742  //Half-duplex or full-duplex mode?
743  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
744  {
745  config |= EMAC_MAC_CONFIG_DM;
746  }
747  else
748  {
749  config &= ~EMAC_MAC_CONFIG_DM;
750  }
751 
752  //Update MAC configuration register
753  EMAC_MAC_CONFIG = config;
754 
755  //Successful processing
756  return NO_ERROR;
757 }
758 
759 
760 /**
761  * @brief Write PHY register
762  * @param[in] opcode Access type (2 bits)
763  * @param[in] phyAddr PHY address (5 bits)
764  * @param[in] regAddr Register address (5 bits)
765  * @param[in] data Register value
766  **/
767 
768 void m467EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
769  uint8_t regAddr, uint16_t data)
770 {
771  uint32_t temp;
772 
773  //Valid opcode?
774  if(opcode == SMI_OPCODE_WRITE)
775  {
776  //Take care not to alter MDC clock configuration
778  //Set up a write operation
780  //PHY address
781  temp |= (phyAddr << 11) & EMAC_GMII_ADDR_PA;
782  //Register address
783  temp |= (regAddr << 6) & EMAC_GMII_ADDR_GR;
784 
785  //Data to be written in the PHY register
787 
788  //Start a write operation
789  EMAC_GMII_ADDR = temp;
790  //Wait for the write to complete
791  while((EMAC_GMII_ADDR & EMAC_GMII_ADDR_GB) != 0)
792  {
793  }
794  }
795  else
796  {
797  //The MAC peripheral only supports standard Clause 22 opcodes
798  }
799 }
800 
801 
802 /**
803  * @brief Read PHY register
804  * @param[in] opcode Access type (2 bits)
805  * @param[in] phyAddr PHY address (5 bits)
806  * @param[in] regAddr Register address (5 bits)
807  * @return Register value
808  **/
809 
810 uint16_t m467EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
811  uint8_t regAddr)
812 {
813  uint16_t data;
814  uint32_t temp;
815 
816  //Valid opcode?
817  if(opcode == SMI_OPCODE_READ)
818  {
819  //Take care not to alter MDC clock configuration
821  //Set up a read operation
822  temp |= EMAC_GMII_ADDR_GB;
823  //PHY address
824  temp |= (phyAddr << 11) & EMAC_GMII_ADDR_PA;
825  //Register address
826  temp |= (regAddr << 6) & EMAC_GMII_ADDR_GR;
827 
828  //Start a read operation
829  EMAC_GMII_ADDR = temp;
830  //Wait for the read to complete
831  while((EMAC_GMII_ADDR & EMAC_GMII_ADDR_GB) != 0)
832  {
833  }
834 
835  //Get register value
837  }
838  else
839  {
840  //The MAC peripheral only supports standard Clause 22 opcodes
841  data = 0;
842  }
843 
844  //Return the value of the PHY register
845  return data;
846 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define EMAC_RECEIVE_DESCRIPTOR_LIST_ADDR
#define EMAC_RDES1_RBS1
void m467EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
void EMAC0_IRQHandler(void)
M467 Ethernet MAC interrupt service routine.
uint8_t opcode
Definition: dns_common.h:188
#define EMAC_BUS_MODE_AAB
int bool_t
Definition: compiler_port.h:53
#define netEvent
Definition: net_legacy.h:196
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define EMAC_BUS_MODE_PBL_1
#define EMAC_GMII_ADDR_GW
#define EMAC_MAC_ADDR3_HIGH
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:690
#define EMAC_TDES0_OWN
#define EMAC_RDES0_ES
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define EMAC_OPERATION_MODE_SR
#define TRUE
Definition: os_port.h:50
#define EMAC_MAC_ADDR3_HIGH_AE
uint8_t data[]
Definition: ethernet.h:222
#define EMAC_STATUS
#define EMAC_MAC_ADDR1_LOW
#define M467_ETH_TX_BUFFER_COUNT
#define EMAC_GMII_ADDR_CR_DIV_102
#define EMAC_GMII_DATA
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
#define EMAC_TDES0_IC
error_t m467EthInit(NetInterface *interface)
M467 Ethernet MAC initialization.
const NicDriver m467EthDriver
M467 Ethernet MAC driver.
#define EMAC_INTERRUPT_ENABLE_RIE
uint16_t m467EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define EMAC_INTERRUPT_ENABLE_TIE
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
error_t m467EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
Nuvoton M467 Ethernet MAC driver.
error_t m467EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define EMAC_INTERRUPT_MASK
#define EMAC_MAC_CONFIG_FES
#define FALSE
Definition: os_port.h:46
#define EMAC_RDES1_RCH
#define EMAC_OPERATION_MODE_ST
#define EMAC_TDES1_TBS1
#define EMAC_FLOW_CONTROL
#define EMAC_INTERRUPT_MASK_TSIM
#define EMAC_RDES0_LS
error_t
Error codes.
Definition: error.h:43
#define EMAC_INTERRUPT_ENABLE_NIE
#define M467_ETH_IRQ_GROUP_PRIORITY
#define EMAC_STATUS_TI
#define EMAC_MAC_FRAME_FILTER_PM
#define EMAC_GMII_DATA_GD
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define M467_ETH_IRQ_PRIORITY_GROUPING
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:140
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
#define EMAC_STATUS_TU
@ ERROR_INVALID_LENGTH
Definition: error.h:111
error_t m467EthReceivePacket(NetInterface *interface)
Receive a packet.
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#define EMAC_MAC_ADDR2_HIGH
#define EMAC_MAC_CONFIG_RE
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
#define EMAC_INTERRUPT_ENABLE
#define EMAC_GMII_ADDR_PA
#define EMAC_BUS_MODE
#define EMAC_TDES0_LS
#define rxBuffer
#define M467_ETH_TX_BUFFER_SIZE
MacAddr
Definition: ethernet.h:195
#define EMAC_TDES0_TCH
#define EMAC_MAC_CONFIG_DO
Enhanced RX DMA descriptor.
#define EMAC_BUS_MODE_ATDS
#define EMAC_OPERATION_MODE_TSF
#define EMAC_MAC_ADDR2_LOW
#define EMAC_GMII_ADDR
#define EMAC_MAC_ADDR3_LOW
void m467EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define EMAC_RDES0_FL
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint16_t regAddr
#define EMAC_GMII_ADDR_GR
#define EMAC_MAC_CONFIG_DM
#define EMAC_RECEIVE_POLL_DEMAND
#define ETH_MTU
Definition: ethernet.h:116
void m467EthTick(NetInterface *interface)
M467 Ethernet MAC timer handler.
uint8_t n
#define EMAC_GMII_ADDR_GB
MAC filter table entry.
Definition: ethernet.h:262
#define EMAC_TRANSMIT_DESCRIPTOR_LIST_ADDR
#define EMAC_STATUS_RI
#define EMAC_MAC_ADDR0_LOW
#define EMAC_STATUS_NIS
#define EMAC_GMII_ADDR_CR
#define osEnterIsr()
void m467EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define M467_ETH_RX_BUFFER_SIZE
#define EMAC_MAC_FRAME_FILTER
#define EMAC_MAC_ADDR1_HIGH_AE
#define EMAC_OPERATION_MODE_RSF
#define EMAC_TRANSMIT_POLL_DEMAND
#define M467_ETH_RX_BUFFER_COUNT
Enhanced TX DMA descriptor.
#define EMAC_TDES0_FS
#define rxDmaDesc
#define EMAC_BUS_MODE_USP
#define EMAC_STATUS_RU
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define EMAC_MAC_CONFIG
#define EMAC_MAC_CONFIG_TE
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
error_t m467EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
#define EMAC_OPERATION_MODE
#define EMAC_BUS_MODE_SWR
NIC driver.
Definition: nic.h:286
#define EMAC_RDES0_OWN
#define M467_ETH_IRQ_SUB_PRIORITY
void m467EthEventHandler(NetInterface *interface)
M467 Ethernet MAC event handler.
#define EMAC_INTERRUPT_MASK_PMTIM
__weak_func void m467EthInitGpio(NetInterface *interface)
GPIO configuration.
#define EMAC_MAC_ADDR2_HIGH_AE
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define EMAC_MAC_ADDR1_HIGH
void m467EthDisableIrq(NetInterface *interface)
Disable interrupts.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define EMAC_RDES0_FS
#define EMAC_MAC_ADDR0_HIGH
#define EMAC_BUS_MODE_RPBL_1