@@ -195,6 +195,32 @@ void USBDevice_SAMD21G18x::calibrate() {
195
195
usb.PADCAL .bit .TRIM = pad_trim;
196
196
}
197
197
198
+ /*
199
+ * Synchronization primitives.
200
+ * TODO: Move into a separate header file and make an API out of it
201
+ */
202
+
203
+ class __Guard {
204
+ public:
205
+ __Guard () : primask(__get_PRIMASK()), loops(1 ) {
206
+ __disable_irq ();
207
+ }
208
+ ~__Guard () {
209
+ if (primask == 0 ) {
210
+ __enable_irq ();
211
+ // http://infocenter.arm.com/help/topic/com.arm.doc.dai0321a/BIHBFEIB.html
212
+ __ISB ();
213
+ }
214
+ }
215
+ uint32_t enter () { return loops--; }
216
+ private:
217
+ uint32_t primask;
218
+ uint32_t loops;
219
+ };
220
+
221
+ #define synchronized for (__Guard __guard; __guard.enter(); )
222
+
223
+
198
224
/*
199
225
* USB EP generic handlers.
200
226
*/
@@ -222,39 +248,51 @@ class DoubleBufferedEPOutHandler : public EPHandler {
222
248
usbd.epBank0SetSize (ep, 64 );
223
249
usbd.epBank0SetType (ep, 3 ); // BULK OUT
224
250
225
- usbd.epBank0SetAddress (ep, data0);
251
+ usbd.epBank0SetAddress (ep, const_cast < uint8_t *>( data0) );
226
252
227
253
release ();
228
254
}
229
255
230
256
// Read one byte from the buffer, if the buffer is empty -1 is returned
231
257
int read () {
258
+ // R/W: current, first0/1, ready0/1, notify
259
+ // R : last0/1, data0/1
232
260
if (current == 0 ) {
233
- if (!ready0) {
234
- return -1 ;
261
+ synchronized {
262
+ if (!ready0) {
263
+ return -1 ;
264
+ }
235
265
}
266
+ // when ready0==true the buffer is not being filled and last0 is constant
236
267
if (first0 == last0) {
237
268
first0 = 0 ;
238
269
current = 1 ;
239
- ready0 = false ;
240
- if (notify) {
241
- notify = false ;
242
- release ();
270
+ synchronized {
271
+ ready0 = false ;
272
+ if (notify) {
273
+ notify = false ;
274
+ release ();
275
+ }
243
276
}
244
277
return -1 ;
245
278
}
246
279
return data0[first0++];
247
280
} else {
248
- if (!ready1) {
249
- return -1 ;
281
+ synchronized {
282
+ if (!ready1) {
283
+ return -1 ;
284
+ }
250
285
}
286
+ // when ready1==true the buffer is not being filled and last1 is constant
251
287
if (first1 == last1) {
252
288
first1 = 0 ;
253
289
current = 0 ;
254
- ready1 = false ;
255
- if (notify) {
256
- notify = false ;
257
- release ();
290
+ synchronized {
291
+ ready1 = false ;
292
+ if (notify) {
293
+ notify = false ;
294
+ release ();
295
+ }
258
296
}
259
297
return -1 ;
260
298
}
@@ -264,40 +302,47 @@ class DoubleBufferedEPOutHandler : public EPHandler {
264
302
265
303
virtual void handleEndpoint ()
266
304
{
305
+ // R/W : incoming, ready0/1
306
+ // W : last0/1, notify
267
307
if (usbd.epBank0IsTransferComplete (ep))
268
308
{
269
309
// Ack Transfer complete
270
310
usbd.epBank0AckTransferComplete (ep);
271
- // usbd.epBank0AckTransferFailed(ep);
311
+ // usbd.epBank0AckTransferFailed(ep); // XXX
272
312
273
313
// Update counters and swap banks
274
314
if (incoming == 0 ) {
275
315
last0 = usbd.epBank0ByteCount (ep);
276
316
incoming = 1 ;
277
- usbd.epBank0SetAddress (ep, data1);
317
+ usbd.epBank0SetAddress (ep, const_cast < uint8_t *>( data1) );
278
318
ready0 = true ;
279
- if (ready1) {
280
- notify = true ;
281
- return ;
319
+ synchronized {
320
+ if (ready1) {
321
+ notify = true ;
322
+ return ;
323
+ }
324
+ notify = false ;
282
325
}
283
- notify = false ;
284
326
} else {
285
327
last1 = usbd.epBank0ByteCount (ep);
286
328
incoming = 0 ;
287
- usbd.epBank0SetAddress (ep, data0);
288
- ready1 = true ;
289
- if (ready0) {
290
- notify = true ;
291
- return ;
329
+ usbd.epBank0SetAddress (ep, const_cast <uint8_t *>(data0));
330
+ synchronized {
331
+ ready1 = true ;
332
+ if (ready0) {
333
+ notify = true ;
334
+ return ;
335
+ }
336
+ notify = false ;
292
337
}
293
- notify = false ;
294
338
}
295
339
release ();
296
340
}
297
341
}
298
342
299
343
virtual uint32_t recv (void *_data, uint32_t len)
300
344
{
345
+ // TODO Write an optimized version of this one
301
346
uint8_t *data = reinterpret_cast <uint8_t *>(_data);
302
347
uint32_t i;
303
348
for (i=0 ; i<len; i++) {
@@ -328,14 +373,16 @@ class DoubleBufferedEPOutHandler : public EPHandler {
328
373
const uint32_t size;
329
374
uint32_t current, incoming;
330
375
331
- uint8_t *data0;
332
- uint32_t first0, last0;
333
- bool ready0;
376
+ volatile uint8_t *data0;
377
+ uint32_t first0;
378
+ volatile uint32_t last0;
379
+ volatile bool ready0;
334
380
335
- uint8_t *data1;
336
- uint32_t first1, last1;
337
- bool ready1;
381
+ volatile uint8_t *data1;
382
+ uint32_t first1;
383
+ volatile uint32_t last1;
384
+ volatile bool ready1;
338
385
339
- bool notify;
386
+ volatile bool notify;
340
387
};
341
388
0 commit comments