From 786062aa74dc9d160d13e104b9d7991525ac8b1f Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 2 Aug 2022 22:04:07 +0000 Subject: [PATCH 1/2] To clear a bit in sie_status, just write that single bit --- rp2040-hal/src/usb.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rp2040-hal/src/usb.rs b/rp2040-hal/src/usb.rs index c98ee49..0a36dc6 100644 --- a/rp2040-hal/src/usb.rs +++ b/rp2040-hal/src/usb.rs @@ -544,7 +544,7 @@ impl UsbBusTrait for UsbBus { inner .ctrl_reg .sie_status - .modify(|_, w| w.suspended().set_bit()); + .write(|w| w.suspended().set_bit()); }); } fn resume(&self) { @@ -553,7 +553,7 @@ impl UsbBusTrait for UsbBus { inner .ctrl_reg .sie_status - .modify(|_, w| w.resume().set_bit()); + .write(|w| w.resume().set_bit()); }); } fn poll(&self) -> PollResult { From b636afb7b513cc9027a33659a58373106e4a3958 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 2 Aug 2022 22:05:38 +0000 Subject: [PATCH 2/2] Clear sie_status.suspended / sie_status.resume flags in poll() usb_device ignores PollResult::Suspend when already suspended, and PollResult::Resume when not suspended. This may lead to repeatedly triggered interrupts if for some reason the Suspend flag gets set while the device is already suspended. I observed such a situation when a reset was triggered while the device was suspended. To make sure that this can't cause interrupt storms, clear the flags before returning from poll() --- rp2040-hal/src/usb.rs | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/rp2040-hal/src/usb.rs b/rp2040-hal/src/usb.rs index 0a36dc6..39445d7 100644 --- a/rp2040-hal/src/usb.rs +++ b/rp2040-hal/src/usb.rs @@ -538,24 +538,8 @@ impl UsbBusTrait for UsbBus { .bit_is_set() }) } - fn suspend(&self) { - interrupt::free(|cs| { - let inner = self.inner.borrow(cs).borrow_mut(); - inner - .ctrl_reg - .sie_status - .write(|w| w.suspended().set_bit()); - }); - } - fn resume(&self) { - interrupt::free(|cs| { - let inner = self.inner.borrow(cs).borrow_mut(); - inner - .ctrl_reg - .sie_status - .write(|w| w.resume().set_bit()); - }); - } + fn suspend(&self) {} + fn resume(&self) {} fn poll(&self) -> PollResult { interrupt::free(|cs| { let mut inner = self.inner.borrow(cs).borrow_mut(); @@ -565,8 +549,10 @@ impl UsbBusTrait for UsbBus { if sie_status.bus_reset().bit_is_set() { return PollResult::Reset; } else if sie_status.suspended().bit_is_set() { + inner.ctrl_reg.sie_status.write(|w| w.suspended().set_bit()); return PollResult::Suspend; } else if sie_status.resume().bit_is_set() { + inner.ctrl_reg.sie_status.write(|w| w.resume().set_bit()); return PollResult::Resume; }