从RDA5981A/B/C编译后map文件和datasheet分析内存分配情况
先查看RDA5981的datasheet,
如下图,RDA5981芯片内部有三个RAM区域, I_SRAM,D_SRAM,I_cache, 还可以外挂PSRAM,
内存映射图解释:
在编译目录BUILD\UNO_81C\GCC_ARM\找到*.map文件, 可以搜索到如下地址情况:
.data 0x00100080
.bss 0x001017a8
.stack 0x0011f3d0 0x800
对照datasheet,这些地址 .data .bss .stack 编译后,都分布在I_SRAM,
.heap 0x00180000 0x28000
对照datasheet,的上面内存分布图, 这个地址都在D-SRAM, size 0x28000大小也是跟datasheet上160k是一致的,
也就是D-SRAM编译后全部都分配给了.heap堆
怎么计算剩余的内存呢?
计算可用度内存, 由于芯片有三个RAM: I_SRAM,D_SRAM,I-cache,
.data .bss .stack 编译后,都被分布在I_SRAM区域,
D_SRAM编译后,全部分给了堆.heap
I-cache在boot启动后, 是存放.txt也就是flash读来的代码, 用于运行程序,
相关地址和size大小,定义在文件:
RDA5981C.sct中,
#define RDA_ROM_BASE (0x00000000)
#define RDA_IRAM_BASE (0x00100000) //对应上图的IRAM的起始地址
#define RDA_IRAM_SIZE (0x00020000) //芯片内I_SRAM总共大小:128K
#define RDA_DRAM_BASE (0x00180000) //对应上图的DRAM的起始地址
#define RDA_DRAM_SIZE (0x00028000) //芯片内D_SRAM总共大小:98K
#define RDA_PSRAM_BASE (0x10000000) //无外挂PRSAM芯片,此处无用
#define RDA_FLASH_BASE (0x14000000) //FLASH起始地址
#define RDA_ICACHE_BASE (0x18000000) //I-cache地址,
总共内存也就是I_SRAM: 128K -> 0x20000, D_SRAM:160K ->0x28000(5981C),而I-cache,未公开未知,也未开放给用户使用,
已经使用的I_SRAM, 在编译结束界面,会有显示:
Allocated Stack: 2048 bytes
Total Static RAM memory (data + bss): 94568 bytes
如上, 也就是stack+data+bss, 你所剩内存也就是 128k-2k-94k=32K,
至于你D_SRAM 也就是heap还剩多少可以使用,
我编写了一个测试代码,用malloc函数来测试分配内存是否成功, 如下:
unsigned int i;
unsigned char *buf;
printf("Start malloc test...\r\n");
for(i=0;i<100000;i++)
{
printf("ready to malloc size=%d...\r\n",i*1000);
buf = (unsigned char *)malloc(i*1000); //heap堆,就是需要malloc函数来申请内存
printf("buf=%x...\r\n",buf);
if(!buf) //如果从heap分配内存失败,退出
break;
free(buf);
}
printf("all malloc finish\r\n");
我这边打印的log为:
[20200319-11:44:40]ready to malloc size=128000...
[20200319-11:44:40]buf=180410...
[20200319-11:44:40]ready to malloc size=129000...
[20200319-11:44:40]buf=180410...
[20200319-11:44:40]ready to malloc size=130000...
[20200319-11:44:40]buf=180410...
[20200319-11:44:40]ready to malloc size=131000...
[20200319-11:44:40]buf=0...
[20200319-11:44:40]all malloc finish
也就是heap剩下可用空间为131k,
你的剩下可用空间就是 32K +131K, =163K,
这里提到的.bss, .data, .txt, .stack, .heap的概念,
我在网上搜索了一个资料,供大家理解学习:
bss段:
BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。BSS段属于静态内存分配。
data段:
数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
text段:
代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
rodata段:
存放C中的字符串和#define定义的常量
heap堆:
堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
stack栈:
是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
1: //main.cpp
2: int a = 0; //a在全局已初始化数据区.data
3: char *p1; //p1在.bss(未初始化全局变量)
4: main()
5: {
6: int b; //b在栈区 .stack
7: char s[] = "abc"; //s为数组变量,存储在栈区,.heap
8: //"abc"为字符串常量,存储在已初始化数据区
9: char *p1,p2; //p1,p2在栈区
10: char *p3 = "123456"; //123456\0在已初始化数据区,p3在stack栈区
11: static int c =0; //C为全局(静态)数据,存在于已初始化数据data区
12: //另外,静态数据会自动初始化
13: p1 = (char *)malloc(10);//分配得来的10个字节的区域在堆heap区
14: p2 = (char *)malloc(20);//分配得来的20个字节的区域在堆heap区
15: //注意p1,p2是局部变量,所以存储在栈stack中,10Byte空间在堆heap中;
16: free(p1);
17: free(p2);
18: }