mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 11:03:11 +00:00
Merge branch 'feat/cmake_add_partition_flash_binary_function' into 'master'
feat(esp_partition): Add esp_partition_register_target Cmake function Closes IDF-11870 and DOC-14244 See merge request espressif/esp-idf!37176
This commit is contained in:
@@ -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: "<hex_offset> <absolute_path>".
|
||||
# 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 "$<JOIN:$<TARGET_PROPERTY:linux_flash_data,FLASH_DATA_ENTRIES>,\n>\n")
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
|
||||
@@ -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: "<hex_offset> <absolute_path_to_binary>".
|
||||
// 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 "<hex_offset> <path>"
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <partition>-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()
|
||||
@@ -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.")
|
||||
|
||||
@@ -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}'. "
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -6,7 +6,7 @@ Partitions API
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ``esp_partition`` component has higher-level API functions which work with partitions defined in the :doc:`/api-guides/partition-tables`. These APIs are based on lower level API provided by :doc:`/api-reference/peripherals/spi_flash/index`.
|
||||
The ``esp_partition`` component has higher-level API functions which work with partitions defined in the :doc:`/api-guides/partition-tables`. These APIs are based on lower-level API provided by :doc:`/api-reference/peripherals/spi_flash/index`.
|
||||
|
||||
.. _flash-partition-apis:
|
||||
|
||||
@@ -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 <targets>`` (optional) — CMake targets that must be built before flashing (e.g., a custom target that generates the binary).
|
||||
- ``FLASH_IN_PROJECT_DEPENDENCY_TARGETS <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 ``<partition>-flash`` target.
|
||||
- :component_file:`nvs_flash/project_include.cmake` — ``nvs_create_partition_image`` creates an NVS image and registers a ``<partition>-flash`` target.
|
||||
- :component_file:`spiffs/project_include.cmake` — ``spiffs_create_partition_image`` creates a SPIFFS image and registers a ``<partition>-flash`` target.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
|
||||
@@ -35,12 +35,45 @@ ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导加载
|
||||
|
||||
- :example:`storage/partition_api/partition_mmap` 演示了如何配置 MMU,将分区映射到内存地址空间以进行读操作,并验证写入和读取的数据。
|
||||
|
||||
将二进制文件烧录到分区
|
||||
-------------------------------
|
||||
|
||||
``esp_partition_register_target`` 函数允许将二进制文件注册到特定分区进行烧录。它会创建一个按分区划分的烧录目标(例如,``idf.py mypart-flash``,其中 ``mypart`` 是 ``partitions.csv`` 中分区的名称),并可选择将该二进制文件包含在 ``idf.py flash`` 中。
|
||||
|
||||
该函数在 :component_file:`esp_partition/project_include.cmake` 中定义。
|
||||
|
||||
**在项目的 CMakeLists.txt 中的基本用法:**
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
esp_partition_register_target(my_partition "${CMAKE_BINARY_DIR}/my_data.bin" FLASH_IN_PROJECT)
|
||||
|
||||
这会创建一个 ``my_partition-flash`` 目标,并在运行 ``idf.py flash`` 时包含该二进制文件。
|
||||
|
||||
**参数:**
|
||||
|
||||
- ``partition_name`` — 在分区表中定义的分区名称。
|
||||
- ``binary_path`` — 要烧录的二进制文件路径。
|
||||
- ``FLASH_IN_PROJECT`` (可选) — 在运行 ``idf.py flash`` 时也会烧录此二进制文件。
|
||||
- ``ALWAYS_PLAINTEXT`` (可选) — 即使启用了 flash 加密,仍以非加密方式烧录。用于不支持加密的文件系统(例如 SPIFFS)。不得与分区表中标记为 ``encrypted`` 的分区一起使用。
|
||||
- ``DEPENDS <targets>`` (可选) — 在烧录之前必须构建的 CMake 目标(例如,生成二进制文件的自定义目标)。
|
||||
- ``FLASH_IN_PROJECT_DEPENDENCY_TARGETS <targets>`` (可选) — 额外的烧录目标(例如 ``encrypted-flash``),这些目标也应依赖于 ``DEPENDS`` 中指定的目标。需要 ``FLASH_IN_PROJECT``。
|
||||
|
||||
**组件集成示例:**
|
||||
|
||||
某些 IDF 组件在内部使用了 ``esp_partition_register_target``:
|
||||
|
||||
- 使用 :example:`storage/partition_api/partition_ops` 烧录带有预定义内容的自定义分区。
|
||||
- :component_file:`fatfs/project_include.cmake` — ``fatfs_create_spiflash_image`` 会创建一个 FATFS 镜像并注册 ``<partition>-flash`` 目标。
|
||||
- :component_file:`nvs_flash/project_include.cmake` — ``nvs_create_partition_image`` 会创建 NVS 镜像,并注册 ``<partition>-flash`` 目标。
|
||||
- :component_file:`spiffs/project_include.cmake` — ``spiffs_create_partition_image`` 会创建 SPIFFS 镜像并注册 ``<partition>-flash`` 目标。
|
||||
|
||||
其他资源
|
||||
-------------
|
||||
|
||||
- :doc:`../../api-guides/partition-tables`
|
||||
- :doc:`../system/ota` 提供了高层 API 用于更新存储在 flash 中的 app 固件。
|
||||
- :doc:`nvs_flash` 提供了结构化 API 用于存储 SPI flash 中的碎片数据。
|
||||
- :doc:`../system/ota` 提供了高层 API,用于更新存储在 flash 中的应用程序。
|
||||
- :doc:`nvs_flash` 提供了结构化 API,用于在 SPI flash 中存储小块数据。
|
||||
|
||||
|
||||
.. _api-reference-partition-table:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user