@@ -100,6 +100,7 @@ class USBDevice_SAMD21G18x {
100
100
inline bool epBank0IsTransferComplete (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .TRCPT0 ; }
101
101
inline bool epBank1IsTransferComplete (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .TRCPT1 ; }
102
102
103
+ inline void epAckPendingInterrupts (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = 0x7F ; }
103
104
inline void epBank0AckSetupReceived (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_RXSTP; }
104
105
inline void epBank0AckStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_STALL (1 ); }
105
106
inline void epBank1AckStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_STALL (2 ); }
@@ -162,6 +163,12 @@ class USBDevice_SAMD21G18x {
162
163
inline void epBank0EnableAutoZLP (ep_t ep) { EP[ep].DeviceDescBank [0 ].PCKSIZE .bit .AUTO_ZLP = 1 ; }
163
164
inline void epBank1EnableAutoZLP (ep_t ep) { EP[ep].DeviceDescBank [1 ].PCKSIZE .bit .AUTO_ZLP = 1 ; }
164
165
166
+ inline void epReleaseOutBank0 (ep_t ep, uint16_t s) {
167
+ epBank0SetMultiPacketSize (ep, s);
168
+ epBank0SetByteCount (ep, 0 );
169
+ epBank0ResetReady (ep);
170
+ }
171
+
165
172
private:
166
173
// USB Device registers
167
174
UsbDevice &usb;
@@ -233,33 +240,41 @@ class EPHandler {
233
240
public:
234
241
virtual void handleEndpoint () = 0;
235
242
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;
237
245
};
238
246
239
247
class DoubleBufferedEPOutHandler : public EPHandler {
240
248
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) :
242
252
usbd (usbDev),
243
- ep (endPoint), size(bufferSize),
253
+ ep (endPoint),
244
254
current (0 ), incoming(0 ),
245
255
first0 (0 ), last0(0 ), ready0(false ),
246
256
first1 (0 ), last1(0 ), ready1(false ),
247
257
notify (false )
248
258
{
249
- data0 = reinterpret_cast <uint8_t *>(malloc (size));
250
- data1 = reinterpret_cast <uint8_t *>(malloc (size));
251
-
252
259
usbd.epBank0SetSize (ep, 64 );
253
260
usbd.epBank0SetType (ep, 3 ); // BULK OUT
254
-
255
261
usbd.epBank0SetAddress (ep, const_cast <uint8_t *>(data0));
262
+ usbd.epBank0EnableTransferComplete (ep);
256
263
257
264
release ();
258
265
}
259
266
260
- virtual uint32_t recv (void *_data, uint32_t len)
267
+ virtual ~DoubleBufferedEPOutHandler () {
268
+ }
269
+
270
+ uint32_t _recv ()
261
271
{
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
+ }
263
278
264
279
// R/W: current, first0/1, ready0/1, notify
265
280
// R : last0/1, data0/1
@@ -270,9 +285,8 @@ class DoubleBufferedEPOutHandler : public EPHandler {
270
285
}
271
286
}
272
287
// 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++]);
276
290
}
277
291
if (first0 == last0) {
278
292
first0 = 0 ;
@@ -285,17 +299,15 @@ class DoubleBufferedEPOutHandler : public EPHandler {
285
299
}
286
300
}
287
301
}
288
- return i;
289
302
} else {
290
303
synchronized {
291
304
if (!ready1) {
292
305
return 0 ;
293
306
}
294
307
}
295
308
// 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++]);
299
311
}
300
312
if (first1 == last1) {
301
313
first1 = 0 ;
@@ -308,7 +320,35 @@ class DoubleBufferedEPOutHandler : public EPHandler {
308
320
}
309
321
}
310
322
}
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 ;
312
352
}
313
353
}
314
354
@@ -318,82 +358,66 @@ class DoubleBufferedEPOutHandler : public EPHandler {
318
358
// W : last0/1, notify
319
359
if (usbd.epBank0IsTransferComplete (ep))
320
360
{
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 ) {
325
365
// 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 ();
338
374
}
339
375
}
340
376
} 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 ();
352
385
}
353
386
}
354
387
}
355
- release ( );
388
+ usbd. epAckPendingInterrupts (ep );
356
389
}
357
390
}
358
391
359
392
// 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 ();
374
401
}
375
402
376
403
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);
382
405
}
383
406
384
407
private:
385
408
USBDevice_SAMD21G18x &usbd;
386
409
410
+ RingBuffer _rx_buffer;
411
+
387
412
const uint32_t ep;
388
- const uint32_t size;
389
- uint32_t current, incoming;
413
+ volatile uint32_t current, incoming;
390
414
391
- volatile uint8_t * data0;
415
+ __attribute__ ((__aligned__( 4 ))) volatile uint8_t data0[size] ;
392
416
uint32_t first0;
393
417
volatile uint32_t last0;
394
418
volatile bool ready0;
395
419
396
- volatile uint8_t * data1;
420
+ __attribute__ ((__aligned__( 4 ))) volatile uint8_t data1[size] ;
397
421
uint32_t first1;
398
422
volatile uint32_t last1;
399
423
volatile bool ready1;
0 commit comments