Skip to content

Commit f56d0d5

Browse files
committed
Streamline ESP32 image creation
Modifies the ESP32 build configuration and mkimage tool to automatically detect the image flavor based on the partition table used. By checking the offset of the application partition the correct flavor of language support is used when creating images. Adds a config option to configure an Elixir supported build by using `idf.py -DAVM_ELIXIR_BOOT=on set-target ${CHIP}`. Signed-off-by: Winford <[email protected]>
1 parent e6bf532 commit f56d0d5

17 files changed

+128
-48
lines changed

.github/workflows/esp32-mkimage.yaml

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ jobs:
125125
shell: bash
126126
working-directory: ./src/platforms/esp32/
127127
run: |
128-
cp sdkconfig.release-defaults sdkconfig.defaults
128+
cp sdkconfig.release-defaults.in sdkconfig.defaults.in
129129
130130
- name: "Build ${{ matrix.soc }}${{ matrix.flavor }} with idf.py"
131131
shell: bash
@@ -138,19 +138,14 @@ jobs:
138138
mv partitions${{ matrix.flavor }}.csv partitions.csv
139139
fi
140140
idf.py set-target ${{ matrix.soc }}
141-
idf.py reconfigure
142141
idf.py build
143142
144143
- name: "Create a ${{ matrix.soc }}${{ matrix.flavor }} image"
145144
working-directory: ./src/platforms/esp32/build
146145
run: |
147-
if [ -z "${{ matrix.flavor }}" ]
146+
./mkimage.sh
147+
if [ -n "${{ matrix.flavor }}" ]
148148
then
149-
./mkimage.sh
150-
else
151-
FLAVOR_SUFFIX=$(echo "${{ matrix.flavor }}" | sed 's/-//g')
152-
BOOT_FILE="../../../../build/libs/esp32boot/${FLAVOR_SUFFIX}_esp32boot.avm"
153-
./mkimage.sh --boot "$BOOT_FILE"
154149
mv atomvm-${{ matrix.soc }}.img atomvm-${{ matrix.soc }}${{ matrix.flavor }}.img
155150
fi
156151
ls -l *.img

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6464
- Added `proc_lib`
6565
- Added gen_server support for timeout tuples in callback return actions introduced in OTP-28.
6666
- Added `sys`
67+
- Added ESP32 `-DATOMVM_ELIXIR_SUPPORT=on` configuration option
6768

6869
### Changed
6970

@@ -82,6 +83,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8283
- `binary_to_integer` and `list_to_integer` do not raise anymore `overflow` error, they raise
8384
instead `badarg`.
8485
- ESP32 cmake build options are now also exposed in `idf.py menuconfig`.
86+
- ESP32 Elixir support is determined automatically from the offset of `boot.avm` in the partiton
87+
table.
8588

8689
### Fixed
8790

UPDATING.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ bitshifts: e.g. `(16#FFFF band 0xF) bsl 252`.
1919
- `binary_to_integer` and `list_to_integer` do not raise `overflow` error anymore, they instead
2020
raise `badarg` when trying to parse an integer that exceeds 256 bits. Update any relevant error
2121
handling code.
22+
- ESP32 builds with Elixir support may be configured without making changes to git tracked files
23+
using `idf.py -DATOMVM_ELIXIR_SUPPORT=on set-target ${CHIP}` instead of copying
24+
partitions-elixir.csv to partitions.csv. This configures the build to use partitions-elixir.csv for
25+
the partition table. The `main.avm` offset in the partition table will determine which flavor of
26+
esp32boot libraries to include for the `idf.py flash` task and the image assembled by
27+
`build/mkimage.sh`.
28+
- ESP32 release builds may be configured with `idf.py -DATOMVM_RELEASE=on set-target ${CHIP}`
29+
rather than copy sdkconfig.release-defaults.in to sdkconfig.defaults.in (which still requires a
30+
`reconfigure` or `set-target` to be run to pick up the changes), this may also be combined with the
31+
`ATOMVM_ELIXIR_SUPPORT` option. For example, an Elixir supported release build is configured using:
32+
`idf.py -DATOMVM_ELIXIR_SUPPORT=on -DATOMVM_RELEASE=on set-target ${CHIP}`
2233

2334
## v0.6.4 -> v0.6.5
2435

doc/src/build-instructions.md

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -239,29 +239,31 @@ $ cd <atomvm-source-tree-root>
239239
$ cd src/platforms/esp32
240240
```
241241

242-
If you want to build an image with Elixir modules included you must first have a version of Elixir installed that is compatible with your OTP version, then add the following line to sdkconfig.defaults:
242+
Start by configuring the default build configuration of local `sdkconfig` for your target device:
243+
243244
```shell
244-
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-elixir.csv"
245+
$ idf.py set-target ${CHIP}
245246
```
246247

247-
Start by updating the default build configuration of local `sdkconfig` file via the `idf.py reconfigure` command:
248+
If you want to build a deployment with Elixir modules included you must first have a version of Elixir
249+
installed that is compatible with your OTP version, and instead use the command:
248250

249251
```shell
250-
$ idf.py set-target esp32
251-
$ idf.py reconfigure
252+
idf.py -DATOMVM_ELIXIR_SUPPORT=on set-target ${CHIP}`
252253
```
253254

254255
```{tip}
255-
For those familiar with esp-idf the build can be customized using `menuconfig` instead of
256-
`reconfigure`:
256+
For those familiar with esp-idf the build can be customized using `menuconfig`:
257257
258+
$ idf.py set-target ${CHIP}
258259
$ idf.py menuconfig
259260
260261
This command will bring up a curses dialog box where you can make adjustments such as not including
261262
AtomVM components that are not desired in a particular build. You can also change the behavior of a
262-
crash in the VM to print the error and reboot, or halt after the error is printed. Extreme caution
263-
should be used when changing any non AtomVM settings. You can quit the program by typing `Q`.
264-
Save the changes, and the program will exit.
263+
crash in the VM to print the error and reboot, or halt after the error is printed. To configure an
264+
Elixir supported build under the "Partition Table" setting select the Custom partitions CSV file and
265+
set this to `partitions-elixir.csv`. Extreme caution should be used when changing any non AtomVM
266+
settings. You can quit the program by typing `Q`. Save the changes, and the program will exit.
265267
```
266268
267269
You can now build AtomVM using the build command:
@@ -482,9 +484,17 @@ core Erlang libraries will be written to the `build/libs` directory in the AtomV
482484
you target a different build directory when running CMake.
483485
```
484486
485-
Running this script will generate a single `atomvm-<sha>.img` file in the `build` directory of the esp32 source tree, where `<sha>` is the git hash of the current checkout. This image contains the ESP32 bootloader, AtomVM executable, and the `eavmlib` and `estdlib` Erlang libraries in one file, which can then be flashed to address `0x1000` for the esp32. The bootloader address varies for other chip variants. See the [flashing a binary image to ESP32](./getting-started-guide.md#flashing-a-binary-image-to-esp32) section of the [Getting Started Guide](./getting-started-guide.md) for a chart with the bootloader offset address of each model.
487+
Running this script will generate a single `atomvm-<target-chip>.img` file in the `build` directory
488+
of the esp32 source tree, where `<target-chip>` is the device configured with `set-target`. This
489+
image contains the ESP32 bootloader, AtomVM executable, and the `eavmlib` and `estdlib` Erlang
490+
libraries (and `exavmlib` Elixir libraries if configured for Elixir support) in one file, which can
491+
then be flashed to address `0x1000` for the esp32. The bootloader address varies for other chip
492+
variants. See the
493+
[flashing a binary image to ESP32](./getting-started-guidemd#flashing-a-binary-image-to-esp32)
494+
section of the [Getting Started Guide](./getting-started-guide.md) for a chart with the bootloader
495+
offset address of each model.
486496
487-
To build a thin image with only Erlang libraries `mkimage.sh` script is run from the `src/platform/esp32` directory as follows:
497+
To build a complete image use this command from the `src/platform/esp32` directory as follows:
488498
489499
```shell
490500
$ ./build/mkimage.sh
@@ -496,18 +506,6 @@ Wrote AtomVM Virtual Machine at offset 0x10000 (65536)
496506
Wrote AtomVM Core BEAM Library at offset 0x1D0000 (1114112)
497507
```
498508
499-
To build a full image with Erlang and Elixir libraries the path to the previously (during the generic_unix build) built `elixir_esp32boot.avm` must be passed to the `mkimage.sh` script as follows (Note: this is still run from the AtomVM/src/platforms/esp32 directory for the relative path to work - feel free to use the absolute path to this file):
500-
501-
```shell
502-
$ ./build/mkimage.sh --boot ../../../build/libs/esp32boot/elixir_esp32boot.avm
503-
Writing output to /home/joe/AtomVM/src/platforms/esp32/build/atomvm-esp32.img
504-
=============================================
505-
Wrote bootloader at offset 0x1000 (4096)
506-
Wrote partition-table at offset 0x8000 (32768)
507-
Wrote AtomVM Virtual Machine at offset 0x10000 (65536)
508-
Wrote AtomVM Core BEAM Library at offset 0x1D0000 (1114112)
509-
```
510-
511509
Users can then use the `esptool.py` directly to flash the entire image to the ESP32 device, and then flash their applications to the `main.app` partition at address `0x210000`, (or `0x250000` for Elixir images)
512510
513511
But first, it is a good idea to erase the flash, e.g.,
@@ -602,7 +600,7 @@ applications for the AtomVM platform.
602600
603601
#### Flashing the core libraries
604602
605-
If you are doing development work on the core Erlang/Elixir libraries and wish to test changes that do not involve the `C` code in the core VM you may flash `esp32boot.avm` (or `elixir_esp32boot.avm` when using an Elixir partition table) to the boot.avm partition (offset 0x1D0000) by using the `flash.sh` script in the esp32 build directory as follows:
603+
If you are doing development work on the core Erlang/Elixir libraries and wish to test changes that do not involve the `C` code in the core VM you may flash `esp32boot.avm` or `elixir_esp32boot.avm` to the boot.avm partition by using the `flash.sh` script in the esp32 build directory as follows:
606604
607605
```shell
608606
$ build/flash.sh -l ../../../build/libs/esp32boot.avm
@@ -636,6 +634,13 @@ Leaving...
636634
Hard resetting via RTS pin...
637635
```
638636
637+
```{attention}
638+
It is important that you flash the `esp32boot` variant that matches the configuration used to
639+
create the build currently on the device. Flashing `elixir_esp32boot.avm` to a device that was not
640+
flashed with an Elixir support build will not work, AtomVM will still try to load an application
641+
from an address that is now occupied by the `exavmlib` modules.
642+
```
643+
639644
### Adding custom Nifs, Ports, and third-party components
640645
641646
While AtomVM is a functional implementation of the Erlang virtual machine, it is nonetheless designed to allow developers to extend the VM to support additional integrations with peripherals and protocols that are not otherwise supported in the core virtual machine.
@@ -651,7 +656,9 @@ documentation.
651656
The instructions for adding custom Nifs and ports differ in slight detail, but are otherwise quite similar. In general, they involve:
652657
653658
1. Adding the custom Nif or Port to the `components` directory of the AtomVM source tree.
654-
1. Run `idf.py reconfigure` to pick up any menuconfig options, many extra drivers have an option to disable them (they are enabled by default). Optionally use `idf.py menuconfig` and confirm the driver is enabled and save when quitting.
659+
1. Run `idf.py set-target ${CHIP}` to pick up any menuconfig options, many extra drivers have an
660+
option to disable them (they are enabled by default). Optionally use `idf.py menuconfig` and
661+
confirm the driver is enabled and save when quitting.
655662
1. Building the AtomVM binary.
656663
657664
```{attention}

src/platforms/esp32/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright 2017-2025 Davide Bettio <[email protected]>
2+
# Copyright 2025 Winford (UncleGrumpy) <[email protected]>
3+
#
4+
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5+
6+
sdkconfig.defaults
7+
sdkconfig.old

src/platforms/esp32/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ set(AVM_SELECT_IN_TASK ON)
5454
# JIT is not available yet on esp32
5555
set(AVM_DISABLE_JIT ON)
5656

57+
## Configure partition table based on boot flavor
58+
if (${ATOMVM_ELIXIR_SUPPORT})
59+
set(AVM_PARTITION_TABLE_FILENAME "partitions-elixir.csv")
60+
else()
61+
set(AVM_PARTITION_TABLE_FILENAME "partitions.csv")
62+
endif()
63+
64+
if (${ATOMVM_RELEASE})
65+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.release-defaults.in ${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.defaults @ONLY)
66+
else()
67+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.defaults.in ${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.defaults @ONLY)
68+
endif()
69+
5770
project(atomvm-esp32)
5871

5972
# esp-idf does not use compile_feature but instead sets version in
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#
2+
# This file is part of AtomVM.
3+
#
4+
# Copyright 2025 Winford (Uncle Grumpy) <[email protected]>
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
#
20+
21+
partition_table_get_partition_info(app_offset "--partition-name main.avm" "offset")
22+
set(AVM_APP_OFFSET "${app_offset}")
23+
if ("${app_offset}" STREQUAL "0x210000")
24+
set(BOOT_LIBS "esp32boot.avm")
25+
elseif ("${app_offset}" STREQUAL "0x250000")
26+
set(BOOT_LIBS "elixir_esp32boot.avm")
27+
else()
28+
set(BOOT_LIBS "NONE")
29+
endif()

src/platforms/esp32/sdkconfig.defaults

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CONFIG_PARTITION_TABLE_CUSTOM=y
2+
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
3+
CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y
4+
CONFIG_LWIP_IPV6=n
5+
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="@AVM_PARTITION_TABLE_FILENAME@"
6+
CONFIG_PARTITION_TABLE_FILENAME="@AVM_PARTITION_TABLE_FILENAME@"

0 commit comments

Comments
 (0)