第5章附录 S3C2410中断源名称
- 格式:doc
- 大小:280.00 KB
- 文档页数:11
使用中断的步骤:1、当发生中断IRQ时,CPU进入“中断模式”,这时使用“中断模式”下的堆栈;当发生快中断FIQ时,CPU进入“快中断模式”,这时使用“快中断模式”下的堆栈。
所以在使用中断前,先设置好相应模式下的堆栈。
2、对于“Request sources(without sub -register)”中的中断,将INTSUBMSK寄存器中相应位设为03、将INTMSK寄存器中相应位设为04、确定使用此的方式:是FIQ还是IRQ。
a.如果是FIQ,则在INTMOD寄存器设置相应位为1b.如果是IRQ,则在RIORITY寄存器中设置优先级使用中断的步骤:5、准备好中断处理函数,a.中断向量:在中断向量设置好当FIQ或IRQ被触发时的跳转函数,IRQ、FIQ的中断向量地址分别为0x00000018、0x0000001c b.对于IRQ,在跳转函数中读取INTPND寄存器或INTOFFSET 寄存器的值来确定中断源,然后调用具体的处理函数c.对于FIQ,因为只有一个中断可以设为FIQ,无须判断中断源d.中断处理函数进入和返回6、设置CPSR寄存器中的F-bit(对于FIQ)或I-bit(对于IRQ)为0,开中断s3c2410 中断异常处理在进入正题之前,我想先把ARM920T的异常向量表(Exception Vectors)做一个简短的介绍。
:]ARM920T的异常向量表有两种存放方式,一种是低端存放(从0x00000000处开始存放),另一种是高端存放(从0xfff000000处开始存放)。
关于为什么要分两种方式进行存放这点我将在介绍MMU的文章中进行说明,本文采用低端模式。
ARM920T能处理有8个异常,他们分别是:Reset,Undefined instruction,Software Interrupt,Abort (prefetch),Abort (data),Reserved,IRQ,FIQ下面是某个采用低端模式的系统源码片段:/****************************************************** ***********************_start:b Handle_Resetb HandleUndefb HandleSWIb HandlePrefetchAbortb HandleDataAbortb HandleNotUsedb HandleIRQb HandleFIQ…..…..other codes…...******************************************************* **********************/上面这部分片段一般出现在一个名叫“head.s”的汇编文件的里,“b Handle_Reset”这条语句就是系统上电之后运行的第一条语句。
实验4 S3C2410 外部中断实验一、实验目的掌握S3C2410 通用F口配置为外部中断的方法,会在MDK中可视化配置外部中断,理解外部中断的触发过程,熟练掌握和中断相关寄存器的使用以及中断服务函数的编程方法。
二、实验预备知识熟悉UP-NETARM2410实验箱的结构,S3C2410的外设接口电路,熟悉MDK编程软件的使用方法,熟悉汇编语言程序设计的一般方法。
三、实验内容将I/O口中的PF2配置成外部中断 2 EINT2,编写汇编语言程序编译并下载到UP-NETARM2410实验箱,控制GPC5/GPC6/GPC7上所接的三个LED闪烁,主程序中的实验现象是什么?按下EINT2开关后触发外部中断2实验现象又是什么,请在实验结果中自己作答。
四、参考程序主程序核心代码:32 LDR R0, = SRCPND33 MOV R1, #0x034 STR R1, [R0, #0x4]35 MVN R1, #0x0436 STR R1, [R0, #0x8]37 MOV R1, #0x7F38 STR R1, [R0, #0xC]394041 ledflash42 LDR R0, =GPCDA T_ADDR43 MOV R1, #0x044 EOR R1, R1, #LED_MASK45 STR R1, [R0] ; LED OFF4647 BL Delay4849 MOV R1, #0x6050 EOR R1, R1, #LED_MASK51 STR R1, [R0] ; LED ON5253 BL Delay5455 B ledflash56 Delay57 MOV R3, #0x0F000058 MOV R4, #0x0F000059 subcycle160 SUB R3, R3, #161 subcycle262 SUB R4, R4, #163 CMP R4, #064 BGE subcycle26566 CMP R3, #067 BGE subcycle168 BX LR中断服务程序核心代码:136 ; int2 service137 int2_isr138 ; SUB R14, R14, #4139 ; STMFD SP!, {R0-R8, R14}; save env 140 STMFD SP!, {R0-R1}141142 LDR R0, = SRCPND143 MOV R1, #0x40144 STR R1, [R0] ; clear SRCPND145146 LDR R1, [R0, #0x10]147 STR R1, [R0, #0x10] ; clear INTPND 148149 ; int2-LED3 ON of OFF150 LDR R0, =GPCDAT_ADDR151 MOV R1, #0x0152 EOR R1, R1, #LED3_MASK153 STR R1, [R0] ; LED OFF154155 BL Delay156157 MOV R1, #0x80158 EOR R1, R1, #LED3_MASK159 STR R1, [R0] ; LED ON160161 BL Delay五、实验结果请自己作答。
S3C2410 中断程序的实现
在此要注意的是区别中断向量表和异常向量表。
中断发生后总是从IRQ 或者FIQ 异常入口处进入,然后跳转到相应的异常处理程序处执行,这个异常处理程序一般都是进行查找中断向量表的操作,然后调用中断处理程序。
以下是在应用中中断处理实现的过程:从中不难体会到中断的处理过程。
定义中断向量表的物理地址:
代码
将中断处理程序入口地址放入中断向量表:
代码
定义中断处理程序:
代码
定义异常向量表:
代码
定义异常处理函数:
代码
异常处理宏HANDLER的定义:代码
定义IRQ 中断处理宏IRQHandle:
代码
申明IRQ 异常的服务程序为:IsrIRQ,即,发生IRQ 异常时,执行“b HandlerIRQ”即是
运行IsrIRQ代码:
代码
IRQ 异常处理程序:
代码
由上可以知道,当一个IRQ 中断发生时,CPU将从0X18(IRQ 异常入口地址)取指执行,在这一步PC 的跳转是有硬件实现的。
在入口0x18 地址处放的是一条跳转指令,这条指令将跳到IRQ 异常处理程序运行,IRQ 异常处理程序主要是根据中断源查找中断向量表。
获得中断入口地址后,接着CPU 跳转中断处理程序运行。
在嵌入式系统中异常向量表和中断向量表都是存于FLASH起始的一段空间中。
而异常处理和中断处理程序都是运行在RAM中的。
第5章_基于S3C2410的系统硬件设计5.1引言在第4章中,我们介绍了S3C2410处理器的特性和功能。
本章将介绍基于S3C2410的系统硬件设计。
具体而言,我们将讨论系统的主要硬件模块,包括处理器的外围设备、存储器、输入输出接口等。
5.2系统总体设计__________________________________________________S3C241_________________________________________________Flash 存储_________________________________________________RAM存储_________________________________________________LCD显示_________________________________________________输入设_________________________________________________在这个系统中,S3C2410作为处理器负责控制整个系统的工作。
Flash存储器用于存储程序代码和数据,RAM存储器用于存储运行时数据。
LCD显示屏用于系统的图形界面显示,输入设备用于用户与系统的交互。
5.3处理器的外围设备S3C2410处理器的外围设备包括:-时钟模块:提供处理器时钟信号。
-外部中断控制器:负责处理外部中断信号。
-DMA控制器:用于数据的直接内存访问。
-UART接口:用于串行通信。
-USB接口:用于连接外部USB设备。
-SPI接口:用于串行外围设备的通信。
-I2C总线:用于连接各种外围设备。
-GPIO控制器:用于控制通用输入输出。
5.4存储器系统中的存储器主要包括Flash存储器和RAM存储器。
Flash存储器是非易失性存储器,用于存储程序代码、数据和系统配置信息。
在系统启动时,处理器从Flash存储器中加载程序代码,并将其存储到RAM存储器中执行。
表6-1 中断控制器支持的56个中断源表6-2 SRCPND寄存器的定义表5-3 INTMOD寄存器的定义续表实例6-1完成一个S3C2410芯片中断源的中断控制程序的编写,需要完成四部分内容。
第一部分的实例在前面已经介绍。
下面介绍后三部分内容的编程实例。
例程中所用到的一些寄存器常量等在头文件reg2410.h和isr.h中定义,详见附录。
这两个头文件必须包含在例程文件中。
#include "../inc/reg2410.h"#include "../inc/isr.h"例程中还需要用到下面的结构体。
/* 定义结构体*/typedef struct{Interrupt_func_t InterruptHandlers;void* data;int valid; //设置中断是否有效1=有效0=无效mask_func_t mask;mask_func_t unmask;mask_func_t ack_irq;}struct_InterruptFunc;static struct_InterruptFunc InterruptFunc[NR_IRQS]={NULL,};static void ack_irq(unsigned int irq){rSRCPND = (1 << irq);rINTPND = (1 << irq);}static void mask_irq(unsigned int irq){rINTMSK |= (1 << irq);}static void unmask_irq(unsigned int irq){rINTMSK &= ~(1 << irq);}(1)56个中断源中断向量设置/* 56个中断源的中断向量设置函数*/void ISR_IrqHandler(void){unsigned int irq=GetISROffsetClr(); //得到中断源的中断号irq=fixup_irq(irq); //计算子中断源的地址偏移if(irq>=NR_IRQS)return;if(InterruptFunc[irq].InterruptHandlers==NULL){InterruptFunc[irq].ack_irq(irq); //清中断未决位return;}/* 调用中断服务程序*/InterruptFunc[irq].InterruptHandlers(irq, InterruptFunc[irq].data);InterruptFunc[irq].ack_irq(irq); //清中断未决位}上述程序中,GetISROffsetClr()、fixup_irq()是用来计算中断源号及子中断源地址偏移的函数。
程序代码如下:// GetISROffsetClr()函数int GetISROffsetClr(){//计算中断的偏移地址,高位优先int i,ispr=rI_ISPR,tmp=1<<(MAXHNDLRS-1);for(i=MAXHNDLRS;i>0;i--){if(ispr&tmp){return i-1;}tmp>>=1;}return -1;}// fixup_irq()函数static unsigned int fixup_irq(int irq) {unsigned int ret;unsigned long sub_mask, ext_mask;switch (irq) {case IRQ_UART0:sub_mask = rSUBSRCPND & ~rINTSUBMSK;ret = get_subIRQ(sub_mask, 0, 2, irq);break;case IRQ_UART1:sub_mask = rSUBSRCPND & ~rINTSUBMSK;ret = get_subIRQ(sub_mask, 3, 5, irq);break;case IRQ_UART2:sub_mask = rSUBSRCPND & ~rINTSUBMSK;ret = get_subIRQ(sub_mask, 6, 8, irq);break;case IRQ_ADCTC:sub_mask = rSUBSRCPND & ~rINTSUBMSK;ret = get_subIRQ(sub_mask, 9, 10, irq);break;case IRQ_EINT4_7:ext_mask = rEINTPEND & ~rEINTMASK;ret = get_extIRQ(ext_mask, 4, 7, irq);break;case IRQ_EINT8_23:ext_mask = rEINTPEND & ~rEINTMASK;ret = get_extIRQ(ext_mask, 8, 23, irq);break;default:ret = irq;}return ret;}(2)中断控制初始化中断控制器初始化程序主要完成具体中断源的中断模式、中断屏蔽位、子中断屏蔽位的设置。
根据5.2.3中介绍的寄存器格式,选择对应该中断源的寄存器位是设置为1,还是设置为0。
void ISR_Init(void){int irq;/* 设置所有中断源为IRQ模式,并首先屏蔽所有中断源*/rINTMOD = 0x0; //所有中断源为IRQ模式rINTMSK = BIT_ALLMSK; // BIT_ALLMSK =0xffffffffrINTSUBMSK = BIT_SUB_ALLMSK; // BIT_SUB_ALLMSK= 0x7ff/* 初始化结构体中的成员*/for (irq=0; irq < NORMAL_IRQ_OFFSET; irq++) {InterruptFunc[irq].valid = 1;InterruptFunc[irq].ack_irq = ack_irq;InterruptFunc[irq].mask = mask_irq;InterruptFunc[irq].unmask = unmask_irq;}InterruptFunc[IRQ_RESERVED6].valid = 0;InterruptFunc[IRQ_RESERVED24].valid = 0;InterruptFunc[IRQ_EINT4_7].valid = 0;InterruptFunc[IRQ_EINT8_23].valid = 0;InterruptFunc[IRQ_EINT0].valid = 0;InterruptFunc[IRQ_EINT1].valid = 0;InterruptFunc[IRQ_EINT2].valid = 0;InterruptFunc[IRQ_EINT3].valid = 0;for (irq=NORMAL_IRQ_OFFSET; irq < EXT_IRQ_OFFSET; irq++) {InterruptFunc[irq].valid = 0;InterruptFunc[irq].ack_irq = EINT4_23ack_irq;InterruptFunc[irq].mask = EINT4_23mask_irq;InterruptFunc[irq].unmask = EINT4_23unmask_irq;}for (irq=EXT_IRQ_OFFSET; irq < SUB_IRQ_OFFSET; irq++) {InterruptFunc[irq].valid = 1;InterruptFunc[irq].ack_irq = SUB_ack_irq;InterruptFunc[irq].mask = SUB_mask_irq;InterruptFunc[irq].unmask = SUB_unmask_irq;}}上述例程中,对中断源的控制寄存器进行初始设置,是每个I/O端口或部件采用中断方式控制时必须编写的程序。
但根据不同的用户需求,寄存器设置的值是不同的。
对于初始化结构体中的成员,不是必须的。
初始化工作还需要完成中断句柄的设置。
下面一段程序是完成该功能的例程。
int SetISR_Interrupt(int vector, void (*handler)(int, void*), void* data){if(vector>NR_IRQS || vector<0)return -1;if(!InterruptFunc[vector].valid)return -1;InterruptFunc[vector].ack_irq(vector); //清除未决位InterruptFunc[vector].InterruptHandlers = handler;InterruptFunc[vector].data = data;InterruptFunc[vector].unmask(vector); //开放中断return 0;}(3)中断服务程序中断服务程序是根据I/O端口或部件具体要完成的功能来编写的,没有一个具体的格式。
下面是一个用于键盘的中断服务程序,是通过IIC中断源产生的。
static void Key_ISR(int vector, void* data){static int framecnt=0;U8 status ,kdata;status = rIICSTA T ;if( (status & IICSTA T_MODE_MSK) != IICSTA T_MODE_SR)return;kdata = rIICDS;switch(framecnt){case 0:if(status & IICSTA T_SLA VEADDR){framecnt++;}break;case 1:if(GetI2C_Devtype(kdata) != DTYPE_MKEYB){framecnt=0;}framecnt++;break;case 2:mcukey = kdata;if(mcukey&0x80){framecnt=0;break;}else if(!(mcukey&0x80)){up=1;count=1;tempmcukey=mcukey;}framecnt=0;break;}rIICCON &= ~IICCON_INTPEND;}上面中断服务程序具体完成的功能细节,我们在此暂不考虑。