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

2019-11-11来源: 51hei关键字:arm  程序必备  启动代码

启动代码是几乎是每个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 ;计算结束地址 


;下面是用于向内存控制器 

;装入配置信息的循环 

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

[1] [2]
关键字:arm  程序必备  启动代码 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic479604.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:2440裸机编程之五 定时器
下一篇:访问CP15寄存器的指令

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

多年来苹果基于ARM的Mac并不遥远
今日,外媒MacRumors发文表示,苹果公司目前在Mac系列产品中使用的处理器都依赖于英特尔,但这种情况可能很快会改变。ARM与Intel目前,苹果在所有Mac产品中都使用了Intel的x86芯片,iPhone和iPad则使用基于Arm的芯片。x86芯片和Arm芯片使用了不同的架构。英特尔的芯片是CISC(复杂指令集)架构,而Arm芯片是RISC(精简指令集)架构。顾名思义,RISC指令比CISC指令更小、更简单。这也意味着Arm处理器所需的功率更少,且执行计算任务的效率更高。从历史上看,Arm芯片的功能并不强大,因为x86芯片是为台式机设计,而Arm芯片则是为低功耗应用(如移动设备)设计的。过去,Arm一直专注于电源效率
发表于 2019-11-08
S3C2410启动代码从ADSv1.2移植到KEIL For ARM uV4的方法
到SDRAM内存中运行时,所需要加载的SDRAM配置文件,相当于ADSV1.2工程中每次都需要通过命令行键入” obey wtk2410.ads “文件中的内容。 DebugInRAM.ini文件的内容如下:可以看到,去掉了ads文件里面的禁止vector_catch和semihosting两个命令,其余都一样。二、建立RVMDK工程文件,不要系统自建的启动代码,加入基本文件和main主程序文件。修改init.s文件,这个是移植的关键。需要注意的地方有:1. 宏”MOV_PC_LR“在KEIL里面修改成相应的BX <Rn>指令。2.把init.s文件原来定义的段名”Init“ 修改成”RESET“,这应该相当于
发表于 2019-11-08
S3C2410启动代码从ADSv1.2移植到KEIL For ARM uV4的方法
ARM9学习2-ARM镜像文件和Scatter文件
ARM映像文件什么是arm的映像文件    arm映像文件其实就是可执行文件,包括bin或hex两种格式,可以直接烧到rom里执行。在axd调试过程中,我们调试的是axf文件,其实这也是一种映像文件,它只是在bin文件中加了一个文件头和一些调试信息。映像文件的组成ARM映像文件是一个层次性结构的文件,包括了域(region),输出段(output section)和输入段(input section)。所谓域,指的就是整个bin映像文件所处在的区域,它又分为加载域和运行域。加载域就是映像文件被静态存放的工作区域,一般来说flash里的 整个bin文件所在的地址空间就是加载域,当然在程序一般都不会放在
发表于 2019-11-08
ARM9学习2-ARM镜像文件和Scatter文件
ARM9学习3-调试第一个ARM汇编程序
调试第一个ARM汇编程序1.双击KEIL uVision4图标,打开RVMDK uVision4集成开发环境。2.通过菜单“projectnew uvision project…”,新建一个工程,选择要存放的位置和工程文件名“Test001”,点击“保存按钮”。3.CPU选型,选择三星的S3C2410A,继续点击“OK”按钮。4.不添加启动代码,所以选择“否”5.点击工具栏上的“”New 图标,新建一个文件,键入汇编源代码。6.点击工具栏上的“”Save 图标,保存该汇编源文件,命名为:Test001.s7.在左边的“Project”目录结构中,右击“Source Group 1”,选择“Add Files to Group
发表于 2019-11-08
ARM9学习3-调试第一个ARM汇编程序
ARM9学习4-S3C2410的启动代码分析-For ADSv1.2
通常,启动代码是指CPU复位后到进入C语言的main函数之前需要执行的那段汇编代码.这是由于C语言程序的运行需要具备一定的条件,比如:分配好外部数据空闿堆栈空间和中断入口等筿另外汇编代码可以更直接的对硬件进行操使效率更高. 通常启动代码是放在2410init.s汇编文件;特殊功能寄存器定义在2410addr.s;Memory Bank 配置在mencfg.s;还有系统的选项等在option.s文件;2410init.s不仅包括复位后执行的代码,还包括CPU进入掉电模式,产生中断等和处理器直接相关的,用汇编实现的代码.;=========================================; NAME
发表于 2019-11-08
嵌入式ARM启动代码的工作
能。(8)根据情况切换处理器的模式和状态:ARM在运行启动代码时处于特权模式,用户在进入应用程序之前,可以将其切换到用户 模式,也可以进行ARM状态和Thumb状态的切换。(9)初始化高级程序运行时用到的存储区,例如将RW属性的数据和ZI属性的数据移动到ARM等可以写的储存器,因为这些数据在程序加载时是保存在ROM等储存介质内的。(10)进入高级应用程序。
发表于 2019-09-21
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved