FL2440无操作系统应用程序编写测试001——2440init.s分析修改

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,实现跳转。栈操作情况如下图所示:

FL2440无操作系统应用程序编写测试001——2440init.s分析修改_第1张图片

       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的次序排列的,可以利用该值生成中断处理程序地址,然后跳转执行。栈操作情况如下图所示:

FL2440无操作系统应用程序编写测试001——2440init.s分析修改_第2张图片

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]

 

FL2440无操作系统应用程序编写测试001——2440init.s分析修改_第3张图片

       ldr   r0,=CLKDIVN                    

       ldr   r1,=CLKDIV_VAL         ;5=1:4:8  

       str   r1,[r0]

 

       FL2440无操作系统应用程序编写测试001——2440init.s分析修改_第4张图片

;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

 

FL2440无操作系统应用程序编写测试001——2440init.s分析修改_第5张图片

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

 

 

你可能感兴趣的:(FL2440无操作系统应用程序编写测试001——2440init.s分析修改)