From d94aba66e3efe4e6527b60741e58fd6474e3f852 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 1 Oct 2024 17:28:03 +0200 Subject: [PATCH 1/4] moondancer: fix libgreat command abort handling --- firmware/moondancer/src/bin/moondancer.rs | 45 +++++++++++------------ 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/firmware/moondancer/src/bin/moondancer.rs b/firmware/moondancer/src/bin/moondancer.rs index 51850f78..a63a932e 100644 --- a/firmware/moondancer/src/bin/moondancer.rs +++ b/firmware/moondancer/src/bin/moondancer.rs @@ -501,15 +501,12 @@ impl<'a> Firmware<'a> { "dispatch_libgreat_request error: failed to dispatch command {:?} 0x{:X} {}", class_id, verb_number, e ); + self.libgreat_response = None; self.libgreat_response_last_error = Some(e); - // TODO this is... weird... + // stall endpoint to trigger dispatch_libgreat_abort from control host self.usb2.stall_endpoint_in(0); - unsafe { - riscv::asm::delay(2000); - } - self.usb2.ep_in.reset().write(|w| w.reset().bit(true)); } } @@ -527,38 +524,40 @@ impl<'a> Firmware<'a> { // clear cached response self.libgreat_response = None; - // prime to receive host zlp - aka ep_out_prime_receive() TODO should control do this in send_complete? + // prime to receive host zlp self.usb2.ep_out_prime_receive(0); - } else if let Some(error) = self.libgreat_response_last_error { - warn!("dispatch_libgreat_response error result: {:?}", error); - // prime to receive host zlp - TODO should control do this in send_complete? - self.usb2.ep_out_prime_receive(0); - - // write error - self.usb2.write(0, (error as u32).to_le_bytes().into_iter()); + } else if let Some(error) = self.libgreat_response_last_error { + warn!("dispatch_libgreat_response error result: {:?} (reqlen:{})", error, requested_length); - // clear cached error - self.libgreat_response_last_error = None; } else { - // TODO figure out what to do if we don't have a response or error - error!("dispatch_libgreat_response stall: libgreat response requested but no response or error queued"); self.usb2.stall_endpoint_in(0); + error!("dispatch_libgreat_response stall: libgreat response requested but no response or error queued"); } Ok(()) } - fn dispatch_libgreat_abort(&mut self, _setup_packet: SetupPacket) -> GreatResult<()> { - // send an arbitrary error code if we're aborting mid-response - if let Some(_response) = &self.libgreat_response { - // prime to receive host zlp - TODO should control do this in send_complete? + fn dispatch_libgreat_abort(&mut self, setup_packet: SetupPacket) -> GreatResult<()> { + let requested_length = setup_packet.length as usize; + + if let Some(error) = self.libgreat_response_last_error { + // send error + self.usb2.write_requested(0, requested_length, (error as u32).to_le_bytes().into_iter()); + + // prime to receive host zlp self.usb2.ep_out_prime_receive(0); - // TODO send last error code? - self.usb2.write(0, 0_u32.to_le_bytes().into_iter()); + warn!("dispatch_libgreat_abort error result: {:?} (reqlen:{})", error, requested_length); + + } else { + self.usb2.write_requested(0, requested_length, (GreatError::StateNotRecoverable as u32).to_le_bytes().into_iter()); + + // prime to receive host zlp + self.usb2.ep_out_prime_receive(0); } + // cancel any queued response self.libgreat_response = None; self.libgreat_response_last_error = None; From 5b5276b8dec0db3bfcd04dfbc0c52eb91541c05d Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Wed, 2 Oct 2024 17:09:35 +0200 Subject: [PATCH 2/4] moondancer: shorten connect delay --- firmware/moondancer/src/gcp/moondancer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/moondancer/src/gcp/moondancer.rs b/firmware/moondancer/src/gcp/moondancer.rs index 741e8809..2daf58d4 100644 --- a/firmware/moondancer/src/gcp/moondancer.rs +++ b/firmware/moondancer/src/gcp/moondancer.rs @@ -256,7 +256,7 @@ impl Moondancer { // wait for things to settle and get connection speed unsafe { - riscv::asm::delay(30_000_000); + riscv::asm::delay(20_000_000); } let speed: Speed = self.usb0.controller.speed().read().speed().bits().into(); From 4e30187560fa34e9ce4940c12f0243b4a66ea943 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Wed, 2 Oct 2024 17:10:11 +0200 Subject: [PATCH 3/4] hal: reset endpoint fifo's before issuing stall --- firmware/lunasoc-hal/src/usb.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/lunasoc-hal/src/usb.rs b/firmware/lunasoc-hal/src/usb.rs index 797a26c1..12e7f5fb 100644 --- a/firmware/lunasoc-hal/src/usb.rs +++ b/firmware/lunasoc-hal/src/usb.rs @@ -236,12 +236,14 @@ macro_rules! impl_usb { /// Stall the given IN endpoint number. fn stall_endpoint_in(&self, endpoint_number: u8) { + self.ep_in.reset().write(|w| w.reset().bit(true)); self.ep_in.stall().write(|w| w.stall().bit(true)); self.ep_in.epno().write(|w| unsafe { w.epno().bits(endpoint_number) }); } /// Stall the given OUT endpoint number. fn stall_endpoint_out(&self, endpoint_number: u8) { + self.ep_out.reset().write(|w| w.reset().bit(true)); self.ep_out.epno().write(|w| unsafe { w.epno().bits(endpoint_number) }); self.ep_out.stall().write(|w| w.stall().bit(true)); } @@ -512,7 +514,7 @@ macro_rules! impl_usb { // - no need to prime, fifo is empty // d. A full packet is sent, followed by a zlp // - fifo is empty, but need to prime to send a zlp so host know it's EOT - // e. An emptry packet is sent, followed by a zlp + // e. An empty packet is sent, followed by a zlp // - fifo is empty, but need to prime to send a zlp so host know it's EOT // let is_partial_packet = bytes_written % packet_size != 0; From 589dd2201f3f169d5f8a2522d73cdff740579347 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Wed, 2 Oct 2024 17:17:17 +0200 Subject: [PATCH 4/4] moondancer: prime to receive host zlp _before_ writing response --- firmware/moondancer/src/bin/moondancer.rs | 31 +++++++++-------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/firmware/moondancer/src/bin/moondancer.rs b/firmware/moondancer/src/bin/moondancer.rs index a63a932e..d3c7fc6e 100644 --- a/firmware/moondancer/src/bin/moondancer.rs +++ b/firmware/moondancer/src/bin/moondancer.rs @@ -518,17 +518,17 @@ impl<'a> Firmware<'a> { // do we have a response ready? if let Some(response) = &mut self.libgreat_response { + // prime to receive host zlp + self.usb2.ep_out_prime_receive(0); + // send response self.usb2.write_requested(0, requested_length, response); - // clear cached response + // clear any queued responses self.libgreat_response = None; - // prime to receive host zlp - self.usb2.ep_out_prime_receive(0); - } else if let Some(error) = self.libgreat_response_last_error { - warn!("dispatch_libgreat_response error result: {:?} (reqlen:{})", error, requested_length); + warn!("dispatch_libgreat_response error result: {:?}", error); } else { self.usb2.stall_endpoint_in(0); @@ -541,29 +541,22 @@ impl<'a> Firmware<'a> { fn dispatch_libgreat_abort(&mut self, setup_packet: SetupPacket) -> GreatResult<()> { let requested_length = setup_packet.length as usize; + // prime to receive host zlp + self.usb2.ep_out_prime_receive(0); + + // send error response if let Some(error) = self.libgreat_response_last_error { - // send error self.usb2.write_requested(0, requested_length, (error as u32).to_le_bytes().into_iter()); - - // prime to receive host zlp - self.usb2.ep_out_prime_receive(0); - - warn!("dispatch_libgreat_abort error result: {:?} (reqlen:{})", error, requested_length); - + warn!("dispatch_libgreat_abort: {:?}", error); } else { self.usb2.write_requested(0, requested_length, (GreatError::StateNotRecoverable as u32).to_le_bytes().into_iter()); - - // prime to receive host zlp - self.usb2.ep_out_prime_receive(0); + warn!("dispatch_libgreat_abort: libgreat abort requested but no error queued"); } - - // cancel any queued response + // clear any queued responses self.libgreat_response = None; self.libgreat_response_last_error = None; - error!("dispatch_libgreat_response abort"); - Ok(()) } }