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

arm启动文件2440init.s分析

发布时间:2020-12-15 06:28:57 所属栏目:百科 来源:网络整理
导读:?最近整理电脑,找到了一些当初学习嵌入式linux时的资料,现在共享出来。方便大家学习之用,无所谓原创,无非就是在前人的基础上,进行了系统化的分析和综合而已。不过,还是加入了不少个人学习的思路跟方法,我觉得这才是最重要的。本来想共享到百度文库,

?最近整理电脑,找到了一些当初学习嵌入式linux时的资料,现在共享出来。方便大家学习之用,无所谓原创,无非就是在前人的基础上,进行了系统化的分析和综合而已。不过,还是加入了不少个人学习的思路跟方法,我觉得这才是最重要的。本来想共享到百度文库,赚点积分的,无奈百度嫌我格式太乱不允许上传,就直接复制到这里了,呵呵!


最近在学习嵌入式软件,现分享自己部分成果。平台:s3c2440 mcu

;=========================================

; NAME: 2440INIT.S

; DESC: C start up codes

;??????Configure memory,ISR,stacks

;Initialize C-variables

;=========================================

?

?

?

;注意:axd调试时,可以看到 指令pc地址从0x30000000开始,这是因为ram的起始地址是0x30000000.

;并且如果从nand启动,则处理器自动把nand首部的4k字节,复制到ram中,然后pc跳到0x30000000,开始执行。

?

;此源文件通常包含一些宏定义和常量定义

?

;通用的《启动流程图》:

;入口->屏蔽所有中断,禁止看门狗->根据工作频率设置PLL寄存器->初始化存储控制相关寄存器->初始化各模式下的栈指针

;->设置缺省中断处理函数->将数据拷贝到RAM中,数据段清零->跳转到c语言main入口函数中

?

?

;GET伪指令用于将一个源文件包含到当前源文件中,并将被包含文件在当前位置进行汇编处理,类似于c的include指令

;GET INLCUDE伪指令不能 用来包含目标文件,INCBIN伪指令 可以包含目标文件,

;被INCBIN伪指令包含的文件, 不 进行汇编处理,该执行文件或数据直接放入当前文件,编译器从INCBIN后边开始继续处理

;区分GET,INCLUDE,INCBIN的用法和作用

??????

?????? GEToption.inc???????????? ;定义芯片相关配置

?????? GETmemcfg.inc?????????? ;定义存储器配置

?????? GET2440addr.inc? ;定义寄存器符号

?

?

;REFRESH寄存器[22]bit :SDRAM刷新模式 0- auto refresh; 1 - self refresh

;用于节电模式中,SDRAM自动刷新

BIT_SELFREFRESH EQU?? (1<<22)

?

;Pre-defined constants

;模式预定义常量,给cpsr【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?? ;1100 0000,中断屏蔽掩码

?

;The location of stacks

;0x30000000 = 768M?

;定义各模式下的堆栈常量,是一个递减栈,后边标上了各个栈的大小

UserStack?????? EQU?????? (_STACK_BASEADDRESS-0x3800)? ; ~ 0x33ff4800 ???? 大小不定,跟堆大小相对应。毕竟是用户态栈

SVCStack?????? EQU?????? (_STACK_BASEADDRESS-0x2800)? ; ~ 0x33ff5800 ???? 4M

UndefStack???? EQU?????? (_STACK_BASEADDRESS-0x2400)? ; ~ 0x33ff5c00 ???? 1M

AbortStack???? EQU?????? (_STACK_BASEADDRESS-0x2000)? ; ~ 0x33ff6000 ???? 1M

IRQStack?????? EQU?????? (_STACK_BASEADDRESS-0x1000)? ; ~ 0x33ff7000 ???? 4M

FIQStack EQU?????? (_STACK_BASEADDRESS-0x0) ; ~ 0x33ff8000??? 4M

?

?

;处理器分为16位 32位两种工作状态 程序的编译器也是分16位和32两种编译方式 下面程序根据处理器工作状态确定编译器编译方式

;code16伪指令指示汇编编译器后面的指令为16位的thumb指令

;code32伪指令指示汇编编译器后面的指令为32位的arm指令

?

;Arm上电时处于ARM状态,故无论指令为ARM集或Thumb集,都先强制成ARM集,待init.s初始化完成后

;再根据用户的编译配置转换成相应的指令模式。为此,定义变量THUMBCODE作为指示,跳转到main之前

;根据其值切换指令模式

?

;Check if tasm.exe(armasm -16 ...@ADS 1.0)is used.

;检测工作模式,根据CONFIG的数值,确定工作模式

;{CONFIG}应该来自于ADS环境,在本环境中设置是进入时在ARM环境下,没有设置ARM/THUMB混合环境

;关于是否设置混合编程,在环境设置选项里的ARM Assembler 选项下,由ATPCS -> ARM/Thumb interworking选项负责

;IF ELSE ENDIF指令

?? ?

?????? GBLL??? THUMBCODE

?????? [{CONFIG} = 16????????

THUMBCODE SETL? {TRUE}???????? ;如果设置了config,则允许thumb指令,但THUMBCODE为真并不表明以下就是thumb指令,只是允许

?????? ??? CODE32????????????????????? ;code32表示以下是arm指令,在处理器刚开始时,必须以arm模式运行

???????????? |????????????????????????????????? ;此处容易产生错觉,丢掉CODE32这一行

THUMBCODE SETL? {FALSE}

??? ]

?

;bx是带状态切换的跳转指令,跳转到Rm指定的地址执行程序,若Rm的位[0]为1,则跳转时自动将CPSR的标志T

;T置位,即把目标地址的代码解释为Thumb代码;若Rm的位[0]为0,则跳转时自动将CPSR中的标志T复位,即把

;目标地址的代码解释为ARM代码

?

;定义两个宏,宏的作用:子函数返回(无条件,有条件)。

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

????? MOV_PC_LR

???????????? [ THUMBCODE???????????????????????? ;如果允许thumb指令,则需要根据最低位设置状态。

?????? ??? bx lr?????????????????????????????????? ;跳转,附带状态切换

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

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

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

?????? MEND

?

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

?????? MOVEQ_PC_LR?? ;相等则跳转,相等与否由寄存器某些位确定,在此处,有其上一句的指令执行结果决定

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

???????bxeq lr

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

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

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

?????? MEND

?

;重点分析下面这个宏,它对中断处理函数的调用很重要

?

?

;MACRO和MEND伪指令用于宏定义,MACRO标识开始,MEND标识结束。用MACRO和MEND定义的一段代码,称为

;宏定义体,这样在程序中就可以通过宏指令多次调用该代码段。伪指令格式:

?

;MACRO

;{$label}?macroname {$parameter} {$parameter} ...

????????????? ;宏定义体

;MEND

?

;其中? $label 宏指令被展开时,label可被替换成相应的符号,通常为一个标号,在一个标号前使用$表示被汇编时将

;使用相应的值替代$后的符号。

;macroname 所定义的宏的名称

;$parameter?宏指令的参数,当宏指令被展开时将被替换成相应的值,类似于函数中的形式参数

;对于子程序代码较短,而需要传递的参数比较多的情况下,可以使用汇编技术。首先要用MACRO和MEND伪指令定义宏,包括宏定义

;体代码。在MACRO伪指令之后的第一行定义宏的原型,其中包含该宏定义的名称,及需要的参数。在汇编程序中可以通过该宏定义

;的名称来调用它,当源程序被汇编时,汇编编译器将? 展开 每个宏调用,用宏定义体代替源程序中的宏定义的名称,并用实际的参数

;值代替宏定义时的形式参数

?

?

;在arm中,用的是满递减堆栈:stmfd,ldmfd,如果用其他的方式,arm可能不能有效识别

;注意:满递减指的是在入栈时的操作方式,在出栈时则正好相反的次序

;关于堆栈在数据放置方式,存取顺序上,可以参见《自学手册》P84中的实例分析

;例子:

;STMFD sp!,{R0-R7,LR}:(满递减:先减再放数值)sp根据数据个数,减小相应个数值的数据单位(一步到位),然后利用for循环语句,从当前sp位置,依次存储R0-R7,LR.即:sp处最后指向的是R0数据处

;LDMFD sp!,LR}:复制一个变量为sp值,用该变量依次将数据存入R0-R7,LR,变量值增加,最后,变量指向下一个将要取的值,完成后sp获得该变量值;

;risc模式,这是对ram的操作

?

?

;确切说,这是宏函数,编译时对调用语句要做相应的展开

?

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

$HandlerLabel HANDLER $HandleLabel

?

$HandlerLabel??????????????????????????? ;标号

?????? sub? sp,sp,#4????????? ;留出一个空间,为了存放跳转地址给pc。见:str r0,[sp,#4] ,注意sp值并未改变

??????

?????? stmfd????? sp!,{r0}? ;把r0中的内容入栈,保存起来

??????

?????? ldr???? r0,=$HandleLabel??? ;这是一个伪指令,不是汇编指令,目的:把$HandleLabel本身所在的地址给r0

??????

?????? ldr???? r0,[r0]?????????????????????????? ;把HandleXXX所指向的内容(也就是中断程序的入口地址)放入r0

??????

?????? str???? r0,#4]???? ?????? ????? ;把入口地址放入刚才留出的一个空间里

??????

?????? ldmfd?? sp!,{r0,pc}???? ??? ;出栈的方式恢复r0原值和为pc设定新值(也就完成了到ISR的转跳)。注:栈中r0内容在低地址

??????

?????? MEND

?

;这几个变量是ads环境下自动设置的,可以见环境配置选项里:ARM Linker->Output下,RO Base,RW Base

;RW Base 没设置,因为代码段的结束便是数据段的开始,这个ads可以自动设置

;IMPORT 引用变量

?????? IMPORT? |Image$$RO$$Base|??? ; Base of ROM code

?????? 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 to zero initialise

?????? IMPORT? |Image$$ZI$$Limit|?

?

?????? IMPORT MMU_SetAsyncBusMode

?????? IMPORT MMU_SetFastBusMode ;想知道代码具体内容见cp15手册,并以cp15指令内容搜索2440a手册

?

?????? IMPORT? Main??????????? ;The main entry of mon program

?????? IMPORT? RdNF2SDRAM?? ;Copy Image from Nand Flash to SDRAM

?

?

;AREA伪指令用于定义一个代码段或数据段,一个ARM源程序至少需要一个代码段,大的程序可以包含多个代码段及数据段

;格式:AREA sectionname {,attr} {,attr}...

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

?

;ENTRY伪指令用于指定程序的入口点

;一个程序(可以包含多个源文件)中至少要有一个ENTRY,可以有多个ENTRY,但一个源文件中最多只有一个ENTRY.

?????? ENTRY

??????

;EXPORT声明一个符号可以被其他文件引用,相当于声明了一个全局变量。GLOBAL与EXPORT相同????

;格式:EXPORT symbol{[WEAK]}?? [WEAK]声明其他的同名符优先于本符号被引用

;导出符号__ENTRY

?

?????? EXPORT __ENTRY

__ENTRY

ResetEntry

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

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

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

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

??????

;条件编译,在编译成机器码前就设定好? 大小端转换

;判断ENDIAN_CHANGE是否已定义,ASSERT 是断言伪指令,语法是:ASSERT +逻辑表达式 ,def 是逻辑伪操作符,格式为::DEF:label,作用是:判断label是否定义过

??????

?????? ASSERT :DEF:ENDIAN_CHANGE

?????? [ENDIAN_CHANGE???????????????????????????????????????????? ;definedin option.inc 默认是FALSE,所以此句不会加入代码中

????????????? ASSERT? :DEF:ENTRY_BUS_WIDTH??????????? ;断言指令,检测是否定义该变量,若未定义,报错

????????????? [ENTRY_BUS_WIDTH=32????????????????????? ;definedin option.inc

???????????????????? 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 ;本硬件用的是小端模式,这是第一个执行语句,直接跳转到复位指令处 0X00

?????? ]

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

?????? b???? HandlerSWI????????? ;handlerfor SWI interrupt?????????????????? 0X08

?????? b???? HandlerPabort ;handler for PAbort,指令预取中止??? 0X0C????????????

?????? b???? HandlerDabort?????? ;handler for DAbort,数据中止????????? 0X10

?????? b???? .?????????????????????????? ;reserved 保留未用 注意小圆点???????? 0X14

?????? b???? HandlerIRQ??? ;handlerfor IRQ interrupt????????????????????????? 0X18

?????? b???? HandlerFIQ??? ;handlerfor FIQ interrupt????????????????????????? 0X1C

;这7个中断,每个中断都有固定的中断入口地址,它们位于代码的最前端,不允许另作他用

;@0x20

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

?

;下面是改变大小端的程序,采用直接定义? <机器码>? 的方式,为什么这么做就得问三星了

;反正我们程序里这段代码也不会去执行,不用去管它

;每一个汇编指令,都对应着一个二进制机器码,这里没有使用指令,直接用了机器码,含义未知

ChangeBigEndian

;@0x24

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

;对存储器控制寄存器操作,指定内存模式为Big-endian

;因为刚开始CPU都是按照32位总线的指令格式运行的,如果采用其他的话,CPU别不了,必须转化

;但当系统初始化好以后,则CPU能自动识别

?

?????? ]

?????? [ENTRY_BUS_WIDTH=16

????????????? DCD0x0f10ee11

????????????? DCD0x0080e380

????????????? DCD0x0f10ee01

;因为采用Big-endian模式,采用16位总线时,物理地址的高位和数据的地位对应

;所以指令的机器码也相应的高低对调

?

?????? ]

?????? [ENTRY_BUS_WIDTH=8

????????????? DCD0x100f11ee

????????????? DCD0x800080e3

????????????? DCD0x100f01ee

?????? ]

?????? DCD0xffffffff? ;swinv 0xffffff is similarwith NOP and run well in both endian mode.

?????? DCD0xffffffff

?????? DCD0xffffffff

?????? DCD0xffffffff

?????? DCD0xffffffff

?????? bResetHandler???????????????????? ;设置成大端后,再次跳到复位指令处

??????

??????

?

;本文件底部定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字

;空间都有一个标号,以Handle***命名。

;这是宏实例?? 在这里Handler***就是通过HANDLER这个宏和Handle***建立联系的.

?

;详细分析:

;??? 这是宏示例,也就是宏的调用指令,当编译时编译器会把宏调用指令展开

;??? 这是向量中断

?

;展开方式(举例):

?

;HandlerFIQ?? HANDLERHandleFIQ

?

;展开后变成:

?

;HandlerFIQ??????????????????????? ??????? ;标号,由 " b?????? HandlerFIQ? "指令使用(见上,复位处)

;????? ?? sub??? sp,#4?? ??? ?????? ;留出一个空间,为了存放跳转地址给pc。见:strr0,#4] ,注意sp值并未改变

;?????

;????? ?? stmfd sp!,{r0}? ??? ;把r0中的内容入栈,保存起来

;?????

;????? ?? ldr????r0,=HandleFIQ? ;HandleFIQ标号,在本文件最下方定义

;?????

;????? ?? ldr????r0,[r0]?????????????? ;把HandleXXX所指向的内容(也就是中断程序的入口地址)放入r0

;?????

;????? ?? str????r0,#4]???? ? ;把入口地址放入刚才留出的一个空间里

;?????

;????? ? ldmfd??sp!,pc}???? ?????? ;出栈的方式恢复r0原值和为pc设定新值(也就完成了到ISR的转跳)。注:栈中r0内容在低地址

;?????

; 后边的语句展开方式,同上。编译后,代码都展开放置

?

HandlerFIQ??? HANDLERHandleFIQ

HandlerIRQ??? HANDLERHandleIRQ

HandlerUndef HANDLER HandleUndef

HandlerSWI?? HANDLERHandleSWI

HandlerDabort?????? HANDLER HandleDabort

HandlerPabort HANDLER HandlePabort

?

?

?

;非向量中断总入口(需要自己判断中断类型,而不是直接跳转到相应程序)

;产生中断后,需要中断服务程序自己来判断,到底是哪个中断请求,根据的就是INTOFFSET寄存器中的偏移,再计算中断服务地址

IsrIRQ

?????? sub? sp,#4??????;reserved for PC,预留返回指针的存储位置

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

?

?????? ldr?? r9,=INTOFFSET??? ;the interrupt request source offset

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

?????? ldr?? r8,=HandleEINT0???????? ;HandleEINT0 ,在本文件最下边定义的

?????? add? r8,r8,r9,lsl #2??????? ;r9中只是偏移单位的个数,需要*4变成具体字节偏移(相对于EINT0)

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

?????? str??? r8,#8]???????????????????? ;pc值放在了高位置

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

?

?

?????? LTORG

??????

;LTORG用于声明一个文字池,在使用LDR伪指令时,要在适当的地方加入LTORG声明文字池,这样就会把要加载的数据保存在

;文字池内,再用ARM的《加载指令》读出数据。(若没有使用LTORG声明文字池,则汇编器会在程序末尾自动声明)

;LTORG 伪指令常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器就不会错误地将文字池中的数据当做指令来执行

;注:在此,文字池内存储的是INTOFFSET宏所代表的值:0x4a000014? 。毕竟,当把指令编译成二进制代码时,arm指令(32位)

;不能既表示出指令内容,又表示出数据地址(32位)。估计在编译时,会被汇编成其他的加载指令,再编译成机器码

;LTORG 只要单独写出来就可以了,其他的交给编译器来做,而且它跟它下面的代码没有任何关系

?

?

;=======

; ENTRY

;=======????????????

ResetHandler???????????????

?????? ldr?? r0,=WTCON?????? ;watch dog disable?? 编译时就是 ldr r0,=53000000;伪指令有=号

?????? ldr?? r1,=0x0???????????????? ;这些宏定义都位于2440addr.inc中。???区分:变量定义&& 宏定义

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

?

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

?????? ldr?? r1,=0xffffffff? ;all interrupt disable?? 要理解子中断和中断之间的关系

?????? str??? r1,=INTSUBMSK

?????? ldr?? r1,=0x7fff???????????? ;allsub interrupt disable

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

?

?????? [{FALSE}

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

????????????? ;Led_Display

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

????????????? ldr?? r1,=0x155500

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

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

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

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

?????? ]

?

?????? ;Toreduce PLL lock time,adjust the LOCKTIME register.

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

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

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

?

?????? [PLL_ON_START?????????????? ;defined inoption.inc {TRUE},选择要不要设置频率值

????????????? ;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]

?

?????? ;programhas not been copied,so use these directly

????????????? [CLKDIV_VAL>1 ???????????? ; meansFclk:Hclk is not 1:1.

???????????????????? mrcp15,0

???????????????????? orrr0,#0xc0000000;R1_nF:OR:R1_iA

???????????????????? mcrp15,0

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

???????????????????? mrcp15,0

???????????????????? bicr0,#0xc0000000;R1_iA:OR:R1_nF

???????????????????? mcrp15,0

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

; 在配置UPLLCON和MPLLCON寄存器时,必须先配置UPLLCON,然后再配置MPLLCON,而且两者之间要有7 nop的间隔。(这是2440文档明确要求的)

????????????? ;ConfigureUPLL

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

????????????? ldr?? r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)????????????????????? ;Fin = 12.0MHz,UCLK =48MHz,对于usb来说必须是48MHz

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

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

????????????? nop

????????????? nop

????????????? nop

????????????? nop

????????????? nop

????????????? nop

????????????? ;ConfigureMPLL

????????????? ldr?? r0,=MPLLCON??????????????????? ;计算公式是固定的,可计算得到

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

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

?????? ]

?

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

?????? ldr?? r1,=GSTATUS2???????????? ;这个寄存器数值表示哪个信号引起的复位动作产生

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

?????? tst??? r0,#0x2

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

?????? bne? WAKEUP_SLEEP

?

?????? EXPORTStartPointAfterSleepWakeUp

StartPointAfterSleepWakeUp

?

?????? ;Setmemory control registers

????? ??????????????????? ;ldr? r0,=SMRDATA? ;(等效于下边的指令)

?????

????? adrl? r0,SMRDATA?????? ;be careful!中等范围的地址读取伪指令,用法类似于ldr(大范围地址读取)伪指令

?????? ldr?? r1,=BWSCON?????? ;BWSCONAddress

?????? add? r2,#52????? ;Endaddress of SMRDATA??? 共有13个寄存器地址(4字节)需要赋值,13*4=52字节

?

0

?????? ldr?? r3,[r0],#4??????????? ;这些都是后变址指令

?????? str??? r3,[r1],#4

?????? cmp r2,r0

?????? bne? %B0?????????????????????????????????? ;当<的时候,跳转到0标号处继续执行

?

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

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

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

; check if EIN0 button is pressed

?

???ldr?? r0,=GPFCON?? ;input,无上拉电阻

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

?????? tst??? r0,#0x1

?????? bne%F1?????????????? ;若不相等,则向下跳到1标号,跳过下边代码

??????

??????

?

; Clear SDRAM Start

?

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

?????? ldr?? r1,=0x55aa

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

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

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

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

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

?

?????? movr1,#0

?????? movr2,#0

?????? movr3,#0

?????? movr4,#0

?????? movr5,#0

?????? movr6,#0

?????? movr7,#0

?????? movr8,#0

??????

?????? ldr?? r9,=0x4000000?? ;64MB??????;这几条指令目的是:擦除sdram的所有数据

?????? ldr?? r0,=0x30000000

0????

?????? stmia?????? r0!,{r1-r8}

?????? subs r9,#32

?????? bne? %B0

?

;Clear SDRAM End

?

1

?

?????? ;Initializestacks

?????? bl??? InitStacks

?

;===========================================================

;OM0是flash选择开关,OM0接地时从nand 启动,悬空时(核心板上有上拉电阻)从nor启动

;OM1在核心板上,始终是接地.为0

;OM1:OM0取值:00 nandflash mode;01 16bit nor;10 32bit nor;11 test mode

;详见:s3c2440 用户手册 5.memory controller 一节

?

?????? ldr?? r0,=BWSCON

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

?????? ands r0,#6??????? ;OM[1:0]!= 0,NOR FLash boot do not read nand flash

?????? bne? copy_proc_beg?????????????

?????? adr?? r0,ResetEntry??????? ;OM[1:0] == 0,NAND FLash boot

?????? cmp r0,#0?????????????????????????? ;ifuse Multi-ice,

?????? bne? copy_proc_beg????????????? ;donot read nand flash for boot

?????? ;nop

??????

;ands指令,加s表示结果影响cpsr寄存器的值??????

??????

??????

;===========================================================

;把nand中的数据,拷贝到ram中

nand_boot_beg

?????? [{TRUE}

????????????? blRdNF2SDRAM??????????????????????

?????? ]

?

?????? ldr?? pc,=copy_proc_beg

?

;这里的一段代码时对内存数据的初始化,涉及代码段,数据段,bss段等

;因对这里的变量设置等有异议,暂时未全面分析,但是基本原理想通,就是一个比较地址,复制数据的过程

copy_proc_beg

?????? adr?? r0,ResetEntry

?????? ldr?? r2,BaSEOfROM

?????? cmp r0,r2

?????? ldreq?????? r0,TopOfROM

?????? beq? InitRam??

?????? ldrr3,TopOfROM

0????

?????? ldmia????? r0!,{r4-r7}

?????? stmia?????? r2!,{r4-r7}

?????? cmp r2,r3

?????? bcc? %B0

??????

?????? sub? r2,r2,r3

?????? sub? r0,r2?????????????????????

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

InitRam??

?????? ldr?? r2,BaSEOfBSS

?????? ldr?? r3,BaSEOfZero?????

0

?????? cmp r2,r3

?????? ldrcc?????? r1,#4

?????? strcc r1,[r2],#4

?????? bcc? %B0??????

?

?????? mov r0,?? #0

?????? ldr?? r3,?? EndOfBSS

1????

?????? cmp r2,?? r3

?????? strcc r0,#4

?????? bcc? %B1

??????

?????? ldr?? pc,=%F2????????????? ;gotocompiler address

2

??????

;????? [CLKDIV_VAL>1 ???????????? ; meansFclk:Hclk is not 1:1.

;????? bl??? MMU_SetAsyncBusMode

;????? |

;????? blMMU_SetFastBusMode???? ; default value.

;????? ]

??????

?

;===========================================================

? ??? ; Setup IRQ handler

; 把中断服务函数的总入口地址,赋给HandleIRQ地址(文件最低端定义)

?????? ldr?? r0,=HandleIRQ????? ;Thisroutine is needed

?????? ldr?? r1,=IsrIRQ???? ;ifthere is not 'subs pc,lr,#4' at 0x18,0x1c

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

?

?

?

??? [:LNOT:THUMBCODE

???????????? bl??? Main?????? ;Do not use main() because ......

???????????? b???? .

??? ]

?

??? [THUMBCODE??? ;for start-up code for Thumbmode

???????????? orr?? lr,pc,#1

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

???????????? CODE16

???????????? bl??? Main?????? ;Do not use main() because ......

???????????? b???? .

????????????? CODE32

??? ]

?

?

;function initializing stacks

InitStacks??; 初始化栈空间(各个模式下的),为c函数运行做准备

?????? ;Donot use DRAM,such as stmfd,ldmfd......

?????? ;SVCstackis initialized before

?????? ;Undertoolkit ver 2.5,'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'

?????? mrs? r0,cpsr

?????? bic?? r0,#MODEMASK

?????? orr?? r1,#UNDEFMODE|NOINT

?????? msr? cpsr_cxsf,r1?????????? ;UndefMode

?????? ldr?? sp,=UndefStack???????????? ; UndefStack=0x33FF_5C00

?

?????? orr?? r1,#ABORTMODE|NOINT

?????? msr? cpsr_cxsf,r1?????????? ;AbortMode

?????? ldr?? sp,=AbortStack???????????? ; AbortStack=0x33FF_6000

?

?????? orr?? r1,#IRQMODE|NOINT

?????? msr? cpsr_cxsf,r1?????????? ;IRQMode

?????? ldr?? sp,=IRQStack??????? ;IRQStack=0x33FF_7000

?

?????? orr?? r1,#FIQMODE|NOINT

?????? msr? cpsr_cxsf,r1?????????? ;FIQMode

?????? ldr?? sp,=FIQStack???????? ;FIQStack=0x33FF_8000

?

?????? bic?? r0,#MODEMASK|NOINT

?????? orr?? r1,#SVCMODE

?????? msr? cpsr_cxsf,r1?????????? ;SVCMode

?????? ldr?? sp,=SVCStack??????? ;SVCStack=0x33FF_5800

?

?????? ;USERmode has not be initialized.

?

?????? mov pc,lr

?????? ;TheLR register will not be valid if the current mode is not SVC mode.

??????

?

?????? LTORG

?

SMRDATA DATA??

;配置存储器的管理方式

; Memory configuration should be optimizedfor best performance

; The following parameter is not optimized.

; Memory access cycle parameter strategy

; 1) The memory settings is? safe parameters even at HCLK=75Mhz.

; 2) SDRAM refresh period is forHCLK<=75Mhz.

?

?????? 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<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))?? ;GCS4

?????? DCD((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))?? ;GCS5

?????? DCD((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))??? ;GCS6

?????? DCD((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))??? ;GCS7

?????? DCD((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Tsrc<<18)+(Tchr<<16)+REFCNT)

?

?????? DCD0x32????? ??? ;SCLK power saving mode,BANKSIZE 128M/128M

?

?????? DCD0x30????? ??? ;MRSR6 CL=3clk

?????? DCD0x30????? ??? ;MRSR7 CL=3clk

??????

;分配一个字的空间,并用后边的数值来初始化该空间?? ,这里命名有些混乱

BaSEOfROM?? DCD?????? |Image$$RO$$Base|

TopOfROM??? DCD?????? |Image$$RO$$Limit|

BaSEOfBSS???? DCD?????? |Image$$RW$$Base|

BaSEOfZero??? DCD?????? |Image$$ZI$$Base|

EndOfBSS???? DCD?????? |Image$$ZI$$Limit|

?

?????? ALIGN

??????

;Function for entering power down mode

; 1. SDRAM should be in self-refresh mode.

; 2. All interrupt should be maksked forSDRAM/DRAM self-refresh.

; 3. LCD controller should be disabled forSDRAM/DRAM self-refresh.

; 4. The I-cache may have to be turned on.

; 5. The location of the following code mayhave not to be changed.

?

;void EnterPWDN(int CLKCON);

EnterPWDN

?????? movr2,r0????????????? ;r2=rCLKCON

?????? tstr0,#0x8???????????? ;SLEEP mode?

?????? bneENTER_SLEEP

?

ENTER_STOP

?????? ldrr0,=REFRESH

?????? ldrr3,[r0]????????????? ;r3=rREFRESH

?????? movr1,r3

?????? orrr1,r1,#BIT_SELFREFRESH

?????? strr1,[r0]???????????? ;Enable SDRAMself-refresh

?

?????? movr1,#16?????????????????? ;wait untilself-refresh is issued. may not be needed.

0???? subsr1,#1

?????? bne%B0

?

?????? ldrr0,=CLKCON????????? ;enter STOP mode.

?????? strr2,[r0]

?

?????? movr1,#32

0???? subsr1,#1?? ;1) wait until the STOP mode isin effect.

?????? bne%B0??????? ;2) Or wait here until theCPU&Peripherals will be turned-off

???????????????????? ;?? Entering SLEEP mode,only the reset bywake-up is available.

?

?????? ldrr0,=REFRESH ;exit from SDRAM self refresh mode.

?????? strr3,[r0]

?

?????? MOV_PC_LR

?

ENTER_SLEEP

?????? ;NOTE.

?????? ;1)rGSTATUS3 should have the return address after wake-up from SLEEP mode.

?

?????? ldrr0,=REFRESH

?????? ldrr1,[r0]????????????? ;r1=rREFRESH

?????? orrr1,#16?????????????????? ;Wait untilself-refresh is issued,which may not be needed.

0???? subsr1,#1

?????? bne%B0

?

?????? ldr?? r1,=MISCCR

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

?????? orr?? r0,#(7<<17)? ;Set SCLK0=0,SCLK1=0,SCKE=0.

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

?

?????? ldrr0,=CLKCON????????? ; Enter sleep mode

?????? strr2,[r0]

?

?????? b.???????????????? ;CPU will die here.

?

?

WAKEUP_SLEEP

?????? ;ReleaseSCLKn after wake-up from the SLEEP mode.

?????? ldr?? r1,#(7<<17)? ;SCLK0:0->SCLK,SCLK1:0->SCLK,SCKE:0->=SCKE.

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

?

?????? ;Setmemory control registers

????? ldr?? r0,=SMRDATA????? ;be careful!

?????? ldr?? r1,#52????? ;Endaddress of SMRDATA

0

?????? ldr?? r3,#4

?????? str??? r3,r0

?????? bne? %B0

?

?????? movr1,#256

0???? subsr1,#1?? ;1) wait until the SelfRefreshis released.

?????? bne%B0

?

?????? ldrr1,=GSTATUS3 ????? ;GSTATUS3 has the startaddress just after SLEEP wake-up

?????? ldrr0,[r1]

?

?????? movpc,r0

??????

;=====================================================================

; Clock division test

; Assemble code,because VSYNC time is veryshort

;=====================================================================

?????? EXPORTCLKDIV124

?????? EXPORTCLKDIV144

??????

CLKDIV124

??????

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

?????? ldr???? r1,= 0x3???????? ;0x3 = 1:2:4

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

;????? waituntil clock is stable

?????? nop

?????? nop

?????? nop

?????? nop

?????? nop

?

?????? ldr???? r0,= REFRESH

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

?????? bic????????? r1,#0xff

?????? bic????????? r1,#(0x7<<8)

?????? orr????????? r1,#0x470 ; REFCNT135

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

?????? nop

?????? nop

?????? nop

?????? nop

?????? nop

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

?

CLKDIV144

?????? ldr???? r0,= 0x4???????? ;0x4 = 1:4:4

?????? str???? r1,#0x630 ; REFCNT675 - 1520

?????? str???? r1,lr

?

?

?????? ALIGN

?

?

?

;定义数据段

;^ 标志等价于MAP伪指令

;MAP用于定义一个结构化的内存表首地址,此时内存表的位置计数器值,也变成该首地址值,就相当于在这个地址处操作

;#于FIELD同义,用于定义一个结构化的内存表的数据域,后边数字表示该数据占用的字节数

;Handle*** 在此就是一个标号,为了标示数据量

;用法:把对应的终端处理函数的首地址,放到这里的对应的预留空间处,当发生中断时,就能根据宏函数,直接跳转

?

?

?

?????? AREARamData,DATA,READWRITE

?

?????? ^?? _ISR_STARTADDRESS????????????? ; _ISR_STARTADDRESS=0x33FF_FF00

HandleReset ? #?? 4

HandleUndef #?? 4

HandleSWI??????????? #?? 4

HandlePabort??? #?? 4

HandleDabort??? #?? 4

HandleReserved? #?? 4

HandleIRQ??????????? #?? 4

HandleFIQ??????????? #?? 4

?

;Do not use the label 'IntVectorTable',

;The value of IntVectorTable is differentwith the address you think it may be.

;IntVectorTable

;@0x33FF_FF20

HandleEINT0??????? #?? 4

HandleEINT1??????? #?? 4

HandleEINT2??????? #?? 4

HandleEINT3??????? #?? 4

HandleEINT4_7???? #?? 4

HandleEINT8_23?? #?? 4

HandleCAM????????? #?? 4??????????? ;Added for 2440.

HandleBATFLT????? #?? 4

HandleTICK????????? #?? 4

HandleWDT????????? #?? 4

HandleTIMER0 ??? #?? 4

HandleTIMER1 ??? #?? 4

HandleTIMER2 ??? #?? 4

HandleTIMER3 ??? #?? 4

HandleTIMER4 ??? #?? 4

HandleUART2???? #?? 4

;@0x33FF_FF60

HandleLCD ????????? #?? 4

HandleDMA0??????? #?? 4

HandleDMA1??????? #?? 4

HandleDMA2??????? #?? 4

HandleDMA3??????? #?? 4

HandleMMC????????? #?? 4

HandleSPI0?????????? #?? 4

HandleUART1????????????? #?? 4

HandleNFCON???????????? #?? 4??????????? ;Added for 2440.

HandleUSBD???????? #?? 4

HandleUSBH???????? #?? 4

HandleIIC???????????? #?? 4

HandleUART0 ????? #?? 4

HandleSPI1 ???????? #?? 4

HandleRTC ????????? #?? 4

HandleADC ???????? #?? 4

;@0x33FF_FFA0

?????? END

?

?

?

若有不妥之处,敬请告知!QQ:570886026

?????????????????????????????????????????????????????????????????????????????????????????? 独舞

(编辑:李大同)

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

    推荐文章
      热点阅读