当前文档版本为 NDK-v0.6.0,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

NDK RAM 使用情况分析以及优化指南

1 如何查看KEIL的RAM和Flash使用情况

因为当前工程中很多和BLE时间处理相关的函数为了提升处理速度使用了RAM CODE,所以导致部分CODE会占用RAM空间,所以查看工程的实际占用空间要从RAM和Flash空间进行查看。

首先双击keil项目打开map文件

1.1 如何查看RAM空间:

image

通过STACK查看RAM占用

因为STACK占用RAM边界位置,我们可以通过STACK占用可以知道RAM最多占用0x20007f30+0x800(2048) = 0x20008730的RAM,因为RAM地址默认是0x20000000起始的,所以我们知道RAM占用了0x8730(34608)字节的RAM。

1.2 如何查看Flash空间

从RAM空间往上查找flash边界位置,0x20000000前面的即是flash最大地址

image

查看flash边界

通过map文件找到边界地址0x1c7a8+0x22(34) = 0x1c7ca(116682) bytes。

2 关于堆空间的使用说明

2.1 蓝牙controller的堆

蓝牙controller的堆默认是用于controller的广播,连接等各种数据包动态分配使用的。而且是从host定义来进行分配的,但是不同的参数可能导致堆的需求空间不一致。

我们可以通过打开app_config.h或者app_config_spark.h中的BT controller Memory Pool usage print选项(对应的宏CONFIG_CNTRL_MEM_POOL_PRINT)显示的输出底层controller所需要的内存。

正常分配时如下:

[19:32:53.628]收←◆LL Controller Version:bd5923c

[19:32:53.665]收←◆BT controller memory pool used: 400 bytes, remain bytes: 8496, total:8896 
BT controller memory pool used: 764 bytes, remain bytes: 8132, total:8896 
BT controller memory pool used: 3784 bytes, remain bytes: 5112, total:8896 
BT controller memory pool used: 4840 bytes, remain bytes: 4056, total:8896 
BT controller memory pool used: 5164 bytes, remain bytes: 3732, total:8896 
BT controller memory pool used: 6124 bytes, remain bytes: 2772, total:8896 
BT controller memory pool used: 8896 bytes, remain bytes: 0, total:8896 
app started

上面的log显示正常分配的对内存为8896bytes,所以我们可以打开nimble_glue.c或者nimble_glue_spark.c找到堆分配的宏PAN_BLE_CTLR_BUFFER_ALLOC将其的值修改为8896

#define PAN_BLE_CTLR_BUFFER_ALLOC	(8896)
#define PAN_BLE_CTLR_BUFFER_SIZE	(((PAN_BLE_CTLR_BUFFER_ALLOC) + 3)& (~((uint32_t)0x03))) /*4 bytes aligned*/

static uint32_t mem_buffer[PAN_BLE_CTLR_BUFFER_SIZE/4];
static uint32_t mem_pos;

我们也可以将堆修改为异常很小的值,比如此处设置为4000,看下实际输出:


[19:38:01.115]收←◆LL Controller Version:bd5923c

[19:38:01.151]收←◆BT controller memory pool used: 400 bytes, remain bytes: 3600, total:4000 
BT controller memory pool used: 764 bytes, remain bytes: 3236, total:4000 
BT controller memory pool used: 3784 bytes, remain bytes: 216, total:4000 
BT controller allocating 1056 bytes failed

此时分配失败后会触发断言在初始化的地方卡住。

我们可以一开始设置比较大的堆值,然后再调整为合适的值即可。

2.2 App以及host使用的堆(应用层堆全局使用freertos的堆)

为了方便资源管理,我们app和host全局使用freertos的堆,相应堆的分配函数pvPortMalloc

当前SDK哪些资源默认使用了freertos的堆呢?

  • app中显式使用pvPortMalloc的地方

  • freertos task的栈

  • 创建freertos定时器时的栈(定时器也是task)、

  • freertos创建信号量等

2.3 如何查看freertos heap的使用

我们可以通过打开app_config.h或者app_config_spark.h中的FreeRTOS Heap Usage Print选项(对应的宏CONFIG_FREERTOS_HEAP_PRINT)显示的输出底层controller所需要的内存。

freertos heap的宏是FreeRTOSConfig.h中的configTOTAL_HEAP_SIZE,我们可以通过修改configTOTAL_HEAP_SIZE的值来改变全局堆的大小。

启动时会输出如下:

[19:47:57.875]收←◆total allocated bytes:216,remain:5920
total allocated bytes:304,remain:5832
total allocated bytes:392,remain:5744
total allocated bytes:480,remain:5656
total allocated bytes:536,remain:5600
total allocated bytes:704,remain:5432
total allocated bytes:792,remain:5344
LL Controller Version:bd5923c

[19:47:57.918]收←◆app started
total allocated bytes:848,remain:5288
total allocated bytes:2864,remain:3272
total allocated bytes:2960,remain:3176
total allocated bytes:3232,remain:2904
total allocated bytes:3328,remain:2808
total allocated bytes:4368,remain:1768
total allocated bytes:4464,remain:1672
total allocated bytes:4520,remain:1616
total allocated bytes:4752,remain:1384
total allocated bytes:4776,remain:1360
total allocated bytes:4808,remain:1328

我们故意将configTOTAL_HEAP_SIZE设置为一个很小的值,分配失败是会有如下显示:


[19:50:28.736]收←◆total allocated bytes:216,remain:2848
total allocated bytes:304,remain:2760
total allocated bytes:392,remain:2672
total allocated bytes:480,remain:2584
total allocated bytes:536,remain:2528
total allocated bytes:704,remain:2360
total allocated bytes:792,remain:2272
LL Controller Version:bd5923c

[19:50:28.778]收←◆app started
total allocated bytes:848,remain:2216
total allocated bytes:2864,remain:200
total allocated bytes:2960,remain:104
pvPortMalloc failed
allocate 272 bytes failed,remain:104

另外我们也要注意一点,堆定义的空间可以适当多分配一点,有些堆的分配是在运行时才会去调用。