arduino-esp32 icon indicating copy to clipboard operation
arduino-esp32 copied to clipboard

insufficient TX buffer size

Open folkertvanheusden opened this issue 1 year ago • 5 comments

Board

WT-ETH01

Device Description

ESP32 with Ethernet on board

Hardware Configuration

There's an SD-card reader connected:

#define SD_MISO     2       // SD-Card
#define SD_MOSI    15       // SD-Card
#define SD_SCLK    14       // SD-Card
#define SD_CS      12       // SD-Card

Version

other

IDE Name

platformio

Operating System

linux

Flash frequency

40

PSRAM enabled

no

Upload speed

115200

Description

Hi,

With lots of network-traffic, the WT-ETH01 ESP32 module goes into a loop where it only prints "esp.emac: emac_esp32_transmit(229): insufficient TX buffer size" and never returns to the main code.

I googled it and found this: https://github.com/espressif/esp-idf/issues/12037 to be exact: https://github.com/espressif/esp-idf/issues/12037#issuecomment-1685693130

Is this something that should be implemented in the Arduino32 code? Or is this platformio-specific?

Sketch

https://github.com/folkertvanheusden/iESP/tree/Ethernet

No, that is not a minimal sketch. But please check the URL mentioned: someone already found the solution.

Debug Message

E (851778) esp.emac: emac_esp32_transmit(229): insufficient TX buffer size

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • [X] I confirm I have checked existing issues, online documentation and Troubleshooting guide.

folkertvanheusden avatar Feb 13 '24 22:02 folkertvanheusden

Are you suggesting to enable CONFIG_ETH_TRANSMIT_MUTEX ? @P-R-O-C-H-Y can you check what is the status in the lib-builder?

me-no-dev avatar Feb 14 '24 08:02 me-no-dev

Yes, that is correct.

On Wed, Feb 14, 2024 at 9:30 AM Me No Dev @.***> wrote:

Are you suggesting to enable CONFIG_ETH_TRANSMIT_MUTEX ? @P-R-O-C-H-Y https://github.com/P-R-O-C-H-Y can you check what is the status in the lib-builder?

— Reply to this email directly, view it on GitHub https://github.com/espressif/arduino-esp32/issues/9247#issuecomment-1943284972, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUN5IWZHPCQVCSHMCV55223YTRYYBAVCNFSM6AAAAABDHJJDACVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNBTGI4DIOJXGI . You are receiving this because you authored the thread.Message ID: @.***>

folkertvanheusden avatar Feb 14 '24 08:02 folkertvanheusden

Are you suggesting to enable CONFIG_ETH_TRANSMIT_MUTEX ? @P-R-O-C-H-Y can you check what is the status in the lib-builder?

@me-no-dev In lib-builder we only set SPIs for ETH:

CONFIG_ETH_SPI_ETHERNET_DM9051=y
CONFIG_ETH_SPI_ETHERNET_W5500=y
CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL=y

P-R-O-C-H-Y avatar Feb 14 '24 08:02 P-R-O-C-H-Y

What could be the disadvantage of setting this option?

Jason2866 avatar Feb 14 '24 13:02 Jason2866

I have no idea. In fact I'm surprised it is not on by default. Well unless you run the ESP32 in single-threading-mode, then I guess that a few cycles here and there may be saved.

Trying to rebuild lib-builder myself but with that suddenly most Arduino & wifi related things no longer compile.

On Wed, Feb 14, 2024 at 2:00 PM Jason2866 @.***> wrote:

What could be the disadvantage of setting this option?

— Reply to this email directly, view it on GitHub https://github.com/espressif/arduino-esp32/issues/9247#issuecomment-1943723468, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUN5IW47MRPYAIRAHJ77OMTYTSYOTAVCNFSM6AAAAABDHJJDACVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNBTG4ZDGNBWHA . You are receiving this because you authored the thread.Message ID: @.***>

folkertvanheusden avatar Feb 14 '24 13:02 folkertvanheusden

Apparently it is not only the CONFIG_ETH_TRANSMIT_MUTEX: I backported the mutex-changes to v4.4 but then I still get "insufficient TX buffer size".

diff --git a/components/esp_eth/src/esp_eth.c b/components/esp_eth/src/esp_eth.c
index f6e7526cc0..3a3afcbd52 100644
--- a/components/esp_eth/src/esp_eth.c
+++ b/components/esp_eth/src/esp_eth.c
@@ -18,6 +18,8 @@
 
 static const char *TAG = "esp_eth";
 
+#define ESP_ETH_TX_TIMEOUT_MS   250
+
 ESP_EVENT_DEFINE_BASE(ETH_EVENT);
 
 typedef enum {
@@ -47,6 +49,7 @@ typedef struct {
     atomic_int ref_count;
     void *priv;
     _Atomic esp_eth_fsm_t fsm;
+    SemaphoreHandle_t transmit_mutex;
     esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv);
     esp_err_t (*on_lowlevel_init_done)(esp_eth_handle_t eth_handle);
     esp_err_t (*on_lowlevel_deinit_done)(esp_eth_handle_t eth_handle);
@@ -187,6 +190,7 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_
         .skip_unhandled_events = true
     };
     ESP_GOTO_ON_ERROR(esp_timer_create(&check_link_timer_args, &eth_driver->check_link_timer), err, TAG, "create link timer failed");
+    eth_driver->transmit_mutex = xSemaphoreCreateMutex();
     atomic_init(&eth_driver->ref_count, 1);
     atomic_init(&eth_driver->fsm, ESP_ETH_FSM_STOP);
     eth_driver->mac = mac;
@@ -249,6 +253,7 @@ esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl)
     esp_eth_mac_t *mac = eth_driver->mac;
     esp_eth_phy_t *phy = eth_driver->phy;
     ESP_GOTO_ON_ERROR(esp_timer_delete(eth_driver->check_link_timer), err, TAG, "delete link timer failed");
+    vSemaphoreDelete(eth_driver->transmit_mutex);
     ESP_GOTO_ON_ERROR(phy->deinit(phy), err, TAG, "deinit phy failed");
     ESP_GOTO_ON_ERROR(mac->deinit(mac), err, TAG, "deinit mac failed");
     free(eth_driver);
@@ -331,7 +336,11 @@ esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length)
     ESP_GOTO_ON_FALSE(length, ESP_ERR_INVALID_ARG, err, TAG, "buf length can't be zero");
     ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
     esp_eth_mac_t *mac = eth_driver->mac;
+    if (xSemaphoreTake(eth_driver->transmit_mutex, pdMS_TO_TICKS(ESP_ETH_TX_TIMEOUT_MS)) == pdFALSE) {
+        return ESP_ERR_TIMEOUT;
+    }
     ret = mac->transmit(mac, buf, length);
+    xSemaphoreGive(eth_driver->transmit_mutex);
 err:
     return ret;
 }

By some printf-debug-magic I noticed that this error is returned because the descriptor is not owned by the cpu: components/hal/emac_hal.c, function emac_hal_transmit_frame:

        /* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
        if (desc_iter->TDES0.Own != EMAC_LL_DMADESC_OWNER_CPU) {

Making that into a while loop (with 250ms maximum) does not improve it.

folkertvanheusden avatar Feb 24 '24 22:02 folkertvanheusden

Why not using upcoming core 3.0.0. No backport needed. Just enable in sdkconfig.

Jason2866 avatar Feb 25 '24 10:02 Jason2866

Because platformio.

folkertvanheusden avatar Feb 25 '24 10:02 folkertvanheusden

Because platformio.

platform                    = https://github.com/tasmota/platform-espressif32/releases/download/2024.02.10/platform-espressif32.zip
platform_packages           = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2036/framework-arduinoespressif32-release_v5.1-246cad0.zip

TD-er avatar Feb 25 '24 11:02 TD-er

@TD-er thank you so much! Indeed this woks AND the "insufficient blah" error seems to be gone:

7979008 bytes (8.0 MB, 7.6 MiB) copied, 6.12242 s, 1.3 MB/s (I wrote an iSCSI target for the ESP32, with the ENC28J60 this was at most 300kB/s)

folkertvanheusden avatar Feb 25 '24 11:02 folkertvanheusden

@TD-er one thing:

Serial.printf("%ld] PDU/s: %.2f (%zu), send: %" PRIu64 " kB (%.2f kB/s), recv: %" PRIu64 " kB (%.2f kB/s), written: %.2f kB/s, read: %.2f kB/s, syncs: %.2f/s, load: %.2f%%, mem: %u\r\n", now, pdu_count / dtook, pdu_count, bytes_send / 1024, bytes_send / dkb, bytes_recv / 1024, bytes_recv / dkb, bytes_written / dkb, bytes_read / dkb, n_syncs / dtook, busy * 0.1 / took, get_free_heap_space())

This breaks because it suddenly does not recognize %zu and %lu for printf.

folkertvanheusden avatar Feb 25 '24 11:02 folkertvanheusden

I have no idea where those should be defined. Maybe @Jason2866 knows? He is the one making the PlatformIO packages for this. The one I linked is the one also used in Tasmota and Jason stripped quite a lot out of it before compiling those packages. He also recently started to prepare a "pure" Arduino version, which does result in quite a bit larger build files.

For "pure Arduino", you need to use this one:

platform = https://github.com/Jason2866/platform-espressif32/tree/Arduino/IDF5_org
platform_packages =

The last line should be included but left empty as all is included in that package.

But like I said, it does make the builds quite a bit larger as there's stuff included there which you may not need. No idea what you might need to add to the libs_ignore list to make it smaller.

TD-er avatar Feb 25 '24 12:02 TD-er

Afaik "%lu" is not supported anymore. Not a special thing from my build. Use "%u" as replacement. Probably the same for the others.

Little correction.

platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5_org
platform_packages =

Jason2866 avatar Feb 25 '24 13:02 Jason2866

That's problematic for when you want to print an uint64_t and size_t etc. Lots of existing software breakage.

On Sun, Feb 25, 2024 at 2:32 PM Jason2866 @.***> wrote:

Afaik "%lu" is not supported anymore. Not a special thing from my build. Use "%u" as replacement. Probably the same for the others.

— Reply to this email directly, view it on GitHub https://github.com/espressif/arduino-esp32/issues/9247#issuecomment-1962938075, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUN5IW36HB3KH5NIL7XEU3TYVM2XLAVCNFSM6AAAAABDHJJDACVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNRSHEZTQMBXGU . You are receiving this because you modified the open/close state.Message ID: @.***>

folkertvanheusden avatar Feb 25 '24 13:02 folkertvanheusden

Regarding the format specifiers, please take a look at this section of the migration guide for IDF 5.0: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/release-5.x/5.0/gcc.html#int32-t-and-uint32-t-for-xtensa-compiler. (For fixed-width integer types such as uint32_t and int32_t, you need to use format specifiers defined in inttypes.h: PRIu32, PRIx32, PRId32 and so on. This way is portable between different compilers and toolchains. It is true that this was a fairly significant breaking change, but we needed to do it to make our Xtensa toolchain behavior match that of RISC-V and ARM GCC-based toolchains.)

igrr avatar Feb 25 '24 21:02 igrr