__user_initial_stackheap() RealView Compilation Tools for µVision Libraries and Floating Point Support Guide Version 4.0 Home > The C and C++ Libraries > Tailoring the runtime memory model > __user_initial_stackheap()
2.10.5. __user_initial_stackheap() __user_initial_stackheap()在旧程序中比较常见,该函数的最新替代函数为__user_setup_stackheap().
Migrating to RVCT v4.0 from RVCT v2.x and earlier RVCT v2.x 及之前的版本, Image$$ZI$$Limt的值决定是否调用__user_initial_stackheap()。如果开发人员使用scatter文件,那么 Image$$ZI$$Limt不会被定义,此时开发人员必须重新实现__user_initial_stackheap()的函数体,不然编译不会成功。
或者,在程序中可以用 __user_setup_stackheap() 来代替__user_initial_stackheap()。
Migrating to RVCT v4.0 from RVCT v3.x RVCT v3.x 及之后版本, µVision 库里包含了更多__user_initial_stackheap()的函数体,这样编译器可以根据开发人员scatter文件的内容自动选择合适的函数体。换句话说,针对RVCT v3.x及之后的版本,使用scatter文件的开发人员可以不再重新实现__user_initial_stackheap()的函数体。 See Using a scatter-loading description file for more information.
语法 extern __value_in_regs struct __user_initial_stackheap __user_initial_stackheap(unsigned R0, unsigned SP, unsigned R2, unsigned SL); 用法 __user_initial_stackheap() 的返回值规则:
堆底地址放在 r0,堆底指堆内最小地址
栈顶地址放在r1,栈顶指栈内最大地址
堆顶地址放在r2,堆顶指堆内最大地址
栈底地址放在 r3,栈底指栈内最小地址。
如果该函数函数体重新定义,必须遵循三点:
使用栈的字节数必须小于88 bytes
除了 r12 (ip)之外不能乱用别的寄存器
堆内需要保持8字节对齐。(栈里应该也需要,看KEIL的例程)
针对默认的 one-region 模型, r2 和 r3 中的值被忽略,r0 和 r1中存储的两个地址之间存储区都被堆所使用。针对 two-region 模型, 堆顶地址由 r2中的值决定,栈底地址由r3中的值决定。
当__main() 被调用时,sp (r13)的值会被作为参数传递到r1中。__user_initial_stackheap()的默认函数体由sys_stackheap.o目标提供( using the semihosting SYS_HEAPINFO) 。
To create a version of __user_initial_stackheap() that inherits sp from the execution environment and does not have a heap, set r0 and r2 to the value of r3 and return. See __user_setup_stackheap()) for more information.
rt_misc.h中__initial_stackheap 结构体的定义:
struct __initial_stackheap{ unsigned heap_base, stack_base, heap_limit, stack_limit; }; 注意 由于使用全递减栈,stack_base 的值等于栈内最高地址加0x1
See the examples directory for example reimplementations of this function.
返回值 使用One-region存储器模型或Two-region存储器模型决定r0 到 r3中的返回值 :
One-region
(r0,r1) 是单一的堆+栈区域. r1 大于 r0.,r2 和 r3 忽略。
Two-region (r0, r2) 分配为堆, (r3, r1) 分配为栈. r2 大于等于 r0. r3 小于 r1.
使用scatter-loading (分散加载)描述文件 默认__user_initial_stackheap() 函数体需要使用Image$$ZI$$Limt模型,如果开发人员使用scatter文件的话,Image$$ZI$$Limt模型不会被定义。然而, µVision 的C库里提供了一些__user_initial_stackheap() 的函数体,开发人员可以通过scatter文件中的内容来控制开发环境来调用具体哪一个函数体。
自动选择 one-region 存储器模型 在分散加载文件中定义一个特殊的执行域ARM_LIB_STACKHEAP.,给该域定义EMPTY 属性。
这样,编译器就会从库中选择一个__user_initial_stackheap() 的函数体以ARM_LIB_STACKHEAP为堆-栈合并域,这个函数体需要用到 Image$$ARM_LIB_STACKHEAP$$Base 和Image$$ARM_LIB_STACKHEAP$$ZI$$Limit两个模型。
自动选择 two-region 存储器模型 在分散加载文件中定义两个特殊的执行域,ARM_LIB_HEAP 和 ARM_LIB_STACK.,给这两个域都定义EMPTY 属性。
这样,编译器就会从库中选择一个用到 Image$$ARM_LIB_HEAP$$Base, Image$$ARM_LIB_HEAP$$ZI$$Limit, Image$$ARM_LIB_STACK$$Base, and Image$$ARM_LIB_STACK$$ZI$$Limit.四个模型的__user_initial_stackheap() 的函数体。
sp会通过ARM_LIB_STACKHEAP (one-region 存储器模型)或者 ARM_LIB_STACK (two-region 存储器模型)进行初始化。
错误信息 如果使用了scatter文件,但是没有在scatter文件中定义特定的域(ARM_LIB_STACKHEAP/ARM_LIB_HEAP 和 ARM_LIB_STACK),也没有重定义__user_initial_stackheap(),函数体,函数库在调试信息中报错。
Copyright © 2007, 2008 ARM Limited. All rights reserved. ARM DUI 0378B Non-Confidential Unrestricted Access Home > The C and C++ Libraries > Tailoring the runtime memory model > __user_initial_stackheap()
Copyright © Keil, An ARM Company. All rights reserved.
|