rx65n_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file rx65n_eth_driver.c
3  * @brief Renesas RX65N Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <iorx65n.h>
36 #include <intrinsics.h>
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWRX compiler?
45 #if defined(__ICCRX__)
46 
47 //Transmit buffer
48 #pragma data_alignment = 32
50 //Receive buffer
51 #pragma data_alignment = 32
53 //Transmit DMA descriptors
54 #pragma data_alignment = 32
56 //Receive DMA descriptors
57 #pragma data_alignment = 32
59 
60 //GCC compiler?
61 #else
62 
63 //Transmit buffer
65  __attribute__((aligned(32)));
66 //Receive buffer
68  __attribute__((aligned(32)));
69 //Transmit DMA descriptors
71  __attribute__((aligned(32)));
72 //Receive DMA descriptors
74  __attribute__((aligned(32)));
75 
76 #endif
77 
78 //Current transmit descriptor
79 static uint_t txIndex;
80 //Current receive descriptor
81 static uint_t rxIndex;
82 
83 
84 /**
85  * @brief RX65N Ethernet MAC driver
86  **/
87 
89 {
91  ETH_MTU,
102  TRUE,
103  TRUE,
104  TRUE,
105  TRUE
106 };
107 
108 
109 /**
110  * @brief RX65N Ethernet MAC initialization
111  * @param[in] interface Underlying network interface
112  * @return Error code
113  **/
114 
116 {
117  error_t error;
118 
119  //Debug message
120  TRACE_INFO("Initializing RX65N Ethernet MAC...\r\n");
121 
122  //Save underlying network interface
123  nicDriverInterface = interface;
124 
125  //Disable protection
126  SYSTEM.PRCR.WORD = 0xA50B;
127  //Cancel EDMAC module stop state
128  MSTP(EDMAC0) = 0;
129  //Enable protection
130  SYSTEM.PRCR.WORD = 0xA500;
131 
132  //GPIO configuration
133  rx65nEthInitGpio(interface);
134 
135  //Reset EDMAC module
136  EDMAC0.EDMR.BIT.SWR = 1;
137  //Wait for the reset to complete
138  sleep(10);
139 
140  //Valid Ethernet PHY or switch driver?
141  if(interface->phyDriver != NULL)
142  {
143  //Ethernet PHY initialization
144  error = interface->phyDriver->init(interface);
145  }
146  else if(interface->switchDriver != NULL)
147  {
148  //Ethernet switch initialization
149  error = interface->switchDriver->init(interface);
150  }
151  else
152  {
153  //The interface is not properly configured
154  error = ERROR_FAILURE;
155  }
156 
157  //Any error to report?
158  if(error)
159  {
160  return error;
161  }
162 
163  //Initialize DMA descriptor lists
164  rx65nEthInitDmaDesc(interface);
165 
166  //Maximum frame length that can be accepted
167  ETHERC0.RFLR.LONG = RX65N_ETH_RX_BUFFER_SIZE;
168  //Set default inter packet gap (96-bit time)
169  ETHERC0.IPGR.LONG = 0x14;
170 
171  //Set the upper 32 bits of the MAC address
172  ETHERC0.MAHR = (interface->macAddr.b[0] << 24) | (interface->macAddr.b[1] << 16) |
173  (interface->macAddr.b[2] << 8) | interface->macAddr.b[3];
174 
175  //Set the lower 16 bits of the MAC address
176  ETHERC0.MALR.BIT.MA = (interface->macAddr.b[4] << 8) | interface->macAddr.b[5];
177 
178  //Set descriptor length (16 bytes)
179  EDMAC0.EDMR.BIT.DL = 0;
180 
181 #ifdef _CPU_BIG_ENDIAN
182  //Select big endian mode
183  EDMAC0.EDMR.BIT.DE = 0;
184 #else
185  //Select little endian mode
186  EDMAC0.EDMR.BIT.DE = 1;
187 #endif
188 
189  //Use store and forward mode
190  EDMAC0.TFTR.BIT.TFT = 0;
191 
192  //Set transmit FIFO size (2048 bytes)
193  EDMAC0.FDR.BIT.TFD = 7;
194  //Set receive FIFO size (2048 bytes)
195  EDMAC0.FDR.BIT.RFD = 7;
196 
197  //Enable continuous reception of multiple frames
198  EDMAC0.RMCR.BIT.RNR = 1;
199 
200  //Accept transmit interrupt notifications
201  EDMAC0.TRIMD.BIT.TIM = 0;
202  EDMAC0.TRIMD.BIT.TIS = 1;
203 
204  //Disable all EDMAC interrupts
205  EDMAC0.EESIPR.LONG = 0;
206  //Enable only the desired EDMAC interrupts
207  EDMAC0.EESIPR.BIT.TWBIP = 1;
208  EDMAC0.EESIPR.BIT.FRIP = 1;
209 
210  //Enable EDMAC interrupt requests
211  ICU.GENAL1.BIT.EN_EDMAC0_EINT0 = 1;
212  //Configure EDMAC interrupt priority
213  IPR(ICU, GROUPAL1) = RX65N_ETH_IRQ_PRIORITY;
214 
215  //Enable transmission and reception
216  ETHERC0.ECMR.BIT.TE = 1;
217  ETHERC0.ECMR.BIT.RE = 1;
218 
219  //Instruct the DMA to poll the receive descriptor list
220  EDMAC0.EDRRR.BIT.RR = 1;
221 
222  //Accept any packets from the upper layer
223  osSetEvent(&interface->nicTxEvent);
224 
225  //Successful initialization
226  return NO_ERROR;
227 }
228 
229 
230 /**
231  * @brief GPIO configuration
232  * @param[in] interface Underlying network interface
233  **/
234 
235 __weak_func void rx65nEthInitGpio(NetInterface *interface)
236 {
237 //RSK-RX65N or RSK-RX65N-2M evaluation board?
238 #if defined(USE_RSK_RX65N) || defined(USE_RSK_RX65N_2M)
239  //Unlock MPC registers
240  MPC.PWPR.BIT.B0WI = 0;
241  MPC.PWPR.BIT.PFSWE = 1;
242 
243  //Select MII interface mode
244  MPC.PFENET.BIT.PHYMODE0 = 1;
245 
246  //Configure ET_MDIO (P71)
247  PORT7.PMR.BIT.B1 = 1;
248  MPC.P71PFS.BYTE = 0x11;
249 
250  //Configure ET_MDC (P72)
251  PORT7.PMR.BIT.B2 = 1;
252  MPC.P72PFS.BYTE = 0x11;
253 
254  //Configure ET_ERXD1 (P74)
255  PORT7.PMR.BIT.B4 = 1;
256  MPC.P74PFS.BYTE = 0x11;
257 
258  //Configure ET_ERXD0 P75)
259  PORT7.PMR.BIT.B5 = 1;
260  MPC.P75PFS.BYTE = 0x11;
261 
262  //Configure ET_RX_CLK (P76)
263  PORT7.PMR.BIT.B6 = 1;
264  MPC.P76PFS.BYTE = 0x11;
265 
266  //Configure ET_RX_ER (P77)
267  PORT7.PMR.BIT.B7 = 1;
268  MPC.P77PFS.BYTE = 0x11;
269 
270  //Configure ET_TX_EN (P80)
271  PORT8.PMR.BIT.B0 = 1;
272  MPC.P80PFS.BYTE = 0x11;
273 
274  //Configure ET_ETXD0 (P81)
275  PORT8.PMR.BIT.B1 = 1;
276  MPC.P81PFS.BYTE = 0x11;
277 
278  //Configure ET_ETXD1 (P82)
279  PORT8.PMR.BIT.B2 = 1;
280  MPC.P82PFS.BYTE = 0x11;
281 
282  //Configure ET_CRS (P83)
283  PORT8.PMR.BIT.B3 = 1;
284  MPC.P83PFS.BYTE = 0x11;
285 
286  //Configure ET_ERXD3 (PC0)
287  PORTC.PMR.BIT.B0 = 1;
288  MPC.PC0PFS.BYTE = 0x11;
289 
290  //Configure ET_ERXD2 (PC1)
291  PORTC.PMR.BIT.B1 = 1;
292  MPC.PC1PFS.BYTE = 0x11;
293 
294  //Configure ET_RX_DV (PC2)
295  PORTC.PMR.BIT.B2 = 1;
296  MPC.PC2PFS.BYTE = 0x11;
297 
298  //Configure ET_TX_ER (PC3)
299  PORTC.PMR.BIT.B3 = 1;
300  MPC.PC3PFS.BYTE = 0x11;
301 
302  //Configure ET_TX_CLK (PC4)
303  PORTC.PMR.BIT.B4 = 1;
304  MPC.PC4PFS.BYTE = 0x11;
305 
306  //Configure ET_ETXD2 (PC5)
307  PORTC.PMR.BIT.B5 = 1;
308  MPC.PC5PFS.BYTE = 0x11;
309 
310  //Configure ET_ETXD3 (PC6)
311  PORTC.PMR.BIT.B6 = 1;
312  MPC.PC6PFS.BYTE = 0x11;
313 
314  //Configure ET_COL (PC7)
315  PORTC.PMR.BIT.B7 = 1;
316  MPC.PC7PFS.BYTE = 0x11;
317 
318  //Lock MPC registers
319  MPC.PWPR.BIT.PFSWE = 0;
320  MPC.PWPR.BIT.B0WI = 0;
321 #endif
322 }
323 
324 
325 /**
326  * @brief Initialize DMA descriptor lists
327  * @param[in] interface Underlying network interface
328  **/
329 
331 {
332  uint_t i;
333 
334  //Initialize TX descriptors
335  for(i = 0; i < RX65N_ETH_TX_BUFFER_COUNT; i++)
336  {
337  //The descriptor is initially owned by the application
338  txDmaDesc[i].td0 = 0;
339  //Transmit buffer length
340  txDmaDesc[i].td1 = 0;
341  //Transmit buffer address
342  txDmaDesc[i].td2 = (uint32_t) txBuffer[i];
343  //Clear padding field
344  txDmaDesc[i].padding = 0;
345  }
346 
347  //Mark the last descriptor entry with the TDLE flag
348  txDmaDesc[i - 1].td0 |= EDMAC_TD0_TDLE;
349  //Initialize TX descriptor index
350  txIndex = 0;
351 
352  //Initialize RX descriptors
353  for(i = 0; i < RX65N_ETH_RX_BUFFER_COUNT; i++)
354  {
355  //The descriptor is initially owned by the DMA
356  rxDmaDesc[i].rd0 = EDMAC_RD0_RACT;
357  //Receive buffer length
359  //Receive buffer address
360  rxDmaDesc[i].rd2 = (uint32_t) rxBuffer[i];
361  //Clear padding field
362  rxDmaDesc[i].padding = 0;
363  }
364 
365  //Mark the last descriptor entry with the RDLE flag
366  rxDmaDesc[i - 1].rd0 |= EDMAC_RD0_RDLE;
367  //Initialize RX descriptor index
368  rxIndex = 0;
369 
370  //Start address of the TX descriptor list
371  EDMAC0.TDLAR = txDmaDesc;
372  //Start address of the RX descriptor list
373  EDMAC0.RDLAR = rxDmaDesc;
374 }
375 
376 
377 /**
378  * @brief RX65N Ethernet MAC timer handler
379  *
380  * This routine is periodically called by the TCP/IP stack to handle periodic
381  * operations such as polling the link state
382  *
383  * @param[in] interface Underlying network interface
384  **/
385 
386 void rx65nEthTick(NetInterface *interface)
387 {
388  //Valid Ethernet PHY or switch driver?
389  if(interface->phyDriver != NULL)
390  {
391  //Handle periodic operations
392  interface->phyDriver->tick(interface);
393  }
394  else if(interface->switchDriver != NULL)
395  {
396  //Handle periodic operations
397  interface->switchDriver->tick(interface);
398  }
399  else
400  {
401  //Just for sanity
402  }
403 }
404 
405 
406 /**
407  * @brief Enable interrupts
408  * @param[in] interface Underlying network interface
409  **/
410 
412 {
413  //Enable Ethernet MAC interrupts
414  IEN(ICU, GROUPAL1) = 1;
415 
416  //Valid Ethernet PHY or switch driver?
417  if(interface->phyDriver != NULL)
418  {
419  //Enable Ethernet PHY interrupts
420  interface->phyDriver->enableIrq(interface);
421  }
422  else if(interface->switchDriver != NULL)
423  {
424  //Enable Ethernet switch interrupts
425  interface->switchDriver->enableIrq(interface);
426  }
427  else
428  {
429  //Just for sanity
430  }
431 }
432 
433 
434 /**
435  * @brief Disable interrupts
436  * @param[in] interface Underlying network interface
437  **/
438 
440 {
441  //Disable Ethernet MAC interrupts
442  IEN(ICU, GROUPAL1) = 0;
443 
444  //Valid Ethernet PHY or switch driver?
445  if(interface->phyDriver != NULL)
446  {
447  //Disable Ethernet PHY interrupts
448  interface->phyDriver->disableIrq(interface);
449  }
450  else if(interface->switchDriver != NULL)
451  {
452  //Disable Ethernet switch interrupts
453  interface->switchDriver->disableIrq(interface);
454  }
455  else
456  {
457  //Just for sanity
458  }
459 }
460 
461 
462 /**
463  * @brief RX65N Ethernet MAC interrupt service routine
464  **/
465 
467 {
468  bool_t flag;
469  uint32_t status;
470 
471  //Allow nested interrupts
472  __enable_interrupt();
473 
474  //This flag will be set if a higher priority task must be woken
475  flag = FALSE;
476 
477  //Read interrupt status register
478  status = EDMAC0.EESR.LONG;
479 
480  //Packet transmitted?
481  if((status & EDMAC_EESR_TWB) != 0)
482  {
483  //Clear TWB interrupt flag
484  EDMAC0.EESR.LONG = EDMAC_EESR_TWB;
485 
486  //Check whether the TX buffer is available for writing
487  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) == 0)
488  {
489  //Notify the TCP/IP stack that the transmitter is ready to send
490  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
491  }
492  }
493 
494  //Packet received?
495  if((status & EDMAC_EESR_FR) != 0)
496  {
497  //Clear FR interrupt flag
498  EDMAC0.EESR.LONG = EDMAC_EESR_FR;
499 
500  //Set event flag
501  nicDriverInterface->nicEvent = TRUE;
502  //Notify the TCP/IP stack of the event
503  flag |= osSetEventFromIsr(&netEvent);
504  }
505 
506  //Interrupt service routine epilogue
507  osExitIsr(flag);
508 }
509 
510 
511 /**
512  * @brief RX65N Ethernet MAC event handler
513  * @param[in] interface Underlying network interface
514  **/
515 
517 {
518  error_t error;
519 
520  //Process all pending packets
521  do
522  {
523  //Read incoming packet
524  error = rx65nEthReceivePacket(interface);
525 
526  //No more data in the receive buffer?
527  } while(error != ERROR_BUFFER_EMPTY);
528 }
529 
530 
531 /**
532  * @brief Send a packet
533  * @param[in] interface Underlying network interface
534  * @param[in] buffer Multi-part buffer containing the data to send
535  * @param[in] offset Offset to the first data byte
536  * @param[in] ancillary Additional options passed to the stack along with
537  * the packet
538  * @return Error code
539  **/
540 
542  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
543 {
544  //Retrieve the length of the packet
545  size_t length = netBufferGetLength(buffer) - offset;
546 
547  //Check the frame length
549  {
550  //The transmitter can accept another packet
551  osSetEvent(&interface->nicTxEvent);
552  //Report an error
553  return ERROR_INVALID_LENGTH;
554  }
555 
556  //Make sure the current buffer is available for writing
557  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) != 0)
558  {
559  return ERROR_FAILURE;
560  }
561 
562  //Copy user data to the transmit buffer
563  netBufferRead(txBuffer[txIndex], buffer, offset, length);
564 
565  //Write the number of bytes to send
566  txDmaDesc[txIndex].td1 = (length << 16) & EDMAC_TD1_TBL;
567 
568  //Check current index
569  if(txIndex < (RX65N_ETH_TX_BUFFER_COUNT - 1))
570  {
571  //Give the ownership of the descriptor to the DMA engine
572  txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TFP_SOF |
574 
575  //Point to the next descriptor
576  txIndex++;
577  }
578  else
579  {
580  //Give the ownership of the descriptor to the DMA engine
581  txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TDLE |
583 
584  //Wrap around
585  txIndex = 0;
586  }
587 
588  //Instruct the DMA to poll the transmit descriptor list
589  EDMAC0.EDTRR.BIT.TR = 1;
590 
591  //Check whether the next buffer is available for writing
592  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) == 0)
593  {
594  //The transmitter can accept another packet
595  osSetEvent(&interface->nicTxEvent);
596  }
597 
598  //Successful write operation
599  return NO_ERROR;
600 }
601 
602 
603 /**
604  * @brief Receive a packet
605  * @param[in] interface Underlying network interface
606  * @return Error code
607  **/
608 
610 {
611  error_t error;
612  size_t n;
613  NetRxAncillary ancillary;
614 
615  //Current buffer available for reading?
616  if((rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RACT) == 0)
617  {
618  //SOF and EOF flags should be set
619  if((rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_SOF) != 0 &&
620  (rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_EOF) != 0)
621  {
622  //Make sure no error occurred
623  if((rxDmaDesc[rxIndex].rd0 & (EDMAC_RD0_RFS_MASK & ~EDMAC_RD0_RFS_RMAF)) == 0)
624  {
625  //Retrieve the length of the frame
626  n = rxDmaDesc[rxIndex].rd1 & EDMAC_RD1_RFL;
627  //Limit the number of data to read
629 
630  //Additional options can be passed to the stack along with the packet
631  ancillary = NET_DEFAULT_RX_ANCILLARY;
632 
633  //Pass the packet to the upper layer
634  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
635 
636  //Valid packet received
637  error = NO_ERROR;
638  }
639  else
640  {
641  //The received packet contains an error
642  error = ERROR_INVALID_PACKET;
643  }
644  }
645  else
646  {
647  //The packet is not valid
648  error = ERROR_INVALID_PACKET;
649  }
650 
651  //Check current index
652  if(rxIndex < (RX65N_ETH_RX_BUFFER_COUNT - 1))
653  {
654  //Give the ownership of the descriptor back to the DMA
655  rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT;
656  //Point to the next descriptor
657  rxIndex++;
658  }
659  else
660  {
661  //Give the ownership of the descriptor back to the DMA
662  rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT | EDMAC_RD0_RDLE;
663  //Wrap around
664  rxIndex = 0;
665  }
666 
667  //Instruct the DMA to poll the receive descriptor list
668  EDMAC0.EDRRR.BIT.RR = 1;
669  }
670  else
671  {
672  //No more data in the receive buffer
673  error = ERROR_BUFFER_EMPTY;
674  }
675 
676  //Return status code
677  return error;
678 }
679 
680 
681 /**
682  * @brief Configure MAC address filtering
683  * @param[in] interface Underlying network interface
684  * @return Error code
685  **/
686 
688 {
689  uint_t i;
690  bool_t acceptMulticast;
691 
692  //Debug message
693  TRACE_DEBUG("Updating MAC filter...\r\n");
694 
695  //Set the upper 32 bits of the MAC address
696  ETHERC0.MAHR = (interface->macAddr.b[0] << 24) | (interface->macAddr.b[1] << 16) |
697  (interface->macAddr.b[2] << 8) | interface->macAddr.b[3];
698 
699  //Set the lower 16 bits of the MAC address
700  ETHERC0.MALR.BIT.MA = (interface->macAddr.b[4] << 8) | interface->macAddr.b[5];
701 
702  //This flag will be set if multicast addresses should be accepted
703  acceptMulticast = FALSE;
704 
705  //The MAC address filter contains the list of MAC addresses to accept
706  //when receiving an Ethernet frame
707  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
708  {
709  //Valid entry?
710  if(interface->macAddrFilter[i].refCount > 0)
711  {
712  //Accept multicast addresses
713  acceptMulticast = TRUE;
714  //We are done
715  break;
716  }
717  }
718 
719  //Enable or disable the reception of multicast frames
720  if(acceptMulticast)
721  {
722  EDMAC0.EESR.BIT.RMAF = 1;
723  }
724  else
725  {
726  EDMAC0.EESR.BIT.RMAF = 0;
727  }
728 
729  //Successful processing
730  return NO_ERROR;
731 }
732 
733 
734 /**
735  * @brief Adjust MAC configuration parameters for proper operation
736  * @param[in] interface Underlying network interface
737  * @return Error code
738  **/
739 
741 {
742  //10BASE-T or 100BASE-TX operation mode?
743  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
744  {
745  ETHERC0.ECMR.BIT.RTM = 1;
746  }
747  else
748  {
749  ETHERC0.ECMR.BIT.RTM = 0;
750  }
751 
752  //Half-duplex or full-duplex mode?
753  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
754  {
755  ETHERC0.ECMR.BIT.DM = 1;
756  }
757  else
758  {
759  ETHERC0.ECMR.BIT.DM = 0;
760  }
761 
762  //Successful processing
763  return NO_ERROR;
764 }
765 
766 
767 /**
768  * @brief Write PHY register
769  * @param[in] opcode Access type (2 bits)
770  * @param[in] phyAddr PHY address (5 bits)
771  * @param[in] regAddr Register address (5 bits)
772  * @param[in] data Register value
773  **/
774 
775 void rx65nEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
776  uint8_t regAddr, uint16_t data)
777 {
778  //Synchronization pattern
780  //Start of frame
782  //Set up a write operation
784  //Write PHY address
785  rx65nEthWriteSmi(phyAddr, 5);
786  //Write register address
788  //Turnaround
790  //Write register value
791  rx65nEthWriteSmi(data, 16);
792  //Release MDIO
793  rx65nEthReadSmi(1);
794 }
795 
796 
797 /**
798  * @brief Read PHY register
799  * @param[in] opcode Access type (2 bits)
800  * @param[in] phyAddr PHY address (5 bits)
801  * @param[in] regAddr Register address (5 bits)
802  * @return Register value
803  **/
804 
805 uint16_t rx65nEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
806  uint8_t regAddr)
807 {
808  uint16_t data;
809 
810  //Synchronization pattern
812  //Start of frame
814  //Set up a read operation
816  //Write PHY address
817  rx65nEthWriteSmi(phyAddr, 5);
818  //Write register address
820  //Turnaround to avoid contention
821  rx65nEthReadSmi(1);
822  //Read register value
823  data = rx65nEthReadSmi(16);
824  //Force the PHY to release the MDIO pin
825  rx65nEthReadSmi(1);
826 
827  //Return PHY register contents
828  return data;
829 }
830 
831 
832 /**
833  * @brief SMI write operation
834  * @param[in] data Raw data to be written
835  * @param[in] length Number of bits to be written
836  **/
837 
839 {
840  //Skip the most significant bits since they are meaningless
841  data <<= 32 - length;
842 
843  //Configure MDIO as an output
844  ETHERC0.PIR.BIT.MMD = 1;
845 
846  //Write the specified number of bits
847  while(length--)
848  {
849  //Write MDIO
850  if((data & 0x80000000) != 0)
851  {
852  ETHERC0.PIR.BIT.MDO = 1;
853  }
854  else
855  {
856  ETHERC0.PIR.BIT.MDO = 0;
857  }
858 
859  //Assert MDC
860  usleep(1);
861  ETHERC0.PIR.BIT.MDC = 1;
862  //Deassert MDC
863  usleep(1);
864  ETHERC0.PIR.BIT.MDC = 0;
865 
866  //Rotate data
867  data <<= 1;
868  }
869 }
870 
871 
872 /**
873  * @brief SMI read operation
874  * @param[in] length Number of bits to be read
875  * @return Data resulting from the MDIO read operation
876  **/
877 
879 {
880  uint32_t data = 0;
881 
882  //Configure MDIO as an input
883  ETHERC0.PIR.BIT.MMD = 0;
884 
885  //Read the specified number of bits
886  while(length--)
887  {
888  //Rotate data
889  data <<= 1;
890 
891  //Assert MDC
892  ETHERC0.PIR.BIT.MDC = 1;
893  usleep(1);
894  //Deassert MDC
895  ETHERC0.PIR.BIT.MDC = 0;
896  usleep(1);
897 
898  //Check MDIO state
899  if(ETHERC0.PIR.BIT.MDI != 0)
900  {
901  data |= 0x01;
902  }
903  }
904 
905  //Return the received data
906  return data;
907 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define EDMAC_RD0_RFP_EOF
#define usleep(delay)
Definition: os_port.h:306
__weak_func void rx65nEthInitGpio(NetInterface *interface)
GPIO configuration.
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:61
#define netEvent
Definition: net_legacy.h:196
#define RX65N_ETH_TX_BUFFER_COUNT
#define EDMAC_EESR_TWB
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
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
const NicDriver rx65nEthDriver
RX65N Ethernet MAC driver.
void rx65nEthTick(NetInterface *interface)
RX65N Ethernet MAC timer handler.
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
#define sleep(delay)
Definition: os_port.h:310
#define EDMAC_RD0_RACT
#define SMI_TA
Definition: nic.h:68
Receive DMA descriptor.
#define SMI_START
Definition: nic.h:64
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 osExitIsr(flag)
void rx65nEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define EDMAC_TD0_TWBI
#define RX65N_ETH_IRQ_PRIORITY
#define EDMAC_RD1_RFL
void rx65nEthWriteSmi(uint32_t data, uint_t length)
SMI write operation.
#define EDMAC_RD0_RDLE
#define FALSE
Definition: os_port.h:46
void rx65nEthEnableIrq(NetInterface *interface)
Enable interrupts.
Renesas RX65N Ethernet MAC driver.
#define EDMAC_RD0_RFP_SOF
uint16_t rx65nEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t
Error codes.
Definition: error.h:43
#define EDMAC_RD1_RBL
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
void rx65nEthEventHandler(NetInterface *interface)
RX65N Ethernet MAC event handler.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void rx65nEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define EDMAC_RD0_RFS_RMAF
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:36
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define EDMAC_RD0_RFS_MASK
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NetTxAncillary
Definition: net_misc.h:36
error_t rx65nEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t rx65nEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define MIN(a, b)
Definition: os_port.h:63
#define rxBuffer
#define EDMAC_TD1_TBL
#define TRACE_DEBUG(...)
Definition: debug.h:119
void rx65nEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define EDMAC_TD0_TFP_SOF
uint32_t rx65nEthReadSmi(uint_t length)
SMI read operation.
#define EDMAC_TD0_TDLE
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
#define RX65N_ETH_RX_BUFFER_COUNT
Transmit DMA descriptor.
error_t rx65nEthInit(NetInterface *interface)
RX65N Ethernet MAC initialization.
#define RX65N_ETH_RX_BUFFER_SIZE
#define EDMAC_EESR_FR
error_t rx65nEthReceivePacket(NetInterface *interface)
Receive a packet.
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define EDMAC_TD0_TACT
#define SMI_SYNC
Definition: nic.h:63
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define RX65N_ETH_TX_BUFFER_SIZE
error_t rx65nEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
void rx65nEthIrqHandler(void)
RX65N Ethernet MAC interrupt service routine.
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define EDMAC_TD0_TFP_EOF
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83