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