打印

2440启动代码ADS.KEIL.(大狭帮忙注解!)(新1)

[复制链接]
6455|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
avocationA|  楼主 | 2008-9-10 22:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
;=========================================
; 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 option.inc
    GET memcfg.inc
    GET 2440addr.inc

BIT_SELFREFRESH EQU    (1<<22)    ;bit[22]=1,others=0

;Pre-defined constants        ;系统的工作模式设定
USERMODE    EQU     0x10
FIQMODE     EQU     0x11
IRQMODE     EQU     0x12
SVCMODE     EQU     0x13
ABORTMODE   EQU     0x17
UNDEFMODE   EQU     0x1b
MODEMASK    EQU     0x1f
NOINT       EQU     0xc0

;The location of stacks        ;系统的堆栈空间设定
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 ~

;arm处理器有两种工作状态 1.arm:32位 这种工作状态下执行字对准的arm指令 2.Thumb:16位 这种工作状
;态执行半字对准的Thumb指令 
;因为处理器分为16位 32位两种工作状态 程序的编译器也是分16位和32两种编译方式 所以下面的程序用
;于根据处理器工作状态确定编译器编译方式 
;code16伪指令指示汇编编译器后面的指令为16位的thumb指令 
;code32伪指令指示汇编编译器后面的指令为32位的arm指令 
;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译
;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.

    GBLL    THUMBCODE    ;定义一个全局变量
    [ {CONFIG} = 16            ;if config==16 这里表示你的目前处于领先地16位编译方式
THUMBCODE SETL  {TRUE}        ;设置THUMBCODE 为 true表示告诉系统当前想用thumb,但实际启动时不行,只能启动后再跳
                            ; ][|]表示if else endif 
        CODE32                ;启动时强制使用32位编译模式
         |
THUMBCODE SETL  {FALSE}        ;如果系统要求是ARM指令,则直接设置THUMBCODE 为 false 说明当前的是32位编译模式
    ]

         MACRO                ;宏定义
    MOV_PC_LR
         [ THUMBCODE
        bx lr
         |
        mov    pc,lr
         ]
    MEND

         MACRO
    MOVEQ_PC_LR
         [ THUMBCODE
        bxeq lr        ;相等Z=1,则跳转
         |
        moveq pc,lr
         ]
    MEND

;注意下面这段程序是个宏定义 很多人对这段程序不理解 我再次强调这是一个宏定义 所以大家要注意了
;下面包含的HandlerXXX HANDLER HandleXXX将都被下面这段程序展开 
;这段程序用于把中断服务程序的首地址装载到pc中,有人称之为“加载程序”。 
;本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字
;空间都有一个标号,以Handle***命名。 
;在向量中断模式下使用“加载程序”来执行中断服务程序。 
;这里就必须讲一下向量中断模式和非向量中断模式的概念 
;向量中断模式是当cpu读取位于0x18处的IRQ中断指令的时候,系统自动读取对应于该中断源确定地址上的;
;指令取代0x18处的指令,通过跳转指令系统就直接跳转到对应地址 
;函数中 节省了中断处理时间提高了中断处理速度标 例如 ADC中断的向量地址为0xC0,则在0xC0处放如下
;代码:ldr PC,=HandlerADC 当ADC中断产生的时候系统会 
;自动跳转到HandlerADC函数中 
;非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将interrupt 
;pending寄存器中对应标志位置位 然后跳转到位于0x18处的统一中断 
;函数中 该函数通过读取interrupt pending寄存器中对应标志位 来判断中断源 并根据优先级关系再跳到
;对应中断源的处理代码中

         MACRO 
$HandlerLabel HANDLER $HandleLabel

$HandlerLabel
    sub    sp,sp,#4    ;decrement sp(to store jump address)
    stmfd    sp!,{r0}    ;PUSH the work register to stack(lr does't push because it return to original address)
    ldr     r0,=$HandleLabel;load the address of HandleXXX to r0
    ldr     r0,[r0]     ;load the contents(service routine start address) of HandleXXX
    str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack
    ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)
    MEND
;将$HandleLabel地址空间中的数据给PC,中断服务程序的入口


    IMPORT  |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data)
    IMPORT  |Image$$RW$$Base|   ; Base of RAM to initialise
    IMPORT  |Image$$ZI$$Base|   ; Base and limit of area
    IMPORT  |Image$$ZI$$Limit|  ; to zero initialise

    IMPORT    Main
;导入要用到的字符常量

    AREA    Init,CODE,READONLY

;异常中断矢量表(每个表项占4个字节) 下面是中断向量表 一旦系统运行时有中断发生 即使移植了操作
;系统 如linux 处理器已经把控制权交给了操作系统 一旦发生中断 处理器还是会跳转到从0x0开始 
;中断向量表中某个中断表项(依据中断类型)开始执行 
;具体中断向量布局请参考s3c44b0 spec 例如 adc中断向量为 0x000000c0下面对应表中第49项位置 向量地址0x0+4*(49-1)=0x000000c0 

    ENTRY
;板子上电和复位后 程序开始从位于0x0处开始执行硬件刚刚上电复位后 程序从这里开始执行跳转到标
;为ResetHandler处执行

    ;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是否已定义
    [ ENDIAN_CHANGE                ;如果已经定义了ENDIAN_CHANGE,则判断,here is FALSE
        ASSERT  :DEF:ENTRY_BUS_WIDTH    ;判断ENTRY_BUS_WIDTH是否已定义
        ][ ENTRY_BUS_WIDTH=32    ;如果已经定义了ENTRY_BUS_WIDTH,则判断是不是为32
        b    ChangeBigEndian            ;DCD 0xea000007
        ]
    ;在bigendian中,地址为A的字单元包括字节单元A,A+1,A+2,A+3,字节单元由高位到低位为A,A+1,A+2,A+3
    ;                地址为A的字单元包括半字单元A,A+2,半字单元由高位到低位为A,A+2
        [ ENTRY_BUS_WIDTH=16
        andeq    r14,r7,r0,lsl #20   ;DCD 0x0007ea00    也是b    ChangeBigEndian指令,只是由于总线不一样而取机器码的顺序不一样
        ]                            ;先取低位->高位    上述指令是通过机器码装换而来的

        [ ENTRY_BUS_WIDTH=8
        streq    r0,][r0,-r10,ror #1] ;DCD 0x070000ea 也是b    ChangeBigEndian指令,只是由于总线不一样而取机器码的顺序不一样
        ]
    |
        b    ResetHandler        ;//here is the first instrument  0x00
    ]
    b    HandlerUndef    ;handler for Undefined mode    ;0x04
    b    HandlerSWI    ;handler for SWI interrupt        ;0x08
    b    HandlerPabort    ;handler for PAbort            ;0x0c
    b    HandlerDabort    ;handler for DAbort            ;0x10
    b    .        ;reserved                            ;0x14
    b    HandlerIRQ    ;handler for IRQ interrupt        ;0x18
    b    HandlerFIQ    ;handler for FIQ interrupt        ;0x1c

;@0x20
    b    EnterPWDN    ; Must be @0x20.


;通过设置CP15的C1的位7,设置存储格式为Bigendian,三种总线方式
ChangeBigEndian ;//here ENTRY_BUS_WIDTH=16
;@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
        ;对存储器控制寄存器操作,指定内存模式为Big-endian
        ;因为刚开始CPU都是按照32位总线的指令格式运行的,如果采用其他的话,CPU别不了,必须转化
        ;但当系统初始化好以后,则CPU能自动识别
    ]
    [ ENTRY_BUS_WIDTH=16
        DCD 0x0f10ee11
        DCD 0x0080e380
        DCD 0x0f10ee01
        ;因为采用Big-endian模式,采用16位总线时,物理地址的高位和数据的地位对应
        ;所以指令的机器码也相应的高低对调
    ]
    [ 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

;Function for entering power down mode
; 1. SDRAM should be in self-refresh mode.
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh.
; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh.
; 4. The I-cache may have to be turned on.
; 5. The location of the following code may have not to be changed.

;void EnterPWDN(int CLKCON);
EnterPWDN
    mov r2,r0        ;r2=rCLKCON 保存原始数据 0x4c00000c 使能各模块的时钟输入
    tst r0,#0x8        ;测试bit[3] SLEEP mode? 1=>sleep
    bne ENTER_SLEEP    ;C=0,即TST结果非0,bit[3]=1

;//进入PWDN后如果不是sleep则进入stop

;//进入Stop mode
ENTER_STOP
    ldr r0,=REFRESH        ;0x48000024   DRAM/SDRAM refresh config
    ldr r3,[r0]            ;r3=rREFRESH
    mov r1, r3
    orr r1, r1, #BIT_SELFREFRESH    ;Enable SDRAM self-refresh
    str r1, [r0]        ;Enable SDRAM self-refresh
;//Enable SDRAM self-refresh
    mov r1,#16            ;wait until self-refresh is issued. may not be needed.
0    subs r1,r1,#1
    bne %B0
;//wait 16 fclks for self-refresh
    ldr r0,=CLKCON        ;enter STOP mode.
    str r2,[r0]
;//??????????????

    mov r1,#32
0    subs r1,r1,#1    ;1) wait until the STOP mode is in effect.
    bne %B0            ;2) Or wait here until the CPU&Peripherals will be turned-off
                    ;Entering SLEEP mode, only the reset by wake-up is available.

    ldr r0,=REFRESH ;exit from SDRAM self refresh mode.
    str r3,[r0]

    MOV_PC_LR        ;back to main process
        

ENTER_SLEEP
    ;NOTE.
    ;1) rGSTATUS3 should have the return address after wake-up from SLEEP mode.

    ldr r0,=REFRESH
    ldr r1,[r0]        ;r1=rREFRESH
    orr r1, r1, #BIT_SELFREFRESH
    str r1, [r0]        ;Enable SDRAM self-refresh
;//Enable SDRAM self-refresh

    mov r1,#16            ;Wait until self-refresh is issued,which may not be needed.
0    subs r1,r1,#1
    bne %B0
;//Wait until self-refresh is issued,which may not be needed

    ldr    r1,=MISCCR        ;IO register 
    ldr    r0,[r1]
    orr    r0,r0,#(7<<17)  ;Set SCLK0=1, SCLK1=1, SCKE=1.
    str    r0,[r1]

    ldr r0,=CLKCON        ; Enter sleep mode
    str r2,[r0]

    b .            ;CPU will die here.
;//进入Sleep Mode,1)设置SDRAM为self-refresh
;//                   2)设置MISCCR bit[17] 1:sclk0=sclk 0:sclk0=0
;//                                 bit[18] 1:sclk1=sclk 0:sclk1=0
;//                                 bit[19] 1:Self refresh retain enable
;//                                         0:Self refresh retain disable  
;//                                         When 1, After wake-up from sleep, The self-refresh will be retained.

WAKEUP_SLEEP
    ;Release SCLKn after wake-up from the SLEEP mode.
    ldr    r1,=MISCCR
    ldr    r0,[r1]
    bic    r0,r0,#(7<<17)  ;SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:0->=SCKE.
    str    r0,[r1]
;//设置MISCCR

    ;Set memory control registers
     ldr    r0,=SMRDATA
    ldr    r1,=BWSCON    ;BWSCON Address    ;//总线宽度和等待控制寄存器
    add    r2, r0, #52    ;End address of SMRDATA
0
    ldr    r3, [r0], #4    ;数据处理后R0自加4,[R0]->R3,R0+4->R0
    str    r3, [r1], #4
    cmp    r2, r0
    bne    %B0
;//设置所有的memory control register,他的初始地址为BWSCON,初始化
;//数据在以SMRDATA为起始的存储区

    mov r1,#256
0    subs r1,r1,#1    ;1) wait until the SelfRefresh is released.
    bne %B0
;//1) wait until the SelfRefresh is released.

    ldr r1,=GSTATUS3     ;GSTATUS3 has the start address just after SLEEP wake-up
    ldr r0,[r1]

    mov pc,r0
;//跳出Sleep Mode,进入Sleep状态前的PC



;//异常中断宏调用
    LTORG
HandlerFIQ      HANDLER HandleFIQ
HandlerIRQ      HANDLER HandleIRQ
HandlerUndef    HANDLER HandleUndef
HandlerSWI      HANDLER HandleSWI
HandlerDabort   HANDLER HandleDabort
HandlerPabort   HANDLER HandlePabort

IsrIRQ
    sub    sp,sp,#4       ;reserved for PC
    stmfd    sp!,{r8-r9}

    ldr    r9,=INTOFFSET    ;地址为0x4a000014的空间存着中断的偏移
    ldr    r9,[r9]            ;I_ISR
    ldr    r8,=HandleEINT0
    add    r8,r8,r9,lsl #2
    ldr    r8,[r8]
    str    r8,[sp,#8]
    ldmfd    sp!,{r8-r9,pc}
;//外部中断号判断,通过中断服务程序入口地址存储器的地址偏移确定
;//PC=[HandleEINT0+][INTOFFSET]]

;=======
; ENTRY
;扳子上电和复位后 程序开始从位于0x0执行b ResetHandler 程序从跳转到这里执行 
;板子上电复位后 执行几个步骤这里通过标号在注释中加1,2,3....标示 标号表示执行顺序 
;1.禁止看门狗 屏蔽所有中断
;=======
ResetHandler

;//1.禁止看门狗 屏蔽所有中断
    ldr    r0,=WTCON       ;watch dog disable
    ldr    r1,=0x0
    str    r1,[r0]

    ldr    r0,=INTMSK
    ldr    r1,=0xffffffff  ;all interrupt disable
    str    r1,[r0]

    ldr    r0,=INTSUBMSK
    ldr    r1,=0x3ff        ;all sub interrupt disable
    str    r1,[r0]

    [ {FALSE}
            ;//rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);
            ;//Led_Display
    ldr    r0,=GPFCON        ;//F-IO In/Out config 10 10 10 10 00 00 00 00
    ldr    r1,=0x5500            ;//00 = Input 01 = Output
    str    r1,][r0]                ;//10 = EINT[0] 11 = Reserved    
    ldr    r0,=GPFDAT        ;//F-IO data register
    ldr    r1,=0x10
    str    r1,[r0]
    ]

;//2.根据工作频率设置pll 
;这里介绍一下计算公式 
;//Fpllo=(m*Fin)/(p*2^s) 
;//m=MDIV+8,p=PDIV+2,s=SDIV 
;The proper range of P and M: 1<=P<=62, 1<=M<=248

;Fpllo必须大于20Mhz小于66Mhz 
;Fpllo*2^s必须小于170Mhz 
;如下面的PLLCON设定中的M_DIV P_DIV S_DIV是取自option.h中 
;#elif (MCLK==40000000) 
;#define PLL_M (0x48) 
;#define PLL_P (0x3) 
;#define PLL_S (0x2) 
;所以m=MDIV+8=80,p=PDIV+2=5,s=SDIV=2 
;硬件使用晶振为10Mhz,即Fin=10Mhz 
;Fpllo=80*10/5*2^2=40Mhz

    ;To reduce PLL lock time, adjust the LOCKTIME register.
    ldr    r0,=LOCKTIME
    ldr    r1,=0xffffff
    str    r1,[r0]
;//设置PLL的重置延迟

    [ PLL_ON_START
    ; Added for confirm clock divide. for 2440.
    ; Setting value 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, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.
    str    r1,][r0]                ;//数据表示分频数

    ;//Configure UPLL Fin=12.0MHz UFout=48MHz
    ldr    r0,=UPLLCON
    ldr    r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) ;//USB PLL CONFIG
    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 Fin=12.0MHz MFout=304.8MHz
    ldr    r0,=MPLLCON
    ldr    r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) 
    str    r1,[r0]
    ]
    
;//Check if the boot is caused by the wake-up from SLEEP mode.
    ldr    r1,=GSTATUS2
    ldr    r0,[r1]
    tst    r0,#0x2        ;test if bit[1] is 1 or 0 0->C=1
                    ;                          1->C=0
    ;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.
    bne    WAKEUP_SLEEP    ;C=0,jump

    EXPORT StartPointAfterSleepWakeUp
StartPointAfterSleepWakeUp

;//3.置存储相关寄存器的程序 
;这是设置SDRAM,flash ROM 存储器连接和工作时序的程序,片选定义的程序 
;SMRDATA map在下面的程序中定义 
;SMRDATA中涉及的值请参考memcfg.s程序 
;具体寄存器各位含义请参考s3c44b0 spec    
    ;Set memory control registers
     ldr    r0,=SMRDATA
    ldr    r1,=BWSCON    ;BWSCON Address
    add    r2, r0, #52    ;End address of SMRDATA

    
0
    ldr    r3, [r0], #4
    str    r3, [r1], #4
    cmp    r2, r0
    bne    %B0
;//set memory registers


;//4.初始化各模式下的栈指针
         ;Initialize stacks
    bl    InitStacks
    
    

;//5.设置缺省中断处理函数 
      ; Setup IRQ handler
    ldr    r0,=HandleIRQ       ;This routine is needed
    ldr    r1,=IsrIRQ      ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
    str    r1,[r0]
    ;//initialize the IRQ 将普通中断判断程序的入口地址给HandleIRQ
    
    

;//6.将数据段拷贝到ram中 将零初始化数据段清零 跳入C语言的main函数执行 到这步结束bootloader初步引导结束
    ;If main() is used, the variable initialization will be done in __main().
    
    [    :LNOT:USE_MAIN    ;initialized {FALSE}
                          ;Copy and paste RW data/zero initialized data
                          
    LDR     r0, =|Image$$RO$$Limit| ; Get pointer to ROM data
    LDR     r1, =|Image$$RW$$Base|  ; and RAM copy
    LDR     r3, =|Image$$ZI$$Base|  
    
    ;Zero init base => top of initialised data
    CMP     r0, r1      ; Check that they are different just for debug??????????????????????????
    BEQ     %F2
1       
    CMP     r1, r3      ; Copy init data
    LDRCC   r2, ][r0], #4    ;--> LDRCC r2, [r0] + ADD r0, r0, #4         
    STRCC   r2, [r1], #4    ;--> STRCC r2, [r1] + ADD r1, r1, #4
    BCC     %B1
2       
    LDR     r1, =|Image$$ZI$$Limit| ; Top of zero init segment
    MOV     r2, #0
3       
    CMP     r3, r1      ; Zero init
    STRCC   r2, [r3], #4
    BCC     %B3
    ]


       
    [ :LNOT:THUMBCODE    ;if thumbcode={false} bl main
        bl    Main        ;Don't use main() because ......
        b    .                       
    ]


;//if thumbcod={ture}
    [ THUMBCODE         ;for start-up code for Thumb mode
        orr    lr,pc,#1
        bx    lr
        CODE16
        bl    Main        ;Don't use main() because ......
        b    .
        CODE32
    ]


;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
    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

    ;USER mode has not be initialized.
    ;//为什么不用初始化user的stacks,系统刚启动的时候运行在哪个模式下???????????????????
    mov    pc,lr
    ;The LR register won't be valid if the current mode is not SVC mode.?????????????
;//系统一开始运行就是SVCmode????????????????????????????????????????
    
;=====================================================================
; Clock division test
; Assemble code, because VSYNC time is very short
;=====================================================================
    EXPORT CLKDIV124
    EXPORT CLKDIV144
    
CLKDIV124
    
    ldr     r0, = CLKDIVN
    ldr     r1, = 0x3        ; 0x3 = 1:2:4
    str     r1, [r0]
;    wait until clock is stable
    nop
    nop
    nop
    nop
    nop

    ldr     r0, = REFRESH
    ldr     r1, [r0]
    bic        r1, r1, #0xff
    bic        r1, r1, #(0x7<<8)
    orr        r1, r1, #0x470    ; REFCNT135
    str     r1, [r0]
    nop
    nop
    nop
    nop
    nop
    mov     pc, lr

CLKDIV144
    ldr     r0, = CLKDIVN
    ldr     r1, = 0x4        ; 0x4 = 1:4:4
    str     r1, [r0]
;    wait until clock is stable
    nop
    nop
    nop
    nop
    nop

    ldr     r0, = REFRESH
    ldr     r1, [r0]
    bic        r1, r1, #0xff
    bic        r1, r1, #(0x7<<8)
    orr        r1, r1, #0x630    ; REFCNT675 - 1520
    str     r1, [r0]
    nop
    nop
    nop
    nop
    nop
    mov     pc, lr


;存储器控制寄存器的定义区
    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))
    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)+(Trc<<18)+(Tchr<<16)+REFCNT)

    DCD 0x32        ;SCLK power saving mode, BANKSIZE 128M/128M

    DCD 0x30        ;MRSR6 CL=3clk
    DCD 0x30        ;MRSR7 CL=3clk


    ALIGN

    AREA RamData, DATA, READWRITE

    ^   _ISR_STARTADDRESS        ; _ISR_STARTADDRESS=0x33FF_FF00
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
;@0x33FF_FF20
HandleEINT0        #   4
HandleEINT1        #   4
HandleEINT2        #   4
HandleEINT3        #   4
HandleEINT4_7    #   4
HandleEINT8_23    #   4
HandleCAM        #   4        ; Added for 2440.
HandleBATFLT    #   4
HandleTICK        #   4
HandleWDT        #   4
HandleTIMER0     #   4
HandleTIMER1     #   4
HandleTIMER2     #   4
HandleTIMER3     #   4
HandleTIMER4     #   4
HandleUART2      #   4
;@0x33FF_FF60
HandleLCD         #   4
HandleDMA0        #   4
HandleDMA1        #   4
HandleDMA2        #   4
HandleDMA3        #   4
HandleMMC        #   4
HandleSPI0        #   4
HandleUART1        #   4
HandleNFCON        #   4        ; Added for 2440.
HandleUSBD        #   4
HandleUSBH        #   4
HandleIIC        #   4
HandleUART0     #   4
HandleSPI1         #   4
HandleRTC         #   4
HandleADC         #   4
;@0x33FF_FFA0
    END

相关帖子

来自 2楼
avocationA|  楼主 | 2008-9-10 22:22 | 只看该作者

2

;=====================================================================
; File Name : 2440slib.s
; Function  : S3C2440  (Assembly)
; Date      : March 09, 2002
; Revision    : Programming start (February 26,2002) -> SOP
; Revision    : 03.11.2003 ver 0.0    Attatched for 2440
;=====================================================================

;Interrupt, FIQ/IRQ disable
NOINT  EQU 0xc0    ; 1100 0000

;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.
   GBLL    THUMBCODE
   [ {CONFIG} = 16
THUMBCODE SETL  {TRUE}
     CODE32
   |
THUMBCODE SETL  {FALSE}
   ]

   MACRO
     MOV_PC_LR
     [ THUMBCODE
       bx lr
     |
       mov pc,lr
     ]
   MEND

   AREA |C$$code|, CODE, READONLY

;========================================
;Workaround of problem between LCD and Framebuffer
;========================================
    EXPORT    SDRAMtest
SDRAMtest
        ldr r0,=0x31000000    ;//#表示立即数寻址,但是LDR立即数是有限制的,
           ldr r1,=0x80000        ;//只有部分可以,=是伪指令,表示先把这个数存
           mov r2,#0xf000000f    ;//在某个空间然后再给,如果可以直接寻址就自动
                               ;//设置,编译器自己搞定
           
LB2     str r2,[r0],#4
        str r2,[r0],#4
           subs r1,r1,#4
           bne LB2
           mov pc,lr
           

;==============
; CPSR I,F bit
;==============
;int SET_IF(void);
;The return value is current CPSR.
    EXPORT    SET_IF
SET_IF
    ;This function works only if the processor is in previliged mode.
   mrs r0,cpsr
   mov r1,r0
   orr r1,r1,#NOINT
   msr cpsr_cxsf,r1
   MOV_PC_LR
;//置位IRQ和FIQ控制位,禁止中断



;void WR_IF(int cpsrValue);
   EXPORT WR_IF
WR_IF
    ;This function works only if the processor is in previliged mode.
   msr cpsr_cxsf,r0
   MOV_PC_LR
;//写CPSR


;void CLR_IF(void);
   EXPORT  CLR_IF
CLR_IF
    ;This function works only if the processor is in previliged mode.
   mrs r0,cpsr
   bic r0,r0,#NOINT
   msr cpsr_cxsf,r0
   MOV_PC_LR
;//清零IRQ和FIQ控制位,使能中断



;====================================
; MMU Cache/TLB/etc on/off functions  //TLB--页表缓冲
;====================================


;//=============CP15协处理器MMU的C1功能================
;//M-bit[0]:禁止/使能MMU 1使能
;//A-bit[1]:是否支持内存访问时地址对齐检查系统,1使能
;//C-bit[2]:禁止/使能数据Cache或整个Cache,1使能  不含Cache返回0,不能禁止Cache返回1
;//W-bit[3]:禁止/使能写入缓冲,1使能
;//P-bit[4]:控制PROG32控制信号
;//            0 异常中断处理程序进入32地址的模式
;//            1 异常中断处理程序进入26地址的模式  不支持26位时返回1

;//D-bit[5]:对于向前兼容的26位地址的ARM处理器
;//            0 禁止26位地址异常检查
;//         1 使能26位地址异常检查

;//L-bit[6]:对于ARMv3及以前的版本
;//            1 选择后期中止模型
;//            0 选择早前中止模型

;//B-bit[7]:0 选择little-endian
;//            1 选择big-endian

;//S-bit[8]:用于系统保护
;//R-bit[9]:用于ROM保护
;//F-bit[10]:由生产商定义
;//Z-bit[11]:对于支持跳转预测的ARM系统
;//            1 使能跳转预测功能
;//            0 禁止跳转预测功能

;//I-bit[12]:Cache分开时,1 使能指令Cache,0 禁止使能Cache
;//V-bit[13]:对于支持高端异常中断向量表的系统
;//            0 选择 0x00000000-0x0000001c
;//            1 选择 0xFFFF0000-0xFFFF001c

;//RR-bit[14]:Cache的淘汰算法
;//            0 选择常规的淘汰算法,
;//            1 选择预测性的淘汰算法,如round-robin淘汰算法

;//L4-bit[15]:对于ARM版本5以上的处理器,用于兼容以前的ARM版本的功能
;//            0 保持当前ARM的正常的功能
;//            1 对于一些根据跳转地址的位[0]进行状态切换的指令,忽略[0],不进行状态切换,保持和以前的ARM版本兼容
;//=====================================================

R1_I    EQU    (1<<12) ;//Cache分开时,1 使能指令Cache,0 禁止使能Cache
R1_C    EQU    (1<<2)    ;//禁止/使能数据Cache或整个Cache,1使能  不含Cache返回0,不能禁止Cache返回1
R1_A    EQU    (1<<1)    ;//是否支持内存访问时地址对齐检查系统,1使能
R1_M    EQU    (1)        ;//禁止/使能MMU 1使能
R1_iA    EQU    (1<<31)
R1_nF   EQU    (1<<30)

;void MMU_EnableICache(void)
   EXPORT MMU_EnableICache
MMU_EnableICache
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#R1_I
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_DisableICache(void)
   EXPORT MMU_DisableICache
MMU_DisableICache
   mrc p15,0,r0,c1,c0,0
   bic r0,r0,#R1_I
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR
;//禁止/使能指令Cache



;void MMU_EnableDCache(void)
   EXPORT MMU_EnableDCache
MMU_EnableDCache
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#R1_C
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_DisableDCache(void)
   EXPORT MMU_DisableDCache
MMU_DisableDCache
   mrc p15,0,r0,c1,c0,0
   bic r0,r0,#R1_C
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR
;//禁止/使能数据Cache      



;void MMU_EnableAlignFault(void)
   EXPORT MMU_EnableAlignFault
MMU_EnableAlignFault
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#R1_A
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_DisableAlignFault(void)
   EXPORT MMU_DisableAlignFault
MMU_DisableAlignFault
   mrc p15,0,r0,c1,c0,0
   bic r0,r0,#R1_A
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR
;//使能/禁止存储器对齐功能   
   
   

;void MMU_EnableMMU(void)
   EXPORT MMU_EnableMMU
MMU_EnableMMU
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#R1_M
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_DisableMMU(void)
   EXPORT MMU_DisableMMU
MMU_DisableMMU
   mrc p15,0,r0,c1,c0,0
   bic r0,r0,#R1_M
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR
;//使能/禁止MMU
;//注意:使能/禁止MMU时

;//====================================================================================================
;//1、在使能MMU之前,要在内存中建立好页表,同时CP15中的各相关寄存器必须完成初始化。
;//2、如果使用的不是平板存储模式(物理地址和虚拟地址相等),在禁止/使能MMU时虚拟地
;//址和物理地址的对应关系会发生改变,这时应该清楚Cache中的当前地址变换条目。
;//3、如果完成禁止/使能MMU的代码的物理地址和虚拟地址不相同,则禁止/使能MMU时将造成
;//很**烦,因此强烈完成禁止/使能MMU的代码的物理地址和虚拟地址最好相同。
;//====================================================================================================

;void MMU_SetFastBusMode(void)
; FCLK:HCLK= 1:1
  EXPORT MMU_SetFastBusMode
MMU_SetFastBusMode
   mrc p15,0,r0,c1,c0,0
   bic r0,r0,#R1_iA:OR:R1_nF
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_SetAsyncBusMode(void)
; FCLK:HCLK= 1:2
   EXPORT MMU_SetAsyncBusMode
MMU_SetAsyncBusMode
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#R1_nF:OR:R1_iA
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR


;//C2用于保存页表的在内存中的基地址
;//页表中每一行对应一个虚地址页对应的实地址页的地址、该位的方位权限和该页的缓冲特性
;//通常把部分页表放在页表缓冲器TLB(translation lookaside buffer)中,换页表时,TLB要清空,因为。。。。
;//C8控制清空TLB
;//C10用于控制TLB中内容的锁定
;=========================
; Set TTBase
;=========================
;void MMU_SetTTBase(int base)
   EXPORT MMU_SetTTBase
MMU_SetTTBase
   ;ro=TTBase
   mcr p15,0,r0,c2,c0,0
   MOV_PC_LR



;//MMU将整个存储空间分成16个域(domain),每个域具有相同的访问属性
;//C3用于设置域的属性
;=========================
; Set Domain
;=========================
;void MMU_SetDomain(int domain)
   EXPORT MMU_SetDomain
MMU_SetDomain
   ;ro=domain
   mcr p15,0,r0,c3,c0,0
   MOV_PC_LR

;=========================
; ICache/DCache functions
;=========================
;void MMU_InvalidateIDCache(void)
   EXPORT MMU_InvalidateIDCache
MMU_InvalidateIDCache
   mcr p15,0,r0,c7,c7,0
   MOV_PC_LR

;void MMU_InvalidateICache(void)
   EXPORT MMU_InvalidateICache
MMU_InvalidateICache
   mcr p15,0,r0,c7,c5,0
   MOV_PC_LR

;void MMU_InvalidateICacheMVA(U32 mva)
   EXPORT MMU_InvalidateICacheMVA
MMU_InvalidateICacheMVA
   ;r0=mva
   mcr p15,0,r0,c7,c5,1
   MOV_PC_LR

;void MMU_PrefetchICacheMVA(U32 mva)
   EXPORT MMU_PrefetchICacheMVA
MMU_PrefetchICacheMVA
   ;r0=mva
   mcr p15,0,r0,c7,c13,1
   MOV_PC_LR

;void MMU_InvalidateDCache(void)
   EXPORT MMU_InvalidateDCache
MMU_InvalidateDCache
   mcr p15,0,r0,c7,c6,0
   MOV_PC_LR

;void MMU_InvalidateDCacheMVA(U32 mva)
   EXPORT MMU_InvalidateDCacheMVA
MMU_InvalidateDCacheMVA
   ;r0=mva
   mcr p15,0,r0,c7,c6,1
   MOV_PC_LR

;void MMU_CleanDCacheMVA(U32 mva)
   EXPORT MMU_CleanDCacheMVA
MMU_CleanDCacheMVA
   ;r0=mva
   mcr p15,0,r0,c7,c10,1
   MOV_PC_LR

;void MMU_CleanInvalidateDCacheMVA(U32 mva)
   EXPORT MMU_CleanInvalidateDCacheMVA
MMU_CleanInvalidateDCacheMVA
   ;r0=mva
   mcr p15,0,r0,c7,c14,1
   MOV_PC_LR

;void MMU_CleanDCacheIndex(U32 index)
   EXPORT MMU_CleanDCacheIndex
MMU_CleanDCacheIndex
   ;r0=index
   mcr p15,0,r0,c7,c10,2
   MOV_PC_LR

;void MMU_CleanInvalidateDCacheIndex(U32 index)
   EXPORT MMU_CleanInvalidateDCacheIndex
MMU_CleanInvalidateDCacheIndex
   ;r0=index
   mcr p15,0,r0,c7,c14,2
   MOV_PC_LR

;void MMU_WaitForInterrupt(void)
   EXPORT MMU_WaitForInterrupt
MMU_WaitForInterrupt
   mcr p15,0,r0,c7,c0,4
   MOV_PC_LR

;===============
; TLB functions
;===============
;voic MMU_InvalidateTLB(void)
   EXPORT MMU_InvalidateTLB
MMU_InvalidateTLB
   mcr p15,0,r0,c8,c7,0
   MOV_PC_LR

;void MMU_InvalidateITLB(void)
   EXPORT MMU_InvalidateITLB
MMU_InvalidateITLB
   mcr p15,0,r0,c8,c5,0
   MOV_PC_LR

;void MMU_InvalidateITLBMVA(U32 mva)
   EXPORT MMU_InvalidateITLBMVA
MMU_InvalidateITLBMVA
   ;ro=mva
   mcr p15,0,r0,c8,c5,1
   MOV_PC_LR

;void MMU_InvalidateDTLB(void)
    EXPORT MMU_InvalidateDTLB
MMU_InvalidateDTLB
    mcr p15,0,r0,c8,c6,0
    MOV_PC_LR

;void MMU_InvalidateDTLBMVA(U32 mva)
    EXPORT MMU_InvalidateDTLBMVA
MMU_InvalidateDTLBMVA
    ;r0=mva
    mcr p15,0,r0,c8,c6,1
    MOV_PC_LR

;=================
; Cache lock down
;=================
;void MMU_SetDCacheLockdownBase(U32 base)
   EXPORT MMU_SetDCacheLockdownBase
MMU_SetDCacheLockdownBase
   ;r0= victim & lockdown base
   mcr p15,0,r0,c9,c0,0
   MOV_PC_LR

;void MMU_SetICacheLockdownBase(U32 base)
   EXPORT MMU_SetICacheLockdownBase
MMU_SetICacheLockdownBase
   ;r0= victim & lockdown base
   mcr p15,0,r0,c9,c0,1
   MOV_PC_LR

;=================
; TLB lock down
;=================
;void MMU_SetDTLBLockdown(U32 baseVictim)
   EXPORT MMU_SetDTLBLockdown
MMU_SetDTLBLockdown
   ;r0= baseVictim
   mcr p15,0,r0,c10,c0,0
   MOV_PC_LR

;void MMU_SetITLBLockdown(U32 baseVictim)
   EXPORT MMU_SetITLBLockdown
MMU_SetITLBLockdown
   ;r0= baseVictim
   mcr p15,0,r0,c10,c0,1
   MOV_PC_LR

;============
; Process ID
;============
;void MMU_SetProcessId(U32 pid)
   EXPORT MMU_SetProcessId
MMU_SetProcessId
   ;r0= pid
   mcr p15,0,r0,c13,c0,0
   MOV_PC_LR

   END

使用特权

评论回复
板凳
Etual| | 2008-9-11 08:44 | 只看该作者

原创还是转载?

在友善之臂那里看到过这段注释,一样的。

另外,这个貌似是那个 裸机测试外围的启动代码,不是vivi,不过
原理跟差不多 - -b

使用特权

评论回复
地板
c.sunway| | 2008-9-12 10:31 | 只看该作者

看了很管用

多谢LZ

使用特权

评论回复
5
shyboy1212| | 2008-9-12 11:17 | 只看该作者

谢谢.学习中

使用特权

评论回复
6
linhuaou| | 2008-9-12 16:19 | 只看该作者

呵呵。不错哦!

使用特权

评论回复
7
lhjlxr| | 2008-9-13 11:16 | 只看该作者

很好!

不错啊!

使用特权

评论回复
8
renjie| | 2008-9-13 19:10 | 只看该作者

引导时候其实什么寄存器也可以不配!放在c代码中方便!!

给你提几个意见!
引导时候其实什么寄存器也可以不配!放在c代码中方便!!

使用特权

评论回复
9
robertc| | 2008-9-14 00:23 | 只看该作者

回复主题:2440 启动代码详

不错 学习学习

使用特权

评论回复
10
avocationA|  楼主 | 2008-9-14 17:09 | 只看该作者

keil mdk3.22 2440led工程

使用特权

评论回复
11
avocationA|  楼主 | 2008-9-14 17:34 | 只看该作者

贴在这里是方便看!21IC的背景是灰色的保护眼睛!呵呵!

使用特权

评论回复
12
avocationA|  楼主 | 2008-9-15 10:20 | 只看该作者

.

使用特权

评论回复
13
avocationA|  楼主 | 2008-9-15 14:01 | 只看该作者

再贴MDK3.22下的2440例程!!!可能有错误,E文差

请高人再详细注解下.......!!!!!!!!!!!!!!!!!!!!!
请高人再详细注解下.......!!!!!!!!!!!!!!!!!!!!!
请高人再详细注解下.......!!!!!!!!!!!!!!!!!!!!!
原文以打包上传....在16楼........
更新18楼.........................

使用特权

评论回复
14
freewing| | 2008-9-18 13:54 | 只看该作者

不管怎样,顶一个

不管怎样,顶一个

使用特权

评论回复
15
db10| | 2008-9-18 14:50 | 只看该作者

hao

使用特权

评论回复
16
avocationA|  楼主 | 2008-9-18 21:41 | 只看该作者

源文件

使用特权

评论回复
17
l0p0c| | 2008-9-19 13:35 | 只看该作者

不错!感谢!

使用特权

评论回复
18
avocationA|  楼主 | 2008-9-24 21:53 | 只看该作者

RealView(更新注解)顺便问下怎么改成彩色的代码谢谢!

;/*****************************************************************************/
;/* S3C2440A.S: Startup file for Samsung S3C440A                              */
;/* This file is part of the uVision/ARM development tools.                   */
;/* Copyright (c) 2005-2006 Keil Software. All rights reserved.               */
;/* This software may only be used under the terms of a valid, current,       */
;/* end user licence from KEIL for a compatible version of KEIL software      */
;/* development tools. Nothing else gives you the right to use this software. */
;/*****************************************************************************/

;elementary avocationA (rework:2008.09.24更新)

;***启动代码(执行复位后)***                                                                          
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs//;向量中断模式/非向量中断模式 在PSRs设置(猜的)

                                ; 系统的工作模式设定
Mode_USR        EQU     0x10    ; 定义用户模式标志代码;// 用户模式的CPSR代码 
Mode_FIQ        EQU     0x11    ; 定义快速中断模式标志代码;// 快中断模式的CPSR代码
Mode_IRQ        EQU     0x12    ; 定义普通中断模式标志代码;// 中断模式的CPSR代码
Mode_SVC        EQU     0x13    ; 定义管理模式标志代码;// 管理模式的CPSR代码
Mode_ABT        EQU     0x17    ; 定义中止模式标志代码;// 中止模式的CPSR代码
Mode_UND        EQU     0x1B    ; 定义未定义模式标志代码 ;// 未定义模式的CPSR代码
Mode_SYS        EQU     0x1F    ; 定义系统模式(特权模式)标志代码;// 系统(特权)模式的CPSR代码

I_Bit           EQU     0x80    ;// 普通中断开关(0×80:打开;0×00:关闭)
F_Bit           EQU     0x40    ;// 快速中断开关(0×40:打开;0×00:关闭)

;//栈配置()

;系统的栈空间设定

UND_Stack_Size  EQU     0x00000000 ;未定义     
SVC_Stack_Size  EQU     0x00000008 ;管理模式端栈长度
ABT_Stack_Size  EQU     0x00000000 ;中止模式端栈长度
FIQ_Stack_Size  EQU     0x00000000 ;快速中断模式端栈长度
IRQ_Stack_Size  EQU     0x00000080 ;普通中断模式模式端栈长度
USR_Stack_Size  EQU     0x00000400 ;用户模端栈长度
;//
ISR_Stack_Size  EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size +                          FIQ_Stack_Size + IRQ_Stack_Size);所有的堆栈大小进行相加,得到总堆栈大小
/**********************************************************************************************
;//arm的汇编程序由段组成,段是相对独立的指令或数据单位,每个段由AREA伪指令定义,并定义段的属性:
;//READWRITE(读写)READONLY(只读)
**********************************************************************************************/
                AREA    STACK, NOINIT, READWRITE, ALIGN=3 ;开辟端栈段,段名(STACK)定义为可读可写,不初始化内存单元或将内存写0,字节对齐

Stack_Mem       SPACE   USR_Stack_Size  ;//申请栈内存空间
__initial_sp    SPACE   ISR_Stack_Size

Stack_Top       EQU     Stack_Mem + ISR_Stack_Size ;//定义堆栈开始地址(最大地址,堆栈向下访问)

;//堆配置
;//堆大小 (单位字节)//
Heap_Size       EQU     0x00000000        ;系统的堆空间设定//定义堆空间大小(配合最后的动态内存申请使用)

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3  ;//段名(HEAP)声明堆代码段(不初始化内存,可读写,字节对齐)
Heap_Mem        SPACE   Heap_Size ;//申请堆的内存空间


;时钟管理定义
CLK_BASE        EQU     0x4C000000      ; 时钟基地址 
LOCKTIME_OFS    EQU     0x00            ; PLL锁定时间计数器对应基地址的偏移值
MPLLCON_OFS     EQU     0x04            ; MPLL控制 对应基地址的偏移值//认为MPLL分出三种模式:FCLK、HCLK、PCLK
UPLLCON_OFS     EQU     0X08            ; UPLL控制 对应基地址的偏移值//用于USB设备
CLKCON_OFS      EQU     0x0C            ; 时钟生成控制 对应基地址的偏移值
CLKSLOW_OFS     EQU     0x10            ; 慢时钟控制 对应基地址的偏移值
CLKDIVN_OFS     EQU     0X14            ; 时钟除法器控制 对应基地址的偏移值
CAMDIVN_OFS     EQU     0X18            ; 摄象时钟除法器控制 对应基地址的偏移值//UPLL提供


CLOCK_SETUP     EQU     1                ; 时钟设置
LOCKTIME_Val    EQU     0x0FFF0FFF        ; PLL锁定时间计数器 值
MPLLCON_Val     EQU     0x00043011        ; MPLL控制 值
UPLLCON_Val     EQU     0x00038021        ; UPLL控制 值
CLKCON_Val      EQU     0x001FFFF0        ; 时钟生成控制 值
CLKSLOW_Val     EQU     0x00000004        ; 慢时钟控制 值
CLKDIVN_Val     EQU     0x0000000F        ; 时钟除法器控制 值
CAMDIVN_Val     EQU     0x00000000        ; 摄象时钟除法器控制 值

;Interrupt  definitions      ;中断定义
INTOFFSET          EQU    0X4A000014                      ;中断请求源偏移 地址

;//中断向量表
;// 中断向量地址     <0x20-0x3fffff78>  
;// 中断向量表地址必须字对齐 
;//</e>  
IntVT_SETUP      EQU     1            ;中断向量设置
IntVTAddress    EQU     0x33ffff20    ;中断向量地址


;----------------------- 存储器设定 ------------------------------------

IRAM_BASE       EQU     0x40000000 ; //内存基地址

;  //看门狗定义
WT_BASE         EQU     0x53000000      ; 看门狗基地址
WTCON_OFS       EQU     0x00            ; 看门狗控制 对应基地址的偏移值
WTDAT_OFS       EQU     0x04            ; 看门狗数据 对应基地址的偏移值
WTCNT_OFS       EQU     0x08            ; 看门狗记数 对应基地址的偏移值

WT_SETUP        EQU     1                ; 看门狗设置
WTCON_Val       EQU     0x00000000        ; 看门狗控制
WTDAT_Val       EQU     0x00008000        ; 看门狗数据

; 存储控制器设定
MC_BASE         EQU     0x48000000      ;   存储控制器基地址

MC_SETUP        EQU     0                ;   存储控制器设定

BWSCON_Val      EQU     0x22000000        ;总线宽度和等待控制
BANKCON0_Val    EQU     0x00000700        ;Boot ROM 控制
BANKCON1_Val    EQU     0x00000700        ;BANK1 控制
BANKCON2_Val    EQU     0x00000700        ;BANK2 控制
BANKCON3_Val    EQU     0x00000700        ;BANK3 控制
BANKCON4_Val    EQU     0x00000700        ;BANK4 控制
BANKCON5_Val    EQU     0x00000700        ;BANK5 控制
BANKCON6_Val    EQU     0x00018005        ;BANK6 控制
BANKCON7_Val    EQU     0x00018005        ;BANK7 控制
REFRESH_Val     EQU     0x008404F3        ;DRAM/SDRAM 刷新 控制
BANKSIZE_Val    EQU     0x00000032        ;存储器大小 控制
MRSRB6_Val      EQU     0x00000020        ;SDRAM 的模式设置寄存器 控制
MRSRB7_Val      EQU     0x00000020        ;SDRAM 的模式设置寄存器 控制

; 存储控制器设定结束

; I/O 口设定
PIO_BASE        EQU     0x56000000      ; 端口基地址
PCONA_OFS       EQU     0x00            ; 端口A控制 对应基地址的偏移值
PCONB_OFS       EQU     0x10            ; 端口B控制 对应基地址的偏移值
PCONC_OFS       EQU     0x20            ; 端口C控制 对应基地址的偏移值
PCOND_OFS       EQU     0x30            ; 端口D控制 对应基地址的偏移值
PCONE_OFS       EQU     0x40            ; 端口E控制 对应基地址的偏移值
PCONF_OFS       EQU     0x50            ; 端口F控制 对应基地址的偏移值
PCONG_OFS       EQU     0x60            ; 端口G控制 对应基地址的偏移值
PCONH_OFS       EQU     0x70            ; 端口H控制 对应基地址的偏移值
PCONJ_OFS       EQU     0xD0            ; 端口J控制 对应基地址的偏移值
PUPB_OFS        EQU     0x18            ; 端口B上拉控制 对应基地址的偏移值
PUPC_OFS        EQU     0x28            ; 端口C上拉控制 对应基地址的偏移值
PUPD_OFS        EQU     0x38            ; 端口D上拉控制 对应基地址的偏移值
PUPE_OFS        EQU     0x48            ; 端口E上拉控制 对应基地址的偏移值
PUPF_OFS        EQU     0x58            ; 端口F上拉控制 对应基地址的偏移值
PUPG_OFS        EQU     0x68            ; 端口G上拉控制 对应基地址的偏移值
PUPH_OFS        EQU     0x78            ; 端口H上拉控制 对应基地址的偏移值
PUPJ_OFS        EQU     0xD8            ; 端口J上拉控制 对应基地址的偏移值

;--------端口 配置--------------
PIO_SETUP       EQU     0

;端口A
PIOA_SETUP      EQU     0
PCONA_Val       EQU     0x000003FF
                                                   
;端口B
PIOB_SETUP      EQU     0
PCONB_Val       EQU     0x00000000    ;
PUPB_Val        EQU     0x00000000     ;端口B上拉开启
                                                    
;端口C
PIOC_SETUP      EQU     1
PCONC_Val       EQU     0x00001401    ;
PUPC_Val        EQU     0x00000000  ;端口C上拉开启
  
;端口D
PIOD_SETUP      EQU     0
PCOND_Val       EQU     0x00000000    ;
PUPD_Val        EQU     0x00000000    ;端口D上拉开启
  
;端口E
PIOE_SETUP      EQU     0
PCONE_Val       EQU     0x00000000    ;
PUPE_Val        EQU     0x00000000    ;端口E上拉开启

;端口F
PIOF_SETUP      EQU     0
PCONF_Val       EQU     0x00000000    ;
PUPF_Val        EQU     0x00000000    ;端口F上拉开启
                                                 
;端口G
PIOG_SETUP      EQU     0
PCONG_Val       EQU     0x00000000    ;
PUPG_Val        EQU     0x00000000    ;端口G上拉开启
                                                      
;端口H
PIOH_SETUP      EQU     0
PCONH_Val       EQU     0x000007FF
PUPH_Val        EQU     0x00000000     ;端口H上拉开启
                                                  
;端口J
PIOJ_SETUP      EQU     0
PCONJ_Val       EQU     0x00000000    ;
PUPJ_Val        EQU     0x00000000    ;端口J上拉开启

                ; 汇编程序数据 8 字节对齐
                PRESERVE8          ;c和汇编有8位对齐的要求,这个伪指令可以满足此要求
                
;//存储区设定和程序入口点
;//启动代码必须连接到第一个地址才能运行。
                AREA    RESET, CODE, READONLY ;//开辟端栈段,段名(RESET)定义RESET代码段为只读
                ARM      ;//ARM 模式运行程序
;//异常向量
;//影射到地址0

;//必须使用,绝对寻址方式。
;//虚处理(子程序)是用一个无限循环实现的, 它是可修改的..//(11942295)翻译
Vectors         LDR     PC, Reset_Addr ; 复位        
                LDR     PC, Undef_Addr ; 未定义指令
                LDR     PC, SWI_Addr   ; 软件中断
                LDR     PC, PAbt_Addr  ; 中止(预取)
                LDR     PC, DAbt_Addr  ; 中止(数据)
                NOP                    ; 保留向量 
                LDR     PC, IRQ_Addr   ; 普通
                LDR     PC, FIQ_Addr   ; 快速中断

                IF      IntVT_SETUP <> 0

;//中断向量表地址              
HandleEINT0          EQU    IntVTAddress           
HandleEINT1          EQU    IntVTAddress +4
HandleEINT2          EQU    IntVTAddress +4*2
HandleEINT3          EQU    IntVTAddress +4*3
HandleEINT4_7        EQU    IntVTAddress +4*4
HandleEINT8_23       EQU    IntVTAddress +4*5
HandleCAM            EQU    IntVTAddress +4*6
HandleBATFLT         EQU    IntVTAddress +4*7
HandleTICK           EQU    IntVTAddress +4*8
HandleWDT            EQU    IntVTAddress +4*9
HandleTIMER0         EQU    IntVTAddress +4*10
HandleTIMER1         EQU    IntVTAddress +4*11
HandleTIMER2         EQU    IntVTAddress +4*12
HandleTIMER3         EQU    IntVTAddress +4*13
HandleTIMER4         EQU    IntVTAddress +4*14
HandleUART2          EQU    IntVTAddress +4*15
HandleLCD            EQU    IntVTAddress +4*16
HandleDMA0           EQU    IntVTAddress +4*17
HandleDMA1           EQU    IntVTAddress +4*18
HandleDMA2           EQU    IntVTAddress +4*19
HandleDMA3           EQU    IntVTAddress +4*20
HandleMMC            EQU    IntVTAddress +4*21
HandleSPI0           EQU    IntVTAddress +4*22
HandleUART1          EQU    IntVTAddress +4*23
HandleNFCON          EQU    IntVTAddress +4*24
HandleUSBD           EQU    IntVTAddress +4*25
HandleUSBH           EQU    IntVTAddress +4*26
HandleIIC            EQU    IntVTAddress +4*27
HandleUART0          EQU    IntVTAddress +4*28
HandleSPI1           EQU    IntVTAddress +4*39
HandleRTC            EQU    IntVTAddress +4*30
HandleADC            EQU    IntVTAddress +4*31

IRQ_Entry
                sub    sp,sp,#4       ;//保留PC值
                stmfd  sp!,{r8-r9}
                
                ldr    r9,=INTOFFSET
                ldr    r9,[r9]
                ldr    r8,=HandleEINT0
                add    r8,r8,r9,lsl #2
                ldr    r8,[r8]
                str    r8,[sp,#8]
                ldmfd  sp!,{r8-r9,pc}                
                
                ENDIF

Reset_Addr      DCD     Reset_Handler ;定义中断的入口地址; 以Reset_Addr为Reset_Handler分配一段字对齐的内存单元
Undef_Addr      DCD     Undef_Handler ; 注:应该是将CODE映射(复制)到RAM的开始地址
SWI_Addr        DCD     SWI_Handler
PAbt_Addr       DCD     PAbt_Handler
DAbt_Addr       DCD     DAbt_Handler
                DCD     0              ;//保留地址 
IRQ_Addr        DCD     IRQ_Handler
FIQ_Addr        DCD     FIQ_Handler

Undef_Handler   B       Undef_Handler ;中断处理程序的入口地址//B为跳转指令|| ??自己跳转到自己??
SWI_Handler     B       SWI_Handler
PAbt_Handler    B       PAbt_Handler
DAbt_Handler    B       DAbt_Handler
                
                IF      IntVT_SETUP <> 1
IRQ_Handler     B       IRQ_Handler
                ENDIF
                
                IF      IntVT_SETUP <> 0
IRQ_Handler     B       IRQ_Entry
                ENDIF
                
FIQ_Handler     B       FIQ_Handler


;//存储控制器配制 
                IF      MC_SETUP <> 0
MC_CFG
                DCD     BWSCON_Val
                DCD     BANKCON0_Val
                DCD     BANKCON1_Val
                DCD     BANKCON2_Val
                DCD     BANKCON3_Val
                DCD     BANKCON4_Val
                DCD     BANKCON5_Val
                DCD     BANKCON6_Val
                DCD     BANKCON7_Val
                DCD     REFRESH_Val
                DCD     BANKSIZE_Val
                DCD     MRSRB6_Val
                DCD     MRSRB7_Val
                ENDIF


;//时钟管理配置
                IF      CLOCK_SETUP <> 0
CLK_CFG
                DCD     LOCKTIME_Val     
                DCD     CLKDIVN_Val 
                DCD     UPLLCON_Val 
                DCD     MPLLCON_Val 
                DCD     CLKSLOW_Val 
                DCD     CLKCON_Val 
                DCD     CAMDIVN_Val 
                ENDIF 

            
;//I/O 配置
               
                IF      PIO_SETUP <> 0
PIOA_CFG     
                DCD     PCONA_Val
PIOB_CFG        DCD     PCONB_Val
                DCD     PUPB_Val
PIOC_CFG        DCD     PCONC_Val
                DCD     PUPC_Val
PIOD_CFG        DCD     PCOND_Val
                DCD     PUPD_Val
PIOE_CFG        DCD     PCONE_Val
                DCD     PUPE_Val
PIOF_CFG        DCD     PCONF_Val
                DCD     PUPF_Val
PIOG_CFG        DCD     PCONG_Val
                DCD     PUPG_Val
PIOH_CFG        DCD     PCONH_Val
                DCD     PUPH_Val
PIOJ_CFG        DCD     PCONJ_Val
                DCD     PUPJ_Val
                ENDIF

; //复位处理模块
                ;//下面是重起时的中断处理函数
                EXPORT  Reset_Handler  ;//定义一个全局函数名变量
Reset_Handler   

                IF      WT_SETUP <> 0            ;//看门狗处理;若WT_SETUP为1,则执行下一个语句
                LDR     R0, =WT_BASE
                LDR     R1, =WTCON_Val
                LDR     R2, =WTDAT_Val
                STR     R2, [R0, #WTCNT_OFS]
                STR     R2, [R0, #WTDAT_OFS]
                STR     R1, [R0, #WTCON_OFS]
                ENDIF
                
                
                IF      CLOCK_SETUP <> 0        ;//时钟处理;若CLOCK_SETUP为1,则执行下一个语句        
                LDR     R0, =CLK_BASE            
                ADR     R8, CLK_CFG
                LDMIA   R8, {R1-R7}            
                STR     R1, [R0, #LOCKTIME_OFS]
                STR     R2, [R0, #CLKDIVN_OFS]  
                STR     R3, [R0, #UPLLCON_OFS] 
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                STR     R4, [R0, #MPLLCON_OFS]  
                STR     R5, [R0, #CLKSLOW_OFS]
                STR     R6, [R0, #CLKCON_OFS]
                STR     R7, [R0, #CAMDIVN_OFS]
                ENDIF                          
                                    
                IF      MC_SETUP <> 0            ;//存储控制器处理;若MC_SETUP为1,则执行下一个语句
                ADR     R13, MC_CFG
                LDMIA   R13, {R0-R12}
                LDR     R13, =MC_BASE
                STMIA   R13, {R0-R12}
                ENDIF                            
                                
                IF      PIO_SETUP <> 0            ;//IO处理;若PIO_SETUP为1,则执行下一个语句
                LDR     R13, =PIO_BASE

                IF      PIOA_SETUP <> 0            ;//端口A处理;若PIOA_SETUP为1,则执行下一个语句        
                ADR     R0, PIOA_CFG
                STR     R0, [R13, #PCONA_OFS]
                ENDIF

                IF      PIOB_SETUP <> 0            ;//端口B处理        
                ADR     R0, PIOB_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONB_OFS]
                STR     R1, [R13, #PUPB_OFS]
                ENDIF

                IF      PIOC_SETUP <> 0            ;//端口C处理
                ADR     R0, PIOC_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONC_OFS]
                STR     R1, [R13, #PUPC_OFS]
                ENDIF

                IF      PIOD_SETUP <> 0            ;//端口D处理
                ADR     R0, PIOD_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCOND_OFS]
                STR     R1, [R13, #PUPD_OFS]
                ENDIF

                IF      PIOE_SETUP <> 0              ;//端口E处理
                ADR     R0, PIOE_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONE_OFS]
                STR     R1, [R13, #PUPE_OFS]
                ENDIF

                IF      PIOF_SETUP <> 0              ;//端口F处理
                ADR     R0, PIOF_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONF_OFS]
                STR     R1, [R13, #PUPF_OFS]
                ENDIF

                IF      PIOG_SETUP <> 0              ;//端口G处理
                ADR     R0, PIOG_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONG_OFS]
                STR     R1, [R13, #PUPG_OFS]
                ENDIF
  
                IF      PIOH_SETUP <> 0             ;//端口H处理
                ADR     R0, PIOH_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONH_OFS]
                STR     R1, [R13, #PUPH_OFS]
                ENDIF
               
                IF      PIOJ_SETUP <> 0            ;//端口J处理
                ADR     R0, PIOJ_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONJ_OFS]
                STR     R1, [R13, #PUPJ_OFS]
                ENDIF 

                ENDIF
                
;;以下函数为进入相应的模式,并定义相应模式的端栈大小
;//为每个模式设置栈
                LDR     R0, =Stack_Top

;//进入未定义指令模式并设定其栈指针
                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #UND_Stack_Size

;//进入异常中断模式,并设定其栈指针
                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #ABT_Stack_Size

;//进入 FIQ 模式,并设定其栈指针
                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #FIQ_Stack_Size

;//进入 IRQ 模式,并设定其栈指针
                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #IRQ_Stack_Size

;//进入 Supervisor 模式,并设定其栈指针
                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #SVC_Stack_Size
;                IMPORT MMU_EnableICache
;                bl     MMU_EnableICache


;//进入 用户 模式,并设定其栈指针  //;最后进入用户模式 
                MSR     CPSR_c, #Mode_USR
                MOV     SP, R0
                SUB     SL, SP, #USR_Stack_Size


;//进入C代码
                                            ;
                IMPORT  __main
                LDR     R0, =__main
                BX      R0


;//用护初始堆与栈 ;//用户设置堆栈程序(C外部接口:用于动态申请内存使用)

                AREA    |.text|, CODE, READONLY

               ; IMPORT  __use_two_region_memory

                EXPORT  __user_initial_stackheap
__user_initial_stackheap  
/**********************************************************************
//__user_initial_stackheap 库函数用法翻译
用法:
        __user_initial_stackheap 返回这些值:
                1. 堆基址(heap base)                          ---> RO
                2. 栈基址(stack base,一般为栈的最高地址)      ---> R1
                3. 堆顶(heap limit)                           ---> R2
                4. 栈顶(stack limit)                          ---> R3
***********************************************************************/

                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + USR_Stack_Size)
                LDR     R2, = (Heap_Mem +      Heap_Size)
           &nbs

使用特权

评论回复
19
avocationA|  楼主 | 2008-9-24 22:08 | 只看该作者

函数__user_initial_stackheap翻译 (转)

函数__user_initial_stackheap翻译 
发表于 2008-7-25 23:33:08 
       今天被这些库函数郁闷了,翻出帮助文档,索性就翻译了点,提供给像我这样迷惑的人参考,俺英文水平很有限,见谅!另外格式为txt文本,复制粘贴即可解决。

__user_initial_stackheap 库函数用法翻译
__user_initial_stackheap返回初始化堆和栈的位置。
RVCT V2.X及其更早的版本中__user_initial_stackheap默认使用的是符号|Image$$ZI$$Limit|的值。当使用分散
加载文件的时候这个符号不会产生。如果你使用分散加载文件,那么你需要重新执行__user_initial_stackheap
函数,不然链接会失败。

在RVCT V3.X中__user_initial_stackheap的功能得到了加强,即使你使用分散加载文件也不需要你重新执行
__user_initial_stackheap函数。函数会根据你的分散加载文件的描述选择正确的功能函数段。

注意:如果你重新执行__user_initial_stackheap函数,这将忽略所有的库函数的执行。这就使得存在的应用程序不
需要修改。
语法:
        __valu_in_regs    struct __initial_stackheap    __user_initial_stackheap(unsinged R0,
                                                                                 unsigned SP,
                                                                                 unsgined R2)

用法:
        __user_initial_stackheap 返回这些值:
                1. 堆基址(heap base)                          ---> RO
                2. 栈基址(stack base,一般为栈的最高地址)      ---> R1
                3. 堆顶(heap limit)                           ---> R2
                4. 栈顶(stack limit)                          ---> R3

        如果这个函数被重新执行,那么必须满足以下条件:
                1. 栈的使用不能超过88字节。
                2. R12(ip)不能被破坏。
                3. 堆要以8字节方式对齐(ALIGN = 3)。

        默认的一段模式中R2,R3将被忽略,R0,R1间的存储空间将全部用来作为堆空间。
        如果使用二段模式那么堆和栈的空间将分别受R2,R3的限制。

        在rt_misc.h中__user_initial_stackheap的定义是这样的:
        struct __initial_stackheap {
            unsigned heap_base, stack_base, heap_limit, stack_limit
        }

        注意:
                由于满递减堆栈的原因,stack_base的值比栈的最高地址要高出1个栈容量。


返回:
        R0,R1,R2,R3中的返回值是由你使用的一段存储模式还是二段存储模式决定。
                1. 一段模式中R1比R0大。R2和R3被忽略了。
                2. 二段模式中R0和R2用来初始化堆,R1和R3用来初始化栈。R2 >= R0, R3 < R1

                ┏━━━┳━━━┓<----- R1 ----->┏━━━┳━━━┓<--- HIGH ADDR
                ┃      ↑      ┃    stack_base  ┃      │      ┃
                ┃      │      ┃                ┃      │      ┃
                ┃      │      ┃                ┃    stacks    ┃
                ┃      │      ┃                ┃      │      ┃
                ┃      │      ┃                ┃      ↓      ┃
                ┃      │      ┃       R3 ----->┃      ┻      ┃
                ┃      ↑      ┃                ┃              ┃
                ┃      │      ┃                ┃              ┃
                ┃      │      ┃                ┃              ┃
                ┃      │      ┃       R2 ----->┃      ┳      ┃
                ┃      │      ┃                ┃      ↑      ┃
                ┃      │      ┃                ┃      │      ┃
                ┃      │      ┃                ┃      │      ┃
                ┃    heaps     ┃                ┃     heaps    ┃
                ┃      │      ┃                ┃      │      ┃
                ┃      │      ┃                ┃      │      ┃
                ┃      │      ┃                ┃      │      ┃
                ┗━━━┻━━━┛<----- R0 ----->┗━━━┻━━━┛<--- LOW ADDR

             _use_one_memory_region             _use_two_memory_region


        使用分散加载文件:
                默认情况下__user_initial_stackhep()使用的是符号|Image$$ZI$$limit|的值。这个符号在用户使
                用分散加载文件时不会产生。然而,C库提供了比较折中的方法:利用分散加载文件中的一些信息来
                执行这个函数。

        注意:
        如果你重新执行__user_initial_stackhep()函数,那么其他的库的执行将被忽略。

        选择使用一段存储模式:
                定义一段特殊的执行域在你的分散加载文件中。使用这种符号:ARM_LIB_STACKHEAP,并使用EMPTY
                属性。
                这样库管理器就选择了一个把这个域当作堆和栈合并在一起的__user_initial_stackhep()函数。在
                这个函数中使用了Image$$ARM_LIB_STACKHEAP$$Base和Image$$ARM_LIB_STACKHEAP$$ZI$$Limit符号
                。
        选择使用二段存储模式:
                定义两个特殊的执行域再你的分散加载文件中。使用这两种符号:ARM_LIB_STACK, ARM_LIB_HEAP。
                并且两个段都要使用EMPTY属性。
                这样库管理器就会选择使用符号:Image$$ARM_LIB_HEAP$$Base、
                                              Image$$ARM_LIB_STACK$$ZI$$ZI$$limit、
                                              Image$$ARM_LIB_STACK$$Base
                                              Image$$ARM_LIB_STACK$$ZI$$Limit
                的__user_initial_stackhep()函数。

        例子:
                FLASH_LOAD 0x0000 0x00200000
                {
                        VECTORS +0 0x400
                        {
                                * (:gdef:__vectab_stack_and_reset, +FIRST)
                                ; 其他域可以放在这里
                        }

                        ;; 最高256 异常深度 (256*4bytes == 1024 == 0x400)
                        CODE 0x400 FIXED
                        {
                                * (+RO)
                        }

                        DATA 0x20000000 0x00200000
                        {
                                * (+RW, +ZI)
                        }

                        ;; 堆开始于 1MB ,向高地址生长
                        ARM_LIB_HEAP 0x20100000 EMPTY 0x100000-0x8000
                        {
                        }

                        ;; 堆安排在 2MB RAM的最高地址处
                        ;; 向低地址生长,空间为32KB
                        ARM_LIB_STACK 0x20200000 EMPTY - 0x8000
                        {
                        }
                }

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

123

主题

935

帖子

0

粉丝