Subject:FL2440无操作系统应用程序编写测试001——2440init.s分析修改
Date: 7-Nov-2011
By: Calvinlee1984@163.com
1.本文在2440init.s基础上作部分修改,力求精简易懂
2. 开发板相关配置
CPU: 32440001(2440A)
XTAL: 12000000(12Mhz)
FCLK: 400000000(400Mhz)
UCLK: 48000000(48Mhz)
Pll: PLL_ON_START
Endian: LittleEndian
BusWidth: 32
BootMode: NAND Flash
Bank0: SRAM
Bank4: DM9000
Bank6: SDRAM(Hynix H57V2562TR-75C,0x30000000-0x33ffffff)
3.代码分析
;汇编头文件
GET option.inc
GET memcfg.inc
GET 2440addr.inc
;定义处理器各模式常量及栈地址(_STACK_BASEADDRESS为栈基址)
UserMode EQU 0x10
FIQMode EQU 0x11
IRQMode EQU 0x12
SVCMode EQU 0x13
AbortMode EQU 0x17
UndefMode EQU 0x1b
ModeMask EQU 0x1f
NOINT EQU 0xc0
UserStack EQU (_STACK_BASEADDRESS-0x3800)
SVCStack EQU (_STACK_BASEADDRESS-0x2800)
UndefStack EQU (_STACK_BASEADDRESS-0x2400)
AbortStack EQU (_STACK_BASEADDRESS-0x2000)
IRQStack EQU (_STACK_BASEADDRESS-0x1000)
FIQStack EQU (_STACK_BASEADDRESS-0x0000)
;定义宏$HandlerLabel HANDLER $HandleLabel,该宏用于重定向系统异常或中断发生的处理程序,原理是获取$HandleLabel指定的异常或中断处理程序的地址,并将此地址赋于PC,实现跳转。栈操作情况如下图所示:
MACRO ;宏开始
$HandlerLabel HANDLER $HandleLabel ;宏名
$HandlerLabel ;标号
sub sp,sp,#4 ;①为PC预留地址空间
stmfd sp!,{r0} ;②保存工作组寄存器
ldr r0,=$HandleLabel ;③获取异常或中断处理程序的地址
ldr r0,[r0] ;④
str r0,[sp,#4] ;⑤将该地址所指中断处理程序入口存入预留地址空间
ldmfd sp!,{r0,pc} ;⑥恢复工作组寄存器内容并跳转至中断处理程序
MEND ;宏结束
;引用外部Main函数
IMPORT Main
;代码段
AREA Init,CODE,READONLY
ENTRY
EXPORT __ENTRY
__ENTRY
;异常或中断向量表
;@0x00
ResetEntry
b ResetHandler
;@0x04
b HandlerUndef
;@0x08
b HandlerSWI
;@0x0c
b HandlerPabort
;@0x10
b HandlerDabort
;@0x14
b .
;@0x18
b HandlerIRQ
;@0x1c
b HandlerFIQ
;@0x20(EnterPWDN)
b .
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
;二次重定向中断处理程序。中断(IRQ)源多种多样,通过INTOFFSET中断源偏置值可以确定是何种中断。HandleEINT0及之后的地址是按INTOFFSET的次序排列的,可以利用该值生成中断处理程序地址,然后跳转执行。栈操作情况如下图所示:
IsrIRQ
sub sp,sp,#4 ;①为PC预留地址空间
stmfd sp!,{r8-r9} ;②保存工作组寄存器
ldr r9,=INTOFFSET ;③
ldr r9,[r9] ;④获取中断源偏置值INTOFFSET
ldr r8,=HandleEINT0 ;⑤读取HandleEINT0地址
add r8,r8,r9,lsl #2 ;⑥生成中断处理程序地址ISR=IvectTable + offset*4
ldr r8,[r8] ;⑦
str r8,[sp,#8] ;⑧将该地址所指中断处理程序入口存入预留地址空间
ldmfd sp!,{r8-r9,pc} ;⑨恢复工作组寄存器内容并跳转至中断处理程序
LTORG ;声明文字池
;上电或复位程序入口
ResetHandler
;(1)禁止看门狗及中断
ldr r0,=WTCON
ldr r1,=0x0
str r1,[r0]
ldr r0,=INTMSK
ldr r1,=0xffffffff
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x7fff
str r1,[r0]
;(2)设置锁相环PLL
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
ldr r0,=CLKDIVN
ldr r1,=CLKDIV_VAL ;5=1:4:8
str r1,[r0]
;MMU_SetAsyncBusMode
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)
str r1,[r0]
;UPLL及MPLL的设定须相隔7个或以上nop时间
nop
nop
nop
nop
nop
nop
nop
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)
str r1,[r0]
;(3)设置内存控制器
adrl r0, SMRDATA
ldr r1,=BWSCON
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0 ;%表搜索,B-Backward,F-Foreward,0-局部标号(0-99)
;(4)初始化堆栈
mrs r0,cpsr
bic r0,r0,#ModeMask
orr r1,r0,#UndefMode|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack ;UndefStack=0x33FF_5C00
orr r1,r0,#AbortMode|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack ;AbortStack=0x33FF_6000
orr r1,r0,#IRQMode|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack ;IRQStack=0x33FF_7000
orr r1,r0,#FIQMode|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack ;FIQStack=0x33FF_8000
bic r0,r0,#ModeMask|NOINT
orr r1,r0,#SVCMode
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack ;SVCStack=0x33FF_5800
;(5)读取NAND Flash至SDRAM,然后跳转至SDRAM中执行
mov r5, #NFCONF
;set timing value
ldr r0, =(7<<12)|(7<<8)|(7<<4)
str r0, [r5]
;enable control
ldr r0, =(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)
str r0, [r5, #4] ;->NFCONT
bl ReadNandID ;读取NAND的ID号并存入r5
mov r6, #0
ldr r0, =0xec73 ;期望的NAND ID号
cmp r5, r0
beq %F1
ldr r0, =0xec75 ;另一期望的NAND ID号
cmp r5, r0
beq %F1
mov r6, #1 ;如果都不匹配,则置r6为1
1
bl ReadNandStatus ;读取NAND的状态,并将结果存入r1
mov r8, #0 ;页号存入r8
ldr r9, =ResetEntry ;入口程序地址存入r9
2
ands r0, r8, #0x1f ;从每块开始页进行检错
bne %F3
mov r0, r8
bl CheckBadBlk ;检查NAND坏块
cmp r0, #0 ;若坏块则跳至下一块
addne r8, r8, #32 ;每一块32页
bne %F4
3
mov r0, r8 ;当前页号->r0
mov r1, r9 ;当前目标地址->r1
bl ReadNandPage ;读取当前该页的数据到RAM
add r9, r9, #512 ;每一页512Bytes
add r8, r8, #1 ; r8指向下一页
4
cmp r8, #256 ;256页
bcc %B2
mov r5, #NFCONF ;DsNandFlash
ldr r0, [r5, #4]
bic r0, r0, #1
str r0, [r5, #4]
ldr pc, =%F1
;(6)安装中断向量表
1
ldr r0,=HandleIRQ
ldr r1,=IsrIRQ
str r1,[r0]
;(7)跳入Main函数
bl Main
b .
;子程序->读取NAND ID
ReadNandID
mov r7,#NFCONF
ldr r0,[r7,#4] ;->NFCONT
bic r0,r0,#2 ;Enable Chip Select
str r0,[r7,#4]
mov r0,#0x90 ;Read NAND ID CMD
strb r0,[r7,#8] ;->NFCMMD
mov r4,#0 ;WrNFAddr(0);
strb r4,[r7,#0xc] ;->NFADDR
1 ;while(NFIsBusy());
ldr r0,[r7,#0x20] ;->NFSTAT
tst r0,#1 ;NFSTAT[0]=0->NAND Flash memory busy,NFSTAT[1]=1->NAND Flash memory ready to operate
beq %B1
ldrb r0,[r7,#0x10] ;->NFDATA
mov r0,r0,lsl #8 ;id = RdNFDat()<<8
ldrb r1,[r7,#0x10] ;->NFDATA
orr r5,r1,r0 ;id |= RdNFDat();
ldr r0,[r7,#4] ;->NFCONT
orr r0,r0,#2 ;Disable Chip Select
str r0,[r7,#4]
mov pc,lr
;子程序->读取NAND Status
ReadNandStatus
mov r7,#NFCONF ;->2440addr.inc
ldr r0,[r7,#4] ;->NFCONT
bic r0,r0,#2 ;NFChipEn();
str r0,[r7,#4]
mov r0,#0x70 ;WrNFCmd(QUERYCMD);
strb r0,[r7,#8] ;->NFCMMD
ldrb r1,[r7,#0x10] ;r1 = RdNFDat();
ldr r0,[r7,#4] ;->NFCONT
orr r0,r0,#2 ;NFChipDs()
str r0,[r7,#4]
mov pc,lr
WaitNandBusy
mov r0,#0x70 ;WrNFCmd(QUERYCMD);
mov r1,#NFCONF
strb r0,[r1,#8] ;NFCMMD
1 ;while(!(RdNFDat()&0x40));
ldrb r0,[r1,#0x10] ;NFDATA
tst r0,#0x40
beq %B1
mov r0,#0 ;WrNFCmd(READCMD0);
strb r0,[r1,#8] ;NFCMMD
mov pc,lr
;子程序->检查坏块
CheckBadBlk
mov r7, lr
mov r5, #NFCONF
bic r0,r0,#0x1f ;addr &= ~0x1f;
ldr r1,[r5,#4] ;->NFCONT
bic r1,r1,#2 ;Enable Chip Set
str r1,[r5,#4]
mov r1,#0x50 ;WrNFCmd(READCMD2)
strb r1,[r5,#8] ;->NFCMMD
mov r1, #5 ;6 ;6->5
strb r1,[r5,#0xc] ;WrNFAddr(5);(6) 6->5
strb r0,[r5,#0xc] ;WrNFAddr(addr)
mov r1,r0,lsr #8
strb r1,[r5,#0xc] ;WrNFAddr(addr>>8)
cmp r6,#0 ;if(NandAddr)
movne r0,r0,lsr #16 ;WrNFAddr(addr>>16)
strneb r0,[r5,#0xc]
mov r0, #100
1
subs r0, r0, #1
bne %B1
2
ldr r0, [r5, #0x20] ;->NFSTAT
tst r0, #1
beq %B2
ldrb r0, [r5,#0x10] ;RdNFDat()
sub r0, r0, #0xff
mov r1,#0 ;WrNFCmd(READCMD0)
strb r1,[r5,#8]
ldr r1,[r5,#4] ;NFChipDs()
orr r1,r1,#2
str r1,[r5,#4]
mov pc, r7
;子程序->读到当前页的数据
ReadNandPage
mov r7,lr
mov r4,r1 ;当前目标地址->r4
mov r5,#NFCONF
ldr r1,[r5,#4] ;NFChipEn()
bic r1,r1,#2
str r1,[r5,#4]
mov r1,#0 ;WrNFCmd(READCMD0)
strb r1,[r5,#8] ;->NFCMMD
strb r1,[r5,#0xc] ;WrNFAddr(0)
strb r0,[r5,#0xc] ;WrNFAddr(addr)
mov r1,r0,lsr #8 ;WrNFAddr(addr>>8)
strb r1,[r5,#0xc]
cmp r6,#0 ;if(NandAddr)
movne r0,r0,lsr #16 ;WrNFAddr(addr>>16)
strneb r0,[r5,#0xc]
ldr r0,[r5,#4] ;InitEcc()
orr r0,r0,#0x10
str r0,[r5,#4]
bl WaitNandBusy ;WaitNFBusy()
mov r0,#0 ;for(i=0; i<512; i++)
1
ldrb r1,[r5,#0x10] ;buf[i] = RdNFDat()
strb r1,[r4,r0]
add r0,r0,#1
bic r0,r0,#0x10000
cmp r0,#0x200 ;512Bytes
bcc %B1
ldr r0,[r5,#4] ;NFChipDs()
orr r0,r0,#2
str r0,[r5,#4]
mov pc,r7
ALIGN
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))
DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0
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 ((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
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Tsrc<<18)+(Tchr<<16)+REFCNT)
DCD 0x32 ;SCLK power saving mode, BANKSIZE 128M/128M
DCD 0x20 ;MRSR6 CL=3clk
DCD 0x20 ;MRSR7 CL=3clk
;数据段
ALIGN
AREA RamData, DATA, READWRITE
;异常或中断处理程序地址。从_ISR_STARTADDRESS开始,为各处理程序预留4字节的地址空间,为便于计算各中断子程序的地址,HandleEINT0及之后的地址空间按一定次序排列。
^ _ISR_STARTADDRESS ;_ISR_STARTADDRESS=0x33FF_FF00
HandleReset #4
HandleUndef #4
HandleSWI #4
HandlePabort #4
HandleDabort #4
HandleReserved #4
HandleIRQ #4
HandleFIQ #4
HandleEINT0 #4
HandleEINT1 #4
HandleEINT2 #4
HandleEINT3 #4
HandleEINT4_7 # 4
HandleEINT8_23 #4
HandleCAM #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
HandleNFCON #4
HandleUSBD #4
HandleUSBH #4
HandleIIC #4
HandleUART0 #4
HandleSPI1 #4
HandleRTC #4
HandleADC # 4
END