starts源码分析uboot.docx
- 文档编号:8509564
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:18
- 大小:147.11KB
starts源码分析uboot.docx
《starts源码分析uboot.docx》由会员分享,可在线阅读,更多相关《starts源码分析uboot.docx(18页珍藏版)》请在冰豆网上搜索。
starts源码分析uboot
/*
*armboot-StartupCodeforARM920CPU-core
*
*Copyright(c)2001MariusGr鰃er
*Copyright(c)2002AlexZ黳ke
*Copyright(c)2002GaryJennejohn
*
*SeefileCREDITSforlistofpeoplewhocontributedtothis
*project.
*
*Thisprogramisfreesoftware;youcanredistributeitand/or
*modifyitunderthetermsoftheGNUGeneralPublicLicenseas
*publishedbytheFreeSoftwareFoundation;eitherversion2of
*theLicense,or(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNUGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace,Suite330,Boston,
*MA02111-1307USA
*/
#include
#include
/*
*************************************************************************
*
*Jumpvectortableasintable3.1in[1]
start.s代码,是u-boot的stage1阶段所要运行的代码
由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(flash)的0x地址。
因此,必须通知编译器以使其知道这个入口,该工作可以通过修改连接器的脚本来完成。
1.board/smdk2410/uboot.lds:
ENTRY(_start)==>cpu/arm920t/start.o(.text)
2.Uboot在ram的代码区(TEXT_BASE=0X33F80000)定义在board/amdk2410/config.mk
***********************************************************************
*/
/*
.globlsymbol
定义一个全局符号,让这个符号对链接器可见,通常为连接器(ld)使用。
symbol是全局可见的,可以供其他链接对象模块使用。
.global_start让_start符号成为可见的标识符,这样链接器就知道跳转到程序中的什么地方并开始执行。
linux寻找这个_start标签作为程序的默认进入点。
标号_start是GNU链接器用来指定第一个要执行指令所必须的,同样的是全局可见的(并且只能出现在一个模块中)。
标号是后边紧跟一个冒号的符号,此时该标号代表活动位置计数器的当前值,并且可作为指令的操作数使用。
*/
.globl_start
_start:
breset/*reset异常不返回,下边都是异常跳转地址*/
ldrpc,_undefined_instruction
ldrpc,_software_interrupt
ldrpc,_prefetch_abort
ldrpc,_data_abort
ldrpc,_not_used
ldrpc,_irq
ldrpc,_fiq
/*
.globl_start、_start:
这些伪指令,标号在编译后的代码中并不占用内存。
Ldr加载指定存储器地址中的内容到寄存器,区分:
ldr伪指令
当发生异常时,执行cpu/arm920t/interrupts.c中的中断处理函数
.wordexpressions:
定义一个字,并为之分配空间,4bytes。
同理有:
.shortexpressions/.intexpressions/.byteexpressions/.longexpressions/.ascii"string"
原理分析:
在这里先预留好空间,空间里边的内容就是后边的expression,这里expression是标号,则代表的是某个地址,该地址就是异常处理函数的首地址。
当发生某异常时,处理器自动跳到存储器起始的对应异常处理地址(由硬件确定地址,即地址的前几个字,见上代码),执行里边的代码,里边一般都放置一个跳转指令。
如:
ldrpc,_undefined_instruction;将此标号地址处的内容取出来给pc指针,而这内容恰好是异常处理函数的首地址(预留的空间就是为了放异常处理地址用的,这里_software_interrupt:
.wordsoftware_interrupt指令中software_interrupt,是一个标号,标号代表的是处理地址,也是跳转的目标地址,该标号在本文件最下边有定义,其他标号类似),这样完成了一次异常处理。
见图示更易理解:
地址地址中内容指令内容
*/
_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
/*
这是一个数据对齐指令,在这个.balignl16,0xdeadbeef指令之前,一共占了4x15=60个字节的内存,15个字。
所以本代码的作者当时就简单的在15这个数上,加了个1,即16,把当前指针往后移到地址为64的位置,然后在前面插上了0xdeadbeef这个特殊的值。
见图示中0x0000003c位置的内容。
详细解释见《于关u-boot中的.balignl16,0xdeadbeef的理解》一文。
*/
/*
*************************************************************************
*
*StartupCode(resetvector)
*
*doimportantinitonlyifwedon'tstartfrommemory!
*relocatearmboottoram
*setupstack
*jumptosecondstage
*
*************************************************************************
*/
_TEXT_BASE:
.wordTEXT_BASE
.globl_armboot_start
_armboot_start:
.word_start
/*
*Thesearedefinedintheboard-specificlinkerscript.
*/
.globl_bss_start
_bss_start:
.word__bss_start
.globl_bss_end
_bss_end:
.word_end
#ifdefCONFIG_USE_IRQ
/*IRQstackmemory(calculatedatrun-time)*/
.globlIRQ_STACK_START
IRQ_STACK_START:
.word0x0badc0de
/*IRQstackmemory(calculatedatrun-time)*/
.globlFIQ_STACK_START
FIQ_STACK_START:
.word0x0badc0de
#endif
/*
*theactualresetcode
*/
reset:
/*
*setthecputoSVC32mode
刚进入系统时,设置为管理模式
CPSR_c或SPSR_c的位示意图(控制位:
低8位):
76543210
IFTM4M3M2M1M0
I:
IRQ禁止,1禁止,0允许
F:
FIQ禁止,1禁止,0允许
T:
状态位,0-ARM,1-Thumb
M4-M0:
模式位
10000-用户,10001-快速中断,10010-中断,10011-管理,10111-未定义,11111-系统
*/
mrsr0,cpsr
bicr0,r0,#0x1f
orrr0,r0,#0xd3
msrcpsr,r0
/*turnoffthewatchdog*/
/*这些寄存器的地址,根据不同的芯片有不同配置,具体用到时,要更改*/
#ifdefined(CONFIG_S3C2400)
#definepWTCON0x15300000
#defineINTMSK0x14400008/*Interupt-Controllerbaseaddresses*/
#defineCLKDIVN0x14800014/*clockdivisorregister*/
#elifdefined(CONFIG_S3C2410)/*这是S3C2410的寄存器地址*/
#definepWTCON0x53000000
#defineINTMSK0x4A000008/*Interupt-Controllerbaseaddresses*/
#defineINTSUBMSK0x4A00001C
#defineCLKDIVN0x4C000014/*clockdivisorregister*/
#endif
#ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)
ldrr0,=pWTCON/*这是个ldr伪指令,将pWTCON所代表的32值给r0寄存器*/
movr1,#0x0
strr1,[r0]
/*
*maskallIRQsbysettingallbitsintheINTMR-default
*/
ldrr0,=INTMSK
movr1,#0xffffffff
strr1,[r0]
#ifdefined(CONFIG_S3C2410)
ldrr1,=0x3ff
ldrr0,=INTSUBMSK
strr1,[r0]
#endif/*CONFIG_S3C2410*/
/*FCLK:
HCLK:
PCLK=1:
2:
4*/
/*defaultFCLKis120MHz!
*/
ldrr0,=CLKDIVN
movr1,#3
strr1,[r0]
#endif/*CONFIG_S3C2400||CONFIG_S3C2410*/
/*
*wedosys-criticalinitsonlyatreboot,
*notwhenbootingfromram!
*/
/*
cpu_init_crit代码的主要工作是:
禁止MMU,以及指令cache和数据cache,因为uboot在开始时,需要用到物理地址,不能是虚拟地址。
故禁止MMU.关闭cache,是为了uboot在写入数据的时候,一定要实实在在的写到物理地址上,而不是写到缓存中。
顺便再跳转到lowlevel_init.s中,进行sdram的初始化,为以后拷贝代码做好准备
*/
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
blcpu_init_crit
#endif
#ifndefCONFIG_SKIP_RELOCATE_UBOOT
relocate:
/*relocateU-BoottoRAM*/
adrr0,_start/*r0<-currentpositionofcode*/
ldrr1,_TEXT_BASE/*testifwerunfromflashorRAM*/
cmpr0,r1/*don'trelocduringdebug*/
beqstack_setup
/*
bss段的开始地址,就是代码段的结束地址:
_bss_start-_armboot_start=sizeofdata
关于_start和_TEXT_BASE之间的关系,还有虚拟地址,物理地址在此处的分配,还有待以后研究。
注意:
此处的源代码,并没有涉及从nandflash拷贝数据到ram中,如果需要移植的话,要自己写nandflash的驱动函数,并且拷贝数据到ram中。
*/
ldrr2,_armboot_start
ldrr3,_bss_start
subr2,r3,r2/*r2<-sizeofarmboot*/
addr2,r0,r2/*r2<-sourceendaddress*/
/*
这个循环拷贝,是从norflash中拷贝数据到ram中,并不是从nandflash拷贝数据,norflash的操作类似于ram,直接操作地址总线,数据总线即可。
Nandflash却不可以,需要一定的操作时序和驱动。
直白一点:
norflash类似于ram,可以直接跟cpu的数据、控制、地址总线连接,进行控制;nandflash不可以,有时序限制,需要驱动。
*/
copy_loop:
ldmiar0!
{r3-r10}/*copyfromsourceaddress[r0]*/
stmiar1!
{r3-r10}/*copytotargetaddress[r1]*/
cmpr0,r2/*untilsourceendaddreee[r2]*/
blecopy_loop
#endif/*CONFIG_SKIP_RELOCATE_UBOOT*/
/*
Setupthestack
分析:
建立栈空间的过程
Ram中的地址分布(高->低):
...,bss区,u-boot镜像,CFG_MALLOC_LEN,GBL_DATA_SIZE,
IRQ&FIQ栈区(可选,视具体情况),用户栈区(向下生长,sp指针初始位置),SDRAM_BASE。
_TEXT_BASE并不是ram中的起始地址,只是u-boot放置的首地址,源码中是:
0x33f80000。
*/
stack_setup:
ldrr0,_TEXT_BASE/*upper128KiB:
relocateduboot*/
subr0,r0,#CFG_MALLOC_LEN/*mallocarea*/
subr0,r0,#CFG_GBL_DATA_SIZE/*bdinfo*/
#ifdefCONFIG_USE_IRQ
subr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
subsp,r0,#12/*leave3wordsforabort-stack*/
/*
借此详细分析:
编译器跟代码的交互原理
在ads编译程序代码的时候,会要求我们输入程序的入口代码地址,开始执行地址,各个段的存放首地址(基本由编译器自己根据代码大小情况决定,但我们可以自己指定,虽然一般不这么做)等信息。
类似,在用交叉编译器,编译我们的bootloader代码时,它们也会用到这些地址。
不过一般由编译器自己指定一部分(如:
__bss_start),我们指定一部分必要的(如:
TEXT_BASE,一般放在某些配置文件里边,供编译器查看)。
我们看看由编译器自己指定的情况:
.globl_bss_start
_bss_start:
.word__bss_start
定义一个全局标号_bss_start,标号代表该地址,在该地址处定义了一个字大小的变量,变量内容是__bss_start,而这个__bss_start是由编译器在编译代码时确定的,由编译器把该变量的值填入此位置,供其他代码使用。
__bss_start:
应该是编译器内部定义好的变量,专用的。
*/
clear_bss:
ldrr0,_bss_start/*findstartofbsssegment*/
ldrr1,_bss_end/*stophere*/
movr2,#0x00000000/*clear*/
clbss_l:
strr2,[r0]/*clearloop...*/
addr0,r0,#4
cmpr0,r1
bleclbss_l
/*这一段代码默认是不编译的,也就是寄存器设置,和时钟设置,参考datasheet就可以*/
#if0
/*trydoingthisstuffaftertherelocation*/
ldrr0,=pWTCON
movr1,#0x0
strr1,[r0]
/*
*maskallIRQsbysettingallbitsintheINTMR-default
*/
movr1,#0xffffffff
ldrr0,=INTMR
strr1,[r0]
/*FCLK:
HCLK:
PCLK=1:
2:
4*/
/*defaultFCLKis120MHz!
*/
ldrr0,=CLKDIVN
movr1,#3
strr1,[r0]
/*ENDstuffafterrelocation*/
#endif
ldrpc,_start_armboot
_start_armboot:
.wordstart_armboot
/*
*************************************************************************
*
*CPU_init_criticalregisters
*
*setupimportantregisters
*setupmemorytiming
*
*************************************************************************
*/
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
以下指令时对协处理器进行操作:
cp15
*flushv4I/Dcaches
mcrp15,0,r0,c7,c7,0;这一句的意思是:
使指令cache和数据cache失效,即:
关闭
这一句的具体含义见《arm920ttechnicalreferencemanual》手册,里边也并未给出具体含义,只是写出了某些操作时需要用到的命令。
mcrp15,0,r0,c8,c7,0;关闭指令tlb和数据tlb,文档也只是列出了五个相关指令。
*/
movr0,#0
mcrp15,0,r0,c7,c7,0/*flushv3/v4cache*/
mcrp15,0,r0,c8,c7,0/*flushv4TLB*/
/*
*disableMMUstuffandcaches
协处理器中register1是controlregister
13:
Vbitfunction:
baselocationofexceptionregisters(异常寄存器的基地址)
0=lowaddress=0x00000000;1=highaddress=0xffff0000
12:
IbitIcacheenable,0=Icachedisabled,1=Icacheenabled
9:
RbitROMprotection,thisbitmodifiestheMMUprotectionsystem
8:
Sbitsystemprotection,thisbitmodifiestheMMUprotectionsystem
7:
Bbitendianness,0=little-endianoperation1=big-endianoperation
2:
CbitDcacheenable,0=Dcachedisabled,1=Dcacheenabled
1:
AbitAlignmentfaultenable,Dataaddressalignmentfaultchecking
0=faultcheckingdisabled,1=faultcheckingenabled
0:
MbitMMUenable0=MMUdisabled,1=MMUenabled
*/
mrcp15,0,r0,c1,c0,0
bicr0,r0,#0x00002300@clearbits13,9:
8(--V---RS)
bic
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- starts 源码 分析 uboot