Arm 使用FreeRTOS的微控制器上未静态分配的RAM会发生什么情况

Arm 使用FreeRTOS的微控制器上未静态分配的RAM会发生什么情况,arm,embedded,microcontroller,freertos,Arm,Embedded,Microcontroller,Freertos,我正在用FreeRTOS做一个嵌入式项目,我只使用静态内存分配 查看我的链接器脚本,我发现以下内容占用了RAM空间: .data .bss \u用户\u堆\u堆栈 据我所知,链接过程中使用了\u user\u heap\u stack,以查看是否有足够的RAM空间用于用户指定的最小MSP堆栈大小。以下是我的链接器脚本中的一个相关片段: /* User_heap_stack section, used to check that there is enough RAM left */ ._

我正在用FreeRTOS做一个嵌入式项目,我只使用静态内存分配

查看我的链接器脚本,我发现以下内容占用了RAM空间:
.data
.bss
\u用户\u堆\u堆栈

据我所知,链接过程中使用了
\u user\u heap\u stack
,以查看是否有足够的RAM空间用于用户指定的最小MSP堆栈大小。以下是我的链接器脚本中的一个相关片段:

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM
我相信MSP总是被初始化为指向RAM的末尾,而不管它的最小堆栈大小如何,并且从那里开始递减,数据被推送到堆栈上。我看到我的启动
.S
文件将
sp
配置如下:

_estack = 0x20004000;    /* end of RAM */

Reset_Handler:
  ldr   sp, =_estack    /* Atollic update: set stack pointer */
至于FreeRTOS任务,它们每个都有静态分配的堆栈空间,所以这与
\u user\u heap\u stack
无关


我的问题是,在分配了RAM
.data
.bss
\u user\u heap\u stack
的情况下,我仍然有一些未分配的RAM,那么这些RAM会怎么样?有人用它吗?保留一些空闲RAM(即非静态分配的RAM)有用吗?还是只是浪费?或者,如果主堆栈的大小超过了
\u Min\u stack\u size

TL中指定的大小,那么它可能只是MSP使用的额外空间;DR-剩余的RAM由堆栈使用


或者,如果主堆栈的大小比_Min_stack_size中指定的要大,那么它可能只是MSP可以使用的额外空间

是的,这似乎是正确的。详见最后一段;不仅仅是堆栈更大

见:这部分,

_estack = 0x20004000;    /* end of RAM */

Reset_Handler:
  ldr   sp, =_estack    /* Atollic update: set stack pointer */
因此,至少引导sp将位于RAM的末尾

具有
=.+_最小堆栈大小只需确保堆栈最小,否则会发生链接器错误。您的堆栈实际上更大,并且至少在启动时使用它。我对FreeRTOS一无所知,但我怀疑这是系统堆栈,你有用户堆栈。ARM上的每个模式都有一个单独的堆栈。如果FreeRTOS有任何内存保护或特权级别,那么您将有多个堆栈。因此,一个任务崩溃(由于堆栈溢出等原因)不会使整个系统崩溃。只是tasksnote2堆栈已损坏,而不是管理整个系统的堆栈

将堆栈和堆放在一起是一个常见的习惯用法。堆向上,堆向下。这样,最小堆大小和最小堆栈大小都是虚构的。最终,当两者的大小都是总大小时,它们将发生碰撞。但是,如果堆栈进入堆逻辑空间或堆进入堆栈逻辑空间,只要它没有被另一个使用,事情可能会好起来。我所说的空格是指链接器文件中的常量,而不是实际使用中的值

注1:既浪费内存,又让RTOS代码与所有任务使用相同的堆栈,这有点疯狂。至少它不是一个健壮的操作系统


注2:我所说的任务是指一个可调度的实体。可能是进程、任务、线程、光纤等。

TL;DR-剩余的RAM由堆栈使用


或者,如果主堆栈的大小比_Min_stack_size中指定的要大,那么它可能只是MSP可以使用的额外空间

是的,这似乎是正确的。详见最后一段;不仅仅是堆栈更大

见:这部分,

_estack = 0x20004000;    /* end of RAM */

Reset_Handler:
  ldr   sp, =_estack    /* Atollic update: set stack pointer */
因此,至少引导sp将位于RAM的末尾

具有
=.+_最小堆栈大小只需确保堆栈最小,否则会发生链接器错误。您的堆栈实际上更大,并且至少在启动时使用它。我对FreeRTOS一无所知,但我怀疑这是系统堆栈,你有用户堆栈。ARM上的每个模式都有一个单独的堆栈。如果FreeRTOS有任何内存保护或特权级别,那么您将有多个堆栈。因此,一个任务崩溃(由于堆栈溢出等原因)不会使整个系统崩溃。只是tasksnote2堆栈已损坏,而不是管理整个系统的堆栈

将堆栈和堆放在一起是一个常见的习惯用法。堆向上,堆向下。这样,最小堆大小和最小堆栈大小都是虚构的。最终,当两者的大小都是总大小时,它们将发生碰撞。但是,如果堆栈进入堆逻辑空间或堆进入堆栈逻辑空间,只要它没有被另一个使用,事情可能会好起来。我所说的空格是指链接器文件中的常量,而不是实际使用中的值

注1:既浪费内存,又让RTOS代码与所有任务使用相同的堆栈,这有点疯狂。至少它不是一个健壮的操作系统


注2:我所说的任务是指一个可调度的实体。可能是进程、任务、线程、光纤等。

如果您可以验证代码中没有任何内容与之接触,那么代码中也没有任何内容与之接触(尽管通常情况下,C启动例程会在幕后将其归零)。有时使用的一种技术是使用一个神奇的值(可能通过修改启动代码来实现,而不是零)预先填充内存,运行一段时间,然后返回,然后查看发生了什么变化;问题是,这只显示您实际执行的代码路径的行为。有时,出于捕获溢出的希望,会将保护值放在已使用的值之间并进行检查,理论上,强制重新启动比在损坏状态下运行更好;但同样,这只会在事物主动变更时捕获它们,并且只有在检查程序及时看到它的情况下才会捕获。magic value方法是否通常假定一个活动的调试器连接?我设想您使用调试器运行代码,然后在使用调试器一段时间后返回并检查内存内容。如果我在现场部署系统,并且没有活动的调试连接,这将如何工作