Skip to content

Commit 49adbda

Browse files
committed
Fix many quirks in USB implementation
1 parent 46a36c9 commit 49adbda

File tree

3 files changed

+84
-57
lines changed

3 files changed

+84
-57
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: 82 additions & 56 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");
@@ -326,11 +336,6 @@ impl Inner {
326336
// enable interrupts
327337
self.reg().devier().write(|w| {
328338
w.eorstes().set_bit();
329-
w.suspes().set_bit();
330-
w.wakeupes().set_bit();
331-
332-
// should we use this?
333-
w.sofes().set_bit();
334339

335340
w
336341
});
@@ -411,16 +416,14 @@ impl Inner {
411416
}
412417

413418
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.
419+
// Set the address in hardware and enable it.
416420
self.reg().devctrl().modify(|_, w| {
417421
unsafe {
418422
w.uadd().bits(addr);
419423
}
420-
w.adden().clear_bit();
424+
w.adden().set_bit();
421425
w
422426
});
423-
self.set_address = true;
424427
}
425428

426429
fn poll(&mut self) -> PollResult {
@@ -441,27 +444,37 @@ impl Inner {
441444
const DEVISR_PEPS_MASK: u32 = 0x3ff000;
442445
const DEVISR_PEPS_OFFSET: u8 = 12;
443446
for ep in BitIter::from((dev_isr.bits() & DEVISR_PEPS_MASK) >> DEVISR_PEPS_OFFSET) {
444-
let sr = self.reg().deveptisr_ctrl_mode(ep).read();
445-
446-
// SETUP packet?
447-
if sr.rxstpi().bit_is_set() {
448-
ep_setup |= 1 << ep;
449-
};
450-
451-
// OUT packet?
452-
if sr.rxouti().bit_is_set() {
453-
ep_out |= 1 << ep;
454-
};
447+
let isr = self.reg().deveptisr_ctrl_mode(ep).read();
455448

456-
// IN packet?
457-
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;
449+
if ep == 0 {
450+
// OUT packet?
451+
let imr = self.reg().deveptimr_ctrl_mode(ep).read();
452+
if isr.rxouti().bit_is_set() && imr.rxoute().bit_is_set() {
453+
ep_out |= 1;
454+
}
455+
// SETUP packet?
456+
if ep_out == 0 {
457+
if isr.rxstpi().bit_is_set() {
458+
ep_setup |= 1;
459+
};
460+
}
461+
// IN packet?
462+
if isr.txini().bit_is_set() && imr.txine().bit_is_set() {
463+
ep_in_complete |= 1;
464+
// disable TXINI interrupt
465+
self.reg()
466+
.deveptidr_ctrl_mode(ep)
467+
.write(|w| w.txinec().set_bit());
468+
}
469+
} else {
470+
// OUT packet?
471+
if isr.rxouti().bit_is_set() {
472+
ep_out |= 1 << ep;
473+
};
474+
// IN packet?
475+
if isr.txini().bit_is_set() {
476+
ep_in_complete |= 1 << ep;
462477
}
463-
464-
ep_in_complete |= 1 << ep;
465478
};
466479
}
467480

@@ -514,25 +527,27 @@ impl Inner {
514527

515528
fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> UsbResult<usize> {
516529
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-
);
530+
let isr = self.reg().deveptisr_ctrl_mode(ep).read();
531+
let len = core::cmp::min(isr.byct().bits() as _, buf.len());
521532

522533
self.read_fifo(ep, &mut buf[0..len]);
523534

524535
if ep == 0 {
525536
// 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());
537+
if isr.rxouti().bit_is_set() {
538+
// Clear RXOUTI
539+
self.reg()
540+
.devepticr_ctrl_mode(0)
541+
.write(|w| w.rxoutic().set_bit());
542+
} else if isr.rxstpi().bit_is_set() {
543+
// Clear RXSTPI interrupt, and make FIFO available
544+
self.reg()
545+
.devepticr_ctrl_mode(0)
546+
.write(|w| w.rxstpic().set_bit());
547+
} else {
548+
// Should never come here.
549+
return Err(UsbError::WouldBlock);
550+
}
536551
} else {
537552
// Other Endpoints
538553

@@ -550,21 +565,32 @@ impl Inner {
550565
Ok(len)
551566
}
552567

553-
fn is_stalled(&self, _ep: EndpointAddress) -> bool {
554-
// stub: seemingly not required
555-
false
568+
fn is_stalled(&self, ep_addr: EndpointAddress) -> bool {
569+
let ep = ep_addr.index();
570+
if ep == 0 {
571+
self.reg().deveptimr_ctrl_mode(ep).read().stallrq().bit()
572+
} else {
573+
false
574+
}
556575
}
557576

558-
fn set_stalled(&self, _ep: EndpointAddress, _stalled: bool) {
559-
// stub: seemingly not required
577+
fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool) {
578+
let ep = ep_addr.index();
579+
if ep == 0 {
580+
if stalled {
581+
self.reg()
582+
.deveptier_ctrl_mode(ep)
583+
.write(|w| w.stallrqs().set_bit());
584+
} else {
585+
self.reg()
586+
.deveptidr_ctrl_mode(ep)
587+
.write(|w| w.stallrqc().set_bit());
588+
}
589+
}
560590
}
561591
}
562592

563593
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-
568594
fn enable(&mut self) {
569595
interrupt::free(|cs| unsafe { &mut *self.inner.borrow(cs).get() }.enable());
570596
}

0 commit comments

Comments
 (0)