⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410start.s.txt

📁 bootloader 的启动汇编代码 start.s的注释
💻 TXT
📖 第 1 页 / 共 2 页
字号:
	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 + -