m487_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file m487_eth_driver.c
3  * @brief Nuvoton M487 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.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "m480.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 //Current transmit descriptor
78 static uint_t txIndex;
79 //Current receive descriptor
80 static uint_t rxIndex;
81 
82 
83 /**
84  * @brief M487 Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief M487 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 M487 Ethernet MAC...\r\n");
120 
121  //Save underlying network interface
122  nicDriverInterface = interface;
123 
124  //Enable EMAC clock
125  CLK_EnableModuleClock(EMAC_MODULE);
126  //Select MDC clock frequency
127  CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(200));
128 
129  //Perform a software reset
130  EMAC->CTL |= EMAC_CTL_RST_Msk;
131  //Wait for the reset to complete
132  while((EMAC->CTL & EMAC_CTL_RST_Msk) != 0)
133  {
134  }
135 
136  //GPIO configuration
137  m487EthInitGpio(interface);
138 
139  //Valid Ethernet PHY or switch driver?
140  if(interface->phyDriver != NULL)
141  {
142  //Ethernet PHY initialization
143  error = interface->phyDriver->init(interface);
144  }
145  else if(interface->switchDriver != NULL)
146  {
147  //Ethernet switch initialization
148  error = interface->switchDriver->init(interface);
149  }
150  else
151  {
152  //The interface is not properly configured
153  error = ERROR_FAILURE;
154  }
155 
156  //Any error to report?
157  if(error)
158  {
159  return error;
160  }
161 
162  //Set the upper 32 bits of the MAC address
163  EMAC->CAM0M = interface->macAddr.b[3] |
164  (interface->macAddr.b[2] << 8) |
165  (interface->macAddr.b[1] << 16) |
166  (interface->macAddr.b[0] << 24);
167 
168  //Set the lower 16 bits of the MAC address
169  EMAC->CAM0L = (interface->macAddr.b[5] << 16) |
170  (interface->macAddr.b[4] << 24);
171 
172  //Enable the corresponding CAM entry
173  EMAC->CAMEN = EMAC_CAMEN_CAMxEN_Msk << 0;
174  //Accept broadcast and multicast packets
175  EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | EMAC_CAMCTL_ABP_Msk;
176 
177  //Maximum frame length that can be accepted
178  EMAC->MRFL = M487_ETH_RX_BUFFER_SIZE;
179 
180  //Initialize DMA descriptor lists
181  m487EthInitDmaDesc(interface);
182 
183  //Enable the desired MAC interrupts
184  EMAC->INTEN = EMAC_INTEN_TXCPIEN_Msk | EMAC_INTEN_TXIEN_Msk |
185  EMAC_INTEN_RXGDIEN_Msk | EMAC_INTEN_RXIEN_Msk;
186 
187  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
188  NVIC_SetPriorityGrouping(M487_ETH_IRQ_PRIORITY_GROUPING);
189 
190  //Configure EMAC transmit interrupt priority
191  NVIC_SetPriority(EMAC_TX_IRQn, NVIC_EncodePriority(M487_ETH_IRQ_PRIORITY_GROUPING,
193 
194  //Configure EMAC receive interrupt priority
195  NVIC_SetPriority(EMAC_RX_IRQn, NVIC_EncodePriority(M487_ETH_IRQ_PRIORITY_GROUPING,
197 
198  //Enable transmission and reception
199  EMAC->CTL |= EMAC_CTL_TXON_Msk | EMAC_CTL_RXON_Msk;
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 m487EthInitGpio(NetInterface *interface)
215 {
216 //NuMaker-PFM-M487 or NuMaker-IoT-M487 evaluation board?
217 #if defined(USE_NUMAKER_PFM_M487) || defined(USE_NUMAKER_IOT_M487)
218  uint32_t temp;
219 
220  //Select RMII interface mode
221  EMAC->CTL |= EMAC_CTL_RMIIEN_Msk;
222 
223  //Configure EMAC_RMII_RXERR (PA.6) and EMAC_RMII_CRSDV (PA.7)
224  temp = SYS->GPA_MFPL;
225  temp = (temp & ~SYS_GPA_MFPL_PA6MFP_Msk) | SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR;
226  temp = (temp & ~SYS_GPA_MFPL_PA7MFP_Msk) | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
227  SYS->GPA_MFPL = temp;
228 
229  //Configure EMAC_RMII_RXD1 (PC.6) and EMAC_RMII_RXD0 (PC.7)
230  temp = SYS->GPC_MFPL;
231  temp = (temp & ~SYS_GPC_MFPL_PC6MFP_Msk) | SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1;
232  temp = (temp & ~SYS_GPC_MFPL_PC7MFP_Msk) | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
233  SYS->GPC_MFPL = temp;
234 
235  //Configure EMAC_RMII_REFCLK (PC.8)
236  temp = SYS->GPC_MFPH;
237  temp = (temp & ~SYS_GPC_MFPH_PC8MFP_Msk) | SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
238  SYS->GPC_MFPH = temp;
239 
240  //Configure EMAC_RMII_MDC (PE.8), EMAC_RMII_MDIO (PE.9),
241  //EMAC_RMII_TXD0 (PE.10), EMAC_RMII_TXD1 (PE.11) and
242  //EMAC_RMII_TXEN (PE.12)
243  temp = SYS->GPE_MFPH;
244  temp = (temp & ~SYS_GPE_MFPH_PE8MFP_Msk) | SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC;
245  temp = (temp & ~SYS_GPE_MFPH_PE9MFP_Msk) | SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO;
246  temp = (temp & ~SYS_GPE_MFPH_PE10MFP_Msk) | SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0;
247  temp = (temp & ~SYS_GPE_MFPH_PE11MFP_Msk) | SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1;
248  temp = (temp & ~SYS_GPE_MFPH_PE12MFP_Msk) | SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
249  SYS->GPE_MFPH = temp;
250 
251  //Enable high slew rate on RMII output pins
252  temp = PE->SLEWCTL;
253  temp = (temp & ~GPIO_SLEWCTL_HSREN10_Msk) | (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos);
254  temp = (temp & ~GPIO_SLEWCTL_HSREN11_Msk) | (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos);
255  temp = (temp & ~GPIO_SLEWCTL_HSREN12_Msk) | (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos);
256  PE->SLEWCTL = temp;
257 #endif
258 }
259 
260 
261 /**
262  * @brief Initialize DMA descriptor lists
263  * @param[in] interface Underlying network interface
264  **/
265 
267 {
268  uint_t i;
269 
270  //Initialize TX DMA descriptor list
271  for(i = 0; i < M487_ETH_TX_BUFFER_COUNT; i++)
272  {
273  //The descriptor is initially owned by the CPU
274  txDmaDesc[i].txdes0 = 0;
275  //Transmit buffer address
276  txDmaDesc[i].txdes1 = (uint32_t) txBuffer[i];
277  //Transmit frame status
278  txDmaDesc[i].txdes2 = 0;
279  //Next descriptor address
280  txDmaDesc[i].txdes3 = (uint32_t) &txDmaDesc[i + 1];
281  }
282 
283  //The last descriptor is chained to the first entry
284  txDmaDesc[i - 1].txdes3 = (uint32_t) &txDmaDesc[0];
285  //Initialize TX descriptor index
286  txIndex = 0;
287 
288  //Initialize RX DMA descriptor list
289  for(i = 0; i < M487_ETH_RX_BUFFER_COUNT; i++)
290  {
291  //The descriptor is initially owned by the DMA
292  rxDmaDesc[i].rxdes0 = EMAC_RXDES0_OWNER;
293  //Receive buffer address
294  rxDmaDesc[i].rxdes1 = (uint32_t) rxBuffer[i];
295  //Reserved field
296  rxDmaDesc[i].rxdes2 = 0;
297  //Next descriptor address
298  rxDmaDesc[i].rxdes3 = (uint32_t) &rxDmaDesc[i + 1];
299  }
300 
301  //The last descriptor is chained to the first entry
302  rxDmaDesc[i - 1].rxdes3 = (uint32_t) &rxDmaDesc[0];
303  //Initialize RX descriptor index
304  rxIndex = 0;
305 
306  //Start address of the TX descriptor list
307  EMAC->TXDSA = (uint32_t) txDmaDesc;
308  //Start address of the RX descriptor list
309  EMAC->RXDSA = (uint32_t) rxDmaDesc;
310 }
311 
312 
313 /**
314  * @brief M487 Ethernet MAC timer handler
315  *
316  * This routine is periodically called by the TCP/IP stack to handle periodic
317  * operations such as polling the link state
318  *
319  * @param[in] interface Underlying network interface
320  **/
321 
322 void m487EthTick(NetInterface *interface)
323 {
324  //Valid Ethernet PHY or switch driver?
325  if(interface->phyDriver != NULL)
326  {
327  //Handle periodic operations
328  interface->phyDriver->tick(interface);
329  }
330  else if(interface->switchDriver != NULL)
331  {
332  //Handle periodic operations
333  interface->switchDriver->tick(interface);
334  }
335  else
336  {
337  //Just for sanity
338  }
339 }
340 
341 
342 /**
343  * @brief Enable interrupts
344  * @param[in] interface Underlying network interface
345  **/
346 
348 {
349  //Enable Ethernet MAC interrupts
350  NVIC_EnableIRQ(EMAC_TX_IRQn);
351  NVIC_EnableIRQ(EMAC_RX_IRQn);
352 
353  //Valid Ethernet PHY or switch driver?
354  if(interface->phyDriver != NULL)
355  {
356  //Enable Ethernet PHY interrupts
357  interface->phyDriver->enableIrq(interface);
358  }
359  else if(interface->switchDriver != NULL)
360  {
361  //Enable Ethernet switch interrupts
362  interface->switchDriver->enableIrq(interface);
363  }
364  else
365  {
366  //Just for sanity
367  }
368 }
369 
370 
371 /**
372  * @brief Disable interrupts
373  * @param[in] interface Underlying network interface
374  **/
375 
377 {
378  //Disable Ethernet MAC interrupts
379  NVIC_DisableIRQ(EMAC_TX_IRQn);
380  NVIC_DisableIRQ(EMAC_RX_IRQn);
381 
382  //Valid Ethernet PHY or switch driver?
383  if(interface->phyDriver != NULL)
384  {
385  //Disable Ethernet PHY interrupts
386  interface->phyDriver->disableIrq(interface);
387  }
388  else if(interface->switchDriver != NULL)
389  {
390  //Disable Ethernet switch interrupts
391  interface->switchDriver->disableIrq(interface);
392  }
393  else
394  {
395  //Just for sanity
396  }
397 }
398 
399 
400 /**
401  * @brief Ethernet MAC transmit interrupt
402  **/
403 
405 {
406  bool_t flag;
407 
408  //Interrupt service routine prologue
409  osEnterIsr();
410 
411  //This flag will be set if a higher priority task must be woken
412  flag = FALSE;
413 
414  //Packet transmitted?
415  if((EMAC->INTSTS & EMAC_INTSTS_TXCPIF_Msk) != 0)
416  {
417  //Clear TXCPIF interrupt flag
418  EMAC->INTSTS = EMAC_INTSTS_TXCPIF_Msk;
419 
420  //Check whether the TX buffer is available for writing
421  if((txDmaDesc[txIndex].txdes0 & EMAC_TXDES0_OWNER) == 0)
422  {
423  //Notify the TCP/IP stack that the transmitter is ready to send
424  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
425  }
426  }
427 
428  //Interrupt service routine epilogue
429  osExitIsr(flag);
430 }
431 
432 
433 /**
434  * @brief Ethernet MAC receive interrupt
435  **/
436 
438 {
439  bool_t flag;
440 
441  //Interrupt service routine prologue
442  osEnterIsr();
443 
444  //This flag will be set if a higher priority task must be woken
445  flag = FALSE;
446 
447  //Packet received?
448  if((EMAC->INTSTS & EMAC_INTSTS_RXGDIF_Msk) != 0)
449  {
450  //Clear RXGDIF interrupt flag
451  EMAC->INTSTS = EMAC_INTSTS_RXGDIF_Msk;
452 
453  //Set event flag
454  nicDriverInterface->nicEvent = TRUE;
455  //Notify the TCP/IP stack of the event
456  flag |= osSetEventFromIsr(&netEvent);
457  }
458 
459  //Interrupt service routine epilogue
460  osExitIsr(flag);
461 }
462 
463 
464 /**
465  * @brief M487 Ethernet MAC event handler
466  * @param[in] interface Underlying network interface
467  **/
468 
470 {
471  error_t error;
472 
473  //Process all pending packets
474  do
475  {
476  //Read incoming packet
477  error = m487EthReceivePacket(interface);
478 
479  //No more data in the receive buffer?
480  } while(error != ERROR_BUFFER_EMPTY);
481 }
482 
483 
484 /**
485  * @brief Send a packet
486  * @param[in] interface Underlying network interface
487  * @param[in] buffer Multi-part buffer containing the data to send
488  * @param[in] offset Offset to the first data byte
489  * @param[in] ancillary Additional options passed to the stack along with
490  * the packet
491  * @return Error code
492  **/
493 
495  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
496 {
497  size_t length;
498  uint_t txNextIndex;
499 
500  //Retrieve the length of the packet
501  length = netBufferGetLength(buffer) - offset;
502 
503  //Check the frame length
505  {
506  //The transmitter can accept another packet
507  osSetEvent(&interface->nicTxEvent);
508  //Report an error
509  return ERROR_INVALID_LENGTH;
510  }
511 
512  //Make sure the current buffer is available for writing
513  if((txDmaDesc[txIndex].txdes0 & EMAC_TXDES0_OWNER) != 0)
514  {
515  return ERROR_FAILURE;
516  }
517 
518  //Copy user data to the transmit buffer
519  netBufferRead((uint8_t *) txBuffer[txIndex], buffer, offset, length);
520 
521  //Calculate the index of the next descriptor
522  txNextIndex = txIndex + 1;
523 
524  //Wrap around if necessary
525  if(txNextIndex >= M487_ETH_TX_BUFFER_COUNT)
526  {
527  txNextIndex = 0;
528  }
529 
530  //Set the start address of the buffer
531  txDmaDesc[txIndex].txdes1 = (uint32_t) txBuffer[txIndex];
532  //Write the number of bytes to send
533  txDmaDesc[txIndex].txdes2 = length & EMAC_TXDES2_TBC;
534  //Set the address of the next descriptor
535  txDmaDesc[txIndex].txdes3 = (uint32_t) &txDmaDesc[txNextIndex];
536 
537  //Give the ownership of the descriptor to the DMA
538  txDmaDesc[txIndex].txdes0 = EMAC_TXDES0_OWNER | EMAC_TXDES0_INTEN |
540 
541  //Instruct the DMA to poll the transmit descriptor list
542  EMAC->TXST = 0;
543 
544  //Point to the next register
545  txIndex = txNextIndex;
546 
547  //Check whether the next buffer is available for writing
548  if((txDmaDesc[txIndex].txdes0 & EMAC_TXDES0_OWNER) == 0)
549  {
550  //The transmitter can accept another packet
551  osSetEvent(&interface->nicTxEvent);
552  }
553 
554  //Data successfully written
555  return NO_ERROR;
556 }
557 
558 
559 /**
560  * @brief Receive a packet
561  * @param[in] interface Underlying network interface
562  * @return Error code
563  **/
564 
566 {
567  error_t error;
568  size_t n;
569  uint_t rxNextIndex;
570  NetRxAncillary ancillary;
571 
572  //Current buffer available for reading?
573  if((rxDmaDesc[rxIndex].rxdes0 & EMAC_RXDES0_OWNER) == 0)
574  {
575  //Valid frame received?
576  if((rxDmaDesc[rxIndex].rxdes0 & EMAC_RXDES0_RXGDIF) != 0)
577  {
578  //Retrieve the length of the frame
579  n = rxDmaDesc[rxIndex].rxdes0 & EMAC_RXDES0_RBC;
580  //Limit the number of data to read
582 
583  //Additional options can be passed to the stack along with the packet
584  ancillary = NET_DEFAULT_RX_ANCILLARY;
585 
586  //Pass the packet to the upper layer
587  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
588 
589  //Valid packet received
590  error = NO_ERROR;
591  }
592  else
593  {
594  //The packet is not valid
595  error = ERROR_INVALID_PACKET;
596  }
597 
598  //Calculate the index of the next descriptor
599  rxNextIndex = rxIndex + 1;
600 
601  //Wrap around if necessary
602  if(rxNextIndex >= M487_ETH_RX_BUFFER_COUNT)
603  {
604  rxNextIndex = 0;
605  }
606 
607  //Set the start address of the buffer
608  rxDmaDesc[rxIndex].rxdes1 = (uint32_t) rxBuffer[rxIndex];
609  //Set the address of the next descriptor
610  rxDmaDesc[rxIndex].rxdes3 = (uint32_t) &rxDmaDesc[rxNextIndex];
611  //Give the ownership of the descriptor back to the DMA
612  rxDmaDesc[rxIndex].rxdes0 = EMAC_RXDES0_OWNER;
613 
614  //Point to the next register
615  rxIndex = rxNextIndex;
616  }
617  else
618  {
619  //No more data in the receive buffer
620  error = ERROR_BUFFER_EMPTY;
621  }
622 
623  //Instruct the DMA to poll the receive descriptor list
624  EMAC->RXST = 0;
625 
626  //Return status code
627  return error;
628 }
629 
630 
631 /**
632  * @brief Configure MAC address filtering
633  * @param[in] interface Underlying network interface
634  * @return Error code
635  **/
636 
638 {
639  uint_t i;
640  bool_t acceptMulticast;
641 
642  //Debug message
643  TRACE_DEBUG("Updating MAC filter...\r\n");
644 
645  //This flag will be set if multicast addresses should be accepted
646  acceptMulticast = FALSE;
647 
648  //The MAC address filter contains the list of MAC addresses to accept
649  //when receiving an Ethernet frame
650  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
651  {
652  //Valid entry?
653  if(interface->macAddrFilter[i].refCount > 0)
654  {
655  //Accept multicast addresses
656  acceptMulticast = TRUE;
657  //We are done
658  break;
659  }
660  }
661 
662  //Enable or disable the reception of multicast frames
663  if(acceptMulticast)
664  {
665  EMAC->CAMCTL |= EMAC_CAMCTL_AMP_Msk;
666  }
667  else
668  {
669  EMAC->CAMCTL &= ~EMAC_CAMCTL_AMP_Msk;
670  }
671 
672  //Successful processing
673  return NO_ERROR;
674 }
675 
676 
677 /**
678  * @brief Adjust MAC configuration parameters for proper operation
679  * @param[in] interface Underlying network interface
680  * @return Error code
681  **/
682 
684 {
685  uint32_t config;
686 
687  //Read MAC control register
688  config = EMAC->CTL;
689 
690  //10BASE-T or 100BASE-TX operation mode?
691  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
692  {
693  config |= EMAC_CTL_OPMODE_Msk;
694  }
695  else
696  {
697  config &= ~EMAC_CTL_OPMODE_Msk;
698  }
699 
700  //Half-duplex or full-duplex mode?
701  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
702  {
703  config |= EMAC_CTL_FUDUP_Msk;
704  }
705  else
706  {
707  config &= ~EMAC_CTL_FUDUP_Msk;
708  }
709 
710  //Update MAC control register
711  EMAC->CTL = config;
712 
713  //Successful processing
714  return NO_ERROR;
715 }
716 
717 
718 /**
719  * @brief Write PHY register
720  * @param[in] opcode Access type (2 bits)
721  * @param[in] phyAddr PHY address (5 bits)
722  * @param[in] regAddr Register address (5 bits)
723  * @param[in] data Register value
724  **/
725 
726 void m487EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
727  uint8_t regAddr, uint16_t data)
728 {
729  uint32_t temp;
730 
731  //Valid opcode?
732  if(opcode == SMI_OPCODE_WRITE)
733  {
734  //Set up a write operation
735  temp = EMAC_MIIMCTL_MDCON_Msk | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk;
736  //PHY address
737  temp |= (phyAddr << EMAC_MIIMCTL_PHYADDR_Pos) & EMAC_MIIMCTL_PHYADDR_Msk;
738  //Register address
739  temp |= (regAddr << EMAC_MIIMCTL_PHYREG_Pos) & EMAC_MIIMCTL_PHYREG_Msk;
740 
741  //Data to be written in the PHY register
742  EMAC->MIIMDAT = data & EMAC_MIIMDAT_DATA_Msk;
743 
744  //Start a write operation
745  EMAC->MIIMCTL = temp;
746  //Wait for the write to complete
747  while((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) != 0)
748  {
749  }
750  }
751  else
752  {
753  //The MAC peripheral only supports standard Clause 22 opcodes
754  }
755 }
756 
757 
758 /**
759  * @brief Read PHY register
760  * @param[in] opcode Access type (2 bits)
761  * @param[in] phyAddr PHY address (5 bits)
762  * @param[in] regAddr Register address (5 bits)
763  * @return Register value
764  **/
765 
766 uint16_t m487EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
767  uint8_t regAddr)
768 {
769  uint16_t data;
770  uint32_t temp;
771 
772  //Valid opcode?
773  if(opcode == SMI_OPCODE_READ)
774  {
775  //Set up a read operation
776  temp = EMAC_MIIMCTL_MDCON_Msk | EMAC_MIIMCTL_BUSY_Msk;
777  //PHY address
778  temp |= (phyAddr << EMAC_MIIMCTL_PHYADDR_Pos) & EMAC_MIIMCTL_PHYADDR_Msk;
779  //Register address
780  temp |= (regAddr << EMAC_MIIMCTL_PHYREG_Pos) & EMAC_MIIMCTL_PHYREG_Msk;
781 
782  //Start a read operation
783  EMAC->MIIMCTL = temp;
784  //Wait for the read to complete
785  while((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) != 0)
786  {
787  }
788 
789  //Get register value
790  data = EMAC->MIIMDAT & EMAC_MIIMDAT_DATA_Msk;
791  }
792  else
793  {
794  //The MAC peripheral only supports standard Clause 22 opcodes
795  data = 0;
796  }
797 
798  //Return the value of the PHY register
799  return data;
800 }
#define txDmaDesc
#define rxBuffer
#define txBuffer
#define rxDmaDesc
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint8_t opcode
Definition: dns_common.h:188
error_t
Error codes.
Definition: error.h:43
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
error_t m487EthInit(NetInterface *interface)
M487 Ethernet MAC initialization.
error_t m487EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void EMAC_RX_IRQHandler(void)
Ethernet MAC receive interrupt.
error_t m487EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
__weak_func void m487EthInitGpio(NetInterface *interface)
GPIO configuration.
void EMAC_TX_IRQHandler(void)
Ethernet MAC transmit interrupt.
uint16_t m487EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t m487EthReceivePacket(NetInterface *interface)
Receive a packet.
const NicDriver m487EthDriver
M487 Ethernet MAC driver.
void m487EthDisableIrq(NetInterface *interface)
Disable interrupts.
void m487EthTick(NetInterface *interface)
M487 Ethernet MAC timer handler.
void m487EthEventHandler(NetInterface *interface)
M487 Ethernet MAC event handler.
void m487EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t m487EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
void m487EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
void m487EthEnableIrq(NetInterface *interface)
Enable interrupts.
Nuvoton M487 Ethernet MAC driver.
#define EMAC_RXDES0_OWNER
#define M487_ETH_TX_BUFFER_SIZE
#define EMAC_TXDES2_TBC
#define M487_ETH_TX_BUFFER_COUNT
#define EMAC_TXDES0_CRCAPP
#define M487_ETH_RX_BUFFER_COUNT
#define M487_ETH_IRQ_GROUP_PRIORITY
#define EMAC_RXDES0_RXGDIF
#define EMAC_TXDES0_OWNER
#define EMAC_TXDES0_PADEN
#define M487_ETH_IRQ_SUB_PRIORITY
#define EMAC_TXDES0_INTEN
#define M487_ETH_RX_BUFFER_SIZE
#define EMAC_RXDES0_RBC
#define M487_ETH_IRQ_PRIORITY_GROUPING
uint16_t regAddr
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
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:674
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
#define SMI_OPCODE_WRITE
Definition: nic.h:66
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define SMI_OPCODE_READ
Definition: nic.h:67
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define osEnterIsr()
#define osExitIsr(flag)
RX DMA descriptor.
TX DMA descriptor.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
NIC driver.
Definition: nic.h:283
uint8_t length
Definition: tcp.h:368