Skip to content

Conversation

@UncleGrumpy
Copy link
Collaborator

Changes include automatic detection of the beam application partition (default main.avm) to prevent overwriting the wrong flash sectors. This prevents overwriting Elixir library modules for Elixir supported builds, and assures that the application will be written to the same address that AtomVM will load and run. When flashing to a device with a custom partition table the app_partition parameter should be supplied if the app partition is not named main.avm.

Other changes include:

  • Device port is now auto discovered instead of hard coded
  • Improved error reporting
  • Stacktraces are only displayed in diagnostic mode
  • Dialyzer warnings for atomvm_rebar3_plugin esp32_flash provider fixed

@UncleGrumpy UncleGrumpy marked this pull request as draft July 29, 2025 02:22
@UncleGrumpy UncleGrumpy force-pushed the detect_esp32_offset branch 3 times, most recently from 5685f2a to 91a5fc9 Compare August 2, 2025 05:59
@UncleGrumpy UncleGrumpy marked this pull request as ready for review August 2, 2025 06:00
@UncleGrumpy UncleGrumpy force-pushed the detect_esp32_offset branch from 91a5fc9 to 783d3ad Compare August 2, 2025 08:14
@UncleGrumpy UncleGrumpy requested review from bettio and pguyot October 21, 2025 14:12
@UncleGrumpy UncleGrumpy force-pushed the detect_esp32_offset branch 2 times, most recently from 586a1ef to d334c12 Compare December 8, 2025 07:35
@UncleGrumpy UncleGrumpy requested review from pguyot and removed request for bettio and pguyot December 8, 2025 07:36
Copy link
Collaborator

@pguyot pguyot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Partial review)

auto ->
read_flash_offset(EspTool, Port, Partition, State);
Val ->
Offset0 = read_flash_offset(EspTool, Port, Partition, State),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicer transition behaviour would be to check that offset matches the beginning of any partition (main.avm or named otherwise).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea! Now if the given offset does not match the expected partition name a warning will be issued, but as long as it is a data partition of a valid subtype (any subtype not specifically reserved for other purposes - i.e. cordump, nvs, nsv_keys, fat, etc) the partition will be used.

"0xc00",
TempFile
]),
os:cmd(Cmd),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os:cmd doesn't return the status. We may want to use the good old open_port({spawn_executable, Esptool}).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated this file and the esp32_flash provider to use open_port/2, this had the added benefit of faster flash operations and quieter output.

Changes error reporting for the esp32_flash task to include stack trace when rebar3 is executed
with DIAGNOSTIC=1 or DEBUG=1.

Signed-off-by: Winford <winford@object.stream>
@UncleGrumpy UncleGrumpy force-pushed the detect_esp32_offset branch 2 times, most recently from 3a391b9 to 4d4e57e Compare December 16, 2025 03:25
@UncleGrumpy UncleGrumpy requested a review from pguyot December 16, 2025 03:44
@UncleGrumpy UncleGrumpy force-pushed the detect_esp32_offset branch 2 times, most recently from 11dfd1c to 9b7d519 Compare December 16, 2025 06:04
The `offset` for the beam application partition is now read from the partition table on the attached
esp32 device. When a custom partition table is used that does not use `main.avm` for the beam app
partition name the `app_partition` parameter should be used to specify the application partition
to be flashed. Valid application partition sub-types (the type is `data`) are `phy` or `0xAA`.

If the `offset` parameter is specified it will be used to verify that the offset address of the
application partition matched the expected value. This may be used to prevent flashing to a
standard build of AtomMV for application that require a custom partition table.

The `port` that the ESP32 is attached to is now auto discovered by default. When more than one
ESP32 device is plugged into USB the port should be specified to control which device is flashed.

Error reporting has been improved with descriptive error messages.

Dialyzer warnings for the esp32_flash task have been fixed when analyzing atomvm_rebar3_plugin.

Signed-off-by: Winford <winford@object.stream>
I.
-spec integer_from_string(S :: list() | integer()) -> Value :: integer().
integer_from_string("auto") ->
-1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should have this function return integer() | auto instead of using -1 as a magic number.

TempFile = get_part_tempfile(State),
Address =
case Offset of
-1 ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want auto here.

rebar_api:abort("Partition ~s not found!", [Partition]);
error:invalid_partition_table ->
rebar_api:abort(
"Error parsing partition table, possible line noise reading from device.",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Port already open with minicom is more likely here than line noise ;-)

end;
Val ->
Offset0 = read_flash_offset(EspTool, Port, Partition, TempFile),
case Val =:= Offset0 of
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case Offset0 of or if Val =:= Offset0 look more Erlang to me.

end,
Cmd = lists:join(" ", [
EspTool,
[ProjectAppAVM | _] = [get_avm_file(ProjectApp) || ProjectApp <- ProjectApps],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you using side effects from get_avm_file/1 here or could you just process the first ProjectApps (with hd(ProjectApps))?

while [ "${#}" -gt 0 ]; do
case ${1} in
read_flash ) shift
if [ "${1}" = "0x8000" ] && [ "${2}" = "0xC00" ] || [ "${2}" = "0xc00" ]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if [ "${1}" = "0x8000" ] && [ "${2}" = "0xC00" ] || [ "${2}" = "0xc00" ]; then
if [ "${1}" = "0x8000" ] && { [ "${2}" = "0xC00" ] || [ "${2}" = "0xc00" ]; }; then

I;
integer_from_string(S) when is_list(S) ->
S0 = string:trim(S),
case lists:prefix("0x", S0) of
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use string:prefix/2 or lists:sublist(S0, 2) instead of lists:subtract(S0, "0x")


-spec lookup_partition_by_name(Name :: string(), Partitions :: binary()) ->
Offset :: non_neg_integer().
lookup_partition_by_name(Name, Partitions) ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lookup_partition_by_name/2 and lookup_partition_by_offset should have the same signature (return error tuple or raise).


%% @private
get_part_tempfile(State) ->
OutDir = filename:absname(rebar_dir:base_dir(State)),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should call mktemp(1) here

{Tool, {exit_status, Status}} ->
error({"esptool.py failure", Status})
after 120000 ->
error("esptool.py failed (2 minute timeout exceeded)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tool is not closed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants