This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

STM32启动代码启动相关的讨论

有些问题疑惑了很久,过来问下amanda_s,也希望大家都能够讨论、相互学习下。

STM32F4在MDK-ARM中的启动代码是这样的:

定义了READWRITE属性的栈区;定义了READWRITE属性的堆区;定义了READWRITE属性的异常向量表;定义了READONLY属性的异常向量处理函数,和一个堆栈的初始化汇编代码。

1.假设从用户flash启动,硬件加电稳定后,系统从0x00出获取了MSP,接着PC读取了Reset_Handler的地址值(还未开始执行)。

我的问题是:此时内核直接读取了Flash是吗?

我的理解是内核直接通过地址总线读取了0x00处的sp,和0x04处的一个地址(就是复位向量地址值)。

2.系统通过PC的值开始执行如下代码(songbin,如何添加带有格式的代码啊?)

Reset_HandlerPROC
             EXPORT  Reset_Handler         [WEAK]
    IMPORT  SystemInit
    IMPORT  __main
             LDR R0, =SystemInit
             BLX R0
             LDR R0, =__main
             BX  R0
             ENDP

可以看到系统会转向执行SystemInit,在SystemInit中,会调用SystemInit_ExtMemCtl(我用了外部的SDRAM)。

我的问题是:此时在SystemInit及其迭代调用的任何函数中不能出现任何的C语言相关的变量,如果全局的、局部的等,因为此时还未初始化C语言需要的堆、栈等必须的配置。是这样的吗?

我看到,有些局部的变量被定义为了 register uint32_t index;这说明还是在直接使用寄存器,并未使用C相关的东西。

3.接着系统调用了__main,我在《Libraries and Floating-Point Support User Guide》找到了__rt_entry、__initial_sp等编译器相关的库函数,但是唯独没有找到__main的详细说明,这是为什么、在哪可以找到?

我在"Initialization of the execution environment and execution of the application"小结中,找到了如下内容

The entry point of a program is at __main in the C library where library code:

Copies non-root (RO and RW) execution regions from their load addresses to their execution addresses. Also, if any data sections are compressed, they are decompressed from the load address to the execution address.

Zeroes ZI regions.

Branches to __rt_entry.

这个__main也可以自己写,它主要是为了C语言能够执行,完成对内存的初始化等。

__rt_entry是这样说明的:

The library function __rt_entry() runs the program as follows:

  1. Sets up the stack and the heap by one of a number of means that include calling __user_setup_stackheap(), calling __rt_stackheap_init(), or loading the absolute addresses of scatter-loaded regions.

  2. Calls __rt_lib_init() to initialize referenced library functions, initialize the locale and, if necessary, set up argc and argv for main().

    For C++, calls the constructors for any top-level objects by way of __cpp_initialize__aeabi_.

  3. Calls main(), the user-level root of the application.

    From main(), your program might call, among other things, library functions.

  4. Calls exit() with the value returned by main().

__rt_entry()完成了堆栈的初始化、初始化C/C++库,并转向C的main函数开始用户程序代码,如果main返回则调用exit(),但exit()干什么了不知道?如果用户从main中返回,那么是否从exit()也返回了,这样代码就回到了Reset_Handler,此时系统应该是停止了吧?

另外,在调用main之前,都不应该使用C相关的变量分配,因为在main之前还未对C/C++的库运行做好准备,是吧?