u-boot详细解析
来源:互联网 发布:php 执行shell命令 编辑:程序博客网 时间:2024/04/30 06:37
对于Uboot移植工作,有一些技术细节可能不需要我们搞特别清楚,但是通过分析Uboot源码,可以让我们对uboot整个架构有一个清晰的认识,在进行uboot移植的过程中可以有一个清晰的思路。
u-boot 源码目录
平台相关
Arch
Board
Include
平台无关
Api
Common
Disk
Doc
Drivers
Dts
Examples
Fs
Lib
Net
Post
Spl
Test
tools
u-boot 的启动分为两个阶段:
u-boot第一阶段 :
u-boot 的入口是由链接脚本决定的, uboot 下 armv7 链接脚本默认目录为arch/arm/cpu/u-boot.lds ,从下图可以看出,第一个链接的是 CPUDIR/start.o ,其对应的代码为 arch/arm/cpu/armv7/start.S
ENTRY() 和 ENDPROC() 分别为汇编函数的入口和出口
arch/arm/cpu/armv7/start.S :
设置异常向量表:
//ldr指令是将寄存器装载指令,将内存中的地址的内容装载到PC寄存器中。
看到上电后 u-boot 会进入 reset 函数:
可以看到进入 reset 函数后,会先进入 save_boot_params 函数
注意到 save_boot_params 函数中没有进行任何操作,直接返回了,注释告诉我们栈指针还没有初始化,不能向栈中保存
任何数据。
值得注意的是 .weak 伪操作: .weak save_boot_params
可以理解为如果定义了 save_boot_params 这个函数,那么久调用它,如果没有定义,就定义它,具体可以参考http://blog.chinaunix.net/uid-25358071-id-309285.html
然后 reset 函数执行下面的指令:
reset:
bl save_boot_params
ldr r0, =0x44e10884
ldr r1, =0x10
str r1,[r0]
/* * set the cpu to SVC32 mode */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
设置了 CPSR 寄存器为 d3 ,使得 CPU 进入 SVC 模式,并禁止中断, CPSR 寄存器详情查看《 ARM 基础知识》
这个时候可以用汇编代码进行点灯,确定代码确实运行到这一步:
#if 1
ldr r0, =0x11000c40 @GPK2_7 led2
ldr r1, [r0]
bic r1, r1, #0xf0000000
orr r1, r1, #0x10000000
str r1, [r0]
ldr r0, =0x11000c44
mov r1,#0xff
str r1, [r0]
#endif
接着调用cpu_init_crit函数,禁止MMU,禁止caches等工作
bl cpu_init_crit
cpu_init_crit:
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
#ifdef CONFIG_SYS_ICACHE_OFF
bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
#else
orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
#endif
mcr p15, 0, r0, c1, c0, 0
/*
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
mov ip, lr @ persevere link reg across call
bl lowlevel_init @ go setup pll,mux,memory
mov lr, ip @ restore link
mov pc, lr @ back to my caller
#endif
lowlevel_init.S (mcu-uboot-wk\arch\arm\cpu\armv7\ti81xx)
这个函数就和具体的硬件有关系了,我所使用的单板是Nor flash
.globl lowlevel_init
lowlevel_init:
/* The link register is saved in ip by start.S */
mov r6, ip
/* check if we are already running from RAM */
ldr r2, _lowlevel_init
ldr r3, _TEXT_BASE
sub r4, r2, r3
sub r0, pc, r4
/* require dummy instr or subtract pc by 4 instead i'm doing stack init */
ldr sp, SRAM_STACK
mark1:
ldr r5, _mark1
sub r5, r5, r2 /* bytes between mark1 and lowlevel_init */
sub r0, r0, r5 /* r0 <- _start w.r.t current place of execution */
mov r10, #0x0 /* r10 has in_ddr used by s_init() */
#ifdef CONFIG_NOR_BOOT
cmp r0, #0x08000000 /* check for running from NOR */
beq ocmc_init_start /* if == then running from NOR */
在这个函数中进行了总线的初始化以及一些GPIO的初始化操作,我们可以根据具体的硬件需求添加一些自定义的代码
#ifdef CONFIG1_SPL_BUILD
ands r0, r0, #0xC0000000 /* MSB 2 bits <> 0 then we are in ocmc or DDR */
cmp r0, #0x40000000 /* if running from ocmc */
beq nor_init_start /* if == skip ocmc init and jump to nor init */
将Nor flash中的代码拷贝到Ram中继续执行
nor_init_start:
/* gpmc init */
bl cpy_nor_gpmc_code /* copy nor gpmc init code to sram */
mov r0, pc
add r0, r0, #12 /* 12 is for next three instructions */
mov lr, r0 /* gpmc init code in sram should return to s_init_start */
ldr r0, sram_pc_start
mov pc, r0 /* transfer ctrl to nor_gpmc_init() in sram */
#endif
#endif
mov r10, #0x01 /* if <> we are running from DDR hence skip ddr init */
/* by setting in_ddr to 1 */
b s_init_start /* and jump to s_init */
s_init_start:
mov r0, r10 /* passing in_ddr in r0 */
bl s_init
/* back to arch calling code */
mov pc, r6
/* the literal pools origin */
.ltorg
然后跳转到中执行
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
bl board_init_f
Board.c (mcu-uboot-wk\arch\arm\lib)
函数作用是:对 gd 结构体( include/asm/global_data.h )进行设置,进行各种初始化
gd->mon_len = (ulong)&__bss_end - (ulong)_start;
初始化 mon_len ,代表 uboot code 的大小。
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
这些函数中有很多与硬件有关,比如串口
init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init, /* basic arch cpu dependent setup */
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
timer_init, /* initialize timer */
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init, /* configure available RAM banks */
NULL,
};
接着会执行
relocate_code(addr_sp, id, addr); 代码自搬移
stack_setup //设置堆栈
copy_loop //
clear_bss //清BSS段
jump_2_ram
_board_init_r_ofs
.word board_init_r - _start //最终跳转到board_init_r执行后续程序,也就是第二阶段
U-boot第二阶段 Board.c (mcu-uboot-wk\arch\arm\lib),这阶段的代码与硬件关系很大,uboot的移植工作主要在此处,包括网卡初始化,串口初始化,中断初始化,中断使能,环境变量的初始化等工作。
void board_init_r(gd_t *id, ulong dest_addr)
{
enable_caches();
board_init(); /* Setup chipselects */
…
flash_size = flash_init();
env_relocate(); /* initialize environment ,初始化环境变量*/
gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr"); /* IP Address */
stdio_init(); /* get the devices list going. */
console_init_r(); /* fully init console as a device */
interrupt_init(); /* set up exceptions */
enable_interrupts()/* enable exceptions */
eth_init(gd->bd); /*初始化网卡*/
/*最终进入死循环,进入uboot的主函数*/
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop();
}
}
Main.c (mcu-uboot-wk\common)
board_init_r进行完板级初始化后最后进入死循环,打印命令行,等待命令输入和解析。到这里uboot的启动过程就全部结束了!
void main_loop (void)
{
bootcount = bootcount_load(); /*uboot的倒计时*/
bootcount++;
bootcount_store (bootcount);
sprintf (bcs_set, "%lu", bootcount);
setenv ("bootcount", bcs_set);
bcs = getenv ("bootlimit");
bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;
update_tftp (0UL); //tftp
if (len == -1) //执行相关命令
puts ("<INTERRUPT>\n");
else
rc = run_command (lastcommand, flag);
if (rc <= 0) {
/* invalid command or not repeatable, forget it */
lastcommand[0] = 0;
}
}
- u-boot详细解析
- U-BOOT mkconfig文件详细解析
- u-boot 详细介绍
- u-boot 详细介绍
- u-boot 详细介绍 .
- U-BOOT详细讲解
- u-boot解析
- U-boot源码解析
- u-boot配置文件解析
- mt7620 u-boot解析
- U-boot环境变量解析
- u-boot移植详细文档
- u-boot详细命令集!
- u-boot移植详细文档
- U-boot 移植问题解析
- u-boot mkconfig文件解析
- u-boot链接脚本解析
- u-boot的main_loop解析
- zepto之tap事件点透问题分析及解决方案
- Mybatis初步建立与实现
- metlab 4
- scala--9--内部类
- ubuntu: apt-get update的时候遇到“Hash Sum mismatch”错误
- u-boot详细解析
- 学术笔记·2015 IWA Alternative Water Resources Conference·十
- 题目1070:今年的第几天? 九度OJ
- 【机器学习 基本概念】隐马尔可夫模型
- 搜索专题训练hdu4403A very hard Aoshu problem
- 在Excel表格中,通过公式查询数据并在另外一个文档中保存
- 【SpringMVC+mybatis】2.mybatis框架原理
- WSAM_GPU
- 题目1186:打印日期 九度OJ