Skip to content

Commit

Permalink
Merge pull request #191 from antoinevg/antoinevg/fix-188
Browse files Browse the repository at this point in the history
Fix Facedancer USB Timeout error
  • Loading branch information
antoinevg authored Oct 8, 2024
2 parents 10ba03b + 589dd22 commit d54a77f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 30 deletions.
4 changes: 3 additions & 1 deletion firmware/lunasoc-hal/src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down Expand Up @@ -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;
Expand Down
48 changes: 20 additions & 28 deletions firmware/moondancer/src/bin/moondancer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}

Expand All @@ -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(())
}
}
2 changes: 1 addition & 1 deletion firmware/moondancer/src/gcp/moondancer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down

0 comments on commit d54a77f

Please sign in to comment.