通过《Cortex-M4设备通用用户指南》,可以在0x0中找到初始sp值。
通过startup_stm32l431xx。S,可以找到
Reset_Handler:
ldr sp, =_estack /* Set stack pointer */ //LDR loads a register with a value from a PC-relative memory address.The memory address is specified by a label or by an offset from the PC.
所以,我的问题是为什么在0x0中仍然有初始SP值,因为我们已经在startup_stm32l431xx中完成了初始SP值。我想是启动。S的工作之一是初始sp值)
既然我们总是在启动代码中设置sp,为什么我们仍然有一个地址0x0来存储初始sp值?
复位时SP的硬件初始化的目的是允许用C编写启动源代码-具有诸如不需要静态初始化或标准库初始化,以及入口点不是main()
的约束。
典型的Cortex-M启动为:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0;
ENDP
其中SystemInit
通常是具有相同约束的C函数,但是如果它直接通过重置向量运行,则必须负责调用__main
,创建一个包含SystemInit()
自己的堆栈帧的调用堆栈,该堆栈不能被运行时重用,直到从main()
返回,这将是不寻常的,通常是错误的。
因此,如果您正在运行一个完整的C运行时,main()
入口点而不是直接跳转到SystemInit()
以最大化可用的堆栈空间,那么这是有意义的,在这种情况下,假设所使用的构建工具在向量表中适当地设置初始SP是不明智的,因为一条指令一定要。
我从未见过Cortex-M能够直接引导到使用的C代码,但是对于没有C运行时库要求的非常简单的应用程序,它可能是有用的。
这是一个非常好的问题,我猜是这初始化是多余的,因为从0 x0包含_estack
,正如你提到的,和这个值将自动加载重置成sp
,同样pc
将装满addresseReset_Handler
:例如,手臂的等效代码编译器不包含任何额外的代码加载sp
:的gcc版本启动代码是唯一一个使用这样一个冗余的初始化:你可以比较gcc版本(我假设你引用的那个),arm版本和iar版本。