从RDA5981A/B/C编译后map文件和datasheet分析内存分配情况

先查看RDA5981的datasheet,

如下图,RDA5981芯片内部有三个RAM区域, I_SRAM,D_SRAM,I_cache, 还可以外挂PSRAM,

从RDA5981A/B/C编译后map文件和datasheet分析内存分配情况

内存映射图解释:

 

从RDA5981A/B/C编译后map文件和datasheet分析内存分配情况

在编译目录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, 在编译结束界面,会有显示:

从RDA5981A/B/C编译后map文件和datasheet分析内存分配情况
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: }