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

Improve pico_flash task #26

Merged
merged 1 commit into from
Feb 19, 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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,9 @@ If your pico uses a different device path or mount directory supply the full pat

shell$ rebar3 atomvm pico_flash --path /mnt/pico --reset /dev/cu.usbmodem1411202

> Warning: There is currently a known bug that occurs when the VM is compiled with the `-DAVM_WAIT_FOR_USB_CONNECT` cmake option. If you have previously connected to the tty serial port with `screen`, `minicom`, or similar and have disconnected or closed the session, the device will take unusually long to reset and fail to mount the FAT partition within 30 seconds and `pico_flash` will fail. This can be worked around by unplugging the pico from usb and plug it back in again, before repeating the flash procedure.
> Note: If you use the `pico_flash` task while you are still connected to a serial monitoring application such as `minicom` or `screen` the `pico_flash` task will attempt to locate [`picotool`](https://github.com/raspberrypi/picotool) in the users PATH. If `picotool` is found it will be used to reboot the pico, disconnecting the serial monitor in the process, and the device will be put into `BOOTSEL` mode after it is rebooted. If `picotool` is not available the user will be informed, and reminded that manually closing the serial monitor is necessary before using `pico_flash`.

> Warning: There is currently a known bug that occurs when the VM has exited, the processor is left in as hung state. The device will take unusually long attempting to reset, and fail to mount the FAT partition within 30 seconds and `pico_flash` will fail. There is work under way to fix this bug, but in the meantime it can be worked around by unplugging the pico from usb and plug it back in again, before repeating the flash procedure.

The following table enumerates the properties that may be defined in your project's `rebar.config` file for this task. Use `pico_flash` as the key for any properties defined for this task.

Expand Down
49 changes: 35 additions & 14 deletions src/atomvm_pico_flash_provider.erl
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ init(State) ->
{example, "rebar3 atomvm pico_flash"},
% list of options understood by the plugin
{opts, ?OPTS},
{short_desc, "Convert an AtomVM packbeam file to uf2 and copy to a an rp2040 device"},
{short_desc, "Convert an AtomVM packbeam file to uf2 and copy to an rp2040 device"},
{desc,
"~n"
"Use this plugin to convert an AtomVM packbeam file to a rp2040 a uf2 file and copy to an rp2040 devices.~n"
"Use this plugin to convert an AtomVM packbeam file to a uf2 file and copy to an rp2040 device.~n"
}
]),
{ok, rebar_state:add_provider(State, Provider)}.
Expand All @@ -74,8 +74,8 @@ do(State) ->
),
{ok, State}
catch
C:E:S ->
rebar_api:error("An error occurred in the ~p task. Class=~p Error=~p Stacktrace=~p~n", [?PROVIDER, C, E, S]),
_C:E:_S ->
rebar_api:error("An error occurred in the ~p task. Error=~p~n", [?PROVIDER, E]),
{error, E}
end.

Expand Down Expand Up @@ -158,7 +158,7 @@ wait_for_mount(Mount, Count) when Count < 30 ->
end;
wait_for_mount(Mount, 30) ->
rebar_api:error("Pico not mounted at ~s after 30 seconds. giving up...", [Mount]),
rebar_api:abort().
erlang:throw(mount_error).

%% @private
check_pico_mount(Mount) ->
Expand All @@ -170,7 +170,7 @@ check_pico_mount(Mount) ->
ok;
"false\n" ->
rebar_api:error("Pico not mounted at ~s.", [Mount]),
rebar_api:abort()
erlang:throw(no_device)
end.

%% @private
Expand Down Expand Up @@ -202,26 +202,47 @@ do_flash(ProjectApps, PicoPath, ResetPort) ->
ok;
true ->
Flag = get_stty_file_flag(),
Reset = lists:join(" ", [
BootselMode = lists:join(" ", [
"stty", Flag, ResetPort, "1200"
]),
rebar_api:info("Resetting device at path ~s", [ResetPort]),
ResetStatus = os:cmd(Reset),
ResetStatus = os:cmd(BootselMode),
case ResetStatus of
"" ->
ok;
_Any ->
rebar_api:error("Reset ~s failed. Is tty console attached?", [ResetPort]),
rebar_api:abort()
Error ->
case os:find_executable(picotool) of
false ->
rebar_api:error("Warning: ~s~nUnable to locate 'picotool', close the serial monitor before flashing, or install picotool for automatic disconnect and BOOTSEL mode.", [Error]),
erlang:throw(reset_error);
_Path ->
rebar_api:warn("Warning: ~s~nFor faster flashing remember to disconnect serial monitor first.", [Error]),
DevReset = lists:join(" ", [
"picotool", "reboot", "-f", "-u"
]),
rebar_api:warn("Disconnecting serial monitor with: `~s' in 5 seconds...", [DevReset]),
timer:sleep(5000),
RebootReturn = os:cmd(DevReset),
RebootStatus = string:trim(RebootReturn),
case RebootStatus of
"The device was asked to reboot into BOOTSEL mode." ->
ok;
BootError ->
rebar_api:error("Failed to prepare pico for flashing: ~s", [BootError]),
erlang:throw(picoflash_reboot_error)
end
end
end,
rebar_api:info("Waiting for the device at path ~s to settle and mount...", [PicoPath]),
PrettyPath = lists:join(" ", [
"echo", PicoPath
]),
rebar_api:info("Waiting for the device at path ~s to settle and mount...", [string:trim(os:cmd(PrettyPath))]),
wait_for_mount(PicoPath, 0)
fadushin marked this conversation as resolved.
Show resolved Hide resolved
end,
check_pico_mount(PicoPath),
TargetUF2 = get_uf2_file(ProjectApps),
Cmd = lists:join(" ", [
"cp", "-v", TargetUF2, PicoPath
]),
rebar_api:info("Copying ~s to ~s...~n", [TargetUF2, PicoPath]),
io:format("~s", [os:cmd(Cmd)]),
rebar_api:info("Copying packbeam files...~n~s", [os:cmd(Cmd)]),
ok.
Loading