Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Facedancer USB Timeout error #191

Merged
merged 4 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading