ARM启动代码研究
ARM启动代码

arm启动代码详细分析所谓启动代码,就是处理器在启动的时候执行的一段代码,主要任务是初始化处理器模式,设置堆栈,初始化变量等等.由于以上的操作均与处理器体系结构和系统配置密切相关,所以一般由汇编来编写.具体到S64,启动代码分成两部分,一是与ARM7TDMI内核相关的部分,包括处理器各异常向量的配置,各处理器模式的堆栈设置,如有必要,复制向量到RAM,以便remap之后处理器正确处理异常,初始化数据(包括RW与ZI),最后跳转到Main.二是与处理器外部设备相关的部分,这和厂商的联系比较大.虽然都采用了ARM7TDMI的内核,但是不同的厂家整合了不同的片上外设,需要不同的初始化,其中比较重要的是初始化WDT,初始化各子系统时钟,有必要的话,进行remap.这一部分与一般控制器的初始化类似,因此,本文不作重点描述.在进行分析之前,请确认如下相关概念:S64片上FLASH起始于0x100000,共64kB,片上RAM起始于0x200000,共16kB.S64复位之后,程序会从0开始执行,此时FLASH被映射到0地址,因此,S64可以取得指令并执行.显然,此时还是驻留在0x100000地址.如果使用remap命令,将会把RAM映射到0地址,同样的这时0地址的内容也只是RAM的镜像.S64的FLASH可以保证在最差情况时以30MHz进行单周期访问,而RAM可以保证在最大速度时的单周期访问.OK,以下开始分析启动代码.一,处理器异常S64将异常向量至于0地址开始的几个直接,这些是必需要处理的.由于复位向量位于0,也需要一条跳转指令.具体代码如下:RESETB SYSINIT ; ResetB UDFHANDLER ; UNDEFINEDB SWIHANDLER ; SWIB PABTHANDLER ; PREFETCH ABORTB DABTHANDLER ; DATA ABORTB . ; RESERVEDB VECTORED_IRQ_HANDLERB . ; ADD FIQ CODE HEREUDFHANDLERB .SWIHANDLERB .PABTHANDLERB .DABTHANDLERB .请注意,B指令经汇编后会替换为当前PC值加上一个修正值(+/-),所以这条指令是代码位置无关的,也就是不管这条指令是在0地址还是在0x100000执行,都能跳转到指定的位置,而LDR PC,=???将向PC直接装载一个标号的值,请注意,标号在编译过后将被替换为一个与RO相对应的值,也就是说,这样的指令无论在哪里执行,都只会跳转到一个指定的位置.下面举一个具体的例子来说明两者的区别:假定有如下程序:RESETB INIT 或者LDR PC,=INIT…INIT…其中RESET为起始时的代码,也就是这条代码的偏移为0,设INIT的偏移量为offset.如果将这段程序按照RO=0x1000000编译, 那么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设置为0x200000,编译后生成代码,还是得烧写到FLASH 中,也就是还是0x100000,系统复位后从0地址执行,还是FLASH的副本,此时执行B INIT,将跳到副本中的INIT位置执行,此处有对应的代码;但是如果执行LDR PC,=INIT,将向PC 加载0x200000+offset,这将使得PC跳到RAM中,而此时由于代码没有复制,RAM中的指定位置并没有代码,程序无法运行.二,处理器模式ARM的处理器可工作于多种模式,不同模式有不同的堆栈,以下设置各模式及其堆栈.预定义一些参数:MODUSR EQU 0x10MODSYS EQU 0x1FMODSVC EQU 0x13MODABT EQU 0x17MODUDF EQU 0x1BMODIRQ EQU 0x12MODFIQ EQU 0x11IRQBIT EQU 0x80FIQBIT EQU 0x40RAMEND EQU 0x00204000 ; S64 : 16KB RAMVECTSIZE EQU 0x100 ;UsrStkSz EQU 8 ; size of USR stackSysStkSz EQU 128 ; size of SYS stackSvcStkSz EQU 8 ; size of SVC stackUdfStkSz EQU 8 ; size of UDF stackAbtStkSz EQU 8 ; size of ABT stackIrqStkSz EQU 128 ; size of IRQ stackFiqStkSz EQU 16 ; size of FIQ stack修改这些值即可修改相应模式堆栈的尺寸.以下为各模式代码:SYSINIT;MRS R0,CPSRBIC R0,R0,#0x1FMOV R2,#RAMENDORR R1,R0,#(MODSVC :OR: IRQBIT :OR: FIQBIT) MSR cpsr_cxsf,R1 ; ENTER SVC MODEMOV sp,R2SUB R2,R2,#SvcStkSzORR R1,R0,#(MODFIQ :OR: IRQBIT :OR: FIQBIT)MSR CPSR_cxsf,R1 ; ENTER FIQ MODEMOV sp,R2SUB R2,R2,#FiqStkSzORR R1,R0,#(MODIRQ :OR: IRQBIT :OR: FIQBIT)MSR CPSR_cxsf,R1 ; ENTER IRQ MODEMOV sp,R2SUB R2,R2,#IrqStkSzORR R1,R0,#(MODUDF :OR: IRQBIT :OR: FIQBIT) MSR CPSR_cxsf,R1 ; ENTER UDF MODEMOV sp,R2SUB R2,R2,#UdfStkSzORR R1,R0,#(MODABT :OR: IRQBIT :OR: FIQBIT)MSR CPSR_cxsf,R1 ; ENTER ABT MODEMOV sp,R2SUB R2,R2,#AbtStkSz;ORR R1,R0,#(MODUSR :OR: IRQBIT :OR: FIQBIT) ;MSR CPSR_cxsf,R1 ; ENTER USR MODE;MOV sp,R2;SUB R2,R2,#UsrStkSzORR R1,R0,#(MODSYS :OR: IRQBIT :OR: FIQBIT)MSR CPSR_cxsf,R1 ; ENTER SYS MODEMOV sp,R2 ;三,初始化变量编译完成之后,连接器会生成三个基本的段,分别是RO,RW,ZI,并会在image中顺序摆放.显然,RW,ZI在运行开始时并不位于指定的RW位置,因此必须初始化LDR R0,=|Image$$RO$$Limit|LDR R1,=|Image$$RW$$Base|LDR R2,=|Image$$ZI$$Base|1CMP R1,R2LDRLO R3,[R0],#4STRLO R3,[R1],#4BLO %B1MOV R3,#0LDR R1,=|Image$$ZI$$Limit|2CMP R2,R1STRLO R3,[R2],#4BLO %B2四,复制异常向量由于代码于RAM运行时,有明显的速度优势,而且变量可以动态配置,因此可以通过re map将RAM映射到0,使得出现异常时ARM从RAM中取得向量.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_RAMLDR R0,=|Image$$RO$$Base|LDR R1,=SYSINITLDR R2,=0x200000 ; RAM STARTCMP R0,R1LDRLO R3,[R0],#4STRLO R3,[R2],#4BLO %B0这段程序将SYSINIT之前的代码,也就是异常处理函数,全部复制到RAM中, 这就意味着不能将RW设置为0x200000,这样会使得向量被冲掉.四,在RAM中运行如果有必要,且代码足够小,可以将代码置于RAM中运行,由于RAM中本身没有代码,就需要将代码复制到RAM中:COPY_BEGINLDR R0,=0x200000LDR R1,=RESET ; =|Image$$RO$$Base|CMP R1,R0 ;BLO COPY_END ;ADR R0,RESETADR R2,COPY_ENDSUB R0,R2,R0ADD R1,R1,R0LDR R3,=|Image$$RO$$Limit|3CMP R1,R3LDRLO R4,[R2],#4STRLO R4,[R1],#4BLO %B3LDR PC,=COPY_ENDCOPY_END程序首先取得RESET的连接地址,判断程序是否时是在RAM中运行,方法是与RAM起始地址比较,如果小于,那么就跳过代码复制.在复制代码的时候需要注意,在这段程序结束之前的代码没有必要复制,因为这些代码都已经执行过了,所以,先取得COPY_END,作为复制起始地址,然后计算其相对RESET的偏移,然后以RO的值加上这个偏移,就是复制目的地的起始地址,然后开始复制.五,开始主程序以上步骤完成,就可以跳转到main运行IMPORT MainLDR PC,=MainB .六,器件初始化主程序首先要进行器件的初始化,对S64而言,应该先初始化WDT,因为默认情况下,W DT是打开的,然后是各设备的时钟分配,最后应该remapiar下.s79的分析BSP目录中的是和硬件平台代码相关的函数和定义。
实验一 ARM汇编程序的编写以及启动代码的分析

实验ARM汇编程序的编写以及启动代码的分析一、实验目的:练习ARM汇编程序的编写,对提供的程序的启动代码进行分析,了解S3C2410初始化过程, 初始化代码主要是包含在start.s中。
二、实验原理:启动程序要完成的任务包括:硬件初始化,系统存储系统的配置,复制二级中断向量表。
启动程序过程●系统硬件初始化系统上电或复位后,程序从位于地址0x0的Reset Exception Vector处开始执行,因此需要在这里放置Bootloader的第一条指令:b ResetHandler,跳转到标号为ResetHandler处进行第一阶段的硬件初始化,执行完,系统进行堆栈和存储器的初始化。
使用了外设,则需要设置相关的寄存器,确定其刷新频率、总线宽度等信息。
●代码段复制到RAM中运行需要把系统的代码复制到RAM中运行。
映像文件内部共有三种输出段:RO段、RW段和ZI段。
ARMLink同时还产生了这三种输出段的起始和终止定位信息:Image$$RO$$Base、Image$$RO$$Limit、Image$$RW$$Base、Image$RW$Limit、Image$ZI$Base和Image$$ZI$$Limit。
可以在程序中使用这些定位信息。
将ROM中的代码和数据搬移到RAM中。
●建立二级中断向量表在ARM系统中,中断向量表位于0X0开始的地址处,意味着无论运行什么样的上层软件,一旦发生中断,程序就得到Flash存储器中的中断向量表里去,降低系统的运行效率。
因此在RAM中建立自己的二级中断向量表,当中断发生后,程序直接从RAM中取中断向量进入中断子程序。
尤其是在中断频繁发生的系统里,这种方法可以大大提高系统的运行效率。
三、实验内容:1.运行一个简单的串口程序,单步执行初始化代码,观察寄存器变化。
2.分析系统上电后的初始化工作包括哪些内容。
3.分析中断的处理过程,包括中断向量表的建立、中断源的识别及中断IRQ 服务程序是如何进入的。
arm启动原理及代码分析

初始化应用程序的执行环境
• Elf文件的类型:可执行文件、可重定位文 件、共享库object(又叫做共享库)文件。 • Elf文件的功能: 1、用作链接器的输入生成可执行的映像 文件 2、可装载到内存里运行,完成特定功能 的文件。
elf文件的物理结构
• • • • Elf文件头 Section: .text .data .bss .symtab Program header 可重定位文件与可执行文件的区别: 区与段的概念 program header
Section Header Table
可执行映像文件的逻辑结构
Output 输出段
Output 输出段 域 Output 输出段
装载域和运行域
• 域又组成什么呢?当然就是组成可执行文 件了,一个映像文件可以包含一到多个域。 与看起来有些多余,实际上更为重要的是 用域来描述输出区运行前和运行时在存储 系统上的位置。所以,域分为装载域和运 行域。装载域描述运行前输出段在rom/ram 中的分布状态,运行域描述运行时输出段 在rom/ram中的分布状态
• Nand flash(不可作为bootrom的存储器)
Boot相关硬件
Boot的主要功能
• • • • • 建立异常向量表 初始化中断 初始化硬件设备 初始化应用程序执行环境 跳转到主应用程序
0x00 0x04 异 常 中 断 向 量 表 的 建 立 0x08 0x0c 0x10 0x14 0x18
Section Header Table Hello.o
可执行映像文件的逻辑结构
由几个可重定位的目标文件的相同属性区组 成了可执行映像的段,那么段有组成什么? 在逻辑结构里,段组成了更大的组织:域
输入区ro 输入区rw
基于ARM的系统启动过程研究与系统移植

基于ARM的系统启动过程研究与系统移植随着信息技术的发展,嵌入式系统在各个领域中得到了广泛的应用。
而ARM架构作为一种低功耗、高性能的处理器架构,成为了嵌入式系统中的重要选择。
在ARM架构的嵌入式系统中,系统启动过程是系统正常运行的基础和前提。
本文将对基于ARM架构的系统启动过程进行研究,并探讨系统移植的相关问题。
首先,我们需要了解ARM架构的系统启动过程。
ARM架构的系统启动过程主要包括硬件初始化、引导加载和操作系统启动三个阶段。
在硬件初始化阶段,系统会对硬件进行初始化设置,包括时钟、内存、外设等。
在引导加载阶段,系统会从存储介质中加载引导程序,该引导程序负责加载操作系统。
在操作系统启动阶段,系统会启动操作系统并进入用户空间,等待用户的进一步操作。
然后,我们需要研究系统移植的相关问题。
系统移植是将一个已经开发完成的系统移植到另一个硬件平台上的过程。
在ARM架构的系统移植中,需要考虑硬件差异和驱动适配等问题。
首先,由于不同的ARM处理器有着不同的体系结构和指令集,需要进行相应的适配工作。
其次,硬件的差异也需要进行适配,包括时钟、内存、外设等。
最后,驱动的适配也是系统移植中的重要工作,需要将原系统的驱动程序适配到新的硬件平台上。
在进行系统移植时,需要进行一系列的步骤和工作。
首先,需要进行硬件的了解和分析,包括处理器的架构和指令集、外设的接口和寄存器等。
其次,需要进行引导加载程序的移植,将原系统的引导加载程序适配到新的硬件平台上。
然后,需要进行驱动程序的移植,将原系统的驱动程序适配到新的硬件平台上。
最后,需要进行系统的测试和调试,确保移植后的系统能够正常运行。
总之,基于ARM的系统启动过程研究与系统移植是嵌入式系统开发中的重要内容。
通过对系统启动过程的研究,我们可以更好地理解ARM架构的嵌入式系统的运行机制。
通过系统移植的工作,我们可以将已有的系统移植到新的硬件平台上,提高系统的灵活性和可移植性。
这对于嵌入式系统的开发和应用具有重要的意义。
ARM的启动分析详解及应用

ARM的启动分析详解及应用ARM是一款广泛应用于嵌入式系统和移动设备的处理器架构。
在ARM的启动过程中,主要涉及到硬件初始化、加载引导程序和启动操作系统等步骤。
下面将对ARM的启动过程进行详细分析,并讨论其在实际应用中的应用。
硬件初始化:在ARM的启动过程中,首先需要对硬件进行初始化。
这包括对中央处理器(CPU)、存储器、外设等进行初始化操作。
例如,初始化CPU的控制和配置寄存器,设置存储器的访问模式和权限等。
硬件初始化的目的是确保系统处于一个稳定的状态,为后续的操作打下基础。
加载引导程序:引导程序是ARM启动的关键部分,它负责初始化系统环境和加载操作系统的镜像文件。
引导程序通常位于启动设备的引导扇区或者特定的存储器地址中。
在ARM中,引导程序可以是U-Boot、Das U-Boot或是其他自定义的引导程序。
加载引导程序的方式可以是通过串口、以太网或者其他类似的介质。
引导程序的主要功能是初始化设备和外设,配置内存和中断控制器等。
它会加载操作系统的镜像文件到内存中,并跳转到操作系统的起始地址,从而将控制权交给操作系统。
启动操作系统:在引导程序加载并跳转到操作系统的起始地址后,操作系统开始运行。
操作系统负责管理硬件资源、提供系统服务和支持应用程序的运行。
常见的ARM操作系统有Linux、Android等。
ARM的启动分析步骤在实际应用中具有重要的意义。
首先,通过硬件初始化可以确保系统处于一个稳定的状态,避免因为硬件问题导致系统崩溃或运行不正常。
其次,加载引导程序可以实现自定义的系统启动流程和初始化操作,满足特定应用需求。
最后,启动操作系统可以为用户提供高效、稳定的系统环境,并支持各种应用程序的运行。
在实际的应用中,ARM的启动分析步骤具有广泛的应用。
例如,嵌入式系统可以通过自定义的引导程序来实现特定的启动流程和初始化操作,以满足设备的需求。
移动设备则可以通过加载引导程序和启动操作系统来提供稳定的系统环境和良好的用户体验。
ARM启动代码分析

ARM启动代码分析
ARM启动代码的第一步是设置处理器的模式和栈指针。
ARM处理器有
多种模式,如用户模式、系统模式、中断模式和监视模式等,而每种模式
都有自己的寄存器集合,因此需要选择一个合适的模式。
一般情况下,一
开始会进入特权模式(如系统模式),然后将栈指针设置到RAM的一些合
适位置。
ARM启动代码的第三步是设置不同的中断服务例程。
ARM处理器支持
多种中断,如IRQ中断和FIQ中断等。
具体中断处理过程包括保存现场、
执行中断服务例程、恢复现场等步骤,这些都需要在启动代码中进行相关
的设置。
ARM启动代码的第四步是初始化内存管理单元(MMU)。
MMU是用来处
理虚拟地址和物理地址之间的映射关系的硬件单元,它可以提供更高的系
统性能和更灵活的内存管理能力。
初始化MMU需要设置页表和相关的控制
寄存器。
除了上述主要的步骤,ARM启动代码还可能包括其他一些完成特定任
务的代码,如初始化外设、配置中断控制器、设置缓存等。
这些任务的完
成都是为了保证系统正常启动和运行。
总之,ARM启动代码是用来初始化ARM处理器和系统环境的一段代码,它完成了处理器模式设置、时钟频率配置、中断服务例程设置、MMU初始
化以及跳转到操作系统内核等主要任务。
通常情况下,ARM启动代码由汇
编语言编写,具有高度灵活性和直接性。
ARM启动代码分析
ARM启动代码分析-philips的LPC2xxx系列***********************************************************************************************File: startup.s*Author: Embest w.h.xie 2005.02.21*Desc: lpc22xx\lpc212x\lpc211x\lpc210x startup code*History:* note modify:cui jian jie 2006-4-25*comment:**********************************************************************************************/# 处理器的七种工作方式的常量定义.EQU Mode_USR, 0x10 #用户模式.EQU Mode_FIQ, 0x11 #FIQ模式.EQU Mode_IRQ, 0x12 #IRQ模式.EQU Mode_SVC, 0x13 #超级用户模式.EQU Mode_ABT, 0x17 #终止模式.EQU Mode_UND, 0x1B #未定义模式.EQU Mode_SYS, 0x1F #系统模式# 中断屏蔽位.EQU I_Bit, 0x80 //IRQ中断控制位,当被置位时,IRQ中断被禁止.EQU F_Bit, 0x40 //FIQ中断控制位,当被置位时,FIQ中断被禁止# 状态屏蔽位.EQU T_bit, 0x20 //T位,置位时在Thumb模式下运行,清零时在ARM下运行# 定义程序入口点.globl _start.code 32.TEXT_start:# 中断向量表Vectors:LDR PC, Reset_Addr //把Reset_Addr地址处的内容放入PC中LDR PC, Undef_AddrLDR PC, SWI_AddrLDR PC, PAbt_AddrLDR PC, DAbt_Addr.long 0xb9205f80 @ keep interrupt vectors sum is 0LDR PC, [PC, #-0xff0] //当前PC值减去0xFF0等于IRQ中断入口地址LDR PC, FIQ_Addr#地址表Reset_Addr: #该地址标号存放Reset_Handler程序段的入口地址 .long Reset_HandlerUndef_Addr: #该地址标号存放Undef_Handler程序段的入口地址 .long Undef_HandlerSWI_Addr: #该地址标号存放SWI_Handler程序段的入口地址 .long SWI_HandlerPAbt_Addr: #该地址标号存放PAbt_Handler程序段的入口地址 .long PAbt_HandlerDAbt_Addr:.long DAbt_Handler.long 0IRQ_Addr: #地址标号处存放一个无效的数据.long 0FIQ_Addr: #该地址标号存放FIQ_Handler程序段的入口地址 .long FIQ_HandlerUndef_Handler:B Undef_HandlerPAbt_Handler:B PAbt_HandlerDAbt_Handler:B DAbt_Handler#软中断的中断服务子程序入口地址SWI_Handler:STMFD sp!, {r0-r3, r12, lr} //入栈,现场数据保护MOV r1, sp //把堆栈指针SP存入R1中MRS r0, spsr //把SPSR值存入R0,SPSR值为产生软中断时的CPSRTST r0, #T_bit //判断R0(SPSR)的T位是否为0#SPSR的T位不为0,工作在Thumb模式下LDRNEH r0, [lr,#-2] //SPSR的T位不为0,则[lr-2]-〉r0BICNE r0, r0, #0xFF00 // SPSR的T位不为0,清除r0的Bit8~Bit15位# SPSR的T位为0,工作在ARM模式下LDREQ r0, [lr,#-4] // SPSR的T位为0,则[lr-4] -〉r0BICEQ r0, r0, #0xFF000000 // SPSR的T位为0,清除r0的Bit24~Bit131位# R0 is interrupt number //R0是中断号# R1 is stack point //R1是堆栈指针BL SWI_Exception //进入软中断处理程序LDMFD sp!, {r0-r3, r12, pc}^ //出栈,现场数据恢复# 快速响应中断的中断服务自程序的入口地址FIQ_Handler:STMFD SP!, {R0-R3, LR} //入栈的现场保护# BL FIQ_Exception //进入FIQ的中断处理程序LDMFD SP!, {R0-R3, LR} //出栈,恢复现场SUBS PC, LR, #4 //返回到主程序# 复位后程序处理的入口地址Reset_Handler:BL RemapSRAM //进行存储器映射的操作#下面几行代码用来判断当前的工作模式MRS R0, CPSR //读CPSR到寄存器R0AND R0, R0, #0x1F //R0 = R0 AND 0x1FCMP R0, #Mode_USR //比较R0 和#Mode_USR,二者相减//如果相等则说明当前处在用户模式下,需要通过产生11号软中断进入系统模式。
ARM启动代码研究
ARM启动代码研究PRESERVE8:1.1.PRESERVE8:Reguire8和Preserve8C和汇编有8位对齐的要求,这两个伪指令可以满足此要求,存在REQUIRE8<——> PRESERVE8的对应关系,但不是说有一个REQUIRE8就要有一个PRESERVE8,如果是一个c文件和一个汇编文件的调用,也就涉及一个PRESERVE8或者是一个REQUIRE8.另外,REQUIRE8和PRESERVE8并不完成8byte对齐的操作,对齐由ALIGN完成。
将ADS的代码移植到KEIL MDK上需要做的修改:当用户拥有ADS遗留工程的所有源代码时,使用MDK重新编译链接全部代码是最好的解决方法,MDK中的新版本编译工具会重新生成满足堆栈8BYTE对齐要求的目标文件,避免由于堆栈不对齐引起的链接错误.从ADS到KEIL很重要的一个修改的地方就是这里的8BYTE对齐,想要编译通过,在startup.s 里面我们必须加入PRESERVE8指令,使得寄存器8BYTE对齐.代码:CODE32PRESERVE8;这个在KEIL里面是必须的,要求8BYTE对齐.在ADS的启动代码中就没有. AREA vectors,CODE,READONLY2:ARM的处理器可工作于多种模式,下面设置个模式的一些参数.Mode_USR EQU0x10用户模式Mode_FIQ EQU0x11快中断模式Mode_IRQ EQU0x12中断模式Mode_SVC EQU0x13管理模式Mode_ABT EQU0x17中止模式Mode_UND EQU0x1B未定义模式Mode_SYS EQU0x1F系统模式参数的由来:这里各个模式的参数是由寄存器CPSR的模式位设置M[4:0]得来的,比如这里的用户模式,CPSR的M[4:0]设置为10000就是0x10,同理其他.详见<<ARM嵌入式系统基础教程>>P47页,CPSR设置很关键!3:I_Bit EQU0x80;when I bit is set,IRQ is disabledF_Bit EQU0x40;when F bit is set,FIQ is disabled也和CPSR寄存器的设置有关,这里两位是禁止/开启快速中断和一般中断的设置.4:各模式下定义的堆栈地址.UND_Stack_Size EQU0x00000000SVC_Stack_Size EQU0x00000100ABT_Stack_Size EQU0x00000000FIQ_Stack_Size EQU0x00000000IRQ_Stack_Size EQU0x00000100USR_Stack_Size EQU0x00000200设置堆栈大小Stack_Size EQU(UND_Stack_Size+SVC_Stack_Size+ABT_Stack_Size+FIQ_Stack_Size+IRQ_Stack_Size+USR_Stack_Size)AREA STACK,NOINIT,READWRITE,ALIGN=3Stack_Mem SPACE Stack_SizeStack_Top EQU Stack_Mem+Stack_Size堆栈大小的设置,各公司写的启动代码有所不同,但是不影响大局,可以借鉴一些你认为比较简单的启动代码,然后写自己的堆栈地址和大小设置程序.5:堆的设置Heap_Size EQU0x00000000AREA HEAP,NOINIT,READWRITE,ALIGN=3Heap_Mem SPACE Heap_SizeAREA Init,CODE,READONLY,ALIGN=3//指定后面的指令为8位对齐(2的3次方)align n它的含义就是使得下面的代码按一定规则对齐,.align n指令的对齐值有两种方案,n或2^n,各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器,必然要保持和原来汇编器的兼容,因此在gas中如何解释.align指令会显得有些混乱,原因在于保持兼容。
ARM启动代码研究(附源代码).
ARM启动代码研究(附源代码)1:PRESERVE8:Reguire8和Preserve8C和汇编有8位对齐的要求,这两个伪指令可以满足此要求,存在REQUIRE8<——>PRESERVE8的对应关系,但不是说有一个REQUIRE8就要有一个PRESERVE8,如果是一个c文件和一个汇编文件的调用,也就涉及一个PRESERVE8或者是一个REQUIRE8.另外,REQUIRE8和PRESERVE8并不完成8byte对齐的操作,对齐由ALIGN完成。
将ADS的代码移植到KEILMDK上需要做的修改:当用户拥有ADS遗留工程的所有源代码时,1:PRESERVE8:Reguire8和Preserve8C和汇编有8位对齐的要求,这两个伪指令可以满足此要求,存在REQUIRE8<——> PRESERVE8的对应关系,但不是说有一个REQUIRE8就要有一个 PRESERVE8,如果是一个c文件和一个汇编文件的调用,也就涉及一个PRESERVE8或者是一个REQUIRE8.另外,REQUIRE8和PRESERVE8并不完成8 byte 对齐的操作,对齐由ALIGN完成。
将ADS的代码移植到KEIL MDK上需要做的修改:当用户拥有ADS遗留工程的所有源代码时,使用MDK重新编译链接全部代码是最好的解决方法,MDK中的新版本编译工具会重新生成满足堆栈8BYTE对齐要求的目标文件,避免由于堆栈不对齐引起的链接错误.从ADS到KEIL很重要的一个修改的地方就是这里的8BYTE对齐,想要编译通过,在startup.s里面我们必须加入PRESERVE8指令,使得寄存器8BYTE对齐.代码:CODE32PRESERVE8 ;这个在KEIL里面是必须的,要求8BYTE对齐.在ADS的启动代码中就没有.AREA vectors,CODE,READONLY2: ARM的处理器可工作于多种模式,下面设置个模式的一些参数.Mode_USR EQU 0x10 用户模式Mode_FIQ EQU 0x11快中断模式Mode_IRQ EQU 0x12中断模式Mode_SVC EQU 0x13 管理模式Mode_ABT EQU 0x17 中止模式Mode_UND EQU 0x1B 未定义模式Mode_SYS EQU 0x1F系统模式参数的由来:这里各个模式的参数是由寄存器CPSR的模式位设置M[4:0]得来的,比如这里的用户模式,CPSR的M[4:0]设置为10000就是0x10,同理其他.详见<<ARM嵌入式系统基础教程>>P47页,CPSR设置很关键!3:I_Bit EQU 0x80 ; when I bit is set, IRQ is disabledF_Bit EQU 0x40 ; when F bit is set, FIQ is disabled也和CPSR寄存器的设置有关,这里两位是禁止/开启快速中断和一般中断的设置.4: 各模式下定义的堆栈地址.UND_Stack_Size EQU 0x00000000SVC_Stack_Size EQU 0x00000100ABT_Stack_Size EQU 0x00000000FIQ_Stack_Size EQU 0x00000000IRQ_Stack_Size EQU 0x00000100USR_Stack_Size EQU 0x00000200设置堆栈大小Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size +FIQ_Stack_Size +IRQ_Stack_Size + USR_Stack_Size)AREA STACK, NOINIT, READWRITE, ALIGN=3Stack_Mem SPACE Stack_SizeStack_Top EQU Stack_Mem + Stack_Size堆栈大小的设置,各公司写的启动代码有所不同,但是不影响大局,可以借鉴一些你认为比较简单的启动代码,然后写自己的堆栈地址和大小设置程序.5:堆的设置Heap_Size EQU 0x00000000AREA HEAP, NOINIT, READWRITE, ALIGN=3Heap_Mem SPACE Heap_SizeAREA Init,CODE,READONLY,ALIGN=3 //指定后面的指令为8位对齐(2的3次方) align n它的含义就是使得下面的代码按一定规则对齐,.align n 指令的对齐值有两种方案,n 或 2^n ,各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器,必然要保持和原来汇编器的兼容,因此在gas中如何解释 .align指令会显得有些混乱,原因在于保持兼容。
ARM的启动分析详解
7
程序入口
下面是大小端的一个判断, 条件编译, 下面是大小端的一个判断 条件编译,在编译成机器码前 就设定好,在 里已经设为FALSE。 就设定好 在Option.inc里已经设为 里已经设为 。
8
分配中断向量表
ARM 要求中断向量表必须放置在从 要求中断向量表必须放置在从0x00000000 地址开 始,连续32 个字节的空间内。 连续 个字节的空间内。 每当一个中断发生后,即使移植了操作系统如 每当一个中断发生后,即使移植了操作系统如linux ,处理 处理 器还是会跳转到从0x0开始 强制把 指针指向对应中断类型 开始,强制把 器还是会跳转到从 开始 强制把PC指针指向对应中断类型 的向量表中的地址。 的向量表中的地址。 因为每个中断只占据向量表中4 个字节的存储空间, 因为每个中断只占据向量表中 个字节的存储空间,只能 放置一条ARM 指令,所以,通常放一条跳转指令让程序跳 指令,所以, 放置一条 转到存储器的其他地方,再执行中断处理。 转到存储器的其他地方,再执行中断处理。
根据工作频率设置pll : 根据工作频率设置 Fpllo=(m*Fin)/(p*2^s) m=MDIV+8,p=PDIV+2,s=SDIV Fpllo必须大于 必须大于20Mhz小于 小于66Mhz,Fpllo*2^s必须小于 必须小于170Mhz 必须大于 小于 , 必须小于
14
4、初始化PLL和时钟 、初始化 和时钟
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=12MHz,Fout=50MHz str r1,[r0] ;Configure UPLL ldr r0,=UPLLCON ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) ;Fin=12MHz,UPLLout=48MHz str r1,[r0] ] 16
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ARM启动代码研究PRESERVE8:1.1.PRESERVE8:Reguire8和Preserve8C和汇编有8位对齐的要求,这两个伪指令可以满足此要求,存在REQUIRE8<——> PRESERVE8的对应关系,但不是说有一个REQUIRE8就要有一个PRESERVE8,如果是一个c文件和一个汇编文件的调用,也就涉及一个PRESERVE8或者是一个REQUIRE8.另外,REQUIRE8和PRESERVE8并不完成8byte对齐的操作,对齐由ALIGN完成。
将ADS的代码移植到KEIL MDK上需要做的修改:当用户拥有ADS遗留工程的所有源代码时,使用MDK重新编译链接全部代码是最好的解决方法,MDK中的新版本编译工具会重新生成满足堆栈8BYTE对齐要求的目标文件,避免由于堆栈不对齐引起的链接错误.从ADS到KEIL很重要的一个修改的地方就是这里的8BYTE对齐,想要编译通过,在startup.s 里面我们必须加入PRESERVE8指令,使得寄存器8BYTE对齐.代码:CODE32PRESERVE8;这个在KEIL里面是必须的,要求8BYTE对齐.在ADS的启动代码中就没有. AREA vectors,CODE,READONLY2:ARM的处理器可工作于多种模式,下面设置个模式的一些参数.Mode_USR EQU0x10用户模式Mode_FIQ EQU0x11快中断模式Mode_IRQ EQU0x12中断模式Mode_SVC EQU0x13管理模式Mode_ABT EQU0x17中止模式Mode_UND EQU0x1B未定义模式Mode_SYS EQU0x1F系统模式参数的由来:这里各个模式的参数是由寄存器CPSR的模式位设置M[4:0]得来的,比如这里的用户模式,CPSR的M[4:0]设置为10000就是0x10,同理其他.详见<<ARM嵌入式系统基础教程>>P47页,CPSR设置很关键!3:I_Bit EQU0x80;when I bit is set,IRQ is disabledF_Bit EQU0x40;when F bit is set,FIQ is disabled也和CPSR寄存器的设置有关,这里两位是禁止/开启快速中断和一般中断的设置.4:各模式下定义的堆栈地址.UND_Stack_Size EQU0x00000000SVC_Stack_Size EQU0x00000100ABT_Stack_Size EQU0x00000000FIQ_Stack_Size EQU0x00000000IRQ_Stack_Size EQU0x00000100USR_Stack_Size EQU0x00000200设置堆栈大小Stack_Size EQU(UND_Stack_Size+SVC_Stack_Size+ABT_Stack_Size+FIQ_Stack_Size+IRQ_Stack_Size+USR_Stack_Size)AREA STACK,NOINIT,READWRITE,ALIGN=3Stack_Mem SPACE Stack_SizeStack_Top EQU Stack_Mem+Stack_Size堆栈大小的设置,各公司写的启动代码有所不同,但是不影响大局,可以借鉴一些你认为比较简单的启动代码,然后写自己的堆栈地址和大小设置程序.5:堆的设置Heap_Size EQU0x00000000AREA HEAP,NOINIT,READWRITE,ALIGN=3Heap_Mem SPACE Heap_SizeAREA Init,CODE,READONLY,ALIGN=3//指定后面的指令为8位对齐(2的3次方)align n它的含义就是使得下面的代码按一定规则对齐,.align n指令的对齐值有两种方案,n或2^n,各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器,必然要保持和原来汇编器的兼容,因此在gas中如何解释.align指令会显得有些混乱,原因在于保持兼容。
arm-linux是按照2^n的方案对齐的.ARM的.align5就是2的5次方(32位)对齐,也就是4字节(32位)对齐.6:AREA RESET,CODE,READONLYARM下面的是ARM的代码,不是THUMB.7:中断向量表ResetLDR PC,ResetAddrLDR PC,UndefinedAddrLDR PC,SWI_AddrLDR PC,PrefetchAddrLDR PC,DataAbortAddrDCD0xb9205f80LDR PC,[PC,#-0xff0]LDR PC,FIQ_AddrResetAddr DCD ResetInit UndefinedAddr DCD Undefined SWI_Addr DCD SoftwareInterrupt PrefetchAddr DCD PrefetchAbort DataAbortAddr DCD DataAbort Nouse DCD0IRQ_Addr DCD0FIQ_Addr DCD FIQ_Handler;未定义指令UndefinedB Undefined;软中断SoftwareInterruptB SoftwareInterrupt;取指令中止PrefetchAbortB PrefetchAbort;取数据中止DataAbortB DataAbort;快速中断FIQ_HandlerSTMFD SP!,{R0-R3,LR}BL FIQ_ExceptionLDMFD SP!,{R0-R3,LR}SUBS PC,LR,#4 8:InitStackMOV R0,LR;Build the SVC stack;设置管理模式堆栈MSR CPSR_c,#0xd3LDR SP,StackSvc;Build the IRQ stack;设置中断模式堆栈MSR CPSR_c,#0xd2LDR SP,StackIrq;Build the FIQ stack;设置快速中断模式堆栈MSR CPSR_c,#0xd1LDR SP,StackFiq;Build the DATAABORT stack;设置中止模式堆栈MSR CPSR_c,#0xd7LDR SP,StackAbt;Build the UDF stack;设置未定义模式堆栈MSR CPSR_c,#0xdbLDR SP,StackUnd;Build the SYS stack;设置系统模式堆栈MSR CPSR_c,#0x5f;#0xdfLDR SP,=StackUsrMOV PC,R09:BL InitStack;初始化堆栈Initialize the stackBL TargetResetIni;目标板基本初始化;跳转到c语言入口Jump to the entry point of C programB__main周立功启动代码:;/****************************************Copyright(c)**************************************************;**Guangzou ZLG-MCU Development Co.,LTD.;**graduate school;**;**;**--------------File Info-------------------------------------------------------------------------------;**File name:Startup.s;**Last modified Date:2004-09-17;**Last Version: 1.0;**Descriptions:The start up codes for LPC2100,including the initializing codes for the entry point of exceptions and the stacks of user tasks.;**Every project should have a independent copy of this file for related modifications ;**------------------------------------------------------------------------------------------------------;**Created by:Chenmingji;**Created date:2004-02-02;**Version: 1.0;**Descriptions:The original version//原著;**;**------------------------------------------------------------------------------------------------------;**Modified by:Chenmingji;**Modified date:2004-09-17;**Version: 1.01;**Descriptions:Modified the bus setting to adapt for many common situations;**//改进了总线,可以根据这里的更改来控制总线的速率;**------------------------------------------------------------------------------------------------------;**Modified by:Chenmingji;**Modified date:2004-09-17;**Version: 1.02;**Descriptions:Added codes to support the enciphering of the chip;**//增加了芯片加密;**------------------------------------------------------------------------------------------------------;**Modified by:Chenmingji;**Modified date:2004-09-17;**Version: 1.04;**Descriptions:Renewed the template,added codes to support more compilers;**//重建模板,加入更多代码来支持更多的编译;**------------------------------------------------------------------------------------------------------;**Modified by:;**Modified date:;**Version:;**Descriptions:;**;********************************************************************************************************/;define the stack size;定义堆栈的大小SVC_STACK_LEGTH EQU0FIQ_STACK_LEGTH EQU0IRQ_STACK_LEGTH EQU256ABT_STACK_LEGTH EQU0UND_STACK_LEGTH EQU0NoInt EQU0x80;定义处理器模式,用户/管理/系统/中断USR32Mode EQU0x10SVC32Mode EQU0x13SYS32Mode EQU0x1fIRQ32Mode EQU0x12FIQ32Mode EQU0x11PINSEL2EQU0xE002C014//定义PINSEL2地址,这个地址的值一般用户不需要改变,和芯片的加密有关//更改后有可能使得JTAG调试失效,进入芯片加密状态. BCFG0EQU0xFFE00000BCFG1EQU0xFFE00004BCFG2EQU0xFFE00008BCFG3EQU0xFFE0000C//定义存储器组配置寄存器BCFG_16DEF EQU0x10000400;//16Bit BusBCFG_CS3EQU(BCFG_16DEF|(0x01<<00)|(0x07<<05)|(0x07<<11));//分别是IDCY/WST1/WST2对应读写速率等;//从第0位开始对其写入0001,;//从第5位开始写入0111;//从11位开始写入0111(0x07)/11111(0x1f)IMPORT__use_no_semihosting_swi;The imported labels;引入的外部标号在这声明IMPORT FIQ_Exception;Fast interrupt exceptions handler快速中断异常处理程序IMPORT__main;The entry point to the main function C 语言主程序入口IMPORT TargetResetInit;initialize the target board目标板基本初始化;The emported labels;给外部使用的标号在这声明EXPORT bottom_of_heapEXPORT StackUsrEXPORT ResetEXPORT__user_initial_stackheapCODE32AREA vectors,CODE,READONLY ENTRY;interrupt vectors;中断向量表ResetLDR PC,ResetAddrLDR PC,UndefinedAddrLDR PC,SWI_AddrLDR PC,PrefetchAddrLDR PC,DataAbortAddrDCD0xb9205f80LDR PC,[PC,#-0xff0]LDR PC,FIQ_AddrResetAddr DCD ResetInit UndefinedAddr DCD Undefined SWI_Addr DCD SoftwareInterrupt PrefetchAddr DCD PrefetchAbort DataAbortAddr DCD DataAbort Nouse DCD0IRQ_Addr DCD0FIQ_Addr DCD FIQ_Handler;未定义指令UndefinedB Undefined;软中断SoftwareInterruptB SoftwareInterrupt;取指令中止PrefetchAbortB PrefetchAbort;取数据中止DataAbortB DataAbort;快速中断FIQ_HandlerSTMFD SP!,{R0-R3,LR}BL FIQ_ExceptionLDMFD SP!,{R0-R3,LR}SUBS PC,LR,#4;/********************************************************************************************************* ;**unction name函数名称:InitStack;**Descriptions功能描述:Initialize the stacks初始化堆栈;**input parameters输入:None无;**Returned value输出:None无;**Used global variables全局变量:None无;**Calling modules调用模块:None无;**;**Created by作者:Chenmingji陈明计;**Created Date日期:2004/02/022004年2月2日;**-------------------------------------------------------------------------------------------------------;**Modified by修改:;**Modified date日期:;**-------------------------------------------------------------------------------------------------------;********************************************************************************************************/ InitStackMOV R0,LR;Build the SVC stack;设置管理模式堆栈MSR CPSR_c,#0xd3LDR SP,StackSvc;Build the IRQ stack;设置中断模式堆栈MSR CPSR_c,#0xd2LDR SP,StackIrq;Build the FIQ stack;设置快速中断模式堆栈MSR CPSR_c,#0xd1LDR SP,StackFiq;Build the DATAABORT stack;设置中止模式堆栈MSR CPSR_c,#0xd7LDR SP,StackAbt;Build the UDF stack;设置未定义模式堆栈MSR CPSR_c,#0xdbLDR SP,StackUnd;Build the SYS stack;设置系统模式堆栈MSR CPSR_c,#0x5f;#0xdfLDR SP,=StackUsrMOV PC,R0;/********************************************************************************************************* ;**unction name函数名称:ResetInit;**Descriptions功能描述:RESET复位入口;**input parameters输入:None无;**Returned value输出:None无;**Used global variables全局变量:None无;**Calling modules调用模块:None无;**;**Created by作者:Chenmingji陈明计;**Created Date日期:2004/02/022004年2月2日;**-------------------------------------------------------------------------------------------------------;**Modified by修改:Chenmingji陈明计;**Modified date日期:2004/02/022004年3月3日;**-------------------------------------------------------------------------------------------------------;********************************************************************************************************/ ResetInit;初始化外部总线控制器,根据目标板决定配置;;LDR R0,=PINSEL2;IF:DEF:EN_CRP;LDR R1,=0x0f814910;ELSE;LDR R1,=0x0f814914;ENDIF;STR R1,[R0]LDR R0,=BCFG0LDR R1,=0x1000ffef;0x00001046STR R1,[R0]LDR R0,=BCFG1LDR R1,=BCFG_CS3;0x1000ffef;0x1000ffef;;STR R1,[R0]LDR R0,=BCFG2LDR R1,=0x2000ffefSTR R1,[R0];LDR R0,=BCFG3;LDR R1,=0x00000CA0;0x2000ffef;STR R1,[R0]BL InitStack;初始化堆栈Initialize the stackBL TargetResetInit;目标板基本初始化Initialize the target board;跳转到c语言入口Jump to the entry point of C programB__main;/*********************************************************************************************************;**unction name函数名称:__user_initial_stackheap;**Descriptions功能描述:Initial the function library stacks and heaps,can not deleted!库函数初始化堆和栈,不能删除;**input parameters输入:reference by function library参考库函数手册;**Returned value输出:reference by function library参考库函数手册;**Used global variables全局变量:None无;**Calling modules调用模块:None无;**;**Created by作者:Chenmingji陈明计;**Created Date日期:2004/02/022004年2月2日;**-------------------------------------------------------------------------------------------------------;**Modified by;**Modified date;**-------------------------------------------------------------------------------------------------------;********************************************************************************************************/ __user_initial_stackheapLDR r0,=bottom_of_heap;LDR r1,=StackUsrMOV pc,lrStackSvc DCD SvcStackSpace+(SVC_STACK_LEGTH-1)*4 StackIrq DCD IrqStackSpace+(IRQ_STACK_LEGTH-1)*4 StackFiq DCD FiqStackSpace+(FIQ_STACK_LEGTH-1)*4 StackAbt DCD AbtStackSpace+(ABT_STACK_LEGTH-1)*4 StackUnd DCD UndtStackSpace+(UND_STACK_LEGTH-1)*4;/*********************************************************************************************************;**unction name函数名称:CrpData;**Descriptions功能描述:encrypt the chip;**input parameters输入:None无;**Returned value输出:None无;**Used global variables全局变量:None无;**Calling modules调用模块:None无;**;**Created by作者:Chenmingji陈明计;**Created Date日期:2004/03/272004年3月27日;**-------------------------------------------------------------------------------------------------------;**Modified by修改:;**Modified date日期:;**-------------------------------------------------------------------------------------------------------;********************************************************************************************************/ IF:DEF:EN_CRPIF.>=0x1fcINFO1,"The data at0x000001fc must be0x87654321.Please delete some source before this line."ENDIFCrpDataWHILE.<0x1fcNOPWENDCrpData1DCD0x87654321;/*When the Data is为0x87654321,user code be protected.当此数为0x87654321时,用户程序被保护*/ENDIF;/*分配堆栈空间*/AREA MyStacks,DATA,NOINIT,ALIGN=2SvcStackSpace SPACE SVC_STACK_LEGTH*4;Stack spaces for Administration Mode管理模式堆栈空间IrqStackSpace SPACE IRQ_STACK_LEGTH*4;Stack spaces for Interrupt ReQuest Mode中断模式堆栈空间FiqStackSpace SPACE FIQ_STACK_LEGTH*4;Stack spaces for Fast Interrupt reQuest Mode快速中断模式堆栈空间AbtStackSpace SPACE ABT_STACK_LEGTH*4;Stack spaces for Suspend Mode 中止义模式堆栈空间UndtStackSpace SPACE UND_STACK_LEGTH*4;Stack spaces for Undefined Mode 未定义模式堆栈AREA Heap,DATA,NOINITbottom_of_heap SPACE1AREA Stacks,DATA,NOINITStackUsrEND;/********************************************************************************************************* ;**End Of File;********************************************************************************************************/。