diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 4b2464fd59..a872b37fa2 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -193,7 +193,7 @@ void USBUartComponent::loop() { } // Return chunk to pool for reuse - this->free_chunks_.push(chunk); + this->chunk_pool_.release(chunk); } static constexpr int LOG_CHUNK_THRESHOLD = 5; @@ -231,8 +231,8 @@ void USBUartComponent::start_input(USBUartChannel *channel) { } if (!channel->dummy_receiver_ && status.data_len > 0) { - // Get a free chunk from the pool - UsbDataChunk *chunk = this->free_chunks_.pop(); + // Allocate a chunk from the pool + UsbDataChunk *chunk = this->chunk_pool_.allocate(); if (chunk == nullptr) { ESP_LOGW(TAG, "No free chunks available, dropping %u bytes", status.data_len); // Mark input as not started so we can retry @@ -249,7 +249,7 @@ void USBUartComponent::start_input(USBUartChannel *channel) { if (!this->usb_data_queue_.push(chunk)) { ESP_LOGW(TAG, "USB data queue full, dropping %u bytes", status.data_len); // Return chunk to pool - this->free_chunks_.push(chunk); + this->chunk_pool_.release(chunk); } } diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 91a4329f22..1389ceeaee 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -6,6 +6,7 @@ #include "esphome/components/uart/uart_component.h" #include "esphome/components/usb_host/usb_host.h" #include "esphome/core/lock_free_queue.h" +#include "esphome/core/event_pool.h" namespace esphome { namespace usb_uart { @@ -76,6 +77,12 @@ struct UsbDataChunk { uint8_t data[MAX_CHUNK_SIZE]; size_t length; USBUartChannel *channel; + + // Required for EventPool - reset to clean state + void release() { + this->length = 0; + this->channel = nullptr; + } }; class USBUartChannel : public uart::UARTComponent, public Parented { @@ -114,13 +121,7 @@ class USBUartChannel : public uart::UARTComponent, public Parenteddata_chunk_pool_[i] = new UsbDataChunk(); - this->free_chunks_.push(this->data_chunk_pool_[i]); - } - } + USBUartComponent(uint16_t vid, uint16_t pid) : usb_host::USBClient(vid, pid) {} void setup() override; void loop() override; void dump_config() override; @@ -135,15 +136,12 @@ class USBUartComponent : public usb_host::USBClient { static constexpr int USB_DATA_QUEUE_SIZE = 32; LockFreeQueue usb_data_queue_; + // Pool for allocating data chunks (uses EventPool pattern like BLE) + static constexpr int MAX_DATA_CHUNKS = 40; + EventPool chunk_pool_; + protected: std::vector channels_{}; - - // Pool of pre-allocated data chunks to avoid dynamic allocation - static constexpr int MAX_DATA_CHUNKS = 40; - UsbDataChunk *data_chunk_pool_[MAX_DATA_CHUNKS]; - // IMPORTANT: This is used bidirectionally (USB task pops, main loop pushes) - // which technically violates SPSC, but works in practice because operations are atomic - LockFreeQueue free_chunks_; }; class USBUartTypeCdcAcm : public USBUartComponent {