众所周知,对于X86架构:按下电源按钮后,机器开始执行0xFFFFFFF0处的代码,然后它开始在BIOS中执行代码以进行硬件初始化。 BIOS执行后,它使用bootloader将操作系统映像加载到内存中。最后,操作系统代码开始运行。 对于ARM体系结构,使用后的启动过程按电源按钮是什么? 谢谢!
答案 0 :(得分:59)
目前,ARM架构中有两种异常模型(重置被视为一种例外):
经典型号,用于预Cortex芯片和当前的Cortex-A / R芯片。其中,0处的内存包含几个异常处理程序:
Offset Handler
===============
00 Reset
04 Undefined Instruction
08 Supervisor Call (SVC)
0C Prefetch Abort
10 Data Abort
14 (Reserved)
18 Interrupt (IRQ)
1C Fast Interrupt (FIQ)
当异常发生时,处理器只是从特定的偏移开始执行,因此通常这个表在代码中包含对完整处理程序的单指令分支。典型的经典矢量表如下所示:
00000000 LDR PC, =Reset
00000004 LDR PC, =Undef
00000008 LDR PC, =SVC
0000000C LDR PC, =PrefAbort
00000010 LDR PC, =DataAbort
00000014 NOP
00000018 LDR PC, =IRQ
0000001C LDR PC, =FIQ
在运行时,向量表可以重定位到0xFFFF0000,这通常被实现为紧密耦合的内存范围,以实现最快的异常处理。但是,上电复位通常从0x00000000开始(但有些芯片可以通过处理器引脚设置为0xFFFF0000)。
新的微控制器模型用于Cortex-M系列芯片。在那里,0处的向量表实际上是向量(指针)的表,而不是指令。第一个条目包含SP寄存器的启动值,第二个条目包含复位向量。这允许直接在C中写入重置处理程序,因为处理器设置堆栈。同样,该表可以在运行时重新定位。 Cortex-M的典型向量表如下所示:
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
[...more vectors...]
请注意,在现代复杂芯片(如OMAP3或Apple A4)中,执行的第一段代码通常不是用户代码,而是片上Boot ROM。它可以检查各种条件以确定从何处加载用户代码以及是否加载它(例如,它可能需要有效的数字签名)。在这种情况下,用户代码可能必须符合不同的启动约定。
答案 1 :(得分:3)
电源接通后cpu将开始执行异常模式第一个复位,因为复位必须作为监控模式运行,因为CPU在执行时无法知道寄存器的状态,因此无法进入监控器模式。要实现这个小代码需要编写(见末尾)。在此之后,可以通过将地址加载到PC来处理其他异常。
.globl _start
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
reset:
mrs r0,cpsr /* set the cpu to SVC32 mode */
bic r0,r0,#0x1f /* (superviser mode, M=10011) */
orr r0,r0,#0x13
msr cpsr,r0
答案 2 :(得分:3)
...最后,操作系统代码开始运行。对于ARM体系结构,使用后的启动过程是什么?按电源按钮?
这个答案主要是在上下文或现代Cortex-A CPU中;有各种各样的ARM平台。但是,对于像PC这样的ARM(平板电脑,手机等)......
ARM CPU将从0x0或0xffff0000获取指令(对于Cortex-M,它是数据而不是指令)。典型的ARM SOC有一些使用这种机制的启动ROM。对于最终用户,您需要查阅手册以确定如何运行代码。即,许多使用该向量的ARM SOC内置了 BIOS ,但您需要使用不同的东西来运行代码。
通常,ARM SOC将支持多个引导设备。该设备由某些FUSE(由制造工具设置)或采样引脚确定。引脚将在正在运行的系统中作为CPU输出,但已上拉/下拉以配置引导设备。每个启动设备都有特殊的细节; ROM很简单,但NAND闪存,SPI闪存,MMC等需要一些配置细节。这些通常也由片上FUSE和/或采样引脚提供。可以读取设备的一小部分以进一步配置设备。
对于深度嵌入式ARM芯片,它只能从板载闪存启动,这个过程要简单得多;但我相信你提到更先进的ARM CPU的问题。更高级的ARM系统具有引导加载程序。这是因为ROM加载器将加载的代码量通常是有限的和/或受限制的。设置SDRAM通常也很复杂,并且引导加载程序可以构造为从配置SDRAM的内部静态RAM运行。
运行操作系统有其特有的问题。对于ARM Linux,它是ATAGS,现在是devicetree。人们可以编写自己的引导加载程序代码,或者使用u-boot中最常见的许多开源项目之一。 U-boots支持vxWorks,Linux,NetBSD,Plan9,OSE,QNX,Integrity和OpenRTOS以及二进制映像。
许多原始ARM Linux设备支持Linux的直接启动而没有启动加载程序。但是,除了一些非常老的ARM SOC /核心之外,Linux在主线上不支持这一点。