您的位置 首页 国产IC

LPC2xxx发动代码剖析

ARM启动代码分析-philips的LPC2xxx系列12006-7-2414:30:00*******************************************************

ARM发动代码剖析-philips的LPC2xxx系列12006-7-24 14:30:00

/**********************************************************************************************
*File: startup.s
*Author: Embest w.h.xie 2005.02.21
*Desc: lpc22xx/lpc212x/lpc211x/lpc210x startup code
*History:
* note modify:cui jian jie 2006-4-25
*comment:
**********************************************************************************************/
#处理器的七种作业方式的常量界说
.EQU Mode_USR, 0x10#用户形式
.EQU Mode_FIQ, 0x11 #FIQ形式
.EQU Mode_IRQ, 0x12 #IRQ形式
.EQU Mode_SVC, 0x13#超级用户形式
.EQU Mode_ABT, 0x17#停止形式
.EQU Mode_UND, 0x1B #未界说形式
.EQU Mode_SYS, 0x1F#体系形式
#中止屏蔽位
.EQU I_Bit, 0x80 //IRQ中止操控位,当被置位时,IRQ中止被制止
.EQU F_Bit, 0x40 //FIQ中止操控位,当被置位时,FIQ中止被制止
#状况屏蔽位
.EQU T_bit, 0x20//T位,置位时在Thumb形式下运转,清零时在ARM下运转
#界说程序进口点
.globl _start
.code 32
.TEXT
_start:
#中止向量表
Vectors:
LDR PC, Reset_Addr//把Reset_Addr地址处的内容放入PC中
LDR PC, Undef_Addr
LDR PC, SWI_Addr
LDR PC, PAbt_Addr
LDR PC, DAbt_Addr
.long 0xb9205f80@ keep interrupt vectors sum is 0
LDR PC, [PC, #-0xff0] //当时PC值减去0xFF0等于IRQ中止进口地址
LDR PC, FIQ_Addr
#地址表
Reset_Addr: #该地址标号寄存Reset_Handler程序段的进口地址
.long Reset_Handler
Undef_Addr: #该地址标号寄存Undef_Handler程序段的进口地址
.long Undef_Handler
SWI_Addr: #该地址标号寄存SWI_Handler程序段的进口地址
.long SWI_Handler
PAbt_Addr: #该地址标号寄存PAbt_Handler程序段的进口地址
.long PAbt_Handler
DAbt_Addr:
.long DAbt_Handler
.long 0
IRQ_Addr: #地址标号处寄存一个无效的数据
.long 0
FIQ_Addr: #该地址标号寄存FIQ_Handler程序段的进口地址
.long FIQ_Handler
Undef_Handler:
B Undef_Handler
PAbt_Handler:
B PAbt_Handler
DAbt_Handler:
B DAbt_Handler
#软中止的中止服务子程序进口地址
SWI_Handler:
STMFD sp!, {r0-r3, r12, lr}//入栈,现场数据维护
MOV r1, sp //把仓库指针SP存入R1中
MRS r0, spsr//把SPSR值存入R0,SPSR值为发生软中止时的CPSR
TST r0, #T_bit //判别R0(SPSR)的T位是否为0
#SPSR的T位不为0,作业在Thumb形式下
LDRNEH r0, [lr,#-2] //SPSR的T位不为0,则[lr-2]-〉r0
BICNE r0, r0, #0xFF00// SPSR的T位不为0,铲除r0的Bit8~Bit15位
# SPSR的T位为0,作业在ARM形式下
LDREQ r0, [lr,#-4] // SPSR的T位为0,则[lr-4] -〉r0
BICEQ r0, r0, #0xFF000000// SPSR的T位为0,铲除r0的Bit24~Bit131位
# R0 is interrupt number //R0是中止号
# R1 is stack point //R1是仓库指针
BL SWI_Exception //进入软中止处理程序
LDMFD sp!, {r0-r3, r12, pc}^ //出栈,现场数据康复
#快速呼应中止的中止服务自程序的进口地址
FIQ_Handler:
STMFD SP!, {R0-R3, LR} //入栈的现场维护
# BL FIQ_Exception//进入FIQ的中止处理程序
LDMFD SP!, {R0-R3, LR} //出栈,康复现场
SUBS PC, LR, #4 //回来到主程序
#复位后程序处理的进口地址
Reset_Handler:
BL RemapSRAM//进行存储器映射的操作
#下面几行代码用来判别当时的作业形式
MRS R0, CPSR //读CPSR到寄存器R0
AND R0, R0, #0x1F //R0 = R0 AND 0x1F
CMP R0,#Mode_USR//比较R0和#Mode_USR,二者相减
//假如持平则阐明当时处在用户形式下,需求经过发生11号软中止进入体系形式。由于下面的初始化仓库
//需求在不同的作业形式下切换,而在用户形式下不能直接切换,只要体系形式能够,所以要经过发生11
//号软中止切换到用户形式。
SWIEQ #11
BL InitStack //进行仓库初始化作业
ARM发动代码剖析-philips的LPC2xxx系列32006-7-24 14:33:00
#——————————————————————————
#-初始化C变量
#————————
#-下表由连接器主动发生
#- RO:只读=代码区。
#- RW:可读可写=预先初始化的数据(初始化的全局变量)和预先被清零的数据(未初始化的全局变量)。.
#- ZI:预先被清零的数据区(未初始化的全局变量)
#-预先被初始化的数据区定位在代码区之后。
#-预先被清零的数据区定位在预先被初始化的数据区之后。
#-留意数据区的方位:
#- I假如用ARM SDT,当链接器挑选no -rw-base时,数据区被映射在代码区之后
#-你能够把数据区房子内部的SRAM( -rw-base=0x40 or 0x34)中
#-或许放在外部的SRAM( -rw-base=0x2000000 )中。
#-留意:为了进步代码的密度,预先被初始化的数据有必要尽可能的少。
#——————————————————————————
#该部分程序功用:先判别当时是在RAM中运转仍是在FLASH中运转,假如在FLASH中运转,先把FLASH
#中的预先赋值的RW段数据和未赋值的ZI段数据都搬移到RAM区中,再把ZI段数据悉数清零;假如程#序就是在RAM中运转,则直接把ZI段数据清零。
.extern Image_RO_Limit /* ROM区中数据段的开端地址*/
.extern Image_RW_Base /* RW段开端地址*/
.extern Image_ZI_Base /* ZI段的开端地址*/
.extern Image_ZI_Limit /* ZI段的完毕地址加1 */
ldr r0, =Image_RO_Limit /*取ROM区中数据段的首地址*/
ldr r1, =Image_RW_Base/*取RAM区中RW段的方针首地址*/
ldr r3, =Image_ZI_Base/*取RAM区中ZI段的首地址*/
cmp r0, r1/*比较ROM区中数据段首地址和RAM区中RW段方针首地址*/
beq NoRW /*持平代表当时是在RAM中运转*/
LoopRw: cmp r1, r3 /*不持平则和RAM区中ZI段的方针地址比较*/
ldrcc r2, [r0], #4/*假如r1
strcc r2, [r1], #4/*假如r1
bcc LoopRw/*假如r1
NoRW: ldr r1, =Image_ZI_Limit /*取ZI段的完毕地址*/
mov r2, #0 /*将r2赋0*/
LoopZI: cmp r3, r1/*将ZI段清零*/
strcc r2, [r3], #4/*假如r3
bcc LoopZI /*假如r3
.externMain /*声明外部变量*/
B Main /*t跳转到用户的主程序进口*/
#为每一种形式树立仓库,ARM仓库指针向下成长
InitStack:
MOV R1, LR //把该子程序回来地址保留在R1中
LDR R0, =Top_Stack//取栈定地址到R0中
#进入未界说形式,并制止FIQ中止和IRQ中止
MSR CPSR_c, #Mode_UND|I_Bit|F_Bit
#设置未界说形式下仓库的栈顶指针
MOV SP, R0
SUB R0, R0, #UND_Stack_Size#未界说形式下仓库深度
#进入停止形式,并制止制止FIQ中止和IRQ中止
MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit
#紧接着未界说形式下的仓库,设置停止形式下栈顶指针
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size#停止形式下仓库深度
#进入FIQ形式,并制止FIQ中止和IRQ中止
MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit
#紧接着停止形式下的仓库,设置下FIQ形式下栈顶指针
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size#FIQ形式下的仓库深度
#进入IRQ形式,并制止FIQ中止和IRQ中止
MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit
#紧接着FIQ形式下的仓库,设置IRQ形式下的栈顶指针
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size#IRQ形式下的仓库深度
#进入超级用户形式,并制止FIQ中止和IRQ中止
MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit
#紧接着IRQ形式下的仓库,设置超级用户下的栈顶指针
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size#超级用户下的仓库深度
#设置进入用户形式
MSR CPSR_c, #Mode_USR
#紧接着超级用户形式下的仓库,设置用户形式下的栈顶指针,剩下的空间都开辟为仓库
MOV SP, R0
MOV PC, R1 #仓库初始化子程序回来
#重映射SRAM区
RemapSRAM:
MOV R0, #0x40000000 //RAM区首地址
LDR R1, =Vectors //向量表首地址
#下面一段程序是把从0x00000000开端的64个字节(FLASH中的中止向量表和地址表)搬移到以
#0x40000000为首地址的RAM区中
LDMIAR1!, {R2-R9}//把以[R1]为首地址的32个字节数据装载到R2-R9中
STMIAR0!, {R2-R9}//把R2-R9中的数据存入以[R0]为首地址的单元中
LDMIAR1!, {R2-R9}//把以[R1]为首地址的32个字节数据装载到R2-R9中
STMIAR0!, {R2-R9}////把R2-R9中的数据存入以[R0]为首地址的单元中
#下面几行代码设置存储器映射操控寄存器
LDR R0, =MEMMAP//取MEMMAP地址到R0
MOV R1, #0x02
STR R1, [R0]//给MEMMAP赋值为0x02,设置中止向量从RAM区重新映射
mov pc,lr //跳转到主程序
#下面一段程序代码是进入软中止来切换体系的作业形式,当期望从一种形式切换入另一种形式时,能够通
#过调用下面对应标号的程序段进入软中止。在软中止处理程序中会依据所给定的中止号处理,履行SWI #num后软中止号被存入R0中。
.globl disable_IRQ
.globl restore_IRQ
.globl ToSys
.globl ToUser
#制止IRQ
disable_IRQ:
STMFD SP!, {LR} //把LR值压入仓库
swi #0 //发生0号软中止,0 -〉R0
LDMFD SP!, {pc} //康复PC值,回来
#康复IRQ
restore_IRQ:
STMFD SP!, {LR} //把LR值压入仓库
swi #1 //发生1号软中止,1 –〉R0
LDMFD SP!, {pc} //康复PC值,回来
#进入体系作业形式
ToSys:
STMFD SP!, {LR} //把LR值压入仓库
swi #11 //发生11号软中止,11 –〉R0
LDMFD SP!, {pc} //康复PC值,回来
#进入用户作业形式
ToUser:
STMFD SP!, {LR} //把LR值压入仓库
swi #12 //发生12号软中止,11 –〉R0
LDMFD SP!, {pc} //康复PC值,回来

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/ic/276790.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部