《uboot启动之start.s分析》

原文链接:https://blog.csdn.net/itdo_just/article/details/78701886

 

以下源码以u-boot-1.1.6中的2440为例。

1.start.s的引入

board/smdk2240/u-boot.lds中可以看到ENTRY(_start),。Uboot整个程序的入口取决于链接脚本中ENTRY声明的地方。ENTRY(_start) 因此_start符号所在的文件就是整个程序的起始文件,_start所在处的代码就是整个程序的起始代码。

 

2.start.s分析

设置异常向量表

跳转reset

/*
  globl就是相当于C语言中的Extern,声明此变量,并且告诉链接器此变量是全局的,外部可以访问
  指定入口为_start
  u-boot.lds里面定义了ENTRY(_start),即指定入口为_start 
 */
.globl _start
_start:    b       reset
/*
  ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。
  比如想把数据从内存中某处读取到寄存器中,只能使用ldr
  将_undefined_instruction这个地址处的word(一字节)定义的值赋给pc。

  ARM体系结构规定在上电复位的起始位置必须有8条连续的跳转指令,
  通过硬件来实现。它们就是异常向量表。ARM在上电复位后是从0x0开始启动,
  如果bootloader存在,则是从_start开始执行上面的跳转没有执行。
  设置异常向量表的作用是识别bootloader,以后每当系统有异常出现时,
  cpu会根据异常号从内存0x0处开始查找并做相应的处理   
  下面8条即设置异常中断向量表
 */
   /*构建异常向量表*/
    ldr    pc, _undefined_instruction
    ldr    pc, _software_interrupt
    ldr    pc, _prefetch_abort
    ldr    pc, _data_abort
    ldr    pc, _not_used
    ldr    pc, _irq
    ldr    pc, _fiq

reset分析:

/*
 * the actual reset code
 */

reset:
/* 首先进入SVC管理模式,为什么要进行SVC管理模式而不是其它模式,主要因为SVC模式比其他模式有更多的硬件访问权限,
并且多了影子寄存器,可以访问的硬件资源更多,详情:http://www.360doc.com/content/13/0514/11/7245213_285318786.shtml */
/* * set the cpu to SVC32 mode */
/*
* MRS{条件} 通用寄存器,程序状态寄存器(CPSR或SPSR)
* mrs :程序状态寄存器访问指令
* 通用寄存器  程序状态寄存器(CPSR或SPSR)
* 读取CPSR程序状态寄存器,保存到R0中
*/
  
mrs    r0,cpsr
/*
 * bic :BIC{条件}{S} 目的寄存器,操作数1,操作数2,
 * BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中。操作数1应是一个寄存器
 * 操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。操作数2为32位的掩码,如果在掩码中设置了某一
 * 位,则清除这一位。未设置的掩码位保持不变。
 * 0x1f=00011111,相当于清除低5位,刚好是模式位。
 */ bic r0,r0,#
0x1f

/*
 * ORR{条件}{S} 目的寄存器,操作数1,操作数2
 * ORR指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。操作数1应是一个寄存器,操作数
 * 2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于设置操作数1的某些位。
 * 0xd3=11010011
 * 将r0与0xd3算数或运算,然后将结果给r0,即把r0的bit[7:6]和bit[4]和bit[2:0]置为1。
 */
   orr    r0,r0,#0xd3
 /*
  * MSR{条件} 程序状态寄存器(CPSR或SPSR)_<域>,操作数
  * MSR指令用于将操作数的内容传送到程序状态寄存器的特定域中
  * 将r0中的值赋给状态寄存器cpsr
  */
msr cpsr,r0 /* turn off the watchdog */ #if defined(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */ # define CLKDIVN 0x14800014 /* clock divisor register */ #elif defined(CONFIG_S3C2410) # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ #endif #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */ /* * we do sys-critical inits only at reboot, * not when booting from ram! */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit #endif #ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */ copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] */ stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop #endif /* CONFIG_SKIP_RELOCATE_UBOOT */ /* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* leave 3 words for abort-stack */ clear_bss: ldr r0, _bss_start /* find start of bss segment */ ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear */ clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 ble clbss_l #if 0 /* try doing this stuff after the relocation */ ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMR str r1, [r0] /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] /* END stuff after relocation */   #endif ldr pc, _start_armboot
/* 进入这个C函数后就属于第二阶段的代码了,汇编到此结束 */ _start_armboot: .word start_armboot

 设置SVC模式

关看门狗

屏蔽中断

初始化SDRAM

设置stack

设置时钟

重定位(代码从FLASH拷贝到内存中)(怎么拷贝)

清理BSS段()

调用start_armboot

以上完成得是硬件相关初始化,称为uboot的第一阶段。

猜你喜欢

转载自www.cnblogs.com/zhuangquan/p/11413200.html