S3C2410启动代码详解(3)



;================================================================================
; ENTRY  系统上电后经过一个b ResetHandler就跳转到此处来。在此完成一些相关的软硬件配置工作

1.        屏蔽所有中断,关看门狗。
2.        根据工作频率设置PLL寄存器
3.        初始化存储控制相关寄存器
4.        初始化各模式下的栈指针
5.        设置缺省中断处理函数
6.        将数据段拷贝到RAM中,将零初始化数据段清零
7.        跳转到C 语言Main入口函数中
;================================================================================
ResetHandler
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}              //;是得有些表示了,该点点LED灯了,不过被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]
]

;To reduce PLL lock time, adjust the LOCKTIME register. 为了减少PLL的lock time, 调整LOCKTIME寄存器.
ldr r0,=LOCKTIME     //LOCKTIME为锁定计数定时器,即设置PLL稳定过渡时间,一般大于150uS
ldr r1,=0xffffff
str r1,[r0]
      

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

上电复位时的时钟行为。晶振在几毫秒内开始振荡。当OSC时钟稳定后,PLL根据默认PLL设置开始生效,但是通常这个时候是不稳定的,因此在软件重新配置PLLCON寄存器之前FCLK直接使用Fin而不是MPLL,即使用户不希望改变PLLCON的默认值,用户也应该执行一边写PLLCON操作。

;这里介绍一下计算公式
;Fpllo=(m*Fin)/(p*2^s)
;m=MDIV+8,p=PDIV+2,s=SDIV
;Fpllo必须大于20Mhz小于66Mhz
;Fpllo*2^s必须小于170Mhz
;如下面的PLLCON设定中的M_DIV P_DIV S_DIV是取自option.h中M_DIV=0x5c=92 P_DIV=0x4  S_DIV=0x2

所以Fpllo=(m*Fin)/(p*2^s)=(92+8)*12M/(4+2)*2^2=50M


;==================================================================================  
     [ PLL_ON_START
;Configure MPLL
ldr r0,=MPLLCON          //M_DIV=0x5c=92 P_DIV=0x4  S_DIV=0x2
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)  ;Fin=12MHz,Fout=50MHz
str r1,[r0]
       ;Configure UPLL
ldr r0,=UPLLCON          
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)  ;Fin=12MHz,UPLLout=48MHz
str r1,[r0]
]

;Check if the boot is caused by the wake-up from POWER_OFF mode.
ldr r1,=GSTATUS2
ldr r0,[r1]
tst r0,#0x2
        ;In case of the wake-up from POWER_OFF mode, go to POWER_OFF_WAKEUP handler.
bne WAKEUP_POWER_OFF

EXPORT StartPointAfterPowerOffWakeUp
StartPointAfterPowerOffWakeUp

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

//设置内存控制器等寄存器的值,因为这些寄存器是连续排列的,所以采用如下办法对这些 ;寄存器进行连续设置.其中用到了SMRDATA的数据,这在代码后面有定义 ;Set memory control registers

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

ldr r0,=SMRDATA
ldr r1,=BWSCON                     ;BWSCON Address
add r2, r0, #52                        ;End address of SMRDATA,共13个DCD,52个字节
0      
ldr r3, [r0], #4    
str r3, [r1], #4    
cmp r2, r0  
bne %B0                         //上面这段小程序将后面定义的数据复制到相关内存控制寄存器

     ;Initialize stacks
bl InitStacks                      //调用堆栈初始化子程序
;==================================================================================

关于异常中断系统:异常中断矢量表(每个表项占4个字节) 下面是中断向量表 一旦系统运行时有中断发生 即使移植了操作系统 如linux 处理器已经把控制权交给了操作系统 一旦发生中断 处理器还是会跳转到从0x0开始
;中断向量表中某个中断表项(依据中断类型)开始执行;具体中断向量布局请参考s3c44b0 spec 例如 adc中断向量为 0x000000c0下面对应表中第49项位置 向量地址0x0+4*(49-1)=0x000000c0
2410异常中断系统中有两张中断转移表,经过二重转移才跳到中断处理程序。第一张中断向量表由硬件决定,所在区域为ROM(flash),地址空间从0X00开始,其中0X00-0X1C为异常向量入口地址。另一张中断向量表在RAM 中,可以随便改,其位置在程序连接后才定。ARM7的内核实际上只有8个(1个保留)异常向量,对于其他所有众多的中断源,ARM7 的内核是通过IRQ或FRQ 的软件查询中断状态寄存器的位来获得ISR的起始地址。
;===================================================================================
   ; Setup IRQ handler  //;设置缺省中断处理函数
ldr r0,=HandleIRQ       //;This routine is needed;//使用ldr伪指令装载HandleIRQ的地址到r0中
ldr r1,=IsrIRQ          //If there isn't 'subs pc,lr,#4' at 0x18, 0x1c;//使用ldr伪指令装载IsrIRQ的地址到r1中
str r1,[r0]            //把r1的值写到r0指向的存储地址中,把IsrIRQ这个函数的地址写入到HandleIRQ存储单元里面



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

;Copy and paste RW data/zero initialized data

//以下程序段将加载哉中的数据段RW拷贝到运行域的ram中 将ZI段中的零初始化数据段清零

//跳入C语言的main函数执行到这步结束bootloader初步引导结束    

程序先把 ROM 里|Image$$RO$$Limt|开始的 RW 初始数据拷贝到 RAM 里面|Image$$RW$$Base|开始的地址,当RAM这边的目标地址到达|Image$$ZI$$Base|后就表示RW区的结束和ZI区的开始,接下去就对这片ZI区进行清零操作,直到遇到结束地址|Image$$ZI$$Limit|。

;======================================================================================
ldr r0, =|Image$$RO$$Limit|     //Get pointer to ROM data,rom中的RW数据源的起始地址
ldr r1, =|Image$$RW$$Base|   //and RAM copyRW区在RAM里的执行区起始地址
ldr r3, =|Image$$ZI$$Base|      //ZI区在RAM里面的起始地址

;Zero init base => top of initialised data检查装载地址和执行地址是否相同
cmp r0, r1      ; Check that they are different
beq %F2            ;//若相等则跳转到2,相同,则不拷贝该区间,初始化零数据区
1      
cmp r1, r3            ; Copy init data;//如果r0不等于r1,r1和r3比较,Copy init data,不相同,将装载区拷贝到执行区
ldrcc r2, [r0], #4    ;--> LDRCC r2, [r0] + ADD r0, r0, #4   当无符号数r1<r3时,读取r0地址处的内容      
strcc r2, [r1], #4    ;--> STRCC r2, [r1] + ADD r1, r1, #4
bcc %B1               ;//若相等则跳转到1,相同,则不拷贝该区间,初始化零数据区

2      
ldr r1, =|Image$$ZI$$Limit|      ; Top of zero init segment,ZI区在RAM里面的结束地址后面的一个地址
mov r2, #0
3      
cmp r3, r1      ; Zero init
strcc r2, [r3], #4     //当ZI区的起始地址未达等于结束地址时,继续清0
bcc %B3                ;//当无符号数r3<r1时,跳转到3处,这样做就完成了zi区的初始化清0



    [ :LNOT:THUMBCODE
     bl Main        ;Don't use main() because ......跳到Main()主函数,注意大小写
     b .                      
    ]

    [ 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                          ;//读取CPSR的值,R0=CPSR,CPSR为当前程序状态寄存器
bic r0,r0,#MODEMASK       ;//R0=R0&(~MODEMASK),MODEMASK=0X1F,也就是低五位清0
orr r1,r0,#UNDEFMODE|NOINT  ;//R1=R0|(MODEMASK|NONINT),R1为未定义模式,也就是低八位为11X11011
msr cpsr_cxsf,r1  ;UndefMode   ;//写把R1的值写到状态寄存器cpsr_cxsf(也就是CPSR),UndefMode
ldr sp,=UndefStack                    ;//设置未定义模式下的堆栈指针

orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1  ;AbortMode
ldr sp,=AbortStack

orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1  ;IRQMode
ldr sp,=IRQStack
    
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1  ;FIQMode
ldr sp,=FIQStack

bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1  ;SVCMode
ldr sp,=SVCStack

//USER mode has not be initialized.注意:不要切换到User模式进行User模式的堆栈设置,因为进入User模式后就

//不能再操作CPSR回到别的模式了,可能会对接下去的程序执行造成影响

mov pc,lr                             //堆栈初始化完成返回
;The LR register won't be valid if the current mode is not SVC mode.


;以下是上面提到的对存储寄存器初始化的数据map,共13个DCD

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))  //BAN1,6,7为32位数据完,其他除0外为16
     DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))   ;GCS0;BANK0的相关访问模式及各访问周期设置, 各位定义可参考memcfg.inc文件
     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, ARM  core burst disable, BANKSIZE 128M/128M

     DCD 0x30            ;MRSR6 CL=3clk CL:CAS latency
     DCD 0x30            ;MRSR7
;     DCD 0x20            ;MRSR6 CL=2clk
;     DCD 0x20            ;MRSR7

  

//下面是对ram区域map的定义;这里定义了处理器工作于各模式的堆栈区在ram中map.

ALIGN                  //字对齐
     AREA RamData, DATA, READWRITE

        ^   _ISR_STARTADDRESS         //^=map
HandleReset  #   4                               //#=field
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
HandleEINT0    #   4
HandleEINT1    #   4
HandleEINT2    #   4
HandleEINT3    #   4
HandleEINT4_7 #   4
HandleEINT8_23 #   4
HandleRSV6 #   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
HandleRSV24 #   4
HandleUSBD #   4
HandleUSBH #   4
HandleIIC    #   4
HandleUART0  #   4
HandleSPI1  #   4
HandleRTC  #   4
HandleADC  #   4

        END





文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: arm
相关日志:
评论: 0 | 引用: 0 | 查看次数: -
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.