定义 ARM MCU 内存边界

Define ARM MCU memory boundaries

我正在开展一个项目,该项目涉及获取在 STM32F051C6 上运行的 FreeRTOS 的 CMSIS-RTOS 包。我在Visual Studio里面用VisualGDB编写和调试代码,用ST提供的STM32CubeMX工具生成项目代码。 RTOS 运行 非常好,我满脸笑容,但是,我添加了一个 queue 和一个内存池来处理任务之间的消息发送和接收,编译器抱怨 .bss compiled/generated 的内存部分不适合链接器中设置的内存部分。这已通过减少 FreeRTOS 配置中的堆大小解决 header.

当我想让项目更复杂(更多任务,queues 等)时,我对这可能会带我去哪里感到有点不高兴,因为我可能不得不进一步减少堆栈以让 .bss 部分适合。

所以我的问题是 - 解决这个问题的方法是将 .bss 部分扩展到 .data 部分(上面的部分)以允许更多堆和未初始化.bss 部分的数据? 经过一番观察和试验,我发现 .data 部分只有大约 1%(如果不是,更少)被实际使用,根据VisualGDB 的 Memory Explorer window 在构建时,拥有所有未使用的 RAM 似乎很疯狂。

为了自己尝试这样做,我仔细查看了链接器脚本和启动代码,但找不到在哪里定义 .bss 的开始和结束。 是否可以定义这些边界,如果可能,我将如何定义?如果不可能,链接器如何知道这些边界在目标芯片上的位置?

以下是我认为是链接描述文件中的相关部分:

.data :
{
    . = ALIGN(4);
    _sidata = .;

    _sdata = _sidata;

    PROVIDE(__data_start__ = _sdata);
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;

    PROVIDE(__data_end__ = _edata);
} > SRAM

.bss :
{
    . = ALIGN(4);
    _sbss = .;

    PROVIDE(__bss_start__ = _sbss);
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    _ebss = .;

    PROVIDE(__bss_end__ = _ebss);
} > SRAM

PROVIDE(end = .);

...和启动文件:

extern void *_sidata, *_sdata, *_edata;
extern void *_sbss, *_ebss;

void __attribute__((naked, noreturn)) Reset_Handler()
{
    //Normally the CPU should will setup the based on the value from the first entry in the vector table.
    //If you encounter problems with accessing stack variables during initialization, ensure 
    //asm ("ldr sp, =_estack");

    void **pSource, **pDest;
    for (pSource = &_sidata, pDest = &_sdata; pDest != &_edata; pSource++, pDest++)
        *pDest = *pSource;

    for (pDest = &_sbss; pDest != &_ebss; pDest++)
        *pDest = 0;

    SystemInit();
    __libc_init_array();
    main();
    for (;;) ;
}

我认为您不能明确设置 .bss.data 部分的大小。它仅由您的程序定义。您可以查看每个变量从映射文件中消耗了多少内存。

示例:

.bss.xHeap     0x0000000020000690     0xa000 obj/heap_2.o

在我的设置中,FreeRTOS 配置了

#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 40 * 1024 ) )

而且我在我的地图文件中看到了所有这 40 KB。

链接器知道您的 MCU 有多少内存,并尝试将所有内存对象放入其中。如果不合适,您会看到错误。

你不能"extend" .bss进入.data部分,因为前者被未初始化的静态分配变量占用,后者被初始化的静态分配变量占用。如果您可以摆脱一些静态分配的变量(例如全局变量),您的 .bss or/and .data 部分大小将会减少。 8 KB 的 RAM 不是很多。

也许您应该在链接描述文件中查找 ._user_heap_stack 部分(或类似名称)并优化堆(不要与 FreeRTOS 堆混淆)和堆栈大小值。例如。如果您仅使用 FreeRTOS 内存分配,那么您可以将堆大小设置为 0,这将为 .bss 部分允许更多 space。

来自我的项目:

_Min_Heap_Size = 0;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

._user_heap_stack :
{
  . = ALIGN(4);
  PROVIDE ( end = . );
  PROVIDE ( _end = . );
  . = . + _Min_Heap_Size;
  . = . + _Min_Stack_Size;
  . = ALIGN(4);
} >RAM