starts源码分析ubootWord文档格式.docx

上传人:b****5 文档编号:21645794 上传时间:2023-01-31 格式:DOCX 页数:18 大小:147.11KB
下载 相关 举报
starts源码分析ubootWord文档格式.docx_第1页
第1页 / 共18页
starts源码分析ubootWord文档格式.docx_第2页
第2页 / 共18页
starts源码分析ubootWord文档格式.docx_第3页
第3页 / 共18页
starts源码分析ubootWord文档格式.docx_第4页
第4页 / 共18页
starts源码分析ubootWord文档格式.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

starts源码分析ubootWord文档格式.docx

《starts源码分析ubootWord文档格式.docx》由会员分享,可在线阅读,更多相关《starts源码分析ubootWord文档格式.docx(18页珍藏版)》请在冰豆网上搜索。

starts源码分析ubootWord文档格式.docx

config.h>

version.h>

*************************************************************************

*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

.globlFIQ_STACK_START

FIQ_STACK_START:

#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*/

#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

#endif/*CONFIG_S3C2410*/

/*FCLK:

HCLK:

PCLK=1:

2:

4*/

/*defaultFCLKis120MHz!

ldrr0,=CLKDIVN

movr1,#3

#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

#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*/

subr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

subsp,r0,#12/*leave3wordsforabort-stack*/

借此详细分析:

编译器跟代码的交互原理

在ads编译程序代码的时候,会要求我们输入程序的入口代码地址,开始执行地址,各个段的存放首地址(基本由编译器自己根据代码大小情况决定,但我们可以自己指定,虽然一般不这么做)等信息。

类似,在用交叉编译器,编译我们的bootloader代码时,它们也会用到这些地址。

不过一般由编译器自己指定一部分(如:

__bss_start),我们指定一部分必要的(如:

TEXT_BASE,一般放在某些配置文件里边,供编译器查看)。

我们看看由编译器自己指定的情况:

定义一个全局标号_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

*maskallIRQsbysettingallbitsintheINTMR-default

movr1,#0xffffffff

ldrr0,=INTMR

/*FCLK:

/*defaultFCLKis120MHz!

/*ENDstuffafterrelocation*/

ldrpc,_start_armboot

_start_armboot:

.wordstart_armboot

*CPU_init_criticalregisters

*setupimportantregisters

*setupmemorytiming

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 法语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1