From cda5af86edf3022a6d5761fd56afe3b6e93793ad Mon Sep 17 00:00:00 2001 From: Winford Date: Wed, 22 May 2024 00:25:20 -0700 Subject: [PATCH 1/7] Allow setting ESP32 build options from menuconfig Exposes the settable build options for the ESP32 platform to the `idf.py menuconfig` utility, allowing for a more natural configuration experience for those already accustomed to the ESP-IDF development environment. Signed-off-by: Winford --- CHANGELOG.md | 1 + src/platforms/esp32/main/Kconfig.projbuild | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87918e9643..8e4d56a445 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `binary_to_integer/1` no longer accepts binaries such as `<<"0xFF">>` or `<<" 123">>` - `binary_to_integer` and `list_to_integer` do not raise anymore `overflow` error, they raise instead `badarg`. +- ESP32 cmake build options are now also exposed in `idf.py menuconfig`. ### Fixed diff --git a/src/platforms/esp32/main/Kconfig.projbuild b/src/platforms/esp32/main/Kconfig.projbuild index 88bf92aa1a..2992d0a284 100755 --- a/src/platforms/esp32/main/Kconfig.projbuild +++ b/src/platforms/esp32/main/Kconfig.projbuild @@ -40,4 +40,22 @@ menu "AtomVM configuration" help Enable TinyUSB CDC functionality if USE_USB_SERIAL is enabled. + config AVM_CREATE_STACKTRACES + bool "Create BEAM stack traces." + default y + help + Create stacktraces for AtomVM application debugging, when an application crashes a stacktrace will be emitted. + + config AVM_VERBOSE_ABORT + bool "Verbose error when a VM abort occurs." + default n + help + Print the C module and line number when a VM abort occurs. + + config ENABLE_REALLOC_GC + bool "Enable experimental optimized realloc garbage collection." + default n + help + Enable experimental optimized garbage collection mode that makes use of C realloc instead of copying data. + endmenu From 983026c236daf4823ef892891fc7a77d29306a06 Mon Sep 17 00:00:00 2001 From: Winford Date: Wed, 25 Jun 2025 22:37:26 +0000 Subject: [PATCH 2/7] Allow using the GetVersion.cmake file for any platform Changes GetVersion.cmake to allow use by platforms other than generic_unix, by allowing the cmake include of version.cmake before including GetVersion.cmake on other platforms. Fix version reporting for ESP32 builds when executing mkimage.sh by including the AtomVM/version.cmake and AtomVM/CMakeModules/GetVersion.cmake files to be able to get the correct version number when reporting build information during build/mkimage.sh execution. Signed-off-by: Winford --- CMakeModules/GetVersion.cmake | 4 +++- src/platforms/esp32/tools/CMakeLists.txt | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeModules/GetVersion.cmake b/CMakeModules/GetVersion.cmake index 4ec7fe95a3..971b8d0e43 100644 --- a/CMakeModules/GetVersion.cmake +++ b/CMakeModules/GetVersion.cmake @@ -18,7 +18,9 @@ # SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later # -include(${CMAKE_SOURCE_DIR}/version.cmake) +if (!ATOMVM_BASE_VERSION) + include(${CMAKE_SOURCE_DIR}/version.cmake) +endif() if (ATOMVM_DEV) set(ATOMVM_GIT_REVISION "") diff --git a/src/platforms/esp32/tools/CMakeLists.txt b/src/platforms/esp32/tools/CMakeLists.txt index 8bc657d38a..a8c9bd4650 100644 --- a/src/platforms/esp32/tools/CMakeLists.txt +++ b/src/platforms/esp32/tools/CMakeLists.txt @@ -20,6 +20,8 @@ cmake_minimum_required (VERSION 3.13) project (ReleaseEsp32) +include(../../../../version.cmake) +include(../../../../CMakeModules/GetVersion.cmake) ## Build image tools for target chip @@ -62,7 +64,7 @@ file(COPY ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/flash.sh FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) -if (NOT EXISTS ../../../../build/libs/esp32boot/esp32boot.avm) +if (NOT EXISTS ../../../../build/libs/esp32boot/${BOOT_LIBS}) message(WARNING "A generic_unix build must be done first in the top level AtomVM/build directory! \n\ Consult https://doc.atomvm.org/main/build-instructions.html for build instructions.") endif() From e6bf532a01a413b6ba1fbd67901ae0dd8954504e Mon Sep 17 00:00:00 2001 From: Winford Date: Mon, 21 Jul 2025 22:54:25 +0000 Subject: [PATCH 3/7] Fix small bug in ESP32 mkimage.sh when using the help option Change the script to exit after printing the help, instead of erroneously reporting that the image was successfully created. Signed-off-by: Winford --- src/platforms/esp32/tools/mkimage.sh.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platforms/esp32/tools/mkimage.sh.in b/src/platforms/esp32/tools/mkimage.sh.in index 2cfa9598d6..4a12281d51 100644 --- a/src/platforms/esp32/tools/mkimage.sh.in +++ b/src/platforms/esp32/tools/mkimage.sh.in @@ -25,6 +25,11 @@ escript "@CMAKE_BINARY_DIR@/mkimage.erl" \ --out "@CMAKE_BINARY_DIR@/atomvm-@CONFIG_IDF_TARGET@.img" \ "$@" +if (test ${@} = "--help"); then + echo "" + exit 0; +fi + echo "=============================================" echo "" From f56d0d5fb76721e6edba9051a9e79e0cbdc166d9 Mon Sep 17 00:00:00 2001 From: Winford Date: Mon, 30 Jun 2025 02:29:55 +0000 Subject: [PATCH 4/7] 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 --- .github/workflows/esp32-mkimage.yaml | 11 +--- CHANGELOG.md | 3 + UPDATING.md | 11 ++++ doc/src/build-instructions.md | 59 +++++++++++-------- src/platforms/esp32/.gitignore | 7 +++ src/platforms/esp32/CMakeLists.txt | 13 ++++ src/platforms/esp32/GetBootAVM.cmake | 29 +++++++++ src/platforms/esp32/sdkconfig.defaults | 4 -- src/platforms/esp32/sdkconfig.defaults.in | 6 ++ ....license => sdkconfig.defaults.in.license} | 0 ...defaults => sdkconfig.release-defaults.in} | 2 + ... => sdkconfig.release-defaults.in.license} | 0 src/platforms/esp32/tools/CMakeLists.txt | 18 ++++-- .../platforms/esp32/tools/flash.sh.in | 2 +- src/platforms/esp32/tools/mkimage.config.in | 4 +- src/platforms/esp32/tools/mkimage.erl | 4 +- src/platforms/esp32/tools/mkimage.sh.in | 3 +- 17 files changed, 128 insertions(+), 48 deletions(-) create mode 100644 src/platforms/esp32/.gitignore create mode 100644 src/platforms/esp32/GetBootAVM.cmake delete mode 100644 src/platforms/esp32/sdkconfig.defaults create mode 100644 src/platforms/esp32/sdkconfig.defaults.in rename src/platforms/esp32/{sdkconfig.defaults.license => sdkconfig.defaults.in.license} (100%) rename src/platforms/esp32/{sdkconfig.release-defaults => sdkconfig.release-defaults.in} (60%) rename src/platforms/esp32/{sdkconfig.release-defaults.license => sdkconfig.release-defaults.in.license} (100%) rename tools/dev/flash.sh => src/platforms/esp32/tools/flash.sh.in (98%) diff --git a/.github/workflows/esp32-mkimage.yaml b/.github/workflows/esp32-mkimage.yaml index f7baaf2a36..1735718eb3 100644 --- a/.github/workflows/esp32-mkimage.yaml +++ b/.github/workflows/esp32-mkimage.yaml @@ -125,7 +125,7 @@ jobs: shell: bash working-directory: ./src/platforms/esp32/ run: | - cp sdkconfig.release-defaults sdkconfig.defaults + cp sdkconfig.release-defaults.in sdkconfig.defaults.in - name: "Build ${{ matrix.soc }}${{ matrix.flavor }} with idf.py" shell: bash @@ -138,19 +138,14 @@ jobs: mv partitions${{ matrix.flavor }}.csv partitions.csv fi idf.py set-target ${{ matrix.soc }} - idf.py reconfigure idf.py build - name: "Create a ${{ matrix.soc }}${{ matrix.flavor }} image" working-directory: ./src/platforms/esp32/build run: | - if [ -z "${{ matrix.flavor }}" ] + ./mkimage.sh + if [ -n "${{ matrix.flavor }}" ] then - ./mkimage.sh - else - FLAVOR_SUFFIX=$(echo "${{ matrix.flavor }}" | sed 's/-//g') - BOOT_FILE="../../../../build/libs/esp32boot/${FLAVOR_SUFFIX}_esp32boot.avm" - ./mkimage.sh --boot "$BOOT_FILE" mv atomvm-${{ matrix.soc }}.img atomvm-${{ matrix.soc }}${{ matrix.flavor }}.img fi ls -l *.img diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e4d56a445..5700034f71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `proc_lib` - Added gen_server support for timeout tuples in callback return actions introduced in OTP-28. - Added `sys` +- Added ESP32 `-DATOMVM_ELIXIR_SUPPORT=on` configuration option ### Changed @@ -82,6 +83,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `binary_to_integer` and `list_to_integer` do not raise anymore `overflow` error, they raise instead `badarg`. - ESP32 cmake build options are now also exposed in `idf.py menuconfig`. +- ESP32 Elixir support is determined automatically from the offset of `boot.avm` in the partiton +table. ### Fixed diff --git a/UPDATING.md b/UPDATING.md index f905f1681c..f3bcb35f82 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -19,6 +19,17 @@ bitshifts: e.g. `(16#FFFF band 0xF) bsl 252`. - `binary_to_integer` and `list_to_integer` do not raise `overflow` error anymore, they instead raise `badarg` when trying to parse an integer that exceeds 256 bits. Update any relevant error handling code. +- ESP32 builds with Elixir support may be configured without making changes to git tracked files +using `idf.py -DATOMVM_ELIXIR_SUPPORT=on set-target ${CHIP}` instead of copying +partitions-elixir.csv to partitions.csv. This configures the build to use partitions-elixir.csv for +the partition table. The `main.avm` offset in the partition table will determine which flavor of +esp32boot libraries to include for the `idf.py flash` task and the image assembled by +`build/mkimage.sh`. +- ESP32 release builds may be configured with `idf.py -DATOMVM_RELEASE=on set-target ${CHIP}` +rather than copy sdkconfig.release-defaults.in to sdkconfig.defaults.in (which still requires a +`reconfigure` or `set-target` to be run to pick up the changes), this may also be combined with the +`ATOMVM_ELIXIR_SUPPORT` option. For example, an Elixir supported release build is configured using: +`idf.py -DATOMVM_ELIXIR_SUPPORT=on -DATOMVM_RELEASE=on set-target ${CHIP}` ## v0.6.4 -> v0.6.5 diff --git a/doc/src/build-instructions.md b/doc/src/build-instructions.md index ea1251a126..4325fc6af3 100644 --- a/doc/src/build-instructions.md +++ b/doc/src/build-instructions.md @@ -239,29 +239,31 @@ $ cd $ cd src/platforms/esp32 ``` -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: +Start by configuring the default build configuration of local `sdkconfig` for your target device: + ```shell -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-elixir.csv" +$ idf.py set-target ${CHIP} ``` -Start by updating the default build configuration of local `sdkconfig` file via the `idf.py reconfigure` command: +If you want to build a deployment with Elixir modules included you must first have a version of Elixir +installed that is compatible with your OTP version, and instead use the command: ```shell -$ idf.py set-target esp32 -$ idf.py reconfigure +idf.py -DATOMVM_ELIXIR_SUPPORT=on set-target ${CHIP}` ``` ```{tip} -For those familiar with esp-idf the build can be customized using `menuconfig` instead of -`reconfigure`: +For those familiar with esp-idf the build can be customized using `menuconfig`: + $ idf.py set-target ${CHIP} $ idf.py menuconfig This command will bring up a curses dialog box where you can make adjustments such as not including AtomVM components that are not desired in a particular build. You can also change the behavior of a -crash in the VM to print the error and reboot, or halt after the error is printed. Extreme caution -should be used when changing any non AtomVM settings. You can quit the program by typing `Q`. -Save the changes, and the program will exit. +crash in the VM to print the error and reboot, or halt after the error is printed. To configure an +Elixir supported build under the "Partition Table" setting select the Custom partitions CSV file and +set this to `partitions-elixir.csv`. Extreme caution should be used when changing any non AtomVM +settings. You can quit the program by typing `Q`. Save the changes, and the program will exit. ``` 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 you target a different build directory when running CMake. ``` -Running this script will generate a single `atomvm-.img` file in the `build` directory of the esp32 source tree, where `` 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. +Running this script will generate a single `atomvm-.img` file in the `build` directory +of the esp32 source tree, where `` is the device configured with `set-target`. This +image contains the ESP32 bootloader, AtomVM executable, and the `eavmlib` and `estdlib` Erlang +libraries (and `exavmlib` Elixir libraries if configured for Elixir support) 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-guidemd#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. -To build a thin image with only Erlang libraries `mkimage.sh` script is run from the `src/platform/esp32` directory as follows: +To build a complete image use this command from the `src/platform/esp32` directory as follows: ```shell $ ./build/mkimage.sh @@ -496,18 +506,6 @@ Wrote AtomVM Virtual Machine at offset 0x10000 (65536) Wrote AtomVM Core BEAM Library at offset 0x1D0000 (1114112) ``` -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): - -```shell -$ ./build/mkimage.sh --boot ../../../build/libs/esp32boot/elixir_esp32boot.avm -Writing output to /home/joe/AtomVM/src/platforms/esp32/build/atomvm-esp32.img -============================================= -Wrote bootloader at offset 0x1000 (4096) -Wrote partition-table at offset 0x8000 (32768) -Wrote AtomVM Virtual Machine at offset 0x10000 (65536) -Wrote AtomVM Core BEAM Library at offset 0x1D0000 (1114112) -``` - 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) But first, it is a good idea to erase the flash, e.g., @@ -602,7 +600,7 @@ applications for the AtomVM platform. #### Flashing the core libraries -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: +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: ```shell $ build/flash.sh -l ../../../build/libs/esp32boot.avm @@ -636,6 +634,13 @@ Leaving... Hard resetting via RTS pin... ``` +```{attention} +It is important that you flash the `esp32boot` variant that matches the configuration used to +create the build currently on the device. Flashing `elixir_esp32boot.avm` to a device that was not +flashed with an Elixir support build will not work, AtomVM will still try to load an application +from an address that is now occupied by the `exavmlib` modules. +``` + ### Adding custom Nifs, Ports, and third-party components 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. The instructions for adding custom Nifs and ports differ in slight detail, but are otherwise quite similar. In general, they involve: 1. Adding the custom Nif or Port to the `components` directory of the AtomVM source tree. -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. +1. Run `idf.py set-target ${CHIP}` 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. 1. Building the AtomVM binary. ```{attention} diff --git a/src/platforms/esp32/.gitignore b/src/platforms/esp32/.gitignore new file mode 100644 index 0000000000..ae4535a728 --- /dev/null +++ b/src/platforms/esp32/.gitignore @@ -0,0 +1,7 @@ +# Copyright 2017-2025 Davide Bettio +# Copyright 2025 Winford (UncleGrumpy) +# +# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later + +sdkconfig.defaults +sdkconfig.old diff --git a/src/platforms/esp32/CMakeLists.txt b/src/platforms/esp32/CMakeLists.txt index 9dec6ec5f3..9dbf3bb8b3 100644 --- a/src/platforms/esp32/CMakeLists.txt +++ b/src/platforms/esp32/CMakeLists.txt @@ -54,6 +54,19 @@ set(AVM_SELECT_IN_TASK ON) # JIT is not available yet on esp32 set(AVM_DISABLE_JIT ON) +## Configure partition table based on boot flavor +if (${ATOMVM_ELIXIR_SUPPORT}) + set(AVM_PARTITION_TABLE_FILENAME "partitions-elixir.csv") +else() + set(AVM_PARTITION_TABLE_FILENAME "partitions.csv") +endif() + +if (${ATOMVM_RELEASE}) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.release-defaults.in ${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.defaults @ONLY) +else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.defaults.in ${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig.defaults @ONLY) +endif() + project(atomvm-esp32) # esp-idf does not use compile_feature but instead sets version in diff --git a/src/platforms/esp32/GetBootAVM.cmake b/src/platforms/esp32/GetBootAVM.cmake new file mode 100644 index 0000000000..9dab59dc7d --- /dev/null +++ b/src/platforms/esp32/GetBootAVM.cmake @@ -0,0 +1,29 @@ +# +# This file is part of AtomVM. +# +# Copyright 2025 Winford (Uncle Grumpy) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later +# + +partition_table_get_partition_info(app_offset "--partition-name main.avm" "offset") +set(AVM_APP_OFFSET "${app_offset}") +if ("${app_offset}" STREQUAL "0x210000") + set(BOOT_LIBS "esp32boot.avm") +elseif ("${app_offset}" STREQUAL "0x250000") + set(BOOT_LIBS "elixir_esp32boot.avm") +else() + set(BOOT_LIBS "NONE") +endif() diff --git a/src/platforms/esp32/sdkconfig.defaults b/src/platforms/esp32/sdkconfig.defaults deleted file mode 100644 index ac849e02fc..0000000000 --- a/src/platforms/esp32/sdkconfig.defaults +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y -CONFIG_LWIP_IPV6=n diff --git a/src/platforms/esp32/sdkconfig.defaults.in b/src/platforms/esp32/sdkconfig.defaults.in new file mode 100644 index 0000000000..23d95e33ac --- /dev/null +++ b/src/platforms/esp32/sdkconfig.defaults.in @@ -0,0 +1,6 @@ +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y +CONFIG_LWIP_IPV6=n +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" +CONFIG_PARTITION_TABLE_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" diff --git a/src/platforms/esp32/sdkconfig.defaults.license b/src/platforms/esp32/sdkconfig.defaults.in.license similarity index 100% rename from src/platforms/esp32/sdkconfig.defaults.license rename to src/platforms/esp32/sdkconfig.defaults.in.license diff --git a/src/platforms/esp32/sdkconfig.release-defaults b/src/platforms/esp32/sdkconfig.release-defaults.in similarity index 60% rename from src/platforms/esp32/sdkconfig.release-defaults rename to src/platforms/esp32/sdkconfig.release-defaults.in index e58c9c9cb0..8cefa319cf 100644 --- a/src/platforms/esp32/sdkconfig.release-defaults +++ b/src/platforms/esp32/sdkconfig.release-defaults.in @@ -4,3 +4,5 @@ CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y CONFIG_COMPILER_OPTIMIZATION_PERF=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y CONFIG_LWIP_IPV6=n +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" +CONFIG_PARTITION_TABLE_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" diff --git a/src/platforms/esp32/sdkconfig.release-defaults.license b/src/platforms/esp32/sdkconfig.release-defaults.in.license similarity index 100% rename from src/platforms/esp32/sdkconfig.release-defaults.license rename to src/platforms/esp32/sdkconfig.release-defaults.in.license diff --git a/src/platforms/esp32/tools/CMakeLists.txt b/src/platforms/esp32/tools/CMakeLists.txt index a8c9bd4650..9b7d7a518c 100644 --- a/src/platforms/esp32/tools/CMakeLists.txt +++ b/src/platforms/esp32/tools/CMakeLists.txt @@ -22,6 +22,7 @@ cmake_minimum_required (VERSION 3.13) project (ReleaseEsp32) include(../../../../version.cmake) include(../../../../CMakeModules/GetVersion.cmake) +include(../GetBootAVM.cmake) ## Build image tools for target chip @@ -45,9 +46,20 @@ elseif(${CONFIG_IDF_TARGET} STREQUAL "esp32p4") set(BOOTLOADER_OFFSET "0x2000") endif() +if ("${BOOT_LIBS}" STREQUAL "NONE") + message(WARNING "This appears to be a custom partition map using application offset: ${app_offset}, no AtomVM libraries will be included.") +else() + if (NOT EXISTS ../../../../build/libs/esp32boot/${BOOT_LIBS}) + message(WARNING "A generic_unix build must be done first in the top level AtomVM/build directory! \n\ + Consult https://doc.atomvm.org/main/build-instructions.html for build instructions.") + endif() +endif() + +set(ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mkimage.config.in ${CMAKE_BINARY_DIR}/mkimage.config) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../../../tools/dev/flash.sh ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/flash.sh COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flash.sh.in ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/flash.sh @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mkimage.erl ${CMAKE_BINARY_DIR}/mkimage.erl COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flashimage.sh.in ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/flashimage.sh @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mkimage.sh.in ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/mkimage.sh @ONLY) @@ -64,7 +76,3 @@ file(COPY ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/flash.sh FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) -if (NOT EXISTS ../../../../build/libs/esp32boot/${BOOT_LIBS}) - message(WARNING "A generic_unix build must be done first in the top level AtomVM/build directory! \n\ - Consult https://doc.atomvm.org/main/build-instructions.html for build instructions.") -endif() diff --git a/tools/dev/flash.sh b/src/platforms/esp32/tools/flash.sh.in similarity index 98% rename from tools/dev/flash.sh rename to src/platforms/esp32/tools/flash.sh.in index ff6f7a5656..6879696078 100644 --- a/tools/dev/flash.sh +++ b/src/platforms/esp32/tools/flash.sh.in @@ -23,7 +23,7 @@ set -e : "${FLASH_BAUD_RATE:=115200}" : "${FLASH_SERIAL_PORT:=/dev/ttyUSB0}" -: "${FLASH_OFFSET:=0x210000}" +: "${FLASH_OFFSET:=@AVM_APP_OFFSET@}" ESP_TOOL=`which esptool.py` if [ -z ${ESP_TOOL} ]; then diff --git a/src/platforms/esp32/tools/mkimage.config.in b/src/platforms/esp32/tools/mkimage.config.in index 8856f72a16..bd85d0f5c3 100644 --- a/src/platforms/esp32/tools/mkimage.config.in +++ b/src/platforms/esp32/tools/mkimage.config.in @@ -33,12 +33,12 @@ #{ name => "AtomVM Virtual Machine", offset => "0x10000", - path => ["${BUILD_DIR}/atomvm-esp32.bin", "${ROOT_DIR}/src/platforms/esp32/build/atomvvm-esp32.bin"] + path => ["${BUILD_DIR}/atomvm-esp32.bin", "${ROOT_DIR}/src/platforms/esp32/build/atomvm-esp32.bin"] }, #{ name => "AtomVM Boot and Core BEAM Library", offset => "0x1D0000", - path => ["$[BOOT_FILE]"] + path => ["${ROOT_DIR}/build/libs/esp32boot/${BOOT_LIBS}"] } ] }. diff --git a/src/platforms/esp32/tools/mkimage.erl b/src/platforms/esp32/tools/mkimage.erl index e6518ee5d4..cee805dff3 100644 --- a/src/platforms/esp32/tools/mkimage.erl +++ b/src/platforms/esp32/tools/mkimage.erl @@ -43,7 +43,9 @@ do_main(Argv) -> try Config = load_config(maps:get(config, Opts, "mkimage.config")), BuildDir = get_build_dir(Opts, RootDir), - BootFile = BuildDir ++ "/libs/esp32boot/esp32boot.avm", + BootFile = maps:get( + boot, Opts, BuildDir ++ "/libs/esp32boot/esp32boot.avm" + ), mkimage( RootDir, BuildDir, diff --git a/src/platforms/esp32/tools/mkimage.sh.in b/src/platforms/esp32/tools/mkimage.sh.in index 4a12281d51..98a0a4eb90 100644 --- a/src/platforms/esp32/tools/mkimage.sh.in +++ b/src/platforms/esp32/tools/mkimage.sh.in @@ -23,6 +23,7 @@ escript "@CMAKE_BINARY_DIR@/mkimage.erl" \ --root_dir "@CMAKE_BINARY_DIR@/../../../.." \ --config "@CMAKE_BINARY_DIR@/mkimage.config" \ --out "@CMAKE_BINARY_DIR@/atomvm-@CONFIG_IDF_TARGET@.img" \ + --boot "@CMAKE_BINARY_DIR@/../../../../build/libs/esp32boot/@BOOT_LIBS@" \ "$@" if (test ${@} = "--help"); then @@ -33,5 +34,5 @@ fi echo "=============================================" echo "" -echo "AtomVM @CONFIG_IDF_TARGET@ version @ATOMVM_VERSION@ image written to:" +echo "AtomVM @CONFIG_IDF_TARGET@ version @ATOMVM_VERSION@ image with @BOOT_LIBS@ libraries written to:" echo "@CMAKE_BINARY_DIR@/atomvm-@CONFIG_IDF_TARGET@.img" From c9d8442bc34df18b8d4ccbb01dfb3ea42d627262 Mon Sep 17 00:00:00 2001 From: Winford Date: Mon, 30 Jun 2025 02:37:10 +0000 Subject: [PATCH 5/7] Add esp32boot library to idf.py flash target Adds the esp32boot library flavor (determined from partition table) to the idf.py flash job, allowing developers to simply skip running mkimage.sh and flashimage.sh from the build directory to flash all of the necessary partitions for a complete install to their device. Signed-off-by: Winford --- CHANGELOG.md | 1 + doc/src/build-instructions.md | 50 +++++++++++++------ src/platforms/esp32/CMakeLists.txt | 12 +++++ src/platforms/esp32/GetBootAVM.cmake | 1 - .../esp32/components/libatomvm/CMakeLists.txt | 3 ++ 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5700034f71..de98a5e04b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,7 @@ instead `badarg`. - ESP32 cmake build options are now also exposed in `idf.py menuconfig`. - ESP32 Elixir support is determined automatically from the offset of `boot.avm` in the partiton table. +- ESP32 ports now flash a complete working image using the `idf.py flash` task. ### Fixed diff --git a/doc/src/build-instructions.md b/doc/src/build-instructions.md index 4325fc6af3..bd82541aba 100644 --- a/doc/src/build-instructions.md +++ b/doc/src/build-instructions.md @@ -207,7 +207,10 @@ Tests for the following libraries are supported: Building AtomVM for ESP32 must be done on either a Linux or MacOS build machine. -In order to build a complete AtomVM image for ESP32, you will also need to build AtomVM for the Generic UNIX platform (typically, the same build machine you are suing to build AtomVM for ESP32). +In order to build a complete AtomVM image for ESP32, you will also need to build AtomVM for the Generic UNIX platform (typically, the same build machine you are suing to build AtomVM for ESP32). This is expected to +be done before building an ESP32 port, since the BEAM libraries packed into the esp32boot.avm (or +elixir_esp32boot.avm for Elixir supported builds) are created at the same time as the atomvmlib.avm +libraries as part of the generic UNIX build. ### ESP32 Build Requirements @@ -272,19 +275,34 @@ You can now build AtomVM using the build command: $ idf.py build ``` -This command, once completed, will create the Espressif bootloader, partition table, and AtomVM binary. The last line of the output should read something like the following: +This command, once completed, will create the Espressif bootloader, partition table, and AtomVM binary. The last line of the output should read something like the following example: - Project build complete. To flash, run this command: - ~/.espressif/python_env/idf5.1_py3.11_env/bin/python ~/esp/esp-idf-v5.1/components - /esptool_py/esptool/esptool.py -p (PORT) -b 921600 --before default_reset - --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect - --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 - build/partition_table/partition-table.bin 0x10000 build/atomvm-esp32.bin - or run 'idf.py -p (PORT) flash' +``` +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32 -b 921600 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 4MB --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/atomvm-esp32.bin 0x1d0000 ../../../build/libs/esp32boot/esp32boot.avm +or from the "/home/joe/AtomVM/src/platforms/esp32/build" directory + python -m esptool --chip esp32 -b 921600 --before default_reset --after hard_reset write_flash "@flash_args" +``` -At this point, you can run `idf.py flash` to upload the 3 binaries up to your ESP32 device, and in some development scenarios, this is a preferable shortcut. +```{important} +When using the `@flash_args` method be sure to execute from +/src/platforms/esp32/build. +``` -However, first, we will build a single binary image file containing all of the above 3 binaries, as well as the AtomVM core libraries. See [Building a Release Image](#building-a-release-image), below. But first, it is helpful to understand a bit about how the AtomVM partitioning scheme works, on the ESP32. +At this point, you can run `idf.py flash` and have a complete working image. In some development +scenarios is may be helpful to use `idf.py app-flash` (to only flash a new AtomVM binary to the +`factory` partition) to avoid re-flashing the entire image if no changes were made to the Erlang or +Elixir libraries, and the partition table has not been altered. If you have made changes to the +sdkconfig file (using `idf.py menuconfig` or by other means) it may be necessary to also update the +bootloader using `idf.py bootloader-flash`. As with most other `idf.py` commands these may be +combined (for example: `idf.py bootloader-flash app-flash`). For more information about these +partitions and the flash partitions layout see [Flash Layout](#flash-layout) below. + +To build a single binary image file see [Building a Release Image](#building-a-release-image), below. ### Running tests for ESP32 @@ -417,18 +435,18 @@ The flash layout is roughly as follows (not to scale): | partition table | 3KB | +-----------------+ | | | | - | NVS | 24KB | + | nvs | 24KB | | | | +-----------------+ | | PHY_INIT | 4KB | +-----------------+ | AtomVM | | | binary | | | image - | | | | AtomVM | | - | Virtual | 1.75MB | - | Machine | | + | Virtual | | + | Machine | 1.75MB | | | | + | (factory) | | | | | +-----------------+ | | boot.avm | 256-512KB v @@ -474,7 +492,7 @@ and `boot.avm` partitions. ### Building a Release Image -The `/tools/release/esp32` directory contains the `mkimage.sh` script that can be used to create a single AtomVM image file, which can be distributed as a release, allowing application developers to develop AtomVM applications without having to build AtomVM from scratch. +The `/src/platforms/esp32/build` directory contains the `mkimage.sh` script that can be used to create a single AtomVM image file, which can be distributed as a release, allowing application developers to develop AtomVM applications without having to build AtomVM from scratch. ```{attention} Before running the `mkimage.sh` script, you must have a complete build of both the esp32 project, as well as a full diff --git a/src/platforms/esp32/CMakeLists.txt b/src/platforms/esp32/CMakeLists.txt index 9dbf3bb8b3..c08688af8c 100644 --- a/src/platforms/esp32/CMakeLists.txt +++ b/src/platforms/esp32/CMakeLists.txt @@ -86,3 +86,15 @@ option(AVM_VERBOSE_ABORT "Print module and line number on VM abort" OFF) option(AVM_CREATE_STACKTRACES "Create stacktraces" ON) add_subdirectory(tools) + +include(GetBootAVM.cmake) +message(NOTICE "-- Configuring atomvmlib esp32boot flavor: ${BOOT_LIBS}") +if (NOT ("${BOOT_LIBS}" STREQUAL "NONE")) + set(BOOT_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../build/libs/esp32boot/${BOOT_LIBS}") + if (NOT EXISTS "${BOOT_LIB_PATH}") + message(ERROR "A generic_unix build must be done first in the top level AtomVM/build directory! \n\ + Consult https://doc.atomvm.org/main/build-instructions.html for build instructions.") + endif() + partition_table_get_partition_info(lib_offset "--partition-name boot.avm" "offset") + esptool_py_flash_target_image(flash boot.avm "${lib_offset}" "${BOOT_LIB_PATH}") +endif() diff --git a/src/platforms/esp32/GetBootAVM.cmake b/src/platforms/esp32/GetBootAVM.cmake index 9dab59dc7d..0edd2da6ad 100644 --- a/src/platforms/esp32/GetBootAVM.cmake +++ b/src/platforms/esp32/GetBootAVM.cmake @@ -19,7 +19,6 @@ # partition_table_get_partition_info(app_offset "--partition-name main.avm" "offset") -set(AVM_APP_OFFSET "${app_offset}") if ("${app_offset}" STREQUAL "0x210000") set(BOOT_LIBS "esp32boot.avm") elseif ("${app_offset}" STREQUAL "0x250000") diff --git a/src/platforms/esp32/components/libatomvm/CMakeLists.txt b/src/platforms/esp32/components/libatomvm/CMakeLists.txt index 97580dbfea..4130c5383d 100644 --- a/src/platforms/esp32/components/libatomvm/CMakeLists.txt +++ b/src/platforms/esp32/components/libatomvm/CMakeLists.txt @@ -35,3 +35,6 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE libAtomVM "-u platform_nifs_get_nif" "-u platform_defaultatoms_init") target_compile_features(${COMPONENT_LIB} INTERFACE c_std_11) + +include(../../GetBootAVM.cmake) +partition_table_get_partition_info(boot_offset "--partition-name boot.avm" "offset") From 2f30389290879e8c20d7ed99291caa467702a7fb Mon Sep 17 00:00:00 2001 From: Winford Date: Tue, 22 Jul 2025 00:10:51 -0700 Subject: [PATCH 6/7] Allow provisioning ESP32 nvs partition when building Adds the option to provision nvs partition data at build time for the esp32 platform. If the file `nvs_partition.csv` is found in the AtomVM/src/platforms/esp32 directory when building; the nvs partition will be created and added to the `idf.py flash` task as well as to the configuration for the mkimage.sh script in the build directory. An example file is provided and `nvs_partition.csv` is added to `.gitignore` to prevent accidentally pushing secrets to remote repositories. Signed-off-by: Winford --- CHANGELOG.md | 1 + doc/src/build-instructions.md | 65 +++++++++++++++++++ src/platforms/esp32/.gitignore | 1 + src/platforms/esp32/CMakeLists.txt | 4 ++ src/platforms/esp32/nvs_partition.csv-example | 4 ++ .../esp32/nvs_partition.csv-example.license | 2 + src/platforms/esp32/tools/CMakeLists.txt | 6 +- .../esp32/tools/mkimage_nvs.config.in | 50 ++++++++++++++ 8 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/platforms/esp32/nvs_partition.csv-example create mode 100644 src/platforms/esp32/nvs_partition.csv-example.license create mode 100644 src/platforms/esp32/tools/mkimage_nvs.config.in diff --git a/CHANGELOG.md b/CHANGELOG.md index de98a5e04b..198f04ea6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added gen_server support for timeout tuples in callback return actions introduced in OTP-28. - Added `sys` - Added ESP32 `-DATOMVM_ELIXIR_SUPPORT=on` configuration option +- Added support for ESP32 development builds to include NVS partition data at build time ### Changed diff --git a/doc/src/build-instructions.md b/doc/src/build-instructions.md index bd82541aba..3ff1cbfe77 100644 --- a/doc/src/build-instructions.md +++ b/doc/src/build-instructions.md @@ -304,6 +304,71 @@ partitions and the flash partitions layout see [Flash Layout](#flash-layout) bel To build a single binary image file see [Building a Release Image](#building-a-release-image), below. +#### NVS Partition Provisioning + +For streamlining deployment of images for an environment developers may pre-provision NVS partition +data. This is done by creating a file in the AtomVM/src/platforms/esp32 directory named +`nvs_partition.csv`, an example called `nvs_partition.csv-example` is provided in the same +directory. If this file exists it will be included by the mkimage.sh script in the build directory. +The partition is not included in the `idf.py flash` task so that settings made by applications can +be retained. To update changes or restore to the defaults defined in `nvs_partition.csv` delete the +generated `build/nvs.bin` file (if present) and execute the command `idf.py nvs-flash`. + +This is a more detailed example, with explanations of the structure: + +```{csv} +key,type,encoding,value +network,namespace,, +ssid,data,binary,"NETWORK_NAME" +psk,data,binary,"PASSWORD" +settings,namespace,, +feature0,data,binary,"1" +extra_feature,data,binary,"0" +token,file,binary,/path/to/file +``` + +Let's break this down line by line: + +```csv +key,type,encoding,value +``` +This is the header describing the columns. It is important that there is no whitespace at the end of each line +and none separating the commas (`,`) throughout this file. + +```csv +network,namespace,, +``` +The first entry should have a "key" name and have type "namespace". The namespaces are the same +used to look up the keys with +[esp:nvs_get_binary/2 (or /3)](./apidocs/erlang/eavmlib/esp.md#nvs_get_binary2). Note that the +`encoding` and `value` are empty. + +```csv +ssid,data,binary,"NETWORK_NAME" +... +``` +The keys must use encoding type `binary` as this is the only type currently supported by AtomVM. + +```csv +settings,namespace,, +... +``` +Multiple namespaces may be used for separation, followed by their keys. + +```csv +token,file,binary,/path/to/file +``` +External file contents may be included + +The initial values flashed to the `nvs` partition may be changed by applications using +[esp:nvs_put_binary/3](./apidocs/erlang/eavmlib/esp.md#nvs_put_binary3). If you wish to make +changes to the partition data and re-flash without rebuilding and flashing the entire AtomVM build +you may delete the generated `build/nvs.bin` file and run `idf.py nvs-flash`, this will regenerate +and flash the `nvs` partition. + +For more information about the format of this file see Espressif's +[documentation for the NVS generator file format](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/storage/nvs_partition_gen.html#csv-file-format). + ### Running tests for ESP32 Tests for ESP32 are run on the desktop (or CI) using qemu. diff --git a/src/platforms/esp32/.gitignore b/src/platforms/esp32/.gitignore index ae4535a728..932b2b26ca 100644 --- a/src/platforms/esp32/.gitignore +++ b/src/platforms/esp32/.gitignore @@ -5,3 +5,4 @@ sdkconfig.defaults sdkconfig.old +nvs_partition.csv diff --git a/src/platforms/esp32/CMakeLists.txt b/src/platforms/esp32/CMakeLists.txt index c08688af8c..fbdd9abf70 100644 --- a/src/platforms/esp32/CMakeLists.txt +++ b/src/platforms/esp32/CMakeLists.txt @@ -98,3 +98,7 @@ if (NOT ("${BOOT_LIBS}" STREQUAL "NONE")) partition_table_get_partition_info(lib_offset "--partition-name boot.avm" "offset") esptool_py_flash_target_image(flash boot.avm "${lib_offset}" "${BOOT_LIB_PATH}") endif() + +if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/nvs_partition.csv) + nvs_create_partition_image(nvs ${CMAKE_CURRENT_SOURCE_DIR}/nvs_partition.csv) +endif() diff --git a/src/platforms/esp32/nvs_partition.csv-example b/src/platforms/esp32/nvs_partition.csv-example new file mode 100644 index 0000000000..1b2244d21e --- /dev/null +++ b/src/platforms/esp32/nvs_partition.csv-example @@ -0,0 +1,4 @@ +key,type,encoding,value +network,namespace,, +ssid,data,string,"NETWORK_NAME" +psk,data,string,"PASSWORD" diff --git a/src/platforms/esp32/nvs_partition.csv-example.license b/src/platforms/esp32/nvs_partition.csv-example.license new file mode 100644 index 0000000000..b805ab2cac --- /dev/null +++ b/src/platforms/esp32/nvs_partition.csv-example.license @@ -0,0 +1,2 @@ +SPDX-License-Identifier: Apache-2.0 +SPDX-FileCopyrightText: AtomVM Contributors diff --git a/src/platforms/esp32/tools/CMakeLists.txt b/src/platforms/esp32/tools/CMakeLists.txt index 9b7d7a518c..1aa0d5b817 100644 --- a/src/platforms/esp32/tools/CMakeLists.txt +++ b/src/platforms/esp32/tools/CMakeLists.txt @@ -57,7 +57,11 @@ endif() set(ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../") -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mkimage.config.in ${CMAKE_BINARY_DIR}/mkimage.config) +if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../nvs_partition.csv) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mkimage_nvs.config.in ${CMAKE_BINARY_DIR}/mkimage.config) +else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mkimage.config.in ${CMAKE_BINARY_DIR}/mkimage.config) +endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/flash.sh.in ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/flash.sh @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mkimage.erl ${CMAKE_BINARY_DIR}/mkimage.erl COPYONLY) diff --git a/src/platforms/esp32/tools/mkimage_nvs.config.in b/src/platforms/esp32/tools/mkimage_nvs.config.in new file mode 100644 index 0000000000..00c9c42841 --- /dev/null +++ b/src/platforms/esp32/tools/mkimage_nvs.config.in @@ -0,0 +1,50 @@ +% +% This file is part of AtomVM. +% +% Copyright 2020-2021 Fred Dushin +% Copyright 2025 Winford (UncleGrumpy) +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. +% +% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later +% + +#{ + segments => [ + #{ + name => "bootloader", + offset => "${BOOTLOADER_OFFSET}", + path => ["${BUILD_DIR}/bootloader/bootloader.bin"] + }, + #{ + name => "partition-table", + offset => "0x8000", + path => ["${BUILD_DIR}/partition_table/partition-table.bin", "${BUILD_DIR}/partitions.bin"] + }, + #{ + name => "nvs", + offset => "0x9000", + path => ["${BUILD_DIR}/nvs.bin"] + }, + #{ + name => "AtomVM Virtual Machine", + offset => "0x10000", + path => ["${BUILD_DIR}/atomvm-esp32.bin", "${ROOT_DIR}/src/platforms/esp32/build/atomvm-esp32.bin"] + }, + #{ + name => "AtomVM Boot and Core BEAM Library", + offset => "0x1D0000", + path => ["${ROOT_DIR}/build/libs/esp32boot/${BOOT_LIBS}"] + } + ] +}. From bb855d753886b341eea77671feed4a3f1299688a Mon Sep 17 00:00:00 2001 From: Winford Date: Tue, 12 Aug 2025 15:17:52 +0000 Subject: [PATCH 7/7] Enable reproducible builds for ESP32 platform Use reproducible builds for ESP32 platform so that locally build binaries will be an exact match of release binaries for the same tag. Error message line info will start from the source path, trimming any diectories leading up to it. SHA256 sums of binaries built from release tags should be an exact match of release binaries. Signed-off-by: Winford --- CHANGELOG.md | 1 + doc/src/programmers-guide.md | 18 +++++++++++++++++- src/platforms/esp32/sdkconfig.defaults.in | 2 ++ .../esp32/sdkconfig.release-defaults.in | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 198f04ea6a..4ad064754c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,7 @@ instead `badarg`. - ESP32 Elixir support is determined automatically from the offset of `boot.avm` in the partiton table. - ESP32 ports now flash a complete working image using the `idf.py flash` task. +- ESP32 platform now uses reproducible builds. ### Fixed diff --git a/doc/src/programmers-guide.md b/doc/src/programmers-guide.md index 69932fd3d4..c13d0e7abd 100644 --- a/doc/src/programmers-guide.md +++ b/doc/src/programmers-guide.md @@ -163,6 +163,22 @@ Deployment of the AtomVM virtual machine and an AtomVM application currently req For more information about deploying the AtomVM image and AtomVM applications to your device, see the [Getting Started Guide](./getting-started-guide.md) +```note +The ESP32 platform uses reproducible builds, this has an effect when doing advanced debugging with +GDB because paths are altered to strip away leading paths that are substituted with the following +placeholders: + +* Path to ESP-IDF is replaced with /IDF +* Path to the project is replaced with /IDF_PROJECT +* Path to the build directory is replaced with /IDF_BUILD +* Paths to components are replaced with /COMPONENT_NAME_DIR (where NAME is the name of the +component) + +For information on how to configure GDB for debugging reproducible builds consult the ESP-IDF +documentation about +[Reproducible Builds and Debugging](https://docs.espressif.com/projects/esp-idf/en/v5.5/esp32/api-guides/reproducible-builds.html#reproducible-builds-and-debugging). +``` + ## Applications An AtomVM application is a collection of BEAM files, aggregated into an AtomVM "Packbeam" (`.avm`) file, and typically deployed (flashed) to some device. These BEAM files be be compiled from Erlang, Elixir, or any other language that targets the Erlang VM. @@ -1582,7 +1598,7 @@ The read options take the form of a proplist, if the key `raw` is true (`{raw, t If the key `voltage` is true (or simply appears in the list as an atom), then a calibrated voltage value will be returned in millivolts in the second element of the returned tuple. Otherwise, this element will be the atom `undefined`. -You may specify the number of samples (1 - 100000) to be taken and averaged over using the tuple `{samples, Samples :: 1..100000}`, the default is `64`. +You may specify the number of samples (1 - 100000) to be taken and averaged over using the tuple `{samples, Samples :: 1..100000}`, the default is `64`. ```{warning} Using a large number of samples can significantly increase the amount of time before a response, up to several seconds. diff --git a/src/platforms/esp32/sdkconfig.defaults.in b/src/platforms/esp32/sdkconfig.defaults.in index 23d95e33ac..f9d2091ca4 100644 --- a/src/platforms/esp32/sdkconfig.defaults.in +++ b/src/platforms/esp32/sdkconfig.defaults.in @@ -4,3 +4,5 @@ CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y CONFIG_LWIP_IPV6=n CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" CONFIG_PARTITION_TABLE_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" +CONFIG_APP_REPRODUCIBLE_BUILD=y + diff --git a/src/platforms/esp32/sdkconfig.release-defaults.in b/src/platforms/esp32/sdkconfig.release-defaults.in index 8cefa319cf..186d42b364 100644 --- a/src/platforms/esp32/sdkconfig.release-defaults.in +++ b/src/platforms/esp32/sdkconfig.release-defaults.in @@ -6,3 +6,4 @@ CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y CONFIG_LWIP_IPV6=n CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" CONFIG_PARTITION_TABLE_FILENAME="@AVM_PARTITION_TABLE_FILENAME@" +CONFIG_APP_REPRODUCIBLE_BUILD=y