大致的流程图如下:
上电后RESET,ARM核开始执行Boot ROM,具体操作有:(代码固化在ROM中)
1、 初始化内置SRAM堆栈
2、 初始化nand/emmc(手机内置存储)
3、 把nand内存储的Pre-loader导入SRAM中
4、 跳到SRAM中执行Pre-loader
在内置SRAM中执行Pre-loader操作:(到bootloader/preloader下进行操作)<代码都在preloader目录下面>
1、配置c运行环境(寄存器、堆栈、BSS等) BSS静态内存段(未初始化)、数据段(初始化)、堆段、栈段
2、初始化外部DRAM的timer、时钟、UART、EMI(DRAM防静电干扰)
3、跳到DRAM执行LK(little kernel)<LK代码被调到DRAM中>
具体源码如下:
先执行一个ld链接脚本——显示一部分(在bootable/bootloader/preloader平台的link_descriptor.ld文件)
OUTPUT_ARCH(arm)
ENTRY(_start) //进入_start执行
romBase = 0x00201000;
ramBase = 0x00102180;
MEMORY {
ram : ORIGIN= ramBase, LENGTH = 0xBA80
rom : ORIGIN= romBase, LENGTH = 0x1F000
}
_start在init.s中位置,在ld里面定义c运行环境 (c运行环境(寄存器、堆栈、BSS等)地址)在这里被初始化
.globl _start
_start:
b resethandler
… … …
resethandler: //进行reset操作,并disable irq
LDR r6,=bldr_args_addr
STR r4, [r6]
MOV r0, #0
… … … …
LDR r0, =bldr_args_addr //跳转操作,bldr_args_addr地址在之前有定义
B main
进入main.c文件执行main操作
void main(u32 *arg){
mtk_uart_init(UART_SRC_CLK_FRQ, CFG_LOG_BAUDRATE);
bldr_pre_process(); //外部RWAM的timer、时钟、UART设置
bldr_handshake(&handler); //UART、USB握手测试(保证可以通信)
bldr_load_images; //导入Uboot镜像(镜像地址在此函数内的addr有定义)
bldr_post_process();
bldr_jump(jump_addr,jump_arg, sizeof(boot_arg_t)); //跳转到DRAM执行
}
在跳转到DRAM执行LK时,传递了参数哪些参数呢?
bldr_jump(jump_addr, jump_arg, sizeof(boot_arg_t));
1、jump_addr跳转到LK执行的地址
2、向LK传递参数的地址
3、传递参数的大小
传递了一个boot_arg_t 结构的数据,这个结构数据定义在platform.c的platform_set_boot_args()函数下定义
在LK里面进行外设的初始化,加载内核并启动android系统初始化等操作,具体如下: