uboot整体结构移植步骤以及启动代码分析.docx
《uboot整体结构移植步骤以及启动代码分析.docx》由会员分享,可在线阅读,更多相关《uboot整体结构移植步骤以及启动代码分析.docx(16页珍藏版)》请在冰点文库上搜索。
uboot整体结构移植步骤以及启动代码分析
一、整体结构
首先下载u-boot的源代码(www.denx.de),解压缩,你可以看到下面的目录:
-board目标板相关文件,主要包含SDRAM、FLASH驱动;
-common独立于处理器体系结构的通用代码,如内存大小探测与故障检测;
-cpu与处理器相关的文件。
如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;
-driver通用设备驱动,如CFIFLASH驱动(目前对INTELFLASH支持较好)
-docU-Boot的说明文档;
-examples可在U-Boot下运行的示例程序;如hello_world.c,timer.c;
-includeU-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;
-lib_xxx处理器体系相关的文件,如lib_ppc,lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;
-net与网络功能相关的文件目录,如bootp,nfs,tftp;
-post上电自检文件目录。
尚有待于进一步完善;
-rtcRTC驱动程序;
-tools用于创建U-BootS-RECORD和BIN镜像文件的工具;
二、移植步骤
为了使U-Boot支持新的开发板,一种简便的做法是在U-Boot已经支持的开发板中选择一种和目标板接近的,并在其基础上进行修改。
代码修改的步骤如下:
1)在board目录下创建smdk2410目录,添加smdk2410.c、flash.c、memsetup.s、u-boot.lds和config.mk等;
2)在cpu目录下创建arm920t目录,主要包含start.s、interrupts.c、cpu.c、serial.c和speed.c等文件;
3)在include/configs目录下添加smdk2410.h,它定义了全局的宏定义等;
4)修改u-boot根目录下的Makefile文件:
smdk2410_config :
unconfig@./mkconfig$(@:
_config=)armarm920tsmdk2410
5)运行makesmdk2410_config,如果没有错误,就可以开始进行与硬件相关的代码移植工作。
由于这部分代码与硬件紧密相关,所以要熟悉开发板的硬件配置,可参考各芯片的用户手册。
当然,这个是一般步骤,后面我们做的可能具体文件名还和这个不一样,等到那时候在交待,这里先介绍的目的是在开始的时候给个大概的思路,要不直接分析源代码,有点在原始森林的感觉,耐心的看吧:
)
三、start.S分析
首先介绍start.S中的代码的具体作用,由于该代码是系统最开始执行的,这时,u-boot对系统一无所知,必须要初始化一些东西,比如设置异常的入口地址和异常处理函数;配置PLLCON寄存器,确定系统的主频;屏蔽看门狗和中断;初始化I/O寄存器;关闭MMU功能;调用/board/smdk2410中的memsetup.s,初始化存储器空间,设置刷新频率;将U-Boot的内容复制到SDRAM中;设置堆栈的大小,然后ldrpc,_start_armboot,跳到C函数
代码来自华恒的板子上面的资料
/*CPUclcok*/
/*50.00MHz*/
#defineMDIV_50 0x5c
#definePDIV_50 0x4
#defineSDIV_50 0x2
/*100.00MHz*/
#defineMDIV_100 0xa1
#definePDIV_100 0x3
#defineSDIV_100 0x1
/*200.00MHz*/
/*CPUclock=202.800000Mhz,HCLK=101.400000Mhz,PCLK=50.700000Mhz*/
/*0xa1 3 1*/
/*180Mhz90Mhz45Mhz 0x52 1 1*/
/*152MHZ 0x441 1*/
#defineMDIV_200 0xa1
#definePDIV_200 0x3
#defineSDIV_200 0x1
#definevMPLLCON_50 ((MDIV_50<<12)|(PDIV_50<<4)|(SDIV_50))
#definevMPLLCON_100 ((MDIV_100<<12)|(PDIV_100<<4)|(SDIV_100))
#definevMPLLCON_200 ((MDIV_200<<12)|(PDIV_200<<4)|(SDIV_200))
/*
*************************************************************************
*
*Jumpvectortableasintable3.1in[1]
*
*************************************************************************
*/
.globl_start
_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
ldr pc,_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
.balignl16,0xdeadbeef
/*
*************************************************************************
*
*StartupCode(resetvector)
*
*doimportantinitonlyifwedon'tstartfrommemory!
*relocatearmboottoram
*setupstack
*jumptosecondstage
*
*************************************************************************
*/
/*
*CFG_MEM_ENDisintheboarddependentconfig-file(configs/config_BOARD.h)
*/
_TEXT_BASE:
.word TEXT_BASE
.globl_armboot_start
_armboot_start:
.word_start
/*
*Note:
_armboot_end_dataand_armboot_endaredefined
*bythe(board-dependent)linkerscript.
*_armboot_end_dataisthefirstusableFLASHaddressafterarmboot
*/
.globl_armboot_end_data
_armboot_end_data:
.wordarmboot_end_data
.globl_armboot_end
_armboot_end:
.wordarmboot_end
/*
*_armboot_real_endisthefirstusableRAMaddressbehindarmboot
*andthevariousstacks
*/
.globl_armboot_real_end
_armboot_real_end:
.word0x0badc0de
#ifdefCONFIG_USE_IRQ
/*IRQstackmemory(calculatedatrun-time)*/
.globlIRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/*IRQstackmemory(calculatedatrun-time)*/
.globlFIQ_STACK_START
FIQ_STACK_START:
.word0x0badc0de
#endif
/*
*theactualresetcode
*/
reset:
=============================================〉程序开始的时候跳转到这里
ldr r0,=pWTCON
mov r1,#0x0
str r1,[r0];0x0写到0x53000000地址上,其实该地址是看门狗的控制寄存器,该指令就是关闭看门狗,具体对应位请看2410的用户手册。
/*
*maskallIRQsbysettingallbitsintheINTMR-default
*/
mov r1,#0xffffffff
ldr r0,=INTMSK
str r1,[r0];将0xffffffff写到INTMSK代表的地址上,屏蔽中断
#ifdefined(CONFIG_S3C2410)
ldr r1,=0x7ff
ldr r0,=INTSUBMSK
str r1,[r0];对于2410还要设置此寄存器
#endif
@initialisesystemclocks;下面没什么要讲的,具体参看2410的用户手册
mov r1,#CLK_CTL_BASE
mvn r2,#0xff000000
str r2,[r1,#0x0] /*oLOCKTIME*/
@ldr r2,mpll_50mhz
@str r2,[r1,#0x4] /*oMPLLCON*/
mov r1,#CLK_CTL_BASE
/* mov r2,#0x3*/
mov r2,#0x3
str r2,[r1,#0x14] /*oCLKDIVN*/
mrc p15,0,r1,c1,c0,0 @readctrlregister
orr r1,r1,#0xc0000000 @Asynchronous
mcr p15,0,r1,c1,c0,0 @writectrlregister
@now,CPUclockis200Mhz
mov r1,#CLK_CTL_BASE
ldr r2,mpll_200mhz
str r2,[r1,#0x4] /*oMPLLCON*/
/*
*wedosys-criticalinitsonlyatreboot,
*notwhenbootingfromram!
*/
#ifdefCONFIG_INIT_CRITICAL
bl cpu_init_crit;跳到下面的子过程
#endif
relocate:
;下面代码的作用是把u-boot的后续代码搬运到内存中
/*
*relocatearmboottoRAM
*/
adr r0,_start /*r0<-currentpositionofcode*/
ldr r2,_armboot_start
ldr r3,_armboot_end
sub r2,r3,r2 /*r2<-sizeofarmboot*/
ldr r1,_TEXT_BASE \board\smdk2410\config.mk中定义了_TEXT_BASE,表示把u-boot搬到内存中的相应位置,在这里是0x33F00000,相对于0x30000000来说是63MB的地方,朋友们可能要疑惑了,前面的文章不是介绍了我们用的板子是32M内存吗?
那怎么是63M的地方呢,其实2410支持地址循环,这里其实就是31M的地方,哈哈,那u-boot不是把自己放在SDRAM中的最高的地方吗?
的确是这样的。
add r2,r0,r2 /*r2<-sourceendaddress*/
/*
*r0=sourceaddress
*r1=targetaddress
*r2=sourceendaddress
*/
copy_loop:
;开始拷贝
ldmia r0!
{r3-r10}
stmia r1!
{r3-r10}
cmp r0,r2
ble copy_loop
/*setupthestack*/;最后我们在u-boot之后建立堆栈,为C语言的执行创建环境,否则是不允许执行C程序的,大小为128*1024
ldr r0,_armboot_end
add r0,r0,#CONFIG_STACKSIZE该宏在\include\configs\smdk2410.h中定义
sub sp,r0,#12 /*leave3wordsforabort-stack*/
ldr pc,_start_armboot
_start_armboot:
.wordstart_armboot;跳转到/lib_arm/board.c中的start_armboot()函数中运行了,到此我们完成了第一阶段,初始汇编代码的运行
/*
*************************************************************************
*
*CPU_init_criticalregisters
*
*setupimportantregisters
*setupmemorytiming
*
*************************************************************************
*/
cpu_init_crit:
/*
*flushv4I/Dcaches;意思很明白不是?
*/
mov r0,#0
mcr p15,0,r0,c7,c7,0 //flushv3/v4cache
mcr p15,0,r0,c8,c7,0 //flushv4TLB
/*
*disableMMUstuffandcaches
*/
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x00002300 @clearbits13,9:
8(--V---RS)
bic r0,r0,#0x00000087 @clearbits7,2:
0(B----CAM)
orr r0,r0,#0x00000002 @setbit2(A)Align
orr r0,r0,#0x00001000 @setbit12(I)I-Cache
mcr p15,0,r0,c1,c0,0
/*
*beforerelocating,wehavetosetupRAMtiming
*becausememorytimingisboard-dependend,youwill
*findamemsetup.Sinyourboarddirectory.
*/
mov ip,lr
bl memsetup==〉上面英文注释就是,在重新定位之前,要初始化RAM,以及设置刷新频率
我们在本文的最后插上memsetup.S的代码。
mov lr,ip
mov pc,lr返回,并且回到上面,进行重定位
/*
*************************************************************************
*
*Interrupthandling
*
*************************************************************************
*/
@
@IRQstackframe.
@
#defineS_FRAME_SIZE 72
#defineS_OLD_R0 68
#defineS_PSR 64
#defineS_PC 60
#defineS_LR 56
#defineS_SP 52
#defineS_IP 48
#defineS_FP 44
#defineS_R10 40
#defineS_R9 36
#defineS_R8 32
#defineS_R7 28
#defineS_R6 24
#defineS_R5 20
#defineS_R4 16
#defineS_R3 12
#defineS_R2 8
#defineS_R1 4
#defineS_R0 0
#defineMODE_SVC0x13
#defineI_BIT 0x80
/*
*usebad_save_user_regsforabort/prefetch/undef/swi...
*useirq_save_user_regs/irq_restore_user_regsforIRQ/FIQhandling
*/
.macro bad_save_user_regs
sub sp,sp,#S_FRAME_SIZE
stmia sp,{r0-r12} @Callingr0-r12
add r8,sp,#S_PC
ldr r2,_armboot_end
add r2,r2,#CONFIG_STACKSIZE
sub r2,r2,#8
ldmia r2,{r2-r4} @getpc,cpsr,old_r0
add r0,sp,#S_FRAME_SIZE @restoresp_SVC
add r5,sp,#S_SP
mov r1,lr
stmia r5,{r0-r4} @savesp_SVC,lr_SVC,pc,cpsr,old_r
mov r0,sp
.endm
.macro irq_save_user_regs
sub sp,sp,#S_FRAME_SIZE
stmia sp,{r0-r12} @Callingr0-r12
add r8,sp,#S_PC
stmdb r8,{sp,lr}^ @CallingSP,LR
str lr,[r8,#0] @SavecallingPC
mrs r6,spsr
str r6,[r8,#4] @SaveCPSR
st