【中科蓝讯BT896X】app.lst、ram.ld、map.txt文件的分析和使用
测试SDK版本:《SDK_BT896X_S12685_20240314》
文章目录
- 【中科蓝讯BT896X】app.lst、ram.ld、map.txt文件的分析和使用
- 前言
- 一、app.lst、ram.ld、map.txt文件介绍
- 1.1 app.lst文件
- 1.2 ram.ld文件
- 1.3 map.txt文件
- 二、通过 ram.ld 和 map.txt文件,查看代码在CPU Ram中的占用情况
- 三、通过 分析 map.txt文件,节省用户代码对RAM空间的消耗
- 四、分析 map.txt文件中的字节对齐
- 五、RAM空间溢出分析
- 六、代码优化 省RAM空间
- 七、通过app.lst文件查看程序运行流程
前言
要熟悉蓝讯开发的app.lst、ram.ld、map.txt文件,建议先仔细研读下面几篇博客,可以对蓝讯开发有一个较为全面的认识:
- 中科蓝讯蓝牙: 芯片框架简述
- 中科蓝讯蓝牙: 公共区(com区)空间不够一般优化方法
- 中科蓝讯蓝牙:RAM使用,ram.ld文件和map.txt文件的查看
一、app.lst、ram.ld、map.txt文件介绍
1.1 app.lst文件
app.lst 文件是编译过程中的中间输出文件,通常由编译器生成,它包含了汇编级别的详细信息,如每行源代码对应的机器指令、地址、符号信息等。在RISC-V架构下,使用RV32-Toolchain编译应用程序时,如果启用了生成清单文件(listing file)的选项,就会产出app.lst这样的文件。
要创建并查看app.lst,你需要遵循以下步骤:
打开CodeBlock,并导入或创建一个新的项目。
将你的源代码文件(例如:app.c)添加到该项目中。
在项目设置中,确保编译器设置正确,并启用生成清单文件的选项。这可能位于“构建目标”> “全局选项”> “C/C++”类别下的相应配置。
编译你的项目。点击“构建”或“编译并运行”,CodeBlock将调用RV32-Toolchain进行编译。
如果编译成功,app.lst文件将在你的项目目录下生成,与你的.o对象文件和最终的.dcf文件在同一位置。
1.2 ram.ld文件
ram.ld 是一种链接脚本(Linker Script),用于在构建嵌入式系统时定义内存布局和映射。它通常由GNU ld或者类似的链接器使用,用来指导编译器如何将编译后的对象文件组织到最终的可执行文件中,特别是在资源有限的微控制器如ARM Cortex-M系列芯片上。
在中科蓝讯的设备中,ram.ld 可能定义了如下内容:
- RAM 区域的开始地址和大小,比如 .data 和 .bss 段的位置。
- FLASH 区域的开始地址和大小,用于存放程序代码和初始化数据。
- 有可能还包括中断向量表(Vector Table)的位置。
- 可能会指定某些段是否应该在加载时初始化或者是在运行时由硬件自动扩展。
以下是一个简化的ram.ld例子:
MEMORY {RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64KFLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
}SECTIONS {.vector_table :{*(.vectors)} >FLASH.text :{*(.text*)*(.rodata*)} >FLASH.data :{*(.data*)} AT>FLASH ALIGH_TO(4){_sidata = LOADADDR(.data);*(.data*)} >RAM.bss :{_sbss = .;*(.bss*)_ebss = .;} >RAM
}
在这个例子中:
- MEMORY 定义了两个内存区域,一个是RAM,另一个是FLASH。
- SECTIONS 部分定义了各个段(如.text, .data, .bss)应该如何被放置在内存中。
ram.ld文件是用于定义RAM空间分配的规则,它指导链接器如何在内存中安排程序和数据。在530X标准SDK的例子中,MEMORY部分列出了所有可用的RAM区域。例如,这个特定的530X芯片有总共156.4KB的RAM,不包括内部的CACHE。
在ram.ld中,不同的RAM区域有不同的用途,比如:
- comm和bcomm区是公共区,用于存放用户代码和数据,它们是上电时加载并且一直驻留在RAM中的。
- stack区通常用于栈操作,长度为1K。
- data段包含了初始化的数据。
- heap段则用于动态内存分配(尽管蓝讯SDK可能不支持malloc/free)。
- aram, bram, cram, dram, eram, 和 fram可能是不同类型的RAM复用方式。
优化公共区的方法包括检查512字节的对齐是否必要,查看map.txt文件找出占用空间的代码,以及尝试将部分代码移动到其他未充分利用的RAM区域。
1.3 map.txt文件
map.txt 文件是软件开发过程中的一种映射文件,它通常由编译器或链接器生成,详细列出了编译后的程序各个部分在内存中的分布情况。在中科蓝讯的蓝牙方案中,map.txt 文件对于分析和优化COM区的空间使用非常关键。你可以通过以下步骤使用和分析这个文件:
- 打开 map.txt 文件:使用文本编辑器打开此文件,它将列出程序的所有段(如.text, .data, .bss等)以及它们的地址和大小。
- 查找占用空间的函数或模块:在文件中搜索关键字,例如“com”,“public”,或者特定函数名,找出占用com区空间的部分。
- 分析内存分配:检查各个段的起始地址和长度,了解哪部分代码占据了最多的RAM空间。
- 识别可优化部分:确定哪些函数或模块不是必需的,或者可以通过优化减少其大小。
- 调整代码:根据分析结果,禁用不必要的宏定义,删除冗余代码,或者将某些部分移到其他区域(如BANK区),然后重新编译。
- 验证优化效果:重新生成 map.txt 文件,对比优化前后com区的占用变化。
二、通过 ram.ld 和 map.txt文件,查看代码在CPU Ram中的占用情况
下面,我们通过一个实例进行分析:
例如我们灯效代码段命名为 lamp_rgb,下一步,在LD文件中,将lamp_rgb段添加到ram的一段空间内:
可以看到,我将lamp_rgb段放到了 Ram的comm1段,让灯效上电时加载后,一直驻留在RAM中。
然后我们在LD文件中搜索 comm1这个ram的公共段,查看这个comm1的空间分配情况:
从上图我们可以看出,comm1段在RAM中的起始地址为 0x24000,占用大小为32kByte(16进制:0x8000),所以,可用范围:0x24000~0x2c000
在清楚上面的信息后,我们就可以通过map文件查看代码在RAM中的使用情况了
如下图,我们先在map文件中搜索comm1,找到comm1段,再找到comm1段下的lamp_rgb段,当然,你也可以直接搜索lamp_rgb段:
以 .lamp_rgb.eff段为例:
可以看到,目前 .lamp_rgb.eff段占用RAM大小为0x2194字节(8K+Byte)
三、通过 分析 map.txt文件,节省用户代码对RAM空间的消耗
有了前几个小节对RAM空间分布的认识,我们试着优化下代码,看能不能省点RAM空间出来:
如上图,左边是.lamp_rgb.eff段占用RAM大小为0x2194字节的代码,在这个灯效模式中,所有用到的变量都是单独初始化,我们直接改用memset函数一次性初始化,然后再编译看看map文件有什么不同:
从上面对比数据可知,优化后的代码.lamp_rgb.eff段占用0x2178字节,较原来省了0x16字节的空间。
四、分析 map.txt文件中的字节对齐
例如前面lamp_rgb段末尾出现的 0x000000000002be00 . = ALIGN (0x200)
在计算机编程和链接器脚本中,0x000000000002be00 是一个内存地址,而 . = ALIGN (0x200) 是用于对齐内存位置的指令。这里是对这段语句的一个解释:
- 0x000000000002be00: 这是一个十六进制数,表示当前的数据或代码将被放置在内存中的这个位置开始。
- . = ALIGN (0x200): 这条指令意味着当前的段(通常是数据段或者代码段)将会被调整到下一个 0x200(即 512 字节)的边界。这意味着如果当前地址不是 512 字节的倍数,它会被增加到最近的512字节倍数的位置。这样做通常是为了优化处理器的性能,因为某些处理器在访问对齐的内存时效率更高。
因此,如果当前的地址 0x000000000002be00 不是 512 字节的倍数,那么. = ALIGN (0x200) 将会把地址向后调整到下一个 512 字节的边界。
五、RAM空间溢出分析
如下图,是编译时RAM爆空间后的错误信息提示:
可以看到,提示说.comm1段溢出了512字节,让我们来看看map文件的描述:
可以看到,.comm1段的大小已经到0x2c200 byte了,结合前面内容得知,comm1段最大0x2c000字节,现在超了0x200字节,刚好是512字节。
解决办法如下:
1、结合用户代码段(例如lamp_rgb段)的占用大小,看看有无其它RAM段可以放得下的,放到其它空间足够的段。
2、优化代码,将没用到的变量、函数等删除或注释,换更省RAM空间的写法。
六、代码优化 省RAM空间
未完待续~~
七、通过app.lst文件查看程序运行流程
芯片启动流程: