Skip to content

Commit 7e68413

Browse files
committed
Track IN endpoint state
1 parent 018642f commit 7e68413

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

mod.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub struct Usbd<'c> {
7272
iso_in_used: bool,
7373
iso_out_used: bool,
7474
ep0_state: Mutex<Cell<EP0State>>,
75+
busy_in_endpoints: Mutex<Cell<u16>>,
7576

7677
// used to freeze `Clocks` and ensure they remain in the `ExternalOscillator` state
7778
_clocks: &'c (),
@@ -102,6 +103,7 @@ impl<'c> Usbd<'c> {
102103
in_transfer_state: TransferState::NoTransfer,
103104
is_set_address: false,
104105
})),
106+
busy_in_endpoints: Mutex::new(Cell::new(0)),
105107
_clocks: &(),
106108
})
107109
}
@@ -303,6 +305,8 @@ impl UsbBus for Usbd<'_> {
303305
regs.size.epout[i].reset();
304306
}
305307
}
308+
309+
self.busy_in_endpoints.borrow(cs).set(0);
306310
});
307311
}
308312

@@ -361,7 +365,11 @@ impl UsbBus for Usbd<'_> {
361365

362366
interrupt::free(|cs| {
363367
let regs = self.periph.borrow(cs);
368+
let busy_in_endpoints = self.busy_in_endpoints.borrow(cs);
364369

370+
if busy_in_endpoints.get() & (1 << i) != 0 {
371+
return Err(UsbError::WouldBlock);
372+
}
365373
if regs.epstatus.read().bits() & (1 << i) != 0 {
366374
return Err(UsbError::WouldBlock);
367375
}
@@ -436,6 +444,9 @@ impl UsbBus for Usbd<'_> {
436444
// Clear EPSTATUS.EPIN[i] flag
437445
regs.epstatus.write(|w| unsafe { w.bits(1 << i) });
438446

447+
// Mark the endpoint as busy
448+
busy_in_endpoints.set(busy_in_endpoints.get() | (1 << i));
449+
439450
Ok(buf.len())
440451
})
441452
}
@@ -547,6 +558,11 @@ impl UsbBus for Usbd<'_> {
547558
});
548559
}
549560
}
561+
562+
if stalled {
563+
let busy_in_endpoints = self.busy_in_endpoints.borrow(cs);
564+
busy_in_endpoints.set(busy_in_endpoints.get() & !(1 << ep_addr.index()));
565+
}
550566
});
551567
}
552568

@@ -576,6 +592,7 @@ impl UsbBus for Usbd<'_> {
576592
fn poll(&self) -> PollResult {
577593
interrupt::free(|cs| {
578594
let regs = self.periph.borrow(cs);
595+
let busy_in_endpoints = self.busy_in_endpoints.borrow(cs);
579596

580597
if regs.events_usbreset.read().events_usbreset().bit_is_set() {
581598
regs.events_usbreset.reset();
@@ -628,6 +645,9 @@ impl UsbBus for Usbd<'_> {
628645
let mut state = ep0_state.get();
629646
state.in_transfer_state = TransferState::NoTransfer;
630647
ep0_state.set(state);
648+
649+
// Mark the endpoint as not busy
650+
busy_in_endpoints.set(busy_in_endpoints.get() & !1);
631651
} else {
632652
// Do not clear OUT events, since we have to continue reporting them until the
633653
// buffer is read.
@@ -644,6 +664,9 @@ impl UsbBus for Usbd<'_> {
644664
regs.epdatastatus.write(|w| unsafe { w.bits(1 << i) });
645665

646666
in_complete |= 1 << i;
667+
668+
// Mark the endpoint as not busy
669+
busy_in_endpoints.set(busy_in_endpoints.get() & !(1 << i));
647670
}
648671
if epdatastatus & (1 << (i + 16)) != 0 {
649672
// EPDATASTATUS.EPOUT[i] is set

0 commit comments

Comments
 (0)