UBOOT从NAND FLASH启动分析.docx

上传人:b****7 文档编号:9614269 上传时间:2023-02-05 格式:DOCX 页数:23 大小:42.12KB
下载 相关 举报
UBOOT从NAND FLASH启动分析.docx_第1页
第1页 / 共23页
UBOOT从NAND FLASH启动分析.docx_第2页
第2页 / 共23页
UBOOT从NAND FLASH启动分析.docx_第3页
第3页 / 共23页
UBOOT从NAND FLASH启动分析.docx_第4页
第4页 / 共23页
UBOOT从NAND FLASH启动分析.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

UBOOT从NAND FLASH启动分析.docx

《UBOOT从NAND FLASH启动分析.docx》由会员分享,可在线阅读,更多相关《UBOOT从NAND FLASH启动分析.docx(23页珍藏版)》请在冰豆网上搜索。

UBOOT从NAND FLASH启动分析.docx

UBOOT从NANDFLASH启动分析

UBOOT从NANDFLASH启动分析

 

UBOOT从NANDFLASH启动分析

在分析启动代码之前先看一下S3C2440的NAND启动:

在配置NAND启动模式之后,S3C2440上电会先将NAND中的0x0-0x1000共4096字节的数据拷贝到位于Bank0中的BootInternalSRAM上

Bank0如下图:

可以看出BootInternalSRAM为4KB大小,也正是因为BootInternalSRAM只有4KB大小,所以只能从NAND中拷贝4K的内容=3=这个BootInternalSRAM是配置为NANDFLASH启动模式才有的

这4K内容是什么呢?

~这就要看Uboot的镜像文件中是如何进行连接的了~

连接脚本在board/smdk2440/u-boot.lds中,如下

SECTIONS

{

.=0x00000000;

.=ALIGN(4);

.text:

{

cpu/arm920t/start.o(.text)

cpu/arm920t/s3c24x0/nand_read.o(.text)

*(.text)

}

.=ALIGN(4);

.rodata:

{*(.rodata)}

.=ALIGN(4);

.data:

{*(.data)}

.=ALIGN(4);

.got:

{*(.got)}

.=.;

__u_boot_cmd_start=.;

.u_boot_cmd:

{*(.u_boot_cmd)}

__u_boot_cmd_end=.;

.=ALIGN(4);

__bss_start=.;

.bss:

{*(.bss)}

_end=.;

}

.text为代码段,可以看出cpu/arm920t/start.o在代码段的最前面,所以会先执行start.o中的代码

连接完成后的镜像文件的前4K如下

cpu/arm920t/start.o(.text)

.text0x33f800000x4e0cpu/arm920t/start.o

0x33f80050IRQ_STACK_START

0x33f80048_bss_start

0x33f8004c_bss_end

0x33f80044_armboot_start

0x33f80000_start

0x33f80054FIQ_STACK_START

cpu/arm920t/s3c24x0/nand_read.o(.text)

.text0x33f804e00x1b8cpu/arm920t/s3c24x0/nand_read.o

0x33f804e0nand_read_ll

*(.text)

.text0x33f806980x64board/smdk2440/libsmdk2440.a(lowlevel_init.o)

0x33f8069clowlevel_init

.text0x33f806fc0x280cpu/arm920t/libarm920t.a(interrupts.o)

0x33f80934do_fiq

0x33f80880do_undefined_instruction

0x33f80744show_regs

0x33f80958do_irq

0x33f80728bad_mode

0x33f808c8do_prefetch_abort

0x33f8070cdisable_interrupts

0x33f80910do_not_used

0x33f808ecdo_data_abort

0x33f808a4do_software_interrupt

0x33f806fcenable_interrupts

.text0x33f8097c0x250cpu/arm920t/s3c24x0/libs3c24x0.a(interrupts.o)

0x33f80aa4set_timer

0x33f80a20reset_timer

0x33f8097cinterrupt_init

0x33f80ba0get_tbclk

0x33f80a90get_timer

0x33f809f0reset_timer_masked

0x33f80a24get_timer_masked

0x33f80ab4udelay

0x33f80b10udelay_masked

0x33f80bacreset_cpu

0x33f80b8cget_ticks

.text0x33f80bcc0x150cpu/arm920t/s3c24x0/libs3c24x0.a(speed.o)

0x33f80c4cget_HCLK

0x33f80cecget_PCLK

0x33f80c44get_FCLK

0x33f80d14get_UCLK

.text0x33f80d1c0x1e8cpu/arm920t/s3c24x0/libs3c24x0.a(cmd_s3c24xx.o)

0x33f80d8cdo_s3c24xx

.text0x33f80f040xdccpu/arm920t/s3c24x0/libs3c24x0.a(serial.o)

0x33f80f04serial_setbrg

0x33f80fa8serial_tstc

0x33f80f80serial_putc

0x33f80f58serial_init

0x33f80fb8serial_puts

0x33f80f68serial_getc

.text0x33f80fe00x140lib_arm/libarm.a(_divsi3.o)

0x33f80fe0__divsi3

如何设置从0x33f80000开始呢?

~这是链接的时候指定的

在根目录下面的config.mk中有下面一句

LDFLAGS+=-Bstatic-T$(LDSCRIPT)-Ttext$(TEXT_BASE)$(PLATFORM_LDFLAGS)

关键就是其中的-Ttext$(TEXT_BASE),这句指明了代码段的起始地址

而TEXT_BASE在board/smdk2440/config.mk中定义TEXT_BASE=0x33F80000

为什么是0x33F80000呢?

~

这是将NAND中Uboot拷贝到RAM中的起始地址,所以在代码拷贝到RAM之前不能使用绝对地址来寻址数据,只能用相对地址

在以下将用虚拟地址来指Uboot在RAM中的地址,也就是0x33F80000

现在来看代码cpu/arm920t/start.S

_start:

;异常处理向量表

bstart_code

ldrpc,_undefined_instruction;未定义指令异常:

0x00000004

ldrpc,_software_interrupt;软中断异常:

0x00000008

ldrpc,_prefetch_abort;预取异常:

0x0000000C

ldrpc,_data_abort;数据异常:

0x00000010

ldrpc,_not_used;未使用:

0x00000014

ldrpc,_irq;外部中断请求IRQ:

0x00000018

ldrpc,_fiq;快束中断请求FIQ:

0x0000001C

bstart_code在虚拟地址0x33F80000处,拷贝到BootInternalSRAM后则位于0x0处,所以bstart_code是第一条执行的指令,

start_code在cpu/arm920t/start.S中

代码如下:

//读取CPSR寄存器的内容到R0

mrsr0,cpsr

//清除R0中的0-4这5个位后保存到R0中

//也就是清除用户模式位

bicr0,r0,#0x1f

//置R0的01467位为真

//也就是选择SVC模式,同时IRQ和FIQ被禁止,处理器处于ARM状态

//关闭中断和快速中断

orrr0,r0,#0xd3

//将R0中的值保存到CPSR上

msrcpsr,r0

#definepWTCON0x53000000;看门狗控制寄存器WTCON

#defineINTMSK0x4A000008;中断屏蔽寄存器INTMSK

#defineINTSUBMSK0x4A00001C;辅助中断屏蔽寄存器,由于外设中断源太多,要用此寄存器屏蔽剩余的中断源

#defineLOCKTIME0x4c000000;PLL锁定时间计数寄存器

#defineMPLLCON0x4c000004;主时钟锁相环控制寄存器

#defineUPLLCON0x4c000008

#defineCLKDIVN0x4C000014;时钟分频寄存器/*clockdivisorregister*/

#defineINTSUBMSK_val0xffff

#defineMPLLCON_val((18412)+(24)+2)/*406M*/

#defineUPLLCON_val((6012)+(44)+2)/*47M*/

#defineCLKDIVN_val7/*FCLK:

HCLK:

PCLK=1:

3:

6*/

#defineCAMDIVN0x4C000018

//取得看门狗寄存器的地址

ldrr0,=pWTCON

//将R1寄存器清0

movr1,#0x0

//将看门狗寄存器清0,即将看门狗禁止,包括定时器定时,溢出中断及溢出复位等

strr1,[r0]

/*

*maskallIRQsbysettingallbitsintheINTMR-default

*/

//设R1寄存器为0xFFFFFFFF

movr1,#0xffffffff

//读取中断屏蔽寄存器的地址

ldrr0,=INTMSK

//将中断屏蔽寄存器中的位全设1,屏蔽所有中断

strr1,[r0]

//#defineINTSUBMSK_val0xffff

//设R1寄存器为0xFFFF

ldrr1,=INTSUBMSK_val

//读取辅助中断屏蔽寄存器的地址

ldrr0,=INTSUBMSK

//将辅助中断屏蔽寄中的11个中断信号屏蔽掉,本人觉得INTSUBMS_val应设成7ff

strr1,[r0]

//#defineLOCKTIME0x4c000000

//读取PLL锁频计数器寄存器地址到R0中

ldrr0,=LOCKTIME

//将R1设为0x00FFFFFF

ldrr1,=0xffffff

//M_LTIME为最大的0xFFF

//U_LTIME为最大的0xFFF

strr1,[r0];0xfff=4096>1800,远远满足锁定要求

/*FCLK:

HCLK:

PCLK=1:

2:

4*/

/*defaultFCLKis120MHz!

*/

//#defineCLKDIVN0x4C000014/*clockdivisorregister*/

//读取时钟分频寄存器的地址

ldrr0,=CLKDIVN

//#defineCLKDIVN_val7/*FCLK:

HCLK:

PCLK=1:

3:

6*/

//将R1设为0x7

movr1,#CLKDIVN_va

//PDIVN-1:

PCLKhastheclocksameastheHCLK/2.

//HDIVN-11:

HCLK=FCLK/3whenCAMDIVN[8]=0.

//HCLK=FCLK/6whenCAMDIVN[8]=1.

strr1,[r0]

/*MakesurewegetFCLK:

HCLK:

PCLK=1:

3:

6*/

//#defineCAMDIVN0x4C000018

//读取摄像头时钟分频寄存器的地址

ldrr0,=CAMDIVN

//将R1设为0

movr1,#0

//将摄像头时钟分频寄存器清0

strr1,[r0]

/*Clockasynchronousmode*/

//MRCp15,0,Rd,c1,c0,0;readcontrolregister

//读取控制寄存器中的值到R1中

mrcp15,0,r1,c1,c0,0;将协处理器p15的寄存器c1和c0的值传到arm处理器的R1寄存器中

//31iAbitAsynchronousclockselect

//30nFbitnotFastBusselect

orrr1,r1,#0xc0000000;将最高两位置1

//MCRp15,0,Rd,c1,c0,0;writecontrolregister

//将R1中的值写到控制寄存器中

mcrp15,0,r1,c1,c0,0将arm的寄存器R1的32位数据传到协处理器p15的两个16位寄存器c1和c0

//#defineUPLLCON0x4c000008

//读取UPLL设置寄存器的地址到R0中

ldrr0,=UPLLCON

//#defineUPLLCON_val((60

ldrr1,=UPLLCON_val

//将R1中的值写入UPLL设置寄存器中

strr1,[r0]

//ARM920T为5级流水线,需要至少5个周期来让指令生效

nop

nop

nop

nop

nop

nop

nop

nop

//读取MPLL设置寄存器的地址到R0中

ldrr0,=MPLLCON

//#defineMPLLCON_val((184

ldrr1,=MPLLCON_val

//将R1中的值写入MPLL设置寄存器中

strr1,[r0]

#defineGPJCON0x560000D0

#defineGPJDAT0x560000D4

#defineGPJUP0x560000D8

//跳转到cpu_init_crit处执行

//并将下一条指令的地址写入LR寄存器中

blcpu_init_crit

cpu_init_crit在cpu/arm920t/start.S中

代码如下:

cpu_init_crit:

/*

*flushv4I/Dcaches

*/

//将R0寄存器置0

movr0,#0

//InvalidateICacheandDCacheSBZMCRp15,0,Rd,c7,c7,0

//禁止指令和数据cache

mcrp15,0,r0,c7,c7,0/*flushv3/v4cache*/

//InvalidateTLB(s)SBZMCRp15,0,Rd,c8,c7,0

mcrp15,0,r0,c8,c7,0/*flushv4TLB*/

/*

*disableMMUstuffandcaches

*/

//MRCp15,0,Rd,c1,c0,0;readcontrolregister

mrcp15,0,r0,c1,c0,0

//清除[8][9][13]这3个位

//8-Systemprotection

//9-ROMprotection

//13-Baselocationofexceptionregisters-0=Lowaddresses=0x00000000.

bicr0,r0,#0x00002300//clearbits13,9:

8(--V---RS)

//清除[0][1][2][7]这4个位

//0-MMUenable-0=MMUdisabled.

//1-Alignmentfaultenable-0=Faultcheckingdisabled.

//2-DCacheenable-0=DCachedisabled.

//7-Endianness-0=Little-endianoperation.

bicr0,r0,#0x00000087//clearbits7,2:

0(B----CAM)

//设置位[1]为真

//1-Alignmentfaultenable-1=Faultcheckingenabled.

orrr0,r0,#0x00000002//setbit2(A)Align

//设置位[12]为真

//12-ICacheenable-1=ICacheenabled.

orrr0,r0,#0x00001000//setbit12(I)I-Cache

//MCRp15,0,Rd,c1,c0,0;writecontrolregister

mcrp15,0,r0,c1,c0,0

//将返回地址保存到IP中

movip,lr

//跳转到lowlevel_init中执行

bllowlevel_init

cpu_init_crit在cpu/arm920t/start.S中

代码如下:

.globllowlevel_init

//读取下面标号为SMRDATA处的地址到R0中

ldrr0,=SMRDATA

//读取上面标号为_TEXT_BASE处的地址内容到R1中

//也就是取得TEXT_BASE的值到R1中

ldrr1,_TEXT_BASE

//计算SMRDATA的相对地址保存到R0中

//SMRDATA为虚拟地址,而TEXT_BASE为虚拟地址的起始地址

//而现在Uboot的起始地址并不为虚拟地址

//TEXT_BASE为0x33F80000,SMRDATA为0x33F806C8

//而现在程序运行在起始地址为0x00000000的地方

//所以需要计算以0x00000000为标准的相对地址

subr0,r0,r1

//取得带宽与等待状态控制寄存器地址到R1中

ldrr1,=BWSCON/*BusWidthStatusController*/

//一共需要设置13个寄存器,每个寄存器4字节

addr2,r0,#13*4

0:

//读取R0所指的项的值到R3中后R0自加4字节

ldrr3,[r0],#4

//将R3中的值保存到R1所指的地址中后R1自加4字节

strr3,[r1],#4

//比较R0和R2是否相等,相等则说明13个寄存器全部设置完毕

cmpr2,r0

//不等则跳转到上面标号为0处的地址继续执行

bne0b

//跳回到返回地址中继续执行

movpc,lr

.ltorg

/*theliteralpoolsorigin*/

SMRDATA:

.word(0+(B1_BWSCON4)+(B2_BWSCON8)+(B3_BWSCON12)+(B4_BWSCON16)+(B5_BWSCON20)+(B6_BWSCON24)+(B7_BWSCON28))

.word((B0_Tacs13)+(B0_Tcos11)+(B0_Tacc8)+(B0_Tcoh6)+(B0_Tah4)+(B0_Tacp2)+(B0_PMC))

.word((B1_Tacs13)+(B1_Tcos11)+(B1_Tacc8)+(B1_Tcoh6)+(B1_Tah4)+(B1_Tacp2)+(B1_PMC))

.word((B2_Tacs13)+(B2_Tcos11)+(B2_Tacc8)+(B2_Tcoh6)+(B2_Tah4)+(B2_Tacp2)+(B2_PMC))

.word((B3_Tacs13)+(B3_Tcos11)+(B3_Tacc8)+(B3_Tcoh6)+(B3_Tah4)+(B3_Tacp2)+(B3_PMC))

.word((B4_Tacs13)+(B4_Tcos11)+(B4_Tacc8)+(B4_Tcoh6)+(B4_Tah4)+(B4_Tacp2)+(B4_PMC))

.word((B5_Tacs13)+(B5_Tcos11)+(B5_Tacc8)+(B5_Tcoh6)+(B5_Tah4)+(B5_Tacp2)+(B5_PMC))

.word((B6_MT15)+(B6_Trcd2)+(B6_SCAN))

.word((B7_MT15)+(B7_Trcd2)+(B7_SCAN))

.word((REFEN23)+(TREFMD22)+(Trp20)+(Trc18)+(Tchr16)+REFCNT)

.word0x32

.word0x30

.word0x30

执行movpc,lr后将返回到cpu_init_crit中

剩下来还有2条指令

//恢复返回地址到LR

movlr,ip

//跳转到返回地址

movpc,lr

执行完毕之后将返回到start_code中执行接下来的代码

代码如下:

//#defineGPJCON0x560000D0

//取得J端口控制寄存器的地址到R0中

LDRR0,=GPJCON

//将R1设置为0x15555

LDRR1,=0x15555

//将R1中的值保存到J端口控制寄存器

//GPJ0-01-Output

//GPJ1-01-Output

//GPJ2-01-Output

//GPJ3-01-Output

//GPJ4-01-Output

STRR1,[R0]

//#defineGPJUP0x560000D8

//取得J端口上拉功能寄存器的地址到R0中

LDRR0,=GPJUP

//将R1设置为0x1F

LDRR1,=0x1f

//将R1中的值保存到J端口上拉功能寄存器

//禁止GPJ0-GPJ4的上拉功能

STRR1,[R0]

//#defineGPJDAT0x560000D4

//取得J端口数据寄存器的地址到R0中

LDRR0,=GPJDAT

//将R1设为0x0

LDRR1,=0x00

//将R1中的值保存到J端口数据寄存器

//将J端口数据寄存器清0

STRR1,[R0]

//下面是NAND数据拷贝过程

//relocate:

copy_myself:

//#defineS3C2440_NAND_BASE0x4E000000

//取得NandFlash设置寄存器的地址

movr1,#S3C2440_NAND_BASE

//将R2设为0xFFF0

ldr

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

当前位置:首页 > 经管营销 > 人力资源管理

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

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