ARM组装 - 基本中断处理

时间:2012-05-18 03:38:34

标签: assembly embedded arm

我目前正在使用lpc2378上的一些ARM Assembler,我写了一个循环来控制炉子的温度;我相信我需要实现某种中断处理来完成我的项目。

当应用程序运行时,它进入循环,等待Button_1输入,然后循环继续并经历各个阶段,但它无法等待Button_2输入以使应用程序运行。

这里有几个问题,中断处理程序究竟是如何工作的?我怎样才能将它实现到我的应用程序中。

这是我的Button_1代码:

;=========================================================================
; Wait for BUT1 to be pressed
;=========================================================================
WaitBUT1
  STMFD r13!,{r0,r5,r14}   ; Push r0, r5 and LR

WaitForBUT1Pressed
    ldr r0, = IO0PIN            ; Address of FIO0PIN register 
    ldr r1, [r0]                ; Read FIO0PIN in to r1
    ands r1, r1, # B1_MASK      ; Mask out BUT1
    beq BUT1Pressed             ; Exit LED toggle loop if button is pressed
    B WaitForBUT1Pressed
BUT1Pressed

  LDMFD r13!,{r0,r5,r14}   ; Pop r0, r5 and LR
  mov pc, r14              ; Put link register back into PC

和我的Button_2代码:

;=========================================================================
; Wait for BUT2 to be pressed
;=========================================================================
WaitBUT2
  STMFD r13!,{r0,r5,r14}   ; Push r0, r5 and LR

WaitForBUT2Pressed
    ldr r0, = IO0PIN            ; Address of FIO0PIN register 
    ldr r1, [r0]                ; Read FIO0PIN in to r1
    ands r1, r1, # B2_MASK      ; Mask out BUT1
    beq BUT2Pressed             ; Exit LED toggle loop if button is pressed
    B WaitForBUT2Pressed
BUT2Pressed

  LDMFD r13!,{r0,r5,r14}   ; Pop r0, r5 and LR
  mov pc, r14              ; Put link register back into PC

以及我的炉控制循环:

LoopStart

   BL WaitBUT1 ; wait until button 1 is pressed
   BL heaterOn ; turn heater on
   BL systemLedOn ; turn system LED on
   BL readTemp ; Check ADC for temp
   BL checkTemp ; Count down, check ADC for temp
   CMP r3, #5 ; Compare timer with delay
   BGT errorVal
   SUBS r4, r2, r7  ;Performs r7 = r4 - r2 and sets condition register
   BEQ LoopStart ; if equal nothing to do
   BGT overTemp ; r7 < 0 case
   BL errorLedOn
   BL heaterOn
   BL FanOff
   B LoopStart

overTemp
   BL errorLedOn
   BL heaterOff
   BL FanOn
   B LoopStart


   BL WaitBUT2
   BL FanOff
   BL errorLedOff
   BL systemLedOff
   BL heaterOff

       B LoopStart

提前致谢。

2 个答案:

答案 0 :(得分:11)

如果您还没有,则需要获取ARM ARM(ARM架构参考手册)。过去只有一个,但现在有很多核心,他们不得不将它拆分为不同的架构。 {@ 3}}左侧是ARM体系结构,然后是参考手册,然后是ARMv5,是的,我知道你有一个ARMv4(ARM7TDMI)。过去的ARMv5手册是手册。

它将涵盖异常向量等。

您可能已经知道在启动时,会执行地址0x00000000处的指令。 对于中断,调用地址0x00000018处的指令。

.globl _start
_start:
    b   reset     ;@ 0x00000000 reset
    b   handler   ;@ 0x00000004 undefined instruction
    b   handler   ;@ 0x00000008 software interrupt swi
    b   handler   ;@ 0x0000000C prefetch abort
    b   handler   ;@ 0x00000010 data abort
    b   handler   ;@ 0x00000014 dont know
    b    irq_handler   ;@ 0x00000018 irq
    b   handler   ;@ 0x000000

从ARM ARM中你还应该看到寄存器被存储,特别是r13堆栈指针,在中断模式下有一个单独的堆栈指针。因此,在启动时,当您设置正常堆栈时,您还需要为中断堆栈设置一些空间。

reset:
;@//mov r0, #(PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD2
msr cpsr_c, r0
ldr sp, =0xD600C000

;@//mov r0, #(PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD3
msr cpsr_c, r0
ldr sp, =0xD600B000

在某些时候你需要在cpsr中启用中断。你可能会等到这个,直到你在任何外围设备中启用了任何中断(在芯片内,在核心之外)。

;@ SVC MODE, IRQ ENABLED, FIQ DIS
mov r0,#0x53
msr cpsr_c, r0

您需要阅读lpc部分的手册,以了解如何启用中断,以及如何在发生中断时清除中断。

您需要在中断处理程序中执行的第一件事(您在地址0x18处转移到的代码)是保留堆栈中的共享(非存储区)寄存器,这样您就不会搞砸它们。如果你不回到被中断的代码,寄存器就会改变,代码可能无效。由于您的项目似乎是在ASM中,因此您可以在应用程序中使用某些寄存器,并仅为isr保留一些寄存器,而不必设置堆栈。如果您要在处理程序中的任何位置使用bl,则需要将lr保存在堆栈中。

在某些时候,你的处理程序需要清除外设中的中断,这样它才会再次触发,直到下一次中断,才能读取lpc手册。是的当我说lpc我的意思是恩智浦以前的飞利浦...

最后一件事是如果你按下lr,弹出它,然后弹出其他寄存器,如果你按下它们,然后使用这个确切的指令,手臂将返回并将模式切换回被中断的模式(切换到使用那些存储的寄存器)。

subs pc,lr,#4

注意您可能还需要,对于ARM来说,获取特定内核的TRM(Techincal Reference Manual)通常是一个好主意,在您的情况下是ARM7TDMI-S。在信息中心页面上,左侧是ARM7处理器,而不是架构下的ARMv7,而是ARM11,ARM9,ARM7的较低位置。

按钮可能会因中断而混乱,因为它们反弹并在I / O引脚上产生许多边沿。看看你的另一篇文章,我看不到你需要中断的地方。除非另有必要,否则通常应避免中断。他们一般都很乱。当然,有些设计你不能避免使用它们。并且存在事件驱动的设计,其中所有代码都是中断处理程序,应用程序中没有任何内容,但启动代码和无限循环(或某种类型的睡眠)。

你可以使用中断进行去抖动,例如,如果你设置了一个定时器中断并为中断中的按钮采样I / O引脚,你可以避免相当多的弹跳,但你也有可能丢失按下按钮。只是因为按钮I / O引脚被断言连续两次中断,而不是两次按下,你在某处更改状态变量,当释放按钮时,你改变状态变量。该状态变量的边缘变化是应用程序感兴趣的。当按钮从未按下状态变为按下状态时,执行某些操作,如果从按下按下到未按下状态,则不执行任何操作,等待它从未按下状态更改为按下按下状态。

您也可以使用相同的计时器中断来启动或采样adc。

由于你还没有解决你在这里提到的其他问题,我不会接近中断。首先解决问题,然后确定是否存在需要中断的功能。就像adc的偶数/定期采样一样。

这应该足以让你开始。如果您尝试中断,请不要尝试将它们作为此应用程序的一部分,创建一个完全独立的应用程序,例如LED闪光灯。更改中断处理程序中的led状态,和/或更改处理程序中的全局变量或寄存器,并为其指定forground并更改led作为结果。总是将你的问题/学习练习分成单独的部分,然后解决它们然后将它们粘在一起添加一块,测试,添加一块,测试。

答案 1 :(得分:1)

在这种情况下,中断处理程序似乎是不必要的,您可以简单地在主循环中轮询按钮2而不是使用“等待”功能。将其添加到循环的末尾:

ldr r1, [r0]                ; Read FIO0PIN in to r1
ands r1, r1, # B2_MASK      ; Mask out BUT1
beq STOP

其中STOP是执行安全炉关闭的目标(即不会使其无限期运行)。

请注意,你的循环包括等待button1 - 肯定应该 LoopStart之前?否则,控制循环将在每次迭代时按下按钮而不执行任何控制操作 - 如果最后一个操作是heaterOn,则可能是危险的情况!

除此之外,请注意,在ARM-Cortex内核(LPX2378是ARM7TDMI-S内核)之前,ARM内核仅定义了两个中断源IRQ和FIQ,大多数部件在ARM内核外部都有一个独立的中断控制器,此中断控制器是特定于供应商的。因此,要确定您的GPIO中断如何处理,您需要参考设备的参考手册而不是ARM文档。

基于ARM Cortex-M的设备正在迅速取代ARM7设备,使用这样的设备可能会更好。特别是中断处理更加直接,灵活和高效。有关Cortex-M如何改进ARM7的信息,请参阅this article