arm启动文件2440init.s分析
?最近整理电脑,找到了一些当初学习嵌入式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 ?????????????????????????????????????????????????????????????????????????????????????????? 独舞 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |