nuc472_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file nuc472_eth_driver.c
3  * @brief Nuvoton NUC472 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2021 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.0.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "nuc472_442.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 NUC472 Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief NUC472 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 NUC472 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(100));
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  nuc472EthInitGpio(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 = NUC472_ETH_RX_BUFFER_SIZE;
179 
180  //Initialize DMA descriptor lists
181  nuc472EthInitDmaDesc(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(NUC472_ETH_IRQ_PRIORITY_GROUPING);
189 
190  //Configure EMAC transmit interrupt priority
191  NVIC_SetPriority(EMAC_TX_IRQn, NVIC_EncodePriority(NUC472_ETH_IRQ_PRIORITY_GROUPING,
193 
194  //Configure EMAC receive interrupt priority
195  NVIC_SetPriority(EMAC_RX_IRQn, NVIC_EncodePriority(NUC472_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 //NuTiny-SDK-NUC472 or NuMaker-PFM-NUC472 evaluation board?
210 #if defined(USE_NUTINY_SDK_NUC472) || defined(USE_NUMAKER_PFM_NUC472)
211 
212 /**
213  * @brief GPIO configuration
214  * @param[in] interface Underlying network interface
215  **/
216 
217 void nuc472EthInitGpio(NetInterface *interface)
218 {
219  uint32_t temp;
220 
221  //Select RMII interface mode
222  EMAC->CTL |= EMAC_CTL_RMIIEN_Msk | EMAC_CTL_RMIIRXCTL_Msk;
223 
224  //Configure EMAC_MII_MDC (PB.14) and EMAC_MII_MDIO (PB.15)
225  temp = SYS->GPB_MFPH;
226  temp = (temp & ~SYS_GPB_MFPH_PB14MFP_Msk) | SYS_GPB_MFPH_PB14MFP_EMAC_MII_MDC;
227  temp = (temp & ~SYS_GPB_MFPH_PB15MFP_Msk) | SYS_GPB_MFPH_PB15MFP_EMAC_MII_MDIO;
228  SYS->GPB_MFPH = temp;
229 
230  //Configure EMAC_REFCLK (PC.0), EMAC_MII_RXERR (PC.1), EMAC_MII_RXDV (PC.2),
231  //EMAC_MII_RXD1 (PC.3), EMAC_MII_RXD0 (PC.4), EMAC_MII_TXD0 (PC.6) and
232  //EMAC_MII_TXD1 (PC.7)
233  temp = SYS->GPC_MFPL;
234  temp = (temp & ~SYS_GPC_MFPL_PC0MFP_Msk) | SYS_GPC_MFPL_PC0MFP_EMAC_REFCLK;
235  temp = (temp & ~SYS_GPC_MFPL_PC1MFP_Msk) | SYS_GPC_MFPL_PC1MFP_EMAC_MII_RXERR;
236  temp = (temp & ~SYS_GPC_MFPL_PC2MFP_Msk) | SYS_GPC_MFPL_PC2MFP_EMAC_MII_RXDV;
237  temp = (temp & ~SYS_GPC_MFPL_PC3MFP_Msk) | SYS_GPC_MFPL_PC3MFP_EMAC_MII_RXD1;
238  temp = (temp & ~SYS_GPC_MFPL_PC4MFP_Msk) | SYS_GPC_MFPL_PC4MFP_EMAC_MII_RXD0;
239  temp = (temp & ~SYS_GPC_MFPL_PC6MFP_Msk) | SYS_GPC_MFPL_PC6MFP_EMAC_MII_TXD0;
240  temp = (temp & ~SYS_GPC_MFPL_PC7MFP_Msk) | SYS_GPC_MFPL_PC7MFP_EMAC_MII_TXD1;
241  SYS->GPC_MFPL = temp;
242 
243  //Configure EMAC_MII_TXEN (PC.8)
244  temp = SYS->GPC_MFPH;
245  temp = (temp & ~SYS_GPC_MFPH_PC8MFP_Msk) | SYS_GPC_MFPH_PC8MFP_EMAC_MII_TXEN;
246  SYS->GPC_MFPH = temp;
247 
248  //Enable high slew rate on RMII output pins
249  PC->SLEWCTL |= GPIO_SLEWCTL_HSREN6_Msk | GPIO_SLEWCTL_HSREN7_Msk |
250  GPIO_SLEWCTL_HSREN8_Msk;
251 }
252 
253 #endif
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 < NUC472_ETH_TX_BUFFER_COUNT; i++)
267  {
268  //The descriptor is initially owned by the CPU
269  txDmaDesc[i].txdes0 = 0;
270  //Transmit buffer address
271  txDmaDesc[i].txdes1 = (uint32_t) txBuffer[i];
272  //Transmit frame status
273  txDmaDesc[i].txdes2 = 0;
274  //Next descriptor address
275  txDmaDesc[i].txdes3 = (uint32_t) &txDmaDesc[i + 1];
276  }
277 
278  //The last descriptor is chained to the first entry
279  txDmaDesc[i - 1].txdes3 = (uint32_t) &txDmaDesc[0];
280  //Initialize TX descriptor index
281  txIndex = 0;
282 
283  //Initialize RX DMA descriptor list
284  for(i = 0; i < NUC472_ETH_RX_BUFFER_COUNT; i++)
285  {
286  //The descriptor is initially owned by the DMA
287  rxDmaDesc[i].rxdes0 = EMAC_RXDES0_OWNER;
288  //Receive buffer address
289  rxDmaDesc[i].rxdes1 = (uint32_t) rxBuffer[i];
290  //Reserved field
291  rxDmaDesc[i].rxdes2 = 0;
292  //Next descriptor address
293  rxDmaDesc[i].rxdes3 = (uint32_t) &rxDmaDesc[i + 1];
294  }
295 
296  //The last descriptor is chained to the first entry
297  rxDmaDesc[i - 1].rxdes3 = (uint32_t) &rxDmaDesc[0];
298  //Initialize RX descriptor index
299  rxIndex = 0;
300 
301  //Start address of the TX descriptor list
302  EMAC->TXDSA = (uint32_t) txDmaDesc;
303  //Start address of the RX descriptor list
304  EMAC->RXDSA = (uint32_t) rxDmaDesc;
305 }
306 
307 
308 /**
309  * @brief NUC472 Ethernet MAC timer handler
310  *
311  * This routine is periodically called by the TCP/IP stack to handle periodic
312  * operations such as polling the link state
313  *
314  * @param[in] interface Underlying network interface
315  **/
316 
317 void nuc472EthTick(NetInterface *interface)
318 {
319  //Valid Ethernet PHY or switch driver?
320  if(interface->phyDriver != NULL)
321  {
322  //Handle periodic operations
323  interface->phyDriver->tick(interface);
324  }
325  else if(interface->switchDriver != NULL)
326  {
327  //Handle periodic operations
328  interface->switchDriver->tick(interface);
329  }
330  else
331  {
332  //Just for sanity
333  }
334 }
335 
336 
337 /**
338  * @brief Enable interrupts
339  * @param[in] interface Underlying network interface
340  **/
341 
343 {
344  //Enable Ethernet MAC interrupts
345  NVIC_EnableIRQ(EMAC_TX_IRQn);
346  NVIC_EnableIRQ(EMAC_RX_IRQn);
347 
348 
349  //Valid Ethernet PHY or switch driver?
350  if(interface->phyDriver != NULL)
351  {
352  //Enable Ethernet PHY interrupts
353  interface->phyDriver->enableIrq(interface);
354  }
355  else if(interface->switchDriver != NULL)
356  {
357  //Enable Ethernet switch interrupts
358  interface->switchDriver->enableIrq(interface);
359  }
360  else
361  {
362  //Just for sanity
363  }
364 }
365 
366 
367 /**
368  * @brief Disable interrupts
369  * @param[in] interface Underlying network interface
370  **/
371 
373 {
374  //Disable Ethernet MAC interrupts
375  NVIC_DisableIRQ(EMAC_TX_IRQn);
376  NVIC_DisableIRQ(EMAC_RX_IRQn);
377 
378 
379  //Valid Ethernet PHY or switch driver?
380  if(interface->phyDriver != NULL)
381  {
382  //Disable Ethernet PHY interrupts
383  interface->phyDriver->disableIrq(interface);
384  }
385  else if(interface->switchDriver != NULL)
386  {
387  //Disable Ethernet switch interrupts
388  interface->switchDriver->disableIrq(interface);
389  }
390  else
391  {
392  //Just for sanity
393  }
394 }
395 
396 
397 /**
398  * @brief Ethernet MAC transmit interrupt
399  **/
400 
402 {
403  bool_t flag;
404 
405  //Interrupt service routine prologue
406  osEnterIsr();
407 
408  //This flag will be set if a higher priority task must be woken
409  flag = FALSE;
410 
411  //Packet transmitted?
412  if((EMAC->INTSTS & EMAC_INTSTS_TXCPIF_Msk) != 0)
413  {
414  //Clear TXCPIF interrupt flag
415  EMAC->INTSTS = EMAC_INTSTS_TXCPIF_Msk;
416 
417  //Check whether the TX buffer is available for writing
418  if((txDmaDesc[txIndex].txdes0 & EMAC_TXDES0_OWNER) == 0)
419  {
420  //Notify the TCP/IP stack that the transmitter is ready to send
421  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
422  }
423  }
424 
425  //Interrupt service routine epilogue
426  osExitIsr(flag);
427 }
428 
429 
430 /**
431  * @brief Ethernet MAC receive interrupt
432  **/
433 
435 {
436  bool_t flag;
437 
438  //Interrupt service routine prologue
439  osEnterIsr();
440 
441  //This flag will be set if a higher priority task must be woken
442  flag = FALSE;
443 
444  //Packet received?
445  if((EMAC->INTSTS & EMAC_INTSTS_RXGDIF_Msk) != 0)
446  {
447  //Disable receive interrupts
448  EMAC->INTEN &= ~EMAC_INTEN_RXIEN_Msk;
449 
450  //Set event flag
451  nicDriverInterface->nicEvent = TRUE;
452  //Notify the TCP/IP stack of the event
453  flag |= osSetEventFromIsr(&netEvent);
454  }
455 
456  //Interrupt service routine epilogue
457  osExitIsr(flag);
458 }
459 
460 
461 /**
462  * @brief NUC472 Ethernet MAC event handler
463  * @param[in] interface Underlying network interface
464  **/
465 
467 {
468  error_t error;
469 
470  //Packet received?
471  if((EMAC->INTSTS & EMAC_INTSTS_RXGDIF_Msk) != 0)
472  {
473  //Clear interrupt flag
474  EMAC->INTSTS = EMAC_INTSTS_RXGDIF_Msk;
475 
476  //Process all pending packets
477  do
478  {
479  //Read incoming packet
480  error = nuc472EthReceivePacket(interface);
481 
482  //No more data in the receive buffer?
483  } while(error != ERROR_BUFFER_EMPTY);
484  }
485 
486  //Re-enable DMA interrupts
487  EMAC->INTEN = EMAC_INTEN_TXCPIEN_Msk | EMAC_INTEN_TXIEN_Msk |
488  EMAC_INTEN_RXGDIEN_Msk | EMAC_INTEN_RXIEN_Msk;
489 }
490 
491 
492 /**
493  * @brief Send a packet
494  * @param[in] interface Underlying network interface
495  * @param[in] buffer Multi-part buffer containing the data to send
496  * @param[in] offset Offset to the first data byte
497  * @param[in] ancillary Additional options passed to the stack along with
498  * the packet
499  * @return Error code
500  **/
501 
503  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
504 {
505  size_t length;
506  uint_t txNextIndex;
507 
508  //Retrieve the length of the packet
509  length = netBufferGetLength(buffer) - offset;
510 
511  //Check the frame length
513  {
514  //The transmitter can accept another packet
515  osSetEvent(&interface->nicTxEvent);
516  //Report an error
517  return ERROR_INVALID_LENGTH;
518  }
519 
520  //Make sure the current buffer is available for writing
521  if((txDmaDesc[txIndex].txdes0 & EMAC_TXDES0_OWNER) != 0)
522  {
523  return ERROR_FAILURE;
524  }
525 
526  //Copy user data to the transmit buffer
527  netBufferRead((uint8_t *) txBuffer[txIndex], buffer, offset, length);
528 
529  //Calculate the index of the next descriptor
530  txNextIndex = txIndex + 1;
531 
532  //Wrap around if necessary
533  if(txNextIndex >= NUC472_ETH_TX_BUFFER_COUNT)
534  {
535  txNextIndex = 0;
536  }
537 
538  //Set the start address of the buffer
539  txDmaDesc[txIndex].txdes1 = (uint32_t) txBuffer[txIndex];
540  //Write the number of bytes to send
541  txDmaDesc[txIndex].txdes2 = length & EMAC_TXDES2_TBC;
542  //Set the address of the next descriptor
543  txDmaDesc[txIndex].txdes3 = (uint32_t) &txDmaDesc[txNextIndex];
544 
545  //Give the ownership of the descriptor to the DMA
546  txDmaDesc[txIndex].txdes0 = EMAC_TXDES0_OWNER | EMAC_TXDES0_INTEN |
548 
549  //Instruct the DMA to poll the transmit descriptor list
550  EMAC->TXST = 0;
551 
552  //Point to the next register
553  txIndex = txNextIndex;
554 
555  //Check whether the next buffer is available for writing
556  if((txDmaDesc[txIndex].txdes0 & EMAC_TXDES0_OWNER) == 0)
557  {
558  //The transmitter can accept another packet
559  osSetEvent(&interface->nicTxEvent);
560  }
561 
562  //Data successfully written
563  return NO_ERROR;
564 }
565 
566 
567 /**
568  * @brief Receive a packet
569  * @param[in] interface Underlying network interface
570  * @return Error code
571  **/
572 
574 {
575  error_t error;
576  size_t n;
577  uint_t rxNextIndex;
578  NetRxAncillary ancillary;
579 
580  //Current buffer available for reading?
581  if((rxDmaDesc[rxIndex].rxdes0 & EMAC_RXDES0_OWNER) == 0)
582  {
583  //Valid frame received?
584  if((rxDmaDesc[rxIndex].rxdes0 & EMAC_RXDES0_RXGDIF) != 0)
585  {
586  //Retrieve the length of the frame
587  n = rxDmaDesc[rxIndex].rxdes0 & EMAC_RXDES0_RBC;
588  //Limit the number of data to read
590 
591  //Additional options can be passed to the stack along with the packet
592  ancillary = NET_DEFAULT_RX_ANCILLARY;
593 
594  //Pass the packet to the upper layer
595  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
596 
597  //Valid packet received
598  error = NO_ERROR;
599  }
600  else
601  {
602  //The packet is not valid
603  error = ERROR_INVALID_PACKET;
604  }
605 
606  //Calculate the index of the next descriptor
607  rxNextIndex = rxIndex + 1;
608 
609  //Wrap around if necessary
610  if(rxNextIndex >= NUC472_ETH_RX_BUFFER_COUNT)
611  {
612  rxNextIndex = 0;
613  }
614 
615  //Set the start address of the buffer
616  rxDmaDesc[rxIndex].rxdes1 = (uint32_t) rxBuffer[rxIndex];
617  //Set the address of the next descriptor
618  rxDmaDesc[rxIndex].rxdes3 = (uint32_t) &rxDmaDesc[rxNextIndex];
619  //Give the ownership of the descriptor back to the DMA
620  rxDmaDesc[rxIndex].rxdes0 = EMAC_RXDES0_OWNER;
621 
622  //Point to the next register
623  rxIndex = rxNextIndex;
624  }
625  else
626  {
627  //No more data in the receive buffer
628  error = ERROR_BUFFER_EMPTY;
629  }
630 
631  //Instruct the DMA to poll the receive descriptor list
632  EMAC->RXST = 0;
633 
634  //Return status code
635  return error;
636 }
637 
638 
639 /**
640  * @brief Configure MAC address filtering
641  * @param[in] interface Underlying network interface
642  * @return Error code
643  **/
644 
646 {
647  uint_t i;
648  bool_t acceptMulticast;
649 
650  //Debug message
651  TRACE_DEBUG("Updating MAC filter...\r\n");
652 
653  //This flag will be set if multicast addresses should be accepted
654  acceptMulticast = FALSE;
655 
656  //The MAC address filter contains the list of MAC addresses to accept
657  //when receiving an Ethernet frame
658  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
659  {
660  //Valid entry?
661  if(interface->macAddrFilter[i].refCount > 0)
662  {
663  //Accept multicast addresses
664  acceptMulticast = TRUE;
665  //We are done
666  break;
667  }
668  }
669 
670  //Enable the reception of multicast frames if necessary
671  if(acceptMulticast)
672  {
673  EMAC->CAMCTL |= EMAC_CAMCTL_AMP_Msk;
674  }
675  else
676  {
677  EMAC->CAMCTL &= ~EMAC_CAMCTL_AMP_Msk;
678  }
679 
680  //Successful processing
681  return NO_ERROR;
682 }
683 
684 
685 /**
686  * @brief Adjust MAC configuration parameters for proper operation
687  * @param[in] interface Underlying network interface
688  * @return Error code
689  **/
690 
692 {
693  uint32_t config;
694 
695  //Read MAC control register
696  config = EMAC->CTL;
697 
698  //10BASE-T or 100BASE-TX operation mode?
699  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
700  {
701  config |= EMAC_CTL_OPMODE_Msk;
702  }
703  else
704  {
705  config &= ~EMAC_CTL_OPMODE_Msk;
706  }
707 
708  //Half-duplex or full-duplex mode?
709  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
710  {
711  config |= EMAC_CTL_FUDUP_Msk;
712  }
713  else
714  {
715  config &= ~EMAC_CTL_FUDUP_Msk;
716  }
717 
718  //Update MAC control register
719  EMAC->CTL = config;
720 
721  //Successful processing
722  return NO_ERROR;
723 }
724 
725 
726 /**
727  * @brief Write PHY register
728  * @param[in] opcode Access type (2 bits)
729  * @param[in] phyAddr PHY address (5 bits)
730  * @param[in] regAddr Register address (5 bits)
731  * @param[in] data Register value
732  **/
733 
734 void nuc472EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
735  uint8_t regAddr, uint16_t data)
736 {
737  uint32_t temp;
738 
739  //Valid opcode?
740  if(opcode == SMI_OPCODE_WRITE)
741  {
742  //Set up a write operation
743  temp = EMAC_MIIMCTL_MDCON_Msk | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk;
744  //PHY address
745  temp |= (phyAddr << EMAC_MIIMCTL_PHYADDR_Pos) & EMAC_MIIMCTL_PHYADDR_Msk;
746  //Register address
747  temp |= (regAddr << EMAC_MIIMCTL_PHYREG_Pos) & EMAC_MIIMCTL_PHYREG_Msk;
748 
749  //Data to be written in the PHY register
750  EMAC->MIIMDAT = data & EMAC_MIIMDAT_DATA_Msk;
751 
752  //Start a write operation
753  EMAC->MIIMCTL = temp;
754  //Wait for the write to complete
755  while((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) != 0)
756  {
757  }
758  }
759  else
760  {
761  //The MAC peripheral only supports standard Clause 22 opcodes
762  }
763 }
764 
765 
766 /**
767  * @brief Read PHY register
768  * @param[in] opcode Access type (2 bits)
769  * @param[in] phyAddr PHY address (5 bits)
770  * @param[in] regAddr Register address (5 bits)
771  * @return Register value
772  **/
773 
774 uint16_t nuc472EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
775  uint8_t regAddr)
776 {
777  uint16_t data;
778  uint32_t temp;
779 
780  //Valid opcode?
781  if(opcode == SMI_OPCODE_READ)
782  {
783  //Set up a read operation
784  temp = EMAC_MIIMCTL_MDCON_Msk | EMAC_MIIMCTL_BUSY_Msk;
785  //PHY address
786  temp |= (phyAddr << EMAC_MIIMCTL_PHYADDR_Pos) & EMAC_MIIMCTL_PHYADDR_Msk;
787  //Register address
788  temp |= (regAddr << EMAC_MIIMCTL_PHYREG_Pos) & EMAC_MIIMCTL_PHYREG_Msk;
789 
790  //Start a read operation
791  EMAC->MIIMCTL = temp;
792  //Wait for the read to complete
793  while((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) != 0)
794  {
795  }
796 
797  //Get register value
798  data = EMAC->MIIMDAT & EMAC_MIIMDAT_DATA_Msk;
799  }
800  else
801  {
802  //The MAC peripheral only supports standard Clause 22 opcodes
803  data = 0;
804  }
805 
806  //Return the value of the PHY register
807  return data;
808 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
const NicDriver nuc472EthDriver
NUC472 Ethernet MAC driver.
uint8_t length
Definition: coap_common.h:191
#define EMAC_RXDES0_RBC
TX DMA descriptor.
uint8_t opcode
Definition: dns_common.h:172
error_t nuc472EthInit(NetInterface *interface)
NUC472 Ethernet MAC initialization.
int bool_t
Definition: compiler_port.h:49
void nuc472EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define netEvent
Definition: net_legacy.h:267
#define EMAC_TXDES0_INTEN
Nuvoton NUC472 Ethernet MAC driver.
uint8_t data[]
Definition: ethernet.h:210
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:122
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
#define EMAC_TXDES0_OWNER
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:88
#define TRUE
Definition: os_port.h:50
void nuc472EthTick(NetInterface *interface)
NUC472 Ethernet MAC timer handler.
RX DMA descriptor.
#define NUC472_ETH_RX_BUFFER_SIZE
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 osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:65
error_t nuc472EthReceivePacket(NetInterface *interface)
Receive a packet.
void nuc472EthDisableIrq(NetInterface *interface)
Disable interrupts.
error_t nuc472EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define NUC472_ETH_IRQ_GROUP_PRIORITY
#define FALSE
Definition: os_port.h:46
#define NUC472_ETH_TX_BUFFER_SIZE
error_t
Error codes.
Definition: error.h:43
void nuc472EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:97
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
uint16_t nuc472EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:139
#define NetInterface
Definition: net.h:36
#define EMAC_RXDES0_RXGDIF
@ ERROR_INVALID_LENGTH
Definition: error.h:110
#define NUC472_ETH_TX_BUFFER_COUNT
void nuc472EthEventHandler(NetInterface *interface)
NUC472 Ethernet MAC event handler.
@ ERROR_BUFFER_EMPTY
Definition: error.h:140
#define NUC472_ETH_IRQ_SUB_PRIORITY
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:66
error_t nuc472EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define TRACE_INFO(...)
Definition: debug.h:95
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:62
#define EMAC_TXDES2_TBC
#define rxBuffer
#define EMAC_TXDES0_CRCAPP
#define EMAC_RXDES0_OWNER
#define TRACE_DEBUG(...)
Definition: debug.h:107
error_t nuc472EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
uint16_t regAddr
void nuc472EthInitGpio(NetInterface *interface)
#define ETH_MTU
Definition: ethernet.h:105
uint8_t n
#define NUC472_ETH_RX_BUFFER_COUNT
#define osEnterIsr()
void EMAC_TX_IRQHandler(void)
Ethernet MAC transmit interrupt.
#define NUC472_ETH_IRQ_PRIORITY_GROUPING
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define EMAC_TXDES0_PADEN
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:109
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
NIC driver.
Definition: nic.h:280
void EMAC_RX_IRQHandler(void)
Ethernet MAC receive interrupt.
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:82
void nuc472EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.