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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <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  //Disable FR interrupts
498  EDMAC0.EESIPR.BIT.FRIP = 0;
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  //Packet received?
521  if((EDMAC0.EESR.LONG & EDMAC_EESR_FR) != 0)
522  {
523  //Clear FR interrupt flag
524  EDMAC0.EESR.LONG = EDMAC_EESR_FR;
525 
526  //Process all pending packets
527  do
528  {
529  //Read incoming packet
530  error = rx65nEthReceivePacket(interface);
531 
532  //No more data in the receive buffer?
533  } while(error != ERROR_BUFFER_EMPTY);
534  }
535 
536  //Re-enable EDMAC interrupts
537  EDMAC0.EESIPR.BIT.TWBIP = 1;
538  EDMAC0.EESIPR.BIT.FRIP = 1;
539 }
540 
541 
542 /**
543  * @brief Send a packet
544  * @param[in] interface Underlying network interface
545  * @param[in] buffer Multi-part buffer containing the data to send
546  * @param[in] offset Offset to the first data byte
547  * @param[in] ancillary Additional options passed to the stack along with
548  * the packet
549  * @return Error code
550  **/
551 
553  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
554 {
555  //Retrieve the length of the packet
556  size_t length = netBufferGetLength(buffer) - offset;
557 
558  //Check the frame length
560  {
561  //The transmitter can accept another packet
562  osSetEvent(&interface->nicTxEvent);
563  //Report an error
564  return ERROR_INVALID_LENGTH;
565  }
566 
567  //Make sure the current buffer is available for writing
568  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) != 0)
569  {
570  return ERROR_FAILURE;
571  }
572 
573  //Copy user data to the transmit buffer
574  netBufferRead(txBuffer[txIndex], buffer, offset, length);
575 
576  //Write the number of bytes to send
577  txDmaDesc[txIndex].td1 = (length << 16) & EDMAC_TD1_TBL;
578 
579  //Check current index
580  if(txIndex < (RX65N_ETH_TX_BUFFER_COUNT - 1))
581  {
582  //Give the ownership of the descriptor to the DMA engine
583  txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TFP_SOF |
585 
586  //Point to the next descriptor
587  txIndex++;
588  }
589  else
590  {
591  //Give the ownership of the descriptor to the DMA engine
592  txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TDLE |
594 
595  //Wrap around
596  txIndex = 0;
597  }
598 
599  //Instruct the DMA to poll the transmit descriptor list
600  EDMAC0.EDTRR.BIT.TR = 1;
601 
602  //Check whether the next buffer is available for writing
603  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) == 0)
604  {
605  //The transmitter can accept another packet
606  osSetEvent(&interface->nicTxEvent);
607  }
608 
609  //Successful write operation
610  return NO_ERROR;
611 }
612 
613 
614 /**
615  * @brief Receive a packet
616  * @param[in] interface Underlying network interface
617  * @return Error code
618  **/
619 
621 {
622  error_t error;
623  size_t n;
624  NetRxAncillary ancillary;
625 
626  //Current buffer available for reading?
627  if((rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RACT) == 0)
628  {
629  //SOF and EOF flags should be set
630  if((rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_SOF) != 0 &&
631  (rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_EOF) != 0)
632  {
633  //Make sure no error occurred
634  if((rxDmaDesc[rxIndex].rd0 & (EDMAC_RD0_RFS_MASK & ~EDMAC_RD0_RFS_RMAF)) == 0)
635  {
636  //Retrieve the length of the frame
637  n = rxDmaDesc[rxIndex].rd1 & EDMAC_RD1_RFL;
638  //Limit the number of data to read
640 
641  //Additional options can be passed to the stack along with the packet
642  ancillary = NET_DEFAULT_RX_ANCILLARY;
643 
644  //Pass the packet to the upper layer
645  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
646 
647  //Valid packet received
648  error = NO_ERROR;
649  }
650  else
651  {
652  //The received packet contains an error
653  error = ERROR_INVALID_PACKET;
654  }
655  }
656  else
657  {
658  //The packet is not valid
659  error = ERROR_INVALID_PACKET;
660  }
661 
662  //Check current index
663  if(rxIndex < (RX65N_ETH_RX_BUFFER_COUNT - 1))
664  {
665  //Give the ownership of the descriptor back to the DMA
666  rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT;
667  //Point to the next descriptor
668  rxIndex++;
669  }
670  else
671  {
672  //Give the ownership of the descriptor back to the DMA
673  rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT | EDMAC_RD0_RDLE;
674  //Wrap around
675  rxIndex = 0;
676  }
677 
678  //Instruct the DMA to poll the receive descriptor list
679  EDMAC0.EDRRR.BIT.RR = 1;
680  }
681  else
682  {
683  //No more data in the receive buffer
684  error = ERROR_BUFFER_EMPTY;
685  }
686 
687  //Return status code
688  return error;
689 }
690 
691 
692 /**
693  * @brief Configure MAC address filtering
694  * @param[in] interface Underlying network interface
695  * @return Error code
696  **/
697 
699 {
700  uint_t i;
701  bool_t acceptMulticast;
702 
703  //Debug message
704  TRACE_DEBUG("Updating MAC filter...\r\n");
705 
706  //Set the upper 32 bits of the MAC address
707  ETHERC0.MAHR = (interface->macAddr.b[0] << 24) | (interface->macAddr.b[1] << 16) |
708  (interface->macAddr.b[2] << 8) | interface->macAddr.b[3];
709 
710  //Set the lower 16 bits of the MAC address
711  ETHERC0.MALR.BIT.MA = (interface->macAddr.b[4] << 8) | interface->macAddr.b[5];
712 
713  //This flag will be set if multicast addresses should be accepted
714  acceptMulticast = FALSE;
715 
716  //The MAC address filter contains the list of MAC addresses to accept
717  //when receiving an Ethernet frame
718  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
719  {
720  //Valid entry?
721  if(interface->macAddrFilter[i].refCount > 0)
722  {
723  //Accept multicast addresses
724  acceptMulticast = TRUE;
725  //We are done
726  break;
727  }
728  }
729 
730  //Enable or disable the reception of multicast frames
731  if(acceptMulticast)
732  {
733  EDMAC0.EESR.BIT.RMAF = 1;
734  }
735  else
736  {
737  EDMAC0.EESR.BIT.RMAF = 0;
738  }
739 
740  //Successful processing
741  return NO_ERROR;
742 }
743 
744 
745 /**
746  * @brief Adjust MAC configuration parameters for proper operation
747  * @param[in] interface Underlying network interface
748  * @return Error code
749  **/
750 
752 {
753  //10BASE-T or 100BASE-TX operation mode?
754  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
755  {
756  ETHERC0.ECMR.BIT.RTM = 1;
757  }
758  else
759  {
760  ETHERC0.ECMR.BIT.RTM = 0;
761  }
762 
763  //Half-duplex or full-duplex mode?
764  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
765  {
766  ETHERC0.ECMR.BIT.DM = 1;
767  }
768  else
769  {
770  ETHERC0.ECMR.BIT.DM = 0;
771  }
772 
773  //Successful processing
774  return NO_ERROR;
775 }
776 
777 
778 /**
779  * @brief Write PHY register
780  * @param[in] opcode Access type (2 bits)
781  * @param[in] phyAddr PHY address (5 bits)
782  * @param[in] regAddr Register address (5 bits)
783  * @param[in] data Register value
784  **/
785 
786 void rx65nEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
787  uint8_t regAddr, uint16_t data)
788 {
789  //Synchronization pattern
791  //Start of frame
793  //Set up a write operation
795  //Write PHY address
796  rx65nEthWriteSmi(phyAddr, 5);
797  //Write register address
799  //Turnaround
801  //Write register value
802  rx65nEthWriteSmi(data, 16);
803  //Release MDIO
804  rx65nEthReadSmi(1);
805 }
806 
807 
808 /**
809  * @brief Read PHY register
810  * @param[in] opcode Access type (2 bits)
811  * @param[in] phyAddr PHY address (5 bits)
812  * @param[in] regAddr Register address (5 bits)
813  * @return Register value
814  **/
815 
816 uint16_t rx65nEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
817  uint8_t regAddr)
818 {
819  uint16_t data;
820 
821  //Synchronization pattern
823  //Start of frame
825  //Set up a read operation
827  //Write PHY address
828  rx65nEthWriteSmi(phyAddr, 5);
829  //Write register address
831  //Turnaround to avoid contention
832  rx65nEthReadSmi(1);
833  //Read register value
834  data = rx65nEthReadSmi(16);
835  //Force the PHY to release the MDIO pin
836  rx65nEthReadSmi(1);
837 
838  //Return PHY register contents
839  return data;
840 }
841 
842 
843 /**
844  * @brief SMI write operation
845  * @param[in] data Raw data to be written
846  * @param[in] length Number of bits to be written
847  **/
848 
850 {
851  //Skip the most significant bits since they are meaningless
852  data <<= 32 - length;
853 
854  //Configure MDIO as an output
855  ETHERC0.PIR.BIT.MMD = 1;
856 
857  //Write the specified number of bits
858  while(length--)
859  {
860  //Write MDIO
861  if((data & 0x80000000) != 0)
862  {
863  ETHERC0.PIR.BIT.MDO = 1;
864  }
865  else
866  {
867  ETHERC0.PIR.BIT.MDO = 0;
868  }
869 
870  //Assert MDC
871  usleep(1);
872  ETHERC0.PIR.BIT.MDC = 1;
873  //Deassert MDC
874  usleep(1);
875  ETHERC0.PIR.BIT.MDC = 0;
876 
877  //Rotate data
878  data <<= 1;
879  }
880 }
881 
882 
883 /**
884  * @brief SMI read operation
885  * @param[in] length Number of bits to be read
886  * @return Data resulting from the MDIO read operation
887  **/
888 
890 {
891  uint32_t data = 0;
892 
893  //Configure MDIO as an input
894  ETHERC0.PIR.BIT.MMD = 0;
895 
896  //Read the specified number of bits
897  while(length--)
898  {
899  //Rotate data
900  data <<= 1;
901 
902  //Assert MDC
903  ETHERC0.PIR.BIT.MDC = 1;
904  usleep(1);
905  //Deassert MDC
906  ETHERC0.PIR.BIT.MDC = 0;
907  usleep(1);
908 
909  //Check MDIO state
910  if(ETHERC0.PIR.BIT.MDI != 0)
911  {
912  data |= 0x01;
913  }
914  }
915 
916  //Return the received data
917  return data;
918 }
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:303
__weak_func void rx65nEthInitGpio(NetInterface *interface)
GPIO configuration.
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
#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:307
#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:104
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:140
#define NetInterface
Definition: net.h:36
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define EDMAC_RD0_RFS_MASK
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
#define NetTxAncillary
Definition: net_misc.h:36
error_t rx65nEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
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:107
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:50
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