STM32的C环境准备
stm32 startup.s文件用于准备C语言运行的环境。主要是SP指针 堆栈设置。
- 初始化芯片的寄存器:启动文件会初始化芯片的各种寄存器,使芯片处于正确的状态,各种外设也能正常使用。
- 设置堆和栈的初始值:堆和栈是在内存中分配给程序使用的两个区域,启动文件会设置它们的初值和大小。
- 初始化中断向量表:中断向量表是一张存放中断处理程序地址的表,启动文件会把中断向量表复制到内存中,并把中断向量表的地址写入NVIC寄存器。
- 配置系统时钟:启动文件会配置系统时钟,根据芯片的型号和外部晶振的频率,设置CPU时钟、总线时钟和外设时钟。
- 跳转至主程序:在复位中断中服务程序中跳转执行C标准库main函数,以上这些完成后,跳转到主程序中的main函数执行相关函数应用。
IMX6的C环境准备
是由U-BOOT完成的。 在U-boot 启动的一系列调用中的lowlevel_init 函数内容如下:
#include <asm-offsets.h>
15 #include <config.h>
16 #include <linux/linkage.h>
17
18 ENTRY(lowlevel_init)
19 /*
20 * Setup a temporary stack. Global data is not available yet.
21 */
22 ldr sp, =CONFIG_SYS_INIT_SP_ADDR
23 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
24 #ifdef CONFIG_SPL_DM
25 mov r9, #0
26 #else
27 /*
28 * Set up global data for boards that still need it. This will be
29 * removed soon.
30 */
31 #ifdef CONFIG_SPL_BUILD
32 ldr r9, =gdata
33 #else
34 sub sp, sp, #GD_SIZE
35 bic sp, sp, #7
36 mov r9, sp
37 #endif
38 #endif
39 /*
40 * Save the old lr(passed in ip) and the current lr to stack
41 */
42 push {ip, lr}
43
44 /*
45 * Call the very early init function. This should do only the
46 * absolute bare minimum to get started. It should not:
47 *
48 * - set up DRAM
49 * - use global_data
50 * - clear BSS
51 * - try to start a console
52 *
53 * For boards with SPL this should be empty since SPL can do all
54 * of this init in the SPL board_init_f() function which is
55 * called immediately after this.
56 */
57 bl s_init
58 pop {ip, pc}
59 ENDPROC(lowlevel_init)
- 第 22 行设置 sp 指向 CONFIG_SYS_INIT_SP_ADDR
CONFIG_SYS_INIT_RAM_ADDR = IRAM_BASE_ADDR = 0x00900000。
CONFIG_SYS_INIT_RAM_SIZE = 0x00020000 =128KB。
CONFIG_SYS_INIT_SP_OFFSET = 0x00020000 – 256 = 0x1FF00。
CONFIG_SYS_INIT_SP_ADDR = 0x00900000 + 0X1FF00 = 0X0091FF00
SP指向内部的RAM
- 第 23 行对 sp 指针做 8 字节对齐处理!
- 第 34 行,sp 指针减去 GD_SIZE,GD_SIZE 同样在 generic-asm-offsets.h 中定了,大小为248
- 第 35 行对 sp 做 8 字节对齐,此时 sp 的地址为 0X0091FF00-248=0X0091FE08,此时 sp 位置如图 32.2.2.2 所示:
- - 第 36 行将 sp 地址保存在 r9 寄存器中。
- 第 42 行将 ip 和 lr 压栈
- C运行环境准备完毕!!
- 第 57 行调用函数 s_init,这个函数开始U-BOOT开始出现C语言代码执行。
- 第 58 行将第 36 行入栈的 ip 和 lr 进行出栈,并将 lr 赋给 pc。
STM32与IMX6 代码运行的不同
stm32代码一般是在内部flash运行和存储。取值-译码-执行 的三级流水线。
IMX6的代码存储和运行不在一个位置。存储在ROM中 运行时需要搬运到ram中运行。
所以IMX6准备运行环境时比STM32多一个代码搬运的步骤。
STM32 与 IMX6上电过程对比
项目 | STM32 | IMX6U |
---|---|---|
boot 阶段 | 根据BOOT0/1引脚选择代码位置直接执行代码 | 原厂固化在ROM的代码,根据BOOT_MOD引脚的配置来决定从哪个存储介质中读取U-Boot的映像 ,搬运到内存中后开始执行 |
引导阶段 | IAP程序 的startup文件 使用默认的中断向量表初始化系统时钟后如果没有在线更新则跳转到下一个程序 | U-boot 重新设置中断向量表并开始进一步的硬件初始化和配置。这可能包括设置时钟、初始化内存控制器、配置外设。最后将linux代码搬到内存中开始执行 |
引导阶段 | IAP程序可以提供一些调试接口,该阶段所有外设可用 | U-boot 提供调试接口,所有外设可用 |
APP启动 | startup文件 重新设置中断向量表 main函数进行初始化后,RTOS启动 | LINUX启动,目前尚不清楚细节 |