From f6ae6d843d88373725f686477174a6221f9713b1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 24 Apr 2019 16:32:26 +0200 Subject: [PATCH 1/2] Fixing typo - although control endpoints are located at endpoint #0 we should leave this choice to the caller of the function and be consistent within the rest of the code --- cores/arduino/USB/USBCore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 80ff50124..7e2c3d5f6 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -425,7 +425,7 @@ void USBDeviceClass::initEP(uint32_t ep, uint32_t config) // Setup Control IN usbd.epBank1SetSize(ep, 64); - usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[0]); + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); usbd.epBank1SetType(ep, 1); // CONTROL IN // Release OUT EP From 4c5ac51cc9f63424693232777d1a6a58f38445fb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 24 Apr 2019 17:16:50 +0200 Subject: [PATCH 2/2] Deleting superflous call to 'usbd.epBank0ResetReady' - this function is already called within 'USBDeviceClass::ISRHandler' and 'USBDeviceClass::recvControl' is called by 'handleClassInterfaceSetup' within the ISR Bugfix - removal of delay within USBDeviceClass::ISRHandler - remove stall requests of endpoint #0 OUT (bank #0) if present - copy data from cache into structure instead of referencing it via pointer. When referencing via pointer the content of the structure can change if new data is written to the buffer. - Fixing MULTI_PACKET_SIZE parameter of call to 'usbd.epBank0SetMultiPacketSize' within 'USBDeviceClass::armRecvCtrlOUT' to correct size, MULTI_PACKET_SIZE should not be set to a value < SIZE, this means at least to 64. - resetting byte count for endpoint #0 seems to eliminate issue of the bootloader not being triggered. --- cores/arduino/USB/USBCore.cpp | 42 +++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 7e2c3d5f6..4769e7f64 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -469,9 +469,6 @@ uint32_t USBDeviceClass::recvControl(void *_data, uint32_t len) { uint8_t *data = reinterpret_cast(_data); - // The RAM Buffer is empty: we can receive data - usbd.epBank0ResetReady(0); - //usbd.epBank0AckSetupReceived(0); uint32_t read = armRecvCtrlOUT(0); if (read > len) @@ -551,7 +548,17 @@ uint8_t USBDeviceClass::armRecvCtrlOUT(uint32_t ep) { // Get endpoint configuration from setting register usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]); - usbd.epBank0SetMultiPacketSize(ep, 8); + /* Atmel-42181G–SAM-D21_Datasheet–09/2015 / Page 806 + * + * For OUT endpoints, MULTI_PACKET_SIZE holds the total + * data size for the complete transfer. This value must + * be a multiple of the maximum packet size. + * + * Since SIZE is 64 (see 'USBDeviceClass::initEP') for + * all endpoints MULTI_PACKET_SIZE should not be set to + * a value < SIZE, this means at least to 64. + */ + usbd.epBank0SetMultiPacketSize(ep, 64); usbd.epBank0SetByteCount(ep, 0); usbd.epBank0ResetReady(ep); @@ -830,23 +837,34 @@ void USBDeviceClass::ISRHandler() #endif } + /* Remove any stall requests for endpoint #0 */ + if (usbd.epBank0IsStalled(0)) { usbd.epBank0DisableStalled(0); } + // Endpoint 0 Received Setup interrupt if (usbd.epBank0IsSetupReceived(0)) { - USBSetup *setup = reinterpret_cast(udd_ep_out_cache_buffer[0]); - - delayMicroseconds(20); - /* Clear the Bank 0 ready flag on Control OUT */ - // The RAM Buffer is empty: we can receive data + /* Retrieve received endpoint #0 data from buffer */ + USBSetup setup; + memcpy(&setup, udd_ep_out_cache_buffer[0], sizeof(USBSetup)); + + /* Tell the USB hardware that we are ready to receive more data for endpoint #0 and also reset the byte count + * for endpoint #0 - the clearing seems to be necessary for the code to function correctly, although the datasheet + * is not clear on the subject. + * + * Atmel-42181G–SAM-D21_Datasheet–09/2015 / Page 806 + * For IN endpoints, BYTE_COUNT holds the number of bytes to be sent in the next IN transaction. + * For OUT endpoint or SETUP endpoints, BYTE_COUNT holds the number of bytes received upon the last OUT or SETUP transaction. + */ + usbd.epBank0SetByteCount(0, 0); usbd.epBank0ResetReady(0); bool ok; - if (REQUEST_STANDARD == (setup->bmRequestType & REQUEST_TYPE)) { + if (REQUEST_STANDARD == (setup.bmRequestType & REQUEST_TYPE)) { // Standard Requests - ok = handleStandardSetup(*setup); + ok = handleStandardSetup(setup); } else { // Class Interface Requests - ok = handleClassInterfaceSetup(*setup); + ok = handleClassInterfaceSetup(setup); } if (ok) {