ARM启动代码详解_第1页
ARM启动代码详解_第2页
ARM启动代码详解_第3页
ARM启动代码详解_第4页
ARM启动代码详解_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

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

文档简介

1、 PART1 系统初始化流程如下:禁止看门狗-在中断控制器中屏蔽所有中断-系统时钟设置-初始化端口-DMA设置-cashe和总线设置-存储器设置,初始化SDRAM-初始化堆栈-设置IRQ和FIQ的入口-地址重映射。必须由汇编来完成的任务有:异常中断向量表的设置、IRQ向量表(向量模式或ISR初始化(非向量模式、二级ISR地址表的定义、Flash和SDRAM的设置(否则系统无法加载代码、堆栈设置和模式切换、拷贝RW和ZI代码、设置系统时钟等。对于非向量模式,不使用IRQ中断向量表,但二级ISR地址表的设置是相同的。 PART2 理解启动代码(ADS 所谓启动代码,就是处理器在启动的时候执行的一段

2、代码,主要任务是初始化处理器模式,设置堆栈,初始化变量等等.由于以上的操作均与处理器体系结构和系统配置密切相关,所以一般由汇编来编写. 具体到S64,启动代码分成两部分,一是与ARM7TDMI内核相关的部分,包括处理器各异常向量的配置,各处理器模式的堆栈设置,如有必要,复制向量到RAM,以便remap之后处理器正确处理异常,初始化数据(包括RW与ZI,最后跳转到Main.二是与处理器外部设备相关的部 分,这和厂商的联系比较大.虽然都采用了ARM7TDMI的内核,但是不同的厂家整合了不同的片上外设,需要不同的初始化,其中比较重要的是初始化WDT,初始化各子系统时钟,有必要的话,进行remap.这

3、一部分与一般控制器的初始化类似,因此,本文不作重点描述. 在进行分析之前,请确认如下相关概念: S64片上FLASH起始于0 x100000,共64kB,片上RAM起始于0 x200000,共16kB. S64复位之后,程序会从0开始执行,此时FLASH被映射到0地址,因此,S64可以取得指令并执行.显然,此时还是驻留在0 x100000地址.如果使用remap命令,将会把RAM映射到0地址,同样的这时0地址的内容也只是RAM的镜像. S64的FLASH可以保证在最差情况时以30MHz进行单周期访问,而RAM可以保证在最大速度时的单周期访问. OK,以下开始分析启动代码. 一,处理器异常 S6

4、4将异常向量至于0地址开始的几个直接,这些是必需要处理的.由于复位向量位于0,也需要一条跳转指令.具体代码如下: RESET B SYSINIT ; Reset B UDFHANDLER ; UNDEFINED B SWIHANDLER ; SWI B PABTHANDLER ; PREFETCH ABORT B DABTHANDLER ; DATA ABORT B . ; RESERVED B VECTORED_IRQ_HANDLER B . ; ADD FIQ CODE HERE UDFHANDLER B . SWIHANDLER B . PABTHANDLER B . DABTHANDL

5、ER B . 请注意,B指令经汇编后会替换为当前PC值加上一个修正值(+/-,所以这条指令是代码位置无关的,也就是不管这条指令是在0地址还是在0 x100000执行,都能跳转到指定的位置,而LDR PC,=?将向PC直接装载一个标号的值,请注意,标号在编译过后将被替换为一个与RO 相对应的值,也就是说,这样的指令无论在哪里执行,都只会跳转到一个指定的位置.下面举一个具体的例子来说明两者的区别: 假定有如下程序: RESET B INIT 或者LDR PC,=INIT INIT 其中RESET为起始时的代码,也就是这条代码的偏移为0,设INIT的偏移量为offset.如果将这段程序按照RO=0

6、x1000000编译, 那么B INIT可理解为ADD PC, PC, #offset,而LDR PC,=INIT可被理解为MOV PC,#(RO+offset .显然当系统复位时,程序从0开始运行,而0地址有FLASH的副本,执行B INIT将把PC指向位于0地址处的镜像代码位置,也即INIT;如果执行LDR PC,=INIT将会将PC 直接指向位于FLASH中的原始代码.因此以上两者都能正确运行.下面将RO设置为0 x200000,编译后生成代码,还是得烧写到FLASH中,也就是还是0 x100000,系统复位后从0地址执行,还是FLASH的副本,此时执行B INIT,将跳到副本中的INI

7、T位置执行,此处有对应的代码;但是如果执行LDR PC,=INIT,将向PC加载0 x200000+offset,这将使得PC跳到RAM中,而此时由于代码没有复制,RAM中的指定位置并没有代码,程序无法运行. 二,处理器模式 ARM的处理器可工作于多种模式,不同模式有不同的堆栈,以下设置各模式及其堆栈. 预定义一些参数: MODUSR EQU 0 x10 MODSYS EQU 0 x1F MODSVC EQU 0 x13 MODABT EQU 0 x17 MODUDF EQU 0 x1B MODIRQ EQU 0 x12 MODFIQ EQU 0 x11 IRQBIT EQU 0 x80 FI

8、QBIT EQU 0 x40 RAMEND EQU 0 x00204000 ; S64 : 16KB RAM VECTSIZE EQU 0 x100 ; UsrStkSz EQU 8 ; size of USR stack SysStkSz EQU 128 ; size of SYS stack SvcStkSz EQU 8 ; size of SVC stack UdfStkSz EQU 8 ; size of UDF stack AbtStkSz EQU 8 ; size of ABT stack IrqStkSz EQU 128 ; size of IRQ stack FiqStkSz

9、EQU 16 ; size of FIQ stack 修改这些值即可修改相应模式堆栈的尺寸. 以下为各模式代码: SYSINIT ; MRS R0,CPSR BIC R0,R0,#0 x1F MOV R2,#RAMEND ORR R1,R0,#(MODSVC :OR: IRQBIT :OR: FIQBIT MSR cpsr_cxsf,R1 ; ENTER SVC MODE MOV sp,R2 SUB R2,R2,#SvcStkSz ORR R1,R0,#(MODFIQ :OR: IRQBIT :OR: FIQBIT MSR CPSR_cxsf,R1 ; ENTER FIQ MODE MOV s

10、p,R2 SUB R2,R2,#FiqStkSz ORR R1,R0,#(MODIRQ :OR: IRQBIT :OR: FIQBIT MSR CPSR_cxsf,R1 ; ENTER IRQ MODE MOV sp,R2 SUB R2,R2,#IrqStkSz ORR R1,R0,#(MODUDF :OR: IRQBIT :OR: FIQBIT MSR CPSR_cxsf,R1 ; ENTER UDF MODE MOV sp,R2 SUB R2,R2,#UdfStkSz ORR R1,R0,#(MODABT :OR: IRQBIT :OR: FIQBIT MSR CPSR_cxsf,R1 ;

11、 ENTER ABT MODE MOV sp,R2 SUB R2,R2,#AbtStkSz ;ORR R1,R0,#(MODUSR :OR: IRQBIT :OR: FIQBIT ;MSR CPSR_cxsf,R1 ; ENTER USR MODE ;MOV sp,R2 ;SUB R2,R2,#UsrStkSz ORR R1,R0,#(MODSYS :OR: IRQBIT :OR: FIQBIT MSR CPSR_cxsf,R1 ; ENTER SYS MODE MOV sp,R2 ; 三,初始化变量 编译完成之后,连接器会生成三个基本的段,分别是RO,RW,ZI,并会在image中顺序摆放.

12、显然,RW,ZI在运行开始时并不位于指定的 RW位置,因此必须初始化 LDR R0,=|Image$RO$Limit| LDR R1,=|Image$RW$Base| LDR R2,=|Image$ZI$Base| 1 CMP R1,R2 LDRLO R3,R0,#4 STRLO R3,R1,#4 BLO MOV R3,#0 LDR R1,=|Image$ZI$Limit| 2 CMP R2,R1 STRLO R3,R2,#4 BLO 2 四,复制异常向量 由于代码于RAM运行时,有明显的速度优势,而且变量可以动态配置,因此可以通过remap将RAM映射到0,使得出现异常时ARM从RAM中取得

13、向量. IMPORT |Image$RO$Base| IMPORT |Image$RO$Limit| IMPORT |Image$RW$Base| IMPORT |Image$RW$Limit| IMPORT |Image$ZI$Base| IMPORT |Image$ZI$Limit| COPY_VECT_TO_RAM LDR R0,=|Image$RO$Base| LDR R1,=SYSINIT LDR R2,=0 x200000 ; RAM START CMP R0,R1 LDRLO R3,R0,#4 STRLO R3,R2,#4 BLO 这段程序将SYSINIT之前的代码,也就是异常处

14、理函数,全部复制到RAM中, 这就意味着不能将RW设置为0 x200000,这样会使得向量被冲掉. 四,在RAM中运行 如果有必要,且代码足够小,可以将代码置于RAM中运行,由于RAM中本身没有代码,就需要将代码复制到RAM中: COPY_BEGIN LDR R0,=0 x200000 LDR R1,=RESET ; =|Image$RO$Base| CMP R1,R0 ; BLO COPY_END ; ADR R0,RESET ADR R2,COPY_END SUB R0,R2,R0 ADD R1,R1,R0 LDR R3,=|Image$RO$Limit| 3 CMP R1,R3 LDRL

15、O R4,R2,#4 STRLO R4,R1,#4 BLO 3 LDR PC,=COPY_END COPY_END 程序首先取得RESET的连接地址,判断程序是否时是在RAM中运行,方法是与RAM起始地址比较,如果小于,那么就跳过代码复制. 在复制代码的时候需要注意,在这段程序结束之前的代码没有必要复制,因为这些代码都已经执行过了,所以,先取得COPY_END,作为复制起始地址,然后计算其相对RESET的偏移,然后以RO的值加上这个偏移,就是复制目的地的起始地址,然后开始复制. 五,开始主程序 以上步骤完成,就可以跳转到main运行 IMPORT Main LDR PC,=Main B . 六

16、,器件初始化 主程序首先要进行器件的初始化,对S64而言,应该先初始化WDT,因为默认情况下,WDT是打开的,然后是各设备的时钟分配,最后应该remap. 以上是必要的启动步骤,实际应用中可以根据具体情况添加一些代码. PART3 ARM启动程序分析 字体: 小中大 | 打印发布: 2007-7-17 11:05 作者: 网络转载来源: 网络查看: 4次 ARM启动程序分析 TIMER1用来触发和IRQ中断代码在FLASH中运行 这个例子有一下几个文件: 1. 中断向量表(ivt.s 2. 汇编启动代码 (init.s 3. C主函数文件 中断向量表 ;代码必须链接在地址0X0。这里提供了AR

17、M内核的中断向量 ; ; 汇编指令 ; AREA IVT, CODE ; 新代码段 CODE32 ; ARM指令 IMPORT start ; 在这段中没有定义 Entry ; 定义程序进入点 ; LDR PC, =start LDR PC, Undefined_Addr LDR PC,_Addr LDR PC, Prefetch_Addr LDR PC, Abort_Addr ; 在地址0 x14用户应该插入一个标记(校验和. ; 此标记让引导程序决定是否在Flash中有有效的用户代码,目前大多数FLASH编程工具(debuggers and ISP utility ; 有这个内置的功能,因

18、此用户不用考虑这个问题.假如开发工具没有提供这种功能,那么这个值必须自己计算,并把计算得到的值写到地址0 x14. 计算校验和的细节可以参考LPC2104/5/6用户指南的FLASH编程章节. DCD .?. LDR PC, PC, #0 xFF0 LDR PC, FIQ_Addr Undefined_Addr DCD Undefined_HandlerPrefetch_Addr DCD Prefetch_Handler Abort_Addr DCD Abort_Handler FIQ_Addr DCD FIQ_Handler ; ; 异常处理 ; Undefined_Handler B Un

19、defined_HandlerB_Handler Prefetch_Handler B Prefetch_Handler Abort_Handler B Abort_Handler FIQ_Handler B FIQ_Handler END 系统复位后,第一条要执行的指令是: LDR PC,=start 这条指令将跳转到汇编的起始代码(startup,他将中断使能,为IRQ 和管理模式设置堆栈 ;比较重要的中断向量是IRQ中断. LDR PC, PC, #0 xFF0 ;这条指令将从中断向量控制控制器(VIC中的地址寄存器 (0 xFFFF F030 导入PC,并执行. ;所有剩余的向量都有中

20、断句柄 . 启动程序汇编代码 ; ; 汇编语言 ; AREA asm_code, CODE ; 新代码段 CODE32 ; ARM指令 IMPORT _main ; main在这个程序段中没有定义 EXPORT start ; 全局变量 ; 参考ivt.s文件 ; start ; 中断使能 MSR cpsr_c,#0 x13 ; 在管理模式时设定堆栈指针SP LDR SP,=0 x4?. ; 设置IRQ模式.设置SP_irq,然后返回管理模式 MRS R0, CPSR BIC R1, R0,#0 x1F ORR R1, R1,#0 x12 MSR cpsr_c, R1 ;进入中断模式 LDR

21、SP, =0 x4?. MSR cpsr_c, R0 ;返回管理模式 ; 跳转到c程序 LDR lr, =_main MOV pc, lr END 这段代码在与ivt.s链接. 假如设置堆栈指针失败将导致数据中止异常,因此堆栈的初始化应该在跳转到c main(函数之前。 C 代码 Timer1 的寄存器这么配置,当匹配的时候将中断内核,并且复位。Timer1运行在 60 MHz. 这段代码在一个评估板上运行,其外部始终使用10 MHz晶体,并且内部PLL 设定好。时钟操作的具体细节请参考LPC2106/5/4 中的相关章节。中断服务程序为空,用户可以根据需 要添加。在IRQHandler( 函

22、数中可以点亮一些LEDs 或触发一些引脚. _irq 关键字编译器用来定义 IRQHandler (函数作为IRQ 中断服务程序。 C main函数在init.s 文件后执行。 LDR lr, =_main MOV pc, lr C代码如下: /* 函数定义 */ _irq void IRQHandler(void; void feed(void; void Initialize(void; /* 头文件 */ #include“LPC210 x.h” /* MAIN */ int main( /* 系统初始化 */ Initialize(; /* 启动时钟 */ T1_TCR=0 x1; while(1 /* 初始化 */ void Initialize( /* * 初始化 PLL 10MHz6=60MHz */ /* 设置乘除数值*/ PLLCFG=0 x25; feed(; /* 使能 PLL */ PLLCON=0 x1; feed(; /* 等待PLL锁定设定的频率 */ while(!(PLLSTAT feed(; /* * 使能存储器加速模块MAM,设定访问FLASH的时钟*/ MAMCR=0 x2; MAMTIM=0 x4; /* * 设定外围模块工作时钟(pclk与系

温馨提示

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

评论

0/150

提交评论