@@ -195,6 +195,32 @@ void USBDevice_SAMD21G18x::calibrate() {
195195 usb.PADCAL .bit .TRIM = pad_trim;
196196}
197197
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+
198224/*
199225 * USB EP generic handlers.
200226 */
@@ -222,39 +248,51 @@ class DoubleBufferedEPOutHandler : public EPHandler {
222248 usbd.epBank0SetSize (ep, 64 );
223249 usbd.epBank0SetType (ep, 3 ); // BULK OUT
224250
225- usbd.epBank0SetAddress (ep, data0);
251+ usbd.epBank0SetAddress (ep, const_cast < uint8_t *>( data0) );
226252
227253 release ();
228254 }
229255
230256 // Read one byte from the buffer, if the buffer is empty -1 is returned
231257 int read () {
258+ // R/W: current, first0/1, ready0/1, notify
259+ // R : last0/1, data0/1
232260 if (current == 0 ) {
233- if (!ready0) {
234- return -1 ;
261+ synchronized {
262+ if (!ready0) {
263+ return -1 ;
264+ }
235265 }
266+ // when ready0==true the buffer is not being filled and last0 is constant
236267 if (first0 == last0) {
237268 first0 = 0 ;
238269 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+ }
243276 }
244277 return -1 ;
245278 }
246279 return data0[first0++];
247280 } else {
248- if (!ready1) {
249- return -1 ;
281+ synchronized {
282+ if (!ready1) {
283+ return -1 ;
284+ }
250285 }
286+ // when ready1==true the buffer is not being filled and last1 is constant
251287 if (first1 == last1) {
252288 first1 = 0 ;
253289 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+ }
258296 }
259297 return -1 ;
260298 }
@@ -264,40 +302,47 @@ class DoubleBufferedEPOutHandler : public EPHandler {
264302
265303 virtual void handleEndpoint ()
266304 {
305+ // R/W : incoming, ready0/1
306+ // W : last0/1, notify
267307 if (usbd.epBank0IsTransferComplete (ep))
268308 {
269309 // Ack Transfer complete
270310 usbd.epBank0AckTransferComplete (ep);
271- // usbd.epBank0AckTransferFailed(ep);
311+ // usbd.epBank0AckTransferFailed(ep); // XXX
272312
273313 // Update counters and swap banks
274314 if (incoming == 0 ) {
275315 last0 = usbd.epBank0ByteCount (ep);
276316 incoming = 1 ;
277- usbd.epBank0SetAddress (ep, data1);
317+ usbd.epBank0SetAddress (ep, const_cast < uint8_t *>( data1) );
278318 ready0 = true ;
279- if (ready1) {
280- notify = true ;
281- return ;
319+ synchronized {
320+ if (ready1) {
321+ notify = true ;
322+ return ;
323+ }
324+ notify = false ;
282325 }
283- notify = false ;
284326 } else {
285327 last1 = usbd.epBank0ByteCount (ep);
286328 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 ;
292337 }
293- notify = false ;
294338 }
295339 release ();
296340 }
297341 }
298342
299343 virtual uint32_t recv (void *_data, uint32_t len)
300344 {
345+ // TODO Write an optimized version of this one
301346 uint8_t *data = reinterpret_cast <uint8_t *>(_data);
302347 uint32_t i;
303348 for (i=0 ; i<len; i++) {
@@ -328,14 +373,16 @@ class DoubleBufferedEPOutHandler : public EPHandler {
328373 const uint32_t size;
329374 uint32_t current, incoming;
330375
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;
334380
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;
338385
339- bool notify;
386+ volatile bool notify;
340387};
341388
0 commit comments