1.ram.ld文件和map.txt文件的作用:
ram.ld文件:是RAM或FLASH空间分配的规则,工具链中的链接器按ram.ld中的规则分配程序或ram占用的空间。 map.txt 文件: 最终链接的结果可以在map.txt中查看,程序或各种buf占用的ram,在map.txt中可以找到 (static 函数或变量除外)
注意: 1.目前蓝讯所有SDK均不支持malloc/free之类的RAM动态分配。RAM复用可以在ld文件中定义来实现。 2.基本上所有RAM均可以放程序(如comm或bcomm),也可以放数据(如a / b / c / d / e /fram ,stack ,data, heap)
2. ram.ld文件 MEMORY
下面可以来看看ram.ld文件中的内容(以530X标准SDK为例) 在MEMORY中,可以看到所有RAM的的大致分配。(内部程序CACHE和数据CACHE 没有列到这里)
从MEMORY中可以看到:530X所有的RAM一共有 34+8+1+25+12+16+24+18+12+2.5+4 = 156.4K (不包括cache,内部有几十K的cache,先不分析)
3.flash区
首先来看flash区:(函数地址从__base+512也就是从0x10000200开始) 如果函数定义时,未用AT指定的段名,均放到flash区。由于comm区有限,大部份代码均放到flash区。flash主要存放代码及常量及各种资源文件(如提示音,EQ参数)
为了方便评估每个模块用了多少代码空间,建议放在flash区中的代码均要用AT指定,放到text中的某个段(按模块划分,(.text*),这里的*表示任意字符),如:
关于flash区和com区的定义及使用,可以查看如下链接
下面描述各RAM的使用情况:
4. comm (34K) 公共区:
.comm (34K) 公共区:(0x20000 到 0x20000+34K),也就是【0x20000,0x28800】
上电后公共区代码会从flash加载进来,整个程序生命周期内,comm区的代码均驻留在ram中,主要存放中断及各种中断检测代码,或一些对运行时间要求比较高的代码(运行时省掉了从falsh加载代码的时间)。当然也可以存放数据。 在 SECTIONS中,可以看到如下的段均放到comm区内。
其中 如(.com_text*),后面的 * 表示 任意符号,如(.com_text.bsp.key) 也在(.com_text*)段内 放入comm区的函数,需要在函数前增加 "AT(comm区中的段名)", 如 AT(.com_text.bsp.key)
可以在map.txt文件中看到,bsp_key_process在comm区[0x20000,0x28800]之中
当然,数据区也可以放到RAM中,只需要在定义时AT到comm区中:
在map.txt文件中可以看到,test_u8和TestBuf均在[0x20000,0x28800]的公共区中
5.bcomm区:
和comm区类似, bcomm这里指蓝牙专用的com区,也是上电时程序就加载进来,如果不用到蓝牙,可以随便使用该区域
6.stack区(长度为1K):
栈,主要用于函数调用时,保存调用者当前的运行环境,当被调函数执行完成后,从stack中恢复调用者函数的运行环境并继续执行下去。 这里的栈只有1K,所以要避免函数中定义大的局部buf,当局部buf接近或超过栈大小时,会引起栈爆掉,导致各种死机。
7.data段:
存放全局变量或数组,如,定义一个,当没有对TestBuf指定段时,默认是放到data段中 [0x1C00,0x8000]
当data区的数据空间爆后,如果comm区还有空间,经常可以把data区的一些buf移到comm区中,见comm区章节存放变量及buf数组示例
8.heap 段
系统用到,这里暂时不做分析。
9.aram,bram,cram,dram,eram,fram。RAM复用方法
这些ram主要用于存放数据(当然也可以手动加载代码到这些ram中运行)。 具体这些ram的作用,可以在ld文件 中查看,也可以仿照ld文件中的做法,实现ram的复用。 如下面的dram, 这里就复用来做各中解码用到的buf, 由于同一时刻,不会同时做多种解码,所以这里可以复用 总结:同一时序不会同时用到的RAM,就可以拿来做复用
上面程序中的 .= 0x3000表示从__dram_vma到0x3000的偏移,当dram中段数据总量超过了0x3000,编译就会报错。 这种用法ld文件中很常见,如下面的*(.rec.sco)这段buf就限制在了
(__dram_vma)到 (__dram_vma+0x1400)这段地址内,如果*(.rec.sco)这段容量超过了0x1400,程序就会报错
通过这种对buf的限制,可以实现更多精细化的复用 当然,一个buf要定义到*(.rec.sco)中,只需要定义时增加AT命令即可,如: u8 test_buf[100] AT*(.rec.sco)
//————————————————————————-
bram: 蓝牙后台(蓝牙后台代码或数据会加载到此RAM中运行),当不做蓝牙后台时,可用于各种数据缓存如,复用于做karaok混响,变速不变调(stretch)数据区
//————————————————————————-
cram:复用有点多,这里暂列举几个: flac解码,upd或串口升级代码,fcc测试缓存,fota无线升级,wma解码,mp3压缩等
剩下的eram/fram可以查看ld文件 ,这里不再细述。
//————————————————————————-
在ram.ld文件中,还有大量如下使用
这种用法,是SDK内部加载代码用的,用于一些对时效性要求高的代码。 如这里在sbc解码或mp3解码时,可以把这些代码一次性加载到RAM中运行,在解码周期内,不会释放,解码模式完成后,才释放,相当于动态增加了com区,节约解码时间。
//————————————————————————-
这部份相当于是 comm和bcomm区在flash中的地址和实际ram中的地址,加载com区时会用到
实际在,在内部加载com区是memcpy直接把代码从flash中拷贝到ram中实现的 memcpy(&__comm_vma, &__comm_lma, (u32)&__comm_size); //Load COMM memcpy(&__bcomm_vma, &__bcomm_lma, (u32)&__bcomm_size); //Load BTCOMM
//————————————————————————-
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/290772.html