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保存在堆栈中.
在某些时候,你的处理程序需要清除外设中的中断,因此它不会再次触发,直到下一个中断,必须阅读lpc手册.是的,当我说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作为结果.总是将你的问题/学习练习分成单独的部分,然后解决它们然后将它们粘在一起添加一块,测试,添加一块,测试.