新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > Wince外部中斷控制LED詳解動態申請

        Wince外部中斷控制LED詳解動態申請

        作者: 時間:2016-11-20 來源:網絡 收藏
        本實例是基于S3C2440,WINCE5.0

        1.中斷分兩大類:內部中斷和外部中斷

        本文引用地址:http://www.104case.com/article/201611/318685.htm

        外部中斷:由外部設備所引發的中斷,這些外部中斷都是通過GPIO中的中斷引腳產生的。S3C2440有24個外部中斷,相關的寄存器如下:

        EXTINT0-EXTINT2:三個寄存器設定EINT0-EINT23的觸發方式。

        EINTFLT0-EINTFLT3:控制濾波時鐘和濾波寬度。

        EINTPEND:中斷掛起寄存器

        EINTMASK:中斷屏蔽寄存器

        內部中斷:內部中斷是有CPU內部器件產生的中斷,如定時器中斷,USB中斷,UART中斷等。相關的寄存器如下:

        SUBSRCPND:次級中斷掛起寄存器。

        INTSUBMSK:次級中斷屏蔽寄存器。

        INTMOD:中斷方式寄存器

        PRIORITY :優先級寄存器

        SRCPND :中斷掛起寄存器

        INTMSK :中斷屏蔽寄存器。

        INTPND :中斷發生后,SRCPND中會有位置1,可能好幾個,這些中斷會由優先級仲裁器選出一個優先級最高的,然后INTPND中相應位置1,同一時間只有一位是1。

        這里要注意一級中斷和次級中斷的區別,次級中斷的設置要比一級中斷復雜一些。
        2.WINCE中斷機制:ISR和IST

        WINCE中斷從大的方面分為ISR和IST兩部分,具體ISR,IST是什么這里就不詳說了,網上一搜一大把。簡單的說是ISR負責把IRQ轉化為邏輯中斷并返回給內核;IST則負責中斷的邏輯處理。

        3.WINCE中斷實例:外部按鍵中斷控制LED

        (1)創建一個簡單的流驅動模板,這一步可以手動創建,也可以通過"Windows CE Developer Samples" -> "Windows CE 5.0 Embedded Development Labs" -> "DrvWiz.exe" 框架產生。建議采用后者,簡單快捷,不易出錯。這里工程命名為LED,即生產的DLL為LED_DLL。

        (2)填充函數體。這里主要介紹與中斷相關的兩個函數:

        DWORD LED_Init( LPCTSTR pContext)//驅動初始化函數,主要做內存的分配和調用中斷初始化函數。

        DWORD WINAPI LED_IST( LPVOID lpvParam ) //中斷處理線程,即IST,在這里進行中斷處理.

        DWORD InitInterrupt( void ) //中斷初始化函數,包括中斷寄存器的設置,事件和線程的創建,初始化等。

        首先介紹DWORD InitInterrupt( void ),代碼如下:

        DWORD InitInterrupt( void )
        {
        HANDLE g_htIST; //線程返回句柄
        BOOL fRetVal;
        DWORD dwThreadID;
        printfmsg((TEXT("come into the setup interrupt!!!rn")));

        //初始化外部中斷8
        s2440IO->rGPGCON &= ~(0X3);
        s2440IO->rGPGCON |= 0X2;//設置為中斷模式
        s2440IO->rEXTINT1 &= ~(0X0f);
        s2440IO->rEXTINT1 |= 0XA; //下降沿觸發,使能濾波器
        s2440IO->rEINTMASK &= ~(1<<8);//打開中斷 8
        s2440IO->rEINTPEND |= (1<<8);//清除中斷
        //GPIO 設置-LED
        s2440IO->rGPBCON = (s2440IO->rGPBCON &~(3 << 14)) | (1<< 14); // GPB7 == OUTPUT.
        s2440IO->rGPBCON = (s2440IO->rGPBCON &~(3 << 16)) | (1<< 16); // GPB8 == OUTPUT.


        s2440INTR->rINTMSK &= ~(0x20); //取消外部中斷8的屏蔽
        s2440INTR->rSRCPND |= (0x20); //清除外部中斷8
        s2440INTR->rINTPND |=0X20; //清除外部中斷,即初始化
        // Create an event
        // 創建一個事件
        g_hevInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
        if(!g_hevInterrupt) return -10;

        // Have the OAL Translate the IRQ to a system irq
        //將物理中斷IRQ轉換為邏輯中斷
        fRetVal = KernelIoControl( IOCTL_HAL_TRANSLATE_IRQ,
        &dwIrq,
        sizeof( dwIrq ),
        &g_dwSysInt,
        sizeof( g_dwSysInt ),
        NULL );


        if( !fRetVal )
        { return -1 }

        // Create a thread that waits for signaling
        // 創建中斷服務線程IST
        g_htIST = CreateThread(NULL,// CE Has No Security
        0, // No Stack Size
        ThreadIST,// Interrupt Thread
        NULL,// No Parameters
        CREATE_SUSPENDED,// Create Suspended until we are done
        &dwThreadID // Thread Id
        );
        if( !g_htIST )
        {return -1 }
        // Set the thread priority to real time
        // 設置線程的優先級
        int m_nISTPriority = 7;
        if(!CeSetThreadPriority( g_htIST, m_nISTPriority))
        { return -1 }
        // Initialize the interrupt
        // 初始化中斷,將邏輯中斷號與事件關聯,即中斷產生時觸發該事件
        //在中斷服務線程IST中會等該事件的發生,即WaitForSingleObject(g_hevInterrupt, INFINITE);
        //從而中斷發生就導致IST運行,處理中斷任務
        if ( !InterruptInitialize(g_dwSysInt, g_hevInterrupt, NULL, 0) )
        {return -1; }
        ResumeThread( g_htIST );
        printfmsg((TEXT("*leave the setup interrupt!!!rn")));

        return 1;
        }

        簡單說一下初始化中斷的流程,首先是初始化相關的中斷寄存器,我這里采用的是外部中斷8。接下來是創建一個事件,用于關聯外部中斷8和IST線程。在IST中會通過dwStatus = WaitForSingleObject(g_hevInterrupt, INFINITE)來等待中斷的發生。然后利用KernelIoControl( IOCTL_HAL_TRANSLATE_IRQ,
        &dwIrq, sizeof( dwIrq ), &g_dwSysInt, sizeof( g_dwSysInt ), NULL ); 將物理中斷IRQ轉換為邏輯中斷。這是給內核用的。接著就要創建中斷服務線程了:g_htIST = CreateThread(NULL,// CE Has No Security
        0, // No Stack Size
        ThreadIST,// Interrupt Thread
        NULL,// No Parameters
        CREATE_SUSPENDED,// Create Suspended until we are done
        &dwThreadID // Thread Id
        );

        這些都做好以后就可以初始化中斷了.

        // Initialize the interrupt
        // 初始化中斷,將邏輯中斷號與事件關聯,即中斷產生時觸發該事件
        //在中斷服務線程IST中會等該事件的發生,即WaitForSingleObject(g_hevInterrupt, INFINITE);
        //從而中斷發生就導致IST運行,處理中斷任務
        InterruptInitialize(g_dwSysInt, g_hevInterrupt, NULL, 0) 該函數就將物理中斷對應的邏輯中斷號和事件關聯起來了。

        到這里整個初始化就做好了,這其中的函數調用順序不是唯一的,但只要理清各個函數的調用順序就行了。

        DWORD TST_Init( LPCTSTR pContext)
        {
        printfmsg((TEXT("come into the init!!!rn")));


        // GPIO Virtual alloc
        s2440IO = (volatile IOPreg *) VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE, PAGE_NOACCESS);
        if(s2440IO == NULL) {
        printfmsg((TEXT("For s2440IO: VirtualAlloc faiLED!rn")));
        }
        else {
        if(!VirtualCopy((PVOID)s2440IO,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_READWRITE | PAGE_NOCACHE )) {
        printfmsg((TEXT("For s2440IO: Virtualcopy faiLED!rn")));
        }
        }

        s2440INTR = (volatile INTreg *) VirtualAlloc(0,sizeof(INTreg ),MEM_RESERVE, PAGE_NOACCESS);
        if(s2440INTR == NULL) {
        printfmsg((TEXT("For s2440INTR: VirtualAlloc faiLED!rn!rn")));
        }
        else {
        if(!VirtualCopy((PVOID)s2440INTR,(PVOID)(INT_BASE),sizeof(INTreg),PAGE_READWRITE | PAGE_NOCACHE )) {
        printfmsg((TEXT("For s2440INTR: Virtualcopy faiLED!rn!rn")));
        }

        InitInterrupt();
        return 0x1234;

        }
        這個函數是在驅動被加載的時候調用的,所以要把初始化的任務放在這里。

        與中斷相關的部分就這么多,這是動態申請中斷的方法,比較復雜。其實完全可以不用動態申請的方法,而且不推薦采用此方法。靜態申請是一種很好的方法,比較簡單。在后面的文章會進一步講解。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 玉屏| 琼结县| 阿鲁科尔沁旗| 中宁县| 天祝| 武陟县| 政和县| 柳江县| 潜江市| 玉环县| 梁河县| 鹤壁市| 临城县| 枣强县| 建平县| 山丹县| 石屏县| 彭水| 积石山| 青浦区| 芒康县| 房山区| 延津县| 瓮安县| 普安县| 镇坪县| 洞口县| 黄冈市| 蕉岭县| 钟山县| 平武县| 栾川县| 旬邑县| 冕宁县| 冷水江市| 普安县| 崇仁县| 安顺市| 湘乡市| 女性| 兰州市|