
esp-iot-solution 资源打包与内存映射指南深入解析 esp_mmap_assets 组件的分区、MMAP 与文件系统三种访问模式【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution导读在嵌入式 GUI 与显示应用中图片、字体等资源通常体积庞大若随应用代码一起编译进固件会显著增大 app 二进制体积、拉长编译与烧录时间。esp_mmap_assets是 Espressif esp-iot-solution 仓库中用于打包资源并直接映射访问的组件它在构建期将图片、字体等资源打包成独立的.bin镜像运行时通过自动生成的枚举和句柄 API 直接访问支持分区Partition、内存映射Memory Mapping与文件系统File System三种访问模式并集成了 SJPG/SPNG 图片切片、QOI 转换、LVGL Bin 转换等丰富的图像预处理能力。阅读本文后你将掌握如何在 ESP-IDF 工程中配置并生成资源镜像、选择最合适的访问模式、以及如何在应用代码中使用mmap_assets_*系列 API 读写资源。组件定位与核心特性esp_mmap_assets组件位于仓库的 components/display/tools/esp_mmap_assets 目录源码实现为 esp_mmap_assets.c对外接口定义在 esp_mmap_assets.h。其核心设计思路是让资源和代码分离资源镜像独立烧录减少 app 二进制体积同时利用自动生成的枚举访问资源信息简化资源管理。组件提供的能力可归纳为以下几类导入文件类型丰富支持.bin、.jpg、.ttf等多种文件格式的资源打包。三种访问模式默认的Partition 模式从 ESP32 分区读取资源Memory Mapping 模式直接映射分区地址性能最高File System 模式从文件系统读取资源便于开发调试。图片切片Split按设定的切片高度将图片切分配合 SJPG/SPNG/SQOI 解码器降低解码所需内存。格式转换支持将 JPG/PNG 图片转换为 QOI 格式体积小、解码快以及转换为 LVGL 可直接使用的 Bin 二进制数据。多分区支持spiffs_create_partition_assets函数支持挂载多个分区每个分区拥有独立的处理逻辑。完整性与校验通过文件数、校验和checksum与元数据魔数magic校验确保镜像与程序一致性。接入工程该组件已发布到乐鑫组件服务可通过组件管理器添加idf.py add-dependency esp_mmap_assets也可以直接在工程中创建idf_component.yml声明依赖。若使用 esp-iot-solution 源码目录作为组件路径则直接引用仓库内的 idf_component.yml 所对应的组件目录即可。从 CMakeLists.txt 可以看到组件运行期依赖spi_flash、esp_partition、app_update等模块在 ESP-IDF 5.5 之前额外依赖bootloader_support5.5 及以后改为esp_bootloader_format。此外组件通过 project_include.cmake 向工程注入spiffs_create_partition_assets()CMake 函数供各组件在构建期调用以生成资源镜像。CMake 构建选项详解选项总览在工程或组件的 CMakeLists.txt 中调用spiffs_create_partition_assets()前需要先set以下选项函数内部通过cmake_parse_arguments解析见 project_include.cmake。布尔开关选项optionsset(options FLASH_IN_PROJECT, FLASH_APPEND_APP, MMAP_SUPPORT_SJPG, MMAP_SUPPORT_SPNG, MMAP_SUPPORT_QOI, MMAP_SUPPORT_SQOI, MMAP_SUPPORT_RAW, MMAP_RAW_DITHER, MMAP_RAW_BGR_MODE)单值参数选项one_value_argsset(one_value_args MMAP_FILE_SUPPORT_FORMAT, MMAP_SPLIT_HEIGHT, MMAP_RAW_FILE_FORMAT, IMPORT_INC_PATH, COPY_PREBUILT_BIN)说明原文档与 CMake 解析逻辑中还存在MMAP_RAW_COLOR_FORMAT这一单值参数见 project_include.cmake用于指定 RAW 图像的颜色格式在“LVGL Bin 支持”一节会详细介绍。通用选项说明选项含义FLASH_IN_PROJECT允许在idf.py flash时将生成的资源镜像与应用二进制、分区表等一起自动烧录FLASH_APPEND_APP允许将资源二进制bin追加到应用二进制app_bin末尾实现追加式固件IMPORT_INC_PATH生成的头文件目标路径默认指向组件所在位置从源码看默认值为CMAKE_CURRENT_LIST_DIR见 project_include.cmakeCOPY_PREBUILT_BIN将预先生成的二进制文件复制到目标目录支持直接使用外部生成的资源镜像而无需从源文件重新构建MMAP_FILE_SUPPORT_FORMAT指定支持的资源文件后缀如.png、.jpg、.ttfMMAP_SPLIT_HEIGHT图片切分高度像素用于降低解码内存占用依赖MMAP_SUPPORT_SJPG、MMAP_SUPPORT_SPNG或MMAP_SUPPORT_SQOI参数依赖与合法性校验从 project_include.cmake 的校验逻辑中可以总结出以下关键约束构建期若违反会直接FATAL_ERROR未启用COPY_PREBUILT_BIN时必须指定MMAP_FILE_SUPPORT_FORMAT否则报错提示填写要打包的文件后缀。MMAP_SUPPORT_QOI与MMAP_SUPPORT_SJPG/MMAP_SUPPORT_SPNG互斥不能同时开启。MMAP_SUPPORT_SQOI依赖MMAP_SUPPORT_QOI且开启 SQOI 时必须配套设置MMAP_SPLIT_HEIGHT。只要开启了 SJPG/SPNG/SQOI 中的任意一个就必须定义MMAP_SPLIT_HEIGHT且取值 1。MMAP_SUPPORT_RAWLVGL Bin 转换与 SJPG/SPNG/QOI/SQOI/PJPG不能同时开启。若提供COPY_PREBUILT_BIN会跳过格式与转换相关的校验仅检查该路径下文件是否存在。通用打包示例spiffs_create_partition_assets( my_spiffs_partition my_folder FLASH_IN_PROJECT MMAP_FILE_SUPPORT_FORMAT .jpg,.png,.ttf )预构建二进制资源示例spiffs_create_partition_assets( my_spiffs_partition ${ASSETS_DIR} FLASH_IN_PROJECT COPY_PREBUILT_BIN ${ASSETS_DIR}/prebuilt.bin )动画资源与自定义头文件路径示例组件 README 中还给出了带IMPORT_INC_PATH的动画资源打包方式spiffs_create_partition_assets( anim_boot ${ASSETS_DIR}/boot FLASH_IN_PROJECT MMAP_FILE_SUPPORT_FORMAT .aaf,.eaf IMPORT_INC_PATH ${ASSETS_DIR} )支持的图像格式与预处理格式开关选项说明MMAP_SUPPORT_SJPG启用 SJPGSplit JPG格式需使用 LVGL 的 SJPG 解码器解析参考 LVGL 8.4 的 SJPG 库MMAP_SUPPORT_SPNG启用 SPNGSplit PNG格式需配合本仓库的esp_lv_decoder组件解析MMAP_SUPPORT_QOI启用 QOIQuite OK Image格式支持将 JPG/PNG 转换为 QOI解码更快适合资源受限系统MMAP_SUPPORT_SQOI启用 SQOISplit QOI格式依赖MMAP_SUPPORT_QOI同样需esp_lv_decoder解析另外在 project_include.cmake 的解析列表以及 README 中还存在MMAP_SUPPORT_PJPG将 PNG 转为 JPG 并使用 JPG 解码器处理 PNG 文件可作为渐进式 JPEG 的补充手段。图片切片示例spiffs_create_partition_assets( my_spiffs_partition my_folder FLASH_IN_PROJECT MMAP_FILE_SUPPORT_FORMAT .jpg MMAP_SUPPORT_SJPG MMAP_SPLIT_HEIGHT 16 )切片高度越小解码内存占用越低但镜像文件会略大。py_tool 的 README 建议内存受限设备推荐 8~16 像素内存充足时可使用 32~64 像素。LVGL Bin 支持MMAP_SUPPORT_RAW将 JPG/PNG 转换为 LVGL 可直接使用的Bin二进制数据。LVGL v8 的转换参考lvgl_image_converter工具LVGL v9 的转换参考 LVGL 官方脚本LVGLImage.py。MMAP_RAW_FILE_FORMAT指定 RAW 图像的文件格式。LVGL v8{true_color, true_color_alpha, true_color_chroma, indexed_1, indexed_2, indexed_4, indexed_8, alpha_1, alpha_2, alpha_4, alpha_8, raw, raw_alpha, raw_chroma}LVGL v9不使用。MMAP_RAW_COLOR_FORMAT指定 RAW 图像的颜色格式。LVGL v8{RGB332, RGB565, RGB565SWAP, RGB888}LVGL v9{L8, I1, I2, I4, I8, A1, A2, A4, A8, ARGB8888, XRGB8888, RGB565, RGB565A8, ARGB8565, RGB888, AUTO, RAW, RAW_ALPHA}MMAP_RAW_DITHER启用 RAW 图像的**抖动dithering**处理。LVGL v8 需要开启LVGL v9 不使用。MMAP_RAW_BGR_MODE启用 RAW 图像的BGR 模式。LVGL v8/v9 均不使用。LVGL v9 示例spiffs_create_partition_assets( ......... MMAP_FILE_SUPPORT_FORMAT .png MMAP_SUPPORT_RAW MMAP_RAW_COLOR_FORMAT ARGB8888 )LVGL v8 示例spiffs_create_partition_assets( ......... MMAP_FILE_SUPPORT_FORMAT .png MMAP_SUPPORT_RAW MMAP_RAW_FILE_FORMAT true_color_alpha MMAP_RAW_COLOR_FORMAT RGB565SWAP )从 project_include.cmake 可以看出当开启MMAP_SUPPORT_RAW时构建系统会自动检测工程中的 LVGL 版本若无法确定则按 v8.x 处理从而选择对应的转换参数因此 LVGL v8 与 v9 的配置差异由工具链自动适配。构建流程与二进制格式构建管线调用spiffs_create_partition_assets()后构建系统会通过partition_table_get_partition_info获取目标分区的 offset 与 size见 project_include.cmake随后将 config_template.json.in 配置模板渲染为构建目录下的partition.json以--build参数调用组件自带 Python 工具 spiffs_assets_gen.py生成资源镜像mmap_build/base_dir_name/partition/partition.bin若开启FLASH_IN_PROJECT通过esptool_py_flash_to_partition将镜像烧录到对应分区见 project_include.cmake若开启FLASH_APPEND_APP则以--merge参数将资源二进制合并进 app 二进制。在生成过程中若主机缺少Pillow、numpy、qoi-conv等 Python 依赖CMake 会自动尝试通过 pip 安装见 project_include.cmake。独立构建工具组件还提供了不依赖 CMake 的独立 Python 构建脚本 assets_gen.py支持纯命令行参数直接生成资源镜像详见其 READMEpip install Pillow numpy qoi-conv packaging # 依赖脚本也会自动安装 python assets_gen.py \ --assets-path ./images \ --output ./build/assets.bin常用参数包括--support-spng、--support-sjpg、--support-qoi、--support-sqoi、--support-pjpg、--split-height N、--partition-size默认 0x1000000即 16MB、--name-length默认 32、--support-format默认.png,.jpg、--partition-name默认 assets。构建成功后会在输出目录生成资源二进制与对应的mmap_generate_name.h头文件。镜像二进制布局从 esp_mmap_assets.c 的注释可以看到镜像的二进制结构头部32 字节MMAP魔数4B、版本号4B、单个资源名长度name_len4B、资源总数files4B、资源表校验和checksum4B、资源表数据总长payload_len4B、预留 8B。资源表table每个条目以stride name_len 12步进依次存放资源名、payload 大小4B、相对数据块的偏移4B、宽度2B、高度2B。数据负载Data Payload所有资源文件的原始字节连续存放每个子资源的起始处有 2 字节魔数0x5A5AASSETS_FILE_MAGIC_HEAD作为元数据标记。组件同时兼容旧版v0镜像当头部魔数不是MMAP时会回退到 legacy 格式解析此时资源名步进由 Kconfig 中已废弃的CONFIG_MMAP_FILE_NAME_LENGTH默认 16决定见 Kconfig 与 esp_mmap_assets.c。应用初始化生成头文件与句柄自动生成的头文件构建完成后会自动生成形如mmap_generate_my_spiffs_partition.h的头文件包含资源总数、校验和以及文件枚举#include mmap_generate_my_spiffs_partition.h #define TOTAL_MMAP_FILES 2 #define MMAP_CHECKSUM 0xB043 enum MMAP_FILES { MMAP_JPG_JPG 0, /*! jpg.jpg */ MMAP_PNG_PNG 1, /*! png.png */ };注意头文件名中的分区名部分如my_spiffs_partition由构建配置决定实际使用时请以构建生成的宏为准。在组件测试工程中对应的头文件为 mmap_generate_assets_build.h 与 mmap_generate_factory.h测试用例通过其中的MMAP_ASSETS_BUILD_FILES、MMAP_ASSETS_BUILD_CHECKSUM等宏完成一致性校验。配置结构体配置结构体定义在 esp_mmap_assets.htypedef struct { const char *partition_label; /*! 分区标签use_fs 时作为文件路径 */ int max_files; /*! 支持的最大资源数量 */ uint32_t checksum; /*! 资源表校验和用于完整性验证 */ struct { unsigned int mmap_enable: 1; /*! 是否启用内存映射 */ unsigned int use_fs: 1; /*! 是否使用文件系统partition_label 作为文件路径 */ unsigned int app_bin_check: 1; /*! 是否启用 app 头部与 bin 文件一致性检查 */ unsigned int full_check: 1; /*! 是否启用整体自一致性检查 */ unsigned int metadata_check: 1; /*! 是否启用元数据魔数校验 */ unsigned int reserved: 27; /*! 预留 */ } flags; } mmap_assets_config_t;其中max_files与checksum应取自编译生成的头文件如MMAP_MY_FOLDER_FILES、MMAP_MY_FOLDER_CHECKSUM保证程序与镜像严格一致该检查由app_bin_check控制见 esp_mmap_assets.c资源数量不匹配返回ESP_ERR_INVALID_SIZE校验和不匹配返回ESP_ERR_INVALID_CRC。分区模式默认mmap_assets_handle_t asset_handle; const mmap_assets_config_t config { .partition_label my_spiffs_partition, .max_files MMAP_MY_FOLDER_FILES, //Get it from the compiled .h .checksum MMAP_MY_FOLDER_CHECKSUM, //Get it from the compiled .h .flags { .mmap_enable false, // Use partition mode .use_fs false, // Not using file system .app_bin_check true, } }; ESP_ERROR_CHECK(mmap_assets_new(config, asset_handle));该模式下资源通过esp_partition_read按需读取内存占用低适合生产部署。测试工程 partitions.csv 中assets_build、assets_storage等即为此类data/spiffs分区。内存映射模式const mmap_assets_config_t config { .partition_label my_spiffs_partition, .max_files MMAP_MY_FOLDER_FILES, .checksum MMAP_MY_FOLDER_CHECKSUM, .flags { .mmap_enable true, // Enable memory mapping .use_fs false, // Not using file system .app_bin_check true, } }; ESP_ERROR_CHECK(mmap_assets_new(config, asset_handle));该模式通过esp_partition_mmap将分区直接映射到地址空间见 esp_mmap_assets.c访问资源时无需额外读取操作性能最佳适合高性能显示场景。需要留意的是映射会占用内存映射MMU页源码中会先检查spi_flash_mmap_get_free_pages可用空间是否足够不足则返回ESP_ERR_INVALID_SIZE。文件系统模式const mmap_assets_config_t config { .partition_label /spiffs/assets.bin, // File path instead of partition name .max_files MMAP_MY_FOLDER_FILES, .checksum MMAP_MY_FOLDER_CHECKSUM, .flags { .mmap_enable false, // Disable memory mapping .use_fs true, // Use file system .app_bin_check true, } }; ESP_ERROR_CHECK(mmap_assets_new(config, asset_handle));此模式下partition_label是文件系统中的镜像文件路径而非分区标签组件通过标准 C 库fopen/fread访问见 esp_mmap_assets.c适合开发与测试阶段——例如测试用例 test_esp_mmap_assets.c 先挂载 SPIFFS 到/spiffs再以/spiffs/assets_build.bin作为资源路径完成读取与校验。三种模式对比模式性能内存占用适用场景分区Partition良好低生产部署内存映射Memory Mapping最佳中等高性能应用文件系统File System良好低开发与测试关于线程安全分区模式由 ESP-IDF 内部机制保证线程安全内存映射模式为直接内存访问天然线程安全文件系统模式的文件操作由内部互斥锁mutex保护。从源码看句柄内部创建了 FreeRTOS 互斥量mmap_assets_copy_mem在文件读取路径上会加锁执行见 esp_mmap_assets.c。资源访问 API创建句柄后即可使用生成头文件中的枚举来获取资源信息const char *name mmap_assets_get_name(asset_handle, MMAP_JPG_JPG); const void *mem mmap_assets_get_mem(asset_handle, MMAP_JPG_JPG); int size mmap_assets_get_size(asset_handle, MMAP_JPG_JPG); int width mmap_assets_get_width(asset_handle, MMAP_JPG_JPG); int height mmap_assets_get_height(asset_handle, MMAP_JPG_JPG); ESP_LOGI(TAG, Name:[%s], Mem:[%p], Size:[%d bytes], Width:[%d px], Height:[%d px], name, mem, size, width, height);mmap_assets.h对外提供的完整 API 包括mmap_assets_new/mmap_assets_del创建与释放资源句柄mmap_assets_get_mem获取指定索引资源的内存指针内存映射模式下直接指向映射地址内部会跳过 2 字节文件魔数见 esp_mmap_assets.cmmap_assets_copy_mem按偏移量将资源的一部分复制到目标缓冲区跨模式通用mmap_assets_copy_by_index按索引一次性复制完整资源数据到目标缓冲区mmap_assets_get_name/get_size/get_width/get_height获取资源名、大小、宽高宽高为 0 表示非图像资源如字体文件mmap_assets_get_stored_files获取镜像中实际存储的资源总数便于遍历所有资源。测试用例 test_esp_mmap_assets.c 中展示了典型的遍历方式通过mmap_assets_get_stored_files获取总数逐项打印名称、内存地址、大小、宽高并通过 PNG/JPG 文件签名magic bytes验证读取到的数据真实有效内存映射模式下直接memcpy其余模式则通过mmap_assets_copy_mem读取这正是两种模式下取数路径的差异所在。小结esp_mmap_assets为 ESP32 系列显示与 GUI 应用提供了一套构建期打包、运行期映射的资源管理方案通过spiffs_create_partition_assets()CMake 函数把图片、字体等资源打成独立镜像配合自动生成的枚举头文件让资源访问变得安全、高效、易维护三种访问模式分别覆盖生产部署、高性能渲染与开发调试等典型场景SJPG/SPNG 切片、QOI 转换与 LVGL Bin 转换等预处理能力则进一步降低了资源解码对 RAM 的占用。结合本仓库 test_apps 中的完整测试工程分区表见 partitions.csv用例见 test_esp_mmap_assets.c你可以快速搭建起自己的资源打包与映射流程。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考