Skip to content

Commit

Permalink
Use USB OUT endpoint transfer failed interrupt
Browse files Browse the repository at this point in the history
Previously, when the USB interrupt was unmasked and a host issued an OUT
transfer that was not subsequently `read()`, the interrupt would
continually fire until `read()` was called.  This change provides a way
for a USB class to acknowledge the transfer without reading the data,
and so clear the interrupt flag.
  • Loading branch information
ianrrees committed Jul 1, 2021
1 parent 8c40356 commit 1e4c163
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 6 deletions.
13 changes: 10 additions & 3 deletions hal/src/thumbv6m/usb/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ impl<'a> Bank<'a, OutBank> {
/// Enables endpoint-specific interrupts.
fn setup_ep_interrupts(&mut self) {
self.epintenset(self.index())
.write(|w| w.rxstp().set_bit().trcpt0().set_bit());
.write(|w| w.rxstp().set_bit().trfail0().set_bit().trcpt0().set_bit());
}

/// Copies data from the bank0 buffer to the provided array. The caller
Expand Down Expand Up @@ -920,7 +920,11 @@ impl Inner {
// instead it is cleared in the read handler.
}

if bank0.is_transfer_complete() {
// A class may have used an empty read, via .read(&mut[]), on an OUT
// endpoint to signal that the class is not ready to receive more
// data. That action clears the transfer complete and failed flags,
// but not bk0rdy. So, check .is_ready() here.
if bank0.is_ready() {
dbgprint!("ep {} READABLE\n", ep);
ep_out |= mask;
}
Expand Down Expand Up @@ -978,7 +982,10 @@ impl Inner {
// self.print_epstatus(idx, "read");

bank.clear_transfer_complete();
bank.set_ready(false);

if buf.len() != 0 {
bank.set_ready(false);
}

drop(bank);

Expand Down
13 changes: 10 additions & 3 deletions hal/src/thumbv7em/usb/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ impl<'a> Bank<'a, OutBank> {
/// Enables endpoint-specific interrupts.
fn setup_ep_interrupts(&mut self) {
self.epintenset(self.index())
.write(|w| w.rxstp().set_bit().trcpt0().set_bit());
.write(|w| w.rxstp().set_bit().trfail0().set_bit().trcpt0().set_bit());
}

/// Copies data from the bank0 buffer to the provided array. The caller
Expand Down Expand Up @@ -866,7 +866,11 @@ impl Inner {
// instead it is cleared in the read handler.
}

if bank0.is_transfer_complete() {
// A class may have used an empty read, via .read(&mut[]), on an OUT
// endpoint to signal that the class is not ready to receive more
// data. That action clears the transfer complete and failed flags,
// but not bk0rdy. So, check .is_ready() here.
if bank0.is_ready() {
dbgprint!("ep {} READABLE\n", ep);
ep_out |= mask;
}
Expand Down Expand Up @@ -924,7 +928,10 @@ impl Inner {
// self.print_epstatus(idx, "read");

bank.clear_transfer_complete();
bank.set_ready(false);

if buf.len() != 0 {
bank.set_ready(false);
}

drop(bank);

Expand Down

0 comments on commit 1e4c163

Please sign in to comment.