zoukankan      html  css  js  c++  java
  • arm启动代码详解

    ;---------------------------------------------------------------------
    ;startup.s
    ;系统启动代码
    ;起始时间 : 2009.5.7 ----->2009.5.11
    ;---------------------------------------------------------------------



    ;---------------------------------------------------------------------
    GET ./Include/s3c2440.inc ;寄存器地址信息
    GET ./Include/memcfg.inc ;内存控制器配置信息

    ;处理器模式
    USERMODE EQU  0x10
    FIQMODE EQU  0x11
    IRQMODE EQU  0x12
    SVCMODE EQU  0x13
    ABORTMODE EQU  0x17
    UNDEFMODE EQU  0x1b
    SYSMODE EQU 0x1f
    ;相关掩码
    MODEMASK     EQU  0x1f
    NOINT EQU  0xc0

    ;各个处理器模式下堆栈设置
    _STACK_BASEADDRESS EQU 0x33ff8000 ;BANK6 64MB顶部
    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 ~

    ;导入操作系统入口函数
    IMPORT OSEntry

    ;导入外部C语言编写的异常与中断处理函数
    IMPORT vectorUNDEF
    IMPORT vectorSWI
    IMPORT vectorPABT
    IMPORT vectorDABT
    IMPORT vectorIRQ
    IMPORT vectorFIQ

    ;导入镜像装载域段起始地址
    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
    ;--------------------------------------------------------------------


    ;------------------------------------------------------
    AREA startup, CODE, READONLY

    ENTRY

    ;系统向量表

     b vectorRESET ;复位向量
     b vectorUNDEF ;未定义指令
     b vectorSWI ;软中断
     b vectorPABT ;预取指终止
     b vectorDABT ;数据终止
     b . ;系统保留
     b vectorIRQ ;外部中断
     b vectorFIQ ;快速中断
    ;-------------------------------------------------------

    ;--------------------------------------------------------------------------
    ;复位向量
    ;复位向量是ARM处理器上电后第一个被执行的异常
    ;此时系统处理管理(SVC)模式

    vectorRESET

    ;复位向量有以下六件事要做

    ;第一步 : 关闭看门狗定时器屏蔽所有中断
    ;第二步 : 配置系统时钟
    ;第三步 : 配置内存控制器
    ;第四步 : 配置每种处理器模式下堆栈指针
    ;第五步 : 初始化镜像运行域
    ;第六步 : 跳转到操作系统入口


    ;------------------------------------------
    ;第一步 : 关闭看门狗定时器
    ;具体内容请参看s3c2440a数据手册的第18章
    ldr r0, =WTCON
    ldr  r1, =0x0
    str  r1, [r0, #0x0]

    ;屏蔽所有中断
    ldr r0, =INTMSK
    ldr r1, =0xffffffff
    str r1, [r0]
    ;------------------------------------------



    ;------------------------------------------
    ;第二步 : 配置系统时钟
    ;具体内容请看手册第7章

    ;先减少锁相环锁定时间,s3c2440a要求PLL
    ;锁定时间>300us,在上电时s3c2440a预设值
    ;mpll为晶体频率,我用的晶体频率为12MHz
    ;300us*12M = 3600设置LOCKTIME = 0xfff
    ;足够了
    ldr r0, =LOCKTIME
    ldr r1, =0xfff0fff0 ;高16为对应UPLL
    ;低16为对应MPLL
    str r1, [r0, #0x0]

    ;根据器件手册我们还有以下几个事要做
    ;step1.配置UPLL
    ;step2.配置MPLL
    ;注:手册要求先配置UPLL后MPLL
    ; 且之间要间隔7NOP
    ; 详请看手册第7-21.
    ;step3.配置分频系数

    ;step1:
    ldr r0, =UPLLCON
    ldr r1, =((56<<12) + (2<<4) + 2)
    ldr r1, [r0]

    ;按手册要求插入7个NOP
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    ;step2:
    ldr r0, =MPLLCON
    ldr r1, =((127<<12) + (2<<4) + 1)
    ldr r1, [r0]

    ;step3:
    ldr r0, =CLKDIVN
    ldr r1, =((0<<3) + (2 << 2) + 1)
    ldr r1, [r0]
    ;------------------------------------------



    ;------------------------------------------
    ;第三步 : 配置内存控制器
    ;内存控制内的寄存器器地址是连续分布的
    ;从0x4800_0000 -- 0x4800_0030,所以可以
    ;通过一个循环依次填入各个寄存器的内容

    ldr r0, =SMRDATA ;装入配置值的地址
    ldr r1, =BWSCON ;装入起始寄存器地址
    add r2, r0, #0x34 ;计算结束地址

    ;下面是用于向内存控制器
    ;装入配置信息的循环
    0
    ldr r3, [r0], #4 ;装入配置值到r3,后变址
    str r3, [r1], #4  ;把r3内包含的配置值写入
    ;内存控制器的寄存器
    cmp r2, r0 ;结束否?
    bne %B0 ;没结束则继续
    ;------------------------------------------



    ;------------------------------------------
    ;第四步 : 配置每种处理器模式下堆栈指针
    ;方法与原则:
    ;1: 通过CPSR寄存器切换处理器模式
    ;2: 对CPSR的操作方式为 读-修改-写回
    ;3: 绝对不要跳到用户模式,跳过去容易
    ; 回来就难了
    ;4: 切到新处理器模式后要屏蔽IRQ和FIQ
    ; 防止在未设置好堆栈前进入中断处理
    ; 程序,但是在启动代码的最先我们已
    ; 经屏蔽了所有的32个中断源,所以感
    ; 觉是否屏蔽都可以

    ;step1: 先把程序状态寄存器读到r0
    mrs r0, cpsr

    ;step2: 清除处理器模式位(最前面5位)
    bic r0, r0, #MODEMASK

    ;step3: 设置未定义状态下的堆栈指针
    orr r1, r0, #UNDEFMODE|NOINT
    msr cpsr_cxsf, r1 ;UndefMode
    ldr sp, =UndefStack ;UndefStack=0x33FF_5C00

    ;step4: 设置终止状态下的堆栈指针
    orr r1, r0, #ABORTMODE|NOINT
    msr cpsr_cxsf, r1 ;AbortMode
    ldr sp, =AbortStack ;AbortStack=0x33FF_6000

    ;step5: 设置中断模式下的堆栈指针
    orr r1, r0, #IRQMODE|NOINT
    msr cpsr_cxsf, r1 ;IRQMode
    ldr sp, =IRQStack ;IRQStack=0x33FF_7000

    ;step6: 设置快速中断模式下的堆栈指针
    orr r1, r0, #FIQMODE|NOINT
    msr cpsr_cxsf, r1 ;FIQMode
    ldr sp, =FIQStack ;FIQStack=0x33FF_8000

    ;step7: 设置管理模式下的堆栈指针
    orr r1, r0, #SVCMODE|NOINT
    msr cpsr_cxsf, r1 ;SVCMode
    ldr sp, =SVCStack ;SVCStack=0x33FF_5800

    ;step8: 因为管理模式与用户模式共用
    ; 堆栈指针,所以借着系统模式
    ; 来设置用户模式的堆栈指针
    orr r1, r0, #SYSMODE|NOINT
    msr cpsr_cxsf, r1 ;SYSMode
    ldr sp, =UserStack ;SVCStack & USERMode=0x33ff4800

    ;现在处理器处于系统模式
    ;------------------------------------------
       
       
       
    ;------------------------------------------
    ;第五步 : 初始化镜像运行域
    ;复制RW段和ZI段到SDRAM指定地址

    LDR     r0, =|Image$$RO$$Limit| ; 装入RO段结束地址
    LDR     r1, =|Image$$RW$$Base|  ; 装入RW段起始地址
    LDR     r3, =|Image$$ZI$$Base|  ; 装入ZI段起始地址


    ;|Image$$RO$$Limit| == |Image$$RW$$Base| ? 跳过RW段复制 : 复制RW段
    CMP     r0, r1     
    BEQ     %F2

    ;复制RW段
    1       
    CMP     r1, r3  
    LDRCC   r2, [r0], #4     
    STRCC   r2, [r1], #4
    BCC     %B1
    2       
    LDR     r1, =|Image$$ZI$$Limit| 
    MOV     r2, #0

    ;构造ZI段
    3       
    CMP     r3, r1     
    STRCC   r2, [r3], #4
    BCC     %B3

    ;------------------------------------------   



    ;------------------------------------------
    ;第六步 : 跳转到操作系统入口

    b OSEntry ;不要使用main,因为如果使用main
    ;ads还会调用_main()初始化RW和ZI
    ;段,但是那里的数据和本程序不同

    b .

    ;------------------------------------------

    ;---------------------------------------------------------------------------



    SMRDATA DATA

    ;这里是内存控制器的配置数据
    ;配置数据需要根据你使用的存储器修改
    ;在第三步时会将以下数据写入
    ;内存控制器的相关寄存器中
    ;共13个寄存器的配置值

    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 ;数据边界对齐

    END
  • 相关阅读:
    CentOS7突然出现无法连接网络的情况--VM下
    设置Linux系统的LANG变量
    习题
    Linux目录路径知识
    Linux目录详细介绍
    regexp正则
    https://github.com/rwson/awesome-javascript-cn
    JavaScript资源大全中文版(Awesome最新版)
    关于 Chrome DevTools 的 25 个实用技巧
    从前端菜鸟到大神,看这一篇就够了
  • 原文地址:https://www.cnblogs.com/ljf181275034/p/1961951.html
Copyright © 2011-2022 走看看