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

arm启动代码分析

发布时间:2020-12-15 06:53:01 所属栏目:百科 来源:网络整理
导读:? /*文件名:2440init.s ;*功能:2440启动代码,实现硬件初始化及存储空间的映射等 ;*设计者:enjoymylinux ;*设计时间:2010.2.10 ;*版本:V1.0 ;*参考程序:友善之臂启动代码及sumsang的bootloader源代码vivi ;*/ ? ;//注意点:由于ARM是32位的,一般都按
?

/*文件名:2440init.s

;*功能:2440启动代码,实现硬件初始化及存储空间的映射等

;*设计者:enjoymylinux

;*设计时间:2010.2.10

;*版本:V1.0

;*参考程序:友善之臂启动代码及sumsang的bootloader源代码vivi

;*/

?

;//注意点:由于ARM是32位的,一般都按照32位的字对齐

?

;//64M SDRAM?内存空间分配状况

;//0x3000_0000???内存起始地址

;//???????????????????????>???supervivi下载程序的缓存空间???共16M

;//0x3100_0000

;//???????????????????????>?????程序的运行空间

;//0x31ff_0000

;//???????????????????????>?????堆栈空间????????

;//0x33ff_8000

;//?????????????????????????????????预保留空间

;//0x33ff_ff00

;//???????????????????????>?????中断向量表

;//0x3400_0000???内存结束地址

?

;//系统引导及启动过程

;//(1)硬件初始化????????关闭看门狗,屏蔽所有中断

;//(2)时钟初始化????????调整PLL锁相环到合适频率

;//(3)开启总线状态指示灯

;//(4)检测启动状态??????boot启动还是外界唤醒恢复?

;//(5)初始化内存????????设置SDRAM寄存器,擦除内存

;//(6)初始化FLASH???????设置FLASH寄存器,检测启动物理位置

;//(7)拷贝代码到内存????NOR FLASH可以直接运行;NAND FLASH必须拷贝到RAM中才行

;//(8)跳转到Main去执行

?

?

?

?

;//包含头文件,注意:在汇编程序中头文件后缀名为.inc,而在C程序中后缀名为.h

;// option.inc???定义配置PLL及总线宽度寄存器位

;// memcfg.inc???定义存储器的寄存器的位定义

;// 2440addr.inc 2440各寄存器的地址

;//获取头文件,其中GET可用include来代替,两者可以互换

?????????GET option.inc

?????????GET memcfg.inc

?????????GET 2440addr.inc

?

BIT_SELFREFRESH EQU???(1<<22)

?

;//定义一些常量,EQU相当#define语句

;//处理器各工作模式定义,即CPSR中后五位CPSR[4:0]

USERMODE????EQU?????0x10

FIQMODE?????EQU???????0x11

IRQMODE?????EQU??????0x12

SVCMODE?????EQU??????0x13

ABORTMODE???EQU????0x17

UNDEFMODE???EQU????0x1b

MODEMASK????EQU????0x1f

;//CPSR[7:5]

I_BIT??????EQU??????0x80??;//中断位

F_BIT??????EQU??????0x40??;//快速中断位

T_BIT??????EQU??????0x20??;//指令模式状态位

NOINT??????EQU?????????0xc0??;//屏蔽中断位

?

;//定义stack的地址,其中_STACK_BASEADDRESS代表堆栈基地址

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 ~

?

;//检测是thumb指令集还是arm指令集

?????????GBLL????THUMBCODE???????????????????????;//定义一个全局变量

?????????[ {CONFIG} = 16?????????????????????????;// #if(CONFIG=16)

THUMBCODE SETL??{TRUE}??????????????????????;//????THUMBCODE=TRUE;

?????????????CODE32??;//说明此后代码为arm指令???????????

?????????????????|??????????????????????????????????????????????????????????????????????????????????;// #else

THUMBCODE SETL??{FALSE}?????????????????????;//????THUMBCODE=FALSE;

????]

;//宏定义

?????????????????MACRO???????;//宏定义开始

?????????MOV_PC_LR???????;//宏名称

?????????????????[ THUMBCODE

?????????????bx lr

?????????????????|

?????????????mov?pc,lr

?????????????????]

?????????MEND???????????;//宏定义结束

;//宏定义

?????????????????MACRO

?????????MOVEQ_PC_LR

?????????????????[ THUMBCODE

????????bxeq lr

??????????????????|

?????????????moveq pc,lr

?????????????????]

?????????MEND

;//带参数的宏定义

;//宏定义,作用是当发生中断时,将中断服务程序的首地址装载到PC中

;//$HandlerLabel HANDLER(宏名称)?$HandleLabel(宏的参数)

;//*********************************************************

?????????????????MACRO

$HandlerLabel HANDLER $HandleLabel

?

$HandlerLabel

?????????sub???sp,sp,#4????????????;//SP减4,为了存储跳转地址

?????????stmfd????????sp!,{r0}??????????;//将工作寄存器压入堆栈,

????ldr?????r0,=$HandleLabel ;//装载HandleLable的地址到r0

?????????ldr?????r0,[r0]??????????????????;//装载HandleLable的内容到r0,即服务程序的地址

?????????str?????r0,[sp,#4]???????;//存储HandleLable的内容到堆栈

?????????ldmfd???sp!,{r0,pc}??????;//恢复r0的内容,并使PC跳转到HandleLable,即中断服务的首地址

?????????MEND

;//*********************************************************

;//声明、通知编译器标号在其他源文件中定义,但要在本文件中调用

;//一个ARM程序是由RO、RW、ZI三段组成(具体可见编译器生成的空间分配list文件)

;//RO代码段(只读)??RW?已经初始化的全局变量(读写)?ZI未初始化的全局变量(零初始化)

;//这些地址是通过编译器的设定来确定的

?????????IMPORT??|Image$$RO$$Base|?????;//RO段起始地址

?????????IMPORT??|Image$$RO$$Limit|??;//RO段结束地址加1

?????????IMPORT??|Image$$RW$$Base|???;//RW段起始地址

?????????IMPORT??|Image$$RW$$Limit|??;//RW段结束地址加1

?????????IMPORT??|Image$$ZI$$Base|???;//ZI段起始地址

?????????IMPORT??|Image$$ZI$$Limit|??;//ZI段结束地址加1

???

?????????IMPORT???MMU_SetAsyncBusMode

?????????IMPORT???MMU_SetFastBusMode??;

?

?????????IMPORT??Main????;//C代码的入口点

;//**********************************************************8

;//定义一个代码段,段名为Init,属性:代码,只读

?????????AREA????Init,CODE,READONLY

;//声明入口点,整个镜像从这个地方开始执行,一般来说一个文件里只能有一个

?????????ENTRY

;//声明一个全局标号,可以在其他文件中被引用????

?????????EXPORT????__ENTRY

__ENTRY?????;//__ENTRY标号

ResetEntry??;//ResetEntry标号

;//指令?b?:跳转指令,后加代码段标号,程序执行到此处时将会跳转到相应的代码段执行?

?????????;1)The code,which converts to Big-endian,should be in little endian code.

?????????;2)The following little endian code will be compiled in Big-Endian mode.

?????????;??The code byte order should be changed as the memory bus width.

?????????;3)The pseudo instruction,DCD can not be used here because the linker generates error.

????????

?????????ASSERT?????:DEF:ENDIAN_CHANGE???;;//断言伪定义,假定后面的ENDIAN标识已经定义

????????

?????????[ ENDIAN_CHANGE

?????????????ASSERT??:DEF:ENTRY_BUS_WIDTH

?????????????[ ENTRY_BUS_WIDTH=32

???????????????????b???????ChangeBigEndian?????????;DCD 0xea000007

?????????????]

?

?????????????[ ENTRY_BUS_WIDTH=16

???????????????????andeq???????r14,r7,r0,lsl #20???;DCD 0x0007ea00

?????????????]

?

?????????????[ ENTRY_BUS_WIDTH=8

???????????????????streq?????????r0,[r0,-r10,ror #1] ;DCD 0x070000ea

?????????????]

?????????|

?????????????b???????ResetHandler

????]

;/**********************************************************/

;//中断向量表vertor table

?????????b???????HandlerUndef??;handler for Undefined mode

?????????b???????HandlerSWI??????????;handler for SWI interrupt

?????????b???????HandlerPabort??????????;handler for PAbort

?????????b???????HandlerDabort?????????;handler for DAbort

?????????b??????????????.??????????;reserved

?????????b???????HandlerIRQ??????????;handler for IRQ interrupt

?????????b???????HandlerFIQ???????????;handler for FIQ interrupt

?

?

?????????b???????EnterPWDN?????; Must be @0x20.

;/***********************************************************/

;//ChangeBigEndian标号

ChangeBigEndian

;//?符号[]相当于编译指令#if····#else??????····

;//通过编译指令,不同的总线宽度采取不同的存储单元分配措施

;//伪汇编指令DCD?用于分配一片连续的字节存储单元

?????????[ ENTRY_BUS_WIDTH=32

?????????????DCD?0xee110f10??????;0xee110f10 => mrc p15,c1,c0,0

?????????????DCD?0xe3800080?????;0xe3800080 => orr r0,#0x80;??//Big-endian

?????????????DCD?0xee010f10??????;0xee010f10 => mcr p15,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

;//宏展开,正确理解代码内容,代码要按规则编写,不要引起误解

;//代码标号相当于C语言中的函数,标号后的代码内容为函数的内容,即函数的具体实现过程?????????????

HandlerFIQ???

???????????HANDLER HandleFIQ

HandlerIRQ???

???????????HANDLER HandleIRQ

HandlerUndef?

???????????HANDLER HandleUndef

HandlerSWI???

???????????HANDLER HandleSWI

HandlerDabort?

???????????HANDLER HandleDabort

HandlerPabort

??????HANDLER HandlePabort

;//IsrIRQ代码段,实现中断服务程序的跳转

IsrIRQ

?????????sub???sp,#4???????;reserved for PC

?????????stmfd????????sp!,{r8-r9}

?

?????????ldr????r9,=INTOFFSET

?????????ldr????r9,[r9]

?????????ldr????r8,=HandleEINT0

?????????add??r8,r8,r9,lsl #2

?????????ldr????r8,[r8]

?????????str????r8,#8]

?????????ldmfd????????sp!,{r8-r9,pc}

?

?

?????????LTORG

;/*************************************************************************************/

;//声明一个标号ResetHandler,当其他处引用此标号时,程序跳转到此处执行

;//ResetHandler代码段

ResetHandler

?????;//禁止看门狗

?????????ldr????r0,=WTCON???????;//把寄存器WTCON的地址装入R0,watch dog disable

?????????ldr????r1,=0x0???????????????????????;//把0装入R1

?????????str????r1,[r0]??????????;//把R1内的值赋给地址为R0的存储区域,即WTCON,这三条语句相当于?WTCON=0x0;

????;//禁止所有中断

?????????ldr????r0,=INTMSK

?????????ldr????r1,=0xffffffff??;all interrupt disable

?????????str????r1,[r0]?????????;//这三条语句相当于?INTMSK=0xffffffff;

????;//禁止所有次级中断

?????????ldr????r0,=INTSUBMSK

?????????ldr????r1,=0x7fff???????????????????;all sub interrupt disable

?????????str????r1,[r0]?????????;//这三条语句相当于?INTSUBMSK=0x7ffff;

?

????//打开状态指示灯LED

?????????[ {TRUE}

?????????;rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);

?????????; Led_Display

?????????ldr????r0,=GPBCON

?????????ldr????r1,=0x00555555

?????????str????r1,[r0]?????????????????????????;//即GPCON=0x00555555;

????????

?????????ldr????r0,=GPBDAT

?????????ldr????r1,=0x07fe

?????????str????r1,[r0]?????????????????????????;//即GPBDAT=0x07fe;

?????????]

?

?????????;//To reduce PLL lock time,adjust the LOCKTIME register.

?????????ldr????r0,=LOCKTIME

?????????ldr????r1,=0xffffff

?????????str????r1,[r0]?????????????????????????;//即LOCKTIME=0xffffff;

;/************************************************************************************/

????[ PLL_ON_START

?????????; Added for confirm clock divide. for 2440.

?????????; Setting value Fclk:Hclk:Pclk

?????????ldr????r0,=CLKDIVN

?????????ldr????r1,=CLKDIV_VAL????????????????; 0=1:1:1,1=1:1:2,2=1:2:2,3=1:2:4,4=1:4:4,5=1:4:8,6=1:3:3,7=1:3:6.

?????????str????r1,[r0]???????????????????????????????????;//即CLKDIVN=CLKDIV_VAL;

?

?????????;//协处理器操作,MMU和CACHE属于P15协处理器,ARM处理器共支持多达16个协处理器

?

?

?????????[ CLKDIV_VAL>1???????????????; means Fclk:Hclk is not 1:1.

?????????mrc p15,0???????;//????

?????????orr r0,#0xc0000000??????;R1_nF:OR:R1_iA

?????????mcr p15,0

?????????|

?????????mrc p15,0

?????????bic r0,#0xc0000000;R1_iA:OR:R1_nF

?????????mcr p15,0

?????????],

????????

?????????;//Configure UPLL

?????????ldr????r0,=UPLLCON

?????????ldr????r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)?

?????????str????r1,[r0]?????????????????????????;//即UPLLCON=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)

?????????;//nop指令,不进行任何操作,空指令

?????????nop??; Caution: After UPLL setting,at least 7-clocks delay must be inserted for setting hardware be completed.

?????????nop

?????????nop

?????????nop

?????????nop

?????????nop

?????????nop

?????????;//Configure MPLL

?????????ldr????r0,=MPLLCON

?????????ldr????r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)??;Fin=16.9344MHz

?????????str????r1,[r0]????????????????????????????????????????????;//即MPLLCON=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)

????]

;/************************************************************************************/

?????????;Check if the boot is caused by the wake-up from SLEEP mode.

?????????ldr????r1,=GSTATUS2

?????????ldr????r0,[r1]

?????????tst????r0,#0x2??????????????????????????????????????????;//TST位测试指令,逻辑与操作,更新CPSR中相应的标志位

?????????;In case of the wake-up from SLEEP mode,go to SLEEP_WAKEUP handler.

?????????bne??WAKEUP_SLEEP????????????;//条件跳转指令,bne(b if not equal),beq(b if equal)

?

?????????EXPORT StartPointAfterSleepWakeUp??;//声明外部可以引用

StartPointAfterSleepWakeUp

?????????;//内存控制初始化

?????????;//adrl?地址读取伪指令,谨慎使用,编译器将其分解成两条指令,若不能成功分解会报错

?????????;//这段代码实现了8个BANK寄存器值的设定

????????adrl??r0,SMRDATA??

?????????ldr????r1,=BWSCON???;BWSCON Address

?????????add??r2,#52????????;End address of SMRDATA

?

0

?????????ldr????r3,[r0],#4??;//将地址为r0中的内容装载到r3,然后r0中的值加4,即指向下一个字

?????????str????r3,[r1],#4??;//注意8个BANK控制寄存器的地址是靠着的

?????????cmp?r2,r0????????????????????;//CMP指令会更新CPSR中的相应标志位,后面的指令根据此标志位来决定是否执行相应的操作

?????????bne??%B0???????????;//如果不相等就向后跳转到标号0,类似一个循环,直到r0=r2

?

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;???????When EINT0 is pressed,??Clear SDRAM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;//check if EIN0 button is pressed

;//当EIN0发生时先清除SDRAM再初始化堆栈,若没有发生则跳过SDRAM的清除阶段,

;//直接去初始化堆栈

????ldr????r0,=GPFCON

?????????ldr????r1,=0x0

?????????str????r1,[r0]

????????

?????????ldr????r0,=GPFUP

?????????ldr????r1,=0xff

?????????str????r1,[r0]

?

?????????ldr????r1,=GPFDAT

?????????ldr????r0,[r1]

????bic????r0,#(0x1e<<1)??;//bit clear?在值为1时清零

?????????tst????r0,#0x1???????????????????????;//按位与

?????????bne %F1??????;//如果not equal?向前跳转到标号1

????????

????????

?

;// Clear SDRAM Start

?

?????????ldr????r0,=0x55aa

?????????str????r1,=GPFDAT

?????????ldr????r1,[r0]???????;LED=****

;//所有的寄存器都清零

?????????mov r1,#0

?????????mov r2,#0

?????????mov r3,#0

(编辑:李大同)

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

    推荐文章
      热点阅读