22
22
#include " fsl_common.h"
23
23
#endif
24
24
#include " USBHAL.h"
25
+ #include " mbed_critical.h"
25
26
26
27
USBHAL * USBHAL::instance;
27
28
@@ -64,6 +65,13 @@ typedef struct BDT {
64
65
uint32_t address; // Addr
65
66
} BDT;
66
67
68
+ typedef enum {
69
+ CTRL_XFER_READY,
70
+ CTRL_XFER_IN,
71
+ CTRL_XFER_NONE,
72
+ CTRL_XFER_OUT
73
+ } ctrl_xfer_t ;
74
+
67
75
// there are:
68
76
// * 4 bidirectionnal endpt -> 8 physical endpt
69
77
// * as there are ODD and EVEN buffer -> 8*2 bdt
@@ -73,6 +81,7 @@ uint8_t * endpoint_buffer[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
73
81
74
82
static uint8_t set_addr = 0 ;
75
83
static uint8_t addr = 0 ;
84
+ static ctrl_xfer_t ctrl_xfer = CTRL_XFER_READY;
76
85
77
86
static uint32_t Data1 = 0x55555555 ;
78
87
@@ -223,11 +232,16 @@ bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flag
223
232
USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran.
224
233
bdt[EP_BDT_IDX (log_endpoint, RX, ODD )].byte_count = maxPacket;
225
234
bdt[EP_BDT_IDX (log_endpoint, RX, ODD )].address = (uint32_t ) buf;
226
- bdt[EP_BDT_IDX (log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK;
235
+ bdt[EP_BDT_IDX (log_endpoint, RX, ODD )].info = BD_DTS_MASK;
227
236
bdt[EP_BDT_IDX (log_endpoint, RX, EVEN)].info = 0 ;
237
+ if (log_endpoint == 0 ) {
238
+ // Prepare for setup packet
239
+ bdt[EP_BDT_IDX (log_endpoint, RX, ODD )].info |= BD_OWN_MASK;
240
+ }
228
241
}
229
242
230
- Data1 |= (1 << endpoint);
243
+ // First transfer will be a DATA0 packet
244
+ Data1 &= ~(1 << endpoint);
231
245
232
246
return true ;
233
247
}
@@ -239,13 +253,35 @@ void USBHAL::EP0setup(uint8_t *buffer) {
239
253
}
240
254
241
255
void USBHAL::EP0readStage (void ) {
242
- Data1 &= ~1UL ; // set DATA0
243
- bdt[0 ].info = (BD_DTS_MASK | BD_OWN_MASK);
256
+ // Not needed
244
257
}
245
258
246
259
void USBHAL::EP0read (void ) {
247
- uint32_t idx = EP_BDT_IDX (PHY_TO_LOG (EP0OUT), RX, 0 );
248
- bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
260
+ if (ctrl_xfer == CTRL_XFER_READY) {
261
+ // Transfer is done so ignore call
262
+ return ;
263
+ }
264
+ if (ctrl_xfer == CTRL_XFER_IN) {
265
+ ctrl_xfer = CTRL_XFER_READY;
266
+ // Control transfer with a data IN stage.
267
+ // The next packet received will be the status packet - an OUT packet using DATA1
268
+ //
269
+ // PROBLEM:
270
+ // If a Setup packet is received after status packet of
271
+ // a Control In transfer has been received in the RX buffer
272
+ // but before the processor has had a chance the prepare
273
+ // this buffer for the Setup packet, the Setup packet
274
+ // will be dropped.
275
+ //
276
+ // WORKAROUND:
277
+ // Set data toggle to DATA0 so if the status stage of a
278
+ // Control In transfer arrives it will be ACKed by hardware
279
+ // but will be discarded without filling the RX buffer.
280
+ // This allows a subsequent SETUP packet to be stored
281
+ // without any processor intervention.
282
+ Data1 &= ~1UL ; // set DATA0
283
+ }
284
+ endpointRead (EP0OUT, MAX_PACKET_SIZE_EP0);
249
285
}
250
286
251
287
uint32_t USBHAL::EP0getReadResult (uint8_t *buffer) {
@@ -255,20 +291,50 @@ uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
255
291
}
256
292
257
293
void USBHAL::EP0write (uint8_t *buffer, uint32_t size) {
294
+ if (ctrl_xfer == CTRL_XFER_READY) {
295
+ // Transfer is done so ignore call
296
+ return ;
297
+ }
298
+ if ((ctrl_xfer == CTRL_XFER_NONE) || (ctrl_xfer == CTRL_XFER_OUT)) {
299
+ // Prepare for next setup packet
300
+ endpointRead (EP0OUT, MAX_PACKET_SIZE_EP0);
301
+ ctrl_xfer = CTRL_XFER_READY;
302
+ }
258
303
endpointWrite (EP0IN, buffer, size);
259
304
}
260
305
261
306
void USBHAL::EP0getWriteResult (void ) {
262
307
}
263
308
264
309
void USBHAL::EP0stall (void ) {
310
+ if (ctrl_xfer == CTRL_XFER_READY) {
311
+ // Transfer is done so ignore call
312
+ return ;
313
+ }
314
+ ctrl_xfer = CTRL_XFER_READY;
315
+ core_util_critical_section_enter ();
265
316
stallEndpoint (EP0OUT);
317
+ // Prepare for next setup packet
318
+ // Note - time between stalling and setting up the endpoint
319
+ // must be kept to a minimum to prevent a dropped SETUP
320
+ // packet.
321
+ endpointRead (EP0OUT, MAX_PACKET_SIZE_EP0);
322
+ core_util_critical_section_exit ();
266
323
}
267
324
268
325
EP_STATUS USBHAL::endpointRead (uint8_t endpoint, uint32_t maximumSize) {
269
- endpoint = PHY_TO_LOG (endpoint);
270
- uint32_t idx = EP_BDT_IDX (endpoint, RX, 0 );
326
+ uint8_t log_endpoint = PHY_TO_LOG (endpoint);
327
+
328
+ uint32_t idx = EP_BDT_IDX (log_endpoint, RX, 0 );
271
329
bdt[idx].byte_count = maximumSize;
330
+ if ((Data1 >> endpoint) & 1 ) {
331
+ bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
332
+ }
333
+ else {
334
+ bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
335
+ }
336
+
337
+ Data1 ^= (1 << endpoint);
272
338
return EP_PENDING;
273
339
}
274
340
@@ -307,18 +373,14 @@ EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_
307
373
buffer[n] = ep_buf[n];
308
374
}
309
375
310
- if (((Data1 >> endpoint) & 1 ) == ((bdt[idx].info >> 6 ) & 1 )) {
311
- if (setup && (buffer[6 ] == 0 )) // if no setup data stage,
312
- Data1 &= ~1UL ; // set DATA0
313
- else
314
- Data1 ^= (1 << endpoint);
315
- }
316
-
317
- if (((Data1 >> endpoint) & 1 )) {
318
- bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
319
- }
320
- else {
321
- bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
376
+ if (setup) {
377
+ // Record the setup type
378
+ if (buffer[6 ] == 0 ) {
379
+ ctrl_xfer = CTRL_XFER_NONE;
380
+ } else {
381
+ uint8_t in_xfer = (buffer[0 ] >> 7 ) & 1 ;
382
+ ctrl_xfer = in_xfer ? CTRL_XFER_IN : CTRL_XFER_OUT;
383
+ }
322
384
}
323
385
324
386
USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
@@ -351,9 +413,9 @@ EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
351
413
}
352
414
353
415
if ((Data1 >> endpoint) & 1 ) {
354
- bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
355
- } else {
356
416
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
417
+ } else {
418
+ bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
357
419
}
358
420
359
421
Data1 ^= (1 << endpoint);
@@ -450,7 +512,7 @@ void USBHAL::usbisr(void) {
450
512
451
513
// setup packet
452
514
if ((num == 0 ) && (TOK_PID ((EP_BDT_IDX (num, dir, ev_odd))) == SETUP_TOKEN)) {
453
- Data1 &= ~ 0x02 ;
515
+ Data1 |= 0x02 | 0x01 ; // set DATA1 for TX and RX
454
516
bdt[EP_BDT_IDX (0 , TX, EVEN)].info &= ~BD_OWN_MASK;
455
517
bdt[EP_BDT_IDX (0 , TX, ODD)].info &= ~BD_OWN_MASK;
456
518
0 commit comments