diff --git a/components/esp_partition/CMakeLists.txt b/components/esp_partition/CMakeLists.txt index be80e77476..c2be459430 100644 --- a/components/esp_partition/CMakeLists.txt +++ b/components/esp_partition/CMakeLists.txt @@ -55,6 +55,21 @@ else() # set BUILD_DIR because partition_linux.c uses a file created in the build directory target_compile_definitions(${COMPONENT_LIB} PRIVATE "BUILD_DIR=\"${build_dir}\"") target_link_libraries(${COMPONENT_LIB} PRIVATE dl) + + # Create the linux_flash_data target that accumulates partition data entries + # registered by esp_partition_register_target(). The target may already exist if + # a project_include.cmake ran before this CMakeLists.txt. + if(NOT TARGET linux_flash_data) + add_custom_target(linux_flash_data) + endif() + + # Generate a manifest file listing all partition data binaries to pre-load + # into the emulated flash. Each line has format: " ". + # Generator expressions are evaluated after all CMakeLists.txt processing completes, + # so all entries accumulated by esp_partition_register_target() will be included. + file(GENERATE + OUTPUT "${build_dir}/linux_flash_data.txt" + CONTENT "$,\n>\n") endif() if(CMAKE_C_COMPILER_ID MATCHES "GNU") diff --git a/components/esp_partition/partition_linux.c b/components/esp_partition/partition_linux.c index 7dd8aab9c9..5e8cffc7b0 100644 --- a/components/esp_partition/partition_linux.c +++ b/components/esp_partition/partition_linux.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -182,6 +182,99 @@ static size_t esp_partition_calc_required_flash_size_from_file(const char *parti return required; } +// Load pre-built partition data binaries into the emulated flash. +// Reads a manifest file (BUILD_DIR "/linux_flash_data.txt") where each line +// has format: " ". +// Each binary is copied into s_spiflash_mem_file_buf at the given offset. +static void esp_partition_load_flash_data(void) +{ + const char *manifest_path = BUILD_DIR "/linux_flash_data.txt"; + FILE *manifest = fopen(manifest_path, "r"); + if (manifest == NULL) { + // No manifest file — nothing to pre-load (this is normal for projects + // that don't use esp_partition_register_target()) + return; + } + + char line[PATH_MAX + 32]; + while (fgets(line, sizeof(line), manifest) != NULL) { + // Skip empty lines + size_t len = strlen(line); + if (len == 0) { + continue; + } + // Trim trailing newline + if (line[len - 1] == '\n') { + line[len - 1] = '\0'; + len--; + } + if (len == 0) { + continue; + } + + // Parse " " + char *space = strchr(line, ' '); + if (space == NULL) { + ESP_LOGW(TAG, "Malformed line in flash data manifest: %s", line); + continue; + } + *space = '\0'; + const char *offset_str = line; + const char *file_path = space + 1; + + unsigned long offset = strtoul(offset_str, NULL, 0); + if (offset == 0 && offset_str[0] != '0') { + ESP_LOGW(TAG, "Invalid offset in flash data manifest: %s", offset_str); + continue; + } + + FILE *data_file = fopen(file_path, "rb"); + if (data_file == NULL) { + ESP_LOGW(TAG, "Failed to open flash data file %s: %s", file_path, strerror(errno)); + continue; + } + + // Get file size + if (fseek(data_file, 0L, SEEK_END) != 0) { + ESP_LOGW(TAG, "Failed to seek in flash data file %s: %s", file_path, strerror(errno)); + fclose(data_file); + continue; + } + long data_size = ftell(data_file); + if (data_size < 0) { + ESP_LOGW(TAG, "Failed to get size of flash data file %s: %s", file_path, strerror(errno)); + fclose(data_file); + continue; + } + if (fseek(data_file, 0L, SEEK_SET) != 0) { + ESP_LOGW(TAG, "Failed to seek in flash data file %s: %s", file_path, strerror(errno)); + fclose(data_file); + continue; + } + + // Verify the data fits within the emulated flash + if (offset + (size_t)data_size > s_esp_partition_file_mmap_ctrl_act.flash_file_size) { + ESP_LOGW(TAG, "Flash data file %s (offset: 0x%lx, size: %ld) exceeds emulated flash size (%" PRIu32 " B). Skipping.", + file_path, offset, data_size, (uint32_t) s_esp_partition_file_mmap_ctrl_act.flash_file_size); + fclose(data_file); + continue; + } + + // Copy the data into the emulated flash at the specified offset + uint8_t *dst = (uint8_t *)s_spiflash_mem_file_buf + offset; + size_t bytes_read = fread(dst, 1, (size_t)data_size, data_file); + fclose(data_file); + + if (bytes_read != (size_t)data_size) { + ESP_LOGW(TAG, "Partial read of flash data file %s: expected %ld bytes, got %zu", file_path, data_size, bytes_read); + } else { + ESP_LOGV(TAG, "Loaded flash data: %s at offset 0x%lx (%ld bytes)", file_path, offset, data_size); + } + } + + fclose(manifest); +} + esp_err_t esp_partition_file_mmap(const uint8_t **part_desc_addr_start) { // temporary file is used only if control structure doesn't specify file name. @@ -345,6 +438,10 @@ esp_err_t esp_partition_file_mmap(const uint8_t **part_desc_addr_start) ret = ESP_ERR_INVALID_STATE; break; } + + // Load any pre-built partition data binaries into the emulated flash. + // The manifest file is generated at build time by esp_partition_register_target(). + esp_partition_load_flash_data(); } while (false); } diff --git a/components/esp_partition/project_include.cmake b/components/esp_partition/project_include.cmake new file mode 100644 index 0000000000..1e06f480ea --- /dev/null +++ b/components/esp_partition/project_include.cmake @@ -0,0 +1,130 @@ +# esp_partition_register_target +# +# @brief Register a binary file to be flashed to a named partition. +# +# Creates a per-partition flash target (e.g., ``idf.py -flash``) and optionally +# includes the binary in ``idf.py flash``. Automatically resolves the partition offset from +# the partition table and determines encryption requirements. +# +# @note On the 'linux' target, this function registers the binary for pre-loading into +# the emulated flash image. The ALWAYS_PLAINTEXT, FLASH_IN_PROJECT, and +# FLASH_IN_PROJECT_DEPENDENCY_TARGETS options are ignored for 'linux'. +# +# @param[in] partition_name Partition name as defined in the partition table +# @param[in] binary_path Path to the binary image file +# @param[in, optional] ALWAYS_PLAINTEXT (option) If specified, the binary is flashed in plain text even +# when flash encryption is enabled. Must not be used with +# partitions marked as 'encrypted' in the partition table. +# @param[in, optional] DEPENDS (multi value) Additional dependencies of the custom target. +# @param[in, optional] FLASH_IN_PROJECT (option) If specified, the binary is flashed in the project +# when running `idf.py flash`. +# @param[in, optional] FLASH_IN_PROJECT_DEPENDENCY_TARGETS (multi value) Additional targets that will be +# dependent on dependencies set in DEPENDS. +# FLASH_IN_PROJECT has to be set. +# +# Example usage (from spiffs_create_partition_image): +# +# # Create a custom target that generates the SPIFFS image file +# add_custom_target(spiffs_${partition}_bin ALL +# COMMAND ${spiffsgen_py} ${size} ${base_dir} ${image_file} +# ...) +# +# # Flash the generated image to the partition. +# # ALWAYS_PLAINTEXT is used because SPIFFS does not support flash encryption. +# # DEPENDS ensures the image is generated before flashing. +# # FLASH_IN_PROJECT includes it in `idf.py flash`. +# esp_partition_register_target(${partition} "${image_file}" +# ALWAYS_PLAINTEXT +# DEPENDS spiffs_${partition}_bin +# FLASH_IN_PROJECT +# ) +# +function(esp_partition_register_target partition_name binary_path) + set(options ALWAYS_PLAINTEXT FLASH_IN_PROJECT) + set(multi DEPENDS FLASH_IN_PROJECT_DEPENDENCY_TARGETS) + cmake_parse_arguments(arg "${options}" "" "${multi}" "${ARGN}") + + # Look up partition offset from the partition table + partition_table_get_partition_info(offset "--partition-name ${partition_name}" "offset") + if(NOT offset) + message(FATAL_ERROR "esp_partition_register_target: " + "Could not find partition '${partition_name}' in the partition table.") + endif() + + idf_build_get_property(idf_target IDF_TARGET) + if(idf_target STREQUAL "linux") + # On linux, register the binary for loading into the emulated flash at startup. + # The partition_linux.c emulation layer reads a manifest file listing each + # (offset, binary_path) pair and copies the data into the memory-mapped flash image. + get_filename_component(binary_abs_path "${binary_path}" ABSOLUTE) + + # Use a global CMake target to accumulate entries via generator expressions. + if(NOT TARGET linux_flash_data) + add_custom_target(linux_flash_data) + endif() + set_property(TARGET linux_flash_data APPEND PROPERTY FLASH_DATA_ENTRIES + "${offset} ${binary_abs_path}") + + # Register build dependency so the binary is generated before the app runs + if(arg_DEPENDS) + add_dependencies(linux_flash_data ${arg_DEPENDS}) + endif() + + return() + endif() + + # Validate: ALWAYS_PLAINTEXT must not be used with a partition marked as encrypted + if(arg_ALWAYS_PLAINTEXT) + partition_table_get_partition_info(pt_encrypted "--partition-name ${partition_name}" "encrypted") + if(pt_encrypted STREQUAL "True") + message(FATAL_ERROR + "esp_partition_register_target: ALWAYS_PLAINTEXT was specified for partition '${partition_name}', " + "but this partition is marked as 'encrypted' in the partition table. " + "These settings are contradictory. Either remove ALWAYS_PLAINTEXT or " + "remove the 'encrypted' flag from the partition table entry.") + endif() + endif() + + # Determine encryption requirements. + # If caller passed ALWAYS_PLAINTEXT, use it. Otherwise, auto-detect from partition table. + if(arg_ALWAYS_PLAINTEXT) + set(flash_plaintext TRUE) + else() + esptool_py_partition_needs_encryption(needs_encryption ${partition_name}) + if(NOT needs_encryption) + set(flash_plaintext TRUE) + else() + set(flash_plaintext FALSE) + endif() + endif() + + # Build the esptool_py_flash_target arg list + set(esptool_py_flash_target_arg_list) + if(flash_plaintext) + list(APPEND esptool_py_flash_target_arg_list ALWAYS_PLAINTEXT) + endif() + + # Create the per-partition flash target (e.g., "mypart-flash") + idf_component_get_property(main_args esptool_py FLASH_ARGS) + idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) + esptool_py_flash_target(${partition_name}-flash "${main_args}" "${sub_args}" ${esptool_py_flash_target_arg_list}) + esptool_py_flash_target_image(${partition_name}-flash ${partition_name} ${offset} + "${binary_path}" ${esptool_py_flash_target_arg_list}) + + if(arg_DEPENDS) + add_dependencies(${partition_name}-flash ${arg_DEPENDS}) + endif() + + # Add to the main "flash" target if FLASH_IN_PROJECT is set + if(arg_FLASH_IN_PROJECT) + esptool_py_flash_target_image(flash ${partition_name} ${offset} + "${binary_path}" ${esptool_py_flash_target_arg_list}) + + if(arg_DEPENDS) + add_dependencies(flash ${arg_DEPENDS}) + foreach(target ${arg_FLASH_IN_PROJECT_DEPENDENCY_TARGETS}) + add_dependencies(${target} ${arg_DEPENDS}) + endforeach() + endif() + endif() +endfunction() diff --git a/components/fatfs/project_include.cmake b/components/fatfs/project_include.cmake index aa0edf2a81..9b98033e55 100644 --- a/components/fatfs/project_include.cmake +++ b/components/fatfs/project_include.cmake @@ -67,18 +67,13 @@ function(fatfs_create_partition_image partition base_dir) ADDITIONAL_CLEAN_FILES ${image_file}) - idf_component_get_property(main_args esptool_py FLASH_ARGS) - idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) - # Last (optional) parameter is the encryption for the target. In our - # case, fatfs is not encrypt so pass FALSE to the function. - esptool_py_flash_target(${partition}-flash "${main_args}" "${sub_args}" ALWAYS_PLAINTEXT) - esptool_py_flash_to_partition(${partition}-flash "${partition}" "${image_file}") + set(esp_partition_register_target_optional_args DEPENDS fatfs_${partition}_bin) - add_dependencies(${partition}-flash fatfs_${partition}_bin) if(arg_FLASH_IN_PROJECT) - esptool_py_flash_to_partition(flash "${partition}" "${image_file}") - add_dependencies(flash fatfs_${partition}_bin) + list(APPEND esp_partition_register_target_optional_args FLASH_IN_PROJECT) endif() + + esp_partition_register_target(${partition} "${image_file}" ${esp_partition_register_target_optional_args}) else() set(message "Failed to create FATFS image for partition '${partition}'. " "Check project configuration if using the correct partition table file.") diff --git a/components/nvs_flash/project_include.cmake b/components/nvs_flash/project_include.cmake index 5503753c54..7a2c9c5093 100644 --- a/components/nvs_flash/project_include.cmake +++ b/components/nvs_flash/project_include.cmake @@ -43,20 +43,16 @@ function(nvs_create_partition_image partition csv) PROPERTY ADDITIONAL_CLEAN_FILES ${image_file} ) - idf_component_get_property(main_args esptool_py FLASH_ARGS) - idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) - esptool_py_flash_target(${partition}-flash "${main_args}" "${sub_args}" ALWAYS_PLAINTEXT) - esptool_py_flash_to_partition(${partition}-flash "${partition}" "${image_file}") - - add_dependencies(${partition}-flash nvs_${partition}_bin) + set(register_target_optional_args ALWAYS_PLAINTEXT DEPENDS nvs_${partition}_bin) if(arg_FLASH_IN_PROJECT) - esptool_py_flash_to_partition(flash "${partition}" "${image_file}") - add_dependencies(flash nvs_${partition}_bin) + list(APPEND register_target_optional_args FLASH_IN_PROJECT) if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) - add_dependencies(encrypted-flash nvs_${partition}_bin) + list(APPEND register_target_optional_args FLASH_IN_PROJECT_DEPENDENCY_TARGETS encrypted-flash) endif() endif() + + esp_partition_register_target(${partition} "${image_file}" ${register_target_optional_args}) else() set(message "Failed to create NVS image for partition '${partition}'. " diff --git a/components/spiffs/project_include.cmake b/components/spiffs/project_include.cmake index c322a64b06..0e14a81179 100644 --- a/components/spiffs/project_include.cmake +++ b/components/spiffs/project_include.cmake @@ -47,19 +47,15 @@ function(spiffs_create_partition_image partition base_dir) ADDITIONAL_CLEAN_FILES ${image_file}) - idf_component_get_property(main_args esptool_py FLASH_ARGS) - idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) - # Last (optional) parameter is the encryption for the target. In our - # case, spiffs is not encrypt so pass FALSE to the function. - esptool_py_flash_target(${partition}-flash "${main_args}" "${sub_args}" ALWAYS_PLAINTEXT) - esptool_py_flash_to_partition(${partition}-flash "${partition}" "${image_file}") - - add_dependencies(${partition}-flash spiffs_${partition}_bin) + # Encryption for SPIFFS is not supported, so optional parameter ALWAYS_PLAINTEXT is passed to the function. + set(esp_partition_register_target_optional_args) + list(APPEND esp_partition_register_target_optional_args ALWAYS_PLAINTEXT DEPENDS spiffs_${partition}_bin) if(arg_FLASH_IN_PROJECT) - esptool_py_flash_to_partition(flash "${partition}" "${image_file}") - add_dependencies(flash spiffs_${partition}_bin) + list(APPEND esp_partition_register_target_optional_args FLASH_IN_PROJECT) endif() + + esp_partition_register_target(${partition} "${image_file}" ${esp_partition_register_target_optional_args}) else() set(message "Failed to create SPIFFS image for partition '${partition}'. " "Check project configuration if using the correct partition table file.") diff --git a/docs/en/api-reference/storage/partition.rst b/docs/en/api-reference/storage/partition.rst index 9a38235e86..443fcf5d79 100644 --- a/docs/en/api-reference/storage/partition.rst +++ b/docs/en/api-reference/storage/partition.rst @@ -35,6 +35,39 @@ Application Examples - :example:`storage/partition_api/partition_mmap` demonstrates how to configure the MMU, map a partition into memory address space for read operations, and verify the data written and read. +Flashing Binaries to Partitions +------------------------------- + +The ``esp_partition_register_target`` function allows registering binary files to be flashed to specific partitions. It creates a per-partition flash target (e.g., ``idf.py mypart-flash``, where ``mypart`` is the name of the partition in ``partitions.csv``) and optionally includes the binary in ``idf.py flash``. + +This function is defined in :component_file:`esp_partition/project_include.cmake`. + +**Basic usage in a project's CMakeLists.txt:** + +.. code-block:: cmake + + esp_partition_register_target(my_partition "${CMAKE_BINARY_DIR}/my_data.bin" FLASH_IN_PROJECT) + +This creates a ``my_partition-flash`` target and includes the binary when running ``idf.py flash``. + +**Arguments:** + +- ``partition_name`` — Name of the partition as defined in the partition table. +- ``binary_path`` — Path to the binary file to flash. +- ``FLASH_IN_PROJECT`` (optional) — Also flash this binary when running ``idf.py flash``. +- ``ALWAYS_PLAINTEXT`` (optional) — Flash without encryption even when flash encryption is enabled. Use for filesystems that don't support encryption (e.g., SPIFFS). Must not be used with partitions marked as ``encrypted`` in the partition table. +- ``DEPENDS `` (optional) — CMake targets that must be built before flashing (e.g., a custom target that generates the binary). +- ``FLASH_IN_PROJECT_DEPENDENCY_TARGETS `` (optional) — Additional flash targets (e.g., ``encrypted-flash``) that should also depend on the targets specified in ``DEPENDS``. Requires ``FLASH_IN_PROJECT``. + +**Component integration examples:** + +Several IDF components use ``esp_partition_register_target`` internally: + +- :example:`storage/partition_api/partition_ops` uses it to flash a custom partition with predefined content. +- :component_file:`fatfs/project_include.cmake` — ``fatfs_create_spiflash_image`` creates a FATFS image and registers a ``-flash`` target. +- :component_file:`nvs_flash/project_include.cmake` — ``nvs_create_partition_image`` creates an NVS image and registers a ``-flash`` target. +- :component_file:`spiffs/project_include.cmake` — ``spiffs_create_partition_image`` creates a SPIFFS image and registers a ``-flash`` target. + See Also -------- diff --git a/examples/storage/nvs/nvs_bootloader/main/CMakeLists.txt b/examples/storage/nvs/nvs_bootloader/main/CMakeLists.txt index 47e59caa22..62390cd5cc 100644 --- a/examples/storage/nvs/nvs_bootloader/main/CMakeLists.txt +++ b/examples/storage/nvs/nvs_bootloader/main/CMakeLists.txt @@ -5,9 +5,9 @@ if(NOT CONFIG_NVS_ENCRYPTION) nvs_create_partition_image(nvs ../nvs_data.csv FLASH_IN_PROJECT) else() if(CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC) - esptool_py_flash_to_partition(flash "nvs_key" ${PROJECT_DIR}/main/encryption_keys.bin) - esptool_py_flash_to_partition(flash "nvs" ${PROJECT_DIR}/main/nvs_encrypted.bin) + esp_partition_register_target("nvs_key" ${PROJECT_DIR}/main/encryption_keys.bin FLASH_IN_PROJECT) + esp_partition_register_target("nvs" ${PROJECT_DIR}/main/nvs_encrypted.bin FLASH_IN_PROJECT) else() # NVS Encryption using HMAC (CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC) - esptool_py_flash_to_partition(flash "nvs" ${PROJECT_DIR}/main/nvs_encrypted_hmac.bin) + esp_partition_register_target("nvs" ${PROJECT_DIR}/main/nvs_encrypted_hmac.bin FLASH_IN_PROJECT) endif() endif() diff --git a/examples/storage/partition_api/partition_ops/README.md b/examples/storage/partition_api/partition_ops/README.md index d569671316..3a89aa48dc 100644 --- a/examples/storage/partition_api/partition_ops/README.md +++ b/examples/storage/partition_api/partition_ops/README.md @@ -18,7 +18,8 @@ and read back using `esp_partition_read`, verifying the read and written data ma I (588) example: Written data: ESP-IDF Partition Operations Example (Read, Erase, Write) I (588) example: Read data: ESP-IDF Partition Operations Example (Read, Erase, Write) I (638) example: Erased data -I (638) example: Example end +I (693) example: Read data from custom partition: abcdef123456 +I (693) example: Example end ``` # Others diff --git a/examples/storage/partition_api/partition_ops/create_custom_partition.py b/examples/storage/partition_api/partition_ops/create_custom_partition.py new file mode 100644 index 0000000000..3878ddfb63 --- /dev/null +++ b/examples/storage/partition_api/partition_ops/create_custom_partition.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +"""Create a 4kiB binary file with 'abcdef123456' at the start, rest filled with zeros.""" + +import argparse +import os + +FILE_NAME = 'custom_partition.bin' +FILE_SIZE = 4 * 1024 # 4 kiB +HEADER = b'abcdef123456' + + +def main() -> None: + parser = argparse.ArgumentParser(description='Generate a custom partition binary file.') + parser.add_argument( + 'output_path', + nargs='?', + default=None, + help='Path for the output binary file. Defaults to custom_partition.bin in the script directory.', + ) + args = parser.parse_args() + + if args.output_path: + output_path = args.output_path + else: + script_dir = os.path.dirname(os.path.abspath(__file__)) + output_path = os.path.join(script_dir, FILE_NAME) + + data = HEADER + b'\x00' * (FILE_SIZE - len(HEADER)) + + with open(output_path, 'wb') as f: + f.write(data) + + print(f'Created {output_path} ({FILE_SIZE} bytes)') + + +if __name__ == '__main__': + main() diff --git a/examples/storage/partition_api/partition_ops/main/CMakeLists.txt b/examples/storage/partition_api/partition_ops/main/CMakeLists.txt index 1e6ff73720..c5ad567c3e 100644 --- a/examples/storage/partition_api/partition_ops/main/CMakeLists.txt +++ b/examples/storage/partition_api/partition_ops/main/CMakeLists.txt @@ -1,3 +1,21 @@ idf_component_register(SRCS "main.c" INCLUDE_DIRS "." REQUIRES esp_partition) + +set(partition "custom_partition") +set(image_file ${CMAKE_BINARY_DIR}/custom_partition.bin) +set(custom_partition_script_py ${CMAKE_CURRENT_SOURCE_DIR}/../create_custom_partition.py) + +# Generate custom_partition.bin using the Python script (output to build directory) +add_custom_command( + OUTPUT ${image_file} + COMMAND ${PYTHON} ${custom_partition_script_py} ${image_file} + DEPENDS ${custom_partition_script_py} + COMMENT "Generating custom_partition.bin" +) +add_custom_target(generate_custom_partition ALL DEPENDS ${image_file}) + +# Flash the generated binary to the partition named "custom_partition" +# (build target depends on generate_custom_partition to ensure the binary is created first, and FLASH_IN_PROJECT +# makes it get flashed when calling `idf.py custom_partition-flash` or just `idf.py flash`) +esp_partition_register_target(${partition} "${image_file}" DEPENDS generate_custom_partition FLASH_IN_PROJECT) diff --git a/examples/storage/partition_api/partition_ops/main/main.c b/examples/storage/partition_api/partition_ops/main/main.c index 6521dbf1bd..5ca4d0ed9f 100644 --- a/examples/storage/partition_api/partition_ops/main/main.c +++ b/examples/storage/partition_api/partition_ops/main/main.c @@ -54,5 +54,15 @@ void app_main(void) ESP_LOGI(TAG, "Erased data"); + // Find the custom partition in the partition table + partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "custom_partition"); + assert(partition != NULL); + + memset(read_data, 0, sizeof(read_data)); + // Read the data and check if it matches the expected content (first 12 bytes should be "abcdef123456", rest should be 0x00's) + ESP_ERROR_CHECK(esp_partition_read(partition, 0, read_data, sizeof(read_data))); + assert(memcmp("abcdef123456", read_data, 12) == 0); + ESP_LOGI(TAG, "Read data from custom partition: %s", read_data); + ESP_LOGI(TAG, "Example end"); } diff --git a/examples/storage/partition_api/partition_ops/partitions_example.csv b/examples/storage/partition_api/partition_ops/partitions_example.csv index a70efe6a75..005e851bcd 100644 --- a/examples/storage/partition_api/partition_ops/partitions_example.csv +++ b/examples/storage/partition_api/partition_ops/partitions_example.csv @@ -3,4 +3,5 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, -storage, data, , , 0x40000, +storage, data, , , 0x3F000, +custom_partition, data, , , 0x1000, diff --git a/tools/test_apps/build_system/custom_partition_subtypes/CMakeLists.txt b/tools/test_apps/build_system/custom_partition_subtypes/CMakeLists.txt index 238ddb5428..4ea880ec96 100644 --- a/tools/test_apps/build_system/custom_partition_subtypes/CMakeLists.txt +++ b/tools/test_apps/build_system/custom_partition_subtypes/CMakeLists.txt @@ -25,6 +25,7 @@ add_custom_target(blank_bin ALL DEPENDS ${blank_file}) idf_build_get_property(target IDF_TARGET) if(NOT ${target} STREQUAL "linux") - add_dependencies(flash blank_bin) - esptool_py_flash_to_partition(flash "${partition}" "${blank_file}") + esp_partition_register_target("${partition}" "${blank_file}" + DEPENDS blank_bin + FLASH_IN_PROJECT) endif()