定义ARM MCU内存边界

时间:2015-06-30 13:04:44

标签: c linker embedded stm32 freertos

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

当我想让项目更复杂(更多的任务,队列等)时,我有点不高兴,因为我可能开始不得不进一步减少堆栈以允许.bss适合的部分。

所以我的问题是 - 这样做的解决方案是将.bss部分扩展到.data部分(上面的部分),以便在{中允许更多堆和未初始化的数据{1}}部分?根据VisualGDB的Memory Explorer窗口,经过一些环顾和实验,我发现实际上只有大约1%(如果没有,更少)的.bss部分被使用了。建立时间,拥有所有未使用的RAM似乎很疯狂。

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

以下是我认为链接器脚本中的相关部分:

.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 = .);

1 个答案:

答案 0 :(得分:0)

我认为您无法明确设置.bss.data部分的大小。它仅由您的程序定义。您可以查看每个变量从map-file消耗的内存量。

示例:

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

在我的配置中使用

配置的FreeRTOS
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 40 * 1024 ) )

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

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

您不能将.bss“扩展”到.data部分,因为前者由未初始化的静态分配变量占用,后者由初始化的静态分配变量占用。如果你可以摆脱一些静态分配的变量(例如全局变量),你的.bss或/和.data部分大小将会减少。 8 KB的RAM不是很多。

也许您应该在链接器脚本中查找._user_heap_stack部分(或类似名称)并优化堆(不要与FreeRTOS堆混淆)和堆栈大小值。例如。如果你只使用FreeRTOS内存分配,那么你可以将堆大小设置为0,这将为.bss部分留出更多空间。

从我的项目:

_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