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()
This commit is contained in:
Jan Niehusmann 2022-08-02 22:05:38 +00:00
parent 786062aa74
commit b636afb7b5

View file

@ -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;
}