earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 boards
GNU Lesser General Public License v2.1
1.92k stars 402 forks source link

Fix for Linux hanging on PICO switching to storage mode for upload #2175

Closed xxxajk closed 2 months ago

xxxajk commented 2 months ago

https://github.com/earlephilhower/arduino-pico/blob/master/tools/uf2conv.py#L376-L382

This code will hang on Linux when attempting upload. While I could push a fix for this, it's easier/quicker instead to simply post here the fix that I have been using for a long time.

This block of code is simply changed to be this:

                    ser.open()
                    ser.baudrate = 9600
                    ser.dtr = True
                    ser.rts = True
                    time.sleep(0.1)
                    ser.dtr = False
                    ser.rts = False
                    # Linux requires this to be able to close the port properly.
                    # Without both set True, the kernel will hang.
                    # It will not see the device go away when baud changes.
                    # Why are we messing with dtr/rts anyway?
                    # Isn't the switch to 1200 enough?
                    time.sleep(0.1)
                    ser.dtr = True
                    ser.rts = True
                    ser.baudrate = 1200
                    ser.close()
                    # Give some extra grace time, 
                    # USB is slow to enumerate, FS mounting 
                    # takes at least this long.
                    time.sleep(5) 

Yes BOTH DTR and RTS must be toggled, because if you do not, the kernel will hang waiting for baud rate change to answer. Because the tty no longer exists, the kernel will hang trying over and over until it times out well over a minute later. before it realizes that it is impossible to "close" it, even though python thinks it has been closed. Note that this happens in many C programs as well, and is nothing new.

earlephilhower commented 2 months ago

Sorry, this isn't being seen by myself or others. I actually develop and run on Linux (Ubuntu), and looking at the toolchain downloads we have > 10K other Linux users (and nearly 1K ARM Linux users, amazingly enough). Adding a 5 second sleep for everyone on every upload isn't really an option.

You could try using a different upload method thru the menus. The Picotool one uses a different, non-serial method on a custom USB endpoint.

xxxajk commented 2 months ago

1: Picotool works, but never reboots. 2: The hang happens on both my Reyzen box, and my PI400, and PI3 compute modules, haven't bothered trying the zeroW. 3: 5 seconds isn't required, but it doesn't matter, since I wait that long before it's automounted via dbus anyway. If it's already in the bootloader, there is no 5 second wait.

This totally happens on my AMD Ryzen 9 5900X 12-Core Processor, and the previous 8 core I had in it. Reyzen CPUs are known for some really nasty USB quirks, depending on what brand of board it is on. This fix is the ONLY one that solves the issue for me. I have kernel logs that can show this, and I can make a video if you really really want me to.

Here's one of many fails:

[1175890.091601] usb 1-2.2: Product: Pico
[1175890.091602] usb 1-2.2: Manufacturer: Raspberry Pi
[1175890.091602] usb 1-2.2: SerialNumber: E66178C12799442B
[1175890.160626] cdc_acm 1-2.2:1.0: ttyACM0: USB ACM device
[1175923.502368] usb 1-2.2: USB disconnect, device number 121
[1175923.773407] usb 1-2.2: new full-speed USB device number 122 using xhci_hcd
[1175923.869420] usb 1-2.2: device descriptor read/64, error -32
[1175924.069417] usb 1-2.2: device descriptor read/64, error -32
[1175924.273402] usb 1-2.2: new full-speed USB device number 123 using xhci_hcd
[1175924.365416] usb 1-2.2: device descriptor read/64, error -32
[1175924.573420] usb 1-2.2: device descriptor read/64, error -32
[1175924.681663] usb 1-2-port2: attempt power cycle
[1175925.313400] usb 1-2.2: new full-speed USB device number 124 using xhci_hcd
[1175925.313496] usb 1-2.2: Device not responding to setup address.
[1175925.521494] usb 1-2.2: Device not responding to setup address.
[1175925.729399] usb 1-2.2: device not accepting address 124, error -71
[1175925.821399] usb 1-2.2: new full-speed USB device number 125 using xhci_hcd
[1175925.821493] usb 1-2.2: Device not responding to setup address.
[1175926.029494] usb 1-2.2: Device not responding to setup address.
[1175926.237398] usb 1-2.2: device not accepting address 125, error -71
[1175926.237659] usb 1-2-port2: unable to enumerate USB device
[1175979.037357] usb 1-2.2: new full-speed USB device number 126 using xhci_hcd
[1175980.205373] usb 1-2.2: device descriptor read/64, error -32
[1175980.405369] usb 1-2.2: device descriptor read/64, error -32
[1175980.609353] usb 1-2.2: new full-speed USB device number 127 using xhci_hcd
[1175980.701368] usb 1-2.2: device descriptor read/64, error -32
[1175980.901368] usb 1-2.2: device descriptor read/64, error -32
[1175981.009589] usb 1-2-port2: attempt power cycle
[1175981.641351] usb 1-2.2: new full-speed USB device number 2 using xhci_hcd
[1175981.641445] usb 1-2.2: Device not responding to setup address.
[1175981.849444] usb 1-2.2: Device not responding to setup address.
[1175982.057353] usb 1-2.2: device not accepting address 2, error -71
[1175982.149351] usb 1-2.2: new full-speed USB device number 4 using xhci_hcd
[1175982.149445] usb 1-2.2: Device not responding to setup address.
[1175982.357444] usb 1-2.2: Device not responding to setup address.
[1175982.565353] usb 1-2.2: device not accepting address 4, error -71
[1175982.565590] usb 1-2-port2: unable to enumerate USB device
[1175992.345344] usb 1-2.2: new full-speed USB device number 5 using xhci_hcd
[1175992.476698] usb 1-2.2: New USB device found, idVendor=2e8a, idProduct=0003, bcdDevice= 1.00
[1175992.476701] usb 1-2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1175992.476702] usb 1-2.2: Product: RP2 Boot
[1175992.476703] usb 1-2.2: Manufacturer: Raspberry Pi
[1175992.476704] usb 1-2.2: SerialNumber: E0C9125B0D9B

69 seconds to enumerate... and it actually recovered that time. Other times it gives up. With the above fix, that does NOT happen, ever.

earlephilhower commented 2 months ago

For Picotool, you need to build and upload once with it enabled in the menus to add the picotool-specific USB endpoint to the Arduino app. So, you might want to try that twice in a row and see if that goes. It's the RPI official tool so if it doesn't work then there's probably something fishy w/the OS instance.

The Linux USB stack sometimes gets in a bad way, especially on AMD systems, in my experience. No idea if it's SW or just the B550 being quirky FWIW, I run a 5600x myself and Ubu 20.04.

xxxajk commented 2 months ago

It's a known flaw on this particular Asus board (tuf gaming). I've had to submit patches to other hardware products in order to fix them. For example: https://github.com/UltimateHackingKeyboard/firmware Where enumeration fails if the HID order isn't as "expected" by the BIOS, and sometimes it sees the keyboard, sometimes doesn't. It's particular to this motherboard IFAIK, and it was given to me just to diagnose such issues, and find work-arounds. Newer BIOS helped it a little, but not 100% with this board. Sometimes I have to run my "usb reset" script which tares down all of usb, and rediscovers it, because the XHCI engine gets wedged.

It seems to happen on all non-usb3.x devices, forcing me to use a hub. For example my UPS will constantly drop and reconnect for no reason at all, unless I place it behind a hub. The internal 2.0 ports are useless as well without a hub, which kind of defeats the point of them. FTDI chips act the same screwy way sometimes when you yank them without closing whatever is using them. Arduino Mega2560 hasn't been a problem though. It's hit-and-miss.

As to why I saw problems on the others, it could just as well be that I used the same hub on those as well, but I've seen it happen. The fix above just works, everywhere.

As far as the distro in use, it's a combination. It is mainly based on Mint 21.3 (Virginia), with a splash of this and that. It's never mattered though, it's always failed for me. Looking around via searches, it seems like it actually is a problem, where they change to picotool... That didn't fix it for me though, and it allowed me to flash it 3 times, no reboot, so I fixed the python.