diff --git a/src/bus.rs b/src/bus.rs index 657d8f8..3b3d927 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -71,6 +71,44 @@ impl UsbBus { regs.cntr.modify(|_, w| w.pdwn().bit(pdwn)); }); } + + /// Enter suspend low-power mode + /// + /// This should be used when in suspend mode if low-power mode needs to be entered during + /// suspend (bus-powered device). Application should call this when it is ready to decrease + /// power consumption to meet power consumption requirements of the USB suspend condition + /// (e.g. disable system clocks or reduce their frequency). When wake up event is received + /// low power mode will be automatically disabled. + /// + /// Will not enter low-power mode if not in suspend state. Returns `true` if entered. + pub fn suspend_low_power_mode(&self) -> bool { + interrupt::free(|cs| { + let regs = self.regs.borrow(cs); + if regs.cntr.read().fsusp().is_suspend() { + regs.cntr.modify(|_, w| w.lpmode().set_bit()); + true + } else { + false + } + }) + } + + /// Set/clear remote wakeup bit + /// + /// Allows to modify CNTR.RESUME bit from device to perform remote wake up from suspend + /// (e.g. on keyboard/mouse input). To perform remote wake up: when a condition is met + /// during suspend mode, use this method with `true` to set the RESUME bit. Then, after + /// waiting between 1-15 ms (see reference manual) call it again with `false` to clear + /// the bit. + /// + /// This method will not set the bit if device is not suspended because performing remote + /// wake up in other mode is invalid and host will most likely disable such a device. + pub fn remote_wakeup(&self, resume: bool) { + interrupt::free(|cs| { + self.regs.borrow(cs) + .cntr.modify(|r, w| w.resume().bit(resume && r.fsusp().is_suspend())); + }) + } } impl usb_device::bus::UsbBus for UsbBus { @@ -218,10 +256,7 @@ impl usb_device::bus::UsbBus for UsbBus { if v.ctr_tx().bit_is_set() { ep_in_complete |= bit; - - interrupt::free(|cs| { - ep.clear_ctr_tx(cs); - }); + ep.clear_ctr_tx(cs); } bit <<= 1; @@ -288,7 +323,7 @@ impl usb_device::bus::UsbBus for UsbBus { self.regs .borrow(cs) .cntr - .modify(|_, w| w.fsusp().set_bit().lpmode().set_bit()); + .modify(|_, w| w.fsusp().set_bit()); }); }