Skip to content

Commit 4e7d60f

Browse files
committed
Fix many quirks in USB implementation
1 parent 46a36c9 commit 4e7d60f

File tree

3 files changed

+92
-51
lines changed

3 files changed

+92
-51
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Changelog
22

33
## [Unreleased]
4+
- Fix issues with USB that were affecting reliable operation.
45

56
## [v0.4.6] 2025-03-31
67

hal/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ embedded-hal = { version = "0.2.7" }
3333
nb = "1"
3434
fugit = "0.3.6"
3535
paste = "1"
36-
usb-device = "0.3.1"
36+
usb-device = "0.3.2"
3737
bit-iter = "1"
3838
rtic-monotonic = "1"
3939
void = { version = "1", default-features = false }

hal/src/usb.rs

Lines changed: 90 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ impl Endpoints {
141141

142142
struct Inner {
143143
endpoints: Endpoints,
144-
set_address: bool,
145144
}
146145

147146
/// [`usb_device`] implementation.
@@ -157,7 +156,6 @@ impl Usb {
157156

158157
let inner = Inner {
159158
endpoints: Endpoints::new(),
160-
set_address: false,
161159
};
162160

163161
Self {
@@ -277,6 +275,12 @@ impl Inner {
277275
.deveptidr_ctrl_mode(ep)
278276
.write(|w| w.stallrqc().set_bit());
279277

278+
if ep == 0 {
279+
self.reg()
280+
.devepticr_ctrl_mode(ep)
281+
.write(|w| w.rxoutic().set_bit());
282+
}
283+
280284
if ep != 0 {
281285
// Configure endpoint direction.
282286
self.reg()
@@ -292,9 +296,15 @@ impl Inner {
292296
.cfgok()
293297
.bit_is_set()
294298
{
295-
self.reg()
296-
.deveptier_ctrl_mode(ep)
297-
.write(|w| w.rxstpes().set_bit());
299+
if ep == 0 {
300+
self.reg()
301+
.deveptier_ctrl_mode(ep)
302+
.write(|w| w.rxstpes().set_bit());
303+
} else if conf.ep_dir == UsbDirection::Out {
304+
self.reg()
305+
.deveptier_blk_mode(ep)
306+
.write(|w| w.rxoutes().set_bit());
307+
}
298308
self.enable_endpoint_interrupt(ep);
299309
} else {
300310
todo!("endpoint configuration failed");
@@ -327,10 +337,7 @@ impl Inner {
327337
self.reg().devier().write(|w| {
328338
w.eorstes().set_bit();
329339
w.suspes().set_bit();
330-
w.wakeupes().set_bit();
331-
332-
// should we use this?
333-
w.sofes().set_bit();
340+
// w.wakeupes().set_bit();
334341

335342
w
336343
});
@@ -411,20 +418,19 @@ impl Inner {
411418
}
412419

413420
fn set_device_address(&mut self, addr: u8) {
414-
// Set the address in hardware, but do not enable it. This is
415-
// done in poll() on an TXINI.
421+
// Set the address in hardware and enable it.
416422
self.reg().devctrl().modify(|_, w| {
417423
unsafe {
418424
w.uadd().bits(addr);
419425
}
420-
w.adden().clear_bit();
426+
w.adden().set_bit();
421427
w
422428
});
423-
self.set_address = true;
424429
}
425430

426431
fn poll(&mut self) -> PollResult {
427432
let dev_isr = self.reg().devisr().read();
433+
let dev_imr = self.reg().devimr().read();
428434

429435
if dev_isr.eorst().bit_is_set() {
430436
// EORST - End of Reset, ack the interrupt and notify
@@ -433,6 +439,17 @@ impl Inner {
433439
return PollResult::Reset;
434440
}
435441

442+
if dev_isr.susp().bit_is_set() && dev_imr.suspe().bit_is_set() {
443+
self.reg().devicr().write(|w| w.suspc().set_bit());
444+
self.reg().devidr().write(|w| w.suspec().set_bit());
445+
self.reg().devier().write(|w| w.wakeupes().set_bit());
446+
}
447+
if dev_isr.wakeup().bit_is_set() && dev_imr.wakeupe().bit_is_set() {
448+
self.reg().devicr().write(|w| w.wakeupc().set_bit());
449+
self.reg().devidr().write(|w| w.wakeupec().set_bit());
450+
self.reg().devier().write(|w| w.suspes().set_bit());
451+
}
452+
436453
let mut ep_out = 0;
437454
let mut ep_in_complete = 0;
438455
let mut ep_setup = 0;
@@ -443,25 +460,35 @@ impl Inner {
443460
for ep in BitIter::from((dev_isr.bits() & DEVISR_PEPS_MASK) >> DEVISR_PEPS_OFFSET) {
444461
let sr = self.reg().deveptisr_ctrl_mode(ep).read();
445462

446-
// SETUP packet?
447-
if sr.rxstpi().bit_is_set() {
448-
ep_setup |= 1 << ep;
449-
};
450-
451463
// OUT packet?
452-
if sr.rxouti().bit_is_set() {
453-
ep_out |= 1 << ep;
454-
};
464+
if ep == 0 {
465+
let sr0 = self.reg().deveptisr_ctrl_mode(0).read();
466+
let mr0 = self.reg().deveptimr_ctrl_mode(0).read();
467+
if mr0.rxoute().bit_is_set() && sr0.rxouti().bit_is_set() {
468+
ep_out |= 1;
469+
}
470+
// SETUP packet?
471+
if ep_out == 0 {
472+
if sr0.rxstpi().bit_is_set() {
473+
ep_setup |= 1 << ep;
474+
};
475+
}
476+
} else {
477+
if sr.rxouti().bit_is_set() {
478+
ep_out |= 1 << ep;
479+
};
480+
}
455481

456482
// IN packet?
457483
if sr.txini().bit_is_set() {
458-
if self.set_address {
459-
// commit the new address
460-
self.reg().devctrl().modify(|_, w| w.adden().set_bit());
461-
self.set_address = false;
462-
}
463-
464484
ep_in_complete |= 1 << ep;
485+
486+
if ep == 0 {
487+
// disable TXINI interrupt
488+
self.reg()
489+
.deveptidr_ctrl_mode(ep)
490+
.write(|w| w.txinec().set_bit());
491+
}
465492
};
466493
}
467494

@@ -514,25 +541,27 @@ impl Inner {
514541

515542
fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> UsbResult<usize> {
516543
let ep = ep_addr.index();
517-
let len = core::cmp::min(
518-
self.reg().deveptisr_ctrl_mode(ep).read().byct().bits() as usize,
519-
buf.len(),
520-
);
544+
let deveptisr = self.reg().deveptisr_ctrl_mode(ep).read();
545+
let len = core::cmp::min(deveptisr.byct().bits() as _, buf.len());
521546

522547
self.read_fifo(ep, &mut buf[0..len]);
523548

524549
if ep == 0 {
525550
// control endpoints
526-
527-
// Clear RXSTPI interrupt, and make FIFO available
528-
self.reg()
529-
.devepticr_ctrl_mode(0)
530-
.write(|w| w.rxstpic().set_bit());
531-
532-
// Clear RXOUTI
533-
self.reg()
534-
.devepticr_ctrl_mode(0)
535-
.write(|w| w.rxoutic().set_bit());
551+
if deveptisr.rxouti().bit_is_set() {
552+
// Clear RXOUTI
553+
self.reg()
554+
.devepticr_ctrl_mode(0)
555+
.write(|w| w.rxoutic().set_bit());
556+
} else if deveptisr.rxstpi().bit_is_set() {
557+
// Clear RXSTPI interrupt, and make FIFO available
558+
self.reg()
559+
.devepticr_ctrl_mode(0)
560+
.write(|w| w.rxstpic().set_bit());
561+
} else {
562+
// Should never come here.
563+
return Err(UsbError::WouldBlock);
564+
}
536565
} else {
537566
// Other Endpoints
538567

@@ -550,21 +579,32 @@ impl Inner {
550579
Ok(len)
551580
}
552581

553-
fn is_stalled(&self, _ep: EndpointAddress) -> bool {
554-
// stub: seemingly not required
555-
false
582+
fn is_stalled(&self, ep_addr: EndpointAddress) -> bool {
583+
let ep = ep_addr.index();
584+
if ep == 0 {
585+
self.reg().deveptimr_ctrl_mode(ep).read().stallrq().bit()
586+
} else {
587+
false
588+
}
556589
}
557590

558-
fn set_stalled(&self, _ep: EndpointAddress, _stalled: bool) {
559-
// stub: seemingly not required
591+
fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool) {
592+
let ep = ep_addr.index();
593+
if ep == 0 {
594+
if stalled {
595+
self.reg()
596+
.deveptier_ctrl_mode(ep)
597+
.write(|w| w.stallrqs().set_bit());
598+
} else {
599+
self.reg()
600+
.deveptidr_ctrl_mode(ep)
601+
.write(|w| w.stallrqc().set_bit());
602+
}
603+
}
560604
}
561605
}
562606

563607
impl usb_device::bus::UsbBus for Usb {
564-
/// Ensure the address is set before write of zero sized packet to
565-
/// confirm a SET_ADDRESS transaction.
566-
const QUIRK_SET_ADDRESS_BEFORE_STATUS: bool = true;
567-
568608
fn enable(&mut self) {
569609
interrupt::free(|cs| unsafe { &mut *self.inner.borrow(cs).get() }.enable());
570610
}

0 commit comments

Comments
 (0)