From 409242507c7ad921fba370df571c0bfa7655cad6 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Fri, 12 Jan 2024 21:49:10 +0100 Subject: [PATCH] Usb serial fix queue full crash (#1763) * fixed usb serial queue crashing * fixed usb input buffer handling * fixed black screen issue --- firmware/application/usb_serial_io.c | 21 ++++++++++++------- firmware/application/usb_serial_io.h | 4 +++- .../usb_serial_shell_filesystem.cpp | 16 ++++++++------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/firmware/application/usb_serial_io.c b/firmware/application/usb_serial_io.c index 3195cab74..aa1439c19 100644 --- a/firmware/application/usb_serial_io.c +++ b/firmware/application/usb_serial_io.c @@ -40,15 +40,19 @@ SerialUSBDriver SUSBD1; -uint8_t usbBulkBuffer[USBSERIAL_BUFFERS_SIZE]; +uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE]; void bulk_out_receive(void) { int ret; + + while (chIQGetEmptyI(&SUSBD1.iqueue) < USB_BULK_BUFFER_SIZE) + chThdSleepMilliseconds(1); // wait for shell thread when buffer is full + do { ret = usb_transfer_schedule( &usb_endpoint_bulk_out, - &usbBulkBuffer[0], - USBSERIAL_BUFFERS_SIZE, + &usb_bulk_buffer[0], + USB_BULK_BUFFER_SIZE, serial_bulk_transfer_complete, NULL); @@ -58,18 +62,19 @@ void bulk_out_receive(void) { void serial_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred) { (void)user_data; + chSysLockFromIsr(); for (unsigned int i = 0; i < bytes_transferred; i++) { msg_t ret; do { - chSysLockFromIsr(); - ret = chIQPutI(&SUSBD1.iqueue, usbBulkBuffer[i]); - chSysUnlockFromIsr(); + ret = chIQPutI(&SUSBD1.iqueue, usb_bulk_buffer[i]); + if (ret == Q_FULL) { - chThdYield(); + chDbgPanic("USB iqueue buffer full"); } } while (ret == Q_FULL); } + chSysUnlockFromIsr(); } static void onotify(GenericQueue* qp) { @@ -93,7 +98,7 @@ static void onotify(GenericQueue* qp) { NULL); if (ret == -1) - chThdYield(); + chThdSleepMilliseconds(1); } while (ret == -1); chSysLock(); diff --git a/firmware/application/usb_serial_io.h b/firmware/application/usb_serial_io.h index 9f2c0e590..614f58c8a 100644 --- a/firmware/application/usb_serial_io.h +++ b/firmware/application/usb_serial_io.h @@ -24,8 +24,10 @@ #include "ch.h" #include "hal.h" +#define USB_BULK_BUFFER_SIZE 64 + #ifndef USBSERIAL_BUFFERS_SIZE -#define USBSERIAL_BUFFERS_SIZE 400 +#define USBSERIAL_BUFFERS_SIZE 128 #endif struct SerialUSBDriverVMT { diff --git a/firmware/application/usb_serial_shell_filesystem.cpp b/firmware/application/usb_serial_shell_filesystem.cpp index 0c35fe82a..b4ae90e42 100644 --- a/firmware/application/usb_serial_shell_filesystem.cpp +++ b/firmware/application/usb_serial_shell_filesystem.cpp @@ -348,19 +348,23 @@ void cmd_sd_write_binary(BaseSequentialStream* chp, int argc, char* argv[]) { return; } - long size = (int)strtol(argv[0], NULL, 10); + size_t size = (size_t)strtol(argv[0], NULL, 10); chprintf(chp, "send %d bytes\r\n", size); - uint8_t buffer; + uint8_t buffer[USB_BULK_BUFFER_SIZE]; - for (long i = 0; i < size; i++) { - if (chSequentialStreamRead(chp, &buffer, 1) == 0) + do { + size_t bytes_to_read = size > USB_BULK_BUFFER_SIZE ? USB_BULK_BUFFER_SIZE : size; + size_t bytes_read = chSequentialStreamRead(chp, &buffer[0], bytes_to_read); + if (bytes_read != bytes_to_read) return; - auto error = shell_file->write(&buffer, 1); + auto error = shell_file->write(&buffer[0], bytes_read); if (report_on_error(chp, error)) return; - } + + size -= bytes_read; + } while (size > 0); chprintf(chp, "ok\r\n"); }