×
单片机 > 单片机程序设计 > 详情

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

发布时间:2020-06-09 发布时间:
|
   今天来说一下s3c6410的外部中断:

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

但是具体到咱们的板子上,到底哪些是外部中断,哪些是内部中断呢?可以这样概括,除了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. // enable VE  
  2. __asm__ __volatile__(  
  3.     "mrc p15,0,r0,c1,c0,0/n"  
  4.     "orr r0,r0,#(1<<24)/n"  
  5.                "mcr p15,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. #define VIC0INTENABLE (*(unsigned long volatile *)0x71200010)  
  3. #define VIC0INTSELECT (*(unsigned long volatile *)0x7120000C)  
  4. #define VIC0VECTADDR  (*(unsigned long volatile *)0x71200100)  
  5. #define VIC0IRQSTATUS (*(unsigned long volatile *)0x71200000)  
  6. #define VIC0ADDRESS (*(unsigned long volatile *)0x71200F00)  
  7. #define VIC0SOFTINT (*(unsigned long volatile *)0x71200018)  
  8. #define VIC1ADDRESS (*(unsigned long volatile *)0x71300F00)  
  9. #define VIC0INTENCLEAR (*(unsigned long volatile *)0x71200014)  
  10. // extern interrupt  
  11. #define EINT0CON0 (*(unsigned long volatile *)0x7F008900)  
  12. #define EINT0MASK (*(unsigned long volatile *)0x7F008920)  
  13. #define EINT0PEND (*(unsigned long volatile *)0x7F008924)  
  14. #define EINT0FLTCON0 (*(unsigned long volatile *)0x7F008910)   
  15. // GPN  
  16. #define GPNCON (*(unsigned long volatile *)0x7F008830)  
  17. #define GPNDAT (*(unsigned long volatile *)0x7F008834)  
  18. #define GPNPUD (*(unsigned long volatile *)0x7F008838)  
  19. int count =0;  
  20. void (*show)(char *,...) = (void *)0xc7e11650;  
  21. extern unsigned long print;  
  22. int main()  
  23. {  
  24.     /* enable VE (VIC ENABLE) */  
  25.     __asm__ __volatile__(  
  26.             "mrc p15,0,r0,c1,c0,0/n"  
  27.             "orr r0,r0,#(1<<24)/n"  
  28.             "mcr p15,0,r0,c1,c0,0/n"  
  29.             :  
  30.             :  
  31.             : "r0"  
  32.     );  
  33.     /* GPIO stuff */  
  34.     GPNCON &= 1<<2;  
  35.     GPNCON |= 0x2;                          // set GPNCON (0-1) to extern interrupt.  
  36.     GPNPUD &= ~(1<<2);                        // disable pull down/up.  
  37.     EINT0CON0 &= 1<
  38.     EINT0CON0 |= 0x3;                       // set signal both edge trigger.  
  39. //  EINT0FLTCON0 |= (0x1 <
  40.     EINT0MASK &= ~(0x1);                    // clear the interrupt mask.  
  41.       
  42.     /* VIC stuff */  
  43.     VIC0VECTADDR = &print;  
  44.     VIC0INTSELECT &= ~(1<<0);  
  45.     VIC0INTENABLE |= 1<<0;  
  46.     return 0;  
  47. }  
  48. void __do_irq(void)  
  49. {  
  50.     show("hello extern interrupt./n");  
  51.     VIC0IRQSTATUS &= ~(1<<1);  
  52.     EINT0PEND = 1;  
  53.     VIC0ADDRESS = 0;  
  54.     VIC1ADDRESS = 0;                        // just in case.  
  55. }    
 

 

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

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

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

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

 

       汇编跳转的代码

 

  1. .global print  
  2. .extern __do_irq  
  3. print:  
  4.     mov sp,#0x52000000  
  5.     sub lr,lr,#4  
  6.     stmfd sp!,{r0-r14}  
  7.     bl __do_irq;  
  8.     ldmfd sp,{r0-r13,pc}^  

 

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

关键字:s3c6410  外部中断  key  OK6410 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机电子密码锁仿真 可修改密码