ST意法半导体
直播中

叹久

9年用户 828经验值
擅长:可编程逻辑 光电显示 接口/总线/驱动
私信 关注
[问答]

求一个可用的工作示例来处理STACK和HEAP的解耦?

我有一个关于 STM32CubeIDE 生成的链接描述文件的一般性问题。
大多数情况下,STACK 和 HEAP 一起放置在“相同”的内部 SRAM 中(参见 .user_heap_stack 示例部分以进行演示)。
注意:是的,区域有可能重叠,但这是我不想在这里讨论的事情。
._user_heap_stack :
{
  . =对齐(8);
  提供(结束=。);
  提供 (_end = .);
  . =。+ _Min_Heap_Size;
  . =。+ _Min_Stack_Size;
  . =对齐(8);
} > RAM_D1
我想将一些关键数据、静态变量等以及 STACK 指针放入 DTCRAM 区域。然而,堆在我们的应用程序中并没有被如此频繁地使用,因此我想把它放在一个较慢的区域,例如 RAM_D2/3。
我想这应该是可能的,对吧?
如果我这样做,我假设我可以摆脱链接描述文件中的“. = . + _Min_Stack_Size;”语句,因为堆栈现在与堆分离了?
此外,我假设我还需要修改 sbrk() 函数,它是 malloc 调用的基本部分,因为对从 STACK handling 派生的链接器符号有一些依赖性。那是对的吗?
我们是否有一个可用的工作示例来处理 STACK 和 HEAP 的解耦?









回帖(1)

潘璐

2022-12-9 11:08:27
你解决了吗?


  • 只修改链接器脚本应该是可能的。
  • 无需接触启动代码或 sysmem.c (_sbrk)。
  • ST 没有针对此用例的示例。
  • 您可以去掉 _Min_Stack_Size 符号。但是,如果您根据对堆栈使用的“最佳猜测”修改了该符号,那么保留该符号以获取静态链接时间检查 .data、.bss 和堆栈是否适合 RAM 会很有用。

要解决您的问题,您需要内存组 RAM_D1 用于数据/bss/堆栈,然后可能是 RAM_D2 用于堆。像这样拆分你的链接描述文件
确保堆栈指针设置在 RAM_D1 的末尾:


  • _estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1);    /* end of RAM_D1 */

将堆和堆栈的输出部分拆分为两个输出部分:


  • ._user_heap:
  • {
  •     . = ALIGN(8);
  •     PROVIDE ( end = . );
  •     PROVIDE ( _end = . );
  •     . = . + _Min_Heap_Size;
  •     . = ALIGN(8);
  • } > RAM_D2



  • ._user_stack :
  • {
  •     . = ALIGN(8);
  •     . = . + _Min_Stack_Size;
  •     . = ALIGN(8);
  • } > RAM_D1

注意:_bsrk 内存模型假设数据是这样排序的:
最低地址 最高地址
.data .bss newlib 堆栈
查看 sysmem.c 中的第 68-73 行:


  •   /* Protect heap from growing into the reserved MSP stack */
  •   if (__sbrk_heap_end + incr > max_heap)
  •   {
  •     errno = ENOMEM;
  •     return (void *)-1;
  •   }

我假设您计划用于堆的 RAM_D2 或 RAM_D3 位于内存空间中比 RAM_D1更高的地址?结果,上面代码块中的 if 语句将为真,_sbrk() 将无法分配内存!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分