新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > s3c6410---外部中斷---key (基于OK6410)

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

        作者: 時間:2016-11-09 來源:網絡 收藏
        今天來說一下s3c6410外部中斷

        首先說一下外部中斷:顧名思義,由s3c6410外部觸發的中斷就是外部中斷,由s3c6410內部觸發的是內部中斷。

        本文引用地址:http://www.104case.com/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模式下的棧地址。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 台江县| 横峰县| 井研县| 奉贤区| 磐安县| 宣威市| 崇阳县| 恭城| 神池县| 年辖:市辖区| 邵阳县| 敦煌市| 丘北县| 山阳县| 江达县| 屯门区| 托克逊县| 陕西省| 永顺县| 政和县| 晋江市| 石柱| 华阴市| 博爱县| 洮南市| 仁布县| 南京市| 武川县| 揭西县| 牙克石市| 库车县| 曲阜市| 工布江达县| 宜都市| 巴林左旗| 上杭县| 内江市| 琼结县| 察雅县| 深泽县| 长丰县|