mirror of
https://github.com/esphome/esphome.git
synced 2025-09-26 23:22:21 +01:00
wip
This commit is contained in:
@@ -193,7 +193,7 @@ void USBUartComponent::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return chunk to pool for reuse
|
// Return chunk to pool for reuse
|
||||||
this->free_chunks_.push(chunk);
|
this->chunk_pool_.release(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr int LOG_CHUNK_THRESHOLD = 5;
|
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) {
|
if (!channel->dummy_receiver_ && status.data_len > 0) {
|
||||||
// Get a free chunk from the pool
|
// Allocate a chunk from the pool
|
||||||
UsbDataChunk *chunk = this->free_chunks_.pop();
|
UsbDataChunk *chunk = this->chunk_pool_.allocate();
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
ESP_LOGW(TAG, "No free chunks available, dropping %u bytes", status.data_len);
|
ESP_LOGW(TAG, "No free chunks available, dropping %u bytes", status.data_len);
|
||||||
// Mark input as not started so we can retry
|
// 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)) {
|
if (!this->usb_data_queue_.push(chunk)) {
|
||||||
ESP_LOGW(TAG, "USB data queue full, dropping %u bytes", status.data_len);
|
ESP_LOGW(TAG, "USB data queue full, dropping %u bytes", status.data_len);
|
||||||
// Return chunk to pool
|
// Return chunk to pool
|
||||||
this->free_chunks_.push(chunk);
|
this->chunk_pool_.release(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "esphome/components/uart/uart_component.h"
|
#include "esphome/components/uart/uart_component.h"
|
||||||
#include "esphome/components/usb_host/usb_host.h"
|
#include "esphome/components/usb_host/usb_host.h"
|
||||||
#include "esphome/core/lock_free_queue.h"
|
#include "esphome/core/lock_free_queue.h"
|
||||||
|
#include "esphome/core/event_pool.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace usb_uart {
|
namespace usb_uart {
|
||||||
@@ -76,6 +77,12 @@ struct UsbDataChunk {
|
|||||||
uint8_t data[MAX_CHUNK_SIZE];
|
uint8_t data[MAX_CHUNK_SIZE];
|
||||||
size_t length;
|
size_t length;
|
||||||
USBUartChannel *channel;
|
USBUartChannel *channel;
|
||||||
|
|
||||||
|
// Required for EventPool - reset to clean state
|
||||||
|
void release() {
|
||||||
|
this->length = 0;
|
||||||
|
this->channel = nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class USBUartChannel : public uart::UARTComponent, public Parented<USBUartComponent> {
|
class USBUartChannel : public uart::UARTComponent, public Parented<USBUartComponent> {
|
||||||
@@ -114,13 +121,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon
|
|||||||
|
|
||||||
class USBUartComponent : public usb_host::USBClient {
|
class USBUartComponent : public usb_host::USBClient {
|
||||||
public:
|
public:
|
||||||
USBUartComponent(uint16_t vid, uint16_t pid) : usb_host::USBClient(vid, pid) {
|
USBUartComponent(uint16_t vid, uint16_t pid) : usb_host::USBClient(vid, pid) {}
|
||||||
// Allocate pool of data chunks (never freed - ESPHome reboots instead)
|
|
||||||
for (int i = 0; i < MAX_DATA_CHUNKS; i++) {
|
|
||||||
this->data_chunk_pool_[i] = new UsbDataChunk();
|
|
||||||
this->free_chunks_.push(this->data_chunk_pool_[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void loop() override;
|
void loop() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
@@ -135,15 +136,12 @@ class USBUartComponent : public usb_host::USBClient {
|
|||||||
static constexpr int USB_DATA_QUEUE_SIZE = 32;
|
static constexpr int USB_DATA_QUEUE_SIZE = 32;
|
||||||
LockFreeQueue<UsbDataChunk, USB_DATA_QUEUE_SIZE> usb_data_queue_;
|
LockFreeQueue<UsbDataChunk, USB_DATA_QUEUE_SIZE> usb_data_queue_;
|
||||||
|
|
||||||
|
// Pool for allocating data chunks (uses EventPool pattern like BLE)
|
||||||
|
static constexpr int MAX_DATA_CHUNKS = 40;
|
||||||
|
EventPool<UsbDataChunk, MAX_DATA_CHUNKS> chunk_pool_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<USBUartChannel *> channels_{};
|
std::vector<USBUartChannel *> 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<UsbDataChunk, MAX_DATA_CHUNKS> free_chunks_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class USBUartTypeCdcAcm : public USBUartComponent {
|
class USBUartTypeCdcAcm : public USBUartComponent {
|
||||||
|
Reference in New Issue
Block a user