2.11.4. __user_initial_stackheap()

__user_initial_stackheap() 返回初始堆栈和堆的位置。

在 RVCT 2.x 及更早版本中,__user_initial_stackheap() 的缺省实现使用符号 Image$$ZI$$Limit 的值。 如果链接器使用分散加载描述文件(使用 --scatter 命令行选项指定),则不会定义该符号;因此,如果使用的是分散加载描述文件,则必须重新实现 __user_initial_stackheap(),否则,链接步骤将会失败。

在 RVCT 3.x 版中,库包含额外的 __user_initial_stackheap() 实现,并且可通过分散加载描述文件中提供的信息自动选择正确的实现。 这意味着,如果使用的是分散加载文件,则不需要重新实现该函数。 有关详细信息,请参阅使用分散加载描述文件

Note

如果重新实现 __user_initial_stackheap(),这将覆盖所有库实现。 这样,现有应用程序无需更改即可使用。

语法

__value_in_regs  struct __initial_stackheap __user_initial_stackheap(unsigned R0, unsigned SP, unsigned R2);

用法

__user_initial_stackheap() 返回:

  • r0 中的堆基址

  • r1 中的堆栈基址,即堆栈区中的最高地址

  • r2 中的堆限制

  • r3 中的堆栈限制,即堆栈区中的最低地址

如果重新实现了此函数,则必须满足以下条件:

  • 最多使用堆栈中的 88 个字节

  • 不能破坏 r12 (ip) 以外的寄存器

  • 保持堆的 8 字节对齐方式

对于缺省单区模型,将忽略 r2r3 中的值,并且 r0r1 之间的所有内存始终可供堆使用。 对于双区模型,堆限制是由 r2 设置的,堆栈限制是由 r3 设置的。

调用 __main() 时的 sp (r13) 值将作为 r1 中的自变量进行传递。 __user_initial_stackheap() 的缺省实现(使用半主机 SYS_HEAPINFO)是由 sys_stackheap.o 模块中的库提供的。

要创建从执行环境中继承 sp 并且不使用堆的 __user_initial_stackheap() 版本,请将 r0r2 设置为 r3 的值并返回。 有关详细信息,请参阅__user_setup_stackheap()

rt_misc.h 中的 __initial_stackheap 的定义是:

struct __initial_stackheap

{

    unsigned heap_base, stack_base, heap_limit, stack_limit;

}; 

Note

stack_base 的值比堆栈使用的最高地址大 0x1,这是因为使用的是满降序堆栈。

有关该函数的示例重新实现,请参阅示例目录。

返回值

r0r3 中返回的值取决于是使用单区内存模型,还是使用双区内存模型:

单区

(r0,r1) 是单个堆栈和堆区。r1 大于 r0,并忽略 r2r3

双区

(r0, r2) 是初始堆,(r3, r1) 是初始堆栈。r2 大于或等于 r0r3 小于 r1

使用分散加载描述文件

__user_initial_stackheap() 的缺省实现使用 Image$$ZI$$Limit 符号的值。 如果链接器使用分散加载描述文件,则不会定义此符号。 不过,C 库提供了替代实现,可通过分散加载描述文件中的信息来使用这些实现。

Note

如果重新实现 __user_initial_stackheap(),这将覆盖所有库实现。

自动选择单区模型

在分散加载描述文件中定义一个特殊执行区,即 ARM_LIB_STACKHEAP。 该区具有 EMPTY 属性。

这导致库选择一个 __user_initial_stackheap() 实现,它将该区用作复合堆/堆栈区。 它使用 Image$$ARM_LIB_STACKHEAP$$BaseImage$$ARM_LIB_STACKHEAP$$ZI$$Limit 符号的值。

自动选择双区模型

在分散加载描述文件中定义两个特殊执行区: ARM_LIB_HEAPARM_LIB_STACK。 两个区均具有 EMPTY 属性。

这导致库选择一个使用以下符号值的 __user_initial_stackheap() 实现:Image$$ARM_LIB_HEAP$$BaseImage$$ARM_LIB_HEAP$$ZI$$LimitImage$$ARM_LIB_STACK$$BaseImage$$ARM_LIB_STACK$$ZI$$Limit

Example 2.23 显示了一个用于定义 ARM_LIB_HEAPARM_LIB_STACK 的示例分散加载描述文件。 (它是在主示例目录 install_directory\RVDS\Examples 中作为 Cortex-M3.scat 提供的。)

Example 2.23. ARM_LIB_HEAP 和 ARM_LIB_STACK 分散加载描述


FLASH_LOAD 0x0000 0x00200000

{

  VECTORS +0 0x400

  {

    * (:gdef:__vectab_stack_and_reset, +FIRST)

    ; Additional region for other vectors would be added here

  }



  ;; Maximum of 256 exceptions (256*4bytes == 1024 == 0x400)

  CODE 0x400 FIXED

  {

    * (+RO)

  }



  DATA 0x20000000 0x00200000

  { 

    * (+RW, +ZI)

  }



  ;; Heap starts at 1MB and grows upwards

  ARM_LIB_HEAP 0x20100000 EMPTY 0x100000-0x8000

  {

  }



  ;; Stack space starts at the end of the 2MB of RAM

  ;; And grows downwards for 32KB

  ARM_LIB_STACK 0x20200000 EMPTY -0x8000

  {

  }

}

Example 2.23 中,__vectab_stack_and_reset 是一个特殊的库节,它为 Cortex-M3 嵌入式应用程序提供了一种简便方法,以将 sppc 的初始值放在起始地址为 0 的向量表中。将从 ARM_LIB_STACKHEAP(对于单区模型)或 ARM_LIB_STACK(对于双区模型)中对 sp 进行相应的初始化。

错误消息

如果使用分散文件,而没有指定任何特殊区名称,并且没有重新实现 __user_initial_stackheap(),库将生成一条错误消息。

Copyright © 2007 ARM Limited. All rights reserved. ARM DUI 0349AC
Non-Confidential