From dc2e8c2270b9855eff17e6a665250e8617660519 Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Wed, 25 Feb 2026 12:07:03 +0100 Subject: [PATCH] sync --- buzzer_tool/core/connection.py | 11 +++++++--- firmware/src/protocol.c | 2 +- firmware/src/usb.c | 37 ++++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/buzzer_tool/core/connection.py b/buzzer_tool/core/connection.py index b41c4e3..32818d8 100644 --- a/buzzer_tool/core/connection.py +++ b/buzzer_tool/core/connection.py @@ -90,22 +90,27 @@ class BuzzerConnection: with open(filepath, 'rb') as f: while bytes_sent < file_size: - - # NEU: Prüfe, ob der Controller VORZEITIG abgebrochen hat (z.B. ERR) + # 1. Nicht blockierende Fehlerprüfung vor jedem Chunk if self.serial.in_waiting > 0: line = self.serial.readline().decode('utf-8', errors='ignore').strip() if line.startswith("ERR"): raise BuzzerError(f"Controller hat Transfer abgebrochen: {line}") + # 2. Chunk lesen und schreiben chunk = f.read(chunk_size) if not chunk: break + self.serial.write(chunk) - self.serial.flush() + # WICHTIG: self.serial.flush() hier entfernen. + # Dies verhindert den Deadlock mit dem OS-USB-Puffer. + bytes_sent += len(chunk) + # 3. Callback für UI if progress_callback: progress_callback(len(chunk)) + # 3. Warte auf das finale OK (oder ERR bei CRC/Schreib-Fehlern) start_time = time.time() while (time.time() - start_time) < timeout: diff --git a/firmware/src/protocol.c b/firmware/src/protocol.c index 058855d..0d75de7 100644 --- a/firmware/src/protocol.c +++ b/firmware/src/protocol.c @@ -109,7 +109,7 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr { if (retry_count >= 10) { - LOG_ERR("No data received from USB after multiple attempts"); + LOG_ERR("No data received from USB after multiple attempts (received %zd bytes, expected %zd bytes)", bytes_written, filesize); fs_close(&file); return -ETIMEDOUT; } diff --git a/firmware/src/usb.c b/firmware/src/usb.c index 7380829..078f035 100644 --- a/firmware/src/usb.c +++ b/firmware/src/usb.c @@ -2,6 +2,7 @@ #include #include #include +#include /* NEU */ #include @@ -13,6 +14,10 @@ K_SEM_DEFINE(usb_tx_sem, 0, 1); #define UART_NODE DT_ALIAS(usb_uart) const struct device *cdc_dev = DEVICE_DT_GET(UART_NODE); +/* NEU: Ringbuffer für stabilen asynchronen USB-Empfang */ +#define RX_RING_BUF_SIZE 4096 +RING_BUF_DECLARE(rx_ringbuf, RX_RING_BUF_SIZE); + static void cdc_acm_irq_cb(const struct device *dev, void *user_data) { ARG_UNUSED(user_data); @@ -21,43 +26,45 @@ static void cdc_acm_irq_cb(const struct device *dev, void *user_data) return; } + /* Der Interrupt bleibt permanent an. Daten sofort in Ringbuffer schieben. */ if (uart_irq_rx_ready(dev)) { - uart_irq_rx_disable(dev); + uint8_t buffer[64]; + int len; + + while ((len = uart_fifo_read(dev, buffer, sizeof(buffer))) > 0) { + ring_buf_put(&rx_ringbuf, buffer, len); + } k_sem_give(&usb_rx_sem); - LOG_DBG("RX interrupt: data available"); } - if (uart_irq_tx_ready(dev)) { uart_irq_tx_disable(dev); k_sem_give(&usb_tx_sem); - LOG_DBG("TX interrupt: ready for more data"); } } bool usb_wait_for_data(k_timeout_t timeout) { + /* Wenn Daten im Puffer sind, nicht blockieren */ + if (!ring_buf_is_empty(&rx_ringbuf)) { + return true; + } return (k_sem_take(&usb_rx_sem, timeout) == 0); } int usb_read_char(uint8_t *c) { - if (!device_is_ready(cdc_dev)) return 0; - return uart_fifo_read(cdc_dev, c, 1); + return ring_buf_get(&rx_ringbuf, c, 1); } int usb_read_buffer(uint8_t *buf, size_t max_len) { - if (!device_is_ready(cdc_dev)) return 0; - return uart_fifo_read(cdc_dev, buf, max_len); + return ring_buf_get(&rx_ringbuf, buf, max_len); } void usb_resume_rx(void) { - if (device_is_ready(cdc_dev)) { - uart_irq_rx_enable(cdc_dev); - LOG_DBG("RX interrupt re-enabled"); - } + /* Leere Funktion - Interrupt wird nicht mehr deaktiviert */ } void usb_write_char(uint8_t c) @@ -100,12 +107,12 @@ void usb_flush_rx(void) uint8_t dummy; if (!device_is_ready(cdc_dev)) return; - // Alles lesen, was gerade im Hardware-FIFO liegt + /* Hardware-FIFO leeren, falls Reste vorhanden */ while (uart_fifo_read(cdc_dev, &dummy, 1) > 0); - // Semaphore zurücksetzen, falls sie gesetzt war + /* Ringpuffer und Semaphore zurücksetzen */ + ring_buf_reset(&rx_ringbuf); k_sem_reset(&usb_rx_sem); - usb_resume_rx(); } static void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param)