@@ -61,6 +61,10 @@ class USBDevice_SAMD21G18x {
6161 inline void noRunInStandby () { usb.CTRLA .bit .RUNSTDBY = 0 ; }
6262 inline void wakeupHost () { usb.CTRLB .bit .UPRSM = 1 ; }
6363
64+ // USB QoS
65+ inline void setDataSensitiveQoS () { usb.QOSCTRL .bit .DQOS = 2 ; }
66+ inline void setConfigSensitiveQoS () { usb.QOSCTRL .bit .CQOS = 2 ; }
67+
6468 // USB speed
6569 inline void setFullSpeed () { usb.CTRLB .bit .SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val; }
6670 inline void setLowSpeed () { usb.CTRLB .bit .SPDCONF = USB_DEVICE_CTRLB_SPDCONF_LS_Val; }
@@ -102,27 +106,37 @@ class USBDevice_SAMD21G18x {
102106 // Interrupts
103107 inline uint16_t epInterruptSummary () { return usb.EPINTSMRY .reg ; }
104108
109+ inline bool epHasPendingInterrupts (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .reg != 0 ; }
105110 inline bool epBank0IsSetupReceived (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .RXSTP ; }
106111 inline bool epBank0IsStalled (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .STALL0 ; }
107112 inline bool epBank1IsStalled (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .STALL1 ; }
113+ inline bool epBank0IsTransferFailed (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .TRFAIL0 ; }
114+ inline bool epBank1IsTransferFailed (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .TRFAIL1 ; }
108115 inline bool epBank0IsTransferComplete (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .TRCPT0 ; }
109116 inline bool epBank1IsTransferComplete (ep_t ep) { return usb.DeviceEndpoint [ep].EPINTFLAG .bit .TRCPT1 ; }
110117
118+ inline void epAckPendingInterrupts (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = 0x7F ; }
111119 inline void epBank0AckSetupReceived (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_RXSTP; }
112120 inline void epBank0AckStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_STALL (1 ); }
113121 inline void epBank1AckStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_STALL (2 ); }
122+ inline void epBank0AckTransferFailed (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_TRFAIL (1 ); }
123+ inline void epBank1AckTransferFailed (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_TRFAIL (2 ); }
114124 inline void epBank0AckTransferComplete (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_TRCPT (1 ); }
115125 inline void epBank1AckTransferComplete (ep_t ep) { usb.DeviceEndpoint [ep].EPINTFLAG .reg = USB_DEVICE_EPINTFLAG_TRCPT (2 ); }
116126
117127 inline void epBank0EnableSetupReceived (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENSET .bit .RXSTP = 1 ; }
118128 inline void epBank0EnableStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENSET .bit .STALL0 = 1 ; }
119129 inline void epBank1EnableStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENSET .bit .STALL1 = 1 ; }
130+ inline void epBank0EnableTransferFailed (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENSET .bit .TRFAIL0 = 1 ; }
131+ inline void epBank1EnableTransferFailed (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENSET .bit .TRFAIL1 = 1 ; }
120132 inline void epBank0EnableTransferComplete (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENSET .bit .TRCPT0 = 1 ; }
121133 inline void epBank1EnableTransferComplete (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENSET .bit .TRCPT1 = 1 ; }
122134
123135 inline void epBank0DisableSetupReceived (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENCLR .bit .RXSTP = 1 ; }
124136 inline void epBank0DisableStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENCLR .bit .STALL0 = 1 ; }
125137 inline void epBank1DisableStalled (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENCLR .bit .STALL1 = 1 ; }
138+ inline void epBank0DisableTransferFailed (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENCLR .bit .TRFAIL0 = 1 ; }
139+ inline void epBank1DisableTransferFailed (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENCLR .bit .TRFAIL1 = 1 ; }
126140 inline void epBank0DisableTransferComplete (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENCLR .bit .TRCPT0 = 1 ; }
127141 inline void epBank1DisableTransferComplete (ep_t ep) { usb.DeviceEndpoint [ep].EPINTENCLR .bit .TRCPT1 = 1 ; }
128142
@@ -170,6 +184,15 @@ class USBDevice_SAMD21G18x {
170184 inline void epBank0EnableAutoZLP (ep_t ep) { EP[ep].DeviceDescBank [0 ].PCKSIZE .bit .AUTO_ZLP = 1 ; }
171185 inline void epBank1EnableAutoZLP (ep_t ep) { EP[ep].DeviceDescBank [1 ].PCKSIZE .bit .AUTO_ZLP = 1 ; }
172186
187+ // USB Device Endpoint transactions helpers
188+ // ----------------------------------------
189+
190+ inline void epReleaseOutBank0 (ep_t ep, uint16_t s) {
191+ epBank0SetMultiPacketSize (ep, s);
192+ epBank0SetByteCount (ep, 0 );
193+ epBank0ResetReady (ep);
194+ }
195+
173196private:
174197 // USB Device registers
175198 UsbDevice &usb;
@@ -211,9 +234,9 @@ class EPHandler {
211234public:
212235 virtual void handleEndpoint () = 0;
213236 virtual uint32_t recv (void *_data, uint32_t len) = 0;
214- virtual uint32_t available () const = 0;
215-
216237 virtual void init () = 0;
238+ virtual uint32_t available () = 0;
239+ virtual int peek () = 0;
217240};
218241
219242class DoubleBufferedEPOutHandler : public EPHandler {
@@ -233,19 +256,23 @@ class DoubleBufferedEPOutHandler : public EPHandler {
233256 usbd.epBank0SetType (ep, 3 ); // BULK OUT
234257
235258 usbd.epBank0SetAddress (ep, const_cast <uint8_t *>(data0));
259+ usbd.epBank0EnableTransferComplete (ep);
236260
237261 release ();
238262 }
239263
240264 virtual ~DoubleBufferedEPOutHandler () {
241- free ((void *)data0);
242- free ((void *)data1);
243265 }
244266 void init () {};
245267
246- virtual uint32_t recv ( void *_data, uint32_t len )
268+ uint32_t _recv ( )
247269 {
248- uint8_t *data = reinterpret_cast <uint8_t *>(_data);
270+ uint32_t i = 0 ;
271+ uint32_t len = 0 ;
272+
273+ synchronized {
274+ len = _rx_buffer.availableForStore ();
275+ }
249276
250277 // R/W: current, first0/1, ready0/1, notify
251278 // R : last0/1, data0/1
@@ -256,9 +283,8 @@ class DoubleBufferedEPOutHandler : public EPHandler {
256283 }
257284 }
258285 // when ready0==true the buffer is not being filled and last0 is constant
259- uint32_t i;
260- for (i=0 ; i<len && first0 < last0; i++) {
261- data[i] = data0[first0++];
286+ for (; i<len && first0 < last0; i++) {
287+ _rx_buffer.store_char (data0[first0++]);
262288 }
263289 if (first0 == last0) {
264290 first0 = 0 ;
@@ -279,9 +305,8 @@ class DoubleBufferedEPOutHandler : public EPHandler {
279305 }
280306 }
281307 // when ready1==true the buffer is not being filled and last1 is constant
282- uint32_t i;
283- for (i=0 ; i<len && first1 < last1; i++) {
284- data[i] = data1[first1++];
308+ for (; i<len && first1 < last1; i++) {
309+ _rx_buffer.store_char (data1[first1++]);
285310 }
286311 if (first1 == last1) {
287312 first1 = 0 ;
@@ -298,6 +323,34 @@ class DoubleBufferedEPOutHandler : public EPHandler {
298323 }
299324 }
300325
326+ virtual uint32_t recv (void *_data, uint32_t len) {
327+ _recv ();
328+ uint32_t i = 0 ;
329+ uint8_t *data = reinterpret_cast <uint8_t *>(_data);
330+ synchronized {
331+ for (; i < len && _rx_buffer.available (); i++) {
332+ data[i] = _rx_buffer.read_char ();
333+ }
334+ }
335+ return i;
336+ }
337+
338+ virtual uint32_t _available () const {
339+ if (current == 0 ) {
340+ bool ready = ready0;
341+ synchronized {
342+ ready = ready0;
343+ }
344+ return ready ? (last0 - first0) : 0 ;
345+ } else {
346+ bool ready = false ;
347+ synchronized {
348+ ready = ready1;
349+ }
350+ return ready ? (last1 - first1) : 0 ;
351+ }
352+ }
353+
301354 virtual void handleEndpoint ()
302355 {
303356 // R/W : incoming, ready0/1
@@ -340,39 +393,34 @@ class DoubleBufferedEPOutHandler : public EPHandler {
340393 }
341394 release ();
342395 }
396+ if (usbd.epBank0IsTransferComplete (ep) || usbd.epBank1IsTransferComplete (ep)) {
397+ usbd.epAckPendingInterrupts (ep);
398+ }
343399 }
344400
345401 // Returns how many bytes are stored in the buffers
346- virtual uint32_t available () const {
347- if (current == 0 ) {
348- bool ready = false ;
349- synchronized {
350- ready = ready0;
351- }
352- return ready ? (last0 - first0) : 0 ;
353- } else {
354- bool ready = false ;
355- synchronized {
356- ready = ready1;
357- }
358- return ready ? (last1 - first1) : 0 ;
359- }
402+ virtual uint32_t available () {
403+ _recv ();
404+ return _rx_buffer.available ();
405+ }
406+
407+ virtual int peek () {
408+ _recv ();
409+ return _rx_buffer.peek ();
360410 }
361411
362412 void release () {
363- // Release OUT EP
364- usbd.epBank0EnableTransferComplete (ep);
365- usbd.epBank0SetMultiPacketSize (ep, size);
366- usbd.epBank0SetByteCount (ep, 0 );
367- usbd.epBank0ResetReady (ep);
413+ usbd.epReleaseOutBank0 (ep, size);
368414 }
369415
370416private:
371417 USBDevice_SAMD21G18x &usbd;
372418
419+ RingBuffer _rx_buffer;
420+
373421 const uint32_t ep;
374422 const uint32_t size;
375- uint32_t current, incoming;
423+ volatile uint32_t current, incoming;
376424
377425 volatile uint8_t *data0;
378426 uint32_t first0;
0 commit comments