esp32_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file esp32_eth_driver.c
3  * @brief ESP32 Ethernet MAC controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "soc/soc.h"
36 #include "soc/dport_reg.h"
37 #include "soc/emac_ex_reg.h"
38 #include "soc/emac_reg_v2.h"
39 #include "driver/periph_ctrl.h"
40 #include "core/net.h"
42 #include "debug.h"
43 
44 //Underlying network interface
45 static NetInterface *nicDriverInterface;
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  //Save underlying network interface
105  nicDriverInterface = interface;
106 
107  //Enable EMAC module
108  periph_module_enable(PERIPH_EMAC_MODULE);
109  //Enable Ethernet MAC clock
110  DPORT_REG_SET_BIT(EMAC_CLK_EN_REG, EMAC_CLK_EN);
111 
112  //GPIO configuration
113  esp32EthInitGpio(interface);
114 
115  //Perform a software reset
116  REG_SET_BIT(EMAC_DMABUSMODE_REG, EMAC_SW_RST);
117  //Wait for the reset to complete
118  while(REG_GET_BIT(EMAC_DMABUSMODE_REG, EMAC_SW_RST))
119  {
120  }
121 
122  //Adjust MDC clock range
123  REG_SET_FIELD(EMAC_GMIIADDR_REG, EMAC_MIICSRCLK, 1);
124 
125  //PHY transceiver initialization
126  error = interface->phyDriver->init(interface);
127  //Failed to initialize PHY transceiver?
128  if(error)
129  return error;
130 
131  //Use default MAC configuration
132  REG_WRITE(EMAC_GMACCONFIG_REG, 0);
133  REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACMII);
134  REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACRXOWN);
135 
136  //Set the MAC address of the station
137  REG_WRITE(EMAC_ADDR0HIGH_REG, interface->macAddr.w[2]);
138  REG_WRITE(EMAC_ADDR0LOW_REG, interface->macAddr.w[0] | (interface->macAddr.w[1] << 16));
139 
140  //The MAC supports 3 additional addresses for unicast perfect filtering
141  REG_WRITE(EMAC_ADDR1HIGH_REG, 0);
142  REG_WRITE(EMAC_ADDR1LOW_REG, 0);
143  REG_WRITE(EMAC_ADDR2HIGH_REG, 0);
144  REG_WRITE(EMAC_ADDR2LOW_REG, 0);
145  REG_WRITE(EMAC_ADDR3HIGH_REG, 0);
146  REG_WRITE(EMAC_ADDR3LOW_REG, 0);
147 
148  //Configure the receive filter
149  REG_WRITE(EMAC_GMACFF_REG, 0);
150  //Disable flow control
151  REG_WRITE(EMAC_GMACFC_REG, 0);
152 
153  //Enable store and forward mode
154  REG_WRITE(EMAC_DMAOPERATION_MODE_REG, 0);
155  REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_RX_STORE_FORWARD);
156  REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_TX_STR_FWD);
157 
158  //Configure DMA bus mode
159  REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_RX_DMA_PBL, 1);
160  REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_PROG_BURST_LEN, 1);
161  REG_SET_BIT(EMAC_DMABUSMODE_REG, EMAC_ALT_DESC_SIZE);
162 
163  //Initialize DMA descriptor lists
164  esp32EthInitDmaDesc(interface);
165 
166  //Disable MAC interrupts
167  REG_SET_BIT(EMAC_INTMASK_REG, EMAC_LPIINTMASK);
168  REG_SET_BIT(EMAC_INTMASK_REG, EMAC_PMTINTMASK);
169 
170  //Enable the desired DMA interrupts
171  REG_WRITE(EMAC_DMAIN_EN_REG, EMAC_DMAIN_NISE_M | EMAC_DMAIN_RIE_M |
172  EMAC_DMAIN_TIE_M);
173 
174  //Register interrupt handler
175  esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, esp32EthIrqHandler, NULL, NULL);
176 
177  //Enable MAC transmission and reception
178  REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACTX);
179  REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACRX);
180 
181  //Enable DMA transmission and reception
182  REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND);
183  REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RX);
184 
185  //Accept any packets from the upper layer
186  osSetEvent(&interface->nicTxEvent);
187 
188  //Successful initialization
189  return NO_ERROR;
190 }
191 
192 
193 //ESP32-Ethernet-Kit, ESP32-EVB or ESP32-GATEWAY evaluation board?
194 #if defined(ESP32_ETHERNET_KIT) || defined(ESP32_EVB) || defined(ESP32_GATEWAY)
195 
196 /**
197  * @brief GPIO configuration
198  * @param[in] interface Underlying network interface
199  **/
200 
201 void esp32EthInitGpio(NetInterface *interface)
202 {
203 //ESP32-Ethernet-Kit?
204 #if defined(ESP32_ETHERNET_KIT)
205  //Select RMII interface mode
206  REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL,
207  EMAC_EX_PHY_INTF_RMII);
208 
209  //Select clock source
210  REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_EXT_OSC_EN);
211  //Enable clock
212  REG_SET_BIT(EMAC_EX_OSCCLK_CONF_REG, EMAC_EX_OSC_CLK_SEL);
213 
214  //Configure RMII CLK (GPIO0)
215  gpio_set_direction(0, GPIO_MODE_INPUT);
216 
217  //Configure TXD0 (GPIO19)
218  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
219  //Configure TX_EN (GPIO21)
220  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
221  //Configure TXD1 (GPIO22)
222  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
223 
224  //Configure RXD0 (GPIO25)
225  gpio_set_direction(25, GPIO_MODE_INPUT);
226  //Configure RXD1 (GPIO26)
227  gpio_set_direction(26, GPIO_MODE_INPUT);
228  //Configure CRS_DRV (GPIO27)
229  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
230 
231  //Configure MDC (GPIO23)
232  gpio_matrix_out(23, EMAC_MDC_O_IDX, 0, 0);
233 
234  //Configure MDIO (GPIO18)
235  gpio_matrix_out(18, EMAC_MDO_O_IDX, 0, 0);
236  gpio_matrix_in(18, EMAC_MDI_I_IDX, 0);
237 
238  //Configure PHY_RST (GPIO5)
239  gpio_pad_select_gpio(5);
240  gpio_set_direction(5, GPIO_MODE_OUTPUT);
241 
242  //Reset PHY transceiver
243  gpio_set_level(5, 0);
244  sleep(10);
245  gpio_set_level(5, 1);
246  sleep(10);
247 
248 //ESP32-EVB or ESP32-GATEWAY evaluation board?
249 #elif defined(ESP32_EVB) || defined(ESP32_GATEWAY)
250  //Select RMII interface mode
251  REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL,
252  EMAC_EX_PHY_INTF_RMII);
253 
254  //Select clock source
255  REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_EXT_OSC_EN);
256  //Enable clock
257  REG_SET_BIT(EMAC_EX_OSCCLK_CONF_REG, EMAC_EX_OSC_CLK_SEL);
258 
259  //Configure RMII CLK (GPIO0)
260  gpio_set_direction(0, GPIO_MODE_INPUT);
261 
262  //Configure TXD0 (GPIO19)
263  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
264  //Configure TX_EN (GPIO21)
265  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
266  //Configure TXD1 (GPIO22)
267  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
268 
269  //Configure RXD0 (GPIO25)
270  gpio_set_direction(25, GPIO_MODE_INPUT);
271  //Configure RXD1 (GPIO26)
272  gpio_set_direction(26, GPIO_MODE_INPUT);
273  //Configure CRS_DRV (GPIO27)
274  PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
275 
276  //Configure MDC (GPIO23)
277  gpio_matrix_out(23, EMAC_MDC_O_IDX, 0, 0);
278 
279  //Configure MDIO (GPIO18)
280  gpio_matrix_out(18, EMAC_MDO_O_IDX, 0, 0);
281  gpio_matrix_in(18, EMAC_MDI_I_IDX, 0);
282 #endif
283 }
284 
285 #endif
286 
287 
288 /**
289  * @brief Initialize DMA descriptor lists
290  * @param[in] interface Underlying network interface
291  **/
292 
294 {
295  uint_t i;
296 
297  //Initialize TX DMA descriptor list
298  for(i = 0; i < ESP32_ETH_TX_BUFFER_COUNT; i++)
299  {
300  //Use chain structure rather than ring structure
302  //Initialize transmit buffer size
303  txDmaDesc[i].tdes1 = 0;
304  //Transmit buffer address
305  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
306  //Next descriptor address
307  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
308  //Reserved fields
309  txDmaDesc[i].tdes4 = 0;
310  txDmaDesc[i].tdes5 = 0;
311  //Transmit frame time stamp
312  txDmaDesc[i].tdes6 = 0;
313  txDmaDesc[i].tdes7 = 0;
314  }
315 
316  //The last descriptor is chained to the first entry
317  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
318  //Point to the very first descriptor
319  txCurDmaDesc = &txDmaDesc[0];
320 
321  //Initialize RX DMA descriptor list
322  for(i = 0; i < ESP32_ETH_RX_BUFFER_COUNT; i++)
323  {
324  //The descriptor is initially owned by the DMA
325  rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
326  //Use chain structure rather than ring structure
328  //Receive buffer address
329  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
330  //Next descriptor address
331  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
332  //Extended status
333  rxDmaDesc[i].rdes4 = 0;
334  //Reserved field
335  rxDmaDesc[i].rdes5 = 0;
336  //Receive frame time stamp
337  rxDmaDesc[i].rdes6 = 0;
338  rxDmaDesc[i].rdes7 = 0;
339  }
340 
341  //The last descriptor is chained to the first entry
342  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
343  //Point to the very first descriptor
344  rxCurDmaDesc = &rxDmaDesc[0];
345 
346  //Start location of the TX descriptor list
347  REG_WRITE(EMAC_DMATXBASEADDR_REG, (uint32_t) txDmaDesc);
348  //Start location of the RX descriptor list
349  REG_WRITE(EMAC_DMARXBASEADDR_REG, (uint32_t) rxDmaDesc);
350 }
351 
352 
353 /**
354  * @brief ESP32 Ethernet MAC timer handler
355  *
356  * This routine is periodically called by the TCP/IP stack to
357  * handle periodic operations such as polling the link state
358  *
359  * @param[in] interface Underlying network interface
360  **/
361 
362 void esp32EthTick(NetInterface *interface)
363 {
364  //Handle periodic operations
365  interface->phyDriver->tick(interface);
366 }
367 
368 
369 /**
370  * @brief Enable interrupts
371  * @param[in] interface Underlying network interface
372  **/
373 
375 {
376  //Enable Ethernet PHY interrupts
377  interface->phyDriver->enableIrq(interface);
378 }
379 
380 
381 /**
382  * @brief Disable interrupts
383  * @param[in] interface Underlying network interface
384  **/
385 
387 {
388  //Disable Ethernet PHY interrupts
389  interface->phyDriver->disableIrq(interface);
390 }
391 
392 
393 /**
394  * @brief ESP32 Ethernet MAC interrupt service routine
395  * @param[in] arg Unused parameter
396  **/
397 
398 void IRAM_ATTR esp32EthIrqHandler(void *arg)
399 {
400  bool_t flag;
401  uint32_t status;
402 
403  //Interrupt service routine prologue
404  osEnterIsr();
405 
406  //This flag will be set if a higher priority task must be woken
407  flag = FALSE;
408 
409  //Read DMA status register
410  status = REG_READ(EMAC_DMASTATUS_REG);
411 
412  //A packet has been transmitted?
413  if(status & EMAC_TRANS_INT_M)
414  {
415  //Clear TI interrupt flag
416  REG_WRITE(EMAC_DMASTATUS_REG, EMAC_TRANS_INT_M);
417 
418  //Check whether the TX buffer is available for writing
419  if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
420  {
421  //Notify the TCP/IP stack that the transmitter is ready to send
422  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
423  }
424  }
425 
426  //A packet has been received?
427  if(status & EMAC_RECV_INT_M)
428  {
429  //Disable RIE interrupt
430  REG_CLR_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RIE);
431 
432  //Set event flag
433  nicDriverInterface->nicEvent = TRUE;
434  //Notify the TCP/IP stack of the event
435  flag |= osSetEventFromIsr(&netEvent);
436  }
437 
438  //Clear NIS interrupt flag
439  REG_WRITE(EMAC_DMASTATUS_REG, EMAC_NORM_INT_SUMM_M);
440 
441  //Interrupt service routine epilogue
442  osExitIsr(flag);
443 }
444 
445 
446 /**
447  * @brief ESP32 Ethernet MAC event handler
448  * @param[in] interface Underlying network interface
449  **/
450 
452 {
453  error_t error;
454 
455  //Packet received?
456  if(REG_GET_BIT(EMAC_DMASTATUS_REG, EMAC_RECV_INT))
457  {
458  //Clear interrupt flag
459  REG_WRITE(EMAC_DMASTATUS_REG, EMAC_RECV_INT_M);
460 
461  //Process all pending packets
462  do
463  {
464  //Read incoming packet
465  error = esp32EthReceivePacket(interface);
466 
467  //No more data in the receive buffer?
468  } while(error != ERROR_BUFFER_EMPTY);
469  }
470 
471  //Re-enable DMA interrupts
472  REG_WRITE(EMAC_DMAIN_EN_REG, EMAC_DMAIN_NISE_M | EMAC_DMAIN_RIE_M |
473  EMAC_DMAIN_TIE_M);
474 }
475 
476 
477 /**
478  * @brief Send a packet
479  * @param[in] interface Underlying network interface
480  * @param[in] buffer Multi-part buffer containing the data to send
481  * @param[in] offset Offset to the first data byte
482  * @return Error code
483  **/
484 
486  const NetBuffer *buffer, size_t offset)
487 {
488  size_t length;
489 
490  //Retrieve the length of the packet
491  length = netBufferGetLength(buffer) - offset;
492 
493  //Check the frame length
495  {
496  //The transmitter can accept another packet
497  osSetEvent(&interface->nicTxEvent);
498  //Report an error
499  return ERROR_INVALID_LENGTH;
500  }
501 
502  //Make sure the current buffer is available for writing
503  if(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN)
504  return ERROR_FAILURE;
505 
506  //Copy user data to the transmit buffer
507  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
508 
509  //Write the number of bytes to send
510  txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
511  //Set LS and FS flags as the data fits in a single buffer
512  txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
513  //Give the ownership of the descriptor to the DMA
514  txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
515 
516  //Clear TBUS flag to resume processing
517  REG_WRITE(EMAC_DMASTATUS_REG, EMAC_TRANS_BUF_UNAVAIL_M);
518  //Instruct the DMA to poll the transmit descriptor list
519  REG_WRITE(EMAC_DMATXPOLLDEMAND_REG, 0);
520 
521  //Point to the next descriptor in the list
522  txCurDmaDesc = (Esp32EthTxDmaDesc *) txCurDmaDesc->tdes3;
523 
524  //Check whether the next buffer is available for writing
525  if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
526  {
527  //The transmitter can accept another packet
528  osSetEvent(&interface->nicTxEvent);
529  }
530 
531  //Data successfully written
532  return NO_ERROR;
533 }
534 
535 
536 /**
537  * @brief Receive a packet
538  * @param[in] interface Underlying network interface
539  * @return Error code
540  **/
541 
543 {
544  error_t error;
545  size_t n;
546 
547  //The current buffer is available for reading?
548  if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN))
549  {
550  //FS and LS flags should be set
551  if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) && (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS))
552  {
553  //Make sure no error occurred
554  if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_ES))
555  {
556  //Retrieve the length of the frame
557  n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
558  //Limit the number of data to read
560 
561  //Pass the packet to the upper layer
562  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
563 
564  //Valid packet received
565  error = NO_ERROR;
566  }
567  else
568  {
569  //The received packet contains an error
570  error = ERROR_INVALID_PACKET;
571  }
572  }
573  else
574  {
575  //The packet is not valid
576  error = ERROR_INVALID_PACKET;
577  }
578 
579  //Give the ownership of the descriptor back to the DMA
580  rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
581  //Point to the next descriptor in the list
582  rxCurDmaDesc = (Esp32EthRxDmaDesc *) rxCurDmaDesc->rdes3;
583  }
584  else
585  {
586  //No more data in the receive buffer
587  error = ERROR_BUFFER_EMPTY;
588  }
589 
590  //Clear RBUS flag to resume processing
591  REG_WRITE(EMAC_DMASTATUS_REG, EMAC_RECV_BUF_UNAVAIL_M);
592  //Instruct the DMA to poll the receive descriptor list
593  REG_WRITE(EMAC_DMARXPOLLDEMAND_REG, 0);
594 
595  //Return status code
596  return error;
597 }
598 
599 
600 /**
601  * @brief Configure MAC address filtering
602  * @param[in] interface Underlying network interface
603  * @return Error code
604  **/
605 
607 {
608  uint_t i;
609  uint_t j;
610  bool_t acceptMulticast;
611  MacAddr unicastMacAddr[3];
612  MacFilterEntry *entry;
613 
614  //Debug message
615  TRACE_DEBUG("Updating MAC filter...\r\n");
616 
617  //Set the MAC address of the station
618  REG_WRITE(EMAC_ADDR0HIGH_REG, interface->macAddr.w[2]);
619  REG_WRITE(EMAC_ADDR0LOW_REG, interface->macAddr.w[0] | (interface->macAddr.w[1] << 16));
620 
621  //The MAC supports 3 additional addresses for unicast perfect filtering
622  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
623  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
624  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
625 
626  //This flag will be set if multicast addresses should be accepted
627  acceptMulticast = FALSE;
628 
629  //The MAC address filter contains the list of MAC addresses to accept
630  //when receiving an Ethernet frame
631  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
632  {
633  //Point to the current entry
634  entry = &interface->macAddrFilter[i];
635 
636  //Valid entry?
637  if(entry->refCount > 0)
638  {
639  //Multicast address?
640  if(macIsMulticastAddr(&entry->addr))
641  {
642  //Accept multicast addresses
643  acceptMulticast = TRUE;
644  }
645  else
646  {
647  //Up to 3 additional MAC addresses can be specified
648  if(j < 3)
649  {
650  //Save the unicast address
651  unicastMacAddr[j++] = entry->addr;
652  }
653  }
654  }
655  }
656 
657  //Configure the first unicast address filter
658  if(j >= 1)
659  {
660  REG_WRITE(EMAC_ADDR1HIGH_REG, unicastMacAddr[0].w[2] | EMAC_ADDRESS_ENABLE1_M);
661  REG_WRITE(EMAC_ADDR1LOW_REG, unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16));
662  }
663  else
664  {
665  REG_WRITE(EMAC_ADDR1HIGH_REG, 0);
666  REG_WRITE(EMAC_ADDR1LOW_REG, 0);
667  }
668 
669  //Configure the second unicast address filter
670  if(j >= 2)
671  {
672  REG_WRITE(EMAC_ADDR2HIGH_REG, unicastMacAddr[1].w[2] | EMAC_ADDRESS_ENABLE2_M);
673  REG_WRITE(EMAC_ADDR2LOW_REG, unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16));
674  }
675  else
676  {
677  REG_WRITE(EMAC_ADDR2HIGH_REG, 0);
678  REG_WRITE(EMAC_ADDR2LOW_REG, 0);
679  }
680 
681  //Configure the third unicast address filter
682  if(j >= 3)
683  {
684  REG_WRITE(EMAC_ADDR3HIGH_REG, unicastMacAddr[2].w[2] | EMAC_ADDRESS_ENABLE3_M);
685  REG_WRITE(EMAC_ADDR3LOW_REG, unicastMacAddr[2].w[0] | (unicastMacAddr[0].w[2] << 16));
686  }
687  else
688  {
689  REG_WRITE(EMAC_ADDR3HIGH_REG, 0);
690  REG_WRITE(EMAC_ADDR3LOW_REG, 0);
691  }
692 
693  //Enable the reception of multicast frames if necessary
694  if(acceptMulticast)
695  {
696  REG_SET_BIT(EMAC_GMACFF_REG, EMAC_PAM);
697  }
698  else
699  {
700  REG_CLR_BIT(EMAC_GMACFF_REG, EMAC_PAM);
701  }
702 
703  //Successful processing
704  return NO_ERROR;
705 }
706 
707 
708 /**
709  * @brief Adjust MAC configuration parameters for proper operation
710  * @param[in] interface Underlying network interface
711  * @return Error code
712  **/
713 
715 {
716  uint32_t config;
717 
718  //Read current MAC configuration
719  config = REG_READ(EMAC_GMACCONFIG_REG);
720 
721  //10BASE-T or 100BASE-TX operation mode?
722  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
723  config |= EMAC_EMACFESPEED_M;
724  else
725  config &= ~EMAC_EMACFESPEED_M;
726 
727  //Half-duplex or full-duplex mode?
728  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
729  config |= EMAC_EMACDUPLEX_M;
730  else
731  config &= ~EMAC_EMACDUPLEX_M;
732 
733  //Update MAC configuration register
734  REG_WRITE(EMAC_GMACCONFIG_REG, config);
735 
736  //Successful processing
737  return NO_ERROR;
738 }
739 
740 
741 /**
742  * @brief Write PHY register
743  * @param[in] opcode Access type (2 bits)
744  * @param[in] phyAddr PHY address (5 bits)
745  * @param[in] regAddr Register address (5 bits)
746  * @param[in] data Register value
747  **/
748 
749 void esp32EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
750  uint8_t regAddr, uint16_t data)
751 {
752  uint32_t temp;
753 
754  //Valid opcode?
755  if(opcode == SMI_OPCODE_WRITE)
756  {
757  //Take care not to alter MDC clock configuration
758  temp = REG_READ(EMAC_GMIIADDR_REG) & EMAC_MIICSRCLK_M;
759  //Set up a write operation
760  temp |= EMAC_MIIWRITE_M | EMAC_MIIBUSY_M;
761  //PHY address
762  temp |= (phyAddr << EMAC_MIIDEV_S) & EMAC_MIIDEV_M;
763  //Register address
764  temp |= (regAddr << EMAC_MIIREG_S) & EMAC_MIIREG_M;
765 
766  //Data to be written in the PHY register
767  REG_WRITE(EMAC_MIIDATA_REG, data);
768 
769  //Start a write operation
770  REG_WRITE(EMAC_GMIIADDR_REG, temp);
771  //Wait for the write to complete
772  while(REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY))
773  {
774  }
775  }
776  else
777  {
778  //The MAC peripheral only supports standard Clause 22 opcodes
779  }
780 }
781 
782 
783 /**
784  * @brief Read PHY register
785  * @param[in] opcode Access type (2 bits)
786  * @param[in] phyAddr PHY address (5 bits)
787  * @param[in] regAddr Register address (5 bits)
788  * @return Register value
789  **/
790 
791 uint16_t esp32EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
792  uint8_t regAddr)
793 {
794  uint16_t data;
795  uint32_t temp;
796 
797  //Valid opcode?
798  if(opcode == SMI_OPCODE_READ)
799  {
800  //Take care not to alter MDC clock configuration
801  temp = REG_READ(EMAC_GMIIADDR_REG) & EMAC_MIICSRCLK_M;
802  //Set up a read operation
803  temp |= EMAC_MIIBUSY_M;
804  //PHY address
805  temp |= (phyAddr << EMAC_MIIDEV_S) & EMAC_MIIDEV_M;
806  //Register address
807  temp |= (regAddr << EMAC_MIIREG_S) & EMAC_MIIREG_M;
808 
809  //Start a read operation
810  REG_WRITE(EMAC_GMIIADDR_REG, temp);
811  //Wait for the read to complete
812  while(REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY))
813  {
814  }
815 
816  //Get register value
817  data = REG_READ(EMAC_MIIDATA_REG);
818  }
819  else
820  {
821  //The MAC peripheral only supports standard Clause 22 opcodes
822  data = 0;
823  }
824 
825  //Return the value of the PHY register
826  return data;
827 }
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.
void esp32EthInitGpio(NetInterface *interface)
uint8_t length
Definition: dtls_misc.h:149
#define EMAC_TDES0_OWN
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
Enhanced RX DMA descriptor.
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:672
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define TRUE
Definition: os_port.h:50
error_t esp32EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define EMAC_TDES0_TCH
#define sleep(delay)
Definition: os_port.h:131
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
#define ESP32_ETH_RX_BUFFER_COUNT
#define EMAC_RDES0_FL
ESP32 Ethernet MAC controller.
void esp32EthEventHandler(NetInterface *interface)
ESP32 Ethernet MAC event handler.
uint16_t w[3]
Definition: ethernet.h:166
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:110
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:62
#define EMAC_RDES0_OWN
#define EMAC_TDES0_IC
#define FALSE
Definition: os_port.h:46
#define EMAC_TDES0_FS
error_t
Error codes.
Definition: error.h:42
error_t esp32EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
Generic error code.
Definition: error.h:45
#define txBuffer
error_t esp32EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define NetInterface
Definition: net.h:36
error_t esp32EthReceivePacket(NetInterface *interface)
Receive a packet.
MacAddr addr
MAC address.
Definition: ethernet.h:222
#define EMAC_RDES0_FS
uint16_t esp32EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define ESP32_ETH_TX_BUFFER_COUNT
OsEvent netEvent
Definition: net.c:77
#define SMI_OPCODE_READ
Definition: nic.h:63
#define TRACE_INFO(...)
Definition: debug.h:94
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
void esp32EthTick(NetInterface *interface)
ESP32 Ethernet MAC timer handler.
#define MIN(a, b)
Definition: os_port.h:62
#define EMAC_TDES0_LS
#define rxBuffer
#define EMAC_RDES0_LS
#define EMAC_TDES1_TBS1
#define TRACE_DEBUG(...)
Definition: debug.h:106
void IRAM_ATTR esp32EthIrqHandler(void *arg)
ESP32 Ethernet MAC interrupt service routine.
#define ESP32_ETH_RX_BUFFER_SIZE
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
void esp32EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
uint8_t n
#define EMAC_RDES1_RCH
MAC filter table entry.
Definition: ethernet.h:220
void esp32EthDisableIrq(NetInterface *interface)
Disable interrupts.
#define osEnterIsr()
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t esp32EthInit(NetInterface *interface)
ESP32 Ethernet MAC initialization.
#define txDmaDesc
#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:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
NIC driver.
Definition: nic.h:179
#define EMAC_RDES0_ES
#define EMAC_RDES1_RBS1
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
__start_packed struct @108 MacAddr
MAC address.
Ethernet interface.
Definition: nic.h:79
void esp32EthEnableIrq(NetInterface *interface)
Enable interrupts.