ARM组装 - 基本中断处理

use*_*390 4 embedded assembly 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
Run Code Online (Sandbox Code Playgroud)

和我的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
Run Code Online (Sandbox Code Playgroud)

还有我的炉控制回路:

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
Run Code Online (Sandbox Code Playgroud)

提前致谢.

old*_*mer 11

如果你还没有它,你需要获得ARM ARM(ARM架构参考手册).过去只有一个,但现在有很多核心,他们不得不为不同的架构拆分它们. http://infocenter.arm.com 左侧是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
Run Code Online (Sandbox Code Playgroud)

从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
Run Code Online (Sandbox Code Playgroud)

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

;@ SVC MODE, IRQ ENABLED, FIQ DIS
mov r0,#0x53
msr cpsr_c, r0
Run Code Online (Sandbox Code Playgroud)

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

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

在某些时候,你的处理程序需要清除外设中的中断,因此它不会再次触发,直到下一个中​​断,必须阅读l​​pc手册.是的,当我说lpc我的意思是恩智浦前飞利浦...

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

subs pc,lr,#4
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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