s5d9_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file s5d9_eth_driver.c
3  * @brief Renesas Synergy S5D9 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 "bsp_irq_cfg.h"
36 #include "s5d9.h"
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWARM compiler?
45 #if defined(__ICCARM__)
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 //ARM or 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 S5D9 Ethernet MAC driver
86  **/
87 
89 {
91  ETH_MTU,
102  TRUE,
103  TRUE,
104  TRUE,
105  TRUE
106 };
107 
108 
109 /**
110  * @brief S5D9 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 S5D9 Ethernet MAC...\r\n");
121 
122  //Save underlying network interface
123  nicDriverInterface = interface;
124 
125  //Disable protection
126  R_SYSTEM->PRCR = 0xA50B;
127  //Cancel EDMAC0 module stop state
128  R_MSTP->MSTPCRB_b.MSTPB15 = 0;
129  //Enable protection
130  R_SYSTEM->PRCR = 0xA500;
131 
132  //GPIO configuration
133  s5d9EthInitGpio(interface);
134 
135  //Reset EDMAC0 module
136  R_EDMAC0->EDMR |= EDMAC_EDMR_SWR;
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  s5d9EthInitDmaDesc(interface);
165 
166  //Maximum frame length that can be accepted
167  R_ETHERC0->RFLR = S5D9_ETH_RX_BUFFER_SIZE;
168  //Set default inter packet gap (96-bit time)
169  R_ETHERC0->IPGR = 0x14;
170 
171  //Set the upper 32 bits of the MAC address
172  R_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  R_ETHERC0->MALR = (interface->macAddr.b[4] << 8) | interface->macAddr.b[5];
177 
178  //Select little endian mode and set descriptor length (16 bytes)
179  R_EDMAC0->EDMR = EDMAC_EDMR_DE | EDMAC_EDMR_DL_16;
180  //Use store and forward mode
181  R_EDMAC0->TFTR = 0;
182  //Set transmit and receive FIFO size
183  R_EDMAC0->FDR = EDMAC_FDR_TFD_2048 | EDMAC_FDR_RFD_4096;
184  //Enable continuous reception of multiple frames
185  R_EDMAC0->RMCR = EDMAC_RMCR_RNR;
186  //Select write-back complete interrupt mode and enable transmit interrupts
187  R_EDMAC0->TRIMD = EDMAC_TRIMD_TIM | EDMAC_TRIMD_TIS;
188 
189  //Disable all ETHERC interrupts
190  R_ETHERC0->ECSIPR = 0;
191  //Enable the desired EDMAC interrupts
192  R_EDMAC0->EESIPR = EDMAC_EESIPR_TWBIP | EDMAC_EESIPR_FRIP;
193 
194  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
195  NVIC_SetPriorityGrouping(S5D9_ETH_IRQ_PRIORITY_GROUPING);
196 
197  //Configure EDMAC interrupt priority
198  NVIC_SetPriority(EDMAC0_EINT_IRQn, NVIC_EncodePriority(S5D9_ETH_IRQ_PRIORITY_GROUPING,
200 
201  //Enable transmission and reception
202  R_ETHERC0->ECMR |= ETHERC_ECMR_TE | ETHERC_ECMR_RE;
203 
204  //Instruct the DMA to poll the receive descriptor list
205  R_EDMAC0->EDRRR = EDMAC_EDRRR_RR;
206 
207  //Accept any packets from the upper layer
208  osSetEvent(&interface->nicTxEvent);
209 
210  //Successful initialization
211  return NO_ERROR;
212 }
213 
214 
215 /**
216  * @brief GPIO configuration
217  * @param[in] interface Underlying network interface
218  **/
219 
220 __weak_func void s5d9EthInitGpio(NetInterface *interface)
221 {
222 //PK-S5D9 evaluation board?
223 #if defined(USE_PK_S5D9)
224  //Disable protection
225  R_SYSTEM->PRCR = 0xA50B;
226  //Disable VBATT channel 0 input (P4_2)
227  R_SYSTEM->VBTICTLR_b.VCH0INEN = 0;
228  //Enable protection
229  R_SYSTEM->PRCR = 0xA500;
230 
231  //Unlock PFS registers
232  R_PMISC->PWPR_b.BOWI = 0;
233  R_PMISC->PWPR_b.PFSWE = 1;
234 
235  //Select RMII interface mode
236  R_PMISC->PFENET_b.PHYMODE0 = 0;
237 
238  //Configure ET0_MDC (P4_1)
239  R_PFS->P401PFS_b.PMR = 1;
240  R_PFS->P401PFS_b.PSEL = 23;
241  R_PFS->P401PFS_b.DSCR = 1;
242 
243  //Configure ET0_MDIO (P4_2)
244  R_PFS->P402PFS_b.PMR = 1;
245  R_PFS->P402PFS_b.PSEL = 23;
246  R_PFS->P402PFS_b.DSCR = 1;
247 
248  //Configure RMII0_TXD_EN_B (P4_5)
249  R_PFS->P405PFS_b.PMR = 1;
250  R_PFS->P405PFS_b.PSEL = 23;
251  R_PFS->P405PFS_b.DSCR = 3;
252 
253  //Configure RMII0_TXD1_B (P4_6)
254  R_PFS->P406PFS_b.PMR = 1;
255  R_PFS->P406PFS_b.PSEL = 23;
256  R_PFS->P406PFS_b.DSCR = 3;
257 
258  //Configure RMII0_TXD0_B (P7_0)
259  R_PFS->P700PFS_b.PMR = 1;
260  R_PFS->P700PFS_b.PSEL = 23;
261  R_PFS->P700PFS_b.DSCR = 3;
262 
263  //Configure REF50CK0_B (P7_1)
264  R_PFS->P701PFS_b.PMR = 1;
265  R_PFS->P701PFS_b.PSEL = 23;
266  R_PFS->P701PFS_b.DSCR = 3;
267 
268  //Configure RMII0_RXD0_B (P7_2)
269  R_PFS->P702PFS_b.PMR = 1;
270  R_PFS->P702PFS_b.PSEL = 23;
271  R_PFS->P702PFS_b.DSCR = 3;
272 
273  //Configure RMII0_RXD1_B (P7_3)
274  R_PFS->P703PFS_b.PMR = 1;
275  R_PFS->P703PFS_b.PSEL = 23;
276  R_PFS->P703PFS_b.DSCR = 3;
277 
278  //Configure RMII0_RX_ER_B (P7_4)
279  R_PFS->P704PFS_b.PMR = 1;
280  R_PFS->P704PFS_b.PSEL = 23;
281  R_PFS->P704PFS_b.DSCR = 3;
282 
283  //Configure RMII0_CRS_DV_B (P7_5)
284  R_PFS->P705PFS_b.PMR = 1;
285  R_PFS->P705PFS_b.PSEL = 23;
286  R_PFS->P705PFS_b.DSCR = 3;
287 
288  //Lock PFS registers
289  R_PMISC->PWPR_b.PFSWE = 0;
290  R_PMISC->PWPR_b.BOWI = 1;
291 #endif
292 }
293 
294 
295 /**
296  * @brief Initialize DMA descriptor lists
297  * @param[in] interface Underlying network interface
298  **/
299 
301 {
302  uint_t i;
303 
304  //Initialize TX descriptors
305  for(i = 0; i < S5D9_ETH_TX_BUFFER_COUNT; i++)
306  {
307  //The descriptor is initially owned by the application
308  txDmaDesc[i].td0 = 0;
309  //Transmit buffer length
310  txDmaDesc[i].td1 = 0;
311  //Transmit buffer address
312  txDmaDesc[i].td2 = (uint32_t) txBuffer[i];
313  //Clear padding field
314  txDmaDesc[i].padding = 0;
315  }
316 
317  //Mark the last descriptor entry with the TDLE flag
318  txDmaDesc[i - 1].td0 |= EDMAC_TD0_TDLE;
319  //Initialize TX descriptor index
320  txIndex = 0;
321 
322  //Initialize RX descriptors
323  for(i = 0; i < S5D9_ETH_RX_BUFFER_COUNT; i++)
324  {
325  //The descriptor is initially owned by the DMA
326  rxDmaDesc[i].rd0 = EDMAC_RD0_RACT;
327  //Receive buffer length
329  //Receive buffer address
330  rxDmaDesc[i].rd2 = (uint32_t) rxBuffer[i];
331  //Clear padding field
332  rxDmaDesc[i].padding = 0;
333  }
334 
335  //Mark the last descriptor entry with the RDLE flag
336  rxDmaDesc[i - 1].rd0 |= EDMAC_RD0_RDLE;
337  //Initialize RX descriptor index
338  rxIndex = 0;
339 
340  //Start address of the TX descriptor list
341  R_EDMAC0->TDLAR = (uint32_t) txDmaDesc;
342  //Start address of the RX descriptor list
343  R_EDMAC0->RDLAR = (uint32_t) rxDmaDesc;
344 }
345 
346 
347 /**
348  * @brief S5D9 Ethernet MAC timer handler
349  *
350  * This routine is periodically called by the TCP/IP stack to handle periodic
351  * operations such as polling the link state
352  *
353  * @param[in] interface Underlying network interface
354  **/
355 
356 void s5d9EthTick(NetInterface *interface)
357 {
358  //Valid Ethernet PHY or switch driver?
359  if(interface->phyDriver != NULL)
360  {
361  //Handle periodic operations
362  interface->phyDriver->tick(interface);
363  }
364  else if(interface->switchDriver != NULL)
365  {
366  //Handle periodic operations
367  interface->switchDriver->tick(interface);
368  }
369  else
370  {
371  //Just for sanity
372  }
373 }
374 
375 
376 /**
377  * @brief Enable interrupts
378  * @param[in] interface Underlying network interface
379  **/
380 
382 {
383  //Enable Ethernet MAC interrupts
384  NVIC_EnableIRQ(EDMAC0_EINT_IRQn);
385 
386  //Valid Ethernet PHY or switch driver?
387  if(interface->phyDriver != NULL)
388  {
389  //Enable Ethernet PHY interrupts
390  interface->phyDriver->enableIrq(interface);
391  }
392  else if(interface->switchDriver != NULL)
393  {
394  //Enable Ethernet switch interrupts
395  interface->switchDriver->enableIrq(interface);
396  }
397  else
398  {
399  //Just for sanity
400  }
401 }
402 
403 
404 /**
405  * @brief Disable interrupts
406  * @param[in] interface Underlying network interface
407  **/
408 
410 {
411  //Disable Ethernet MAC interrupts
412  NVIC_DisableIRQ(EDMAC0_EINT_IRQn);
413 
414  //Valid Ethernet PHY or switch driver?
415  if(interface->phyDriver != NULL)
416  {
417  //Disable Ethernet PHY interrupts
418  interface->phyDriver->disableIrq(interface);
419  }
420  else if(interface->switchDriver != NULL)
421  {
422  //Disable Ethernet switch interrupts
423  interface->switchDriver->disableIrq(interface);
424  }
425  else
426  {
427  //Just for sanity
428  }
429 }
430 
431 
432 /**
433  * @brief S5D9 Ethernet MAC interrupt service routine
434  **/
435 
437 {
438  bool_t flag;
439  uint32_t status;
440 
441  //Interrupt service routine prologue
442  osEnterIsr();
443 
444  //This flag will be set if a higher priority task must be woken
445  flag = FALSE;
446 
447  //Read interrupt status register
448  status = R_EDMAC0->EESR;
449 
450  //Packet transmitted?
451  if((status & EDMAC_EESR_TWB) != 0)
452  {
453  //Clear TWB interrupt flag
454  R_EDMAC0->EESR = EDMAC_EESR_TWB;
455 
456  //Check whether the TX buffer is available for writing
457  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) == 0)
458  {
459  //Notify the TCP/IP stack that the transmitter is ready to send
460  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
461  }
462  }
463 
464  //Packet received?
465  if((status & EDMAC_EESR_FR) != 0)
466  {
467  //Clear FR interrupt flag
468  R_EDMAC0->EESR = EDMAC_EESR_FR;
469 
470  //Set event flag
471  nicDriverInterface->nicEvent = TRUE;
472  //Notify the TCP/IP stack of the event
473  flag |= osSetEventFromIsr(&netEvent);
474  }
475 
476  //Clear IR flag
477  R_ICU->IELSRn_b[EDMAC0_EINT_IRQn].IR = 0;
478 
479  //Interrupt service routine epilogue
480  osExitIsr(flag);
481 }
482 
483 
484 /**
485  * @brief S5D9 Ethernet MAC event handler
486  * @param[in] interface Underlying network interface
487  **/
488 
490 {
491  error_t error;
492 
493  //Process all pending packets
494  do
495  {
496  //Read incoming packet
497  error = s5d9EthReceivePacket(interface);
498 
499  //No more data in the receive buffer?
500  } while(error != ERROR_BUFFER_EMPTY);
501 }
502 
503 
504 /**
505  * @brief Send a packet
506  * @param[in] interface Underlying network interface
507  * @param[in] buffer Multi-part buffer containing the data to send
508  * @param[in] offset Offset to the first data byte
509  * @param[in] ancillary Additional options passed to the stack along with
510  * the packet
511  * @return Error code
512  **/
513 
515  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
516 {
517  //Retrieve the length of the packet
518  size_t length = netBufferGetLength(buffer) - offset;
519 
520  //Check the frame length
522  {
523  //The transmitter can accept another packet
524  osSetEvent(&interface->nicTxEvent);
525  //Report an error
526  return ERROR_INVALID_LENGTH;
527  }
528 
529  //Make sure the current buffer is available for writing
530  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) != 0)
531  {
532  return ERROR_FAILURE;
533  }
534 
535  //Copy user data to the transmit buffer
536  netBufferRead(txBuffer[txIndex], buffer, offset, length);
537 
538  //Write the number of bytes to send
539  txDmaDesc[txIndex].td1 = (length << 16) & EDMAC_TD1_TBL;
540 
541  //Check current index
542  if(txIndex < (S5D9_ETH_TX_BUFFER_COUNT - 1))
543  {
544  //Give the ownership of the descriptor to the DMA engine
545  txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TFP_SOF |
547 
548  //Point to the next descriptor
549  txIndex++;
550  }
551  else
552  {
553  //Give the ownership of the descriptor to the DMA engine
554  txDmaDesc[txIndex].td0 = EDMAC_TD0_TACT | EDMAC_TD0_TDLE |
556 
557  //Wrap around
558  txIndex = 0;
559  }
560 
561  //Instruct the DMA to poll the transmit descriptor list
562  R_EDMAC0->EDTRR = EDMAC_EDTRR_TR;
563 
564  //Check whether the next buffer is available for writing
565  if((txDmaDesc[txIndex].td0 & EDMAC_TD0_TACT) == 0)
566  {
567  //The transmitter can accept another packet
568  osSetEvent(&interface->nicTxEvent);
569  }
570 
571  //Successful write operation
572  return NO_ERROR;
573 }
574 
575 
576 /**
577  * @brief Receive a packet
578  * @param[in] interface Underlying network interface
579  * @return Error code
580  **/
581 
583 {
584  error_t error;
585  size_t n;
586  NetRxAncillary ancillary;
587 
588  //Current buffer available for reading?
589  if((rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RACT) == 0)
590  {
591  //SOF and EOF flags should be set
592  if((rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_SOF) != 0 &&
593  (rxDmaDesc[rxIndex].rd0 & EDMAC_RD0_RFP_EOF) != 0)
594  {
595  //Make sure no error occurred
596  if((rxDmaDesc[rxIndex].rd0 & (EDMAC_RD0_RFS_MASK & ~EDMAC_RD0_RFS_RMAF)) == 0)
597  {
598  //Retrieve the length of the frame
599  n = rxDmaDesc[rxIndex].rd1 & EDMAC_RD1_RFL;
600  //Limit the number of data to read
602 
603  //Additional options can be passed to the stack along with the packet
604  ancillary = NET_DEFAULT_RX_ANCILLARY;
605 
606  //Pass the packet to the upper layer
607  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
608 
609  //Valid packet received
610  error = NO_ERROR;
611  }
612  else
613  {
614  //The received packet contains an error
615  error = ERROR_INVALID_PACKET;
616  }
617  }
618  else
619  {
620  //The packet is not valid
621  error = ERROR_INVALID_PACKET;
622  }
623 
624  //Check current index
625  if(rxIndex < (S5D9_ETH_RX_BUFFER_COUNT - 1))
626  {
627  //Give the ownership of the descriptor back to the DMA
628  rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT;
629  //Point to the next descriptor
630  rxIndex++;
631  }
632  else
633  {
634  //Give the ownership of the descriptor back to the DMA
635  rxDmaDesc[rxIndex].rd0 = EDMAC_RD0_RACT | EDMAC_RD0_RDLE;
636  //Wrap around
637  rxIndex = 0;
638  }
639 
640  //Instruct the DMA to poll the receive descriptor list
641  R_EDMAC0->EDRRR = EDMAC_EDRRR_RR;
642  }
643  else
644  {
645  //No more data in the receive buffer
646  error = ERROR_BUFFER_EMPTY;
647  }
648 
649  //Return status code
650  return error;
651 }
652 
653 
654 /**
655  * @brief Configure MAC address filtering
656  * @param[in] interface Underlying network interface
657  * @return Error code
658  **/
659 
661 {
662  uint_t i;
663  bool_t acceptMulticast;
664 
665  //Debug message
666  TRACE_DEBUG("Updating MAC filter...\r\n");
667 
668  //Promiscuous mode?
669  if(interface->promiscuous)
670  {
671  //Accept all frames regardless of their destination address
672  R_ETHERC0->ECMR |= ETHERC_ECMR_PRM;
673  }
674  else
675  {
676  //Disable promiscuous mode
677  R_ETHERC0->ECMR &= ~ETHERC_ECMR_PRM;
678 
679  //Set the upper 32 bits of the MAC address
680  R_ETHERC0->MAHR = (interface->macAddr.b[0] << 24) | (interface->macAddr.b[1] << 16) |
681  (interface->macAddr.b[2] << 8) | interface->macAddr.b[3];
682 
683  //Set the lower 16 bits of the MAC address
684  R_ETHERC0->MALR = (interface->macAddr.b[4] << 8) | interface->macAddr.b[5];
685 
686  //This flag will be set if multicast addresses should be accepted
687  acceptMulticast = FALSE;
688 
689  //The MAC address filter contains the list of MAC addresses to accept
690  //when receiving an Ethernet frame
691  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
692  {
693  //Valid entry?
694  if(interface->macAddrFilter[i].refCount > 0)
695  {
696  //Accept multicast addresses
697  acceptMulticast = TRUE;
698  //We are done
699  break;
700  }
701  }
702 
703  //Enable or disable the reception of multicast frames
704  if(acceptMulticast || interface->acceptAllMulticast)
705  {
706  R_EDMAC0->EESR |= EDMAC_EESR_RMAF;
707  }
708  else
709  {
710  R_EDMAC0->EESR &= ~EDMAC_EESR_RMAF;
711  }
712  }
713 
714  //Successful processing
715  return NO_ERROR;
716 }
717 
718 
719 /**
720  * @brief Adjust MAC configuration parameters for proper operation
721  * @param[in] interface Underlying network interface
722  * @return Error code
723  **/
724 
726 {
727  uint32_t mode;
728 
729  //Read ETHERC mode register
730  mode = R_ETHERC0->ECMR;
731 
732  //10BASE-T or 100BASE-TX operation mode?
733  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
734  {
735  mode |= ETHERC_ECMR_RTM;
736  }
737  else
738  {
739  mode &= ~ETHERC_ECMR_RTM;
740  }
741 
742  //Half-duplex or full-duplex mode?
743  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
744  {
745  mode |= ETHERC_ECMR_DM;
746  }
747  else
748  {
749  mode &= ~ETHERC_ECMR_DM;
750  }
751 
752  //Update ETHERC mode register
753  R_ETHERC0->ECMR = mode;
754 
755  //Successful processing
756  return NO_ERROR;
757 }
758 
759 
760 /**
761  * @brief Write PHY register
762  * @param[in] opcode Access type (2 bits)
763  * @param[in] phyAddr PHY address (5 bits)
764  * @param[in] regAddr Register address (5 bits)
765  * @param[in] data Register value
766  **/
767 
768 void s5d9EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
769  uint8_t regAddr, uint16_t data)
770 {
771  //Synchronization pattern
773  //Start of frame
775  //Set up a write operation
777  //Write PHY address
778  s5d9EthWriteSmi(phyAddr, 5);
779  //Write register address
781  //Turnaround
783  //Write register value
784  s5d9EthWriteSmi(data, 16);
785  //Release MDIO
786  s5d9EthReadSmi(1);
787 }
788 
789 
790 /**
791  * @brief Read PHY register
792  * @param[in] opcode Access type (2 bits)
793  * @param[in] phyAddr PHY address (5 bits)
794  * @param[in] regAddr Register address (5 bits)
795  * @return Register value
796  **/
797 
798 uint16_t s5d9EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
799  uint8_t regAddr)
800 {
801  uint16_t data;
802 
803  //Synchronization pattern
805  //Start of frame
807  //Set up a read operation
809  //Write PHY address
810  s5d9EthWriteSmi(phyAddr, 5);
811  //Write register address
813  //Turnaround to avoid contention
814  s5d9EthReadSmi(1);
815  //Read register value
816  data = s5d9EthReadSmi(16);
817  //Force the PHY to release the MDIO pin
818  s5d9EthReadSmi(1);
819 
820  //Return PHY register contents
821  return data;
822 }
823 
824 
825 /**
826  * @brief SMI write operation
827  * @param[in] data Raw data to be written
828  * @param[in] length Number of bits to be written
829  **/
830 
832 {
833  //Skip the most significant bits since they are meaningless
834  data <<= 32 - length;
835 
836  //Configure MDIO as an output
837  R_ETHERC0->PIR |= ETHERC_PIR_MMD;
838 
839  //Write the specified number of bits
840  while(length--)
841  {
842  //Write MDIO
843  if((data & 0x80000000) != 0)
844  {
845  R_ETHERC0->PIR |= ETHERC_PIR_MDO;
846  }
847  else
848  {
849  R_ETHERC0->PIR &= ~ETHERC_PIR_MDO;
850  }
851 
852  //Assert MDC
853  usleep(1);
854  R_ETHERC0->PIR |= ETHERC_PIR_MDC;
855  //Deassert MDC
856  usleep(1);
857  R_ETHERC0->PIR &= ~ETHERC_PIR_MDC;
858 
859  //Rotate data
860  data <<= 1;
861  }
862 }
863 
864 
865 /**
866  * @brief SMI read operation
867  * @param[in] length Number of bits to be read
868  * @return Data resulting from the MDIO read operation
869  **/
870 
872 {
873  uint32_t data = 0;
874 
875  //Configure MDIO as an input
876  R_ETHERC0->PIR &= ~ETHERC_PIR_MMD;
877 
878  //Read the specified number of bits
879  while(length--)
880  {
881  //Rotate data
882  data <<= 1;
883 
884  //Assert MDC
885  R_ETHERC0->PIR |= ETHERC_PIR_MDC;
886  usleep(1);
887  //Deassert MDC
888  R_ETHERC0->PIR &= ~ETHERC_PIR_MDC;
889  usleep(1);
890 
891  //Check MDIO state
892  if((R_ETHERC0->PIR & ETHERC_PIR_MDI) != 0)
893  {
894  data |= 0x01;
895  }
896  }
897 
898  //Return the received data
899  return data;
900 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define EDMAC_RD0_RFP_EOF
error_t s5d9EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define usleep(delay)
Definition: os_port.h:303
error_t s5d9EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void s5d9EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define S5D9_ETH_RX_BUFFER_COUNT
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
void s5d9EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define S5D9_ETH_IRQ_GROUP_PRIORITY
#define netEvent
Definition: net_legacy.h:196
#define EDMAC_EDTRR_TR
#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
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 S5D9_ETH_TX_BUFFER_COUNT
#define EDMAC_RD0_RACT
#define ETHERC_ECMR_PRM
#define EDMAC_EDMR_DL_16
#define S5D9_ETH_RX_BUFFER_SIZE
void EDMAC0_EINT_IRQHandler(void)
S5D9 Ethernet MAC interrupt service routine.
#define SMI_TA
Definition: nic.h:68
#define SMI_START
Definition: nic.h:64
#define ETHERC_PIR_MDO
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 ETHERC_PIR_MDC
#define osExitIsr(flag)
#define EDMAC_TD0_TWBI
#define EDMAC_EDMR_SWR
#define ETHERC_ECMR_RTM
#define EDMAC_EESIPR_TWBIP
#define EDMAC_RD1_RFL
#define EDMAC_EESR_RMAF
#define EDMAC_RMCR_RNR
#define EDMAC_EDMR_DE
#define EDMAC_RD0_RDLE
#define EDMAC_EESIPR_FRIP
#define FALSE
Definition: os_port.h:46
void s5d9EthWriteSmi(uint32_t data, uint_t length)
SMI write operation.
#define EDMAC_RD0_RFP_SOF
error_t
Error codes.
Definition: error.h:43
#define EDMAC_RD1_RBL
#define ETHERC_ECMR_DM
Transmit DMA descriptor.
#define ETHERC_ECMR_RE
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
error_t s5d9EthReceivePacket(NetInterface *interface)
Receive a packet.
#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 ETHERC_ECMR_TE
#define EDMAC_TRIMD_TIS
#define ETHERC_PIR_MMD
#define EDMAC_FDR_TFD_2048
#define NetTxAncillary
Definition: net_misc.h:36
void s5d9EthEventHandler(NetInterface *interface)
S5D9 Ethernet MAC event handler.
error_t s5d9EthInit(NetInterface *interface)
S5D9 Ethernet MAC initialization.
#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
#define MIN(a, b)
Definition: os_port.h:63
#define S5D9_ETH_IRQ_PRIORITY_GROUPING
#define rxBuffer
Receive DMA descriptor.
#define EDMAC_TD1_TBL
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define EDMAC_TD0_TFP_SOF
#define EDMAC_TD0_TDLE
#define EDMAC_EDRRR_RR
#define S5D9_ETH_TX_BUFFER_SIZE
error_t s5d9EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
const NicDriver s5d9EthDriver
S5D9 Ethernet MAC driver.
uint8_t n
void s5d9EthTick(NetInterface *interface)
S5D9 Ethernet MAC timer handler.
#define osEnterIsr()
void s5d9EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define S5D9_ETH_IRQ_SUB_PRIORITY
#define EDMAC_EESR_FR
#define EDMAC_TRIMD_TIM
Renesas Synergy S5D9 Ethernet MAC driver.
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
uint32_t s5d9EthReadSmi(uint_t length)
SMI read operation.
uint16_t s5d9EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define EDMAC_TD0_TACT
__weak_func void s5d9EthInitGpio(NetInterface *interface)
GPIO configuration.
#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
void s5d9EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ETHERC_PIR_MDI
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define EDMAC_FDR_RFD_4096
#define EDMAC_TD0_TFP_EOF
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83