主要是中断向量表的设置和现场保护。
调试比较久的原因:使用main: b main时调试发现,不能死循环,可能是main标签是保留的
1)在主程序中的步骤一般是:
1.关中断,并设置各主要模式的堆栈指针和容量
2写1清SRCPND,INTPND寄存器
3.配置INTMSK使能相应中断
4.开全局中断
3)中断服务程序中的流程是:
1.屏蔽中断(硬件自动关irq中断)
2.执行任务
3.写1清相应SRPND,INTPND等寄存器(可以利用SRPND=SRPND,INTPND来清零,防止出错)
4.把屏蔽的中断使能回来
5.返回
参考u-boot的start.S自己写了一个外部中断程序,mini2440的按键K1,按一下LED灭,再按一下LED亮......。硬件原理图:按键引脚对应GPIO是PG0,对应EINT8,而LED的引脚是PB8,被设计为低电平时灯亮。
.equ NOINT, 0xc0
.equ DISABLE_IRQ,0x80
.equ SYS_MOD, 0x1f
.equ IRQ_MOD, 0x12
.equ USR_MOD, 0x10
.equ WTCON, 0x53000000
.equ GPBCON, 0x56000010
.equ GPBDAT, 0x56000014
.equ GPBUP, 0x56000018
.equ GPGCON, 0x56000060
.equ EINTMASK, 0x560000a4
.equ EXTINT1, 0x5600008c
.equ EINTPEND, 0x560000a8
.equ INTMSK, 0x4A000008
.equ SRCPND, 0X4A000000
.equ INTPND, 0X4A000010
.equ USE_Stack, 4096
.equ IRQ_Stack, 2048
.text
.code 32
.global _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
.balignl 16,0xdeadbeef
reset:
ldr r0,=WTCON
mov r1,#0x0
str r1,[r0] @关看门狗
ldr r0,=GPBCON
ldr r1,=0x10000
str r1,[r0] @PB8输出
ldr r0,=GPBDAT
mov r1,#0x000
str r1,[r0] @低电平
msr cpsr_c,#(IRQ_MOD|NOINT)
ldr sp,=IRQ_Stack
msr cpsr_c,#(SYS_MOD|NOINT)
ldr sp,=USE_Stack
ldr r0,=GPGCON
mov r1,#0x02
str r1,[r0] @使能外部中断8
ldr r0,=EXTINT1
mov r1,#0x03
str r1,[r0] @下降沿触发
ldr r0, =EINTPEND
ldr r1,=0x00fffff0
str r1,[r0]@ 清EINTPEND,写1清零
ldr r0,=EINTMASK
ldr r1,=0xfffffeff
str r1,[r0] @使能外部中断8,0为使能
ldr r0, =SRCPND
ldr r1,=0xffffffff
str r1,[r0]@ 清SRCPND,写1清零
ldr r0, =INTPND
ldr r1,=0xffffffff
str r1,[r0]@ 清INTPND,写1清零
ldr r0,=INTMSK
ldr r1,=0xffffffdf
str r1,[r0] @使能外部中断EINT8-23
mrs r1, cpsr
bic r1, r1, #DISABLE_IRQ
msr cpsr_c, r1 @开全局IRQ中断
loop: b loop
irq_server:
ldr r0, =EINTPEND
ldr r1,[r0]
tst r1,#0x100 @判断是否为EINT8
beq not_handle
ldr r0,=GPBDAT
ldr r1,[r0]
tst r1,#0x100 @测试PB8当前是高电平还是低电平
ldreq r1,=0x100
movne r1,#0x0
str r1,[r0]
not_handle:
ldr r0, =EINTPEND
ldr r1,[r0] @ldr r1,=0x100
str r1,[r0] @清EINTPEND
ldr r0, =SRCPND
ldr r1,[r0] @ldr r1,=0x20
str r1,[r0] @清SRCPND
ldr r0, =INTPND
ldr r1,[r0] @ldr r1,=0x20
str r1,[r0] @清INTPND
mov pc,lr
undefined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
sub lr,lr,#4
stmfd sp!,{r0-r12,lr}
bl irq_server
ldmfd sp!,{r0-r12,pc}^
fiq:
nop
链接脚本命名为“int.lds”:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
. = 0x00000000;
.text : {
*(.text)
}
.data ALIGN(4): {
*(.data)
}
.bss ALIGN(4): {
*(.bss)
}
}
Makefile是:
led_off.bin : led_off.S
arm-linux-gcc -nostdlib -nostartfiles -g -c -o led_off.o led_off.S
arm-linux-ld -Tint.lds led_off.o -o led_off_elf
arm-linux-objcopy -O binary -S led_off_elf led_off.bin
clean:
rm -f led_off.bin led_off_elf *.o