esp32_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file esp32_eth_driver.c
3  * @brief ESP32 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 "esp_intr_alloc.h"
36 #include "soc/dport_reg.h"
37 #include "soc/dport_access.h"
38 #include "soc/io_mux_reg.h"
39 #include "soc/gpio_sig_map.h"
40 #include "driver/gpio.h"
41 #include "rom/gpio.h"
42 #include "esp_private/periph_ctrl.h"
43 #include "core/net.h"
45 #include "debug.h"
46 
47 //Transmit buffer
49  __attribute__((aligned(1024)));
50 //Receive buffer
52  __attribute__((aligned(1024)));
53 //Transmit DMA descriptors
55  __attribute__((aligned(1024)));
56 //Receive DMA descriptors
58  __attribute__((aligned(1024)));
59 
60 //Pointer to the current TX DMA descriptor
61 static Esp32EthTxDmaDesc *txCurDmaDesc;
62 //Pointer to the current RX DMA descriptor
63 static Esp32EthRxDmaDesc *rxCurDmaDesc;
64 
65 
66 /**
67  * @brief ESP32 Ethernet MAC driver
68  **/
69 
71 {
73  ETH_MTU,
84  TRUE,
85  TRUE,
86  TRUE,
87  FALSE
88 };
89 
90 
91 /**
92  * @brief ESP32 Ethernet MAC initialization
93  * @param[in] interface Underlying network interface
94  * @return Error code
95  **/
96 
98 {
99  error_t error;
100 
101  //Debug message
102  TRACE_INFO("Initializing ESP32 Ethernet MAC...\r\n");
103 
104  //Enable EMAC module
105  periph_module_enable(PERIPH_EMAC_MODULE);
106 
107  //Enable Ethernet MAC clock
108  DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_EMAC_EN);
109 
110  //GPIO configuration
111  esp32EthInitGpio(interface);
112 
113  //Perform a software reset
115  //Wait for the reset to complete
117  {
118  }
119 
120  //Adjust MDC clock range
122 
123  //Valid Ethernet PHY or switch driver?
124  if(interface->phyDriver != NULL)
125  {
126  //Ethernet PHY initialization
127  error = interface->phyDriver->init(interface);
128  }
129  else if(interface->switchDriver != NULL)
130  {
131  //Ethernet switch initialization
132  error = interface->switchDriver->init(interface);
133  }
134  else
135  {
136  //The interface is not properly configured
137  error = ERROR_FAILURE;
138  }
139 
140  //Any error to report?
141  if(error)
142  {
143  return error;
144  }
145 
146  //Use default MAC configuration
148 
149  //Set the MAC address of the station
150  EMAC_ADDR0HIGH_REG = interface->macAddr.w[2];
151  EMAC_ADDR0LOW_REG = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
152 
153  //The MAC supports 3 additional addresses for unicast perfect filtering
154  EMAC_ADDR1HIGH_REG = 0;
155  EMAC_ADDR1LOW_REG = 0;
156  EMAC_ADDR2HIGH_REG = 0;
157  EMAC_ADDR2LOW_REG = 0;
158  EMAC_ADDR3HIGH_REG = 0;
159  EMAC_ADDR3LOW_REG = 0;
160 
161  //Configure the receive filter
162  EMAC_FF_REG = 0;
163  //Disable flow control
164  EMAC_FC_REG = 0;
165 
166  //Enable store and forward mode
169 
170  //Configure DMA bus mode
173 
174  //Initialize DMA descriptor lists
175  esp32EthInitDmaDesc(interface);
176 
177  //Disable MAC interrupts
179 
180  //Enable the desired DMA interrupts
183 
184  //Register interrupt handler
185  esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, ESP32_ETH_IRQ_FLAGS,
186  esp32EthIrqHandler, interface, NULL);
187 
188  //Enable MAC transmission and reception
190 
191  //Enable DMA transmission and reception
194 
195  //Accept any packets from the upper layer
196  osSetEvent(&interface->nicTxEvent);
197 
198  //Successful initialization
199  return NO_ERROR;
200 }
201 
202 
203 /**
204  * @brief GPIO configuration
205  * @param[in] interface Underlying network interface
206  **/
207 
208 __weak_func void esp32EthInitGpio(NetInterface *interface)
209 {
210 //ESP32-Ethernet-Kit?
211 #if defined(ESP32_ETHERNET_KIT)
212  //Select RMII interface mode
214 
215  //Select clock source
217  //Enable clock
219 
220  //Configure RMII CLK (GPIO0)
221  gpio_set_direction(0, GPIO_MODE_INPUT);
222 
223  //Configure TXD0 (GPIO19)
224  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
225  //Configure TX_EN (GPIO21)
226  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
227  //Configure TXD1 (GPIO22)
228  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
229 
230  //Configure RXD0 (GPIO25)
231  gpio_set_direction(25, GPIO_MODE_INPUT);
232  //Configure RXD1 (GPIO26)
233  gpio_set_direction(26, GPIO_MODE_INPUT);
234  //Configure CRS_DRV (GPIO27)
235  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
236 
237  //Configure MDC (GPIO23)
238  gpio_matrix_out(23, EMAC_MDC_O_IDX, 0, 0);
239 
240  //Configure MDIO (GPIO18)
241  gpio_matrix_out(18, EMAC_MDO_O_IDX, 0, 0);
242  gpio_matrix_in(18, EMAC_MDI_I_IDX, 0);
243 
244  //Configure PHY_RST (GPIO5)
245  gpio_pad_select_gpio(5);
246  gpio_set_direction(5, GPIO_MODE_OUTPUT);
247 
248  //Reset PHY transceiver
249  gpio_set_level(5, 0);
250  sleep(10);
251  gpio_set_level(5, 1);
252  sleep(10);
253 
254 //EVK-NINA-W10 evaluation board?
255 #elif defined(EVK_NINA_W10)
256  //Select RMII interface mode
258 
259  //Select clock source
261  //Enable clock
263 
264  //Configure RMII CLK (GPIO0)
265  gpio_set_direction(0, GPIO_MODE_INPUT);
266 
267  //Configure TXD0 (GPIO19)
268  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
269  //Configure TX_EN (GPIO21)
270  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
271  //Configure TXD1 (GPIO22)
272  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
273 
274  //Configure RXD0 (GPIO25)
275  gpio_set_direction(25, GPIO_MODE_INPUT);
276  //Configure RXD1 (GPIO26)
277  gpio_set_direction(26, GPIO_MODE_INPUT);
278  //Configure CRS_DRV (GPIO27)
279  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
280 
281  //Configure MDC (GPIO2)
282  gpio_matrix_out(2, EMAC_MDC_O_IDX, 0, 0);
283 
284  //Configure MDIO (GPIO4)
285  gpio_matrix_out(4, EMAC_MDO_O_IDX, 0, 0);
286  gpio_matrix_in(4, EMAC_MDI_I_IDX, 0);
287 
288 //ESP32-EVB or ESP32-GATEWAY evaluation board?
289 #elif defined(ESP32_EVB) || defined(ESP32_GATEWAY)
290  //Select RMII interface mode
292 
293  //Select clock source
295  //Enable clock
297 
298  //Configure RMII CLK (GPIO0)
299  gpio_set_direction(0, GPIO_MODE_INPUT);
300 
301  //Configure TXD0 (GPIO19)
302  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
303  //Configure TX_EN (GPIO21)
304  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
305  //Configure TXD1 (GPIO22)
306  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
307 
308  //Configure RXD0 (GPIO25)
309  gpio_set_direction(25, GPIO_MODE_INPUT);
310  //Configure RXD1 (GPIO26)
311  gpio_set_direction(26, GPIO_MODE_INPUT);
312  //Configure CRS_DRV (GPIO27)
313  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
314 
315  //Configure MDC (GPIO23)
316  gpio_matrix_out(23, EMAC_MDC_O_IDX, 0, 0);
317 
318  //Configure MDIO (GPIO18)
319  gpio_matrix_out(18, EMAC_MDO_O_IDX, 0, 0);
320  gpio_matrix_in(18, EMAC_MDI_I_IDX, 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 DMA descriptor list
335  for(i = 0; i < ESP32_ETH_TX_BUFFER_COUNT; i++)
336  {
337  //Use chain structure rather than ring structure
339  //Initialize transmit buffer size
340  txDmaDesc[i].tdes1 = 0;
341  //Transmit buffer address
342  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
343  //Next descriptor address
344  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
345  //Reserved fields
346  txDmaDesc[i].tdes4 = 0;
347  txDmaDesc[i].tdes5 = 0;
348  //Transmit frame time stamp
349  txDmaDesc[i].tdes6 = 0;
350  txDmaDesc[i].tdes7 = 0;
351  }
352 
353  //The last descriptor is chained to the first entry
354  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
355  //Point to the very first descriptor
356  txCurDmaDesc = &txDmaDesc[0];
357 
358  //Initialize RX DMA descriptor list
359  for(i = 0; i < ESP32_ETH_RX_BUFFER_COUNT; i++)
360  {
361  //The descriptor is initially owned by the DMA
362  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
363  //Use chain structure rather than ring structure
365  //Receive buffer address
366  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
367  //Next descriptor address
368  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
369  //Extended status
370  rxDmaDesc[i].rdes4 = 0;
371  //Reserved field
372  rxDmaDesc[i].rdes5 = 0;
373  //Receive frame time stamp
374  rxDmaDesc[i].rdes6 = 0;
375  rxDmaDesc[i].rdes7 = 0;
376  }
377 
378  //The last descriptor is chained to the first entry
379  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
380  //Point to the very first descriptor
381  rxCurDmaDesc = &rxDmaDesc[0];
382 
383  //Start location of the TX descriptor list
384  EMAC_DMATXBASEADDR_REG = (uint32_t) txDmaDesc;
385  //Start location of the RX descriptor list
386  EMAC_DMARXBASEADDR_REG = (uint32_t) rxDmaDesc;
387 }
388 
389 
390 /**
391  * @brief ESP32 Ethernet MAC timer handler
392  *
393  * This routine is periodically called by the TCP/IP stack to handle periodic
394  * operations such as polling the link state
395  *
396  * @param[in] interface Underlying network interface
397  **/
398 
399 void esp32EthTick(NetInterface *interface)
400 {
401  //Valid Ethernet PHY or switch driver?
402  if(interface->phyDriver != NULL)
403  {
404  //Handle periodic operations
405  interface->phyDriver->tick(interface);
406  }
407  else if(interface->switchDriver != NULL)
408  {
409  //Handle periodic operations
410  interface->switchDriver->tick(interface);
411  }
412  else
413  {
414  //Just for sanity
415  }
416 }
417 
418 
419 /**
420  * @brief Enable interrupts
421  * @param[in] interface Underlying network interface
422  **/
423 
425 {
426  //Enable Ethernet MAC interrupts
427  esp_intr_enable_source(ETS_ETH_MAC_INTR_SOURCE);
428 
429  //Valid Ethernet PHY or switch driver?
430  if(interface->phyDriver != NULL)
431  {
432  //Enable Ethernet PHY interrupts
433  interface->phyDriver->enableIrq(interface);
434  }
435  else if(interface->switchDriver != NULL)
436  {
437  //Enable Ethernet switch interrupts
438  interface->switchDriver->enableIrq(interface);
439  }
440  else
441  {
442  //Just for sanity
443  }
444 }
445 
446 
447 /**
448  * @brief Disable interrupts
449  * @param[in] interface Underlying network interface
450  **/
451 
453 {
454  //Disable Ethernet MAC interrupts
455  esp_intr_disable_source(ETS_ETH_MAC_INTR_SOURCE);
456 
457  //Valid Ethernet PHY or switch driver?
458  if(interface->phyDriver != NULL)
459  {
460  //Disable Ethernet PHY interrupts
461  interface->phyDriver->disableIrq(interface);
462  }
463  else if(interface->switchDriver != NULL)
464  {
465  //Disable Ethernet switch interrupts
466  interface->switchDriver->disableIrq(interface);
467  }
468  else
469  {
470  //Just for sanity
471  }
472 }
473 
474 
475 /**
476  * @brief ESP32 Ethernet MAC interrupt service routine
477  * @param[in] arg Unused parameter
478  **/
479 
480 void IRAM_ATTR esp32EthIrqHandler(void *arg)
481 {
482  bool_t flag;
483  uint32_t status;
484  NetInterface *interface;
485 
486  //Interrupt service routine prologue
487  osEnterIsr();
488 
489  //Point to the underlying network interface
490  interface = (NetInterface *) arg;
491 
492  //This flag will be set if a higher priority task must be woken
493  flag = FALSE;
494 
495  //Read DMA status register
496  status = EMAC_DMASTATUS_REG;
497 
498  //Packet transmitted?
499  if((status & EMAC_DMASTATUS_TRANS_INT) != 0)
500  {
501  //Clear TI interrupt flag
503 
504  //Check whether the TX buffer is available for writing
505  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
506  {
507  //Notify the TCP/IP stack that the transmitter is ready to send
508  flag |= osSetEventFromIsr(&interface->nicTxEvent);
509  }
510  }
511 
512  //Packet received?
513  if((status & EMAC_DMASTATUS_RECV_INT) != 0)
514  {
515  //Clear RI interrupt flag
517 
518  //Set event flag
519  interface->nicEvent = TRUE;
520  //Notify the TCP/IP stack of the event
521  flag |= osSetEventFromIsr(&netEvent);
522  }
523 
524  //Clear NIS interrupt flag
526 
527  //Interrupt service routine epilogue
528  osExitIsr(flag);
529 }
530 
531 
532 /**
533  * @brief ESP32 Ethernet MAC event handler
534  * @param[in] interface Underlying network interface
535  **/
536 
538 {
539  error_t error;
540 
541  //Process all pending packets
542  do
543  {
544  //Read incoming packet
545  error = esp32EthReceivePacket(interface);
546 
547  //No more data in the receive buffer?
548  } while(error != ERROR_BUFFER_EMPTY);
549 }
550 
551 
552 /**
553  * @brief Send a packet
554  * @param[in] interface Underlying network interface
555  * @param[in] buffer Multi-part buffer containing the data to send
556  * @param[in] offset Offset to the first data byte
557  * @param[in] ancillary Additional options passed to the stack along with
558  * the packet
559  * @return Error code
560  **/
561 
563  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
564 {
565  size_t length;
566 
567  //Retrieve the length of the packet
568  length = netBufferGetLength(buffer) - offset;
569 
570  //Check the frame length
572  {
573  //The transmitter can accept another packet
574  osSetEvent(&interface->nicTxEvent);
575  //Report an error
576  return ERROR_INVALID_LENGTH;
577  }
578 
579  //Make sure the current buffer is available for writing
580  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) != 0)
581  {
582  return ERROR_FAILURE;
583  }
584 
585  //Copy user data to the transmit buffer
586  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
587 
588  //Write the number of bytes to send
589  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
590  //Set LS and FS flags as the data fits in a single buffer
591  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
592  //Give the ownership of the descriptor to the DMA
593  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
594 
595  //Clear TBUS flag to resume processing
597  //Instruct the DMA to poll the transmit descriptor list
599 
600  //Point to the next descriptor in the list
601  txCurDmaDesc = (Esp32EthTxDmaDesc *) txCurDmaDesc->tdes3;
602 
603  //Check whether the next buffer is available for writing
604  if((txCurDmaDesc->tdes0 & EMAC_TDES0_OWN) == 0)
605  {
606  //The transmitter can accept another packet
607  osSetEvent(&interface->nicTxEvent);
608  }
609 
610  //Data successfully written
611  return NO_ERROR;
612 }
613 
614 
615 /**
616  * @brief Receive a packet
617  * @param[in] interface Underlying network interface
618  * @return Error code
619  **/
620 
622 {
623  error_t error;
624  size_t n;
625  NetRxAncillary ancillary;
626 
627  //Current buffer available for reading?
628  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN) == 0)
629  {
630  //FS and LS flags should be set
631  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) != 0 &&
632  (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS) != 0)
633  {
634  //Make sure no error occurred
635  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_ES) == 0)
636  {
637  //Retrieve the length of the frame
638  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
639  //Limit the number of data to read
641 
642  //Additional options can be passed to the stack along with the packet
643  ancillary = NET_DEFAULT_RX_ANCILLARY;
644 
645  //Pass the packet to the upper layer
646  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
647  &ancillary);
648 
649  //Valid packet received
650  error = NO_ERROR;
651  }
652  else
653  {
654  //The received packet contains an error
655  error = ERROR_INVALID_PACKET;
656  }
657  }
658  else
659  {
660  //The packet is not valid
661  error = ERROR_INVALID_PACKET;
662  }
663 
664  //Give the ownership of the descriptor back to the DMA
665  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
666  //Point to the next descriptor in the list
667  rxCurDmaDesc = (Esp32EthRxDmaDesc *) rxCurDmaDesc->rdes3;
668  }
669  else
670  {
671  //No more data in the receive buffer
672  error = ERROR_BUFFER_EMPTY;
673  }
674 
675  //Clear RBUS flag to resume processing
677  //Instruct the DMA to poll the receive descriptor list
679 
680  //Return status code
681  return error;
682 }
683 
684 
685 /**
686  * @brief Configure MAC address filtering
687  * @param[in] interface Underlying network interface
688  * @return Error code
689  **/
690 
692 {
693  uint_t i;
694  uint_t j;
695  bool_t acceptMulticast;
696  MacAddr unicastMacAddr[3];
697  MacFilterEntry *entry;
698 
699  //Debug message
700  TRACE_DEBUG("Updating MAC filter...\r\n");
701 
702  //Set the MAC address of the station
703  EMAC_ADDR0HIGH_REG = interface->macAddr.w[2];
704  EMAC_ADDR0LOW_REG = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
705 
706  //The MAC supports 3 additional addresses for unicast perfect filtering
707  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
708  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
709  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
710 
711  //This flag will be set if multicast addresses should be accepted
712  acceptMulticast = FALSE;
713 
714  //The MAC address filter contains the list of MAC addresses to accept
715  //when receiving an Ethernet frame
716  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
717  {
718  //Point to the current entry
719  entry = &interface->macAddrFilter[i];
720 
721  //Valid entry?
722  if(entry->refCount > 0)
723  {
724  //Multicast address?
725  if(macIsMulticastAddr(&entry->addr))
726  {
727  //Accept multicast addresses
728  acceptMulticast = TRUE;
729  }
730  else
731  {
732  //Up to 3 additional MAC addresses can be specified
733  if(j < 3)
734  {
735  //Save the unicast address
736  unicastMacAddr[j++] = entry->addr;
737  }
738  }
739  }
740  }
741 
742  //Configure the first unicast address filter
743  if(j >= 1)
744  {
745  EMAC_ADDR1HIGH_REG = unicastMacAddr[0].w[2] | EMAC_ADDR1HIGH_ADDRESS_ENABLE1;
746  EMAC_ADDR1LOW_REG = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
747  }
748  else
749  {
750  EMAC_ADDR1HIGH_REG = 0;
751  EMAC_ADDR1LOW_REG = 0;
752  }
753 
754  //Configure the second unicast address filter
755  if(j >= 2)
756  {
757  EMAC_ADDR2HIGH_REG = unicastMacAddr[1].w[2] | EMAC_ADDR2HIGH_ADDRESS_ENABLE2;
758  EMAC_ADDR2LOW_REG = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
759  }
760  else
761  {
762  EMAC_ADDR2HIGH_REG = 0;
763  EMAC_ADDR2LOW_REG = 0;
764  }
765 
766  //Configure the third unicast address filter
767  if(j >= 3)
768  {
769  EMAC_ADDR3HIGH_REG = unicastMacAddr[2].w[2] | EMAC_ADDR3HIGH_ADDRESS_ENABLE3;
770  EMAC_ADDR3LOW_REG = unicastMacAddr[2].w[0] | (unicastMacAddr[0].w[2] << 16);
771  }
772  else
773  {
774  EMAC_ADDR3HIGH_REG = 0;
775  EMAC_ADDR3LOW_REG = 0;
776  }
777 
778  //Enable or disable the reception of multicast frames
779  if(acceptMulticast)
780  {
782  }
783  else
784  {
786  }
787 
788  //Successful processing
789  return NO_ERROR;
790 }
791 
792 
793 /**
794  * @brief Adjust MAC configuration parameters for proper operation
795  * @param[in] interface Underlying network interface
796  * @return Error code
797  **/
798 
800 {
801  uint32_t config;
802 
803  //Read current MAC configuration
804  config = EMAC_CONFIG_REG;
805 
806  //10BASE-T or 100BASE-TX operation mode?
807  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
808  {
809  config |= EMAC_CONFIG_EMACFESPEED;
810  }
811  else
812  {
813  config &= ~EMAC_CONFIG_EMACFESPEED;
814  }
815 
816  //Half-duplex or full-duplex mode?
817  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
818  {
819  config |= EMAC_CONFIG_EMACDUPLEX;
820  }
821  else
822  {
823  config &= ~EMAC_CONFIG_EMACDUPLEX;
824  }
825 
826  //Update MAC configuration register
827  EMAC_CONFIG_REG = config;
828 
829  //Successful processing
830  return NO_ERROR;
831 }
832 
833 
834 /**
835  * @brief Write PHY register
836  * @param[in] opcode Access type (2 bits)
837  * @param[in] phyAddr PHY address (5 bits)
838  * @param[in] regAddr Register address (5 bits)
839  * @param[in] data Register value
840  **/
841 
842 void esp32EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
843  uint8_t regAddr, uint16_t data)
844 {
845  uint32_t temp;
846 
847  //Valid opcode?
848  if(opcode == SMI_OPCODE_WRITE)
849  {
850  //Take care not to alter MDC clock configuration
852  //Set up a write operation
854  //PHY address
855  temp |= (phyAddr << 11) & EMAC_MIIADDR_MIIDEV;
856  //Register address
857  temp |= (regAddr << 6) & EMAC_MIIADDR_MIIREG;
858 
859  //Data to be written in the PHY register
861 
862  //Start a write operation
863  EMAC_MIIADDR_REG = temp;
864  //Wait for the write to complete
865  while((EMAC_MIIADDR_REG & EMAC_MIIADDR_MIIBUSY) != 0)
866  {
867  }
868  }
869  else
870  {
871  //The MAC peripheral only supports standard Clause 22 opcodes
872  }
873 }
874 
875 
876 /**
877  * @brief Read PHY register
878  * @param[in] opcode Access type (2 bits)
879  * @param[in] phyAddr PHY address (5 bits)
880  * @param[in] regAddr Register address (5 bits)
881  * @return Register value
882  **/
883 
884 uint16_t esp32EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
885  uint8_t regAddr)
886 {
887  uint16_t data;
888  uint32_t temp;
889 
890  //Valid opcode?
891  if(opcode == SMI_OPCODE_READ)
892  {
893  //Take care not to alter MDC clock configuration
895  //Set up a read operation
896  temp |= EMAC_MIIADDR_MIIBUSY;
897  //PHY address
898  temp |= (phyAddr << 11) & EMAC_MIIADDR_MIIDEV;
899  //Register address
900  temp |= (regAddr << 6) & EMAC_MIIADDR_MIIREG;
901 
902  //Start a read operation
903  EMAC_MIIADDR_REG = temp;
904  //Wait for the read to complete
905  while((EMAC_MIIADDR_REG & EMAC_MIIADDR_MIIBUSY) != 0)
906  {
907  }
908 
909  //Get register value
911  }
912  else
913  {
914  //The MAC peripheral only supports standard Clause 22 opcodes
915  data = 0;
916  }
917 
918  //Return the value of the PHY register
919  return data;
920 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void esp32EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define EMAC_RDES1_RBS1
#define EMAC_ADDR0LOW_REG
#define EMAC_CONFIG_EMACMII
uint8_t opcode
Definition: dns_common.h:188
#define EMAC_ADDR2HIGH_ADDRESS_ENABLE2
int bool_t
Definition: compiler_port.h:53
#define EMAC_ADDR0HIGH_REG
#define netEvent
Definition: net_legacy.h:196
Enhanced RX DMA descriptor.
#define EMAC_MIIADDR_REG
#define EMAC_DMASTATUS_RECV_INT
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define EMAC_DMAOPERATION_MODE_START_STOP_TX
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
#define EMAC_TDES0_OWN
#define EMAC_ADDR1LOW_REG
#define EMAC_DMABUSMODE_SW_RST
#define EMAC_RDES0_ES
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
error_t esp32EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
uint8_t data[]
Definition: ethernet.h:222
#define sleep(delay)
Definition: os_port.h:307
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
#define EMAC_TDES0_IC
#define EMAC_CONFIG_REG
#define ESP32_ETH_RX_BUFFER_COUNT
#define EMAC_DMASTATUS_NORM_INT_SUMM
#define EMAC_MIIADDR_MIICSRCLK
#define EMAC_DMAOPERATION_MODE_TX_STORE_FORWARD
ESP32 Ethernet MAC driver.
#define EMAC_MIIDATA_REG
#define EMAC_FF_PAM
void esp32EthEventHandler(NetInterface *interface)
ESP32 Ethernet MAC event handler.
#define EMAC_MIIADDR_MIIWRITE
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 macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define EMAC_INTMASK_PMTINTMASK
#define FALSE
Definition: os_port.h:46
#define EMAC_RDES1_RCH
#define EMAC_MIIDATA_MII_DATA
#define EMAC_TDES1_TBS1
#define EMAC_EX_PHYINF_CONF_REG
#define EMAC_RDES0_LS
error_t
Error codes.
Definition: error.h:43
error_t esp32EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define EMAC_EX_OSCCLK_CONF_EMAC_OSC_CLK_SEL
#define EMAC_EX_PHYINF_CONF_EMAC_PHY_INTF_SEL_RMII
#define EMAC_ADDR3LOW_REG
#define EMAC_INTMASK_REG
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
__weak_func void esp32EthInitGpio(NetInterface *interface)
GPIO configuration.
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:140
#define NetInterface
Definition: net.h:36
error_t esp32EthReceivePacket(NetInterface *interface)
Receive a packet.
MacAddr addr
MAC address.
Definition: ethernet.h:263
error_t esp32EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define EMAC_ADDR1HIGH_REG
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
uint16_t esp32EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define EMAC_DMAIN_EN_DMAIN_RIE
#define NetTxAncillary
Definition: net_misc.h:36
#define ESP32_ETH_TX_BUFFER_COUNT
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:95
#define EMAC_ADDR2LOW_REG
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 EMAC_EX_CLK_CTRL_REG
void esp32EthTick(NetInterface *interface)
ESP32 Ethernet MAC timer handler.
#define EMAC_MIIADDR_MIIBUSY
#define MIN(a, b)
Definition: os_port.h:63
#define EMAC_EX_OSCCLK_CONF_REG
#define EMAC_TDES0_LS
#define EMAC_DMAOPERATION_MODE_REG
#define rxBuffer
#define EMAC_DMATXPOLLDEMAND_REG
MacAddr
Definition: ethernet.h:195
#define EMAC_TDES0_TCH
#define EMAC_CONFIG_EMACRXOWN
#define EMAC_RDES0_FL
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define ESP32_ETH_IRQ_FLAGS
#define EMAC_DMASTATUS_TRANS_INT
#define EMAC_MIIADDR_MIIREG
#define EMAC_DMAIN_EN_DMAIN_TIE
void IRAM_ATTR esp32EthIrqHandler(void *arg)
ESP32 Ethernet MAC interrupt service routine.
#define EMAC_DMAIN_EN_REG
#define EMAC_DMAOPERATION_MODE_RX_STORE_FORWARD
#define ESP32_ETH_RX_BUFFER_SIZE
#define EMAC_DMABUSMODE_REG
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
void esp32EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define EMAC_MIIADDR_MIICSRCLK_DIV_62
uint8_t n
MAC filter table entry.
Definition: ethernet.h:262
#define EMAC_FC_REG
void esp32EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define EMAC_ADDR3HIGH_ADDRESS_ENABLE3
#define osEnterIsr()
#define EMAC_DMASTATUS_REG
#define EMAC_DMABUSMODE_PROG_BURST_LEN_32
#define EMAC_ADDR2HIGH_REG
#define EMAC_FF_REG
#define EMAC_DMARXPOLLDEMAND_REG
#define EMAC_ADDR1HIGH_ADDRESS_ENABLE1
#define EMAC_DMATXBASEADDR_REG
#define EMAC_TDES0_FS
#define rxDmaDesc
#define EMAC_DMAIN_EN_DMAIN_NISE
#define EMAC_DMARXBASEADDR_REG
#define EMAC_DMASTATUS_TRANS_BUF_UNAVAIL
#define EMAC_CONFIG_EMACRX
#define EMAC_DMABUSMODE_RX_DMA_PBL_32
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define EMAC_DMAOPERATION_MODE_START_STOP_RX
error_t esp32EthInit(NetInterface *interface)
ESP32 Ethernet MAC initialization.
#define EMAC_DMABUSMODE_ALT_DESC_SIZE
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define ESP32_ETH_TX_BUFFER_SIZE
const NicDriver esp32EthDriver
ESP32 Ethernet MAC driver.
Enhanced TX DMA descriptor.
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
#define EMAC_CONFIG_EMACFESPEED
NIC driver.
Definition: nic.h:286
#define EMAC_RDES0_OWN
#define EMAC_CONFIG_EMACTX
#define EMAC_CONFIG_EMACDUPLEX
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define EMAC_DMASTATUS_RECV_BUF_UNAVAIL
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
#define EMAC_INTMASK_LPIINTMASK
Debugging facilities.
#define EMAC_MIIADDR_MIIDEV
#define EMAC_ADDR3HIGH_REG
#define EMAC_EX_CLK_CTRL_EMAC_EXT_OSC_EN
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define EMAC_RDES0_FS
void esp32EthEnableIrq(NetInterface *interface)
Enable interrupts.