ARM 启动代码详解

上传人:痛*** 文档编号:127754958 上传时间:2022-07-30 格式:DOCX 页数:10 大小:39.10KB
收藏 版权申诉 举报 下载
ARM 启动代码详解_第1页
第1页 / 共10页
ARM 启动代码详解_第2页
第2页 / 共10页
ARM 启动代码详解_第3页
第3页 / 共10页
资源描述:

《ARM 启动代码详解》由会员分享,可在线阅读,更多相关《ARM 启动代码详解(10页珍藏版)》请在装配图网上搜索。

1、ARM 启动代码详解(Vectors.c、Init.s、Target.c、 Target.h)2010-05-15 16:03启动代码是芯片复位后进入C语言的main()函数前执行的一段代码,主要是为运行C语言程序提供基本运行环境,如初始化存储器系统等。ARM公司只设计内核,不自己生产芯片,只是把内核授权给其它厂商,其它厂商购买了授权且加入自己的外设后生产出各具特色的芯片。这样就促进了基于ARM处理器核的芯片多元化,但也使得每一种芯片的启动代码差别很大,不易编写出统一的启动代码。ADS(针对ARM处理器核的C语言编译器)的策略是不提供完整的启动代码,启动代码不足部分或者由厂商提供,或者自己编写

2、。启动代码划分为4个文件:Vectors.c、Init.s、Target.c、 Target.h。Vectors.c包含异常向量表、堆栈初始化及中断服务程序与C程序的接口。Init.s包含统初始化代码,并跳转到ADS提供的初始化代码。Target.c和 Target.h包含目标板特殊的代码,包括异常处理程序和目标板初始化程序。这样做的目的是为了尽量减少汇编代码,同时把不需要修改的代码独立出来以减少错误。 4.2.1 Vectors.c文件的编写4.2.1.1 中断向量表Vectors LDR PC, ResetAddr LDR PC, UndefinedAddr LDR PC, SWI_Add

3、r LDR PC, PrefetchAddr LDR PC, DataAbortAddr DCD 0xb9205f80 LDR PC, PC, #-0xff0 LDR PC, FIQ_AddrResetAddr DCD ResetUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortDataAbortAddr DCD DataAbortnouse DCD 0IRQ_Addr DCD IRQ_HandlerFIQ_Addr DCD FIQ_Handler异常是由内部或外部源产生

4、的以引起处理器处理的一个事件。ARM处理器核支持7种类型的异常。异常出现后,CPU强制从异常类型对应的固定存储地址开始执行程序。这个固定的地址就是异常向量。向量从上到下依次为复位、未定义指令异常、软件中断、预取指令中止、预取数据中止、保留的异常、IRQ和 FIQ。IRQ向量“LDR PC, PC, #-0xff0” 使用的指令与其它向量不同。在正常情况下这条指令所在地址为0X。当CPU执行这条指令但还没有跳转时,PC的值为0X,0X减去 0X00000FF0为 0XFFFFF030,这是向量中断控制器(VIC)的特殊寄存器VICVectAddr。这个寄存器保存当前将要服务的IRQ的中断服务程序

5、的入口,用这一条指令就可以直接跳转到需要的中断服务程序中。至于在保留的异常向量“DCD 0xb9205f80”位置填数据0xb9205f8是为了使向量表中所有的数据32位累加和为0。4.2.1.2 初始化CPU堆栈InitStack MOV R0, LR MSR CPSR_c, #0xd2 ;设置中断模式堆栈 LDR SP, StackIrq MSR CPSR_c, #0xd1 ;设置快速中断模式堆栈 LDR SP, StackFiq MSR CPSR_c, #0xd7 ;设置中止模式堆栈 LDR SP, StackAbt MSR CPSR_c, #0xdb ;设置未定义模式堆栈 LDR SP

6、, StackUnd MSR CPSR_c, #0xdf ;设置系统模式堆栈 LDR SP, StackSys MOV PC, R0StackIrq DCD (IrqStackSpace + IRQ_STACK_LEGTH * 4 - 4)StackFiq DCD (FiqStackSpace + FIQ_STACK_LEGTH * 4 - 4)StackAbt DCD (AbtStackSpace + ABT_STACK_LEGTH * 4 - 4)StackUnd DCD (UndtStackSpace + UND_STACK_LEGTH * 4 - 4)StackSys DCD (Sys

7、StackSpace + SYS_STACK_LEGTH * 4 -4 );/* 分配堆栈空间 */ AREA MyStacks, DATA, NOINITIrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;中断模式堆栈FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;快速中断模式堆栈AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;中止义模式堆栈UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;未定义模式堆栈SysStackSpace SPACE SYS_STACK

8、_LEGTH * 4 ; 系统模式堆栈因为程序需要切换模式,而且程序退出时CPU的模式已经不再是管理模式而是系统模式LR已经不再保存返回程序地址,所以程序首先把返回地址保存到 R0中,同时使用R0返回。然后程序把处理器模式转化为IRQ模式,并设置IRQ模式的堆栈指针。其中变量Stacklrq保存着IRQ模式的堆栈指针的初始值,Irqstackspace是分配给 IRQ模式的堆栈空间的开始地址,IRQ_STACK_LEGTH是用户定义的常量,用于设置 IRQ模式的堆栈空间的大小。程序使用同样的方法设置FIQ模式堆栈指针、中止模式堆栈指针、未定义堆栈指针和系统模式堆栈指针。程序使用编译器分配的空间

9、作为堆栈,而不是按照通常的做法把堆栈分配到 RAM的顶端,之所以这样是因为这样做不必知道RAM顶端位置,移植更加方便;编译器给出的占用RAM空间的大小就是实际占用的大小,便于控制RAM的分配。对于 LPC2106来说,中止模式是不需要分配堆栈空间的,这是因为 LPC2106没有外部总线,也没有虚拟内存机制,如果出现取数据中止或取指令中止肯定是程序有问题。而一般情况下也不需要模拟协处理器指令或扩充指令,未定义中止也就意味着程序有错误,也不需要分配堆栈空间。4.2.1.3 异常处理代码与C语言的接口程序C/OS-中断服务子程序流程图如图4-1所示:图4-1 中断服务子程序流程图异常处理代码与C语言

10、的接口程序如下:MACRO$IRQ_Label HANDLER $IRQ_Exception EXPORT $IRQ_Label ;输出的标号 IMPORT $IRQ_Exception ;引用的外部标号$IRQ_Label SUB LR, LR, #4 ;计算返回地址 STMFD SP!, R0-R3, R12, LR ;保存任务环境 MRS R3, SPSR ;保存状态 STMFD SP!, R3 LDR R2, =OSIntNesting ;OSIntNesting+ LDRB R1, R2 ADD R1, R1, #1 STRB R1, R2 BL $IRQ_Exception ;调用

11、c语言的中断处理程序 MSR CPSR_c, #0x92 ;关中断 BL OSIntExit LDR R0, =OSTCBHighRdy LDR R0, R0 LDR R1, =OSTCBCur LDR R1, R1 CMP R0, R1 LDMFD SP!, R3 MSR SPSR_cxsf, R3 LDMEQFD SP!, R0-R3, R12, PC ;不进行任务切换 LDR PC, =OSIntCtxSw ;进行任务切换 MENDUndefined ;未定义指令 b UndefinedPrefetchAbort ;取指令中止 b PrefetchAbortDataAbort ;取数据中

12、止 b DataAbortIRQ_Handler HANDLER IRQ_Exception ;中断FIQ_Handler ;快速中断 b FIQ_HandlerTimer0_Handler HANDLER Timer0 ;定时器0中断未定义指令异常、取指令中止异常、取数据中止异常均是死循环,其中原因在上一小节已经说明。而快速中断在本应用中并未使用,所以也设置为死循环。LPC2106使用向量中断控制器,各个 IRQ中断的人口不一样,所以使用了一个宏来简化中断服务程序与C语言的接口编写。由ARM处理器核的文档可知,处理器进入IRQ中断服务程序时(LR4)的值为中断返回地址,为了使任务无论在主动放

13、弃CPU时还是中断时堆栈结构都一样,在这里先把LR减4。其它的部分与C/OS-要求的基本一致。ARM处理核在进入中断服务程序时处理器模式变为IRQ模式,与任务的模式不同,它们的堆栈指针SP也不一样,而寄存器应当保存到用户的堆栈中,为了减少不必要的CPU时间和RAM空间的浪费,本移植仅在必要时将处理器的寄存器保存到用户的堆栈中,其它时候还是保存到IRQ模式的堆栈中。同时,从编译器的函数调用规范可知,C语言函数返回时,寄存器R4R11、SP不会改变,所以只需要保存CPSR、R0R3、R12和返回地址LR,在后面保存 CPSR是为了必要时将寄存器保存到用户堆栈比较方便。在异常处理代码与C语言的接口程

14、序中没有与中断服务子程序流程图中的判断语句对应的语句。判断语句是为了避免在函数OSIntCtxsw()调整堆栈指针,这个调整量是与编译器、编译器选项、C/OS -配置选项都相关的变量。在这里进行这些处理相对其它处理器结构可能增加的处理器时间很少,但对于ARM来说,由于中断(IRQ)有独立的堆栈,在这里这样做就需要把所有寄存器从中断的堆栈拷贝到任务的堆栈,需要花费比较多的额外时间。而变量OSIntNesting为0时,并不一定会进行任务切换,所以本移植没有与之对应的程序,而在函数OSIntCtxsw()中做这一项工作。这样,仅在需要时才处理这些事物,程序效率得以提高。在中断调用后,如果需要任务切

15、换,则变量OSTCBHighRdy和变量OSTCBCur的值不同;如果不需要任务切换这两个变量则相同。本移植通过判断这两个变量来决定是进行任务切换,还是不进行任务切换。通过比较,如果需要任务切换则执行“LDR PC, =OSIntCtxSw”跳转到OSIntCtxSw处进行任务切换;如果不需要任务切换则执行“LDMEQFD SP!, R0-R3, R12, PC”中断返回。这里需要对“MSR CPSR_c, #0x92”说明下,这条指令的作用是关IRQ中断。因为中断(IRQ)模式的LR寄存器在处理器响应中断时用于保存中断返回地址,所以在处理器响应中断时中断(IRQ)模式的LR寄存器不能保存有效

16、数据。而BL指令要用LR寄存器保存BL下一条指令的位置,所以在中断(IRQ)模式时,在BL指令之前必须关中断,在保存LR后才能开中断。4.2.2 Target.c文件的编写为了使系统基本能够工作,必须在进人 main()函数前对系统进行一些基本的初始化工作,这些工作由函数TargetResetInit()完成。void TargetResetInit(void) uint32 i; uint32 *cp1; uint32 *cp2; extern void Vectors(void) ; /* 拷贝向量表,保证在flash和ram中程序均可正确运行 */ cp1 = (uint32 *)Vec

17、tors; cp2 = (uint32 *)0x; for (i = 0; i 2 * 8; i+) *cp2+ = *cp1+; MEMMAP = 0x2;PINSEL0 = (PINSEL0 & 0xFFFF0000) | UART0_PCB_PINSEL_CFG | 0x50;PLLCON = 1; /* 设置系统各部分时钟 */ VPBDIV = 0; PLLCFG =0x23; PLLFEED = 0xaa; PLLFEED = 0x55; while(PLLSTAT & (1 10) = = 0) ; PLLCON = 3; PLLFEED = 0xaa; PLLFEED = 0x

18、55; MAMCR = 2; /* 设置存储器加速模块 */#if Fcclk MAMTIM = 1;#else#if Fcclk MAMTIM = 2;#else MAMTIM = 3;#endif#endif首先向量表拷贝到RAM底部,加上这部分是为了代码无论从Flash基地址开始编译还是从RAM基地址开始编译程序均运行正确。而把RAM底部映射到向量表“MEMMAP = 0x2”也是为了同一个目的。至于复制16个字而不是8个字,是因为后8个字存储跳转的地址是通过 PC指针间接寻址的,它们与对应指令(在向量表中)相对位置是不能变化的。因为在进入多任务环境前使用了一些外设,部分外设使用了芯片的

19、引脚,而 LPC2106的所有引脚都是多功能的,所以需要设置引脚功能。同时串口也进行了设置。时钟是芯片各部分正常工作的基础,虽然时钟可以在任何时候设置,但为了避免混乱,最好在进入 main()函数前设置。程序首先使能PLL但不连接PLL,然后设置外设时钟(VPB时钟pclk)与系统时钟(cclk)的分频比。接着设置PLL的乘因子和除因子。设置完成后,使用“PLLFEED = 0xaa; PLLFEED = 0x55;”的访问序列把数据正确写人硬件,并等待PLL跟踪完成。最后,使能PLL,并使PLL联上系统。本应用外接的晶振频率(Fosc)为11.0592MHz,倍增器的值M=4,所以处理器时钟

20、(Fcclk)为44.2368 MHz。为了使电流控制振荡器频率(Fcco)满足156-320MHz,所以分频器的值P=2,使得Fcco= Fcclk2P=176.9472 MHz。取VPB分频器的分频值为1/4,所以外设时钟(Fpclk)= Fcclk/4=11.0592 MHz,则记数周期为0.09042s,定时0.2ms,则记数值为2212个,这些时钟的定义都在config.h文件中。用户程序最终是要在Flash中运行的,而系统复位时Flash是以最低速度运行,这对发挥芯片的性能极其不利。虽然存储器加速模块可以在任何时候设置,但为了避免混乱,最好在进入 main()函数前设置。首先使存储

21、器加速模块全速工作,然后根据系统主时钟利用条件编译将Flash的访问时钟设置到合适的值。4.2.3 Init.s文件的编写由于LPC2106微控制器的存储系统比较简单,所以系统初始化代码也比较简单,代码如下:Reset BL InitStack ;初始化堆栈 BL TargetResetInit ;目标板基本初始化B _main ;跳转到c语言入口在芯片复位在芯片复位时程序会跳转到标号Reset处,程序首先调用Initstack初始化各种模式的堆栈,然后调用TargetResetlnit对系统进行基本初始化,最后跳转到ADS提供的启动代码_main。main是 ADS提供的启动代码起始位置,它初始化库并最终引导CPU进入main函数。类别:Arm | | 添加到搜藏 | 分享到i贴吧 | 浏览(428) | 评论(0) 上一篇:pic单片机键盘程序下一篇:LPC系列 ARM7 startup.s 启动代.

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!