ARM bootloader:中断向量表理解

时间:2014-01-23 15:47:07

标签: arm interrupt bootloader

下面的代码是用于定义中断向量表的u-boot的第一部分,我的问题是如何使用每一行。我理解前两行是起点和第一条实现的指令:reset,我们在下面定义reset。但我们什么时候会在下面使用这些说明?根据System.map,每条指令都有一个固定的地址,所以_fiq在0x0000001C,当我们想要执行fiq时,我们会将这个地址复制到pc然后执行,对吧?但是我们可以通过哪种方式跳转到这条指令:ldr pc,_fiq?它是通过硬件还是软件实现的?希望我能让自己理解正确。

>.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  

>_undefined_instruction: .word undefined_instruction  
>_software_interrupt:    .word software_interrupt  
>_prefetch_abort:        .word prefetch_abort  
>_data_abort:            .word data_abort  
>_not_used:              .word not_used  
>_irq:                   .word irq  
>_fiq:                   .word fiq  

2 个答案:

答案 0 :(得分:10)

如果您了解重置,那么您就能理解所有这些。

当处理器复位时,硬件将pc设置为0x0000并通过获取0x0000处的指令开始执行。当执行未定义的指令或尝试执行时,硬件通过将pc设置为0x0004来响应并开始执行0x0004处的指令。 irq中断,硬件完成正在执行的指令开始执行地址0x0018的指令。等等。

00000000 <_start>:
   0:   ea00000d    b   3c <reset>
   4:   e59ff014    ldr pc, [pc, #20]   ; 20 <_undefined_instruction>
   8:   e59ff014    ldr pc, [pc, #20]   ; 24 <_software_interrupt>
   c:   e59ff014    ldr pc, [pc, #20]   ; 28 <_prefetch_abort>
  10:   e59ff014    ldr pc, [pc, #20]   ; 2c <_data_abort>
  14:   e59ff014    ldr pc, [pc, #20]   ; 30 <_not_used>
  18:   e59ff014    ldr pc, [pc, #20]   ; 34 <_irq>
  1c:   e59ff014    ldr pc, [pc, #20]   ; 38 <_fiq>

00000020 <_undefined_instruction>:
  20:   00000000    andeq   r0, r0, r0

00000024 <_software_interrupt>:
  24:   00000000    andeq   r0, r0, r0

00000028 <_prefetch_abort>:
  28:   00000000    andeq   r0, r0, r0

0000002c <_data_abort>:
  2c:   00000000    andeq   r0, r0, r0

00000030 <_not_used>:
  30:   00000000    andeq   r0, r0, r0

00000034 <_irq>:
  34:   00000000    andeq   r0, r0, r0

00000038 <_fiq>:
  38:   00000000    andeq   r0, r0, r0

当然,除了更改电脑和从这些地址开始执行之外。硬件将保存机器状态,必要时切换处理器模式,然后从向量表开始执行新地址。

我们作为程序员的工作是构建二进制文件,以便我们希望为每条指令运行的指令位于正确的地址。硬件为每个位置提供一个字,一条指令。现在,如果您从未期望过任何这些异常,那么您不必在地址零处有一个分支,例如您可以让您的程序启动,这些地址的内存没有任何魔力。如果您希望有这些例外,那么对于一个单词的指令有两种选择,并且可以跳出后面的异常。一个是分支,另一个是负载pc。各有利弊。

答案 1 :(得分:6)

当硬件发生异常时,程序计数器(PC)自动设置为相关异常向量的地址,处理器开始执行该地址的指令。当处理器复位时,PC会自动设置为base+0。未定义的指令将PC设置为base+4等。向量表(base)的基址是0x00000000,0xFFFF0000或VBAR,具体取决于处理器和配置。请注意,这在向量表放置的位置提供了有限的灵活性,您需要查阅ARM文档以及您正在使用的设备的参考手册以获得正确的值。

表的布局(每个异常4个字节)使得必须立即从向量分支到实际的异常处理程序。 LDR PC, label方法的原因是双重的 - 因为使用B将PC相对分支限制为(24 <2)位(+/- 32MB)将限制代码的布局在记忆中有点;通过加载绝对地址,处理程序可以位于内存中的任何位置。其次,通过简单地将不同的地址写入该位置,而不必组装和编写分支指令,可以非常简单地在运行时更改异常处理程序。

以这种方式拥有可重映射的复位向量几乎没有价值,但这就是为什么你倾向于看到一个实现为一个简单的分支,以跳过其余的向量到真正的入口点代码。