NDK RAM 使用情况分析以及优化指南¶
1 如何查看KEIL的RAM和Flash使用情况¶
因为当前工程中很多和BLE时间处理相关的函数为了提升处理速度使用了RAM CODE,所以导致部分CODE会占用RAM空间,所以查看工程的实际占用空间要从RAM和Flash空间进行查看。
首先双击keil项目打开map文件
1.1 如何查看RAM空间:¶
因为STACK占用RAM边界位置,我们可以通过STACK占用可以知道RAM最多占用0x20007f30+0x800(2048) = 0x20008730
的RAM,因为RAM地址默认是0x20000000
起始的,所以我们知道RAM占用了0x8730(34608)
字节的RAM。
1.2 如何查看Flash空间¶
从RAM空间往上查找flash边界位置,0x20000000前面的即是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
另外我们也要注意一点,堆定义的空间可以适当多分配一点,有些堆的分配是在运行时才会去调用。