Skip to content

Commit da5b342

Browse files
committed
Remove PLUGGABLEUSB and import modern DoubleBufferedEPOutHandler
Fixes https://github.com/arduino/Arduino/issues/9112
1 parent 1458fe0 commit da5b342

File tree

3 files changed

+101
-78
lines changed

3 files changed

+101
-78
lines changed

cores/arduino/USB/SAMD21_USBDevice.h

+92-68
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class USBDevice_SAMD21G18x {
100100
inline bool epBank0IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0; }
101101
inline bool epBank1IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT1; }
102102

103+
inline void epAckPendingInterrupts(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = 0x7F; }
103104
inline void epBank0AckSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP; }
104105
inline void epBank0AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(1); }
105106
inline void epBank1AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(2); }
@@ -162,6 +163,12 @@ class USBDevice_SAMD21G18x {
162163
inline void epBank0EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 1; }
163164
inline void epBank1EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 1; }
164165

166+
inline void epReleaseOutBank0(ep_t ep, uint16_t s) {
167+
epBank0SetMultiPacketSize(ep, s);
168+
epBank0SetByteCount(ep, 0);
169+
epBank0ResetReady(ep);
170+
}
171+
165172
private:
166173
// USB Device registers
167174
UsbDevice &usb;
@@ -233,33 +240,41 @@ class EPHandler {
233240
public:
234241
virtual void handleEndpoint() = 0;
235242
virtual uint32_t recv(void *_data, uint32_t len) = 0;
236-
virtual uint32_t available() const = 0;
243+
virtual uint32_t available() = 0;
244+
virtual int peek() = 0;
237245
};
238246

239247
class DoubleBufferedEPOutHandler : public EPHandler {
240248
public:
241-
DoubleBufferedEPOutHandler(USBDevice_SAMD21G18x &usbDev, uint32_t endPoint, uint32_t bufferSize) :
249+
enum { size = 64 };
250+
251+
DoubleBufferedEPOutHandler(USBDevice_SAMD21G18x &usbDev, uint32_t endPoint) :
242252
usbd(usbDev),
243-
ep(endPoint), size(bufferSize),
253+
ep(endPoint),
244254
current(0), incoming(0),
245255
first0(0), last0(0), ready0(false),
246256
first1(0), last1(0), ready1(false),
247257
notify(false)
248258
{
249-
data0 = reinterpret_cast<uint8_t *>(malloc(size));
250-
data1 = reinterpret_cast<uint8_t *>(malloc(size));
251-
252259
usbd.epBank0SetSize(ep, 64);
253260
usbd.epBank0SetType(ep, 3); // BULK OUT
254-
255261
usbd.epBank0SetAddress(ep, const_cast<uint8_t *>(data0));
262+
usbd.epBank0EnableTransferComplete(ep);
256263

257264
release();
258265
}
259266

260-
virtual uint32_t recv(void *_data, uint32_t len)
267+
virtual ~DoubleBufferedEPOutHandler() {
268+
}
269+
270+
uint32_t _recv()
261271
{
262-
uint8_t *data = reinterpret_cast<uint8_t *>(_data);
272+
uint32_t i = 0;
273+
uint32_t len = 0;
274+
275+
synchronized {
276+
len = _rx_buffer.availableForStore();
277+
}
263278

264279
// R/W: current, first0/1, ready0/1, notify
265280
// R : last0/1, data0/1
@@ -270,9 +285,8 @@ class DoubleBufferedEPOutHandler : public EPHandler {
270285
}
271286
}
272287
// when ready0==true the buffer is not being filled and last0 is constant
273-
uint32_t i;
274-
for (i=0; i<len && first0 < last0; i++) {
275-
data[i] = data0[first0++];
288+
for (; i<len && first0 < last0; i++) {
289+
_rx_buffer.store_char(data0[first0++]);
276290
}
277291
if (first0 == last0) {
278292
first0 = 0;
@@ -285,17 +299,15 @@ class DoubleBufferedEPOutHandler : public EPHandler {
285299
}
286300
}
287301
}
288-
return i;
289302
} else {
290303
synchronized {
291304
if (!ready1) {
292305
return 0;
293306
}
294307
}
295308
// when ready1==true the buffer is not being filled and last1 is constant
296-
uint32_t i;
297-
for (i=0; i<len && first1 < last1; i++) {
298-
data[i] = data1[first1++];
309+
for (; i<len && first1 < last1; i++) {
310+
_rx_buffer.store_char(data1[first1++]);
299311
}
300312
if (first1 == last1) {
301313
first1 = 0;
@@ -308,7 +320,35 @@ class DoubleBufferedEPOutHandler : public EPHandler {
308320
}
309321
}
310322
}
311-
return i;
323+
}
324+
return i;
325+
}
326+
327+
virtual uint32_t recv(void *_data, uint32_t len) {
328+
_recv();
329+
uint32_t i = 0;
330+
uint8_t *data = reinterpret_cast<uint8_t *>(_data);
331+
synchronized {
332+
for (; i < len && _rx_buffer.available(); i++) {
333+
data[i] = _rx_buffer.read_char();
334+
}
335+
}
336+
return i;
337+
}
338+
339+
virtual uint32_t _available() const {
340+
if (current == 0) {
341+
bool ready = ready0;
342+
synchronized {
343+
ready = ready0;
344+
}
345+
return ready ? (last0 - first0) : 0;
346+
} else {
347+
bool ready = false;
348+
synchronized {
349+
ready = ready1;
350+
}
351+
return ready ? (last1 - first1) : 0;
312352
}
313353
}
314354

@@ -318,82 +358,66 @@ class DoubleBufferedEPOutHandler : public EPHandler {
318358
// W : last0/1, notify
319359
if (usbd.epBank0IsTransferComplete(ep))
320360
{
321-
// Ack Transfer complete
322-
usbd.epBank0AckTransferComplete(ep);
323-
//usbd.epBank0AckTransferFailed(ep); // XXX
324-
361+
uint32_t received = usbd.epBank0ByteCount(ep);
362+
if (received == 0) {
363+
release();
364+
} else if (incoming == 0) {
325365
// Update counters and swap banks for non-ZLP's
326-
if (incoming == 0) {
327-
last0 = usbd.epBank0ByteCount(ep);
328-
if (last0 != 0) {
329-
incoming = 1;
330-
usbd.epBank0SetAddress(ep, const_cast<uint8_t *>(data1));
331-
synchronized {
332-
ready0 = true;
333-
if (ready1) {
334-
notify = true;
335-
return;
336-
}
337-
notify = false;
366+
last0 = received;
367+
incoming = 1;
368+
usbd.epBank0SetAddress(ep, const_cast<uint8_t *>(data1));
369+
synchronized {
370+
ready0 = true;
371+
notify = ready1;
372+
if (!notify) {
373+
release();
338374
}
339375
}
340376
} else {
341-
last1 = usbd.epBank0ByteCount(ep);
342-
if (last1 != 0) {
343-
incoming = 0;
344-
usbd.epBank0SetAddress(ep, const_cast<uint8_t *>(data0));
345-
synchronized {
346-
ready1 = true;
347-
if (ready0) {
348-
notify = true;
349-
return;
350-
}
351-
notify = false;
377+
last1 = received;
378+
incoming = 0;
379+
usbd.epBank0SetAddress(ep, const_cast<uint8_t *>(data0));
380+
synchronized {
381+
ready1 = true;
382+
notify = ready0;
383+
if (!notify) {
384+
release();
352385
}
353386
}
354387
}
355-
release();
388+
usbd.epAckPendingInterrupts(ep);
356389
}
357390
}
358391

359392
// Returns how many bytes are stored in the buffers
360-
virtual uint32_t available() const {
361-
if (current == 0) {
362-
bool ready = false;
363-
synchronized {
364-
ready = ready0;
365-
}
366-
return ready ? (last0 - first0) : 0;
367-
} else {
368-
bool ready = false;
369-
synchronized {
370-
ready = ready1;
371-
}
372-
return ready ? (last1 - first1) : 0;
373-
}
393+
virtual uint32_t available() {
394+
_recv();
395+
return _rx_buffer.available();
396+
}
397+
398+
virtual int peek() {
399+
_recv();
400+
return _rx_buffer.peek();
374401
}
375402

376403
void release() {
377-
// Release OUT EP
378-
usbd.epBank0EnableTransferComplete(ep);
379-
usbd.epBank0SetMultiPacketSize(ep, size);
380-
usbd.epBank0SetByteCount(ep, 0);
381-
usbd.epBank0ResetReady(ep);
404+
usbd.epReleaseOutBank0(ep, size);
382405
}
383406

384407
private:
385408
USBDevice_SAMD21G18x &usbd;
386409

410+
RingBuffer _rx_buffer;
411+
387412
const uint32_t ep;
388-
const uint32_t size;
389-
uint32_t current, incoming;
413+
volatile uint32_t current, incoming;
390414

391-
volatile uint8_t *data0;
415+
__attribute__((__aligned__(4))) volatile uint8_t data0[size];
392416
uint32_t first0;
393417
volatile uint32_t last0;
394418
volatile bool ready0;
395419

396-
volatile uint8_t *data1;
420+
__attribute__((__aligned__(4))) volatile uint8_t data1[size];
397421
uint32_t first1;
398422
volatile uint32_t last1;
399423
volatile bool ready1;

cores/arduino/USB/USBCore.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,10 @@ volatile uint32_t _usbConfiguration = 0;
108108
volatile uint32_t _usbSetInterface = 0;
109109

110110
static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0")))
111-
uint8_t udd_ep_out_cache_buffer[4][64];
111+
uint8_t udd_ep_out_cache_buffer[2][64];
112112

113113
static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0")))
114-
uint8_t udd_ep_in_cache_buffer[4][64];
114+
uint8_t udd_ep_in_cache_buffer[2][64];
115115

116116
// Some EP are handled using EPHanlders.
117117
// Possibly all the sparse EP handling subroutines will be
@@ -259,7 +259,6 @@ bool USBDeviceClass::sendDescriptor(USBSetup &setup)
259259
return sendStringDescriptor(STRING_MANUFACTURER, setup.wLength);
260260
}
261261
else if (setup.wValueL == ISERIAL) {
262-
#ifdef PLUGGABLE_USB_ENABLED
263262
#if (SAMD51)
264263
// from section 9.6 of the datasheet
265264
#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x008061FC)
@@ -279,10 +278,10 @@ bool USBDeviceClass::sendDescriptor(USBSetup &setup)
279278
utox8(SERIAL_NUMBER_WORD_1, &name[8]);
280279
utox8(SERIAL_NUMBER_WORD_2, &name[16]);
281280
utox8(SERIAL_NUMBER_WORD_3, &name[24]);
282-
281+
#ifdef PLUGGABLE_USB_ENABLED
283282
PluggableUSB().getShortName(&name[32]);
284-
return sendStringDescriptor((uint8_t*)name, setup.wLength);
285283
#endif
284+
return sendStringDescriptor((uint8_t*)name, setup.wLength);
286285
}
287286
else {
288287
return false;
@@ -510,14 +509,15 @@ void USBDeviceClass::initEP(uint32_t ep, uint32_t config)
510509
if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)))
511510
{
512511
usbd.epBank1SetSize(ep, 64);
513-
usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
512+
usbd.epBank1SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
514513
usbd.epBank1SetType(ep, 4); // INTERRUPT IN
515514
}
516515
else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0)))
517516
{
518-
if (epHandlers[ep] == NULL) {
519-
epHandlers[ep] = new DoubleBufferedEPOutHandler(usbd, ep, 256);
517+
if (epHandlers[ep] != NULL) {
518+
delete (DoubleBufferedEPOutHandler*)epHandlers[ep];
520519
}
520+
epHandlers[ep] = new DoubleBufferedEPOutHandler(usbd, ep);
521521
}
522522
else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)))
523523
{
@@ -533,7 +533,7 @@ void USBDeviceClass::initEP(uint32_t ep, uint32_t config)
533533
{
534534
// Setup Control OUT
535535
usbd.epBank0SetSize(ep, 64);
536-
usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
536+
usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[0]);
537537
usbd.epBank0SetType(ep, 1); // CONTROL OUT / SETUP
538538

539539
// Setup Control IN

cores/arduino/USB/USBDesc.h

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#define __USBDESC_H__
2121

2222
#if !defined(USB_DISABLED)
23-
#define PLUGGABLE_USB_ENABLED
2423
#endif
2524

2625
#if defined(CDC_ONLY) || defined(CDC_HID) || defined(WITH_CDC)

0 commit comments

Comments
 (0)