1.中断简介
中断,指计算机运行过程中,出现异常后,计算机停止当前工作保存当前状态,然后转向对这些异常的处理,在处理完成后再返回到停止时的状态,继续运行。
2.S3C2440中断
S3C2440有60个中断源,这里只以其中的外部中断为例,以最简单的中断处理过程代码来分析中断。
中断处理之前需要先将各个IO引脚设置为中断功能,将指示灯的IO引脚设置为输出模式。在此之后,需要了解S3C2440的各组中断的指针位置。
如代码所示,在这段汇编代码中定义了各个中断的入口,本实验使用HandleIRQ这个入口地址,当出现中断信号时,程序跳转到0x18这个地址,然后再跳转到HandleIRQ这个函数。
HandleIRQ函数首先将当前寄存器状态入栈保存,然后再跳转到真正的中断服务程序。
在中断服务程序中,根据INTOFFSET寄存器的内容来做出相应的指示,在完成中断响应后需要手动清中断。
这样主程序不需要运行其他代码,中断的初始化、IO接口初始化也都在汇编文件中完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| @****************************************************************************** @ File:head.S @ 功能:初始化,设置中断模式、管理模式的栈,设置好中断处理函数 @****************************************************************************** .extern main .text .global _start _start: @****************************************************************************** @ 异常向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用 @****************************************************************************** b Reset
@ 0x04: 未定义指令中止模式的向量地址 HandleUndef: b HandleUndef @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式 HandleSWI: b HandleSWI
@ 0x0c: 指令预取终止导致的异常的向量地址 HandlePrefetchAbort: b HandlePrefetchAbort
@ 0x10: 数据访问终止导致的异常的向量地址 HandleDataAbort: b HandleDataAbort
@ 0x14: 保留 HandleNotUsed: b HandleNotUsed
@ 0x18: 中断模式的向量地址 b HandleIRQ
@ 0x1c: 快中断模式的向量地址 HandleFIQ: b HandleFIQ
Reset: ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈 bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启 msr cpsr_c, #0xd2 @ 进入中断模式 ldr sp, =3072 @ 设置中断模式栈指针
msr cpsr_c, #0xd3 @ 进入管理模式 ldr sp, =4096 @ 设置管理模式栈指针, @ 其实复位之后,CPU就处于管理模式, @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略
bl init_led @ 初始化LED的GPIO管脚 bl init_irq @ 调用中断初始化函数,在init.c中 msr cpsr_c, #0x53 @ 设置I-bit=0,开IRQ中断 ldr lr, =halt_loop @ 设置返回地址 ldr pc, =main @ 调用main函数 halt_loop: b halt_loop
HandleIRQ: sub lr, lr, #4 @ 计算返回地址 stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器 @ 注意,此时的sp是中断模式的sp @ 初始值是上面设置的3072 ldr lr, =int_return @ 设置调用ISR即EINT_Handle函数后的返回地址 ldr pc, =EINT_Handle @ 调用中断服务函数,在interrupt.c中 int_return: ldmia sp!, { r0-r12,pc }^ @ 中断返回, ^表示将spsr的值复制到cpsr
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include "s3c2440.h"
void EINT_Handle() { unsigned long oft = INTOFFSET; unsigned long val;
switch( oft ) { case 1: { GPBDAT |= (0xF<<5); GPBDAT &= ~(1<<5); break; } case 4: { GPBDAT |= (0xF<<5); GPBDAT &= ~(1<<6); break; }
case 2: { GPBDAT |= (0xF<<5); GPBDAT &= ~(1<<7); break; }
case 0: { GPBDAT |= (0xF<<5); GPBDAT &= ~(1<<8); break; }
default: break; }
if( oft == 4 ) EINTPEND = (1<<4); SRCPND = 1<<oft; INTPND = 1<<oft; }
|