加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ARM启动代码分析-philips的LPC2xxx系列

发布时间:2020-12-15 06:53:04 所属栏目:百科 来源:网络整理
导读:? ARM启动代码分析-philips的LPC2xxx系列 /********************************************************************************************** *File:???????? startup.s *Author:??? Embest w.h.xie 2005.02.21 *Desc:?????? lpc22xxlpc212xlpc211xlpc

?

ARM启动代码分析-philips的LPC2xxx系列

/**********************************************************************************************

*File:???????? startup.s

*Author:??? Embest w.h.xie 2005.02.21

*Desc:?????? lpc22xxlpc212xlpc211xlpc210xstartup 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????????? @ keepinterrupt 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,#-4]???????????????????????? // SPSR的T位为0,则[lr-4] -〉r0

???????????? ???BICEQ??r0,#0xFF000000??????? // SPSR的T位为0,清除r0的Bit24~Bit131位

?

??????????????? # R0 is interrupt number????????????????? //R0是中断号

??????????????? # R1 is stack point?????????????????????????? //R1是堆栈指针

?

??????????????? BL????? SWI_Exception?????????? //进入软中断处理程序

??????????????? LDMFD?? sp!,pc}^ ???? //出栈,现场数据恢复

?

?

# 快速响应中断的中断服务自程序的入口地址

FIQ_Handler:???

??????????????? STMFD???? SP!,{R0-R3,LR}????????????????????????? //入栈的现场保护

#??????????????? BL?????????? FIQ_Exception????????????????? //进入FIQ的中断处理程序

??????????????? LDMFD???? SP!,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??????????????????? //进行堆栈初始化工作

?

#------------------------------------------------------------------------------

#- 初始化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<r3,则把r0地址上的数据读出到r2中,然后r0=r0+4*/

??????????????? strcc?????? r2,[r1],#4? /*如果r1<r3,则把r2内数据写入道r1地址中,然后r1=r1+4*/

??????????????? bcc???????? LoopRw?? /*如果r1<r3,则跳转到LoopRw 继续执行*/

NoRW:???????? ldr?????????? r1,=Image_ZI_Limit /* 取ZI段的结束地址 */

??????????????? mov???????? r2,#0?????????????????????????????????? /*将r2赋0*/

LoopZI:???????? cmp???????? r3,r1????????????????? /*将ZI段清零*/

??????????????? strcc??????? r2,[r3],#4? ?/*如果r3<r1,将r2内容写入到r3地址单元中,然后r3=r3+1*/

??????????????? bcc???????? LoopZI???????? ? ?/*如果r3<r1(即C=0),则跳转到LoopZI */

?

??????????????? .extern? Main???????????????????????????????????? /*声明外部变量*/

??????????????? 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,#UND_Stack_Size??????? #未定义模式下堆栈深度

?

#进入终止模式,并禁止禁止FIQ中断和IRQ中断

?????????????????????????????????? MSR???? CPSR_c,#Mode_ABT|I_Bit|F_Bit

#紧接着未定义模式下的堆栈,设置终止模式下栈顶指针

?????????????????????????????????? MOV???? SP,#ABT_Stack_Size????????????????? #终止模式下堆栈深度

?

#进入FIQ模式,并禁止FIQ中断和IRQ中断

?????????????????????????????????? MSR???? CPSR_c,#Mode_FIQ|I_Bit|F_Bit

#紧接着终止模式下的堆栈,设置下FIQ模式下栈顶指针

?????????????????????????????????? MOV???? SP,R0

?????????????????????????????????? SUB???? R0,#FIQ_Stack_Size????????? #FIQ模式下的堆栈深度

?

#进入IRQ模式,并禁止FIQ中断和IRQ中断

?????????????????????????????????? MSR???? CPSR_c,#Mode_IRQ|I_Bit|F_Bit

#紧接着FIQ模式下的堆栈,设置IRQ模式下的栈顶指针

?????????????????????????????????? MOV???? SP,#IRQ_Stack_Size???????? #IRQ模式下的堆栈深度

?

#进入超级用户模式,并禁止FIQ中断和IRQ中断

?????????????????????????????????? MSR???? CPSR_c,#Mode_SVC|I_Bit|F_Bit

#紧接着IRQ模式下的堆栈,设置超级用户下的栈顶指针

?????????????????????????????????? MOV???? SP,#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区中

??????????????? LDMIA? R1!,{R2-R9}????????????? //把以[R1]为首地址的32个字节数据装载到R2-R9中

??????????????? STMIA? R0!,{R2-R9}????????????? //把R2-R9中的数据存入以[R0]为首地址的单元中

??????????????? LDMIA? R1!,{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值,返回

?

# 软中断处理代码

?

SWI_Exception:

?????????????? STMFD?? SP!,{R2-R3,LR}?????????????? //把R2,R3,LR值入栈

#0号软中断的处理程序

CMP???? R0,?#0???????????????????????????? //将R0和0比较

?????????????? //以下4行带EQ条件的代码均为当R0为0时应该执行的语句

?????????????? MRSEQ?? R2,?SPSR?????????????????????? //把SPSR读入到R2中

?????????????? STREQ?? R2,?[R1]????????????????? /把R2的值存入到[R1]中

?????????????? ORREQ?? R2,?R2,#0x80?????????????? //把R2的Bit7位置1

?????????????? MSREQ?? SPSR_c,R2??????????????????? //把R2的值写入到SPSR_c中,即禁止IRQ

?????????????? #1号软中断的处理程序

???????? ??????CMP????R0,? #1?????????????????????????????? //比较R0值和1

?????????????? LDREQ?? R2,?[R1]????????????????? //相等则把[R1]中的数据存入R2中

?????????????? MSREQ?? SPSR_c,R2????????????????? //相等把R2的值写入到SPSR_c中,恢复IRQ

??????????????

????????????????????????? #11号软中断的处理程序

?????????????? CMP???? R0,?#11??????????????????? //比较R0的值和11

?????????????? MRSEQ?? R2,?SPSR?????????????????????? //相等则把SPSR的值转存入到R2中

?????????????? BICEQ?? R2,#0x1F???????????????? //相等则把R2的Bit0~Bit4全部清零

?????????????? ORREQ?? R2,#Mode_SYS???? //相等则把R2与#Mode_SYS相与再存入R2

?????????????? MSREQ?? SPSR_c,R2??????? ????//相等则把R2的值存入SPSR_c中,即进入系统模式

?????????????? #12号软中断的处理程序

?????????????? CMP???? R0,?#12??????????????????? //比较R0的值和12

?????????????? MRSEQ?? R2,?SPSR?????????????????????? //相等则把SPSR的值存入R2

?????????????? BICEQ?? R2,#0x1F???????????????? //相等则把R2的Bit0~Bit4清零

?????????????? ORREQ?? R2,#Mode_USR ? //相等则把R2与#Mode_USR相与再存入R2中

?????????????? MSREQ?? SPSR_c,R2????????????????? //相等则把R2存入SPSR_c,即进入用户模式

?????????????????????????????

LDMFD?? SP!,PC}???????????? //恢复R2、R3、PC值,返回

?

?

?? .END???????????????????????????????????????????????????????????????????????? //汇编代码段结束

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读