sync
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/usb/usb_device.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/sys/ring_buffer.h> /* NEU */
|
||||
|
||||
#include <io.h>
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user