【php精品源码栏目提醒】:网学会员在php精品源码频道为大家收集整理了“【精品】ARM启动代码详细注释 - 网络与通信“提供大家参考,希望对大家有所帮助!
ARM 启动代码详细注释 syd168 2009-07-232410Init.s 包括了板子上电后的初始化过程,具体有以下几个步骤:1. 屏蔽所有中断,关看门狗。
2. 根据工作频率设置 PLL 寄存器3. 初始化存储控制相关寄存器4. 初始化各模式下的栈指针5. 设置缺省中断处理函数6. 将数据段拷贝到 RAM 中,将零初始化数据段清零7. 跳转到 C 语言 Main 入口函数中 NAME: 2410INIT.S DESC: C start up codes Configure memory ISR stacks Initialize C-variables HISTORY: 2002.02.25:kwtark: ver 0.0 2002.03.20:purnnamu: Add some functions for testing STOPPOWER_OFF mode 2002.04.10:SJS:sub interrupt disable 0x3ff -gt 0x7ff GET option.s GET 相当 INCLUDE 将一个源文件包含到当前源文件,这里表示包含 option.s,并在当前位置进行汇编 GET memcfg.s GET 2410addr.sBIT_SELFREFRESH EQU 1ltlt22 SDRAM/DRAM 刷新控制器 bit22 REFMD 位 0:CBR/AUTO REFRESH 1:SHIF REFRESH 下面是对 arm 处理器模式寄存器对应值的常数定义,arm 处理器中有一个 CPSR 程序状态寄存器,后五位决定目前的处理器模式。
Pre-defined constants PSR 模式位USERMODE EQU 0x10 用户模式FIQMODE EQU 0x11 FIQ 快速中断模式IRQMODE EQU 0x12 中断模式SVCMODE EQU 0x13 超级用户模式ABORTMODE EQU 0x17 中止模式UNDEFMODE EQU 0x1b 未定义指令模式MODEMASK EQU 0x1f 系统模式NOINT EQU 0xc0 禁止 IRQ 和 FIQ 中断定义各模式堆栈地址 _STACK_BASEADDRESS 在 option.s 中 _STACK_BASEADDRESS EQU SDRAM_END-0x8000 0x33ff8000UserStack EQU _STACK_BASEADDRESS-0x3800 0x33ff4800 用户模式堆栈SVCStack EQU _STACK_BASEADDRESS-0x2800 0x33ff5800 0x3ff47ff 超级用户模式堆栈 4kUndefStack EQU _STACK_BASEADDRESS-0x2400 0x33ff5c00 0x3ff57ff 未定义指令模式堆栈 1kAbortStack EQU _STACK_BASEADDRESS-0x2000 0x33ff6000 0x3ff5bff 中止模式堆栈 1kIRQStack EQU _STACK_BASEADDRESS-0x1000 0x33ff7000 0x3ff5fff 中断模式堆栈 4kFIQStack EQU _STACK_BASEADDRESS-0x0 0x33ff8000 0x33ff6fff 快速中断模式堆栈 4k arm 处理器有两种工作状态 1.arm:32 位 这种工作状态下执行字对齐的 arm 指令 2.Thumb:16 位 这种工作状态执行半字对齐的 Thumb 指令 因为处理器分为 16 位 32 位两种工作状态 程序的编译器也是分 16 位和 32 两种编译方式 所以下面的程序用于根据处理器工作状态确定编译器编译方式 code16 伪指令指示汇编编译器,后面的指令为 16 位的 thumb 指令 code32 伪指令指示汇编编译器,后面的指令为 32 位的 arm 指令 这段是为了统一目前的处理器工作状态和软件编译方式(16 位编译环境使用 tasm.exe 编译)Check if tasm.exearmasm -16 ...ADS 1.0 is used. 检查是否是用 tasm.exe 进行 16 位编译 GBLL THUMBCODE 声明一个全局变量 并初始化为FALSE CONFIG 16 if config16 这里表示用 16 位编译方式THUMBCODE SETL TRUE SETL 给全局变量赋值 ,设置 THUMBCODE 为 true CODE32 转入 32 位编译模式 等同 ELSETHUMBCODE SETL FALSE 设置 THUMBCODE 为 false 等同 ENDIF MACRO MACRO 定义宏 MOV_PC_LR 宏名 MOV_PC_LR THUMBCODE if THUMBCODEtrue bx lr THUMBCODE 模式上返回 ARM 状态 else mov pclr ARM 状态下返回 end if MEND 宏结束 MACRO 宏定义开始 MOVEQ_PC_LR 宏名为 MOVEQ_PC_LR THUMBCODE if THUMBCODEtrue bxeq lr EQ 相等 则跳转回 ARM 状态 else moveq pclr end if MEND 宏结束注意下面这段程序是个宏定义下面包含的 HandlerXXX HANDLER HandleXXX 将都被下面这段程序展开这段程序用于把中断服务程序的首地址装载到 pc 中,有人称之为“加载程序”。
本初始化程序定义了一个数据区(在文件最后),34 个字空间,存放相应中断服务程序的首地址。
每个字,即 4 字节空间都有一个标号,以 Handle命名。
在向量中断模式下使用“加载程序”来执行中断服务程序。
这里就必须讲一下向量中断模式和非向量中断模式的概念 系统自动读取对应于该中断源确定地址上的指令取代 0x18 处的指令,向量中断模式是当 cpu 读取位于 0x18 处的 IRQ 中断指令的时候,通过跳转指令系统就直接跳转到对应地址函数中 节省了中断处理时间提高了中断处理速度标 例如 ADC 中断的向量地址为 0xC0则在 0xC0 处放如下代码:ldr PCHandlerADC 当 ADC 中断产生的时候系统会自动跳转到 HandlerADC 函数中非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将 interrupt pending 寄存器中对应标志位置位然后跳转到位于 0x18 处的统一中断函数中该函数通过读取 interrupt pending 寄存器中对应标志位来判断中断源,并根据优先级关系再跳到对应中断源的处理代码中大致作用是把宏的第一个参数HandlerLabel 转变为一个标号,然后让程序跳转到第二个参数HandleLabel为一个地址对应的值的地址去。
下面一句一句分析一下,为了便于分析,假设 sp 0x33ff8000,HandleLabel 0x33ffff00 0x33ffff00 0x10000000,r0 0x56001234:HandlerLabel HANDLER HandleLabel 说明宏名字叫 HANDLER 有一个参数HandlerLabel ,它定义了一个标号sub spsp4 把栈顶指针减 4,留出一个字的空间(用于保存跳转地址的值)sp0x33ff7ffcstmfd spr0 首先把 sp 减 4 sp0x33ff7ff8,然后把将要使用的 r0 入栈,此时0x33ff7ff80x56001234ldr r0HandleLabel 给寄存器 r0 赋值,r00x33ffff00ldr r0r0 给寄存器 r0 赋值,r00x10000000str r0sp4 把寄存器 r0 保存到 0x33ff7ffc sp0x33ff7ff84,此时 0x33ff7ffc 0x10000000ldmfd spr0pc 把栈顶的两个字弹出,分别保存到 r0、pc,此时 sp0x33ff8000,r00x56001234,pc0x10000000 ,通过比 较不难发现,sp 和 r0 在执行前后都没有变化,程序就跳转到 0x10000000 处执行所以,通过上面的分析可以看出,HandlerLabel HANDLER HandleLabel 是让 PC 跳转到HandleLabel 中存放的地址执行。
MACRO 宏定义HandlerLabel HANDLER HandleLabel HandlerLabel 行号 展开时可替换成相应的符号 HANDLER 宏名 HandleLabel 宏的形参HandlerLabel 展开时可替换成相应的符号 sub spsp4 sp-sp-4空出的空间用于存放跳转地址 假如 sp 原来为 0x100,则现在 sp 为 0x96 stmfd spr0 spsp-4并将 r0 入栈,现在 sp0x92 r0 存入 0x96 ldr r0HandleLabel 获取存放跳转地址的标号 HandleLabel 到 r0假如 HandleLabel 为 0x1000,则现在 r0 为 0x1000 ldr r0r0 将 HandleLabel 中存放的跳转地址送给 r0,r0 为 0x1000 中的值,假如为 0x3000 str r0sp4 将 r0 存放到 sp4 的地方, ldmfd spr0pc 将中断函数首地址出栈,放入程序指针中,系统将跳转到对应中断处理函数 MEND 宏定义结束一个 ARM 由 RORWZI 三个段组成,其中 RO只读为代码段,RW读写是已经初始化的全局变量,ZI 是未初始化的全局变量对应于 GNU 工具的概念是 TEXT,DATA,BSSbootloader 要将 RW 段复制到 RAM 中,并将 ZI 段清零 编译器使用下列方式来记录各段的起始和结束地址 ImageROBase RO 段起始地址 ImageROLimit RO 段结束地址加 1 ImageRWBase
上一篇:
【精品】面向对象
下一篇:
试论建设企业信息化提升企业竞争力