diff --git a/src/lib.rs b/src/lib.rs index 64604a0..298e76b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,10 @@ pub use types::*; use types::{DPRAM_SIZE, ENDPOINTS_ALLOC_LAYOUT, ONE_MS_16_MGHZ}; +const RESTRICT_RW_FLAG: u8 = !(1 << 5); +const USBINT_CLEAR: u8 = 1 << 0; +const UDINT_CLEAR: u8 = !(1 << 7 | 1 << 1); + impl UsbBus for UsbDevice { fn alloc_ep( &mut self, @@ -24,60 +28,58 @@ impl UsbBus for UsbDevice { _interval: u8, ) -> UsbResult { // Handle first endpoint. // - free(|_cs| { - if ep_addr == Some(EndpointAddress::from_parts(0, UsbDirection::In)) { - Ok(ep_addr.unwrap()) - } else { - let address = match ep_addr { - // If current endpoint doesn't allocated, assign ep_addr to variable. // - Some(addr) if !self.ep_table[addr.index()].is_allocated => addr, - // If ep_aadr not provided, or current endpoint is allocated, try to find next free endpoint, otherwise return UsbError. // - _ => { - let index = self - .ep_table - .iter() - .enumerate() - .skip(1) - .find(|(index, ep)| { - !ep.is_allocated - && max_packet_size <= ENDPOINTS_ALLOC_LAYOUT[*index] - }) - .ok_or(UsbError::EndpointOverflow)? - .0; + if ep_addr == Some(EndpointAddress::from_parts(0, UsbDirection::In)) { + ep_addr.ok_or(UsbError::InvalidState) + } else { + let address = match ep_addr { + // If current endpoint doesn't allocated, assign ep_addr to variable. // + Some(addr) if !self.ep_table[addr.index()].is_allocated => addr, - EndpointAddress::from_parts(index, ep_dir) - } - }; + // If ep_aadr not provided, or current endpoint is allocated, try to find next free endpoint, otherwise return UsbError. // + _ => { + let index = self + .ep_table + .iter() + .enumerate() + .skip(1) + .find(|(index, ep)| { + !ep.is_allocated && max_packet_size <= ENDPOINTS_ALLOC_LAYOUT[*index] + }) + .ok_or(UsbError::EndpointOverflow)? + .0; - // Select endpoint info by address index. // - - let target_endpoint = &mut self.ep_table[address.index()]; - - // Get power of two number of endpoint size. // - - let ep_size = max(8, max_packet_size.next_power_of_two()); - - // Endpoint allocation marker. // - - if DPRAM_SIZE - self.dpram_already_used < ep_size { - Err(UsbError::EndpointMemoryOverflow) - } else { - // Set endpoint parameters. // - - target_endpoint.set_dir(ep_dir); - target_endpoint.set_type(ep_type); - target_endpoint.set_size(ep_size)?; - - // Add used dpram memory. // - - target_endpoint.is_allocated = true; - self.dpram_already_used += ep_size; - - Ok(address) + EndpointAddress::from_parts(index, ep_dir) } + }; + + // Select endpoint info by address index. // + + let target_endpoint = &mut self.ep_table[address.index()]; + + // Get power of two number of endpoint size. // + + let ep_size = max(8, max_packet_size.next_power_of_two()); + + // Endpoint allocation marker. // + + if DPRAM_SIZE - self.dpram_already_used < ep_size { + Err(UsbError::EndpointMemoryOverflow) + } else { + // Set endpoint parameters. // + + target_endpoint.set_dir(ep_dir); + target_endpoint.set_type(ep_type); + target_endpoint.set_size(ep_size)?; + + // Add used dpram memory. // + + target_endpoint.is_allocated = true; + self.dpram_already_used += ep_size; + + Ok(address) } - }) + } } fn enable(&mut self) { @@ -116,7 +118,7 @@ impl UsbBus for UsbDevice { // Endpoint configuration // self.allocated_endpoints().for_each(|(i, _ep)| { - self.configure_endpoint(cs, i).unwrap(); + let _ = self.configure_endpoint(cs, i); }); // Set high speed and attach the USB. // @@ -132,17 +134,15 @@ impl UsbBus for UsbDevice { } fn force_reset(&self) -> UsbResult<()> { - free(|cs| { - let usbcon = &self.usb.borrow(cs).usbcon; - usbcon.modify(|_, w| w.usbe().set_bit()); - }); + let set_detach = |bit| { + free(|cs| { + self.usb.borrow(cs).udcon.modify(|_, w| w.detach().bit(bit)); + }); + }; + set_detach(true); delay_cycles(ONE_MS_16_MGHZ); - - free(|cs| { - let usbcon = &self.usb.borrow(cs).usbcon; - usbcon.modify(|_, w| w.usbe().set_bit()); - }); + set_detach(false); Ok(()) } @@ -162,7 +162,8 @@ impl UsbBus for UsbDevice { if usbint.vbusti().bit_is_set() { usb.usbint - .write(|w| unsafe { w.bits(0x01) }.vbusti().clear_bit()); + .write(|w| unsafe { w.bits(USBINT_CLEAR) }.vbusti().clear_bit()); + if usb.usbsta.read().vbus().bit_is_set() { return PollResult::Resume; } else { @@ -184,7 +185,7 @@ impl UsbBus for UsbDevice { if udint.sofi().bit_is_set() { usb.udint - .write(|w| unsafe { w.bits(0x7d) }.sofi().clear_bit()); + .write(|w| unsafe { w.bits(UDINT_CLEAR) }.sofi().clear_bit()); } if usb.usbcon.read().frzclk().bit_is_clear() { @@ -226,60 +227,62 @@ impl UsbBus for UsbDevice { free(|cs| { let usb = self.usb.borrow(cs); - if let Err(error) = self.select_endpoint(cs, ep_addr.index()) { - Err(error) - } else { - let ep = &self.ep_table[ep_addr.index()]; + self.select_endpoint(cs, ep_addr.index())?; - if ep.ep_type == 0 { - let ueintx = usb.ueintx.read(); + let ep = &self.ep_table[ep_addr.index()]; - if ueintx.rxouti().bit_is_clear() && ueintx.rxstpi().bit_is_clear() { - return Err(UsbError::WouldBlock); - } + if ep.ep_type == 0 { + let ueintx = usb.ueintx.read(); - let buf_size = self.get_size(cs); - if buf.len() < buf_size { - return Err(UsbError::BufferOverflow); - } - - for byte in &mut buf[..buf_size] { - *byte = usb.uedatx.read().bits(); - } - - usb.ueintx.write(|w| { - unsafe { w.bits(0xdf) } - .rxouti() - .clear_bit() - .rxstpi() - .clear_bit() - }); - - Ok(buf_size) - } else { - if usb.ueintx.read().rxouti().bit_is_clear() { - return Err(UsbError::WouldBlock); - } - usb.ueintx - .write(|w| unsafe { w.bits(0xdf) }.rxouti().clear_bit()); - - let mut bytes_read = 0; - for slot in buf { - if usb.ueintx.read().rwal().bit_is_clear() { - break; - } - *slot = usb.uedatx.read().bits(); - bytes_read += 1; - } - - if usb.ueintx.read().rwal().bit_is_set() { - return Err(UsbError::BufferOverflow); - } - - usb.ueintx - .write(|w| unsafe { w.bits(0xdf) }.fifocon().clear_bit()); - Ok(bytes_read) + if ueintx.rxouti().bit_is_clear() && ueintx.rxstpi().bit_is_clear() { + return Err(UsbError::WouldBlock); } + + let buf_size = self.get_size(cs); + + if buf.len() < buf_size { + return Err(UsbError::BufferOverflow); + } + + for byte in &mut buf[..buf_size] { + *byte = usb.uedatx.read().bits(); + } + + usb.ueintx.write(|w| { + unsafe { w.bits(RESTRICT_RW_FLAG) } + .rxouti() + .clear_bit() + .rxstpi() + .clear_bit() + }); + + Ok(buf_size) + } else { + if usb.ueintx.read().rxouti().bit_is_clear() { + return Err(UsbError::WouldBlock); + } + + usb.ueintx + .write(|w| unsafe { w.bits(RESTRICT_RW_FLAG) }.rxouti().clear_bit()); + + let mut bytes_read = 0; + + for slot in buf { + if usb.ueintx.read().rwal().bit_is_clear() { + break; + } + *slot = usb.uedatx.read().bits(); + bytes_read += 1; + } + + if usb.ueintx.read().rwal().bit_is_set() { + return Err(UsbError::BufferOverflow); + } + + usb.ueintx + .write(|w| unsafe { w.bits(RESTRICT_RW_FLAG) }.fifocon().clear_bit()); + + Ok(bytes_read) } }) } @@ -291,13 +294,13 @@ impl UsbBus for UsbDevice { usb.udint.modify(|_, w| w.eorsti().clear_bit()); self.allocated_endpoints().for_each(|(i, _)| { - self.configure_endpoint(cs, i).unwrap(); + let _ = self.configure_endpoint(cs, i); }); // Clear resume informations. // usb.udint.write(|w| { - unsafe { w.bits(0x7d) } + unsafe { w.bits(UDINT_CLEAR) } .wakeupi() .clear_bit() .suspi() @@ -325,7 +328,7 @@ impl UsbBus for UsbDevice { usb.usbcon.modify(|_, w| w.frzclk().clear_bit()); usb.udint.write(|w| { - unsafe { w.bits(0x7d) } + unsafe { w.bits(UDINT_CLEAR) } .wakeupi() .clear_bit() .suspi() @@ -369,7 +372,7 @@ impl UsbBus for UsbDevice { let (usb, pll) = (self.usb.borrow(cs), self.pll.borrow(cs)); usb.udint.write(|w| { - unsafe { w.bits(0x7d) } + unsafe { w.bits(UDINT_CLEAR) } .wakeupi() .clear_bit() .suspi() @@ -395,14 +398,14 @@ impl UsbBus for UsbDevice { free(|cs| { let usb = self.usb.borrow(cs); - if let Err(error) = self.select_endpoint(cs, ep_addr.index()) { - Err(error) - } else { - let ep = &self.ep_table[ep_addr.index()]; + self.select_endpoint(cs, ep_addr.index())?; - // Endpoint type confitions // + let ep = &self.ep_table[ep_addr.index()]; - if ep.ep_type == 0 { + // Endpoint type confitions // + + match ep.ep_type { + 0 => { if usb.ueintx.read().txini().bit_is_clear() { return Err(UsbError::WouldBlock); } @@ -416,13 +419,15 @@ impl UsbBus for UsbDevice { } usb.ueintx - .write(|w| unsafe { w.bits(0xdf) }.txini().clear_bit()); - } else { + .write(|w| unsafe { w.bits(RESTRICT_RW_FLAG) }.txini().clear_bit()); + } + _ => { if usb.ueintx.read().txini().bit_is_clear() { return Err(UsbError::WouldBlock); } + usb.ueintx.write(|w| { - unsafe { w.bits(0xdf) } + unsafe { w.bits(RESTRICT_RW_FLAG) } .txini() .clear_bit() .rxouti() @@ -438,19 +443,19 @@ impl UsbBus for UsbDevice { } usb.ueintx.write(|w| { - unsafe { w.bits(0xdf) } + unsafe { w.bits(RESTRICT_RW_FLAG) } .rxouti() .clear_bit() .fifocon() .clear_bit() }); } + }; - let pending_ins = self.pending_ins.borrow(cs); - pending_ins.set(pending_ins.get() | 1 << ep_addr.index()); + let pending_ins = self.pending_ins.borrow(cs); + pending_ins.set(pending_ins.get() | 1 << ep_addr.index()); - Ok(buf.len()) - } + Ok(buf.len()) }) } }