ESP32 EMAC receive not working

owenthewizard
Posts: 5
Joined: Fri Apr 19, 2024 8:08 pm

ESP32 EMAC receive not working

Postby owenthewizard » Fri Apr 19, 2024 8:42 pm

I'm trying to use the ESP32 Ethernet MAC receive function, but it always sets the buffer length to zero, and doesn't copy any data. I assume I'm using it incorrectly. Is there some documentation on how to use is it?
  1. #include <inttypes.h>
  2. #include "esp_event.h"
  3. #include "esp_log.h"
  4. #include "esp_eth.h"
  5.  
  6. static const char *TAG = "ethtest";
  7.  
  8. /** Event handler for Ethernet events */
  9. static void eth_event_handler(void *arg, esp_event_base_t event_base,
  10.                               int32_t event_id, void *event_data)
  11. {
  12.     uint8_t mac_addr[6] = {0};
  13.     /* we can get the ethernet driver handle from event data */
  14.     esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
  15.  
  16.     switch (event_id) {
  17.     case ETHERNET_EVENT_CONNECTED:
  18.         esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
  19.         ESP_LOGI(TAG, "Ethernet Link Up");
  20.         ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
  21.                     mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  22.         break;
  23.     case ETHERNET_EVENT_DISCONNECTED:
  24.         ESP_LOGI(TAG, "Ethernet Link Down");
  25.         break;
  26.     case ETHERNET_EVENT_START:
  27.         ESP_LOGI(TAG, "Ethernet Started");
  28.         break;
  29.     case ETHERNET_EVENT_STOP:
  30.         ESP_LOGI(TAG, "Ethernet Stopped");
  31.         break;
  32.     default:
  33.         break;
  34.     }
  35. }
  36.  
  37. void app_main(void)
  38. {
  39.     printf("Hello world!\n");
  40.     eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
  41.  
  42.     eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
  43.     esp32_emac_config.smi_mdc_gpio_num = 23;
  44.     esp32_emac_config.smi_mdio_gpio_num = 18;
  45.     esp32_emac_config.interface = EMAC_DATA_INTERFACE_RMII;
  46.     esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
  47.     esp32_emac_config.clock_config.rmii.clock_gpio = 0;
  48.     esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
  49.  
  50.     eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
  51.     phy_config.phy_addr = 1;
  52.     phy_config.reset_gpio_num = 16;
  53.     esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config);
  54.  
  55.     esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
  56.     esp_eth_handle_t eth_handle = NULL;
  57.     esp_eth_driver_install(&config, &eth_handle);
  58.  
  59.     esp_event_loop_create_default();
  60.     esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL);
  61.  
  62.     esp_eth_start(eth_handle);
  63.  
  64.     while (1) {
  65.         uint32_t len = 1522;
  66.         uint8_t *buf = malloc(len);
  67.         if (!buf) {
  68.             ESP_LOGE(TAG, "buf allocation failed!");
  69.             esp_restart();
  70.         }
  71.  
  72.         int ret = (*mac).receive(mac, buf, &len);
  73.         ESP_LOGW(TAG, "receive status: %d", ret);
  74.         ESP_LOGW(TAG, "buf len after allocation: %ld", len);
  75.         free(buf);
  76.     }
  77. }
W (3739) ethtest: receive status: 0
W (3739) ethtest: buf len after allocation: 0

douglasbaird
Posts: 3
Joined: Sun Apr 21, 2024 6:25 pm

Re: ESP32 EMAC receive not working

Postby douglasbaird » Sun Apr 21, 2024 6:31 pm

Hello,
I think the issue might be related to the buffer size you're providing. In your code, you're allocating a buffer with a fixed size of 1522 bytes using malloc(len). However, the len parameter should be initialized with the maximum buffer size you allocate and pass it to the mac.receive() function. After the function call, the len parameter will be updated with the actual received packet length.


To fix the issue, you can modify your code as follows:

Code: Select all

c
while (1) {
    uint32_t len = 1522;
    uint8_t *buf = malloc(len);
    if (!buf) {
        ESP_LOGE(TAG, "buf allocation failed!");
        esp_restart();
    }

    int ret = (*mac).receive(mac, buf, &len);
    if (ret == 0) {
        ESP_LOGI(TAG, "Received packet of length: %ld", len);
        // Process the received packet here
    } else {
        ESP_LOGE(TAG, "Receive error: %d", ret);
    }

    free(buf);
}
Last edited by douglasbaird on Wed Apr 24, 2024 7:02 am, edited 1 time in total.

owenthewizard
Posts: 5
Joined: Fri Apr 19, 2024 8:08 pm

Re: ESP32 EMAC receive not working

Postby owenthewizard » Mon Apr 22, 2024 7:01 am

douglasbaird wrote:
Sun Apr 21, 2024 6:31 pm
Hello,
I think the issue might be related to the buffer size you're providing. In your code, you're allocating a buffer with a fixed size of 1522 bytes using malloc(len). However, the len parameter should be initialized with the maximum buffer size you allocate and pass it to the mac.receive() function. After the function call, the len parameter will be updated with the actual received packet length.
Hello and thank you for the reply. I'm afraid I don't understand, isn't that what I'm doing already?
1. Allocate len bytes
2. Call receive(mac, buf, &len)
3. len is now set to the actual received frame size, which has been copied to buf.

I fail to see the difference in your calling of receive vs mine.

Edit: Just to confirm, your code gives me the same result:
I (6759) ethtest: Received packet of length: 0

ESP_ondrej
Posts: 181
Joined: Fri May 07, 2021 10:35 am

Re: ESP32 EMAC receive not working

Postby ESP_ondrej » Wed Apr 24, 2024 12:57 pm

Hi, you are using the driver incorrectly. If your goal is to have your "custom" function to process received Ethernet frames, you need to register a call back function using `esp_eth_update_input_path`.

owenthewizard
Posts: 5
Joined: Fri Apr 19, 2024 8:08 pm

Re: ESP32 EMAC receive not working

Postby owenthewizard » Wed Apr 24, 2024 2:41 pm

ESP_ondrej wrote:
Wed Apr 24, 2024 12:57 pm
Hi, you are using the driver incorrectly. If your goal is to have your "custom" function to process received Ethernet frames, you need to register a call back function using `esp_eth_update_input_path`.
Thank you for your time and attention! I am grateful.
Would it be possible to document correct usage?

ESP_ondrej
Posts: 181
Joined: Fri May 07, 2021 10:35 am

Re: ESP32 EMAC receive not working

Postby ESP_ondrej » Thu Apr 25, 2024 8:17 am

It's pretty straight forward, just register your callback function to the Ethernet handler.
See examples:
https://github.com/espressif/esp-idf/bl ... fer.c#L300
https://github.com/espressif/esp-idf/bl ... mac.c#L109

owenthewizard
Posts: 5
Joined: Fri Apr 19, 2024 8:08 pm

Re: ESP32 EMAC receive not working

Postby owenthewizard » Thu Apr 25, 2024 4:59 pm

ESP_ondrej wrote:
Thu Apr 25, 2024 8:17 am
It's pretty straight forward, just register your callback function to the Ethernet handler.
See examples:
https://github.com/espressif/esp-idf/bl ... fer.c#L300
https://github.com/espressif/esp-idf/bl ... mac.c#L109
Sorry, I meant if there is any documentation on correct usage of (*mac).receive(mac, buf, &len).

ESP_ondrej
Posts: 181
Joined: Fri May 07, 2021 10:35 am

Re: ESP32 EMAC receive not working

Postby ESP_ondrej » Fri Apr 26, 2024 7:14 am

Why you don't want to use callback? Using `mac->receive` is not designed to be called from user code.

owenthewizard
Posts: 5
Joined: Fri Apr 19, 2024 8:08 pm

Re: ESP32 EMAC receive not working

Postby owenthewizard » Fri Apr 26, 2024 2:44 pm

ESP_ondrej wrote:
Fri Apr 26, 2024 7:14 am
Why you don't want to use callback? Using `mac->receive` is not designed to be called from user code.
Because I only need to capture the first frame.

ESP_ondrej
Posts: 181
Joined: Fri May 07, 2021 10:35 am

Re: ESP32 EMAC receive not working

Postby ESP_ondrej » Mon Apr 29, 2024 7:06 am

Ethernet driver always initializes the Rx task from which is the callback called. Therefore, you don't save any resources if you use `mac->receive` function directly. Just use the callback. If you don't need the Ethernet after receiving your frame, you can stop it and de-initialize it.

Who is online

Users browsing this forum: DreadNaught, Google [Bot], rr0x1958 and 70 guests