S3C2440中断体系结构
0xd2 @ 进入中断模式,cpsr_c表示cpsr[7:0],0xd2=0b1101 0010
ldr sp, =3072 @ 设置中断模式栈指针
msr cpsr_c, #0xdf @ 进入系统模式
ldr sp, =4096 @ 设置系统模式栈指针,
@ 其实复位之后,CPU就处于系统模式,
@ 前面的“ldr sp, =4096”完成同样的功能,此句可省略
bl init_led @ 初始化LED的GPIO管脚
bl init_irq @ 调用中断初始化函数,在init.c中
msr cpsr_c, #0x5f @ 设置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
/*
* init.c: 进行一些初始化
*/
#include "s3c24xx.h"
/*
* LED1-4对应GPB5、GPB6、GPB7、GPB8
*/
#define GPB5_out (1<(5*2)) // LED1
#define GPB6_out (1<(6*2)) // LED2
#define GPB7_out (1<(7*2)) // LED3
#define GPB8_out (1<(8*2)) // LED4
/*
* K1-K4对应GPG0,GPG3,GPG5,GPG6
*/
#define GPG0_eint (2<(0*2)) // K1,EINT8
#define GPG3_eint (2<(3*2)) // K2,EINT11
#define GPF5_eint (2<(5*2)) // K3,EINT13
#define GPF6_eint (2<(6*2)) // K4,EINT14
/*
* 关闭WATCHDOG,否则CPU会不断重启
*/
void disable_watch_dog(void)
{
WTCON = 0;// 关闭WATCHDOG很简单,往这个寄存器写0即可
}
void init_led(void)
{
GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;
}
/*
* 初始化GPIO引脚为外部中断
* GPIO引脚用作外部中断时,默认为低电平触发、IRQ方式(不用设置INTMOD)
*/
void init_irq( )
{
GPGCON = GPG0_eint | GPG3_eint |GPG5_eint |GPG6_eint;
// 对于EINT8、11、13、14,需要在EINTMASK寄存器中使能它们
EINTMASK &= (~(1<8)) & (~(1<11)) & (~(1<13)) & (~(1<14));
/*
* 设定优先级:
* ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2
* 仲裁器1、6无需设置
* 最终:
* EINT0 > EINT2 > EINT11,EINT19,即K4 > K3 > K1,K2
* EINT11和EINT19的优先级相同
*/
PRIORITY = (PRIORITY & ((~0x01) | (0x3<7))) | (0x0 < 7) ;
//开启EINT8_23
INTMSK &= ~(1<5);
}
interrupt.c
#include "s3c24xx.h"
void EINT_Handle()
{
unsigned long oft = INTOFFSET;
switch( oft )
{
//INTOFFSET为5时,代表INTPND的位[5]为1,则EINT8-23中断发生
case 5:
{
GPBDAT |= (0x0f<5); //LED全灭
if (EINTPEND & (1<8)) //EINT8发生(EINT8对应K1)
GPBDAT &= ~(1<5);
if (EINTPEND & (1<11)) //EINT11发生(EINT8对应K2)
GPBDAT &= ~(1<6);
if (EINTPEND & (1<13)) //EINT13发生(EINT8对应K3)
GPBDAT &= ~(1<7);
if (EINTPEND & (1<14)) //EINT14发生(EINT8对应K4)
GPBDAT &= ~(1<8);
break;
}
default:
break;
}
//清除中断
if(oft == 5)
EINTPEND = (1<8) | (1<11) | (1<13) | (1<14);
SRCPND = 1 INTPND = 1 } main.c int main() { while(1); return 0; } Makefile objs := head.o init.o interrupt.o main.o int.bin: $(objs) arm-linux-ld -Ttext 0x00000000 -o int_elf $^ arm-linux-objcopy -O binary -S int_elf $@ arm-linux-objdump -D -m arm int_elf > int.dis %.o:%.c arm-linux-gcc -Wall -O2 -c -o $@ $ %.o:%.S arm-linux-gcc -Wall -O2 -c -o $@ $ clean: rm -f int.bin int_elf int.dis *.o
S3C2440中断体系结 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)