U-BOOT启动流程之一

来源:互联网 发布:excel查找重复数据 编辑:程序博客网 时间:2024/05/22 03:12

U-boot的启动流程


u-boot的作用主要是初始化一部分硬件,设置堆栈,然后把U-boot自身代码搬运到sdram当中运行.

U-BOOT的启动分为两个部分.

第一部分

(1)   初始化一部分硬件,比如关闭watch dog,中断等

(2)   搬运u-boot自身代码到sdram

(3)   设置堆栈sp

(4)   跳到启动代码的第二部分开始执行(C语言部分)

第二部分

(1)   初始化需要用到的硬件,比如tty,flash,i2c总线

(2)   加载kernelsdram中。

(3)   设置内核启动的参数。

(4)   调用内核。

总的来说,分为这几个步骤,调用内核后,就会开始执行内核部分代码

系统上电后会从0x00000000地址处执行代码

cpu的目录下,有几种类型的的CPU,比如arm920T,arm720T,我使用的开发板为s3c2440,CPUarm920T,arm920T目录下有个uboot的链接文件u-boot.lds.其代码如下

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{      . = 0x00000000;      . = ALIGN(4);      .text :      {             cpu/arm920t/start.o      (.text)             board/samsung/Ethan2440/lowlevel_init.o (.text)             board/samsung/Ethan2440/nand_read.o (.text)             *(.text)      }       ...............}

这里面的地址有两个,一个是链接文件(u-boot.lds)中的开始地址是0x0,代码段应该是从0地址开始运行,另一个\board\samsung\Ethan2440\config.mk中的代码段的链接地址。查看system.map可以看出代码段是0x33f80000开始链接的,那么代码怎么会在0x0中运行?查了一些资料,个人理解如下:如果理解透彻的可以讨论一下,这里面的使用的跳转指令ldr,bl,adr应该和地址是无关的,是基于PC指针偏移的,start.s,lowlevel_init.s,nand_read.s才参在系统刚启动的时候代码段得以运行,从而实现把"自身"搬运到0x33f80000的地址处。

globl _start/*跳到start_code处开始执行代码.使用b跳转后,是不会再跳回来了*/start: b      start_code/*把标号放到pc寄存器中执行*/  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, _fiqundefined_instruction:     .word undefined_instructionsoftware_interrupt:  .word software_interruptprefetch_abort:.word prefetch_abortdata_abort:             .word data_abortnot_used:        .word not_usedirq:                 .word irqfiq:                 .word fiq/* 定义一个4字节的函数名来初始,比如undefined_instuction,下面是个函数名,同理其它的也是一样. */.balignl 16,0xdeadbeef

这里面的汇编使用采用AT&T语法,globllinux下汇编的关键字, .global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用._start就是一个标号,也可以说是一个地址.

/**_TEXT_BASE用TEXT_BASE来初始化, TEXT_BASE的值是多少呢,经过自己查找,在board/Samsung/smdk2410下的config.mk, TEXT_BASE = 0x33F80000。*/_TEXT_BASE:   .word     TEXT_BASE.globl _armboot_start_armboot_start:   .word _start/* * These are defined in the board-specific linker script. *//**_bss_start,_bss_end初始化,它们在哪儿定义,它们的值是多少呢,可以在cpu/arm920t/u-boot.lds中查到.它的值是多少呢,自己计算吧.*/.globl _bss_start_bss_start:   .word __bss_start.globl _bss_end_bss_end:  .word _end#ifdef CONFIG_USE_IRQ/* IRQ stack memory (calculated at run-time) */.globl IRQ_STACK_STARTIRQ_STACK_START:   .word     0x0badc0de/* IRQ stack memory (calculated at run-time) */.globl FIQ_STACK_STARTFIQ_STACK_START:   .word 0x0badc0de#endif

(1)下面是代码真正开始执行的部分,上面是一些变量的定义及初始化

 start_code:   /*   * set the cpu to SVC32 mode   */   mrs r0,cpsr   bic  r0,r0,#0x1f   orr  r0,r0,#0xd3   msr cpsr,r0

第1mrs,cpsr是什么,查一下汇编指令, MSR指令用于将操作数的内容传送到程序状态寄存器的特定域中,这里面的程序状态寄存器可以是cpsr,spsr.所以这里面,是把cpsr的值放到了r0.

第2bic指令是把r0#0x1f取反后相与,也就是把后5位清零.可以查一下bic指令的用法.

第3orr指令是把r0#0xd3相或,前面已经把后5位清0,这里面后5位就是0xd3.

第4msrmrs相对应的,r0的值传送到cpsr,这四句代码到底是做什么的,看上面的注释就知道是把cpu设置成管理模式的,哪怎么设置的呢,自己查的,你也可以查

CPSR格式如下所示。SPSRCPSR格式相同。

 31 30 29 28 27 26            7 6 5 4 3 2 1 0

 N Z C V Q DNM(RAZ) I F T M4 M3 M2 M1 M0

这里面我们重点关注后面8,因为我们的是0xd3,也就11010011,对应上面的,I位和F位置1,也就禁止IRQFIQ中断,哪后的10011,就是管理模式了.

(2)watch dog中断及分频的设置

058 # if defined(CONFIG_S3C2400)059 # define pWTCON          0x15300000060 # define INTMSK           0x14400008   /* Interupt-Controller base addresses */061 # define CLKDIVN   0x14800014   /* clock divisor register */062 #else063 # define pWTCON          0x53000000064 # define INTMSK           0x4A000008  /* Interupt-Controller base addresses */065 # define INTSUBMSK     0x4A00001C066 # define CLKDIVN   0x4C000014  /* clock divisor register */067 # endif069     ldr    r0, =pWTCON070     mov   r1, #0x0071     str    r1, [r0]072     /*073      * mask all IRQs by setting all bits in the INTMR - default074      */075     movr1, #0xffffffff076     ldr  r0, =INTMSK077     str  r1, [r0]084 #if defined(CONFIG_S3C2440)085     ldr  r1, =0x7fff086     ldr  r0, =INTSUBMSK087     str  r1, [r0]088 #endif089 #if defined(CONFIG_S3C2440)090 #define MPLLCON    0x4C000004091 #define UPLLCON 0x4C000008092     ldr  r0, =CLKDIVN093     movr1, #5094     str  r1,[r0]095     096     mrc p15,0,r1,c1,c0,0097     orr  r1,r1,#0xc0000000098     mcrp15,0,r1,c1,c0,0100     ldr  r0, =MPLLCON101     ldr r1, =0x7F021102     str  r1,[r0]104     ldr  r0,=UPLLCON105     ldr  r1,=0x38022106     str  r1,[r0]107 #endif   /* CONFIG_S3C2400 || CONFIG_S3C2410 */

 63-67行分别用宏定义了watchdog intmask等寄存器的地址,datasheet看寄存器的地址.

69-71行把watchdog的寄存器设为0,关闭watchdog。

75-77行是设置INTMSK寄存器,屏蔽掉所有中断,设为0xffffffff。

85-87行也是屏蔽中断。

90-91行分别对MPLLUPLL的宏定义,MPLL用于定义FCLK,HCLK,PCLK,FCLK用于CPU,HCLK用于AHB总线上的设备.比如,中断控制器,LCD控制器,DMA.PCLK用于APB总线上的设备,WATCHDOG,,IIS,I2C,PWM定时器等.UPLL主要USB设备

92-94行设置CLKDIVN寄存器,这个寄存器用于设置FCLK HCLK PCLK三者的比例,这里CLKDIVN的值为5,根据samsung手册,5101,10HCLK=FCLK/4,最后一位的1,PCLK=HCLK/2,所以FCLK:HCLK:PCLK=1:4:8.

96-98行这段代码没有研究,参考了别人的,s3c2440,如果HDIVN0,则由fast bus mode变为asynchronous bus mode.

100-102行是对MPLL寄存器的设置,这里面设置0x7F021。

104-106行对UPLL寄存器设置

 

原创粉丝点击