【vc++精品源码栏目提醒】:本文主要为网学会员提供“【精品】LPC21xx启动代码的分析 - 大学课件”,希望对需要【精品】LPC21xx启动代码的分析 - 大学课件网友有所帮助,学习一下!
LPC21xx 启动代码的分析 注:下文中红色标记的部分是源码,黑色部分是解释文字 让我们从头开始……………… 以下定义了几个常数,这些常数定义了五种模式下堆栈的大小以及各种模式对应的状态字,所谓的状态字是 CPSR 寄存器的低 5 位,处理器根据该值确定状态或者切换状态。
每种模式都对应独立的堆栈SVC_STACK_LEGTH EQU 0FIQ_STACK_LEGTH EQU 0IRQ_STACK_LEGTH EQU 256ABT_STACK_LEGTH EQU 0UND_STACK_LEGTH EQU 0定义向量中断 IRQ 以及快速中断掩码CPSR 寄存器结构: N Z C V…………I F T M4 M3 M2 M1 M0NoInt EQU 0x80 X X X X…………1 0 X X X X X XNoFIQ EQU 0x40 X X X X…………0 1 X X X X X X定义各种工作模式的状态字CPSR 寄存器结构: N Z C V…………I F T M4 M3 M2 M1 M0USR32Mode EQU 0x10 X X X X…………X X X 1 0 0 0 0SVC32Mode EQU 0x13 X X X X…………X X X 1 0 0 1 1SYS32Mode EQU 0x1f X X X X…………X X X 1 1 1 1 1IRQ32Mode EQU 0x12FIQ32Mode EQU 0x11上面几行代码,不用过多分析 定义几个符号而已 把 EQU 想像成 C 中的define 就可以了.具体定义的数值,下面的代码用到我再解释.IMPORT __use_no_semihosting_swi上面这一句的作用是在代码中禁用 semihosting 机制. 到底什么是 semihostiong 这里不多说网上有很多. 这里只说明 Semihosting 主要用来调试 在 release 版本的代码中一般是要禁用的.IMPORT FIQ_ExceptionIMPORT __mainIMPORT TargetResetInit上面三行是把要引入的外部标号声明一下,以便下面使用,这些标号可以是其他 C 文件里的,也可以是其他的汇编文件里的。
EXPORT bottom_of_heapEXPORT StackUsrEXPORT ResetEXPORT __user_initial_stackheap上面四行是把本文件里面的函数或者变量输出为外部标号,给其他文件里程序使用。
AREA vectorsCODEREADONLY ENTRY 上面这一行声明汇编文件的入口 整个文件是从这里开始执行的,一个文件里可以有多个 ENTRY,该标号只是表示这是该程序段的入口,至于哪个 ENTRY 作为整个程序的入口,应该在程序编译的时候指定。
每个入口都有一个名字,改名字可以是任意合法的字符串。
Reset LDR PC ResetAddr LDR PC UndefinedAddr LDR PC SWI_Addr LDR PC PrefetchAddr LDR PC DataAbortAddr DCD 0xb9205f80 该处放置确定数字,不必改动 LDR PC PC -0xff0 LDR PC FIQ_Addr 上面几行是配置中断向量表. 中断向量表的顺序是不能变的因为这是 ARM7 规定的,可以参考相关书籍. 这里有几个问题要说明一下. 第一 关于 DCD 0xb9205f80 按照 ARM7 的中断向量表分布图 这个位置是个保留位. nxp 系列的 lpc21xxlpc22xx 片子要求中断向量表中所有数据 32 位累加和为 0,否则程序不能脱机运行。
第二 关于 LDR PC PC -0xff0,这里本应该放 IRQ 中断的,该指令向量中断地址寄存器的地址(这个问题可以放在中断部分解决)。
注:ARM7 的三级流水线结构导致了 PC 指向的是当前指令的后 8 个字节. 本来 IRQ 是应该放在 0x00000018 处的. LDR PC PC -0xff0这条语句执行后 PC 的当前值就是0x000000188-0xff0. 很容易计算出它的结果是 0xfffff030. 看一下 lpc22xx 的手册就知道.这个地址就是 VICVectAddr. 也就是说本来这个地址是应该放 IRQ 服务程序的入口地址的但是这个地址被放在了 VICVectAddr 这个寄存器里. 英文手册里有一段对 VICVectAddr 描述. 看了之后就容易明白是怎么回事了: Vector Address Register. When an IRQ interruptoccurs the IRQ service routine can read this register and jump to the value readResetAddr DCD ResetInitUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortDataAbortAddr DCD DataAbortNouse DCD 0IRQ_Addr DCD 0FIQ_Addr DCD FIQ_Handler 这几行是为上面中断向量表中的中断标号分配内存空间 也就是它们的执行地址.