在 LPC2148 ARM 处理器上创建中断向量的汇编代码 [英] Assembly code for creating interrupts vector on LPC2148 ARM processor

查看:23
本文介绍了在 LPC2148 ARM 处理器上创建中断向量的汇编代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近才开始使用 LPC2148 ARM 处理器.

我想了解一些有关创建中断向量的汇编代码.

代码如下:

//运行时中断向量//-------------------------向量:b _start//重置 - _startldr pc,_undf//未定义 - _undfldr pc,_swi//SWI - _swildr pc,_pabt//程序中止 - _pabtldr pc,_dabt//数据中止 - _dabtnop//保留ldr pc,[pc,#-0xFF0]//IRQ - 读取 VICldr pc,_fiq//FIQ - _fiq#如果 0//将此组用于生产_undf: .word _reset//未定义 - _reset_swi: .word _reset//SWI - _reset_pabt: .word _reset//程序中止 - _reset_dabt: .word _reset//数据中止 - _reset_irq: .word _reset//IRQ - _reset_fiq: .word _reset//FIQ - _reset#别的//使用该组进行开发_undf: .word __undf//未定义_swi: .word __swi//SWI_pabt: .word __pabt//程序中止_dabt: .word __dabt//数据中止_irq: .word __irq//IRQ_fiq: .word __fiq//FIQ__undf: b .//不明确的__swi: b .//SWI__pabt: b .//程序中止__dabt: b .//数据中止__irq: b .//中断请求__fiq: b .//FIQ#万一.size _boot, .- _boot.endfunc

我完全不明白这里发生了什么.如果有人可以向我解释这个过程,尤其是这里如何使用 ldr 指令,我将不胜感激.

塔尔

解决方案

我将删除条件代码,因为它只会使事情复杂化:

//运行时中断向量//-------------------------向量:b _start//重置 - _startldr pc,_undf//未定义 - _undfldr pc,_swi//SWI - _swildr pc,_pabt//程序中止 - _pabtldr pc,_dabt//数据中止 - _dabtnop//保留ldr pc,[pc,#-0xFF0]//IRQ - 读取 VICldr pc,_fiq//FIQ - _fiq_undf: .word __undf//未定义_swi: .word __swi//SWI_pabt: .word __pabt//程序中止_dabt: .word __dabt//数据中止_irq: .word __irq//IRQ_fiq: .word __fiq//FIQ__undf: b .//不明确的__swi: b .//SWI__pabt: b .//程序中止__dabt: b .//数据中止__irq: b .//中断请求__fiq: b .//FIQ.size _boot, .- _boot.endfunc

让我们先看看重置/启动向量:

b _start

该指令是指向标有_start"的代码的无条件分支(跳转),我在您的代码段中没有看到.基本上它将是初始化堆栈和处理器寄存器的程序集,可能是一些内存区域然后可能跳转到执行大部分初始化的 C 例程.

接下来是执行无效指令时ARM将转到的未定义"向量(如果我的记忆是正确的):

ldr pc, _undf

该指令将_undf"符号处的地址加载到 pc 寄存器(程序计数器"或指令指针).如果我们查看 _undf 变量,它包含由符号 __undf 表示的地址.所以ldr pc, _undf 指令用__undf 的地址加载pc - 跳转到__undf:.>

__undf 处,我们看到:

__undf: b .

那只是到同一个地址的一个分支——一个无限循环(. 符号表示这里"或这个位置").

因此,对于这些向量中的大多数(它们遵循与未定义向量相同的技术),它们只会跳到小的无限循环.您可以使用适合相关向量的代码替换这些标签处的无限循环,但许多项目不会这样做,因为这些向量触发会代表某种严重错误.

最后,最有趣的向量槽是 IRQ 向量:

ldr pc,[pc,#-0xFF0]//IRQ - 读取 VIC

这看起来像 NXP 设备的处理程序.

它使用从与 pc 寄存器相关的内存位置读取的值加载 pc 寄存器.由于在 ARM 架构上,IRQ 向量始终位于地址 0x00000018(我将忽略可以将向量映射到其他地方的实现或使用不同向量模型的 Cortex-M3 等 ARM)并且因为指令流水线对使用PC寄存器值进行寻址的影响,该指令读取的内存位置为0xFFFFF030,即内存地址——在向量中断控制器" (VIC) 中映射 VICVectAddr 寄存器:

 'apparent' 管道偏移有效PC 值影响操作码地址------------- ------------ ------------ ------------0x00000018 + 0x00000008 - 0x0000ff0 == 0xfffff030

该设备寄存器将包含刚刚发生的中断的中断处理程序的地址(当然,VIC 需要正确初始化,以便知道该地址).

所以当 ldr pc,[pc,#-0xFF0] 指令执行时,它会加载 pc 寄存器和中断处理程序的地址.适当的设备(基本上,跳转到正确的中断处理程序).

I have just recently started to work with LPC2148 ARM processor.

I am trying to understand some assembly code regarding the creation of the interrupts vector.

here is the code:

// Runtime Interrupt Vectors
// -------------------------
Vectors:
        b     _start                    // reset - _start
        ldr   pc,_undf                  // undefined - _undf
        ldr   pc,_swi                   // SWI - _swi
        ldr   pc,_pabt                  // program abort - _pabt
        ldr   pc,_dabt                  // data abort - _dabt
        nop                             // reserved
        ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC
        ldr   pc,_fiq                   // FIQ - _fiq

#if 0
// Use this group for production
_undf:  .word _reset                    // undefined - _reset
_swi:   .word _reset                    // SWI - _reset
_pabt:  .word _reset                    // program abort - _reset
_dabt:  .word _reset                    // data abort - _reset
_irq:   .word _reset                    // IRQ - _reset
_fiq:   .word _reset                    // FIQ - _reset

#else
// Use this group for development
_undf:  .word __undf                    // undefined
_swi:   .word __swi                     // SWI
_pabt:  .word __pabt                    // program abort
_dabt:  .word __dabt                    // data abort
_irq:   .word __irq                     // IRQ
_fiq:   .word __fiq                     // FIQ

__undf: b     .                         // undefined
__swi:  b     .                         // SWI
__pabt: b     .                         // program abort
__dabt: b     .                         // data abort
__irq:  b     .                         // IRQ
__fiq:  b     .                         // FIQ
#endif
        .size _boot, . - _boot
        .endfunc

I dont understand what is going on here at all. If someone could explain to me the process, especially how the ldr instruction is used here, i would appreciate it.

Tal

解决方案

I'm going to remove the conditional code, since it just complicates things:

// Runtime Interrupt Vectors
// -------------------------
Vectors:
        b     _start                    // reset - _start
        ldr   pc,_undf                  // undefined - _undf
        ldr   pc,_swi                   // SWI - _swi
        ldr   pc,_pabt                  // program abort - _pabt
        ldr   pc,_dabt                  // data abort - _dabt
        nop                             // reserved
        ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC
        ldr   pc,_fiq                   // FIQ - _fiq

_undf:  .word __undf                    // undefined
_swi:   .word __swi                     // SWI
_pabt:  .word __pabt                    // program abort
_dabt:  .word __dabt                    // data abort
_irq:   .word __irq                     // IRQ
_fiq:   .word __fiq                     // FIQ

__undf: b     .                         // undefined
__swi:  b     .                         // SWI
__pabt: b     .                         // program abort
__dabt: b     .                         // data abort
__irq:  b     .                         // IRQ
__fiq:  b     .                         // FIQ

        .size _boot, . - _boot
        .endfunc

Lets look first at the reset/start vector:

b   _start

That instruction is an unconditional branch (a jump) to the the code labeled "_start" which I don't see in your snippet. Basically it'll be the assembly that initializes the stack and processor registers, maybe some memory areas then probably jumps to a C routine that performs the bulk of the initialization.

Next is the "undefined" vector that the ARM will go to when an invalid instruction is executed (if my memory is right):

ldr pc, _undf

That instruction loads the pc register (the 'program counter' or instruction pointer) with the address at the "_undf" symbol. If we look at the _undf variable, it contains the address represented by symbol __undf. So the ldr pc, _undf instruction loads pc with __undf's address - jumping to __undf:.

And at __undf we see:

__undf: b     .  

That's just a branch to the same address - an infinite loop (the . symbol means 'here' or 'this location').

So for most of these vectors (which follow the same technique as the undefined vector), they'll just jump to little infinite loops. You could replace the infinite loops at those labels with code that's appropriate for the vector in question, though many projects don't because those vectors firing would represent some sort of serious error.

Finally, the vector slot that's most interesting is the IRQ vector:

ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC

This looks like the handler for an NXP device.

It loads the pc register with the value read from a memory location that's relative to the pc register. Since on the ARM architecture the IRQ vector is always at address 0x00000018 (I'm going to ignore implementations that can map the vectors elsewhere or ARMs like the Cortex-M3 that use a different vector model) and because of the instruction pipeline's effect on using the PC register value for addressing, the memory location that will be read by this instruction will be 0xFFFFF030, which is the address of the memory-mapped VICVectAddr register in the 'Vectored Interrupt Controller` (VIC):

 'apparent'      Pipeline      offset in      effective
  PC value        effect       the opcode      address
-------------   ------------   -----------    ----------
  0x00000018  +  0x00000008  -  0x0000ff0  == 0xfffff030

This device register will contain the address of the interrupt handler for the interrupt that just occurred (of course the VIC needs to be properly initialized so it knows that address).

So when the ldr pc,[pc,#-0xFF0] instruction executes, it'll load the pc register with the address of the interrupt handler routine for the appropriate device (basically, jumping to the right interrupt handler).

这篇关于在 LPC2148 ARM 处理器上创建中断向量的汇编代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆