nRF52840 BLE 多服务开发中的 NRF_ERROR_NO_MEM 排查与解决实战

张开发
2026/4/12 23:18:18 15 分钟阅读

分享文章

nRF52840 BLE 多服务开发中的 NRF_ERROR_NO_MEM 排查与解决实战
问题现象在基于 nRF5 SDK 的 Heart Rate 示例上添加自定义 LBSLED Button Service私有服务后程序启动后立即进入 Fatal Error → System Reset 循环串口反复打印textapp: ble_lbs_init failed! Error code 0x000000040x00000004 对应 NRF_ERROR_NO_MEM内存不足。根本原因nRF52840 的 SoftDeviceS140在初始化时会分配一块 RAM 给协议栈使用。默认配置下GATT 属性表Attribute Table大小有限。当同时启用以下服务和模块时容易超出限制Heart Rate Service (HRS)Battery Service (BAS)Device Information Service (DIS)自定义 LBS 服务包含至少 2~3 个特征 CCCDPeer Manager Queued Write LESC 等安全特性每个 GATT 服务和特征都需要在属性表中占用空间LBS 服务初始化时申请内存失败导致 ble_lbs_init() 返回 NRF_ERROR_NO_MEM。排查过程关键点通过 APP_ERROR_CHECK 日志打印精确定位到 ble_lbs_init() 失败。确认错误码为 0x00000004NRF_ERROR_NO_MEM。分析同时运行的 BLE 服务数量和 RAM 使用情况。发现 Keil 中 IRAM1 Size 设置过大挤占了 SoftDevice 可用的 RAM。最终解决方案三管齐下代码层面增大 GATT 属性表最重要Cble_cfg.gatts_cfg.attr_tab_size.attr_tab_size 0x1400; // 或更高err_code sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, ble_cfg, ram_start);Keil 工程配置调整 IRAM1将 IRAM1 Size 适当调小例如 0x3A000 ~ 0x39000给 SoftDevice 留出更多 RAM。打印内存信息辅助调试CNRF_LOG_INFO(SoftDevice RAM start 0x%08X, ram_start);NRF_LOG_INFO(Available RAM for app ≈ %d bytes, (256*1024) - (ram_start - 0x20000000));经验教训与最佳实践添加自定义服务前必须评估总的 GATT 属性表占用。永远不要依赖默认配置尤其当项目包含多个服务 Peer Manager 时。建议在 ble_stack_init() 中主动配置 attr_tab_size、conn_cfg 等关键参数。开发过程中养成打印 RAM start 地址和可用内存的习惯能大幅加快调试速度。对于 nRF52840推荐至少预留 20~30KB 给应用层使用

更多文章