一些STM32 CPU包括两组存储器:标准SRAM和另一组存储器(又名CCM),它们可能比标准SRAM更快,通常更小。
为此,有几种可能性,具体取决于程序所需的内存量。在所有情况下,您可能需要手动编辑链接器脚本文件(LinkerScript.ld,link.lds 除非由 CubeMX 生成,其名称取决于芯片引用)。
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
然后,必须决定哪些部分必须放在 CCM 中。
} >RAM AT> FLASH
} >CCMRAM AT> FLASH
} >RAM
} >CCMRAM
可以将单个变量放在 CCRAM 区域中,尽管这可能有点复杂。
char in_ccram_buffer[1024] __attribute__((section("ccmram")));
如果存在,在链接器脚本中要注意不要将ythe变量初始化,即使初始化为零,因为它会占用flash中的空间;(可选)您可以在默认 .ccmram 节定义的末尾禁止显示 AT> FLASH 姿势。
默认情况下,按属性放置在 CCMRAM 中的变量无法初始化,甚至无法初始化为zero。
如果需要将它们初始化为zero,zero则必须修改startup_stm32xxxxx.S 文件,用于添加第二个zero-initialization 循环(使用符号 _sccmram 和 _eccmram),方法是复制 bss 的代码,紧跟在其最终的bcc FillZerobs 之后,将其修改为如下所示:ldr r2, =_sccmram
b LoopFillZeroCcm
/* Zero fill the ccmram segment. */
FillZeroCcm:
movs r3, #0
str r3, [r2]
adds r2, r2, #4
LoopFillZeroCcm:
ldr r3, = _eccmram
cmp r2, r3
bcc FillZeroCcm
反之,可以通过将初始化的变量放在 .ccmidata 部分中来创建初始化的 ccmram 数据部分。
必须首先通过以下方式在链接器脚本中定义此部分:_siccmram = LOADADDR(.ccmram); /* May be already present */
/* Initialized CCM-RAM section
*
* IMPORTANT NOTE!
* If initialized variables will be placed in this section,
* the startup code needs to be modified to copy the init-values.
*/
.ccmidata :
{
. = ALIGN(4);
_sccmidata = .; /* create a global symbol at data start */
*(.ccmidata) /* .data sections */
*(.ccmidata*) /* .data* sections */
. = ALIGN(4);
_eccmidata = .; /* define a global symbol at data end */
} >CCMRAM AT> FLASH
/* Copy the ccm segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyCcmInit
CopyCcmInit:
ldr r3, =_siccmdata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyCcmInit:
ldr r0, =_siccmdata
ldr r3, =_eiccmdata
adds r2, r0, r1
cmp r2, r3
bcc CopyCcmInit
最后,要将堆和堆栈放在 CCMRAM 中(可能在其他数据之后),只需要在链接器脚本中执行两个小的修改:
_estack = 0x20020000; /* end of RAM */
_estack = 0x10010000; /* end of CCMRAM */
#define CCMRAM __attribute__((section(".ccmram")))
CCMRAM int test[100];
int main()
{
for(int i = 0;i<100;i++)
{
test[i] = i;
printf(" %d ",test[i]);
}
}