• 本教程适⽤于泰凌微 B85m 系列芯片
  • B85m SDK V3.4.2.4及之后版本的 SRAM 空间分配与之前版本的分配原理上是一样的,只是为了节省空间,将原来的固定16K/32K retention size 修改为实际使用的 retention size
  • 下面以 SRAM size 64K的IC:8258为例详细介绍 SRAM 区域各个部分。如果 SRAM size 是其他值,用户类推即可。


如上图所示:

  • Flash 中 Firmware 包括 vectorramcoderetention_datatextrodatadata initial value
  • SRAM 中包括 vectorramcoderetention_dataCachedatabssdata no initial valuesdk_versionstackunused SRAM area
  • SRAM 中的 vector/ramcode/ retention_data 是 Flash 中 vector/ramcode/retention_data 的拷贝。

vectors and ram_code

  • “vectors”段是汇编文件 cstartup_8258_RET_16K.S 对应的程序,是软件启动代码(software bootloader)。
  • “ramcode” 段是 Flash Firmware 中需要常驻内存的 code,对应 SDK 中所有加了关键字 “attribute_ram_code” 的函数。函数常驻内存有两个原因:一是某些函数由于涉及到和 Flash MSPI 四根管脚的时序复用,必须常驻内存,如果放到 flash 中就会出现时序冲突,造成死机,如flash操作相关所有函数;二是放到 RAM 中执行的函数每次被调用时不需要从 flash 重新读取,可以节省时间,所以对于一些执行时间有要求的函数可以放到常驻内存,提高执行效率。SDK 中将 BLE 时序相关的一些经常要执行的函数常驻到内存,大大降低执行时间,最终达到节省功耗。用户如果需要将某个函数常驻内存,可以仿照上面 flash_erase_sector,在自己的函数上添加关键 “attribute_ram_code”,编译之后就能在list文件中看到该函数在 ramcode 段了。
  • Firmware 中的 vector 和 ramcode 都需要在 MCU 上电时全部搬到 RAM 上,编译之后,这两部分加起来的 size 为 ramcode_size_。_ramcode_size 是一个编译器能够认识的变量值,它的计算实现在 boot.link 中,编译的结果 ramcode_size 等于 vector 和 ramcode 所有 code 的 size。

retention_data

B85m 的 deepsleep retention mode 支持 MCU 进入 retention 后,SRAM 的前16K/32K可以不掉电保持住 SRAM 上的数据不丢失。程序中的全局变量如果直接编译的话,会分配在 “data” 段或 “bss” 段,这两段的内容不在前16K的 retention 区域,进入 deepsleep retention 后会掉电丢失。如果希望一些特定的变量在 deepsleep (deepsleep retention mode) 期间能够不掉电保存,只要将它们分配到 “retention_data” 段即可,方法是在定义变量时添加关键字 “_attribute_data_retention_”。

Cache

Cache 是 MCU 的指令高速缓存,且必须被配置为 SRAM 中的一段才可以正常运行。Cache size 是固定的,包括256字节的 tag 和2048字节的 Instructions cache,总共0x900 = 2.25K。常驻内存的 code 可以直接从 SRAM 中读取并执行,但 firmware 中可以常驻 SRAM 的 code 只是一部分,剩下绝大部分都还在 Flash 中。根据程序的局部性原理,可以将一部分 Flash code 存储到 Cache 中,如果当前需要执行的 code 在 Cache 里,直接从 Cache 读取并执行;如果不在 Cache 中,则从Flash 读取 code 并搬到 Cache,再从 Cache 中读取执行。Firmware 的 ”text” 段是没有放到 SRAM 中,这部分 code 符合程序局部性原理,需要一直被 load 到 Cache 中才能被执行。Cache 大小是固定的2.25K,新版本中,“Cache” 段配置到 retention_data 后面,即起始地址为 _retention_data_size_align_256_。

data / bss

“data” 段是 SRAM 中存放程序已经初始化的全局变量,即 initial value 非0的全局变量。“bss” 段是 SRAM 中存放程序未初始化的全局变量,即 initial value 为0的全局变量。这两部分是连在一起的,data 段后紧跟 bss 段,所以这里作为一个整体介绍。“data” + “bss” 段紧跟 Cache,起始地址即Cache 的结束地址,新版本中,“data”起始地址为Cache的结束地址 0x840900 + (retention_data_size_align_256)。

data_no_init

为了节省 retention 部分的RAM,我们增加了这一个段。这个段的特点是:其在 RAM 中,却不在 retention 段,此部分的变量初始值为随机值。这个段是 SDK 做优化时使用的,不推荐用户使用。如果真的想要在应用中用到这个段,需要保证:变量在使用之前一定赋过值,且在赋值与使用之间不能经过 deep retention/deep/reboot/重新上电 等。

stack / unused area

对于默认64K的 SRAM ,”stack” 是从最高地址0x850000(48K SRAM对应地址为0x84C000,32K SRAM对应地址为0x848000)开始的,其方向为从下往上延伸,即 stack 指针 SP 在数据入栈时自减,数据出栈时自加。默认情况下,SDK library 使用了 stack 的 size 不超过256 byte,但由于 stack 的使用 size 取决于 stack 最深位置的地址,所以最终 stack 的使用量跟用户上层的程序设计是有关的。如果用户使用了比较麻烦的递归函数调用,或者在函数里使用了比较大的局部数组变量,或者其他有可能造成 stack 比较深的情况,都会导致最终 stack 的使用 size 变大。当用户的 SRAM 使用较多时,需要明确知道自己的程序使用了多少 stack,这个无法通过 list 文件来分析,用户可以使能 cstartup_825x.S/cstartup_827x.S 中的 FLL_STK_EN,此功能是将 data 段和 bss 段到 SRAM最高地址填充为 0xFF,被使用的 SRAM 空间则会被改写。让应用程序运行起来之后,将MCU reset,读取 SRAM 空间去确定 stack 的使用量。
“unused area” 即 bss 段结束地址与 stack 最深地址之间剩余的空间。只有当这个空间存在时,才说明 stack 没有和 bss 冲突,SRAM 使用没有问题。如果 stack 最深的地方和 bss 段重合了,则说明 SRAM 不够用了。

text

“text” 段是 Flash Firmware 中所有非 ram_code 函数的集合。程序中的函数如果加了 “_attribute_ram_code_”,会被编译为 ram_code 段,其他没有加这个关键字的函数就全部编译到了 “text” 段。一般情况下,”text” 段是 Firmware 中最大的空间,远大于 SRAM 的 size,所以需要通过 Cache 的缓存功能,将需要执行的 code 先 load 到 Cache 中再可以被执行。

rodata /data init value

“rodata” 段是程序中定义的可读、不能改写的数据,是用关键字 “const” 定义的变量。
“data init value” 段是程序中已初始化的全局变量。

sdk_version

“sdk_version” 段为 SDK V3.4.2.4 开始新添加的一个段,主要用于存储版本号信息,在程序编译时会输出版本号信息。

参考来源:https://doc.telink-semi.cn/doc/zh/software/res/sdk/ble/b85m_ble_cn/b85m_ble_single_connection_cn/#mcu