Chinaunix首页 | 论坛 | 博客
  • 博客访问: 21071
  • 博文数量: 10
  • 博客积分: 400
  • 博客等级: 下士
  • 技术积分: 110
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-15 10:14
文章分类

全部博文(10)

文章存档

2010年(2)

2009年(8)

我的朋友

分类: LINUX

2009-09-15 17:30:55

;=========================================
;文章来自:http://blog.chinaunix.net/u3/104083/
;名字: MIni2440Init.S
;作用: 启动S3C2440-Targ1
;01.定义入口地址
;02.建立异常向量表
;03.初始化存储器系统
;04.初始化堆栈
;05.初始化必要IO
;06.初始化中断系统要求的RAM 向量
;07.开中断
;08.如有必要,改变处理器模式
;09.如有必要,改变处理器状态
;10.初始化C语言要求的存储器空间
;11.跳转到C去执行
     GET ../Inc/ASM_Jackarm.inc
;系统的工作模式设定
USERMODE    EQU  0x10                         ;用户模式
FIQMODE     EQU  0x11                         ;FIQ模式
IRQMODE     EQU  0x12                         ;IRQ模式
SVCMODE     EQU  0x13                         ;超级用户模式
ABORTMODE   EQU  0x17                         ;中止
UNDEFMODE   EQU  0x1b                         ;未定义模式
MODEMASK    EQU  0x1f                         ;系统模式
NOINT       EQU  0xc0                         ;
;系统的堆栈空间设定
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 ~

;  定义动态中断跳转的宏
;  用法:【行号 HANDLER 内存中存放跳转地址的某一字空间】
;  功能:在定义了isrLabel的地方,取出HandleLabel中的值然后跳转到这个值所代表的地址中去
;-------------------------------------------------------------------------
;满递减:堆栈通过减小存储器的地址向下增长,堆栈指针指向内含有效数据项的最低地址。指令如LDMFD,STMFD 等。
 
 MACRO
$HandlerJackArm HANDLER $HandleJackArm
$HandlerJackArm
    SUB    SP,SP,#4           ; 先空出一个字的空间,待会要把PC填进去
    STMFD  SP!,{R0}           ; 将R0入栈。满递减堆栈。
    LDR    R0,=$HandleJackArm ; 载入跳转表地址
    LDR    R0,[R0]            ; 载入表中的内容,即目的地址
    STR    R0,[SP,#4]         ; 把目的地址作为PC压栈
    LDMFD  SP!,{R0,PC}        ; 数据出栈,放入R0,PC寄存器。满递减堆栈
 
 MEND
;   主程序开始
;---------------------------------------------------------------------------
 
 IMPORT  |Image$$RO$$Base| ; ROM代码段的起始地址(你设置的R0)
 IMPORT  |Image$$RO$$Limit|  ; ROM代码段的结束地址(R0+代码段长度+1)
 IMPORT  |Image$$RW$$Base|   ; 注意这是在RAM里面用来存放RW数据的地方。刚上电时是没有任何数据的,要把数据搬过来
 IMPORT  |Image$$ZI$$Base|   ; SDRAM的ZI段的开始
 IMPORT  |Image$$ZI$$Limit|  ; SDRAM的ZI段的结束(ZI段需要全部清零)
 IMPORT  Main          ;声明C程序中的Main()函数
 AREA    Init,CODE,READONLY              ;声明代码段Init,只读属性
 ENTRY                                   ; 标识程序入口
 EXPORT __ENTRY
__ENTRY
;   复位入口
;---------------------------------------------------------------------------
ResetEntry
    B  ResetHandler     ;程序复位执行开始
    B  IsrUndef      ;handler for Undefined mode
 B  IsrSWI      ;handler for SWI interrupt
 B  IsrPabort     ;handler for PAbort
 B  IsrDabort     ;handler for DAbort
 B  .    ;没对应的异常,没有针对的处理代码
 B  IsrIRQ      ;handler for IRQ interrupt
 B  IsrFIQ      ;handler for FIQ interrupt
; B  EnterPWDN
IsrFIQ      HANDLER HandleFIQ
IsrIRQ      HANDLER HandleIRQ
IsrUndef    HANDLER HandleUndef
IsrSWI      HANDLER HandleSWI
IsrDabort   HANDLER HandleDabort
IsrPabort   HANDLER HandlePabort
;   IRQ中断入口
;   和其他异常不同,IRQ异常需要进一步确定子中断
;   探测是哪个外设引发了中断并根据跳转表中的目的地址进行跳转
;--------------------------------------------------------------------------
Isr_IRQ
 SUB     SP,SP,#4        ; 先空出一个字的空间,待会要把PC填进去                                
 STMFD SP!,{R8-R9}  ; r8 r9入栈                                                  
 LDR     R9,=INTOFFSET   ; 寄存器INTOFFSET中的值表示了是哪个外设引发的中断                       
 LDR     R9,[R9]         ; EINT0是第1个子中断,if INTOFFSET=0 then EINT0 occur                  
 LDR     R8,=HandleEINT0 ; 左移2位的目的是把子中断号换算成'字'偏移                             
 ADD     R8,R8,R9,lsl #2 ; 从中断跳转表中取出中断入口地址                                        
 LDR     R8,[R8]         ; 把这个地址充当PC,压入栈                                               
 STR     R8,[SP,#8]      ; 跳转到各个外设中断处理程序                                          
 LDMFD SP!,{R8-R9,PC}
 LTORG
ResetHandler
 LDR R0,=DSC1  ;设置引脚的驱动强度,第一版PCB必须,否则会造成数据不稳定,而且有些片外访问还会造成程序走飞
 LDR R1,=0xFFF00000
 STR R1,[r0]
 LDR R0,=DSC0
 LDR R1,=0x3FF
 STR R1,[r0]
;关闭看门狗
    LDR R0,=WTCON  ;把WTCON这个地址送给R0寄存器
 LDR R1,=0x00000000  ;把立即数0x00000000送给R1寄存器
 STR R1,[r0]         ;把R1中的数据传送给R0中数据地址
;关闭所有中断
    LDR R0,=INTMSK
    LDR R1,=0xffffffff
    STR R1,[R0]
;设置IRQ的总入口,这样C语言只需要管理子IRQ的入口
 LDR R0,=HandleIRQ ;This routine is needed
 LDR R1,=Isr_IRQ   ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c'
 STR R1,[R0]
 
;To reduce PLL lock time, adjust the LOCKTIME register.
 ldr r0,=LOCKTIME
 ldr r1,=0xFFFFFFFF
 str r1,[r0]
; 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]
 
; 设置CPU总线模式
; If HDIVN is not 0, the CPU bus mode has to be changed from the fast bus mode to the asynchronous bus mode using following instruction
 [ CLKDIV_VAL>1           ; means Fclk:Hclk is not 1:1
 mrc p15,0,r0,c1,c0,0  ;AsyncBusMode FCLK作为CPU时钟,如果不执行这段代码则HCLK作为CPU时钟
 orr r0,r0,#0xc0000000  ;R1_nF:OR:R1_iA
 mcr p15,0,r0,c1,c0,0
 |
 mrc p15,0,r0,c1,c0,0  ;FastBusMode
 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)
 str r1,[r0]
    LDR R0,=rGPBCON
    LDR R1,=0x155555
    STR R1,[R0]
    LDR R0,=rGPBDAT
    LDR R1,=0xaaa
    STR R1,[R0]
;汇编指令TST
;TST{cond} Rn,operand2
;例子1:TST R0,#0x01 ;判断R0 的最低位是否为0
;例子2:TST R1,#0x0F ;判断R1 的低4 位是否为0
;Check if the boot is caused by the wake-up from SLEEP mode.
 ldr r1,=GSTATUS2 ;把GSTATUS2地址送给R1
 ldr r0,[r1]      ;把R1中的地址读出来给R0
 tst r0,#0x2      ;判断R0的第二位是否为0
 bne WAKEUP_SLEEP ;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler
;设置存储器控制器 Set memory control registers
 ldr r0,=SMRDATA ;
 ldr r1,=BWSCON ;BWSCON Address= 0x48000000
 add r2, r0, #52 ;End address of SMRDATA 一共有13个配置寄存器,合52字节
0
 ldr r3, [r0], #4
 str r3, [r1], #4
 cmp r2, r0
 bne %B0
;延时,等待存储器稳定工作相当于延时DELAY
 mov r0, #0x1000    ;随便给的个数
1
 subs r0, r0, #1 ;R0 = R0 - 1
 bne %B1            ;如果R0 != 0 ,B向后跳到1去
 
;为各模式初始化堆栈 Initialize stacks
 bl InitStacks 
;判断是从NAND启动还是从NOR启动
 ldr r0, =BWSCON         ;送BWSCON给R0,为读取这个寄存器做准备
 ldr r0, [r0]            ;读取BWSCON寄存器的值给R0
 ands r0, r0, #6  ;R0=R0&0x06,取出1和2位数据 OM
 bne copy_proc_beg  ;如果不为0
 adr r0, ResetEntry  ;OM[1:0] == 0, NAND FLash boot
 cmp r0, #0    ;程序起始地址不为0,说明当前在用Multi-ice调试
 bne copy_proc_beg  ;don't read nand flash for boot
 
;  代码搬移,RW段初始化,注意:只支持ADS的simple映象布局,不要用scatter方式链接工程
;-------------------------------------------------------------------------------
copy_proc_beg
 adr r0, ResetEntry
 ldr r2, BaseRO
 cmp r0, r2
 ldreq r0, EnddRO
 beq InitRam 
 ldr r3, EnddRO

 ldmia r0!, {r4-r7}
 stmia r2!, {r4-r7}
 cmp r2, r3
 bcc %B0      ; 搬移RO段
 
 sub r2, r2, r3
 sub r0, r0, r2    
  
InitRam 
 ldr r2, BaseRW
 ldr r3, BaseZI 
0
 cmp r2, r3
 ldrcc r1, [r0], #4
 strcc r1, [r2], #4
 bcc %B0      ; 搬移RW段
 mov r0, #0
 ldr r3, EnddZI

 cmp r2, r3
 strcc r0, [r2], #4
 bcc %B1      ; 清空ZI段
 
 ; 终于进入C语言啦
 bl Main ; 注意:C代码中不要出现小写的main,否则ADS会自动生成搬移代码、初始化堆栈、初始化运行库等代码段"__main",产生冗余代码
  b .
;  为各个处理器模式初始化堆栈
;------------------------------------------------------------------------------------------
InitStacks
 ;未定义指令异常
 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
 ;IRQ
 orr r1,r0,#IRQMODE|NOINT
 msr cpsr_cxsf,r1  ;IRQMode
 ldr sp,=IRQStack  ; IRQStack=0x33FF_7000
 ;FIRQ
 orr r1,r0,#FIQMODE|NOINT
 msr cpsr_cxsf,r1  ;FIQMode
 ldr sp,=FIQStack  ; FIQStack=0x33FF_8000
 ;SVC 操作系统保护模式(由SWI指令引发)
 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.
 mov pc,lr
 ;The LR register won't be valid if the current mode is not SVC mode.

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]
 ;Set memory control registers
  ldr r0,=SMRDATA ;be careful!, hzh
 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
 mov r1,#256
0 subs r1,r1,#1 ;1) wait until the SelfRefresh is released.
 bne %B0
 ldr r1,=GSTATUS3  ;GSTATUS3 has the start address just after SLEEP wake-up
 ldr r0,[r1]
 mov pc,r0
 
;  定义各个bank的存储器控制器参数表,这些参数根据ASM_header.inc中的配置而生成,这里无需修改
;  GCS0->SST39VF1601
;  GCS1->16c550
;  GCS2->IDE
;  GCS3->FPGA--FIFO
;  GCS4->DM9000
;  GCS5->CF Card
;  GCS6->SDRAM
;  GCS7->unused
;------------------------------------------------------------------------------
SMRDATA DATA
 DCD ((B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28));配置各个bank的位宽,这里没有指定是否使用wait和UB/LB握手信号(缺省不使用)
 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)+REFCNT);REFRESH CONTROL REGISTER
 DCD ((BURST_EN<<7)+(SCKE_EN<<5)+(SCLK_EN<<4)+BK76MAP);BANKSIZE REGISTER
 DCD (B6_CL<<4);MRSR6
 DCD (B7_CL<<4);MRSR7
 
BaseRO     DCD |Image$$RO$$Base|
EnddRO  DCD |Image$$RO$$Limit|
BaseRW     DCD |Image$$RW$$Base|
BaseZI     DCD |Image$$ZI$$Base|
EnddZI  DCD |Image$$ZI$$Limit|
         
;  定义中断向量表,此表存在内存中,中断入口根据表格中的地址跳转到正确的地址,这样跳转地址就可以在运行时改变
;---------------------------------------------------------------------------------
 ALIGN
 AREA SDRAMDATA, DATA, READWRITE
 
 ^   _ISR_STARTADDRESS
HandleReset   #   4
HandleUndef   #   4
HandleSWI   #   4
HandlePabort     #   4
HandleDabort     #   4
HandleReserved   #   4
HandleIRQ   #   4
HandleFIQ   #   4
;以下是IRQ中断的各个子中断,根据子中断号顺序排列
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
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 
 
    END
阅读(336) | 评论(1) | 转发(0) |
0

上一篇:没有了

下一篇:jackarmBootloader(二)ASM_Jackarm.inc

给主人留下些什么吧!~~

chinaunix网友2009-09-16 11:28:23

不错的东西。。。