From f7c4b48b85914a94846bcddda7fb929ee0fd55c7 Mon Sep 17 00:00:00 2001 From: doryan Date: Mon, 5 May 2025 23:09:42 +0400 Subject: [PATCH 1/9] remove free-interrupt context for endpoint allocator --- src/lib.rs | 97 ++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 64604a0..5b4c157 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,60 +24,57 @@ 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_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_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; - 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) + 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) { From 632286879600afff2e09443b6ea34ee39b976a70 Mon Sep 17 00:00:00 2001 From: doryan Date: Wed, 14 May 2025 21:01:58 +0400 Subject: [PATCH 2/9] refactor: remove unwrap() usage, redundant free(||) usage and etc --- src/lib.rs | 183 +++++++++++++++++++++++++---------------------------- 1 file changed, 86 insertions(+), 97 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5b4c157..659758b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,8 +24,9 @@ impl UsbBus for UsbDevice { _interval: u8, ) -> UsbResult { // Handle first endpoint. // + if ep_addr == Some(EndpointAddress::from_parts(0, UsbDirection::In)) { - Ok(ep_addr.unwrap()) + ep_addr.ok_or(UsbError::WouldBlock) } else { let address = match ep_addr { // If current endpoint doesn't allocated, assign ep_addr to variable. // @@ -113,7 +114,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. // @@ -131,13 +132,11 @@ 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()); - }); - delay_cycles(ONE_MS_16_MGHZ); + usbcon.modify(|_, w| w.usbe().clear_bit()); + + delay_cycles(ONE_MS_16_MGHZ); - free(|cs| { - let usbcon = &self.usb.borrow(cs).usbcon; usbcon.modify(|_, w| w.usbe().set_bit()); }); @@ -158,8 +157,8 @@ impl UsbBus for UsbDevice { let (udint, udien, usbint) = (usb.udint.read(), usb.udien.read(), usb.usbint.read()); if usbint.vbusti().bit_is_set() { - usb.usbint - .write(|w| unsafe { w.bits(0x01) }.vbusti().clear_bit()); + usb.usbint.write(|w| w.vbusti().clear_bit()); + if usb.usbsta.read().vbus().bit_is_set() { return PollResult::Resume; } else { @@ -180,8 +179,7 @@ impl UsbBus for UsbDevice { } if udint.sofi().bit_is_set() { - usb.udint - .write(|w| unsafe { w.bits(0x7d) }.sofi().clear_bit()); + usb.udint.write(|w| w.sofi().clear_bit()); } if usb.usbcon.read().frzclk().bit_is_clear() { @@ -223,60 +221,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) } }) } @@ -288,18 +288,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) } - .wakeupi() - .clear_bit() - .suspi() - .clear_bit() - }); + usb.udint + .write(|w| w.wakeupi().clear_bit().suspi().clear_bit()); usb.udien .modify(|_, w| w.wakeupe().clear_bit().suspe().set_bit()); @@ -321,13 +316,8 @@ impl UsbBus for UsbDevice { usb.usbcon.modify(|_, w| w.frzclk().clear_bit()); - usb.udint.write(|w| { - unsafe { w.bits(0x7d) } - .wakeupi() - .clear_bit() - .suspi() - .clear_bit() - }); + usb.udint + .write(|w| w.wakeupi().clear_bit().suspi().clear_bit()); usb.udien .modify(|_, w| w.wakeupe().clear_bit().suspe().set_bit()); @@ -365,13 +355,8 @@ impl UsbBus for UsbDevice { free(|cs| { let (usb, pll) = (self.usb.borrow(cs), self.pll.borrow(cs)); - usb.udint.write(|w| { - unsafe { w.bits(0x7d) } - .wakeupi() - .clear_bit() - .suspi() - .clear_bit() - }); + usb.udint + .write(|w| w.wakeupi().clear_bit().suspi().clear_bit()); // Suspend. // @@ -392,14 +377,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); } @@ -413,13 +398,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() @@ -435,19 +422,21 @@ 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()) }) } } + +const RESTRICT_RW_FLAG: u8 = !(1 << 5); From 64a6532c94b4f2516ba1ad60ecae19471cb2120e Mon Sep 17 00:00:00 2001 From: doryan Date: Thu, 15 May 2025 10:03:22 +0400 Subject: [PATCH 3/9] fix(f_reset): using detach bit in udcon register instead usbcon --- src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 659758b..82469a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -131,13 +131,13 @@ impl UsbBus for UsbDevice { fn force_reset(&self) -> UsbResult<()> { free(|cs| { - let usbcon = &self.usb.borrow(cs).usbcon; + let udcon = &self.usb.borrow(cs).udcon; - usbcon.modify(|_, w| w.usbe().clear_bit()); + udcon.modify(|_, w| w.detach().set_bit()); delay_cycles(ONE_MS_16_MGHZ); - usbcon.modify(|_, w| w.usbe().set_bit()); + udcon.modify(|_, w| w.detach().clear_bit()); }); Ok(()) From 93ade5bda079b5a0432491eebc2dd12301c126f2 Mon Sep 17 00:00:00 2001 From: doryan Date: Thu, 15 May 2025 10:23:43 +0400 Subject: [PATCH 4/9] fix: add clearing interrupts --- src/lib.rs | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 82469a4..a6b1800 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -157,7 +157,8 @@ impl UsbBus for UsbDevice { let (udint, udien, usbint) = (usb.udint.read(), usb.udien.read(), usb.usbint.read()); if usbint.vbusti().bit_is_set() { - usb.usbint.write(|w| w.vbusti().clear_bit()); + usb.usbint + .write(|w| unsafe { w.bits(USBINT_CLEAR) }.vbusti().clear_bit()); if usb.usbsta.read().vbus().bit_is_set() { return PollResult::Resume; @@ -179,7 +180,8 @@ impl UsbBus for UsbDevice { } if udint.sofi().bit_is_set() { - usb.udint.write(|w| w.sofi().clear_bit()); + usb.udint + .write(|w| unsafe { w.bits(UDINT_CLEAR) }.sofi().clear_bit()); } if usb.usbcon.read().frzclk().bit_is_clear() { @@ -293,8 +295,13 @@ impl UsbBus for UsbDevice { // Clear resume informations. // - usb.udint - .write(|w| w.wakeupi().clear_bit().suspi().clear_bit()); + usb.udint.write(|w| { + unsafe { w.bits(UDINT_CLEAR) } + .wakeupi() + .clear_bit() + .suspi() + .clear_bit() + }); usb.udien .modify(|_, w| w.wakeupe().clear_bit().suspe().set_bit()); @@ -316,8 +323,13 @@ impl UsbBus for UsbDevice { usb.usbcon.modify(|_, w| w.frzclk().clear_bit()); - usb.udint - .write(|w| w.wakeupi().clear_bit().suspi().clear_bit()); + usb.udint.write(|w| { + unsafe { w.bits(UDINT_CLEAR) } + .wakeupi() + .clear_bit() + .suspi() + .clear_bit() + }); usb.udien .modify(|_, w| w.wakeupe().clear_bit().suspe().set_bit()); @@ -355,8 +367,13 @@ impl UsbBus for UsbDevice { free(|cs| { let (usb, pll) = (self.usb.borrow(cs), self.pll.borrow(cs)); - usb.udint - .write(|w| w.wakeupi().clear_bit().suspi().clear_bit()); + usb.udint.write(|w| { + unsafe { w.bits(UDINT_CLEAR) } + .wakeupi() + .clear_bit() + .suspi() + .clear_bit() + }); // Suspend. // @@ -440,3 +457,5 @@ impl UsbBus for UsbDevice { } const RESTRICT_RW_FLAG: u8 = !(1 << 5); +const USBINT_CLEAR: u8 = !(1 << 0); +const UDINT_CLEAR: u8 = !(1 << 1 | 1 << 7); From a269df21fe2c04bc2dfdf5f950c806754956d29d Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 18 May 2025 23:00:00 +0400 Subject: [PATCH 5/9] fix(int): fix bytes for clearing interrupt flags for usbd_serial --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a6b1800..5864c15 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -457,5 +457,5 @@ impl UsbBus for UsbDevice { } const RESTRICT_RW_FLAG: u8 = !(1 << 5); -const USBINT_CLEAR: u8 = !(1 << 0); -const UDINT_CLEAR: u8 = !(1 << 1 | 1 << 7); +const USBINT_CLEAR: u8 = 1 << 0; +const UDINT_CLEAR: u8 = !(1 << 1); From dd28dfe61eb249703e77d98fc6fb93a715a2868f Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 18 May 2025 23:05:30 +0400 Subject: [PATCH 6/9] test --- src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 5864c15..5cf50f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,8 +134,12 @@ impl UsbBus for UsbDevice { let udcon = &self.usb.borrow(cs).udcon; udcon.modify(|_, w| w.detach().set_bit()); + }); - delay_cycles(ONE_MS_16_MGHZ); + delay_cycles(ONE_MS_16_MGHZ); + + free(|cs| { + let udcon = &self.usb.borrow(cs).udcon; udcon.modify(|_, w| w.detach().clear_bit()); }); From dba9637614e3c9b7dc5373f76d06df36e560ae91 Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 18 May 2025 22:15:59 +0300 Subject: [PATCH 7/9] revert a269df21fe2c04bc2dfdf5f950c806754956d29d revert fix(int): fix bytes for clearing interrupt flags for usbd_serial --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5cf50f4..5e5f899 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -461,5 +461,5 @@ impl UsbBus for UsbDevice { } const RESTRICT_RW_FLAG: u8 = !(1 << 5); -const USBINT_CLEAR: u8 = 1 << 0; -const UDINT_CLEAR: u8 = !(1 << 1); +const USBINT_CLEAR: u8 = !(1 << 0); +const UDINT_CLEAR: u8 = !(1 << 1 | 1 << 7); From cfa76a66727c6798d353ae9f62824b61d10aaf84 Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 18 May 2025 23:18:52 +0400 Subject: [PATCH 8/9] fix(int): USBINT interrupt --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5e5f899..79ba68e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -461,5 +461,5 @@ impl UsbBus for UsbDevice { } const RESTRICT_RW_FLAG: u8 = !(1 << 5); -const USBINT_CLEAR: u8 = !(1 << 0); -const UDINT_CLEAR: u8 = !(1 << 1 | 1 << 7); +const USBINT_CLEAR: u8 = 1 << 0; +const UDINT_CLEAR: u8 = !(1 << 7 | 1 << 1); From c510d908d32c73eab994f210194a0450703d9f00 Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 18 May 2025 23:51:41 +0400 Subject: [PATCH 9/9] refactor: move constants + remove code duplicate --- src/lib.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 79ba68e..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, @@ -26,7 +30,7 @@ impl UsbBus for UsbDevice { // Handle first endpoint. // if ep_addr == Some(EndpointAddress::from_parts(0, UsbDirection::In)) { - ep_addr.ok_or(UsbError::WouldBlock) + ep_addr.ok_or(UsbError::InvalidState) } else { let address = match ep_addr { // If current endpoint doesn't allocated, assign ep_addr to variable. // @@ -130,19 +134,15 @@ impl UsbBus for UsbDevice { } fn force_reset(&self) -> UsbResult<()> { - free(|cs| { - let udcon = &self.usb.borrow(cs).udcon; - - udcon.modify(|_, w| w.detach().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 udcon = &self.usb.borrow(cs).udcon; - - udcon.modify(|_, w| w.detach().clear_bit()); - }); + set_detach(false); Ok(()) } @@ -459,7 +459,3 @@ impl UsbBus for UsbDevice { }) } } - -const RESTRICT_RW_FLAG: u8 = !(1 << 5); -const USBINT_CLEAR: u8 = 1 << 0; -const UDINT_CLEAR: u8 = !(1 << 7 | 1 << 1);