uboot启动流程webee210启动第一阶段state_one
2015-12-16 16:38
302 查看
闲来无事,分析一下uboot的启动流程,板子是webee的210板子,虽然已经是流产的项目(自认为),但是板子是好使的。仔细分析一番了。
start.S (arch\arm\cpu\armv7) 是启动的第一个执行的文件(入口类似于main函数),210是基于armv7指令集的。
Webee210.h (include\configs) 里面定义了一些宏定义及和板级相关的配置,一般我们都要有属于板级的相关的一个.h文件。
看英文注释,就是关闭重要的寄存器,不需要关注,都是通用的。最重要的是跳转到了和板级相关的代码了。即lowlevel_init,当lowlevel_init执行完毕时回到调用cpu_init_crit函数的地方。在lowlevel_init.S (board\samsung\webee210)文件中。
@2:这个函数首先会判断是否处在是被唤醒还是的确是上电复位初始化。根据不同的状态来确定初始化的外设或者是直接跳转kernel;
@3:这个函数会进来两次(复位),第一次运行在初始化CPU的一小段内存中,第二次运行在Dram控制器的中的ram中。
具体的解释在以下这个网址http://www.cnblogs.com/Efronc/archive/2012/02/29/2373668.html
@4:最后回到start.s中。
回到调用cpu_init_crit的地方。然后顺序执行:
起初,是读取了当前代码运行的地址到r4,_TEXT_BASE是和硬件相关的地址,就是Dram的起始地址,将这个地址拷贝到r5,显然在第一阶段,当前的运行代码的地址是sram中,并非dram,好,往下走。
然后就去读取具体对应的启动选项,是mmc启动,还是nand启动,这里先已mmc/sd卡启动讲解,其实是一样的。跳转到Mmc_boot.c (arch\arm\cpu\armv7\s5pc1xx),
start.S (arch\arm\cpu\armv7) 是启动的第一个执行的文件(入口类似于main函数),210是基于armv7指令集的。
#include <asm-offsets.h> #include <config.h> #include <version.h> #include <common.h> #include <configs/webee210.h> #include <s5pc110.h> .globl _start //声明一个<span style="font-family: Arial, Helvetica, sans-serif;">_start的全局标识</span> _start: b reset //跳转到reset
Webee210.h (include\configs) 里面定义了一些宏定义及和板级相关的配置,一般我们都要有属于板级的相关的一个.h文件。
reset: bl save_boot_params //空函数 /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr,r0 //svc模式切换 #if defined(CONFIG_OMAP34XX) //<span style="font-family: Arial, Helvetica, sans-serif;">CONFIG_OMAP34XX没有定义</span> /* Copy vectors to mask ROM indirect addr */ adr r0, _start @ r0 <- current position of code add r0, r0, #4 @ skip reset vector mov r2, #64 @ r2 <- size to copy add r2, r0, r2 @ r2 <- source end address mov r1, #SRAM_OFFSET0 @ build vect addr mov r3, #SRAM_OFFSET1 add r1, r1, r3 mov r3, #SRAM_OFFSET2 add r1, r1, r3 next: ldmia r0!, {r3 - r10} @ copy from source address [r0] stmia r1!, {r3 - r10} @ copy to target address [r1] cmp r0, r2 @ until source end address [r2] bne next @ loop until equal */ #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT) /* No need to copy/exec the clock code - DPLL adjust already done * in NAND/oneNAND Boot. */ bl cpy_clk_code @ put dpll adjust code behind vectors #endif /* NAND Boot */ #endif /* the mask ROM code should have PLL and others stable */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit //会跳转到<span style="font-family: Arial, Helvetica, sans-serif;">cpu_init_crit</span> #endifreset其实就是切换到svc模式,然后跳转到cpu_init_crit。
#ifndef CONFIG_SKIP_LOWLEVEL_INIT /************************************************************************* * * CPU_init_critical registers * * setup important registers * setup memory timing * *************************************************************************/ 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,当lowlevel_init执行完毕时回到调用cpu_init_crit函数的地方。在lowlevel_init.S (board\samsung\webee210)文件中。
.globl lowlevel_init lowlevel_init: push {lr} /* check reset status */ ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) ldr r1, [r0] bic r1, r1, #0xfff6ffff cmp r1, #0x10000 beq wakeup_reset_pre cmp r1, #0x80000 beq wakeup_reset_from_didle /* IO Retention release */ ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET) ldr r1, [r0] ldr r2, =IO_RET_REL orr r1, r1, r2 str r1, [r0] /* Disable Watchdog */ ldr r0, =ELFIN_WATCHDOG_BASE /* 0xE2700000 */ mov r1, #0 str r1, [r0] /* SRAM(2MB) init for SMDKC110 */ /* GPJ1 SROM_ADDR_16to21 */ ldr r0, =ELFIN_GPIO_BASE ldr r1, [r0, #GPJ1CON_OFFSET] bic r1, r1, #0xFFFFFF ldr r2, =0x444444 orr r1, r1, r2 str r1, [r0, #GPJ1CON_OFFSET] ldr r1, [r0, #GPJ1PUD_OFFSET] ldr r2, =0x3ff bic r1, r1, r2 str r1, [r0, #GPJ1PUD_OFFSET] /* GPJ4 SROM_ADDR_16to21 */ ldr r1, [r0, #GPJ4CON_OFFSET] bic r1, r1, #(0xf<<16) ldr r2, =(0x4<<16) orr r1, r1, r2 str r1, [r0, #GPJ4CON_OFFSET] ldr r1, [r0, #GPJ4PUD_OFFSET] ldr r2, =(0x3<<8) bic r1, r1, r2 str r1, [r0, #GPJ4PUD_OFFSET] /* CS0 - 16bit sram, enable nBE, Byte base address */ ldr r0, =ELFIN_SROM_BASE /* 0xE8000000 */ mov r1, #0x1 str r1, [r0] /* PS_HOLD pin(GPH0_0) set to high */ ldr r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET) ldr r1, [r0] orr r1, r1, #0x300 orr r1, r1, #0x1 str r1, [r0] /* when we already run in ram, we don't need to relocate U-Boot. * and actually, memory controller must be configured before U-Boot * is running in ram. */ ldr r0, =0x00ffffff bic r1, pc, r0 /* r0 <- current base addr of code */ ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */ bic r2, r2, r0 /* r0 <- current base addr of code */ cmp r1, r2 /* compare r0, r1 */ beq 1f /* r0 == r1 then skip sdram init */ /* init system clock */ bl system_clock_init /* Memory initialize */ bl mem_ctrl_asm_init 1: /* for UART */ bl uart_asm_init bl tzpc_init #if defined(CONFIG_ONENAND) bl onenandcon_init #endif #if defined(CONFIG_NAND) /* simple init for NAND */ bl nand_asm_init #endif /* check reset status */ ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) ldr r1, [r0] bic r1, r1, #0xfffeffff cmp r1, #0x10000 beq wakeup_reset_pre /* ABB disable */ ldr r0, =0xE010C300 orr r1, r1, #(0x1<<23) str r1, [r0] /* Print 'K' */ ldr r0, =ELFIN_UART_CONSOLE_BASE ldr r1, =0x4b4b4b4b str r1, [r0, #UTXH_OFFSET] pop {pc}@1:总的来说这一个函数时用来初始化和CPU相关的东西,包括clock,串口,Dram控制器;
@2:这个函数首先会判断是否处在是被唤醒还是的确是上电复位初始化。根据不同的状态来确定初始化的外设或者是直接跳转kernel;
@3:这个函数会进来两次(复位),第一次运行在初始化CPU的一小段内存中,第二次运行在Dram控制器的中的ram中。
具体的解释在以下这个网址http://www.cnblogs.com/Efronc/archive/2012/02/29/2373668.html
@4:最后回到start.s中。
回到调用cpu_init_crit的地方。然后顺序执行:
/* 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 #if defined(CONFIG_WEBEE210) || defined(CONFIG_MINI210) adr r4, _start ldr r5,_TEXT_BASE cmp r5,r4 beq board_init_in_ram ldr r0, =PRO_ID_BASE ldr r1, [r0,#OMR_OFFSET] bic r2, r1, #0xffffffc1 /* NAND BOOT */ cmp r2, #0x0 @ 512B 4-cycle moveq r3, #BOOT_NAND cmp r2, #0x2 @ 2KB 5-cycle moveq r3, #BOOT_NAND cmp r2, #0x4 @ 4KB 5-cycle 8-bit ECC moveq r3, #BOOT_NAND cmp r2, #0x6 @ 4KB 5-cycle 16-bit ECC moveq r3, #BOOT_NAND cmp r2, #0x8 @ OneNAND Mux moveq r3, #BOOT_ONENAND /* SD/MMC BOOT */ cmp r2, #0xc moveq r3, #BOOT_MMCSD /* NOR BOOT */ cmp r2, #0x14 moveq r3, #BOOT_NOR /* Uart BOOTONG failed */ cmp r2, #(0x1<<4) moveq r3, #BOOT_SEC_DEV ldr r0, =INF_REG_BASE str r3, [r0, #INF_REG3_OFFSET] ldr r1, [r0, #INF_REG3_OFFSET] cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */ beq nand_boot_210 cmp r1, #BOOT_MMCSD beq mmcsd_boot_210 nand_boot_210: bl board_init_f_nand mmcsd_boot_210: bl board_init_f board_init_in_ram: #endif bl board_init_f /*------------------------------------------------------------------------------*/
起初,是读取了当前代码运行的地址到r4,_TEXT_BASE是和硬件相关的地址,就是Dram的起始地址,将这个地址拷贝到r5,显然在第一阶段,当前的运行代码的地址是sram中,并非dram,好,往下走。
然后就去读取具体对应的启动选项,是mmc启动,还是nand启动,这里先已mmc/sd卡启动讲解,其实是一样的。跳转到Mmc_boot.c (arch\arm\cpu\armv7\s5pc1xx),
void board_init_f(unsigned long bootflag) { __attribute__((noreturn)) void (*uboot)(void); copy_uboot_to_ram(); /* Jump to U-Boot image */ uboot = (void *)CONFIG_SYS_TEXT_BASE; (*uboot)(); /* Never returns Here */ }干了一件事情,就是拷贝uboot的代码到sdram中,然后从首地址重新启动。其中CONFIG_SYS_TEXT_BASE是和硬件相关的,主要看dram控制器连接的外部ram方式。webee的是0x33E00000,uboot指向了这个地址,然后呢,重新回到原点运行。
相关文章推荐
- struts2_03 自定义类型转换器 拦截器
- lazyload.js详解
- iOS Block界面反向传值
- SQL SERVER 并发【2015.12.16】
- PDO浅谈之php连接mysql
- listview默认选择第一项,点击换子项背景图
- MySQL中LIKE子句相关使用的学习教程
- Crazy Android Note Chapter-9
- 关于AJAX请求时 加入 进度条
- Mybatis-3.0.6如何采用多个配置文件,模块化,降低耦合度
- Tesseract-OCR引擎 使用方法入门
- Java中使用Jedis操作Redis
- CSS3 实现背景透明,文字不透明,兼容所有浏览器
- 推荐系统学习:协同过滤实现
- xampp配置
- AFNetworking
- CentOS 6.5 安装 MySQL cluster 7.4.8 的安装配置
- Mac OS X 10.10 启用 Web 服务器
- 微信公众号开发官方定制ui
- 判断字符串是否有中文或者BASIC_LATIN编码