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; diff --git a/firmware/moondancer/src/bin/moondancer.rs b/firmware/moondancer/src/bin/moondancer.rs index 51850f78..d3c7fc6e 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)); } } @@ -521,50 +518,45 @@ 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 - aka ep_out_prime_receive() TODO should control do this in send_complete? - 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()); - - // 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? - self.usb2.ep_out_prime_receive(0); + 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); - // TODO send last error code? - self.usb2.write(0, 0_u32.to_le_bytes().into_iter()); + // send error response + if let Some(error) = self.libgreat_response_last_error { + self.usb2.write_requested(0, requested_length, (error as u32).to_le_bytes().into_iter()); + warn!("dispatch_libgreat_abort: {:?}", error); + } else { + self.usb2.write_requested(0, requested_length, (GreatError::StateNotRecoverable as u32).to_le_bytes().into_iter()); + 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(()) } } 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();