U-BOOT启动流程之一

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, _fiq

undefined_instruction:     .word undefined_instruction

software_interrupt:  .word software_interrupt

prefetch_abort:.word prefetch_abort

data_abort:             .word data_abort

not_used:        .word not_used

irq:                 .word irq

fiq:                 .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_START
IRQ_STACK_START:
   .word     0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_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          0x15300000
060 # define INTMSK           0x14400008   /* Interupt-Controller base addresses */
061 # define CLKDIVN   0x14800014   /* clock divisor register */
062 #else
063 # define pWTCON          0x53000000
064 # define INTMSK           0x4A000008  /* Interupt-Controller base addresses */
065 # define INTSUBMSK     0x4A00001C
066 # define CLKDIVN   0x4C000014  /* clock divisor register */
067 # endif
069     ldr    r0, =pWTCON
070     mov   r1, #0x0
071     str    r1, [r0]
072     /*
073      * mask all IRQs by setting all bits in the INTMR - default
074      */
075     movr1, #0xffffffff
076     ldr  r0, =INTMSK
077     str  r1, [r0]
084 #if defined(CONFIG_S3C2440)
085     ldr  r1, =0x7fff
086     ldr  r0, =INTSUBMSK
087     str  r1, [r0]
088 #endif
089 #if defined(CONFIG_S3C2440)
090 #define MPLLCON    0x4C000004
091 #define UPLLCON 0x4C000008
092     ldr  r0, =CLKDIVN
093     movr1, #5
094     str  r1,[r0]
095     
096     mrc p15,0,r1,c1,c0,0
097     orr  r1,r1,#0xc0000000
098     mcrp15,0,r1,c1,c0,0
100     ldr  r0, =MPLLCON
101     ldr r1, =0x7F021
102     str  r1,[r0]
104     ldr  r0,=UPLLCON
105     ldr  r1,=0x38022
106     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寄存器设置

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值