BlueNRG-LP/LPS 芯片添加 OTA 服务后,常出现代码空间溢出问题,核心原因是协议栈与应用程序的存储分配不合理。本文基于 ST 官方 LAT1239 应用笔记(Rev 1.0),从 OTA 方式选型、存储分配优化、协议栈裁剪、静态协议栈部署四个核心维度,详解代码空间优化的完整流程,适配 Keil、IAR、TrueStudio 等主流编译器,帮助用户在保留核心功能的前提下,大幅节省 Flash 空间。
资料获取:【应用笔记】LAT1239 简谈BlueNRG-LP和-LPS的代码空间优化
1. 核心背景与优化目标
1.1 关键问题
- 痛点:默认 OTA 方案(带备份)需存储 2 份协议栈 + 2 份应用,占用大量 Flash(BlueNRG-LP 示例中约 156KB),小容量芯片易溢出;
- 优化目标:通过合理选型 OTA 方式、裁剪协议栈功能、优化存储分配,在保留 OTA 和核心 BLE 功能的前提下,将代码空间压缩 30% 以上。
1.2 适用范围
- 芯片:BlueNRG-LP、BlueNRG-LPS 系列;
- 场景:需 OTA 功能的 BLE 应用(如智能传感器、无线控制器);
- 工具:Keil(.sct 链接脚本)、IAR(.icf 链接脚本)、TrueStudio(.ld 链接脚本)。
2. 第一步:OTA 方式选型 —— 从源头节省空间
ST 官方提供两种 OTA 方案,选型直接决定基础空间占用,优先选择 “不带备份” 方案:
2.1 两种 OTA 方案对比
| OTA 类型 | 核心组成 | 空间占用 | 安全性 | 适用场景 |
|---|---|---|---|---|
| 带备份(默认) | BLE_OTA_ResetManager + 2 份应用(Lower/Higher)+ 2 份协议栈 | 大(示例 156KB) | 高(应用升级失败可回退) | 对稳定性要求极高的场景 |
| 不带备份 | BLE_OTA_ServiceManager + 1 份应用 + 1 份协议栈 | 小(示例 92KB) | 一般(升级失败需重新烧录) | 多数消费级场景,优先选 |
2.2 选型关键注意事项
- 不带备份方案:升级服务集成在 Boot 端,仅需管理 1 份应用,空间节省 40% 以上,是优化首选;
- 带备份方案避坑:Lower/Higher 应用不可混用部署(高地址应用放低地址会运行失败),需在固件中添加标记,让升级工具自动识别。
3. 第二步:存储分配优化 —— 链接脚本精准配置
链接脚本定义了 Flash 的分区规则,通过调整宏定义可避免空间浪费,核心是 “2KB 对齐 + 按需分配”:
3.1 核心宏定义(作用于链接脚本,不影响 C/H 文件)
MEMORY_FLASH_APP_SIZE:限制应用程序最大占用空间,需 2KB 对齐(Flash 擦除最小单位为 2KB);MEMORY_FLASH_APP_OFFSET:定义应用程序链接地址偏移(如不带备份 OTA 需偏移SERVICE_MANAGER_SIZE);RESET_MANAGER_SIZE/SERVICE_MANAGER_SIZE:预留 Boot/OTA 服务的空间,不可随意缩小。
3.2 四种默认链接配置(按需选择)
| 配置宏 | 适用场景 | 空间优化点 |
|---|---|---|
| CONFIG_OTA_HIGHER | 带备份 OTA 高地址应用 | 按需分配高地址区域,避免重叠 |
| CONFIG_OTA_LOWER | 带备份 OTA 低地址应用 | 与高地址应用分区隔离,2KB 对齐 |
| CONFIG_OTA_USE_SERVICE_MANAGER | 不带备份 OTA 应用 | 仅预留 1 份协议栈 + 应用空间,最优选择 |
| 其他(非 OTA) | 无需升级的应用 | 无 OTA 服务占用,空间最省 |
3.3 实操建议
- 优先使用
CONFIG_OTA_USE_SERVICE_MANAGER配置,直接节省带备份方案的额外空间; - 若
MEMORY_FLASH_APP_SIZE未手动定义,链接脚本会自动按 Flash 总容量均分,需根据实际应用大小手动设置(如应用仅需 40KB,可设为 0xA000)。
4. 第三步:协议栈裁剪 —— 功能级按需关闭
BlueNRG SDK 提供 5 种协议栈配置,通过宏定义关闭无用功能,可节省 10KB-50KB 空间:
4.1 5 种协议栈配置选型
| 配置宏 | 核心功能 | 空间占用 | 适用场景 |
|---|---|---|---|
| BLE_STACK_BASIC_CONF | 基础 BLE 连接(无扩展功能) | 最小(约 88KB) | 仅需简单数据传输的场景 |
| BLE_STACK_SLAVE_DLE_CONF | 从机 + 数据长度扩展(DLE) | 中等(约 93KB) | 需传输大数据的从机设备 |
| BLE_STACK_SLAVE_DLE_LE_2M_CODED_CONF | 从机 + DLE+2M PHY | 中等(约 96KB) | 高速传输场景 |
| BLE_STACK_FULL_CONF | 全功能(主机 + 从机 + 安全连接 + 隐私功能) | 最大(约 160KB) | 需主机功能的复杂场景 |
| BLE_STACK_CUSTOM_CONF | 自定义功能(细粒度开关) | 按需调整 | 多数优化场景,首选 |
4.2 自定义裁剪实操(BLE_STACK_CUSTOM_CONF)
在
custom_ble_stack_config.h中开关功能,核心裁剪项及空间占用:CONTROLLER_MASTER_ENABLED(主机功能):关闭节省 10KB;SECURE_CONNECTIONS_ENABLED(安全连接):关闭节省 14.5KB;CONTROLLER_PERIODIC_ADV_ENABLED(周期广播):关闭节省 8KB;CONTROLLER_2M_CODED_PHY_ENABLED(2M PHY):关闭节省 2.9KB;- 核心原则:仅保留 “从机 + DLE”(数据长度扩展),关闭主机、安全连接、周期广播等非必需功能,可将协议栈压缩至 90KB 以内。
5. 第四步:静态协议栈部署 —— 函数级深度优化
静态协议栈将协议栈与应用分离编译,支持函数级裁剪,是空间不足时的终极方案:
5.1 静态协议栈核心优势
- 分离编译:协议栈单独编译为库,应用仅链接所需函数,避免冗余;
- 函数级裁剪:注释
bluenrg_lp_cmd_if.c中cmd_call_table的无用函数,可再省 5KB-10KB; - 空间对比:动态协议栈(全功能)约 160KB,静态协议栈(基础功能)仅 88KB,节省 45%。
5.2 官方 Demo 适配(快速上手)
ST SDK 提供静态协议栈 Demo,路径:
ProjectsBLE_ExamplesBLE_StaticStack,核心组合方式:- 不带备份 OTA:
BLE_StaticStack(Release/Basic) + BLE_SensorDemo_StaticStack(Release); - 带备份 OTA:
BLE_StaticStack(OTA_BTL_ResetManager) + BLE_SensorDemo_StaticStack(LowerApp_OTA/HigherApp_OTA)。
5.3 协议栈升级支持
静态协议栈默认不可 OTA 升级,需添加 Boot 搬运代码:
- 升级时先将新协议栈下载至应用区域;
- Boot 代码启动后,将应用区域的新协议栈拷贝至协议栈区域;
- 重新烧录被擦除的应用程序,完成协议栈 + 应用的完整升级。
6. 第五步:其他优化方法 —— 空间仍不足时使用
若上述优化后空间仍不足,可采用以下补充方案:
- 通用模块合并:将无需修改的通用模块(如 CRC、工具函数)编译进协议栈工程,避免重复占用;
- 片外 Flash 扩展:将字体、配置文件等静态资源存储至片外 SPI Flash,节省芯片内置 Flash;
- 芯片选型升级:若需全功能且空间紧张,可切换至 STM32WB 系列(更大 Flash + 集成 BLE/MCU)。
7. 优化效果验证(BlueNRG-LP 示例)
| 优化阶段 | 配置方案 | 代码空间占用 | 优化幅度 |
|---|---|---|---|
| 初始状态 | 带备份 OTA + 全功能协议栈 | 156KB | - |
| 优化后 | 不带备份 OTA + 自定义裁剪协议栈(从机 + DLE) + 静态协议栈 | 89KB | 43% |
8. 关键注意事项
- 2KB 对齐原则:Flash 分区和
MEMORY_FLASH_APP_SIZE必须 2KB 对齐,否则会浪费空间; - 协议栈裁剪避坑:关闭功能后需重新编译协议栈,确保无函数依赖错误;
- OTA 兼容性:带备份 OTA 的 Lower/Higher 应用需添加识别标记,避免部署混乱;
- 静态协议栈调试:协议栈与应用分离后,调试需加载协议栈符号文件,否则无法单步调试协议栈函数。
BlueNRG-LP/LPS 的代码空间优化核心是 “选型 + 裁剪 + 分配”:优先选择不带备份 OTA 方案从源头省空间,通过协议栈自定义裁剪关闭无用功能,再用静态协议栈实现函数级优化,最后通过链接脚本精准分配存储。整个流程无需修改核心业务代码,即可大幅压缩空间,适配小容量芯片部署。
阅读全文
495