start.S进一步、更详细的、深入的解释和分析 2013.04.26更新(四)

转自:http://zqwt.012.blog.163.com/blog/static/12044684201332662650711/

 

l   下面这几行代码的作用是定义了一些宏,给寄存器赋值(其实赋的是寄存器的地址),以后会用到

#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

l   下面这里就是所谓的关闭看门狗

l   看门狗即watchdog timer,是一个定时器电路,一般有一个输入叫喂狗,一个输出叫MCU(Micro Controller Unit多点控制单元)的RST端(复位端)。MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给WDT(watchdog timer abbreviation)清零,如果超过规定的时间不喂狗(一般在程序跑飞时,会发生这种情况,此时WDT规定的时间被超过),RST就给出一个复位信号到MCU,然后MCU复位。很明显,看门狗的作用就是防止程序发生死循环或者等待超时的情况下进行主控的复位操作。寄存器具体怎么设置,可以根据S3C2410的用户手册来实现。

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

      ldr     r0, =pWTCON   // 还是把寄存器pWTCON的地址装载到r0中

      mov   r1, #0x0     // 给r1清零,关闭看门狗定时器

      str     r1, [r0]

/* 上面几行中,把r1中的数据(全0)装载

*(存储)到寄存器[r0]所包含的有效地址,

* 即给寄存器WTCON清零,目的是关闭看门狗 */

 

l   禁止所有中断(第一个要修改的地方

       /*

        * mask all IRQs by setting all bits in the INTMR - default

        */

      mov      r1, #0xffffffff

      ldr  r0, =INTMSK   //是不是把INTMSK的地址0X4A000008存储在r0中

       str  r1, [r0]   //把r1中的数据存储在寄存器[r0]所包含的有效地址,屏蔽所有中断源

 

# if defined(CONFIG_S3C2410)

      ldr  r1, =0x3ff   // 0x3ff =00111111    (0x3ff =0000 0011 1111 1111 --转者)

      ldr  r0, =INTSUBMSK

      str  r1, [r0]

# endif

这是S3C2410参考手册中列出的中断控制器(Interrupt Controller)表格:

start.S进一步、更详细的、深入的解释和分析 2013.04.26更新(四) - U-BOOT - 少即是多,慢即是快!

l   设置时钟频率(第二个要修改的地方

S3C2410用户手册推荐FLCK:HCLK:PCLK=1:2:4,其中FCLK默认是120MHz,通常FCLK用于CPU,HCLK用于AHB总线,PCLK用于APB总线,具体实现如下:

       /* FCLK:HCLK:PCLK = 1:2:4 */

       /* default FCLK is 120 MHz ! */

      ldr  r0, =CLKDIVN

      mov      r1, #3  //0011 HDIVN=1;PDIVN=1

      str  r1, [r0]

#endif   /* CONFIG_S3C2400 || CONFIG_S3C2410 */

 

l   /* we do sys-critical inits only at reboot, not when booting from ram! */

我们只在系统reboot的时候做一些至关重要的系统初始化,而不在从sram启动的时候做这件事情。

B 转移指令,跳转到指令中指定的目的地址,BL 带链接的转移指令,像B一样跳转,但是会把转移后面紧接的一条指令地址保存到链接寄存器LR(R14)中,以此来完成子程式的调用。

该语句首先调用cpu_init_crit进行CPU的初始化,并把下一条指令的地址保存在LR中,以使得执行完后能够正常返回。

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

      bl   cpu_init_crit   //跳转(第三个要修改的地方

#endif

 

l   下面这段代码的作用是所谓搬运代码(把uboot拷贝到DDR中去执行),即重定向(第四个要修改的地方

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate:                       /* relocate U-Boot to RAM      */

      adr r0, _start         /* r0 <- current position of code  */

//_start为当前程序的入口地址

      ldr  r1, _TEXT_BASE      /* test if we run from flash or RAM */

//_TEXT_BASE为uboot从SDRAM中开始执行的基地址(加载地址)

      cmp     r0, r1                  /* don't reloc during debug  */

//我们的目的就是把uboot从当前的地址_start

//拷贝到sdram中的所谓基地址_TEXT_BASE=0x33f80000)

/* 要调用C子程序,必须分配堆栈空间。因为子程序调用时,

* 要进行入栈出栈处理。又因为从nand flash启动,

* 而nand flash在S3C2410下的特点规定堆栈不能超过4K。

*/

       beq   stack_setup  // 如果r0等于r1(入口地址等于加载地址),那么就先去设置堆栈,再回来搬运代码(重定向) (原文中说明错误,此处判断如果r0==r1,即执行地址_start与加载地址_TEXT_BASE相同,就直接跳到设置堆栈(stack_setup),不用再搬运代码(重定向)。从前文注释“don't reloc during debug  ”可推断,debug过程中应该是从ram启动,不需要relocate  --转者)

      ldr  r2, _armboot_start  //堆栈

//_armboot_start 目前的值为uboot的入口地址

       ldr  r3, _bss_start

// _bss_start为uboot代码存放的结束地址,也是BSS段的起始地址

      sub r2, r3, r2          /* r2 <- size of armboot            */

// 让r3和r2做算数减法的目的是计算出uboot镜像的大小

       add r2, r0, r2         /* r2 <- source end address         */

 

l   下面这几行代码是一个循环,做的事儿就是所谓的搬运代码,这里有条指令ldmia,解释如下:

start.S进一步、更详细的、深入的解释和分析 2013.04.26更新(四) - U-BOOT - 少即是多,慢即是快!
多寄存器传输——数据块操作

start.S进一步、更详细的、深入的解释和分析 2013.04.26更新(四) - U-BOOT - 少即是多,慢即是快!

多寄存器传输——数据块操作


start.S进一步、更详细的、深入的解释和分析 2013.04.26更新(四) - U-BOOT - 少即是多,慢即是快!

start.S进一步、更详细的、深入的解释和分析 2013.04.26更新(四) - U-BOOT - 少即是多,慢即是快!
 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值