ARM引导加载程序:中断向量表理解

ARM引导加载程序:中断向量表理解,arm,interrupt,bootloader,Arm,Interrupt,Bootloader,下面的代码是u-boot定义中断向量表的第一部分,我的问题是如何使用每一行。我理解前两行,这是开始点和第一条要实现的指令:reset,我们在下面定义reset。但是我们什么时候使用下面的说明呢?根据System.map,每个指令都有一个固定地址,所以fiq在0x0000001C,当我们想要执行fiq时,我们会将这个地址复制到pc上然后执行,对吗?但我们可以用哪种方式跳转到这个指令:ldr pc,fiq?它是通过硬件还是软件实现的?希望我能正确地理解自己 >.globl _start &

下面的代码是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  

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


表的布局(每个异常4个字节)需要立即从向量分支到实际的异常处理程序。采用LDR PC,label方法的原因有两方面,因为PC相关分支仅限于(24如果您了解重置,则您了解所有这些分支

当处理器复位时,硬件将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
00000000:
0:ea00000d b 3c
4:e59ff014 ldr pc,[pc,#20];20
8:e59ff014 ldr pc,[pc,#20];24
c:e59ff014 ldr pc,[pc,#20];28
10:e59ff014 ldr pc,[pc,#20];2c
14:e59ff014 ldr pc,[pc,#20];30
18:e59ff014 ldr pc,[pc,#20];34
1c:e59ff014 ldr pc,[pc,#20];38
00000020 :
20:00000000安第克r0,r0,r0
00000024 :
24:00000000安第克r0,r0,r0
00000028 :
28:00000000安第克r0,r0,r0
0000002c:
2c:00000000安第克r0,r0,r0
00000030 :
30:00000000安第克r0,r0,r0
00000034 :
34:00000000安第克r0,r0,r0
00000038 :
38:00000000安第克r0,r0,r0
当然,除了更改pc并从这些地址开始执行外,硬件还将保存机器的状态,必要时切换处理器模式,然后从矢量表的新地址开始执行


作为程序员,我们的工作是构建二进制文件,使我们希望为每个指令运行的指令都位于正确的地址。硬件为每个位置提供一个字,一条指令。现在,如果你从来没有想过会出现这些异常,你不必在地址0处有分支,例如,你可以必须启动您的程序,这些地址的内存没有什么神奇之处。如果您希望出现这些异常,那么您有两种指令选择,一个是一个字,可以跳出随后出现的异常。一个是分支,另一个是加载pc。每种都有优点和缺点。

进一步思考:w首先准备这里的每个中断,然后从“开始”或“重置”计算机开始,这也被定义为中断。然后我们继续重置例行程序。以下中断只是为将来的硬件/软件中断做准备。对吗?
ldr pc,_fiq
翻译为
ldr pc,[pc,#u fiq-offset]
。因此,\u fiq处的单词值被加载到PC中。即,您在地址
\u fiq
处放置一个函数指针。首先,它将为空;稍后人们可以填充它。默认情况下,u-boot中不会启用中断。请参阅:。从我在中看到的向量表0x0处驻留初始SP值,重置时PC是否设置为0x0es处理器解释此值?它总是无效指令吗?您将cortex-m与常规arm内核混淆。常规arm内核与上面类似,它们在异常表中的地址执行指令。cortex-m内核是一个向量表,零向量是堆栈指针的加载值,偏移量4是re重置时设置向量从向量表加载堆栈指针,然后在重置向量地址开始执行