我对s3c2410中断的理解如下:
已经设置cpsr为irq了
中断信号产生-> SRCPND相应位被设置为1 -> 如果没有被Mask -> priority仲裁 -> 设置相应的INTPND位 -> 设置OFFSET -> 跳转到中断程序去执行
以下来自:http://blog.ednchina.com/cllzs/39286/message.aspx
S3C2410有56个中断源,26个中断控制寄存器。1. 产生中断条件
① 设置中断模式
② PSR寄存器的F和I位打开,为0
③ 中断屏蔽位打开,为0
④ 中断挂起寄存器的请求标志位 为1
2. 使用中断通常需设置以下寄存器的值,前五个为必须。
寄存器名字 |
寄存器地址 |
读写权限 |
作用 |
SRCPND |
0x4a000000 |
R/W |
中断源挂起寄存器,当中断产生后,相应位置位 |
INTMOD |
0x4a000004 |
R/W |
中断模式寄存器,设定IRQ或FIQ模式 |
INTMASK |
0x4a000008 |
R/W |
中断屏蔽寄存器,如果相应位置1则该中断屏蔽 |
PRIORITY |
0x4a00000c |
R/W |
中断优先级控制寄存器 |
INTPND |
0x4a000010 |
R/W |
中断挂起寄存器,相应位对应正在执行的中断 |
INTOFFSET |
0x4a000014 |
R |
中断源请求偏移寄存器 |
SUBSRCPND |
0x4a000018 |
R/W |
子中断源挂起寄存器 |
INTSUBMSK |
0x4a00001c |
R/W |
子中断屏蔽寄存器 |
注:
决定能否发生中断的寄存器,也就是说在没有发生中断已经设置的寄存器,不受中断后果的影响:
① PSR寄存器
② INTMASK寄存器 默认值为 0XFFFFFFFF
表明中断是否发生的寄存器
① SRCPND寄存器 默认值0X00000000
在中断服务程序中必须清“0”,通过向对应位写数据
② INTPND寄存器 默认值为0X00000000
在中断服务程序中必须清“0”,通过向对应位写“1”
SRCPND和INTPND的区别:
大体上可以这样理解:S3C2410A支持56个中断源,由一些寄存器的32个位管理决定是否使能中断:SRCPND、INTPND、INTMASK、INTMOD、PRIORITY。
① 有中断源请求到达,SRCPND寄存器的对应位置为 1 ,经过优先模块仲裁后INTPND寄存器的其中一位被置1,而且只能有一位置 1,而SRCPND可允许多位
② 若中断被屏蔽,尽管这样,SRCPND寄存器的相应位被置1,但不影响INTPND寄存器。只要INTPND寄存器的相应位为1,且I-FLAG or F-FLAG位清0,就可以立即启动中断服务程序
③ 中断源的中断请求首先在SRCPND登记
④ SRCPND寄存器不受中断控制器的优先逻辑所影响,INTPND受制于优先级控制。
3. 使用定时器1产生中断步骤
① 配置定时器寄存器:
rTCFG0 ―― 预份频值
rTCFG1 ―― 选择MUX的分割比例
rTCNTB1 ―― 设定计数值
rTCMPB1 ―― 设置占空比
定时器输入时钟频率 = MCLK / { 预分频值 + 1 } / { 除数值 } ,也即1秒钟的计数值
② 配置中断系统
pISR_TIMER1 = (int)Timer1_ISR 赋中断服务程序的入口地址
rINTMSK &= ~(BIT_TIMER1) 开中断
如:
/******************************************************************************
- 函数名称 : void Timer1_init(void)
- 函数说明 : 定时器初始化程序
- 输入参数 : 无
- 输出参数 : 无
******************************************************************************/
void Timer1_init(void)
{
rGPGCON = rGPGCON & 0xfff0ffff | 0x00050000; //配置GPG口为信号输出
rGPGDAT = rGPGDAT | 0x300;
rTCFG0 = 255; // Prescaler0=255
rTCFG1 = 0 << 4; //
//rTCNTB1 = 48828; // 在pclk=50MHZ下,1秒钟的记数值rTCNTB1 = 50000000 / 4 / 256 = 48828;
rTCNTB1 = 3;
rTCMPB1 = 0x00;
rTCON = (1 << 11) | (1 << 9) | (0 << 8); //禁用定时器1,手动加载
rTCON = (1 << 11) | (0 << 9) | (1 << 8); //启动定时器1,自动装载
}
/******************************************************************************
- 函数名称 : void Timer1INT_Init(void)
- 函数说明 : 定时器中断初始化程序
- 输入参数 : 无
- 输出参数 : 无
******************************************************************************/
void Timer1INT_Init(void) //定时器接口使能
{
if ((rINTPND & BIT_TIMER1))
{
rSRCPND |= BIT_TIMER1;
}
pISR_TIMER1 = (int)Timer1_ISR;
rINTMSK &= ~(BIT_TIMER1); //开中断;
}
6.对中断的实质理解
其实我对2410的中断没有真正理解的,我不清楚其中的执行流程,以下是我的部分理解(不一定正确的),写下让自己以后改正。
① 2410的向量中断:中断产生后,CPU自动跳中断服务程序执行。不用计算地址偏移,也不需要到rINTPND中查询
② 2410非向量中断:中断产生后,CPU跳到一个固定的地址,查询中断源标号,接着利用“加载程序”跳到中断服务程序。这属于启动代码,程序如下:
IsrIRQ
sub sp,sp,#4 ;//reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
阅读(2016) | 评论(0) | 转发(0) |