原创 ARM7启动代码的分析与设计(转)

2009-9-13 21:33 2692 3 4 分类: MCU/ 嵌入式

ARM7启动代码的分析与设计(转)

感觉写的比较好,忍不住转过来。

引言

  随着生活水平的提高和IT技术的进步,8位处理器的处理能力已经不能满足嵌入式系统的需要了;而 16位处理器在性能和成本上都没有很大的突破。并且在8位机的开发中,大多使用汇编语言来编写用户程序。这使得程序的可维护性、易移植性等都受到了极大的挑战。正是基于此,ARM公司适时的推出了一系列的32位嵌入式微控制器。目前广泛使用的是ARM7和ARM9系,ARM7TDMI内核的ARM7处理器广泛应用于工业控制、仪器仪表、汽车电子、通讯、消费电子等嵌入式设备。本文主要以NXP公司ARM7TDMI核的LPC2119为例来分析如何编写ARM7的启动代码。


  1、启动代码


  在嵌入式系统软件的开发中,应用程序通常是在嵌入式操作系统的开发平台上采用C语言编写的。然而,在ARM系统上电复位后,需要设置中断向量表、初始化各模式堆栈、设置系统时钟频率等,而这些过程都是针对ARM内部寄存器结构的操作,用C语言编程是很难实现的。因此在转到应用程序的c/c++编写之前,需要用ARM的汇编语言编写启动代码,由启动代码完成系统初始化以及跳转到用户C程序。在ARM设计开发中,启动代码的编写是一个极重要的过程。然而启动代码随具体的目标系统和开发系统有所区别,但通常包含以下部分:


  ·向量表定义


  ·地址重映射及中断向量表的转移


  ·堆栈初始化


  ·设置系统时钟频率


  ·中断寄存器的初始化


  ·进入C应用程序


  下面就结合PHILIPS的LPC2119的启动代码来分析与说明ARM7处理器的启动代码的编写。


  1.1向量表定义


  ARM芯片上电或复位后,系统进入管理模式、ARM状态、PC(R15)指向0x00000000 地址处。中断向量表为每一个中断设置1个字的存储空间,存放一条跳转指令,通过这条指令使PC指针指向相应的中断服务程序入口,继而执行相应的中断处理程序。LPC2219的中断向量表和其它基于ARM核的芯片中断向量表较类似,只要注意LPC2219要使向量表所有数据32位累加和为零 (0x00000000-0x0000001C的8个字的机器码累加), 才能使用户的程序脱机运行。

  1.2 地址重映射及中断向量表的转移


  ARM7处理器在复位后从地址0读取第一条指令并执行,因此系统上电后地址0必须是非易失的 ROM/FLASH,这样才能保证处理器有正确可用的指令。为了加快对中断的处理以及实现在不同操作系统模式下对中断的处理,这就需要重新映射中断向量表、Bootblock和SRAM空间的一小部分。ARM具有非常灵活的存储器地址分配特性。ARM处理器的地址重映射机制有两种情况:


  ①由专门的寄存器完成重映射(Remap),只需对相应的Remap寄存器相应位设置即可。


  ②没有专门的Remap控制寄存器需要重新改写用于控制存储器起始地址的块(Bank)寄存器来实现Remap。在LPC2119上的重映射,可以通过存储器映射控制器来实现。实现REMAP操作的程序实现如下:


  MOV R8,#0x40000000;            /设置新向量表起始地址/


  LDR R9,=Interrupt_Vector_Table;             /读原向量表源地址/


  LDMIA R9!,(R0-R7);               /复制中断向量表及中断处理程序的入口地址到RAM中(64字节)/


  STMIA R8!,(R0-R7)


  LDMIA R9!,(R0-R7)


  STMIA R8!,(R0-R7)


  LDR R8,=MEMMAP ;           /REMMAP操作/


  MOV R9,#0x02


  STR R9, [R8]


  1.3 堆栈初始化


  启动代码中各模式堆栈空间的设置是为中断处理和程序跳转时服务的。当系统响应中断或程序跳转时,需要将当前处理器的状态和部分重要参数保存在一段存储空间中,所以对每个模式都要进行堆栈初始化工作,给每个模式的SP定义一个堆栈基地址和堆栈的容量。堆栈的初始化有两种方法:第一种方法是结合ADS开发套件中的分散加载文件来定义堆栈。第二种方法是最简单也是最常用的一种就是直接进入对应的处理器模式,为SP寄存器指定相应的值。下面给出了用第二种方法初始化管理模式和中断模式堆栈的程序:


  MSR CPSR_c, #0xD3 ;           /切换到管理模式,并初始化管理模式的堆栈/


  LDR SP, Stack_Svc


  MSR CPSR_c, #0xD2 ;            /切换到IRQ模式,并初始化IRQ模式的堆栈/


  LDR SP, Stack_Irq


  …


  1.4 系统部分时钟初始化


  时钟是芯片各部分正常工作的基础,应该在进入main()函数前设置。部分ARM7片子内部集成有PLL(锁相环)电路,用户可以用低频率的晶振通过PLL电路获得一个较高频率的时钟。LPC2119内部的PLL电路接受的输入时钟频率范围为10~25MHz,输入频率通过一个电流控制振荡器(CCO)倍增到范围10~60MHz。同时为了使高速的ARM处理器与低速的外设正常通讯和降低功耗(降低外设运行速度使功耗降低),LPC2119又集成了一个额外的分频器。PLL的激活是由PLLCON寄存器控制。PLL倍频器和分频器的值由PLLCFG寄存器控制。对PLLCON或PLLCFG寄存器的更改必须遵循严格的顺序,否则所作更改是无法生效的(在连续的VPB周期内向PLLFEED寄存器写入0xAA、0x55,在此期间中断必须是被禁止的。)


  1.5 中断初始化


  ARM7的向量中断控制器(Vectored Interrupt Controller)可以将中断编程为3类:FIQ、向量IRQ、非向量IRQ。FIQ中断请求的优先级最高,其次是IRQ中断请求,非向量IRQ的优先级最低。VIC具有32个中断请求输入,但在LPC2219中只占用了17个中断输入。对于这17个中断源的IRQ/FIQ选择,由 VICIntSelect寄存器控制,当对应位设置位1时,则此中断为FIQ中断,否则为IRQ中断。若再将IRQ中断设置到向量控制寄存器 (VICVectCntIn)中,则此中断为向量IRQ中断,否则为非向量IRQ中断。FIQ中断是专门用来处理那些需要及时响应的特殊事件,尽可能地只给FIQ分配一个中断源。


  1.6 进入C应用程序


  至此,系统各部分的初始化基本完成,可以直接从启动代码转入到应用程序的main()函数入口。从启动代码转入到应用程序的实例代码如下:


  IMPORT main


  LDR R0,=main


  BX R0


  2、总结


  一个优秀的启动代码将给应用程序的开发提供一个良好的开发平台。本文中较详细的讨论了启动代码的编写及难点。其中在堆栈初始化过程中要特别的注意两点:


  ①要尽量给堆栈分配快速和高带宽的存储器。


  ②尽量避免过早将处理器切换到用户模式,一般在系统初始化的最后阶段才切换到用户模式(用户模式没有权限通过修改CPSR来进行模式切换)。


  嵌入式系统的迅猛发展,使启动代码的编写成为嵌入式系统开发人员应该具备的能力。本文有助于正在从事嵌入式ARM开发的读者理解启动代码的内涵与编写出适合自己的启动代码。

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户228595 2009-12-15 15:53

万分感谢,你的学习心得。以及无私的奉献学习的源代码。 通过研究你的学习笔记,着实让我受益匪浅,参考书中的解析,太过啰嗦,而且,让广大读者找不着北,不能准确的把握重点知识。而你的笔记,却简明易了,有听君一席话,胜读十年书的感觉。。

用户1156182 2009-10-27 10:40

数码管和中断部分都测试过,都没有问题,估计是can通信的问题,但是又不知道如何查找,请指点,谢谢!

用户1156182 2009-10-26 09:11

按照你的程序自检了,不过运行初正常显示0000,当按下按键后,只有最后一位显示8,其余无任何显示,搞不懂怎么回事,能指点一下吗?不胜感激!

用户188034 2009-9-13 23:03

分析得不错
相关推荐阅读
用户226863 2011-04-05 15:45
基于状态机的单片机按键扫描程序
 硬件连接很简单,四个独立按键分别接在P3^0------P3^3四个I/O上面。 因为51单片机I/O口内部结构的限制,在读取外部引脚状态的时候,需要向端口写1.在51单片机复位后,不需要进行此操作...
用户226863 2010-04-06 21:28
I帧、P帧和B帧的特点
I帧:帧内编码帧I帧特点:1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;2.解码时仅用I帧的数据就可重构完整图像;3.I帧描述了图像背景和运动主体的详情;4.I帧不需要参考其...
用户226863 2009-09-13 21:40
H.264简介
1 H.264简介H.264是ITU-T和ISO/IEC联合制定的最新编码标准,它最先由ITU-T于1997年提出,目标是提出一种更高性能(相对于当时的H.263)的视频编码标准。相对于其它标准,H....
用户226863 2009-08-02 12:54
ARM启动代码分析
ARM启动代码分析 收藏 理解启动代码(ADS) 所谓启动代码,就是处理器在启动的时候执行的一段代码,主要任务是初始化处理器模式,设置堆栈,初始化变量等等.由于以上的操作均与处理器体系结构和系统配置密...
用户226863 2009-06-08 22:48
avr的IO
每个IO口属性由DDRX,PORTX,PINX三个寄存器的对应位来控制,分别是方向,为端口赋值,读取引脚。SFIOR寄存器的PUD位用来禁止所有IO口的上拉电阻。在PUD没有被禁止的情况下,通过DDR...
EE直播间
更多
我要评论
1
3
关闭 站长推荐上一条 /3 下一条