新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > s3c6410---外部中断---key (基于OK6410)

s3c6410---外部中断---key (基于OK6410)

作者: 时间:2016-11-09 来源:网络 收藏
今天来说一下s3c6410外部中断

首先说一下外部中断:顾名思义,由s3c6410外部触发的中断就是外部中断,由s3c6410内部触发的是内部中断。

本文引用地址:https://www.eepw.com.cn/article/201611/317820.htm

但是具体到咱们的板子上,到底哪些是外部中断,哪些是内部中断呢?可以这样概括,除了INT_EINT0---INT_EINT4之

外的都是内部中断。像watch dog就是内部中断,像key,wm9717触发的就是外部中断。

先说下外部中断从外设到cpu的具体流程:对理解中断很中重要!

外设------>GPIO------>VIC------>ARM1176

我们编写关于中断的程序也是这个过程:

配置外设------>配置GPIO------>配置VIC------>配置ARM协处理器等

总之一句话:

你要打造一个通路能够让中断的电平变化能顺顺利利的传送到ARM里!

下面就依照这个顺序讲一下:

(一)、GPIO及其配置

为什么会有GPIO呢?因为外设都是连到GPIO上嘀!s3c6410具有187个多功能I/O端口,其实有127个用于外部中

断。这127个引角呢,可以分为这么10个分组:

这里给大家分一下:

EINT0 GPN0--->GPN15 GPL8--->GPL14 GPM0--->GPM4

EINT1 GPA0--->GPA7 GPB0--->GPB6

EINT2 GPC0--->GPC7

EINT3 GPD0--->GPD5

EINT4 GPF0--->GPF14

EINT5 GPG0--->GPG7

EINT6 GPH0--->GPH9

EINT7 GPO0--->GPO15

EINT8 GPP0--->GPP14

EINT9 GPQ0--->GPQ9

每个引脚可以对应一个外部中断。

那么当外部中断电平变化传GPIO里,除了对应端口的哪几个寄存器(CON,PUD,etc)GPIO里又有哪些寄存器会

对这个中断信号造成影响呢?看下面:

EINTXCON :配置触发方式,低电平,高电平,上升沿,下降沿。

EINTXPEND :这个现在用不到,一会儿中断处理程序会用到,这个是pending register。

EINTXMASK :这里可以屏蔽某个外部中断,要通过需要clear一下对应的中断位。默认是全屏蔽的,需要注意!

EINTXFLTCON : 这里设置滤波方式,可以去毛刺。

我们这里要设置的是EINTXCON,EINTXMASK,EINTXFLTCON。

这样我们的中断信号就可以顺利通过GPIO了,又要到哪里去呢?当时是VIC向量中断控制器!

(到达VIC)

上面说的这些外部中断在GPIO里分成了九组,但是具体反应到VIC里他们占用哪些中断号呢?这里贴一下:

NO SOURCES Description Group

0 INT_EINT0 External interrupt 0 ~ 3 VIC0
1 INT_EINT1 External interrupt 4 ~ 11 VIC0

32 INT_EINT2 External interrupt 12 ~ 19 VIC1

33 INT_EINT3 External interrupt 20 ~ 27 VIC1

53 INT_EINT4 External interrupt Group 1 ~ Group 9 VIC1

(前四个中断号 覆盖了EINT0,他们共用这四个中断号。53中断号覆盖了1--->9组中断引角,他们悲剧的共用一个中断号)

这里我们使用VIC,当然要先开启VIC,这个是在协处理器里设置的 VE位

  1. //enableVE
  2. __asm____volatile__(
  3. "mrcp15,0,r0,c1,c0,0/n"
  4. "orrr0,r0,#(1<<24)/n"
  5. "mcrp15,0,r0,c1,c0,0/n"
  6. :
  7. :
  8. :"r0"
  9. );

这样我们的VIC就能用了。

这里就简单了,就这么几个重要的寄存器

VICXINTSELECT 选择中断方式FIQ or IRQ。

VICXVECTADDR 设置中断处理程序的地址。

VICXINTENABLE 使能GPIO传过来的中断信号。

其实设置到这里外部中断就能正确运行了,但是还有许多别的寄存器,比如设置什么优先级的,大家如果需要就添上去。

(到达ARM)

ARM得知来了个中断,就和VIC进行一系列的握手,得到VICADDRESS,就开始执行我们的中断处理程序了。

另一个重要的内容,就是中断处理程序里清除中断。

我们要clear 一下EINTXPEND,clear 一下VICXADDRESS。有的人说要清除一下VICXIRQSTATUS,但是我发现我清除和不

清除没什么区别,也许是我理解的不透,哪位高手看到了,麻烦告诉我一声,谢了!也许有人要闻,EINTXPEND和VICXADDRESS

清除的顺序,我要说:无所谓了。因为在ARM发出VICIRQACK或者读VICADDRESS的时候,硬件自动屏蔽当前中断和比当前中断优先级

小的中断!但是不屏蔽更高优先级的中断。所以谁先谁后无所谓了,总之都清了就行了。

ARM把我们的中断处理程序执行后,这个循环就完了,我们的设置的就起了作用了。

下面我贴下OK6410 key中断的代码。

  1. //VIC
  2. #defineVIC0INTENABLE(*(unsignedlongvolatile*)0x71200010)
  3. #defineVIC0INTSELECT(*(unsignedlongvolatile*)0x7120000C)
  4. #defineVIC0VECTADDR(*(unsignedlongvolatile*)0x71200100)
  5. #defineVIC0IRQSTATUS(*(unsignedlongvolatile*)0x71200000)
  6. #defineVIC0ADDRESS(*(unsignedlongvolatile*)0x71200F00)
  7. #defineVIC0SOFTINT(*(unsignedlongvolatile*)0x71200018)
  8. #defineVIC1ADDRESS(*(unsignedlongvolatile*)0x71300F00)
  9. #defineVIC0INTENCLEAR(*(unsignedlongvolatile*)0x71200014)
  10. //externinterrupt
  11. #defineEINT0CON0(*(unsignedlongvolatile*)0x7F008900)
  12. #defineEINT0MASK(*(unsignedlongvolatile*)0x7F008920)
  13. #defineEINT0PEND(*(unsignedlongvolatile*)0x7F008924)
  14. #defineEINT0FLTCON0(*(unsignedlongvolatile*)0x7F008910)
  15. //GPN
  16. #defineGPNCON(*(unsignedlongvolatile*)0x7F008830)
  17. #defineGPNDAT(*(unsignedlongvolatile*)0x7F008834)
  18. #defineGPNPUD(*(unsignedlongvolatile*)0x7F008838)
  19. intcount=0;
  20. void(*show)(char*,...)=(void*)0xc7e11650;
  21. externunsignedlongprint;
  22. intmain()
  23. {
  24. /*enableVE(VICENABLE)*/
  25. __asm____volatile__(
  26. "mrcp15,0,r0,c1,c0,0/n"
  27. "orrr0,r0,#(1<<24)/n"
  28. "mcrp15,0,r0,c1,c0,0/n"
  29. :
  30. :
  31. :"r0"
  32. );
  33. /*GPIOstuff*/
  34. GPNCON&=1<<2;
  35. GPNCON|=0x2;//setGPNCON(0-1)toexterninterrupt.
  36. GPNPUD&=~(1<<2);//disablepulldown/up.
  37. EINT0CON0&=1<<3;
  38. EINT0CON0|=0x3;//setsignalbothedgetrigger.
  39. //EINT0FLTCON0|=(0x1<<7);
  40. EINT0MASK&=~(0x1);//cleartheinterruptmask.
  41. /*VICstuff*/
  42. VIC0VECTADDR=&print;
  43. VIC0INTSELECT&=~(1<<0);
  44. VIC0INTENABLE|=1<<0;
  45. return0;
  46. }
  47. void__do_irq(void)
  48. {
  49. show("helloexterninterrupt./n");
  50. VIC0IRQSTATUS&=~(1<<1);
  51. EINT0PEND=1;
  52. VIC0ADDRESS=0;
  53. VIC1ADDRESS=0;//justincase.
  54. }

这里解释一下,我为什么要把滤波设置去掉呢,因为我设置延时滤波,效果不大,数字滤波也没仔细找合适的宽度,这里就是让大家理解一下外部中断

到底怎么一步步的执行的。更细节的东西,你可以在ARM1176的datasheet和向量中断控制器PL192的datasheet里找。

好了,就写到这里了,我想可以大家应该可以明白,如果明白了就在下面顶一下,如果不明白的或者错误的就在下面说下。谢谢!

另外感谢↘`莫、離的提醒。

汇编跳转的代码

  1. .globalprint
  2. .extern__do_irq
  3. print:
  4. movsp,#0x52000000
  5. sublr,lr,#4
  6. stmfdsp!,{r0-r14}
  7. bl__do_irq;
  8. ldmfdsp,{r0-r13,pc}^

这是两个文件,汇编的主要用于模式跳转,设置irq模式下的栈地址。



评论


技术专区

关闭