48
48
#define USB_CNTR_FRES USB_CNTR_USBRST
49
49
#endif
50
50
51
+ // Some chip variants do not define these fields
52
+ #ifndef USB_EP_DTOG_TX_Pos
53
+ #define USB_EP_DTOG_TX_Pos 6
54
+ #define USB_EP_DTOG_RX_Pos 14
55
+ #endif
56
+
51
57
52
58
/****************************************************************
53
59
* USB transfer memory
@@ -110,8 +116,8 @@ btable_configure(void)
110
116
epm_ep_desc_setup (0 , BUFRX , USB_CDC_EP0_SIZE );
111
117
epm_ep_desc_setup (USB_CDC_EP_ACM , BUFTX , 0 );
112
118
epm_ep_desc_setup (USB_CDC_EP_ACM , BUFRX , 0 );
113
- epm_ep_desc_setup (USB_CDC_EP_BULK_OUT , BUFTX , 0 );
114
- epm_ep_desc_setup (USB_CDC_EP_BULK_OUT , BUFRX , USB_CDC_EP_BULK_OUT_SIZE );
119
+ epm_ep_desc_setup (USB_CDC_EP_BULK_OUT , 0 , USB_CDC_EP_BULK_OUT_SIZE );
120
+ epm_ep_desc_setup (USB_CDC_EP_BULK_OUT , 1 , USB_CDC_EP_BULK_OUT_SIZE );
115
121
epm_ep_desc_setup (USB_CDC_EP_BULK_IN , BUFTX , 0 );
116
122
epm_ep_desc_setup (USB_CDC_EP_BULK_IN , BUFRX , 0 );
117
123
}
@@ -192,20 +198,41 @@ calc_epr_bits(uint32_t epr, uint32_t mask, uint32_t value)
192
198
return (((epr & (EPR_RWBITS | tmask )) ^ tvalue ) & ~rwmask ) | rwbits | cbits ;
193
199
}
194
200
201
+ // Check if double buffering endpoint hardware can no longer send/receive
202
+ static int
203
+ epr_is_dbuf_blocking (uint32_t epr )
204
+ {
205
+ return !(((epr >> (USB_EP_DTOG_RX_Pos - USB_EP_DTOG_TX_Pos )) ^ epr )
206
+ & USB_EP_DTOG_TX );
207
+ }
208
+
195
209
196
210
/****************************************************************
197
211
* USB interface
198
212
****************************************************************/
199
213
214
+ static uint32_t bulk_out_pop_count , bulk_out_push_flag ;
215
+
200
216
int_fast8_t
201
217
usb_read_bulk_out (void * data , uint_fast8_t max_len )
202
218
{
203
- uint32_t ep = USB_CDC_EP_BULK_OUT , epr = USB_EPR [ep ];
204
- if ((epr & USB_EPRX_STAT ) == USB_EP_RX_VALID )
219
+ if (readl (& bulk_out_push_flag ))
205
220
// No data ready
206
221
return -1 ;
207
- uint32_t count = btable_read_packet (ep , BUFRX , data , max_len );
208
- USB_EPR [ep ] = calc_epr_bits (epr , USB_EPRX_STAT , USB_EP_RX_VALID );
222
+ uint32_t ep = USB_CDC_EP_BULK_OUT ;
223
+ int bufnum = bulk_out_pop_count & 1 ;
224
+ bulk_out_pop_count ++ ;
225
+ uint32_t count = btable_read_packet (ep , bufnum , data , max_len );
226
+ writel (& bulk_out_push_flag , USB_EP_DTOG_TX );
227
+
228
+ // Check if irq handler pulled another packet before push flag update
229
+ uint32_t epr = USB_EPR [ep ];
230
+ if (epr_is_dbuf_blocking (epr ) && readl (& bulk_out_push_flag )) {
231
+ // Second packet was already read - must notify hardware
232
+ writel (& bulk_out_push_flag , 0 );
233
+ USB_EPR [ep ] = calc_epr_bits (epr , 0 , 0 ) | USB_EP_DTOG_TX ;
234
+ }
235
+
209
236
return count ;
210
237
}
211
238
@@ -275,6 +302,9 @@ usb_set_address(uint_fast8_t addr)
275
302
void
276
303
usb_set_configure (void )
277
304
{
305
+ uint32_t ep = USB_CDC_EP_BULK_OUT ;
306
+ bulk_out_pop_count = 0 ;
307
+ USB_EPR [ep ] = calc_epr_bits (USB_EPR [ep ], USB_EPRX_STAT , USB_EP_RX_VALID );
278
308
}
279
309
280
310
@@ -294,8 +324,9 @@ usb_reset(void)
294
324
| USB_EP_RX_NAK | USB_EP_TX_NAK );
295
325
296
326
ep = USB_CDC_EP_BULK_OUT ;
297
- USB_EPR [ep ] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK
298
- | USB_EP_RX_VALID | USB_EP_TX_NAK );
327
+ USB_EPR [ep ] = (USB_CDC_EP_BULK_OUT | USB_EP_BULK | USB_EP_KIND
328
+ | USB_EP_RX_VALID | USB_EP_TX_NAK | USB_EP_DTOG_TX );
329
+ bulk_out_push_flag = USB_EP_DTOG_TX ;
299
330
300
331
ep = USB_CDC_EP_BULK_IN ;
301
332
USB_EPR [ep ] = (USB_CDC_EP_BULK_IN | USB_EP_BULK
@@ -313,18 +344,22 @@ USB_IRQHandler(void)
313
344
if (istr & USB_ISTR_CTR ) {
314
345
// Endpoint activity
315
346
uint32_t ep = istr & USB_ISTR_EP_ID , epr = USB_EPR [ep ];
316
- USB_EPR [ep ] = calc_epr_bits (epr , USB_EP_CTR_RX | USB_EP_CTR_TX , 0 );
317
- if (ep == 0 ) {
347
+ if (ep == USB_CDC_EP_BULK_OUT ) {
348
+ USB_EPR [ep ] = (calc_epr_bits (epr , USB_EP_CTR_RX | USB_EP_CTR_TX , 0 )
349
+ | bulk_out_push_flag );
350
+ bulk_out_push_flag = 0 ;
351
+ usb_notify_bulk_out ();
352
+ } else if (ep == USB_CDC_EP_BULK_IN ) {
353
+ USB_EPR [ep ] = calc_epr_bits (epr , USB_EP_CTR_RX | USB_EP_CTR_TX , 0 );
354
+ usb_notify_bulk_in ();
355
+ } else if (ep == 0 ) {
356
+ USB_EPR [ep ] = calc_epr_bits (epr , USB_EP_CTR_RX | USB_EP_CTR_TX , 0 );
318
357
usb_notify_ep0 ();
319
358
if (epr & USB_EP_CTR_TX && set_address ) {
320
359
// Apply address after last "in" message transmitted
321
360
USB -> DADDR = set_address ;
322
361
set_address = 0 ;
323
362
}
324
- } else if (ep == USB_CDC_EP_BULK_OUT ) {
325
- usb_notify_bulk_out ();
326
- } else if (ep == USB_CDC_EP_BULK_IN ) {
327
- usb_notify_bulk_in ();
328
363
}
329
364
}
330
365
if (istr & USB_ISTR_RESET ) {
0 commit comments