关于ARM中断实现与理
来源:互联网 发布:工程计量软件叫金路 编辑:程序博客网 时间:2024/05/19 00:42
这个过程有助于ARM中断的理解,以及锻炼我们查手册的能力,很好的例子。因为在刚接触ARM的时候,很多的东西都是围绕在我们的寄存器的操作上,这个寄存器的数量在我们ARM920T这块芯片上,就让很多人迷茫在寄存器里的大海里了;那么更加不用说我们更高级一点儿的Cortex A8平台上了,那将会有更多的寄存器需要我们去操作,所以我们必须掌握好一种学习ARM的方法。很多人对这些外设的操作,因为难度很大的原因,都迈不出第一步,那就是“有目的的去查手册”,尤其是看到纵横交错的电路图时,很多初学者都望而生畏的翻片儿了,理由是,这个偏硬件太多,我感兴趣的只是U-boot和Linux的移植,以及驱动的相关。这也不为过,因为初学者总是被这些热点的东西所吸引,站在兴趣是我们学习知识的最有劲的动力的角度上,一点儿也不为过。但,在我们的驱动学习过程中,还是针对于这些常用的外设展开的
我门的步骤是:
(1)初始化我们的SARM用于中断程序到时候跳转过去,我们的这个程序是在NorFlash上运行的。但是中断程序是在SRAM中加载到我们的MCU去执行的。
(2)我们这里需要两个手册,一个是S3C2410这个datasheet,以及我们的原理图,可以在网上下载!s3c2410的核心原理图和手册。
(3)我们这个实验的主要东西是中断,所以,首先我打开S3C2410的手册【um_s3c2410a_manual_r10.pdf】,我们在书签里面找到”INTERRUPT CONTROLLER“项。
打开后这个图首先引入眼帘,大概意思是:中断控制器S3C2410A在接收来自56个中断源的Request时,我们的中断控制器的功能流程图就是上面这个图。这些中断源来自于,内部外设(是指相对于Core,如DMA控制器,采用通用异步收发机,IIC等等。
当从内部,以及从引脚传来的外部中断请求。ARM920T Core会在我们的中断仲裁程序(即通过优先级或者是条件来选择谁运行)跑起来后,通过我们请求的到底是FIQ,还是IRQ来选择不同的方式相应中断。(你可能要问ARM有7中断模式,为什么只响应这两种中断呢?因为在我们的中断分类中,只有FIQ和IRQ是从外部来驱动我们的中断响应的,其他的那些使我们的Core在和内部实现好的,不能够直接被外界驱动)。响应中断的仲裁程序,依赖于硬件优先逻辑;结果是写入待定寄存器(pending register),这个寄存器,有助于用户知道是由那个中断源,产生的中断。
因为我们的pending register(在我们的程序中的表示方式是“EINTPEND”),这个寄存器,你可以查手册找到如下图的内容
我们需要注意的是这个EINTPEND寄存器的【3:0】0到3位是无效的,FIQ只有一个,但是IRQ却有多个,而这多个中断IRQ请求都有这个寄存器来存储,我们用它的相应的位来区别出到底是那个中断源发来的中断请求。
(4)接下来,我们选择我们的中断程序到底用几号外部中断。
比如我们这里要实现的是一个键盘中断响应的功能模块:
a.查看我们的外设的原理图【FS2410-CORE-V5.0.pdf】,找到如下的图片,这个过程最好自己找找,多动动手,你就会慢慢的对手册熟悉起来。
b.注意我们图的左边,共用到了四个外部中断EINT0、EINT2、EINT11、EINT19,我们的程序的流程设计也是来自于我们的硬件的结构,及我们看到的原理图。
c.继续查我们的手册,不过内容分别是这四个外部中断,我们拿EINT0来举例:
在PDF阅读器里面,使用快捷键Ctrl + F ,输入"EINT0",然后一直查找到如下这里:
在最末行,我们看到EINT0这个外部中断是通过我们GPF寄存器的0号引脚实现的。所以很自然的想到操作GPFCON这个寄存器来实现我们的0号外部中断(EINT0)
在PDF阅读器里面,使用快捷键Ctrl + F ,输入"GPFCON",然后一直查找到如下这里:
查到这里,我们看见:当GPF的[0:1]号位为"10"的时候,就能表示0号外部中断。
例: GPFCON= (GPFCON& (~(0x3<<0))) | (0x2) 这样就表示了EINT0
GPFCON = (GPECON &( ~(0x3<<12))) + (0x1<<12); 这表示的是 EINT6
(5)写到这里我们中断基本上有些眉目了,接下来就是我们来按顺序清除我们的断点标志,请把重点放在这个顺序两个字上,这是因为如果你用的是三星的S3C2410的话,那么板子的一个特性(相对于ARM公司指定的统一标准之外,半导体厂家自己在遵守这一标准的前提下,对芯片加上一些自己的特色)。介于S3C2410的断点标志要顺序删除的特性,所以我们这里在收尾工作的时候一定要细心。
下面是核心部分代码:
//设置中断程序的入口地址
#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_EINT8_23 (*(unsigned *)(_ISR_STARTADDRESS+0x34))
#define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x28))
//清楚中断位
#define Clear1Pending(bit) {SRCPND = bit; INTPND = INTPND;} // precent write wrong data
//设置时钟频率
#define FCLK 202800000
#define HCLK (202800000/2)
#define PCLK (202800000/4)
//中断源
#define UART0 0x0 // UART symbol
#define UART1 0x1
#define UART2 0xBB
//***************************************
void uart_init(int nMainClk, int nBaud, int nChannel)
{
// int i;
if(nMainClk == 0)
nMainClk = PCLK;
switch (nChannel)
{
case UART0:
UFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable
UMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC disable
ULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits
// [10] [9] [8] [7] [6] [5] [4] [3:2] [1:0]
// Clock Sel, Tx Int, Rx Int, Rx Time Out, Rx err, Loop-back, Send break, Transmit Mode, Receive Mode
// 0 1 0, 0 1 0 0, 01 01
// PCLK Level Pulse Disable Generate Normal Normal Interrupt or Polling
UCON0 = 0x245;// Control register
// rUBRDIV0=( (int)(nMainClk/16./nBaud) -1 );// Baud rate divisior register 0
UBRDIV0=( (int)(nMainClk/16./nBaud+0.5) -1 );// Baud rate divisior register 0
break;
case UART1:
UFCON1 = 0x0; //UART channel 1 FIFO control register, FIFO disable
UMCON1 = 0x0; //UART chaneel 1 MODEM control register, AFC disable
ULCON1 = 0x3;
UCON1 = 0x245;
UBRDIV1=( (int)(nMainClk/16./nBaud) -1 );
break;
default:
break;
}
}
void uart_sendbyte(int nData)
{
UTXH0 = nData;
while(!(UTRSTAT0 & 0x2));
}
//*************************************
*********************************************************************************************/
void uart_sendstring(char *pString)
{
while(*pString != '\0')
uart_sendbyte(*pString++);
}
void uart_printf(char *fmt)
{
uart_sendstring(fmt);
}
*********************************************************************************************/
//EINT0中断处理函数
void __irq int0_int(void)
{
uart_printf(" EINT0 interrupt occurred.\n");
Clear1Pending(0x1);
}
*********************************************************************************************/
//EINT11和19中断处理函数
void __irq int11_int(void)
{
if(EINTPEND & (1<<11))
{
EINTPEND=(1<<11);
uart_printf(" EINT11 interrupt occurred.\n");
Clear1Pending(0x1<<5);
}
else //if(EINTPEND & 1<<19)
{
EINTPEND=(1<<19);
uart_printf(" EINT19 interrupt occurred.\n");
Clear1Pending(0x1<<5);
//EINTPEND=(1<<19);
}
}
*********************************************************************************************/
//EINT2中断处理函数
void __irq int2_int(void)
{
uart_printf(" EINT2 interrupt occurred.\n");
Clear1Pending(0x1<<2);
}
*********************************************************************************************/
void int_init(void)
{
SRCPND = SRCPND; // clear all interrupt;清零SRCPEN,用以接收下一个同类型的IRQ
INTPND = INTPND; // clear all interrupt;清零INTPND,用以接收下一个同类型的IRQ
GPFCON=(GPFCON & ~(3<<0))|(0x2<<0) ;// PF0= EINT0
GPGCON=(GPGCON & ~(3<<6))|(0x2<<6) ;// PG3= EINT11
GPFCON=(GPFCON & ~(3<<4))|(0X2<<4);//PF2 = EINT2
GPGCON=(GPGCON & ~(3<<22))|(0X2<<22);//PG11 = EINT19
//相应的中断处理函数
pISR_EINT0 = (unsigned int)int0_int;//isrEINT0;
pISR_EINT8_23 = (unsigned int)int11_int; //isrEINT11_19;
pISR_EINT2 = (unsigned int)int2_int;//isrEINT2
GPECON=(GPECON&(~(0x3<<22)))+(0x1<<22);//KSCAN0 = 0
// GPEDAT=(GPEDAT&~(1<<11));
GPECON=(GPECON&(~(0X3<<26)))|(0X1<<26); //KSCAN2 = 0
GPEDAT=(GPEDAT&~((1<<13)|(1<<11)));
GPGCON=(GPGCON&(~(0X3<<12)))+(0X1<<12);//KSCAN1 = 0
GPGDAT=(GPGDAT&~(1<<6));
GPGCON=(GPGCON&(~(0X3<<4)))+(0X1<<4);//KSCIN3 = 0
GPGDAT=(GPGDAT&~((1<<2)));
//使eintpend清零,接收下一外部中断
EINTPEND = 0xffffff;
// SRCPND = (0x1) | (0x1<<5);//to clear the previous pending states
// INTPND = (0x1) | (0x1<<5);
//设置外部中断触发方式:01x----下降沿触发
EXTINT0 = (EXTINT0 & ~(7<<0)) | (0x2<<0); //EINT0=falling edge triggered
EXTINT0 = (EXTINT0 & ~(7<<8)) | (0x2<<8);
EXTINT1 = (EXTINT1 & ~(7<<12)) | (0x2<<12); //EINT11=falling edge triggered
EXTINT2 = (EXTINT2 & ~(7<<12)) | (0x2<<12);
//设置外部中断屏蔽为,0为使能,1为屏蔽
//打开0,2,11,19号外部中断
EINTMASK &= ~( (1<<11) | (1<<19) );
//设置总的中断屏蔽
//打开EINT0,ENT2,EINT8_23
INTMSK &= ~((0x1)|(1<<2)|(0x1<<5));
//消抖EINT19
EXTINT2 &= 1<<15;
EINTFLT2 = (0x7f << 24);
}
*********************************************************************************************/
void int_test(void)
{
int_init();
uart_printf("\n External Interrupt Test Example\n");
}
/**********************************************************************************************/
int main()
{
WTCON = 0;//关闭看门狗
CLKDIVN = (1<<1) | 1; //设置 1:2:4
MPLLCON = (0xa1<<12) | (0x3<<4) | 0x1; // Fin=12MHz FCLK=202.8MHz
//=== PORT H GROUP
//Ports : GPH10 GPH9 GPH8 GPH7 GPH6 GPH5 GPH4 GPH3 GPH2 GPH1 GPH0
//Signal : GPH10 CLKOUT0 SD_WP CTS1 RTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
//Setting: Output CLKOUT0 GPH8 nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
//Binary : 10, 10 10, 11 11, 10 10, 10 10, 10 10
GPHCON = 0x2afaaa;
GPHUP = 0x7ff; // The pull up function is disabled GPH[10:0]
uart_init(PCLK, 115200, UART0);
uart_printf ("boot success...");
int_test();
while(1);
}
- 关于ARM中断实现与理
- ARM中断与软中断
- ARM异常与中断
- ARM基础:系统调用与软件中断SWI的实现
- linux中实现fiq模式(关于arm中断,唤醒中断)
- 笔记:linux中实现fiq模式(关于arm中断,唤醒中断)
- 关于 arm的中断系统
- 关于arm中的中断处理
- ARM的异常与中断
- ARM工作模式与中断
- ARM工作模式与中断
- ARM 处理器 ~ 中断与异常
- 关于ARM的中断服务程序
- keil for arm 关于enit0 中断计数
- 关于ARM的中断服务程序
- 关于ARM的中断--向量与非向量的区别噢
- 关于ARM中断处理的问题----《ARM嵌入式系统开发-软件设计与优化》第九章中疑问
- 关于中断与异常
- C语言
- Yii PHP 框架分析(四)
- 哲理人生
- wampserver 2.2a安装pear扩展
- 如何查看Control File中保存的内容
- 关于ARM中断实现与理
- 脑残的CSDN
- JavaScript操作Excel并另存文件
- 修改3389端口
- membership入门学习(四)
- 那些导致程序抽风的神秘原因
- 注入入门级
- gdb 调试 程序执行脚本信息
- 工作中的细节