资源部署用户指南
本文档说明
本文档用于指导 HiDiTing 产品进行资源部署:确定固件镜像在 NorFlash 中的分区,以及确定代码、静态数据、栈和堆在 ITCM、DTCM、L2MEM、PSRAM 等存储资源中的布局。文档同时给出静态/动态内存的分析方法和常见的优化方向,帮助开发者在功能、性能、功耗和容量之间进行取舍。
资源部署会直接影响启动、升级、运行稳定性和可用内存。修改前应先确认开发板型号、NorFlash/PSRAM 容量及实际编译目标;未验证的分区或链接脚本改动不应直接用于量产固件。
资源部署背景与整体设计
资源部署解决的问题
资源部署由两个相互关联的部分组成:
| 部分 | 目标 | 主要依据 |
|---|---|---|
| 镜像分区 | 为启动、恢复、应用、NV、FOTA、BT、DSP 等镜像预留互不重叠的非易失存储区域 | NorFlash 分区配置与打包配置 |
| 内存布局 | 将代码段、只读数据、data、bss、中断栈、任务栈和堆放入满足性能、功耗与容量要求的运行时内存 |
链接脚本、PSRAM 内存池配置和代码段属性 |
当前 diting-community 固件包的 NorFlash 分区来自 /src/build/config/target_config/3322/param_sector/param_16m_sector.json,选择逻辑和各镜像装包地址位于 /src/tools/pkg/chip_packet/3322/packet.py。/src/drivers/boards/3322_evb/memory_config/norflash/normal/memory_config_flash.h 用于板级镜像和运行地址配置;PSRAM 的应用堆、NPU 堆、GUI 池等区域由 /src/drivers/boards/3322_evb/memory_config/ram/normal/psram.h 定义;链接器以 /src/drivers/boards/3322_evb/linker/standard/acore/normal/acore.prelds 中的 MEMORY 与 SECTIONS 规则将输入段布置到 Flash、ITCM、DTCM 或 PSRAM。修改分区时必须同时检查打包分区、板级地址和链接布局,不能只改其中一个文件。
存储资源与选型原则
| 资源 | 典型用途 | 取舍原则 |
|---|---|---|
| NorFlash | 固件镜像、常量和加载镜像 | 容量大且掉电保存;运行代码或数据是否需要搬运由链接脚本决定。 |
| ITCM/DTCM | 时延敏感代码、系统栈、热点数据 | 性能和功耗优势明显,但容量有限;优先留给启动、异常处理、实时路径和高频访问对象。 |
| L2MEM | 芯片共享的中间层次存储资源 | 与 DSP/GPU 存在共享关系,分配前需综合评估整机资源占用。 |
| PSRAM | 应用堆、大型数据、GUI/NPU 等内存池 | 容量大,适合低频或亮屏场景数据;性能和功耗不如内部 TCM,并应区分缓存属性。 |
基于代码的部署架构

链接脚本中的 .plt_ramtext、.data、.bss 和 .stacks 是部署决策的关键入口:当前普通 ACore 脚本把系统中断/异常栈固定在 DTCM,按规则选择代码与静态数据的输出段,并从 psram.h 取应用堆等区域的地址和长度。部署变更应遵循“配置 → 链接 → MAP 检查 → 烧录 → 运行时监测”的闭环,而不是只修改某一个地址宏。
配置版本与本文分区表的关系
当前 diting-community 的 pack_style_str 会由 packet.py 选择 16 MiB 的 param_16m_sector.json。其他目标可能选择 param_sector.json、param_8m_sector.json、param_16m_s_norflash_sector.json 或 param_16m_data_flash_sector.json,因此切换目标或 Flash 形态后必须重新确认实际分区文件,不能复用下表地址。
镜像分区表
当前 diting-community 的有效分区如下。表中地址由 param_16m_sector.json 的 Flash 基地址 0x26000000 加相对偏移得到;rootkey_partition_cfg.bin 由打包脚本放在 Flash 基地址,loaderboot_signed.bin 则由打包器按启动镜像规则单独加入固件包。
| 分区/产物 | 绝对起始地址 | 长度 | 配置项 |
|---|---|---|---|
rootkey_partition_cfg.bin |
0x26000000 |
0x00001000 |
分区表与根公钥 |
| SSB | 0x26001000 |
0x00010000 |
ssb |
| SSB 备份 | 0x26011000 |
0x00010000 |
ssb_backup |
| Recovery | 0x26021000 |
0x0005F000 |
recovery_image |
| SEliteOS | 0x26080000 |
0x00040000 |
seliteos_image |
| LiteOS 主应用 | 0x260C0000 |
0x00880000 |
acpu_image |
| FOTA 数据 | 0x26FA3000 |
0x00004000 |
fota_data |
| SSB 升级区 | 0x26FA7000 |
0x00010000 |
ssb_update |
| SEliteOS 升级区 | 0x26FB7000 |
0x00040000 |
seliteos_update |
| DFX 数据 | 0x26FF7000 |
0x00003000 |
dfx_data |
| NV 数据 | 0x26FFA000 |
0x00006000 |
nv_data |
构建后应再核对 <FBB_SDK_DIR>/output/3322/partition_table.bin、最终 diting-community.fwpkg 和打包日志,确认实际选择的分区文件与目标一致。
旧版 8 MiB 布局(仅用于识别历史产品,不用于当前 diting-community)
以下为原始文档保留的旧版布局。 **表 1** 镜像分区表名称 |
存储设备 |
地址 |
长度 |
|---|---|---|---|
loaderboot_signed.bin |
norflash |
0x00000000 |
0x00010000 |
rootkey_partition_cfg.bin |
norflash |
0x26000000 |
0x00001000 |
ssb_signed.bin |
norflash |
0x26001000 |
0x0000F000 |
ssb_backup_signed.bin |
norflash |
0x26010000 |
0x0000f000 |
recovery_signed.bin |
norflash |
0x2601F000 |
0x00061000 |
seliteos_signed.bin |
norflash |
0x26080000 |
0x00040000 |
application_signed.bin |
norflash |
0x260C0000 |
0x6E3000 |
3322_all_nv.bin |
norflash |
0x267FA000 |
0x00006000 |
须知:
- 由于BT、DSP镜像对外闭源交付,起始地址固定,因此除application镜像外,不建议用户自行修改其余地址划分,需要修改时请告知FAE。
- 分区表无法通过OTA(Over the Air)升级更改,因此要注意,分区表的划分需要在产品出货前确定。
内存部署
芯片可使用内存可具体分为ITCM/DTCM、L2MEM、PSRAM三部分,其中TCM由MCU和DSP共享,L2MEM(Level-2-Memory)与DSP、GPU共享。各类内存属性如下,访问性能 ITCM/DTCM>L2MEM>PSRAM,读写功耗 ITCM/DTCM<L2MEM<PSRAM,大小ITCM/DTCM<L2MEM<PSRAM,实际综合性能、功耗、大小进行内存部署。
内存部署具体信息可参考当前普通配置的 /src/drivers/boards/3322_evb/linker/standard/acore/normal/acore.prelds;不同 profile 应查看对应目录下的链接脚本。
-
代码段部署
代码部署在Flash中,芯片启动时将代码搬到PSRAM(Pseudostatic RAM)和ITCM(Instruction Tightly-Coupled Memory)中运行,包括Flash驱动代码、低功耗相关代码以及部分基础库。
如需配置代码到芯片ITCM上运行,可在“.plt_ramtext”段中增加对应静态库即可,具体可参考图1。

-
静态数据段部署,静态数据段包括data段和bss段:
- bss段指初始化为0或者未初始化的全局变量。
- data段指初始化非0的全局变量。
data和bss没有“一类全部放 DTCM、另一类全部放 PSRAM”的全局默认规则。当前acore.prelds先把内核、基础驱动和明确列出的组件.data/.bss放入 DTCM,再把媒体、图形、蓝牙及普通应用等列出的输入段放入.psram_data/.psram_bss。新增组件最终落点取决于链接脚本中的库匹配顺序和兜底规则,必须以本次构建生成的 MAP 文件为准,具体可参考图2、图3。说明: 外部PSRAM内存更大,但是访问性能低于SRAM(Static Random Access Memory),功耗也高于SRAM,因此考虑系统低功耗,适合将访问频次低或亮屏执行的部分放至PSRAM上。


-
栈空间
系统中断栈、异常栈默认部署在DTCM,不支持修改;任务栈支持部署在DTCM或者PSRAM上(参见 /src/application/3322/3322_app_standard/thread_init.c),具体示例如图4所示。

-
堆空间
堆空间分为两部分,一部分为kernel OS内部使用的系统堆空间,默认部署至内部DTCM上;另一部分为各个任务使用的内存堆空间,如各个任务malloc申请空间,默认部署至外部PSRAM上,具体可参考 /src/drivers/boards/3322_evb/memory_config/ram/normal/psram.h 头文件。
此外,堆空间支持自定义内存池使用,调用 osal 接口
osal_pool_mem_init、osal_pool_mem_alloc(实现参见 /src/kernel/osal/src/liteos/osal_addr.c,声明参见 /src/include/osal/memory/osal_addr.h)。
内存分析工具
静态内存
IDE工具提供了镜像分析功能,可以方便分析数据段、代码段等静态内存占用情况。具体使用方法请在《HiSpark Studio for VS Code 使用指南》中依次打开“栈分析和镜像分析”、“镜像分析”。
其中镜像分析功能中默认按照模块进行数据统计,如graphic、media、driver等模块。
动态内存
支持AT命令查看堆、栈内存信息,具体命令如表1所示。
表 1 堆栈内存信息查看命令
AT命令 |
描述 |
|---|---|
AT+HEAPINFO |
系统堆内存信息查看。 |
AT+STACKINFO |
系统任务栈内存信息查看,包括任务栈名称、大小、峰值、使用情况等。 |
常见内存优化方法
-
SDK组件裁剪
SDK当前除功能代码外,默认包含大量测试代码、维测代码以及Sample示例代码,实际用户集成SDK时,不需要该部分功能,因此可直接裁剪。具体可裁剪组件如表1所示。
表 1 SDK可裁剪组件
组件名
对应功能宏
功能描述
'graphic_at_service'
-
图形测试组件。
'app_at_service'
-
系统BSP测试组件。
'audio_at_service'
-
音频测试组件。
'media_at_service'
-
媒体测试组件。
'bt_manager_at_service'
-
蓝牙测试组件。
'audio_proc'
‘CONFIG_DIAG_AUDIO_PROC_SUPPORT’
音频维测相关组件。
'audio_dump'
‘CONFIG_DIAG_AUDIO_DUMP_SUPPORT’
音频维测相关组件。
'audio_probe'
‘CONFIG_DIAG_AUDIO_PROBE_SUPPORT’
音频维测相关组件。
‘SUPPORT_GPU_OPENVG’
GPU(Graphical Processing Unit)支持OpenVG接口。
‘SW_UART_DEBUG’
支持串口直接打印。
-
内部部署调整
内部TCM空间不足时,可以将部分数据段、任务栈部署至外部PSRAM。
-
代码优化
结合内存分析工具,排查当前哪一个模块占用内存较大,结合代码进行优化。代码优化手段较多,此处列出常见的几种优化手段帮助用户优化内存。
- 局部变量不应过大,会撑大栈空间,可考虑使用动态malloc的形式申请内存。
- 超大全局变量数组,需要考虑合理性,可考虑修改为链表的形式进行动态申请。
- 根据栈峰值使用情况,合理规划栈大小,根据经验,中等复杂程度任务一般栈空间3KB左右即可。
- 正常的printf接口无法对打印字符串进行压缩,会导致CodeSize迅速膨胀,因此可使用Diag压缩日志接口打印。
- 将不变的数据段尽量修改为const类型,即由data段转变为rodata段,内存部署也从内部SRAM转变为NorFlash。
注意事项
- 先确认生效配置再改地址。
3322_evb下存在多个 NorFlash、PSRAM 与链接脚本 profile。必须确认当前 target 实际使用的配置文件,不能将本文旧分区表的地址直接复制到其他容量或其他 profile。 - 分区调整需要整体评审。 应用镜像、FOTA、NV、DFX、BT、DSP、恢复镜像及安全相关区域必须互不重叠,并保留镜像签名头、向量表和页对齐空间。除 application 区外,BT、DSP 等闭源镜像地址不建议自行调整;确有需求时请先与 FAE 确认。
- 分区表不是 OTA 的可变配置。 分区布局应在产品出货前冻结。OTA 不能安全地重新定义已有分区边界,升级包必须与设备已有分区表匹配。
- 链接脚本、内存池和代码属性必须一致。 仅修改
psram.h而不检查acore.prelds,或只修改输出段而不确认输入段匹配规则,都会导致链接失败、段未生效或运行时异常。 - 不要移动系统关键栈。 当前普通 ACore 脚本将中断栈、异常栈等系统栈固定到 DTCM。任务栈迁移到 PSRAM 前,应确认访问时序、对齐、缓存属性及峰值用量;不能将中断/异常路径依赖的数据随意迁移到外部内存。
- PSRAM 不是无成本扩容。 它适合大块、低频或亮屏场景的数据;实时路径、频繁访问小对象和对功耗敏感的数据应优先保留在内部存储。GUI、NPU、显示命令链表等内存池还需遵守其缓存/非缓存属性。
- 所有部署变更都要检查 MAP。 编译通过不代表段落在预期位置。每次修改后应通过镜像分析或
.map文件确认.plt_ramtext、.data、.bss、堆和栈的地址、大小及剩余容量。 - 运行时验证不可省略。 烧录后执行关键功能回归,并通过系统 DFX 日志、诊断接口或
.map/运行统计检查堆使用量和任务栈峰值;AT+HEAPINFO、AT+STACKINFO是可选的串口观测入口。对 FOTA 产品还应在测试机上验证升级和回退流程。
常见错误
| 现象 | 常见原因 | 排查与处理 |
|---|---|---|
链接报 region ... overflowed 或镜像超限 |
ITCM/DTCM/Flash 分区容量不足,或新增段未裁剪 | 查看 .map 和镜像分析结果,确定最大对象;先裁剪无关组件、减小静态对象或迁移低频数据,再重新评估分区。 |
| 改了分区后设备无法启动 | 修改了启动/恢复/安全保留区,镜像边界或签名头不一致 | 恢复已验证的整包固件;比对 memory_config_flash.h、打包配置与烧录清单,确认所有镜像地址、长度和 4 KB 页对齐。 |
| 代码或数据没有部署到预期区域 | 输入段名与链接脚本规则不匹配,或改的是未被当前 target 选用的脚本 | 在 .map 中搜索目标符号和段名;核对 acore.prelds 中的输入段匹配规则及当前 profile。 |
| 迁移至 PSRAM 后偶发崩溃、花屏或性能变差 | 使用了不合适的缓存属性,或把实时/高频对象迁移到 PSRAM | 检查对应 PSRAM 内存池的 cache 属性;将关键路径数据迁回内部内存,并用压力场景验证。 |
| 堆剩余较多但仍然申请失败 | 内存碎片、使用了错误内存池,或单次连续申请过大 | 结合堆信息和业务日志确认申请大小/频率;复用缓冲区、改用固定内存池或拆分大块申请。 |
| 栈溢出或任务异常退出 | 局部大数组、递归/深调用或任务栈大小估算不足 | 用 AT+STACKINFO 检查峰值;缩小局部对象、改用受控堆/内存池,并为任务栈保留足够余量。 |
| 修改后 OTA 升级失败或升级后无法启动 | 新固件与已出货设备的分区表不一致 | 不通过 OTA 变更分区边界;为新布局制定出厂烧录方案,并使用同一布局生成完整升级链路。 |
| 文档表格与实际固件地址不一致 | 使用了不同 SDK 版本、Flash 容量或 normal/kid/test 配置 |
以当前 target 的配置头文件和最终 .map/打包清单为准,记录所用 SDK 版本和 board profile。 |