raspberrypi / picotool

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unable to reset pico

LandryNorris opened this issue · comments

When I run picotool.exe reboot -f -u, I get the following error: ERROR: Unable to locate reset interface on the device, despite the fact that running the info command indicates Device at bus 1, address 30 appears to be a RP2040 device with a USB serial connection, not in BOOTSEL mode. You can force reboot into BOOTSEL mode via 'picotool reboot -f -u' first.. Running a load command does work, however, if I manually enter BOOTSEL via the button.

I am using picotool 1.1.2 and libusb 1.0.26 on Windows 11.

I have tried using both the Win32 driver and the libusb-win32 driver from Zadig.

By adding some logging to the source for the 1.1.2 release, I can determine that picotool can find two interfaces with altsettings: one with class/subclass of 2/2, and one with class/subclass of 10/0. Neither of these matches the defined class/subclass for reset.

Having the same issue. When using PlatformIO (which uses the tool too), it works without problems. Checking the log (macOS) shows the following:
Forcing reset using 1200bps open/close on port /dev/cu.usbmodem11301

Using picotool shows:
"No accessible RP2040 devices in BOOTSEL mode were found.

but:

Device at bus 1, address 4 appears to be a RP2040 device with a USB serial connection, so consider
-f to force the reboot."

Now using the proposed command line shows:
"ERROR: Unable to locate reset interface on the device"

You need to ensure that PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE is enabled, which adds the reset interface. See Appendix B in https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf

Forcing reset using 1200bps open/close on port /dev/cu.usbmodem11301

I guess that indicates that PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE is enabled. Maybe that implies that PlatformIO has disabled PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE for some reason?

You need to ensure that PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE is enabled, which adds the reset interface. See Appendix B in https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf

Forcing reset using 1200bps open/close on port /dev/cu.usbmodem11301

I guess that indicates that PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE is enabled. Maybe that implies that PlatformIO has disabled PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE for some reason?

What I mean is PlatformIO (with Arduino) uses picotool (or I'm wrong?) to reset the Pico into BOOTSEL for uploading the uf2. So uploading via VSCode with PlatformIO does everything automatically. But when building my app with pico-sdk (No platformIO nor Arduino), I first have to reconnect Pico while pressing BOOTSEL. I would like to prevent this.

What I mean is PlatformIO (with Arduino) uses picotool (or I'm wrong?) to reset the Pico into BOOTSEL for uploading the uf2.

Your log message indicates that PlatformIO is rebooting the Pico by changing the baud rate of the USB-serial device, which isn't something that picotool does itself.

But when building my app with pico-sdk (No platformIO nor Arduino), I first have to reconnect Pico while pressing BOOTSEL. I would like to prevent this.

Have you got stdio_usb enabled in your CMakeLists.txt ? See Chapter 4 in https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

Your log message indicates that PlatformIO is rebooting the Pico by changing the baud rate of the USB-serial device, which isn't something that picotool does itself.

Ok understood. I thought the message "use -f to force the reboot" would tell me it does that.

I thought the message "use -f to force the reboot" would tell me it does that.

Copied from the README.md for this project:

        -f, --force
            Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing
            the command (unless the command itself is a 'reboot') the device will be rebooted back to application mode
        -F, --force-no-reboot
            Force a device not in BOOTSEL mode but running compatible code to reset so the command can be executed. After executing
            the command (unless the command itself is a 'reboot') the device will be left connected and accessible to picotool, but
            without the RPI-RP2 drive mounted

i.e. if your Pico is already in BOOTSEL mode then the -f flag isn't necessary; but if your Pico is currently running user-code (and if you have both stdio_usb and the custom reset interface enabled), then you need to use the -f flag, and picotool will then use the custom reset-interface to reboot your Pico into BOOTSEL mode, before doing whatever else it is that you asked picotool to do. (I hope that all makes sense!)

Yes, but you already mentioned the point I was talking about:

(and if you have both stdio_usb and the custom reset interface enabled)

If PlatformIO is able to reboot the Pico, even if it is not in BOOTSEL mode nor has these interfaces enabled, I would expect Picotool to be able to handle this too.

As already mentioned, it appears that PlatformIO (which I've not used myself) is using the PICO_STDIO_USB_ENABLE_RESET_VIA_BAUD_RATE feature (whereby it changes the baud-rate of the stdio_usb connection to PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE).
If you want picotool to be able to do this baud-rate twiddling too, you should probably open a separate issue for that.

commented

Also getting the same issues with picotool where the f flag is not working on linux:

image

I have confirmed that PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE is set as per the SDK default.

@dmo9 Have you tried using sudo? (or whatever the ArchLinux equivalent is)

commented

@dmo9 Have you tried using sudo? (or whatever the ArchLinux equivalent is)

No difference with sudo. Per the picotool documentation, it states the flag should work with "compatible" code, but there is no definition of what compatible code is. My code does call stdio_init_all() and enables the USB port via pico_enable_stdio_usb(nasa 1) in CMakeLists.txt

Interestingly, when flashing with picoprobe, which works fine, I get the following message:
Warn : could not read product string for device 0x2e8a:0x000a: Operation timed out

After a really light dive into picotool's source code, I noticed that picotool's error message probably from the following function on line 1584 of main.cpp:
string missing_device_string(bool wasRetry)

Could this be the root cause of the issue?

If you want to do a slightly deeper dive, you should probably take a look at raspberrypi/pico-sdk#197 and #23

commented

Ok, I figured out the problem: incompatible code. My code was exiting before picotool could send it commands. I suggest that the definition of compatible code is added to this repo's documentation.

main.c:

#include "pico/stdio_usb"
int main()
{
    stdio_usb_init();
    while(true)
    {
        // your code here
    }
}

CMakeLists.txt:

pico_enable_stdio_usb(<yourProjectName> 1)