定义 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
我正在开展一个项目,该项目涉及获取在 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