From ee2d18ef91153a213671c7b144d7b66ac9a6b671 Mon Sep 17 00:00:00 2001 From: Gabriel Notman Date: Mon, 28 Sep 2015 15:57:44 +0100 Subject: [PATCH] A fix for the SerialUSB buffer overflow bug. Send the data in chunks based on the buffer size instead of assuming that the whole send data will fit into the buffer. --- cores/arduino/USB/USBCore.cpp | 30 +++++++++++++++++++++++++----- cores/arduino/USB/samd21_device.c | 4 ++-- cores/arduino/USB/samd21_device.h | 3 +++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 31b8380af..a72305f7f 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -120,12 +120,32 @@ uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len) int r = len; const uint8_t* data = (const uint8_t*)d; - if (!_usbConfiguration) - { - TRACE_CORE(printf("pb conf\n\r");) + if (!_usbConfiguration) + { + TRACE_CORE(printf("pb conf\n\r");) return -1; - } - UDD_Send(ep, data, len); + } + + size_t i = 0; + // Ensure the chunk size is aligned 4 + size_t chunkSize = UDD_IN_CACHE_SIZE -(UDD_IN_CACHE_SIZE % 4); + + // Send the full chunks + for (i = 0; i < (len / chunkSize); i++) + { + UDD_Send(ep, data + (i*chunkSize), chunkSize); + + /* Clear the transfer complete flag */ + udd_clear_IN_transf_cplt(ep); + /* Set the bank as ready */ + udd_IN_transfer_allowed(ep); + + /* Wait for transfer to complete */ + while (!udd_is_IN_transf_cplt(ep)); // need fire exit. + } + + // Send the remainder + UDD_Send(ep, data + (i * chunkSize), len % chunkSize); /* Clear the transfer complete flag */ udd_clear_IN_transf_cplt(ep); diff --git a/cores/arduino/USB/samd21_device.c b/cores/arduino/USB/samd21_device.c index cff711f47..3aae35d9f 100644 --- a/cores/arduino/USB/samd21_device.c +++ b/cores/arduino/USB/samd21_device.c @@ -34,8 +34,8 @@ extern "C"{ //#define TRACE_DEVICE(x) x #define TRACE_DEVICE(x) -__attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/ uint8_t udd_ep_out_cache_buffer[4][64]; -__attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/ uint8_t udd_ep_in_cache_buffer[4][128]; +__attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/ uint8_t udd_ep_out_cache_buffer[4][UDD_OUT_CACHE_SIZE]; +__attribute__((__aligned__(4))) /*__attribute__((__section__(".bss_hram0")))*/ uint8_t udd_ep_in_cache_buffer[4][UDD_IN_CACHE_SIZE]; /** * USB SRAM data containing pipe descriptor table diff --git a/cores/arduino/USB/samd21_device.h b/cores/arduino/USB/samd21_device.h index deded25b4..e26bb4873 100644 --- a/cores/arduino/USB/samd21_device.h +++ b/cores/arduino/USB/samd21_device.h @@ -26,6 +26,9 @@ extern "C" { #define EP0 0 #define EPX_SIZE 64// 64 for Full Speed, EPT size max is 1024 +#define UDD_OUT_CACHE_SIZE 64 +#define UDD_IN_CACHE_SIZE 128 + // Force device low speed mode #define udd_force_low_speed() USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_SPDCONF_Msk; USB->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_SPDCONF_1_Val // Force full speed mode