S3C2440启动代码经验总结_第1页
S3C2440启动代码经验总结_第2页
S3C2440启动代码经验总结_第3页
S3C2440启动代码经验总结_第4页
S3C2440启动代码经验总结_第5页
已阅读5页,还剩6页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1、引言2、汇编基础2.1、伪操作GET 伪操作类似于C 语言里面的include,是将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。IMPORT伪操作相当于C 语言中的extern 声明,它告诉编译器当前的符号不再本源文件中定义,而是在其他源文件中定义,在本源文件中可能引用该符号。AERA 伪操作用于定义一个代码或者数据段。ASSERT在汇编编译器对汇编程序的扫描中,如果ASSERT 中条件不成立,ASSERT 伪操作将报告错误信息。2.2、汇编指令LDR伪指令将一个32 位的常数或者一个地址值读取到寄存器中。 BL跳转指令,L 决定是否保存返回地址。MRS用于将状

2、态寄存器的内容传送到通用寄存器中。MSR用于将通用寄存器的内容或一个立即数传送到状态寄存器中。 LDM和STM分别为批量Load/Store内存访问指令。FD为满递减数据栈。3、启动代码功能模块分解启动代码主要是在主程序运行之前初始化系统硬件及软件的运行环境,它的主要功能包括以下的几个方面:* 建立中断向量表* 初始化系统堆栈* 应用程序执行环境初始化* 跳转至主函数3.1、系统堆栈初始化ARM有7种模式:* 用户模式* 快速中断模式* 中断模式* 管理模式* 中止模式* 未定义模式* 系统模式系统堆栈的初始化主要是给各个处理器模式分配堆栈空间。堆栈是为中断或程序跳转服务的,当发生中断或程序跳

3、转时,需要将当前处理器的状态及一些参数保持在堆栈中,当中断处理完毕以后或程序执行完后返回时,再将堆栈保存的现场数据进行恢复,以保证原来的程序正确运行。USERMODE EQU 0x10 ;用户模式FIQMODE EQU 0x11 ;快速中断模式IRQMODE EQU 0x12 ;中断模式SVCMODE EQU 0x13 ;监管模式ABORTMODE EQU 0x17 ;异常中断模式UNDEFMODE EQU 0x1b ;未定义模式MODEMASK EQU 0x1f ;模式掩码NOINT EQU 0xc0 ;取消中断;设置工作模式的堆栈的起始地址;在option.inc 中定义了_STACK_B

4、ASEADDRESS EQU 0x33ff8000UserStack EQU (_STACK_BASEADDRESS-0x3800 ;堆栈空间0x33ff4800 SVCStack EQU (_STACK_BASEADDRESS-0x2800 ;堆栈空间0x33ff5800 UndefStack EQU (_STACK_BASEADDRESS-0x2400 ;堆栈空间0x33ff5c00AbortStack EQU (_STACK_BASEADDRESS-0x2000 ;堆栈空间0x33ff6000IRQStack EQU (_STACK_BASEADDRESS-0x1000 ;堆栈空间0x3

5、3ff7000 FIQStack EQU (_STACK_BASEADDRESS-0x0 ;堆栈空间0x33ff8000 堆栈初始化的顺序决定系统最后运行在哪种处理器模式,最后初始化哪种模式的堆栈,系统就运行在哪种模式。InitStacksmrs r0,cpsrbit r0,r0,#MODEMASK先通过mrs 指令将状态寄存器值读取到r0,然后将r0 对应的处理器模式为修改成未定义指令中止模式,再写回状态寄存器使处理器真正切换到未定义指令中止模式,这就是“读出-修改-写回”的方式来修改状态寄存器的内容。最后将该模式的堆栈指针sp 指向UndefStack 定义的地址,其他的模式操作方式也是一

6、样的。orr r1,r0,#UNDEFMODE|NOINTmsr cpsr_cxsf,r1 ;UndefModeldr sp, = UndefStack ;UndefStack=0x33FF_5C00orr r1,r0,#ABORTMODE|NOINTmsr cpsr_cxsf,r1 ;AbortModeldr sp,=AbortStack ;AbortStack=0x33FF_60003.2、建立中断向量表中断向量表一般位于启动代码的开始部分,它是用户程序与启动代码之间以及启动代码的各部分之间联系的纽带。它由一个一个的跳转函数组成,它就象一个普通的散转函数,只不过散转的过程中有硬件机制参与,

7、当系统发生异常时,ARM 处理器会通过硬件机制强制将PC 指针指向中断向量表中对应的异常跳转函数存储的地址,然后程序会跳转到相应的中断服务程序去执行。b ResetHandler ;复位异常,开发板上电或复位时进入0x00b HandlerUndef ;未定义异常,遇到无法识别的指令时0x04b HandlerSWI ;软中断异常0x08b HandlerPabort ;指令预取错误时进入0x0cb HandlerDabort ;数据访问不能完成时进入0x10b . ;保留 0x14b HandlerIRQ ;发生IRQ 中断时进入0x18b HandlerFIQ ;发生FIQ 中断时进入0x

8、1c这些是从0x0 地址开始的连续32 字节的各个中断入口,每个中断占用4 字节的存储空间,这些中断入口地址是固定的,类似于51 单片机的入口。建立异常向量表需要开辟一块大小为8*4 字节的空间,每个异常占据4 个字节的空间,这4 个字节的空间包含的是一个跳转指令,通过这条指令使PC 指向相应的异常处理函数的入口,具体的处理函数是在别处实现的。下面这个宏是用于第一次查表过程的实现中断向量的重定向,比如当产生FIQ 的时候,PC 先指向FIQ 的中断入口地址0x1c(强制),b HandlerFIQ 执行跳转指令到HandlerFIQ 标号处, 展开宏命令, 将$HandlerLabel HAN

9、DLER $HandleLabel 替换成HandlerFIQ HANDLER HandleFIQ。MACRO$HandlerLabel HANDLER $HandleLabel$HandlerLabelsub sp,sp,#4;减少sp(用于存放转跳地址实质上是在计算返回地址 stmfd sp!,r0 ;SP 先递减,再将r0 压栈ldr r0,=$HandleLabel;将HandleXXX 的标号地址传给r0ldr r0,r0 ;把HandleXXX 所指向的内容(也就是中断程序的入口放入r0 str r0,sp,#4 ;把中断服务程序(ISR压入栈.ldmfd sp!,r0,pc;用出

10、栈的方式恢复r0 的原值和为pc 设定新值(完成了到ISR 的转跳MEND3.3、程序的入口地址初始化程序中必须指明入口地址,因为处理器复位(仿真时,装载image)后PC 要找到入口开始执行代码,当各种异常或是中断产生的时候也要找到各个异常的入口开始执行代码。从这里开始就是真正的代码入口了!AREA Init,CODE,READONLY ;这表明下面的是一个名为Init 的代码段 ENTRY ;定义程序的入口(调试用ENTRY 只是定义一个普通的入口点,且在程序中可以多处定义,如果要使用它作为整个映像文件的唯一入口点,还需要设置链接器中的相关选项。ASSERT :DEF:ENDIAN_CHA

11、NGE ENDIAN_CHANGE ;如果已经定义了ENDIAN_CHANGE,则判断FALSEASSERT :DEF:ENTRY_BUS_WIDTH ;判断ENTRY_BUS_WIDTH 是否已定义 ENTRY_BUS_WIDTH=32 ;若已经定义了ENTRY_BUS_WIDTH,则判断是否为32b ChangeBigEndian ;DCD 0xea000007 ENTRY_BUS_WIDTH=16andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00;也是b ChangeBigEndian 指令,;只是由于总线不一样而取机器码的顺序不一样 ENTRY_BUS_WI

12、DTH=8streq r0,r0,-r10,ror #1 ;DCD 0x070000ea,跟上面一条类似 | ;如果没有定义总线宽度,则跳转到复位中断b ResetHandlerASSERT 是断言伪指令,语法是:ASSERT +逻辑表达式 ,def 是逻辑伪操作符,格式为: :DEF:label,作用是:判断label 是否定义过。这段程序开始使用了ASSERT 伪操作判断ENDIAN_CHANGE 是否被定义,如果没有被定义,ASSERT 伪操作将报告错误类型,并终止汇编。上面的四句指令能且只能执行一句,并且前三句若执行跳转后处理程序的最后一句也是b ResetHandler。“ ” 相当

13、于 if ,“ | ”相当于else,“ ” 相当于endif。这里还要对大小端做一下解释,因为ARM 的一个寄存器占用4 个字节,所以必须要设定数据存放的顺序,平常的写10 进制的习惯是高位放高字节,地位放低字节;这也是小端的存放方式。大端的方式是高字节放在低位,低字节放在高位。举例来看:若将0xffffff 赋值给0x4c000000。Address 0 1 2 3 4 5 6 7 8 9 a b c d e f0x4c000000 FF FF FF 00 -这是小端表示0x4c000000 00 FF FF FF -这是大端表示3.4、看门狗及中断的禁止上电和复位后,程序开始从位于0x0

14、 执行b ResetHandler 程序跳转到这里执行,将看门狗,中断之类的程序关掉,省得他们来打扰初始化程序的进行。ResetHandlerldr r0,=WTCON ;禁止看门狗ldr r1,=0x0str r1,r0WTCON 为看门狗控制寄存器,此处将其写入0x0,就是禁止它的所有功能,包括定时器定时,溢出中断及溢出复位。ldr r0,=INTMSKldr r1,=0xffffffff ;all interrupt disablestr r1,r0ldr r0,=INTSUBMSKldr r1,=0x7fff ;all sub interrupt disablestr r1,r0INT

15、MSK 为中断屏蔽寄存器,写入0xffffffff,就是禁止所有的中断产生,因为中断向量表还未初始化,如果此时产生中断会使程序进入未知的状态而跑飞。因为外设的中断太多,INTMSK 不够用,还需要INTSUBMSK 来将剩余的中断源也禁止掉。3.5、系统时钟初始化ldr r0,=LOCKTIME ;设置pll 锁定时间ldr r1,=0xffffffff ;将0xffffffff 赋值给r1str r1,r0 ;将r1 寄存器的值保存到r0 指向的内存中LOCKTIME 为PLL 锁定时间计数寄存器,重新设定分频值时,PLL 进入锁定,输出稳定频率的时钟需要一定的时间。这里设置成默认的值,以满

16、足锁定的要求。 PLL_ON_STARTldr r0,=CLKDIVN ;用于设定FCLK,HCLK,PCLK 的比例ldr r1,=CLKDIV_VAL ;CLKDIV_VAL 是在option.inc 里定义的,默认为7str r1,r0 ;设置分频数ldr r0,=UPLLCON ;设置UPLL 的输出频率ldr r1,=(U_MDIV<<12+(U_PDIV<<4+U_SDIV ;USB PLL CONFIG str r1,r0nop ;在UPP 设定之后,必须等待7 个时钟的延迟,设定才会有效 nopnopnopnopnopnopldr r0,=MPLLCON

17、 ;设置主时钟锁相环寄存器ldr r1,=(M_MDIV<<12+(M_PDIV<<4+M_SDIV ;设置MPLL 的分频系数str r1,r03.6、初始化内存控制器初始化内存控制器其实就是对S3C2440 的memory bank 进行设置,使其扩展的存储器或外部设备能够被处理器通过内存控制器正确读写。由于S3C2440 的最终应用程序是在SDRAM(bank6)中运行,并与C 语言变量等的用户数据,各种模式的堆栈,中断向量表,都被定位在SDRAM 的空间,所以它必须在涉及这些处理之前完成初始化工作。SMRDATA DATADCD(0+(B1_BWSCON<<4+(B2_BWSCON<<8+(B3_BWSCON<<12+(B4_BWSCON<<16+(B5_BWSCON<<20+(B6_BWSCON<<24+(B7_BWSCON<<28 这段程序的开始使用DATA 伪操作指明SMRDATA 标号处作为一段数据,而非代码。接下来就用DCD 分配一个字的内存单元,一共13 个字数据。adrl r0, SMRDATAldr r1,=BWSCON ;BWSCON Address, 在2440addr.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论