没有合适的资源?快使用搜索试试~ 我知道了~
ARM启动代码分析。很详细的分析,很透彻的分析。赶紧下载哈~
资源推荐
资源详情
资源评论
;=========================================
; NAME: 2440INIT.S
; DESC: C start up codes
; Configure memory, ISR ,stacks
;Initialize C-variables
; HISTORY:
; 2002.02.25:kwtark: ver 0.0
; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep
mode
; 2003.03.14:DonGo: Modified for 2440.
;=========================================
;;context by art 20100901
;;汇编使用 Get 实现类似 C 中的 include 功能, Get 的文件必须是*.inc
GET option.inc ;芯片相关配置定义
GET memcfg.inc ;存储器配置定义
GET 2440addr.inc ;寄存器地址定义
;用于节电模式中,SDRAM 自动刷新, REFRESH 寄存器[22]bit : 0- auto
refresh; 1 - self refresh
BIT_SELFREFRESH EQU(1<<22)
; 处理器模式常量: CPSR 寄存器的后 5 位决定目前处理器模式 M[4:0]
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0
;定义处理器各模式下堆栈地址常量,_STACK_BASEADDRESS 定义在
option.inc 中
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 ~
; 因为存在 ARM 态和 Thumb 态两种工作模式,下一段伪代码用于根据处理器工
作状态确定编译器编译方式
; 初始化过程要强制处于 ARM 状态,待 init.s 初始化完成后再根据用户的编译配
置转换成相应的指令模式。
; 为此,定义变量 THUMBCODE 作为指示,跳转到 main 之前根据其值切换指令
模式,相当于定义一个 prestatus
; [|]类似于 C 语言的#if/#else/#endif
GBLL THUMBCODE
[ {CONFIG} = 16 ; 判断是不是 thumb 状态
THUMBCODE SETL {TRUE} ; 把 THUMBCODE 设置为 TURE
CODE32 ; 把处理器设置成为 ARM 模式
|
THUMBCODE SETL {FALSE} ; 把 THUMBCODE 设置为 FALSE
]
; 下面这段定义了关于在 arm 态和 thumb 态发生跳转时如何保存 LR 的宏,
MACRO
MOV_PC_LR
[ THUMBCODE
bx lr ; 目标地址是 THUMB 指令, 使用 bx 可以在跳转的时候自动切换到
thumb 状态
|
movpc,lr ; 目标地址也是 ARM 指令,采用这种方式跳转
]
MEND
MACRO
MOVEQ_PC_LR
[ THUMBCODE ; 同上
bxeq lr
|
moveq pc,lr ; 同上
]
MEND
;=========================================================
==============================
; 下面这个宏是中断服务程序的 HANDLER 前缀代码, 也就是进入服务程序之前
要跑的几句代码, 用于引导中断服务程序
; 这段程序用于把中断服务程序的首地址装载到 pc 中。2440init.s 定义了两个中
断表数据区(在本文件最后)
; 下面的宏处理第一个中断表, 供 34 个字空间,存放相应中断服务程序的首地址。
; 第二个中断表是 IRQ 中断的子表, 后续会提到
; HANDLER 宏的实现原理如下图:
; H|------| |------| |------| |------| |------|
; |/ / / | |/ / / | |/ / / | |/ / / | |/ / / |
; |------|<-sp |------||------| |------| |------|<-sp
; |------| |------|<-sp |------| |-isr--| |------| isr==>pc
; L|------||------| |--r0--|<-sp |--r0--|<-sp |------| r0==>r0
; (0) (1) (2) (3) (4)
;=========================================================
===============================
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;调整 sp, 跳过一格, 跳过的空间留给 pc
stmfdsp!,{r0} ;r0 入栈, r0 的原值
ldr r0,=$HandleLabel ;获取 HandleLabel 地址即中断向量表项的地址
ldr r0,[r0] ;读取中断服务程序地址到 r0
str r0,[sp,#4] ;r0 入栈, 中断服务程序地址, 同时 sp-=4, 即保持 sp 不变
ldmfd sp!,{r0,pc} ;出栈, r0 恢复原值, pc 实现跳转
MEND
;=========================================================
================================
; 2440init.s 采用简单加载方式, 因此这里用 IMPORT 引入变量|Image$$RO$
$Base|等...
; 它们是简单加载方式下由编译器生成的 RO/RW/ZI 段相关参数。
; 并且在简单加载方式下,通常 RW,ZI 在 Flash 中的位置就紧接着 RO 存储。
; 由于没有使用库函数__main(),RW 和 ZI 的初始化工作需要我们自己实现。
; 所以在初始化后期就需要通过使用这些参数实现代码搬运。
;=========================================================
================================
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
; 顺便定义 Main 跳转以及 TICK 中断所需的函数标号
IMPORT Main ; The main entry of mon program
;IMPORT OS_CPU_IRQ_ISR ;uCOS_II IrqISR
EXPORT HandleEINT0 ;for os_cpu_a.s
;=========================================================
================================
; 这里是正真的代码入口,地址 0 代码由此开始
;=========================================================
================================
EXPORT __ENTRY ; 导出符号_ENTRY,在 ADS 中可作为编译器
参数使用
AREA Init, CODE, READONLY ; 定义名为 Init 的代码段
ENTRY
__ENTRY
ResetEntry
;=========================================================
=============
; 在 ENDIAN_CHANGE 编译成机器码前就设定好, 下段在条件编译被丢弃,不
用理会,有兴趣可看看
; 实际上代码从 b ResetHandler 开始
;=========================================================
=============
ASSERT:DEF:ENDIAN_CHANGE
[ ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH
[ ENTRY_BUS_WIDTH=32
bChangeBigEndian ;DCD 0xea000007
]
[ ENTRY_BUS_WIDTH=16
andeqr14,r7,r0,lsl #20 ;DCD 0x0007ea00
]
[ ENTRY_BUS_WIDTH=8
streqr0,[r0,-r10,ror #1] ;DCD 0x070000ea
]
|
bResetHandler ; 程序 ResetHandler 开始, 在映像文件的位置: 0x00
]
bHandlerUndef ; handler for Undefined mode, 0x04
bHandlerSWI ; handler for SWI interrupt , 0x08
bHandlerPabort ; handler for PAbort , 0x0c
bHandlerDabort ; handler for DAbort , 0x10
b. ; reserved , 0x14
bHandlerIRQ ; handler for IRQ interrupt , 0x18
bHandlerFIQ ; handler for FIQ interrupt , 0x1c
bEnterPWDN ; power down?? , 0x20
;=========================================================
=============
; 这段不会被编译.忽略之,..
;=========================================================
=============
ChangeBigEndian
[ ENTRY_BUS_WIDTH=32
DCD0xee110f10;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD0xe3800080;0xe3800080 => orr r0,r0,#0x80; //Big-endian
DCD0xee010f10;0xee010f10 => mcr p15,0,r0,c1,c0,0
]
[ ENTRY_BUS_WIDTH=16
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8
DCD 0x100f11ee
DCD 0x800080e3
DCD 0x100f01ee
]
DCD 0xffffffff ;swinv 0xffffff is similar with NOP and run well in both
endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler
;=========================================================
=============
; 进入掉电模式的函数, 原型是 void EnterPWDN(int CLKCON), 可以先不理会
剩余23页未读,继续阅读
资源评论
wwz394692092
- 粉丝: 7
- 资源: 12
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功