📄 s3c2410start.s.txt
字号:
ldr r0, =0xec75
cmp r5, r0
beq %F1
mov r6, #1 ;r6=1
1
bl ReadNandStatus ;返回的NAND FLASH CHIP状态保存在r1中
mov r8, #0 ;r8指向NAND FLASH的page,从第0页开始读
ldr r9, =ResetEntry ;(2)这里,注意区别(1)处的adr r0, ResetEntry。此时只是简单地把ResetEntry这个标号地址加载到r9,所以r9=0x30100000?
2
ands r0, r8, #0x1f ;判断r0是否为0,如果r0!=0,则执行%F3,开始读NAND FLASH上的数据。当r8=0,32,64,96,...时,r0=0,要进行CheckBadBlk,也就是说,每遇到某一个block的第0页时(1 block=32 pages),就进行坏块检查,如果该页有错,则整个block有错
bne %F3
mov r0, r8 ;r0作为参数,对页号0,32,64,...进行坏块检查
bl CheckBadBlk
cmp r0, #0 ;r0作也为返回值,如果r0=0,则该页没错,非坏块,可以读取数据;如果r0!=0,表示该页有错,则整块有错,从而r8+32,去判断下一块的第0页是否有错。
addne r8, r8, #32
bne %F4
3
mov r0, r8 ;r0作为输入参数,指向NAND FLASH的第r8页
mov r1, r9 ;r1作为输入参数,指向SDRAM, 第一次指向0x30100000
bl ReadNandPage ;一页读取完毕,把NAND FLASH中一页的代码(512字节),搬运到了SDRAM中了
add r9, r9, #512 ;SDRAM指针增加512字节
add r8, r8, #1 ;NAND FLASH指针增加一页
4
cmp r8, #256 ;只读取0~255,共256页,256*512=128KBytes,0x20000(试着改一下,多读或者少读几页)。实际hfrk_s3c2410_boot.bin也就54K。但在nand.c中定义了boot区的大小为0x30000,
bcc %B2 ;最后结果,把NAND FLASH前256页的代码、数据都搬运到了SDRAM中(把该bootloader的stage1和stage2一口气都搬到了SDRAM中?)
mov r5, #NFCONF ;DsNandFlash
ldr r0, [r5]
and r0, r0, #~0x8000
str r0, [r5]
ldr pc, =copy_proc_beg ;pc突变,从上面的指向SRAM,跳变到了指向SDRAM处的代码,但即将要执行的一下句语句没有突变,衔接得很好,因为上面的读NAND FLASH过程已经在SDRAM中准备好即将执行的代码
;===========================================================
copy_proc_beg
adr r0, ResetEntry ;这里又有了,区别于(1),此时r0=0x30100000,因为pc已经移高到SDRAM中
ldr r2, BaseOfROM ;|Image$$RO$$Base| = 0x30100000
cmp r0, r1 ;为什么要跟r1比较,r1存放的是什么值?
ldreq r0, TopOfROM ;|Image$$RO$$Limit| = 0x3010ce94
beq InitRam
ldr r3, TopOfROM ;|Image$$RO$$Limit| = 0x3010ce94
0
ldmia r0!, {r4-r7} ;把r0所指地址开始的4个字加载到r4~r7,然后r0自增4
stmia r2!, {r4-r7} ;把r4~r7的值写入r2所指地址开始的4字空间,然后r2自增4
cmp r2, r3 ;r2增加到与r3相同
bcc %B0
sub r2, r2, r3 ;r2=0
sub r0, r0, r2 ;r0=0x3010ce94
InitRam
ldr r2, BaseOfBSS ;|Image$$RW$$Base| = 0x3010ce94
ldr r3, BaseOfZero ;|Image$$ZI$$Base| = 0x3010cf58
0
cmp r2, r3
ldrcc r1, [r0], #4 ;把|Image$$RO$$Limit|以上的数据拷贝到以|Image$$RW$$Base|为起始地址的区域中
strcc r1, [r2], #4
bcc %B0
mov r0, #0
ldr r3, EndOfBSS ;|Image$$ZI$$Limit| = 0x301a3228
1
cmp r2, r3
strcc r0, [r2], #4
bcc %B1
;send reset status to main function
ldr r1, =GSTATUS2
ldr r0, [r1]
str r0, [r1] ;clear reset status
[ :LNOT:THUMBCODE
ldr pc, GotoMain ;bl Main ;Don't use main() because ...... ;pc寄存器被赋值为Main函数的起始地址0x3010441c,开始执行C语言
b .
]
[ THUMBCODE ;for start-up code for Thumb mode
orr lr,pc,#1
bx lr
CODE16
bl Main ;Don't use main() because ......
b .
CODE32
]
;===========================================================
EXPORT disable_irq
disable_irq
mrs r0, cpsr ;enter svc mode and disable irq,fiq
orr r0, r0, #0xc0
msr cpsr_c, r0
mov pc, lr
ReadNandID
mov r7,#NFCONF
ldr r0,[r7,#0] ;NFChipEn();
bic r0,r0,#0x800
str r0,[r7,#0]
mov r0,#0x90 ;WrNFCmd(RdIDCMD);
strb r0,[r7,#4]
mov r4,#0 ;WrNFAddr(0) ;0表示什么意思?
strb r4,[r7,#8]
1 ;while(NFIsBusy());
ldr r0,[r7,#0x10] ;读NFSTAT寄存器
tst r0,#1 ;0=BUSY;1=READ TO OPERATE;当r0 AND #1的结果全为0时,Z set,表示equal
beq %B1
ldrb r0,[r7,#0xc] ;id=RdNFDat()<<8 ;厂商ID 此处为0xec
mov r0,r0,lsl #8
ldrb r1,[r7,#0xc] ;id|=RdNFDat() ;设备ID 此处为0x76
orr r5,r1,r0 ;r5作为返回值
ldr r0,[r7,#0] ;NFChipDs();
orr r0,r0,#0x800
str r0,[r7,#0]
mov pc,lr
ReadNandStatus
mov r7,#NFCONF
ldr r0,[r7,#0] ;NFChipEn();
bic r0,r0,#0x800
str r0,[r7,#0]
mov r0,#0x70 ;WrNFCmd(QUERYCMD) ;读取NAND FLASH CHIP的状态的命令,该命令写入NFCMD寄存器
strb r0,[r7,#4]
ldrb r1,[r7,#0xc] ;r1 = RdNFDat() ;r1返回NAND FLASH CHIP的状态
ldr r0,[r7,#0] ;NFChipDs();
orr r0,r0,#0x800
str r0,[r7,#0]
mov pc,lr
WaitNandBusy
mov r0,#0x70 ;WrNFCmd(QUERYCMD);
mov r1,#NFCONF
strb r0,[r1,#4]
1 ;while(!(RdNFDat()&0x40));
ldrb r0,[r1,#0xc]
tst r0,#0x40
beq %B1
mov r0,#0 ;WrNFCmd(READCMD0);
strb r0,[r1,#4]
mov pc,lr
CheckBadBlk ;r0作为参数,代表页号0,32,64,...,同时也作为返回值
mov r7, lr
mov r5, #NFCONF
bic r0, r0, #0x1f ;addr &= ~0x1f ;低5位清零,防止低5位数据不稳定
ldr r1,[r5,#0] ;NFChipEn()
bic r1,r1,#0x800
str r1,[r5,#0]
mov r1,#0x50 ;WrNFCmd(READCMD2) ;写0x50命令,表示对OOB(也称为C区)区进行寻址
strb r1,[r5,#4]
mov r1, #6
strb r1,[r5,#8] ;WrNFAddr(6) ; b0000 0110,A0~A7,表示在A区或B区或C区内的偏移地址,此处已经用0x50命令指定了是对C区进行寻址,可以不用设置A8。OOB区第6个字节(也就是说是整页的第517字节)用来标记坏块,所以这里的偏移值为6。如果不是坏块,该字节标记为0xFF
strb r0,[r5,#8] ;WrNFAddr(addr) ;(以r0=32为例) b0010 0000,A9~A16,其中的A9~A13是对页进行寻址,此时是b000000,表示第0页
mov r1,r0,lsr #8 ;WrNFAddr(addr>>8) ; b0000 0000,A17~A24,A14~A25是对块进行寻址,此时是b0000 0000 0001,表示第1块。所以整个例子的意思是:对第1块第0页(也就是绝对页地址为32)的C区中的第6字节进行寻址
strb r1,[r5,#8]
cmp r6,#0 ;if(NandAddr) ;不知道是什么意思:(
movne r0,r0,lsr #16 ;WrNFAddr(addr>>16) ; b0, A25
strneb r0,[r5,#8]
bl WaitNandBusy ;WaitNFBusy()
ldrb r0, [r5,#0xc] ;RdNFDat() ;在写命令,写地址之后,在NFDATA寄存器中准备好了NAND FLASH提供的查询结果,可以读取了
sub r0, r0, #0xff ;返回值r0=0,表示非坏块
mov r1,#0 ;WrNFCmd(READCMD0) ;这两句好像是多余的
strb r1,[r5,#4]
ldr r1,[r5,#0] ;NFChipDs()
orr r1,r1,#0x800
str r1,[r5,#0]
mov pc, r7
ReadNandPage
mov r7,lr
mov r4,r1 ;r4指向SDRAM
mov r5,#NFCONF
ldr r1,[r5,#0] ;NFChipEn()
bic r1,r1,#0x800
str r1,[r5,#0]
mov r1,#0 ;WrNFCmd(READCMD0) ;表示将要读取某一页的A区,并且将内置指针指向A区的第0个字节
strb r1,[r5,#4]
strb r1,[r5,#8] ;WrNFAddr(0) ; b0000 0000,A0~A7,表示从A区的第0个字节开始
strb r0,[r5,#8] ;WrNFAddr(addr) ;r0指向NAND FLASH的某一页,仍然以r0=32为例。b0010 0000,A9~A16,其中的A9~A13,即b00000,是对页进行寻址,此时是第0页
mov r1,r0,lsr #8 ;WrNFAddr(addr>>8) b0000 0000,A17~A24,A14~A25,即b0000 0000 0001,是对块进行寻址,此时是第1块
strb r1,[r5,#8]
cmp r6,#0 ;if(NandAddr)
movne r0,r0,lsr #16 ;WrNFAddr(addr>>16) b0, A25
strneb r0,[r5,#8]
ldr r0,[r5,#0] ;InitEcc()
orr r0,r0,#0x1000
str r0,[r5,#0]
bl WaitNandBusy ;WaitNFBusy()
mov r0,#0 ;for(i=0; i<512; i++) ;r0改变角色,从指针变为循环变量,
1
ldrb r1,[r5,#0xc] ;buf[i] = RdNFDat() ;写完命令,写完地址,NAND FLASH中该页的512个bytes就自动逐个寄存在NFDATA寄存器中(也就是说,读取一页NAND FLASH,只需要写一次命令和一个地址就可以了)
strb r1,[r4,r0] ;从NFDATA读出一个字,写入r4+r0所指的SDRAM中
add r0,r0,#1 ;循环变量+1
bic r0,r0,#0x10000 ;此句不懂:(
cmp r0,#0x200 ;比较NAND FLASH中该页是不是已经读完
bcc %B1 ;如果没读完,继续读
ldr r0,[r5,#0] ;NFChipDs()
orr r0,r0,#0x800
str r0,[r5,#0]
mov pc,r7
;===========================================================
;function initializing stacks
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
mrs r0,cpsr ;读cpsr寄存器,专用指令mrs
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode 通过写cpsr,使处理器进入不同的模式
ldr sp,=UndefStack ;在该模式下,设置堆栈指针。以下各sp并没有相互覆盖,因为不同处理器模式下各自都有sp这个寄存器
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack
;USER mode has not be initialized.
mov pc,lr
;The LR register won't be valid if the current mode is not SVC mode.
LTORG
SMRDATA DATA
; Memory configuration should be optimized for best performance
; The following parameter is not optimized.
; Memory access cycle parameter strategy
; 1) The memory settings is safe parameters even at HCLK=75Mhz.
; 2) SDRAM refresh period is for HCLK=75Mhz.
DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) ;BUS WIDTH & WAIT CONTROL REGESTER。
DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0 ;BANK CONTROL REGESTER,对BANK0~BANK5分别设置
DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
DCD 0x1f7c;((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6 ;BANK CONTROL REGESTER,BANK6/BANK7使用SDRAM
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) ;REFRESH CONTROL REGESTER
DCD 0x31 ;SCLK power saving mode, BANKSIZE 64M/64M ;BANK SIZE REGESTER
DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7
; DCD 0x20 ;MRSR6 CL=2clk
; DCD 0x20 ;MRSR7
BaseOfROM DCD |Image$$RO$$Base| ;以BaseOfROM为名的地址空间中存放了RO输出段运行时的基地址
TopOfROM DCD |Image$$RO$$Limit|
BaseOfBSS DCD |Image$$RW$$Base|
BaseOfZero DCD |Image$$ZI$$Base|
EndOfBSS DCD |Image$$ZI$$Limit|
GBLS main_entry ;定义全局字符串变量main_entry
main_entry SETS "Main" ;给该字符串变量赋值为字符串"Main"
IMPORT $main_entry ;把变量的值IMPORT进来(获取Main函数首地址)
GotoMain DCD $main_entry ;在GotoMain这个标号代表的空间中(0x301005d8)存放该变量的值,即Main函数入口地址0x3010441c,用于赋值给pc,跳到Main函数
ALIGN
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;Don't use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -