From b219bfa54104985ae0fb87babf1f28891e7bdea3 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 23a09a04c..fbd97628e 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 - Entry point now is `init:boot/1` if it exists. It starts the kernel application and calls `start/0` from the identified startup module. Users who started kernel application (typically for distribution) must no longer do it. Startint `net_kernel` is still required. +- 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 88bf92aa1..2992d0a28 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 9ea8bc03751e6b049255d5838edaf6688d6c975c 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 4ec7fe95a..971b8d0e4 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 8bc657d38..a8c9bd465 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 43e20838cbfd8960469ff61c8c107bf3d7669c5d 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 2cfa9598d..4a12281d5 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 bf09e388182a3d600a516f1817a582cfc77850c0 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 52eeb55ac..3b13572e2 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 fbd97628e..464c2a6de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `supervisor:which_children/1` - Added `monitored_by` in `process_info/2` - Added mock implementation for `current_stacktrace` in `process_info` +- Added ESP32 `-DATOMVM_ELIXIR_SUPPORT=on` configuration option ### Changed @@ -66,6 +67,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 identified startup module. Users who started kernel application (typically for distribution) must no longer do it. Startint `net_kernel` is still required. - 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 23803b7ab..b716014db 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -13,6 +13,17 @@ port socket driver, are also represented by a port and some matching code may ne `is_pid/1` to `is_port/1`. - Ports and pids can be registered. Function `globalcontext_get_registered_process` result now is a term that can be a `port()` or a `pid()`. +- 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 4d8b4458f..dcbe63a04 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 000000000..ae4535a72 --- /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 2683670dd..7ee15fa63 100644 --- a/src/platforms/esp32/CMakeLists.txt +++ b/src/platforms/esp32/CMakeLists.txt @@ -51,6 +51,19 @@ endif() # On Esp32, select is run in a loop in a dedicated task set(AVM_SELECT_IN_TASK 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 000000000..9dab59dc7 --- /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 ac849e02f..000000000 --- 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 000000000..23d95e33a --- /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 e58c9c9cb..8cefa319c 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 a8c9bd465..9b7d7a518 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 ff6f7a565..687969607 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 8856f72a1..bd85d0f5c 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 e6518ee5d..cee805dff 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 4a12281d5..98a0a4eb9 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 6c2f7e804a549aab490e087cd8e25fe12e8014fa 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 464c2a6de..2db9a1340 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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 dcbe63a04..529dfdf71 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 bootlader-flash`. As with most other `idf.py` commands these may be +combined (for example: `idf.py bootlader-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 7ee15fa63..48fc8d72a 100644 --- a/src/platforms/esp32/CMakeLists.txt +++ b/src/platforms/esp32/CMakeLists.txt @@ -83,3 +83,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 9dab59dc7..0edd2da6a 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 97580dbfe..4130c5383 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 34d5a643db55f50cf294376d085682994031020d 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 2db9a1340..45ab76538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `monitored_by` in `process_info/2` - Added mock implementation for `current_stacktrace` in `process_info` - 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 529dfdf71..4b7f71bb9 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 ae4535a72..932b2b26c 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 48fc8d72a..4bc042b49 100644 --- a/src/platforms/esp32/CMakeLists.txt +++ b/src/platforms/esp32/CMakeLists.txt @@ -95,3 +95,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 000000000..1b2244d21 --- /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 000000000..b805ab2ca --- /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 9b7d7a518..1aa0d5b81 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 000000000..00c9c4284 --- /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 3abb4c3f8476aec10ea262d1502401518ba66542 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 45ab76538..a97f64bcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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 reproducable builds. ### Fixed diff --git a/doc/src/programmers-guide.md b/doc/src/programmers-guide.md index 481fa1c0f..451245fe2 100644 --- a/doc/src/programmers-guide.md +++ b/doc/src/programmers-guide.md @@ -171,6 +171,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. @@ -1590,7 +1606,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 23d95e33a..f9d2091ca 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 8cefa319c..186d42b36 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