2440INIT.s详解

    技术2022-05-19  20

     

    ;=========================================

    ; NAME: 2440INIT.S

    ; DESC: C start up codes

    ;       Configure memory, ISR ,stacks

    ;        Initialize C-variables

    ; HISTORY:

    ; 2002.02.25:kwtark: ver 0.0

    ; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode

    ; 2003.03.14:DonGo: Modified for 2440.

    ;=========================================

     

    ;首先,启动代码定义了一些常量

    ;//GET类似于C语言的includeoption.inc文件内定义了一些全局变量,memcfg.inc文件内定义了关于内存bank的符号和数字常量,2440addr.inc文件内定义了用于汇编的s3c2440寄存器变量和地址

    GET  option.inc

    GET  memcfg.inc

    GET  2440addr.inc

     

    BIT_SELFREFRESH  EQU   (1<<22)     ;//#define BIT_SELFREFRESH (1<<22)

     

    ;//arm处理器模式寄存器对应的常数进行赋值,arm处理器有一个CPSR寄存器,它的后五位决定了处理器处于哪个模式下

     

    USERMODE    EQU     0x10 FIQMODE     EQU     0x11 IRQMODE     EQU     0x12 SVCMODE     EQU     0x13 ABORTMODE   EQU     0x17 UNDEFMODE   EQU     0x1b MODEMASK    EQU     0x1f NOINT          EQU     0xc0     ;//禁止IRQ中断,FIQ中断

     

    ;//定义了7种处理器模式下的栈的起始地址,其中用户模式和系统模式共有一个栈空间 UserStack    EQU    (_STACK_BASEADDRESS-0x3800)      ;0x33ff4800 ~ SVCStack    EQU    (_STACK_BASEADDRESS-0x2800)      ;0x33ff5800 ~ UndefStack    EQU    (_STACK_BASEADDRESS-0x2400)    ;0x33ff5c00 ~ AbortStack    EQU    (_STACK_BASEADDRESS-0x2000)    ;0x33ff6000 ~ IRQStack    EQU    (_STACK_BASEADDRESS-0x1000)      ;0x33ff7000 ~ FIQStack    EQU    (_STACK_BASEADDRESS-0x0)         ;0x33ff8000 ~

     

     

     

     

    ;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.

    ;//这一段是统一arm的工作状态和对应的软件编译方式(16位编译环境使用tasm.exe编译)。 ;//arm处理器的工作状态分为两种:32位,arm执行字对齐的arm指令集;16位,arm执行半字对齐的Thumb指令集。 ;//不同的工作状态,编译方式也不一样。所以下面的程序就是判断arm的工作方式来确定它的编译方式。

             GBLL    THUMBCODE      ;//定义THUMBCODE全局变量

             [ {CONFIG} = 16            ;//如果发现时采用16位代码的话   

    THUMBCODE SETL  {TRUE}      ;//THUMBCODE设置为TRUE

                 CODE32               ;//把处理器重新设置成ARM模式

                     |                    ;//如果处理器现在就是ARM模式

    THUMBCODE SETL  {FALSE}         ;//THUMBCODE设置为FALSE

    ]

     

                     MACRO     ;定义一个宏,一个根据THUMBCODEPC寄存器的值保存到LR的宏

             MOV_PC_LR    

                     [ THUMBCODE

                 bx lr            ;ARM模式中要使用BX指令跳转到THUMB指令,并转换模式

                     |

                 mov pc,lr           ;如果目标地址也是Arm指令的话就采用这种方式

                     ]

             MEND

     

                     MACRO

             MOVEQ_PC_LR

                     [ THUMBCODE

            bxeq lr          ;//r14

                     |

                 moveq pc,lr

                     ]

             MEND

     

                       MACRO

    $HandlerLabel  HANDLER  $HandleLabel

    $HandlerLabel        //

             sub   sp,sp,#4   ;decrement sp(to store jump address)减少sp(用于存放跳转地址)

             stmfd        sp!,{r0}     ;把工作寄存器压入栈

             ldr     r0,=$HandleLabel  ;Handlexxx的地址放入r0

             ldr     r0,[r0]         ;Handlexxx所指向的内容(也就是中断程序的入口)放入r0

             str     r0,[sp,#4]      ;把中断服务程序(ISR)压入栈

             ldmfd   sp!,{r0,pc}     ;用出栈的方式恢复r0的原值和为pc设定新值(也就完成了到ISR的跳转)

             MEND

    IMPORT  |Image$$RO$$Base|     ;代码的开始地址

    IMPORT  |Image$$RO$$Limit|  ; ROM code的结束地址(=ROM data 的开始地址)

    IMPORT  |Image$$RW$$Base|   ; 要初始化的RAM的开始地址

    IMPORT  |Image$$ZI$$Base|   ; area(需要清零的RAM区域)的开始地址

    IMPORT  |Image$$ZI$$Limit|  ; area的结束地址

     

    IMPORT   MMU_SetAsyncBusMode

    IMPORT   MMU_SetFastBusMode

     

    IMPORT  Main    ; The main entry of mon program

     

     

    AREA    Init,CODE,READONLY      ;这表明下面是一个名为init的代码段

     

    ENTRY          ;定义程序的入口

            

    EXPORT    __ENTRY

    __ENTRY

    ;========

    ;复位

    ;========

    ResetEntry

    ;1)The code, which converts to Big-endian, should be in little endian code.

    ;2)The following little endian code will be compiled in Big-Endian mode.

    ;  The code byte order should be changed as the memory bus width.

    ;3)The pseudo instruction,DCD can t be used here because the linker generates error.

    ASSERT     :DEF:ENDIAN_CHANGE

    [ ENDIAN_CHANGE      ;下面是大小端的一个判断,在option.inc里已经设为FALSE

    ASSERT  :DEF:ENTRY_BUS_WIDTH

    [ ENTRY_BUS_WIDTH=32

    b       ChangeBigEndian        ;DCD 0xea000007

    ]

     

     [ ENTRY_BUS_WIDTH=16

    andeq       r14,r7,r0,lsl #20   ;DCD 0x0007ea00

    ]

     

     [ ENTRY_BUS_WIDTH=8

    streq         r0,[r0,-r10,ror #1]  ;DCD 0x070000ea

    ]

    |

    b       ResetHandler    ;设成FALSE的话就来到这了,跳转到复位程序入口

    ]

     

    b       HandlerUndef                  ;跳转到Undefined mode程序入口

    b       HandlerSWI               ;跳转到SWI中断程序入口

    b       HandlerPabort                   ;跳转到PAbort(指令异常)程序入口

    b       HandlerDabort         ;跳转到DAbort(数据异常)程序入口

    b       .                 ;保留

    b       HandlerIRQ      ;跳转到IRQ中断程序入口

    b       HandlerFIQ       ;跳转到FIQ中断程序入口

     

    ;@0x20

    b       EnterPWDN     ; Must be @0x20.

     

    ;================================================================================== ;下面是改变大小端的程序,这里采用直接定义机器码的方式,至说为什么这么做就得问三星了 ;反正我们程序里这段代码也不会去执行,不用去管它 ;================================================================================== ChangeBigEndian  ;@0x24 [ ENTRY_BUS_WIDTH=32 DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0 DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0 ] [ ENTRY_BUS_WIDTH=16 DCD 0x0f10ee11 DCD 0x0080e380 DCD 0x0f10ee01 ] [ ENTRY_BUS_WIDTH=8 DCD 0x100f11ee DCD 0x800080e3 DCD 0x100f01ee ] DCD 0xffffffff        ;swinv 0xffffff is similar with NOP and run well in both endian mode. DCD 0xffffffff DCD 0xffffffff DCD 0xffffffff DCD 0xffffffff b ResetHandler

     

     

    ;根据上述宏定义,HandlerHandle之间的联系

    HandlerFIQ      HANDLER  HandleFIQ

    HandlerIRQ      HANDLER  HandleIRQ

    HandlerUndef    HANDLER  HandleUndef

    HandlerSWI      HANDLER  HandleSWI

    HandlerDabort   HANDLER  HandleDabort

    HandlerPabort   HANDLER  HandlePabort

     

     

    ;=================================================================================== ;第二次查表的,不懂 ;=================================================================================== IsrIRQ sub sp,sp,#4       ;PC寄存器保留 stmfd sp!,{r8-r9} ;r8-r9压入栈 ldr r9,=INTOFFSET    ;INTOFFSET的地址装入r9 ldr r9,[r9]                    ;INTOFFSET的值装入r9 ldr r8,=HandleEINT0   ;这就是我们第二个中断向量表的入口的,先装入r8

    add r8,r8,r9,lsl #2 ldr r8,[r8]                    ;;装入中断服务程序的入口 str r8,[sp,#8]              ;str不是入栈,只是把r0值放到sp+8这个地址上面

    ldmfd sp!,{r8-r9,pc}    ;一个个出栈,跳转

     

    LTORG               ;//声明文字池,因为用了ldr伪指令 ldr存储器到寄存器的数据传输指令

     

    ;=======

    ; ENTRY

    ;=======

    ResetHandler

    ldr    r0,=WTCON       ;1watch dog disable关开门狗

    ldr    r1,=0x0

    str    r1,[r0]

     

    ldr    r0,=INTMSK

    ldr    r1,=0xffffffff                     ;2all interrupt disable关中断

    str    r1,[r0]

     

    ldr    r0,=INTSUBMSK

    ldr    r1,=0x7fff                                      ;3all sub interrupt disable关子中断

    str    r1,[r0]

     

             ;4led显示

             [ {FALSE}

             ; rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);

             ; Led_Display

             ldr    r0,=GPFCON

             ldr    r1,=0x5500

             str    r1,[r0]

             ldr    r0,=GPFDAT

             ldr    r1,=0x10

             str    r1,[r0]

             ]

     

    ;5.为了减少PLLlock time, 调整LOCKTIME寄存器. ldr r0,=LOCKTIME ldr r1,=0xffffff str r1,[r0] [ PLL_ON_START    ;6.下面就来设置PLL,你的板快不快就看这了!!                                   ; Added for confirm clock divide. for 2440.                     ; 设定Fclk:Hclk:Pclk ldr r0,=CLKDIVN ldr r1,=CLKDIV_VAL ; 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, str r1,[r0] ; 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.

     

    [ CLKDIV_VAL>1               ; means Fclk:Hclk is not 1:1.

    mrc p15,0,r0,c1,c0,0

    orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA

    mcr p15,0,r0,c1,c0,0

    |

    mrc p15,0,r0,c1,c0,0

    bic r0,r0,#0xc0000000;R1_iA:OR:R1_nF

    mcr p15,0,r0,c1,c0,0

    ]

     

    ;Configure UPLL

    ldr    r0,=UPLLCON

    ldr    r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)  

    str    r1,[r0]

    nop           ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.

    nop

    nop

    nop

    nop

    nop

    nop

     

    ;Configure MPLL

    ldr    r0,=MPLLCON

    ldr    r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)  ;Fin=16.9344MHz

    str    r1,[r0]

     ]

     

    ;检查是否从SLEEP模式中恢复 ldr r1,=GSTATUS2 ldr r0,[r1] tst r0,#0x2 ;如果是从SLEEP模式中恢复, 转跳到SLEEP_WAKEUP. bne WAKEUP_SLEEP EXPORT StartPointAfterSleepWakeUp ;导出符号StartPointAfterSleepWakeUp StartPointAfterSleepWakeUp

    ;=============================================================================== ;设置内存控制器等寄存器的值,因为这些寄存器是连续排列的,所以采用如下办法对这些 ;寄存器进行连续设置.其中用到了SMRDATA的数据,这在代码后面有定义 ;=============================================================================== ;ldr r0,=SMRDATA adrl r0, SMRDATA ;be careful!, hzh ldr r1,=BWSCON ;BWSCON 地址 add r2, r0, #52 ;SMRDATA数据的结束地址,共有52字节的数据 0 ldr r3, [r0], #4 str r3, [r1], #4 cmp r2, r0 bne

    转载请注明原文地址: https://ibbs.8miu.com/read-2209797.html

    最新回复(0)