-
Notifications
You must be signed in to change notification settings - Fork 171
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
gateware.usb2: add disconnect signal to USBResetSequencer #212
gateware.usb2: add disconnect signal to USBResetSequencer #212
Conversation
892f7a6
to
eb34b18
Compare
eb34b18
to
e00763f
Compare
e00763f
to
2117fba
Compare
Sorry for the long delay answering. After going over the spec, I think tying this into the state machine as suggested is the way to go (thought I don't think it needs to be restricted to only work in particular states, after all we're simulating a device being unplugged and that could happen at any time). According to the spec, there's a minimum time (TDDIS) that the host needs to see the lines non-driven before detecting a disconnect state, so we should have the state machine guarantee that, and then stay non-driving for longer if the user continues to assert |
Closes #143 |
2117fba
to
1ad6ef3
Compare
…ddis=2.5uS during forced disconnect
Updated as per recommendation and everything is working swimmingly. The one surprise was that I needed to transition to |
I think we'll need to find a different solution since low/full speed devices should not transition to that state. Can you expand a bit more on the behaviour when exiting into other states? Resetting the operating mode back to normal upon exiting |
Heh, I thought you may say something like this -- let's go through it one-by-one:
Strictly speaking, yes I agree 100% that this is not ideal. The reason it does work though is that
I think the root issue with the other states, and why we end up with reset loops with all the alternatives, is that they are all assuming the bus is at reset on entry. This is however not an assumption which is true after a forced disconnect. Another option I did explore to work around this was to move the SE0 line checks out of I tried a lot of things, but here are some of the failure modes I saw in all cases except the approach used in the PR:
Very first thing I tried… 😅 |
Oh the other thing I wanted to mention was that the existing gateware is pretty much following this approach already if you look at the actual state transitions:
But wait… it gets better: As written the guard around the transition to Which of course never happens in reality because it's normally either neither or one or the other so of course we will always make that transition irrespective of whether we've configured the device for ls/fs or high speed operation… The real kicker though is that with the logic -- as written -- it means that if they are ever both set high the gateware will never exit Which is pretty much where I found myself last week when I figured we probably have two options at this point:
|
Having gone back over the state machine with your comments in mind, I've got some thoughts further to the call earlier.
This, as far as I can see, is not correct. The guard will block transition if either of them are high (ie: it transitions if I've verified on the scope, looking at the data lines & the state signal, that it does not currently go through I've pushed an alternate attempt here: miek@16f9a6c - this sets all the PHY parameters back to expected defaults before going through
(low-speed can be selected too, but it errors out because the descriptors are all wrong). Tested with $ git diff
diff --git a/examples/usb/simple_device.py b/examples/usb/simple_device.py
index 325500b..46f413b 100755
--- a/examples/usb/simple_device.py
+++ b/examples/usb/simple_device.py
@@ -9,6 +9,7 @@ import os
from amaranth import Elaboratable, Module
from usb_protocol.emitters import DeviceDescriptorCollection
+from amaranth.build import *
from luna import top_level_cli
from luna.gateware.platform import NullPin
@@ -72,10 +73,18 @@ class USBDeviceExample(Elaboratable):
descriptors = self.create_descriptors()
usb.add_standard_control_endpoint(descriptors)
+ platform.add_resources([
+ Resource("btns", 0, Pins("1 2 3", conn=("pmod", 0), dir="i"), Attrs(PULLMODE="UP")),
+ ])
+
+ btns = platform.request("btns", 0)
+ pmod1 = platform.request("user_pmod", 1, dir="o")
+
# Connect our device as a high speed device by default.
m.d.comb += [
- usb.connect .eq(1),
- usb.full_speed_only .eq(1 if os.getenv('LUNA_FULL_ONLY') else 0),
+ usb.connect .eq(btns.i[0]),
+ usb.full_speed_only .eq(btns.i[1]),
+ usb.low_speed_only .eq(btns.i[2]),
]
# ... and for now, attach our LEDs to our most recent control request. |
…lect on exiting forced disconnect
Ah you absolute bloody genius you @miek! Setting I've updated the PR with your changes, thank you. |
I have been trying to test this work as part of my HITL work in greatscottgadgets/cynthion-analyzer#6, but I'm having what may or may not be unrelated issues. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm now using this to disconnect and reconnect a device successfully at all speeds, so functionally I think it's good to go.
This draft PR adds a
disconnect
signal that, when pulled high byUSBDevice
, causes the UTMI interface's operating mode to be set toNON_DRIVING
in order to trigger a host disconnect.Open questions:
USBResetSequencer
state machine and only operate if we're in stateLS_FS_NON_RESET
orHS_NON_RESET
?I've run into some weirdness where, after data has been transferred on any of the non control endpoints, I can no longer enumerate the device after disconnect/connect. This may however be due to a bug in my code. Currently investigating.It was indeed a software bug.