您的位置:首页 > 编程语言

启动代码是几乎是每个arm程序程序必备的,

2011-12-07 15:39 302 查看
启动代码是几乎是每个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

我在写一个arm920T的微型OS,主要是想借着写OS的过程学习ARM的底层编程,然后跳到Linux。启动代码是固件的一部分,最经学校要搞个设计,不知OS什么时候能写好,反正搞定后立即发帖。

下边是完整的工程 ourdev_444408.rar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: