AtomVM icon indicating copy to clipboard operation
AtomVM copied to clipboard

RP2040 `AVM_WAIT_FOR_USB_CONNECT=on` conflict with `rebar3 atomvm pico_flash` task

Open UncleGrumpy opened this issue 2 years ago • 5 comments

There is currently a conflict with the rebar3 atomvm pico_flash task that exhibits itself when the AtomVM rp2040 port is compiled with the -DAVM_WAIT_FOR_USB_CONNECT=on cmake option. This is not a default option, so most users will be unaffected.

This option currently leaves the device waiting at boot for a serial connection. This is convenient to catch the output of hello_world, but breaks the automatic reset feature in the rebar3 atomvm pico_flash task that puts the device into BOOTSEL mode for uploading firmware, because after the reset it reverts to waiting for a serial connection.

It looks like this conflict can be avoided by not using the PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS=-1 definition and using stdio_init_all in main.c, but instead use the default PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS and create a sys_init_stdio() function that calls stdio_init_all and then if -DAVM_WAIT_FOR_USB_CONNECT=on is used waits for stdio_usb_connected() to be true. To the user the behavior should be the same, but this will allow the device to be reset into BOOTSEL mode at any time, either while in the waiting loop, or after the application is running.

The other obvious option is to just set PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS to something shorter like 10 or 15 seconds, but this would also require adding a second reset to the rebar3 atomvm pico_flash task if that timeout period is reached, this would generally be slower and more error prone than if the device was always in a resettable state.

This issue is the cause of atomvm_rebar3_plugin Issue 18.

UncleGrumpy avatar Oct 28 '23 23:10 UncleGrumpy

We should do what you suggest (implementing the way ourselves with stdio_usb_connected()) and advertise the feature as it's very useful for development.

@fadushin also shared this link that may be related?

https://forums.raspberrypi.com/viewtopic.php?t=331479

Did you try this approach?

pguyot avatar Oct 29 '23 05:10 pguyot

I have not tried that method yet, I can look into that a bit closer.

I completely agree that it is helpful, almost necessary in many cases. I think if we handle it ourselves we should consider making the default build have a 30 second wait for connection timeout.

UncleGrumpy avatar Oct 29 '23 18:10 UncleGrumpy

@fadushin also shared this link that may be related?

https://forums.raspberrypi.com/viewtopic.php?t=331479

Did you try this approach?

I did finally tests this solution, it does not seem to help in this situation.

UncleGrumpy avatar Feb 05 '24 16:02 UncleGrumpy

After further testing and checking the Pico SDK manual I found:

The return code of main() is ignored by the SDK runtime, and the default behaviour is to hang the processor on exit.

The Pico will reset into BOOTSEL while it is in the waiting for USB state (so we do not need to write a special handler as discussed above), and will reset during a running application (i.e. blinky never exits), but if the device reaches the end of main and returns 0, no attempt to reset will work because the CPU is effectively shut down. The only way around this appears to be to spin forever rather that allow main() to exit, otherwise a hard reset is required.

UncleGrumpy avatar Feb 05 '24 22:02 UncleGrumpy

I have also tried using picotool reset -f to see if this can forcibly reset a pico that is in a processor hung state after exiting main() with a return 0, and even this tool sill not trigger a CPU reset from this state.

This leaves spinning indefinitely as the best workaround for the moment.

UncleGrumpy avatar Feb 05 '24 23:02 UncleGrumpy