首页 > 代码库 > U-BOOT第一阶段程序分析(1)

U-BOOT第一阶段程序分析(1)

       分析移植之前先介绍下我的软硬件环境:
       开发板:JZ2440v2板
       CPU   :ARM920T
       SOC   :S3C2440
       晶振freq:12MHz
       NorFlash:2MB => Am29LV160DB
       NandFlash:256MB => K9F2G08U0A
       SDRAM:32MB X 2pieces => K4S561632H-T(U)C(16M X 16bit)
       U-BOOT版本:u-boot-1.1.6.tar.bz2
       我移植的uboot是基于nand启动的,所以代码的分析过程也是基于nand启动的情况,uboot一上电首先执行的是cpu/arm920t/start.s文件。下面我从该文件开始一步步按代码流程分析:
	1. start.s中用到的头文件
      	#include <config.h>  // 等效包含#include <configs/MY_JZ2440.h>
        #include <version.h> // 等效包含#include "version_autogenerated.h" 
        2. 加入LED灯调试宏定义,这个是我个人在移植的时候加的,在初始化串口之前你无法用printf调试,所以在uboot的第一阶段一般会用汇编点灯的手段去调试程序。
        #define DEBUG_LED 0  //0表示该调试已经被我关闭了
        3. 异常向量表,这个arm架构下的分布
.globl _start //声明全局标号供外部使用
       系统一旦发生异常一定会进入相应的异常地址,比如上电复位时进入0x0地址,由于该地址上放置了"b reset",所以系统上电初始化的时候会进入到reset对应的标号处执行。
_start:
	b      reset    		  //复位
	ldr    pc, _undefined_instruction //未定义指令
	ldr    pc, _software_interrupt    //软中断
	ldr    pc, _prefetch_abort        //预取指中止
	ldr    pc, _data_abort     	  //预取数据中止
	ldr    pc, _not_used       	  //保留
	ldr    pc, _irq        		  //IRQ
	ldr    pc, _fiq        		  //FIQ
_undefined_instruction: .wordundefined_instruction
_software_interrupt:    .wordsoftware_interrupt
_prefetch_abort:       	.wordprefetch_abort
_data_abort:       	.worddata_abort
_not_used:       	.wordnot_used
_irq:           	.wordirq
_fiq:     		.wordfiq
	/*just for match addr*/
	.balignl 16,0xdeadbeef 
        4. 开发板上电复位后真正开始执行的代码
reset:
	/*设置ARM芯片的工作模式*/ 
	mrs r0, cpsr  	   //读cpsr
	bic r0, r0,#0x1f   //清零bit[4:0]
	orr r0, r0,#0xd3   //或指令,0xd3 = 11010011b
                           //=>设置bit[7:6]=11b,禁止FIQ和IRQ中断
                           //=>设置bit[4:0]=10011b,supervisor管理模式
	msr cpsr, r0 	   //回写cpsr
        5. 关闭看门狗(寄对看门狗寄存器写0),屏蔽所有中断,并且在这里把uboot中原来对时钟的设置先去掉,暂时无需配置直接使用默认的(板子上是使用的12M晶振)时钟频率就好了。
	/* 在MY_JZ2440.h中定义了:CONFIG_MY_S3C2440 */
	#if defined(CONFIG_MY_S3C2440)
	#define pWTCON0x53000000
	#define INTMOD    0x4A000004 //Interrupt mode register:0 = IRQ mode , 1 = FIQ mode
	#define INTMSK    0x4A000008 //mask register:0=available , 1=masked
	#define INTSUBMSK 0x4A00001C //mask register:0=available , 1=masked
	#define CLKDIVN   0x4C000014
	#endif  /* CONFIG_MY_S3C2440 */
	#if defined(CONFIG_MY_S3C2440)
	/*关看门狗*/
	ldr  r0, =pWTCON //伪指令,加载看门狗寄存器的地址到r0
	mov  r1, #0x0
	str  r1, [r0] 	 //设置看门狗寄存器的值为0
	/*屏蔽所有IRQ*/
	mov  r1, #0xffffffff//bit[31:0]
	ldr  r0, =INTMSK
	str  r1, [r0]
	ldr  r1, =0x7fff  //bit[14:0]
	ldr  r0, =INTSUBMSK
	str  r1, [r0]
	#endif  /* CONFIG_MY_S3C2440 */
        6. 在完成这次操作之后我加了一个LED灯的调试程序:全亮1s左右。一般只要你配置好的uboot能顺利编译出来,那么此处的LED调试输出信息一般是正常的,毕竟在这之前我们几乎什么也没有做。除非你uboot配置编译就出了问题。
	//=============================>
	#ifDEBUG_LED 	/*LED调试信息:0关闭1打开*/
	#define  REG_GPFCON0x56000050  //GPIO控制寄存器
	#define  REG_GPFDAT0x56000054  //GPIO控制数据器
	#define  REG_GPFPUL0x56000058  //GPIO控制上拉器
	ldr  r0, =REG_GPFCON
	mov  r1, #0x00001500	//0000 0000 0000 0000 0001 0101 0000 0000
	str  r1, [r0]		//设置GPF4/5/6为输出口, 位[13:8]=010101
	ldr  r0, =REG_GPFDAT
	mov  r1, #0x00000000	//xxxx xx[0(000)][0000]  (0亮1灭)
	str  r1, [r0]
	/*延时1s*/
	mov  r0, #0x00100000
LHB_Delay_0: 
	subs r0, r0, #0x1
	bne  LHB_Delay_0
	#endif
	//=============================>

       暂时先分析到这里,敬请关注后续博文。