Files
esp-idf/docs/zh_CN/api-reference/system/app_image_format.rst
2025-09-30 15:28:55 +02:00

157 lines
7.6 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
应用程序镜像格式
================
:link_to_translation:`en:[English]`
.. _app-image-structures:
应用程序镜像结构
----------------------------
应用程序镜像包含以下内容:
1. :cpp:type:`esp_image_header_t` 结构体描述了 SPI flash 的模式和内存段的数量。
2. :cpp:type:`esp_image_segment_header_t` 结构体描述了每个段、每个段的长度及其在 {IDF_TARGET_NAME} 内存中的位置,此描述后接长度为 ``data_len`` 的数据。镜像中每个段的数据偏移量的计算方式如下:
* 0 段的偏移量 = sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`)
* 1 段的偏移量 = 0 段的偏移量 + 0 段长度 + sizeof(:cpp:type:`esp_image_segment_header_t`)
* 2 段的偏移量 = 1 段的偏移量 + 1 段长度 + sizeof(:cpp:type:`esp_image_segment_header_t`)
* ...
``segment_count`` 字段定义了每个段的数量,存储在 :cpp:type:`esp_image_header_t` 中。各段段数量不能超过 :c:macro:`ESP_IMAGE_MAX_SEGMENTS`
运行以下命令,获取镜像段列表:
.. code-block::
esptool --chip {IDF_TARGET_PATH_NAME} image-info build/app.bin
.. code-block::
esptool v5.0.2
Image size: 137312 bytes
ESP32 Image Header
==================
Image version: 1
Entry point: 0x40081214
Segments: 6
Flash size: 2MB
Flash freq: 40m
Flash mode: DIO
ESP32 Extended Image Header
===========================
WP pin: 0xee (disabled)
Flash pins drive settings: clk_drv: 0x0, q_drv: 0x0, d_drv: 0x0, cs0_drv: 0x0, hd_drv: 0x0, wp_drv: 0x0
Chip ID: 0 (ESP32)
Minimal chip revision: v0.0, (legacy min_rev = 0)
Maximal chip revision: v3.99
Segments Information
====================
Segment Length Load addr File offs Memory types
------- ------- ---------- ---------- ------------
0 0x0711c 0x3f400020 0x00000018 DROM
1 0x0241c 0x3ffb0000 0x0000713c BYTE_ACCESSIBLE, DRAM
2 0x06ab0 0x40080000 0x00009560 IRAM
3 0x0b724 0x400d0020 0x00010018 IROM
4 0x060c0 0x40086ab0 0x0001b744 IRAM
5 0x00024 0x50000000 0x0002180c RTC_DATA
ESP32 Image Footer
==================
Checksum: 0x4b (valid)
Validation hash: 8808f05a62fe1a6e1e6830414b95229454b012eb2001511ca434d34e9e63c962 (valid)
Application Information
=======================
Project name: hello_world
App version: qa-test-esp32c61-master-2025070
Compile time: Aug 12 2025 16:36:40
ELF file SHA256: 10972f521b52276e988631d7408de388d639437118e8217c366f2bd93b52e1b6
ESP-IDF: v6.0-dev-1692-g7aad0d47e66-dirt
Minimal eFuse block revision: 0.0
Maximal eFuse block revision: 0.99
MMU page size: 64 KB
Secure version: 0
应用程序启动时ESP-IDF 日志中也会包含段的相关信息:
.. code-block::
I (443) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x13ce0 ( 81120) map
I (489) esp_image: segment 1: paddr=0x00033d08 vaddr=0x3ff80000 size=0x00000 ( 0) load
I (530) esp_image: segment 2: paddr=0x00033d10 vaddr=0x3ff80000 size=0x00000 ( 0) load
I (571) esp_image: segment 3: paddr=0x00033d18 vaddr=0x3ffb0000 size=0x028e0 ( 10464) load
I (612) esp_image: segment 4: paddr=0x00036600 vaddr=0x3ffb28e0 size=0x00000 ( 0) load
I (654) esp_image: segment 5: paddr=0x00036608 vaddr=0x40080000 size=0x00400 ( 1024) load
I (695) esp_image: segment 6: paddr=0x00036a10 vaddr=0x40080400 size=0x09600 ( 38400) load
I (737) esp_image: segment 7: paddr=0x00040018 vaddr=0x400d0018 size=0x62e4c (405068) map
I (847) esp_image: segment 8: paddr=0x000a2e6c vaddr=0x40089a00 size=0x06cec ( 27884) load
I (888) esp_image: segment 9: paddr=0x000a9b60 vaddr=0x400c0000 size=0x00000 ( 0) load
I (929) esp_image: segment 10: paddr=0x000a9b68 vaddr=0x50000000 size=0x00004 ( 4) load
I (971) esp_image: segment 11: paddr=0x000a9b74 vaddr=0x50000004 size=0x00000 ( 0) load
I (1012) esp_image: segment 12: paddr=0x000a9b7c vaddr=0x50000004 size=0x00000 ( 0) load
.. only:: esp32
有关内存段类型和地址范围的更多详细信息,请参阅 **{IDF_TARGET_NAME} 技术参考手册** > **系统和存储器** > **片上存储器** [`PDF <{IDF_TARGET_TRM_CN_URL}#sysmem>`__]。
.. only:: not esp32
有关内存段类型和地址范围的详细信息,请参阅 **{IDF_TARGET_NAME} 技术参考手册** > **系统和存储器** > **内部存储器** [`PDF <{IDF_TARGET_TRM_CN_URL}#sysmem>`__]。
3. 镜像有一个校验和字节,位于最后一个段之后。此字节写在一个十六字节填充边界上,因此应用程序镜像可能需要填充。
4. 如果在 :cpp:type:`esp_image_header_t` 中设置了 ``hash_appended`` 字段,则会附加 SHA256 校验和字段。SHA256 哈希值的计算范围是从第一个字节开始,到这个字段为止。该字段长度为 32 字节。
5. 如果选项 :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` 设置为 ECDSA那么应用程序镜像将有额外的 68 字节用于 ECDSA 签名,其中包括:
* 版本号4 字节)
* 签名数据64 字节)
6. 如果选项 :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` 设置为 RSA 或 ECDSA (V2),则应用程序镜像将有一个额外的签名扇区,大小为 4K 字节。关于此签名扇区格式的更多内容,请参考 :ref:`signature-block-format`
.. _app-image-format-application-description:
应用程序描述
-----------------------
应用程序二进制文件的 ``DROM`` 段从 :cpp:type:`esp_app_desc_t` 结构体开始,该结构体中包含了用于描述应用程序的特定字段,如下所示:
* ``magic_word``:cpp:type:`esp_app_desc_t` 结构体的魔术词
* ``secure_version``:参见 :doc:`防回滚 </api-reference/system/ota>`
* ``version``:参见 :doc:`应用程序版本 </api-reference/system/misc_system_api>` [#f1]_
* ``project_name``:通过 ``PROJECT_NAME`` 填充 [#f1]_
* ``time````date``:编译时间和日期
* ``idf_ver``ESP-IDF 的版本 [#f1]_
* ``app_elf_sha256``:包含应用程序 ELF 文件的 sha256 哈希
.. [#f1] 最大长度为 32 个字符,其中包括 null 终止符。也就是说,如果 ``PROJECT_NAME`` 的长度超过 31 个字符,超出的字符将被忽略。
这个结构体有助于识别通过空中升级 (OTA) 上传的镜像,因为其中包含一个固定的偏移量,大小为 sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`)。一旦设备接收到包含此结构体的第一个段,就能根据其中的充分信息来确定是否应继续更新。
要获取当前运行的应用程序的 :cpp:type:`esp_app_desc_t` 结构体,请调用 :cpp:func:`esp_app_get_description`
要获取另一个 OTA 分区的 :cpp:type:`esp_app_desc_t` 结构体,请调用 :cpp:func:`esp_ota_get_partition_description`
向应用程序添加自定义结构体
-------------------------------------------
也可以自定义类似的结构体,并使其相对于镜像起始位置有一个固定的偏移量。
采用以下方式向镜像添加自定义结构体:
.. code-block:: c
const __attribute__((section(".rodata_custom_desc"))) esp_custom_app_desc_t custom_app_desc = { ... }
自定义结构体的偏移量为 sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`) + sizeof(:cpp:type:`esp_app_desc_t`)。
需在 ``CMakeLists.txt`` 中添加 ``target_link_libraries(${COMPONENT_TARGET} "-u custom_app_desc")``,确保自定义结构体在未使用时也位于镜像中。
API 参考
-------------
.. include-build-file:: inc/esp_app_format.inc