日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WinCE中断结构分析

發(fā)布時間:2025/4/16 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WinCE中断结构分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前一段時間研究了一下WinCE下的中斷結構,整理了一下,希望與大家討論。

最下面有PDF版本下載,便于保存

版權申明:本文版權歸ARMCE所有,轉載請保留所有原文內(nèi)容及 ARMCE標識并注明出
自 ARMCE,禁止任何未經(jīng)作者同意的內(nèi)容修改及再發(fā)布,ARMCE保留所有權利。


Windows Embedded CE??中斷結構分析
關鍵字:WinCE,中斷,體系,結構
摘要:本文主要以WinCE??.NET 5.0 為操作系統(tǒng)平臺,ARM為硬件平臺,分析了WinCE下
中斷的結構與實現(xiàn)方式
作者:ETDrawer@ARMCE

前言
??在嵌入式系統(tǒng)當中,對于中斷的處理是非常重要的一部分內(nèi)容。許多外圍設備都需要通
過中斷來實現(xiàn)自己的功能或者與系統(tǒng)內(nèi)核交互,系統(tǒng)時鐘本身也是由時鐘中斷產(chǎn)生的。所以
本文旨在分析WinCE下的中斷的結構,以及常用的幾種實現(xiàn)方式,來幫助讀者了解WinCE
中斷體系及實現(xiàn)自己的中斷處理結構。
??下面的介紹如非特殊說明,均以 ARM 架構為硬件基礎,操作系統(tǒng)代碼使用 Windows
embedded CE 5.0。

一 WinCE中斷體系結構
??先看圖 1:


下載 (30.76 KB)

剛才


圖 1 WinCE中斷體系結構

??這張是經(jīng)典的說明中斷體系的圖,我們可以通過分析這張圖來了解WinCE的中斷體系。??

??從結構上看,WinCE中斷涉及4 層,即:硬件層、內(nèi)核層、OAL層、IST處理層。了
解這 4層之間的交互傳遞將對我們了解WinCE中斷處理很有幫助。

1 硬件層:
??硬件層就是實際觸發(fā)中斷的硬件,這里主要有兩方面作用,一個是觸發(fā)中斷,第二個是
enable/disable硬件中斷。

2 內(nèi)核層:
??這一層由內(nèi)核來處理,包括中斷異常產(chǎn)生后跳轉到相應的ISR,以及根據(jù)SYSINTR 來
觸發(fā)相應的Event。關于SYSINTR 和 IRQ 的概念后面會說明。

3 OAL層
??這一層主要就是我們需要實現(xiàn)的代碼了,來識別硬件IRQ,對應到SYSINTR。

4 IST處理層
??一般使用 IST 來做實際的中斷處理,這樣不會占用很多的鎖定系統(tǒng)時間來處理中斷,
但是對中斷的實時性大打折扣

二??IRQ,ISR,IST和 SYSINTR

說到這里先解釋下IRQ,ISR,IST及 SYSINTR 的概念、意義及相互關系。

IRQ:
IRQ (Interrupt request),中斷請求。
這里就是外設或其它請求服務的設備發(fā)出來的中斷。屬于硬件中斷,可能是一個電平觸發(fā)的
GPIO 中斷,也可能是內(nèi)部DMA的一個中斷。

ISR:
ISR (Interrupt service routine),??中斷處理程序。
WinCE實際上使用 ISR來處理中斷,即默認的中斷入口函數(shù),在 ARM體系中,系統(tǒng)默認的
ISR就是 OEMInterruptHandler

IST:
IST (Interrupt service thread),??中斷服務線程。
在 ARM 的結構中,ISR 一般不會用來進行任何實際的操作,而只是返回一個 SYSINTR,
實際的操作全部在IST中完成,IST一般是在Device Manager 的一個線程中運行的一段
高優(yōu)先級的應用程序代碼,用來服務實際的中斷請求。

SYSINTR:
在 WinCE中,SYSINTR 就是 system interrupt,就是一個操作系統(tǒng)的邏輯中斷。
一般對于中斷的處理方式都是將一個IRQ映射為一個或者多個(中斷共享)SYSINTR,而后,
在實際的ISR中根據(jù)IRQ返回一個對應的SYSINTR用來告訴操作系統(tǒng)需要服務的邏輯對
象。

使用邏輯中斷的好處當然就是可以實現(xiàn)虛擬的中斷(一個 SYSINTR 就被 OS 認為是一個獨
立中斷)和中斷共享(單 IRQ對應多 SYSINTR)。
邏輯中斷是WinCE需要處理的實際對象,至于這個對象是一個共享的IRQ,還是一個虛擬
的中斷,還是獨立的物理中斷,系統(tǒng)并不過問,從而隔離了硬件與邏輯,我們的 ISR 需要
做的也正是這種物理中斷到邏輯中斷的映射。

三 WinCE中斷處理原理
??下面基于 ARM 體系,來介紹 WinCE 中斷處理的流程與原理。
??對于一個硬件IRQ中斷,系統(tǒng)內(nèi)核在捕獲之后,會交給 OEMInterruptHandler 處理,
這個函數(shù)就是我們實現(xiàn)中斷處理的中心函數(shù),首先我們從CPU 的寄存器里獲得中斷的信息,
這些信息告訴我們到底是哪個 IRQ 源觸發(fā)了中斷。
一般實現(xiàn)中斷服務的方式有以下幾種:

1. 簡單中斷處理——ISR模型
??最簡單的中斷處理辦法就是在ISR中直接處理,這里就是指在OEMInterruptHandler
中直接對中斷源進行判斷,然后調用服務程序。

??這種方式的優(yōu)點和缺點一樣明顯。
??優(yōu)點:快速的響應了中斷處理,使系統(tǒng)的實時性能增加不少
??缺點:由于進入OEMInterruptHandler的時候關閉了系統(tǒng)中斷(當然你可以在ISR中
自己打開中斷,不過處理起來較麻煩),所以如果處理時間過長,其他中斷很可能被忽略,
造成中斷丟失。并且系統(tǒng)被鎖定,使得系統(tǒng)任務的響應變慢。

2. 中斷處理的一般流程——IST模型
??前面看到了 ISR 模型的優(yōu)缺點。作為WinCE,主要定位還是民用的消費類電子產(chǎn)品,
所以,對于中斷響應的實時性不是特別高,所以系統(tǒng)的運行響應速度就顯得更加重要。而且
目前的嵌入式設備的處理速度越來越高,已經(jīng)幾乎達到了當時奔 3 的水平。所以 ISR 的模
型并不適用于WinCE。

如果把中斷服務程序當作一個系統(tǒng)進程或者線程來處理,這樣就不會造成系統(tǒng)被鎖定,
中斷被屏蔽等問題,使得中斷服務程序和其它進程、線程一樣被系統(tǒng)管理調度。于是就有了
IST的概念

IST 模型的想法是,在 ISR 中判斷到具體的中斷源 IRQ,就返回一個標志,用來標記
需要哪個程序來服務中斷,然后重新打開中斷,恢復系統(tǒng)調度,系統(tǒng)根據(jù)這個標志來激活相
應的程序來服務中斷。

這個就是最常用的中斷處理模型。使得中斷被關閉,系統(tǒng)被鎖定的時間最短。
在 WinCE中,經(jīng)常使用的就是建立中斷服務線程(IST),然后以IRQ 來申請一個系統(tǒng)
邏輯中斷號(SYSINTR),創(chuàng)建一個事件(Event),將 Event 與 SYSINTR 綁定,隨后 IST
阻塞在等待Event上面。

ISR 中只給系統(tǒng)返回一個 SYSINTR,系統(tǒng)根據(jù)綁定關系激活相應的Event,使得隨后
的 IST得以運行。

這就是 IST的一般服務流程
IST模型的缺點就是中斷服務的延遲較大,從 ISR 返回,到 IST開始運行,中間需要
花費一定的時間,相比 ISR 模型的中斷實時性較差,但是這種代價對于我們的應用是值得
的。

四??IST模型的實現(xiàn)
??下面我們來看IST模型具體在我們的驅動中是如何實現(xiàn)的。
??上面已經(jīng)介紹了 IST 模型的一般服務流程,下面我們針對驅動程序實例,來分析具體
的實現(xiàn)步驟。
1 驅動程序中 IST的構建與中斷初始化
上面介紹的 IST流程中,很多步驟都是WinCE的內(nèi)置支持,也就是說你只要調用相應
的 API就可以實現(xiàn)功能了,不需要自己編寫太多的代碼。只需要實現(xiàn)一些流程代碼。
首先是驅動程序端的中斷初始化。假設現(xiàn)在有一個驅動程序,需要服務中斷源,IRQ
為 0x12。

a)??以 IRQ 為參數(shù),申請 SYSINTR,方法為調用
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &(dwIrq),? ?
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?sizeof(UINT32), &dwSysIntr,? ?
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?sizeof(UINT32), NULL)
其中 dwIrq為IRQ號,即0x12
dwSysIntr 為系統(tǒng)中斷號,也就是調用返回的結果存放的位置

/* ARMCE深入
實際這個 IOControl調用的是函數(shù) OALIoCtlHalRequestSysIntr,該函數(shù)的位置

WINCE500\PLATFORM\COMMON\SRC\COMMON\INTR\COMMON\Ioctl.c
最終調用 OALIntrRequestSysIntr,這個由 OEM 自己實現(xiàn),一般就是維護了 2
張表,一張是從 SYSINTR 到 IRQ 號碼的映射表,另一張是 IRQ 到 SYSINTR 的
映射表,兩者是對應的關系。
這里注意一點,一個IRQ 映射為多個SYSINTR 是支持的,也就是共享中斷,但是
系統(tǒng)默認的實現(xiàn)并沒有支持一個 SYSINTR 映射為多個 IRQ,你可以自己實現(xiàn)。
這兩張表對于后面在OEMInterruptHandler中由IRQ查找SYSINTR提供了方便
*/

b)??創(chuàng)建與 SYSINTR 綁定的Event
由于我們的IST是需要Event激活的,所以這里申請一個 Event。
申請 Event的步驟比較簡單和標準
hISTEvent = CreateEvent(0,FALSE,FALSE,NULL);

c)??將SYSINTR 與Event綁定
調用 InterruptInitialize(dwSysIntr,hISTEvent,0,0)將 SYSINTR 與 Event 綁
定,用來在OEMInterruptHandler 中返回SYSINTR 時激活相對應的 Event

/* ARMCE深入
InterruptInitialize 的 代 碼 參 考 SC_InterruptInitialize , 在
E:\WINCE500\PRIVATE\WINCEOS\COREOS\NK\KERNEL\Intrapi.c中
主要做兩件事情:
#1 將 Event 的 Ptr 填入一個數(shù)組,這個數(shù)組是記錄每個 SYSINTR 對應激活的
Event

#2 調用OEMInterruptEnable,使能SYSINTR所對應的IRQ,并且將標志 IRQ
被引用次數(shù)的變量加1(WinCE6 的代碼中未見這一變量)
*/


d)??創(chuàng)建一個 IST,并且等待hISTEvent
到了這一步,中斷關于系統(tǒng)方面的初始化基本結束,剩下的就是創(chuàng)建一個 IST,然
后等待 Event來運行中斷服務代碼,例如:
? ?
while(TRUE) {
WaitForSingleObject(hISTEvent,INFINITE) ==
WAIT_OBJECT_0)


}

這里需要注意的是IST什么時候創(chuàng)建都可以,但是在InterruptInitialize之前不要
運行 IST 以等待這個 Event,也就是說在 InterruptInitialize 之前不要使用這個
Event,否則會導致InterruptInitialize失敗。
還有就是不要使用WaitForMultipleObjects來等待Event。
在中斷處理完成之后需要調用 InterruptDone,參數(shù)為該中斷的SYSINTR。來通
知系統(tǒng),中斷處理完成,系統(tǒng)重新使能該中斷


? ? 到了這里,驅動的中斷初始化工作就全部完成了。


2??OEM層需要做的工作
OEM 層 主 要 是 控 制 IRQ 的 enable??(BSPIntrEnableIrq) 與 disable
(BSPIntrDisableIrq), 當然要初始化 IRQ 的配置,使其在正確的觸發(fā)狀態(tài),比如上升延
觸發(fā)

? ? 至此一個中斷處理的IST模型就實現(xiàn)了,系統(tǒng)在IRQ 觸發(fā)時調用映射函數(shù),獲得相應
IRQ 的 SYSINTR,然后返回合法的SYSINTR給系統(tǒng),系統(tǒng)查表激活相應的Event,對應
的 IST進行中斷服務,然后再次等待 Event。

??3??中斷資源的釋放
? ? 當不需要當前中斷繼續(xù)服務的時候可以通過調用 KernelIoControl 來釋放申請到的
SYSINTR,具體格式為:
??KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR,??dwSysIntr,??sizeof(DWORD),
NULL, 0, NULL);

??其中 dwSysIntr 就是需要釋放的 SYSINTR 號碼。

/* ARMCE深入
??這里實際調用的是OALIntrReleaseSysIntr這個函數(shù),由OEM自己實現(xiàn)。所做的動作也
很簡單,就是從SYSINTR 到 IRQ 和 IRQ 到 SYSINTR 的那兩個映射關系數(shù)組中刪除映射
關系。
*/

五 可安裝的 ISR
??1? ? 為什么要使用可安裝 ISR(以下簡稱 IISR)
? ? 需要 IISR 的目的有兩種:
I. 動態(tài)的安裝中斷程序
在系統(tǒng)運行的過程中注冊中斷,這種中斷一般是不可預知設備的中斷,常用在總線設備
中,比如PCI設備

II. 中斷共享
當多個中斷源使用同一個中斷號(IRQ)時,就需要使用 IISR 來實現(xiàn)了

當然如果是需要動態(tài)安裝的共享中斷就最適合了。

因為我們的 IST模型中,中斷服務程序就是驅動中的IST,IRQ與 IST是一對一的關
系。所以在需要動態(tài)添加一個中斷服務程序的時候就沒有辦法處理了。
同樣由于 IRQ 與 IST 的一一對應關系對于一個 IRQ 對應多個需要服務的 IST 就同樣
沒有辦法處理。
基于上面的情況才會有IISR 的出現(xiàn),IISR 從本質上是在ISR 中提供了一個接口,當
ISR 調用 NKCallIntChain時,以此IRQ為參數(shù),在鏈表中依次查找是哪一個服務程序來
服務這次 IRQ,然后返回相應的 SYSINTR,此后的動作與 IST 模型就基本一樣,通過
SYSINTR 來激活Event,從而啟動相應的 IST。
??所以 IISR 的實現(xiàn)就是動態(tài)的向某一個 IRQ服務程序鏈表添加結點的過程。

2 IISR的實現(xiàn)
下面我們來看看IISR 的具體實現(xiàn)步驟:
??首先我們需要了解IISR 服務中斷的實現(xiàn)原理,如上面描述的,根據(jù)IRQ,來順序調用
鏈表中的中斷處理程序。所以我們可以有兩個選擇,一個就是類似 ISR 模型,直接在鏈表
中的中斷處理程序中判斷是不是自己的中斷,并且做處理。還有一種方式就是類似 IST 模
型,如果判斷是自己的中斷,則返回一個SYSINTR,以此SYSINTR 來激活IST。
??無論哪種方法,關于注冊中斷和查詢中斷的方式是一樣的,下面我們來看下如何將中斷
程序添加到鏈表,又如何在中斷來的時候去搜索鏈表。
??Microsoft提供了一個通用的IISR的處理模型,叫做 GIISR,這是一個以 IST模型處
理 IISR 的模塊,源程序可以在WINCE500\PUBLIC\COMMON\OAK\DRIVERS\GIISR
找到。熟悉了 GIISR,想實現(xiàn)自己的 IISR 處理程序或者基于 ISR 模型的處理,都比較簡
單了。
??下面我們就分析這種比較通用的處理 IISR 的模型。
a)??首先我們需要以 IRQ 來申請 SYSINTR,并且將 SYSINTR 與 Event 綁定,這些
步驟與IST模型中介紹的一樣,這里就不重復敘述了,IISR 在這里與 IST模型并
沒有任何的不同。其與 IST 模型的唯一不同點就是如何根據(jù) IRQ 來判斷相應的

SYSINTR。
在 IST 模型中是 OEM寫死的一個判斷程序,而 IISR 可以動態(tài)來注冊一個判斷程
序給系統(tǒng)調用,這是唯一的實現(xiàn)區(qū)別。
b)??下面我們需要注冊可安裝中斷程序的 dll,和 dll中的中斷處理函數(shù),并且將他們與
某一個特定的IRQ相關聯(lián)
這個過程是通過調用LoadIntChainHandler函數(shù)來實現(xiàn)的。
這里我們的中斷服務dll叫做”giisr.dll”,處理函數(shù)名叫做”ISRHandler”,對應IRQ
為0x20,則函數(shù)調用形式如下:
HANDLE??hIsrHandler??=??LoadIntChainHandler(TEXT(“giisr.dll”),
TEXT(“ISRHandler”), 0x20);

/* ARMCE深入
LoadIntChainHandler的源代碼可以在WINCE500\PRIVATE\WINCEOS\
COREOS\NK\KERNEL\Loader.c中找到,就是函數(shù)SC_LoadIntChainHandler
WinCE6 在 KDriver.c 中的 NKLoadIntChainHandler,兩者功能大致相同,只
是在一些結構體定義上略有不同
其主要功能就是加載 dll 到 NK,并且獲得三個函數(shù)的指針,一個是
CreateInstance,一個是你剛才傳進來的處理函數(shù),這里就是 ISRHandler,還
一個就是 IOControl,后面會用到。
首先調用CreateInstance 來獲得一個實例的數(shù)據(jù),這個數(shù)據(jù)就是一個 index,用
來標示其中的一個中斷處理程序的索引。
這里可能需要解釋下 GIISR 的處理原理。我們所有的可安裝中斷都通過 giisr.dll
里面的 ISRHandler來處理,在NKCallIntChain被調用的時候,會遍歷所有注冊
到這個 IRQ 的中斷處理函數(shù),這里全部都是同一個函數(shù) ISRHandler。那么就需
要可以區(qū)分每一次調用,所以就在 giisr 模塊里面維護一個數(shù)組,每一個中斷服務
程序占用一個數(shù)組成員,這些數(shù)組成員的Index就是他們在giisr里面的唯一標識。
所以 CreateInstance 的任務就是查找數(shù)組,找到第一個空閑位置,將 Index 返
回。在ISRHandler 被調用到的時候,會將這個Index傳遞進去,根據(jù)這個 Index,
ISRHandler 就能夠知道是數(shù)組中哪個成員正在被查詢,進而確定是不是這個成員
需要處理中斷請求,進而確定該返回的 SYSINTR。詳細的步驟下面會一一說明,
大家先有一個概念

在從 CreateInstance 返回了可用的數(shù)組 Index 之后,調用 HookIntChain,此
函數(shù)在Kdriver.c中。這個函數(shù)的功能比較簡單,我們先了解下共享中斷在系統(tǒng)中
的處理。
前面有所提到,在調用 NKCallIntChain 時會遍歷一個鏈表,每個鏈表頭就是系統(tǒng)
維護的一個數(shù)組中的一個成員,每一個 IRQ 號碼都對應數(shù)組中的一個成員,這個
數(shù)組就是 pIntChainTable。IRQ 按照其號碼在數(shù)組中對應相應的數(shù)組成員,注意
pIntChainTable 是一個 256 個成員的數(shù)組,這也就意味著你的 IRQ 號碼數(shù)字不
能超過 255,當然這是指你傳遞進來的 IRQ 號碼,如果你的 IRQ 號碼都是大于
255 的,可以對實際 IRQ 號碼做處理,保證其數(shù)字值在 0-255,比如對 256 取模,
這樣當然就可以傳遞進來了。
pIntChainTable中的每個元素都是一個鏈表的頭,當你向一個IRQ 添加中斷處理
的時候,實際是建立了一個新的PINTCHAIN元素,然后向pIntChainTable中的
IRQ 索引位置去添加,如果該位置不為空,則查找這個元素指向的下一個元素,在
這個單向鏈表的操作下,將新的中斷處理程序加入。
這個加入工作就是HookIntChain做的
*/

c)??上一步在GIISR中通過CreateInstance把這個新的中斷處理程序加入GIISR自
己的管理。GIISR 的主要作用就是判斷當中斷來的時候,是不是其內(nèi)部數(shù)組中的某
個成員需要服務中斷。所以需要更多的信息用來判斷中斷是否匹配當前的中斷服務
程序,所以我們需要把信息傳遞進去,這里就是調用KernelLibIoControl。
具體的方法為:
KernelLibIoControl(hIsrHandler,IOCTL_GIISR_INFO,&giisr_info,
sizeof(GIISR_INFO), NULL, 0, NULL);
這里就是把 giisr_info 的內(nèi)容傳遞給剛才注冊的中斷,giisr_info 是一個
GIISR_INFO的結構體,其內(nèi)容如下:
typedef struct _GIISR_INFO {
? ?? ? DWORD SysIntr;? ?? ?? ?? ?? ?? ?? ?? ?? ? // SYSINTR for ISR handler to return
(if associated device is asserting IRQ)
? ?? ? BOOL CheckPort;? ?? ?? ?? ?? ?? ?? ?? ???// If true, check port to see if device is
asserting IRQ
? ?? ? BOOL PortIsIO;? ?? ?? ?? ?? ?? ?? ?? ?? ? // Port is IO port (possibly true only for
x86)
? ?? ? BOOL UseMaskReg;? ?? ?? ?? ?? ?? ?? ?? ?//??If??true,??read??from MaskAddr??to
obtain mask
? ?? ? DWORD PortAddr;? ?? ?? ?? ?? ?? ?? ?? ???// Port Address
? ?? ? DWORD PortSize;? ?? ?? ?? ?? ?? ?? ?? ???// Port data width in bytes
? ?? ? DWORD Mask;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? // Mask??to??use??on??data??port??to
determine if device is asserting IRQ
? ?? ? DWORD MaskAddr;? ?? ?? ?? ?? ?? ?? ?? ???//??Address??of??register??to??use??as
mask
} GIISR_INFO, *PGIISR_INFO;

這些成員都是需要設置的,具體含義如下
SysIntr:這個中斷所對應的系統(tǒng)中斷號,即第一步申請到的 SYSINTR,系統(tǒng)在
確定是當前的設備出發(fā)的 IRQ 之后會返回這個 SysIntr
CheckPort:一般為 TRUE,如果為 FALSE 則直接返回 SysIntr,而不是判斷是
不是當前設備觸發(fā)的中斷
PortIsIO:是不是IO端口,這個可能只是在 x86 下使用,我們置為 FALSE
UseMaskReg:是否使用地址來獲得 Mask,如果為TRUE,則Mask 字段無意義
PortAddr:實際上是可以判斷中斷是哪個設備出發(fā)的那個寄存器的地址
PortSize:PortAddr的位寬,標志PortAddr是1字節(jié)(BYTE),2 字節(jié)(WORD),
還是 4字節(jié)(DWORD)的寄存器,其他不支持
Mask:一個掩碼位,在UseMaskReg為FALSE 的情況下與PortAddr的值進行
位或運算,如果不為0,則確定為當前設備觸發(fā)的中斷
MaskAddr:當 UseMaskReg為 TRUE 的時候,使用這個地址來獲得掩碼的值,
給動態(tài)的判斷中斷提供了接口
仔細看了上面各個成員的介紹,大家就應該可以了解 GIISR 是如何判斷中斷是不
是當前設備產(chǎn)生的。
所有的判斷依據(jù)就是這個結構體。一般我們會將 CheckPort 置為 TRUE,然后讓
系統(tǒng)去讀取PortAddr地址處的值,這個值可以標志是否為當前設備觸發(fā)的中斷。
獲得這個值以后,與一個 mask 值進行或運算(&),如果值不為 0,則認為是當前
設備觸發(fā)的中斷。這個 mask 值在 UseMaskReg 為 FALSE 時是成員 Mask,反
之是從 MaskAddr 地址處獲得。

/* ARMCE深入
KernelLibIoControl 的 源 代 碼 可 以 在 Kdriver.c 中 找 到 , 就 是
SC_KernelLibIoControl 。 SC_KernelLibIoControl 直 接 調 用 的
NKKernelLibIoControl,這個函數(shù)同樣在 kdriver.c 中。分析源碼可知,就是調
用了 giisr.dll 中的 IOControl,參數(shù)為 IOCTL_GIISR_INFO,就是傳遞進去了
一個 GIISR_INFO 結構體,用來給 Index 標示的數(shù)組元素賦值,這個 Index 就
是前面CreateInstance返回的那個數(shù)值,通過 hIsrHandler傳遞進去。
*/

d)??下面就是啟動IST,等待Event,這里和IST模型沒有任何區(qū)別。

到這里全部的初始化就完成了,可以看出,和IST模型相比就是多了兩步 b)和 c),
這兩步?jīng)Q定了中斷判斷的方式,這也是 IISR的根本所在。

? ?
3??中斷的判斷
下面詳細介紹下可安裝中斷在 ISR 中被判斷的過程。
同 樣 , 中 斷 到 來 時 進 入 的 函 數(shù) 是 OEMInterruptHandler , 在
OEMInterruptHandler中會調用NKCallIntChain來遍歷該IRQ對應注冊的IISR。
這是一個鏈表結構,所以對中斷判斷程序是一個順序調用的過程,即先注冊的設備先
判斷,如果判斷到正確的結果,則返回合法的 SYSINTR,OEMInterruptHandler
也同樣返回這個值。所以即使后面的設備也符合條件,也不會被執(zhí)行。如果整個鏈表
中都沒找到正確的設備,則返回 SYSINTR_CHAIN。OEMInterruptHandler 在判
斷到返回結果為SYSINTR_CHAIN 時,即表示請求中斷的設備不在鏈表中。

/* ARMCE深入
NKCallIntChain 的代碼在 KDriver.c 中,是個非常簡單的函數(shù),以傳遞進來的
IRQ 為 Index 找到鏈表的頭,然后去調用各鏈表節(jié)點的 hIsrHandler,并且以
CreateInstance 的返回值為參數(shù)。當有返回的值不是 SYSINTR_CHAIN 時,就返
回 這個值, 反之繼續(xù) 查找, 直到鏈表 尾部, 如果還沒 有找到, 就返 回
SYSINTR_CHAIN。
*/

4??自定義的 IISR
??我們可以不使用GIISR,而自己實現(xiàn)IISR功能,只要知道了IISR 的原理。

當以某一個寄存器或者地址的值,不足以判斷到底是系統(tǒng)中哪個設備觸發(fā)的中斷
的時候,GIISR 就不是這么好用了。比如多個不同的外設,使用同一個GPIO 來觸發(fā)
中斷。外設需要讀取多個寄存器或者需要一個復雜些的計算(不只是簡單的一個&操作)
才能判定中斷是否是其產(chǎn)生的。這時候我們需要使用自己的一套 IISR的處理方式。
當然我們不希望去改動整個微軟對于 IISR 的處理結構,所以我們就要區(qū)分開來上
面介紹的 GIISR 的模型里,哪些是微軟的架構,哪些是GIISR 自己的實現(xiàn)。

??微軟的 IISR 架構:
a)??首先需要使用 LoadIntChainHandler 去注冊這個 IISR 的處理判斷程序的
dll,在這個 dll中除了需要一個判斷處理程序(也就是通過
LoadIntChainHandler傳遞進去的那個參數(shù)),還需要一個CreateInstance
的函數(shù),這個是必須的。在你不改動微軟內(nèi)核的情況下,名字也是固定的,詳
細地函數(shù)定義,可以參考 GIISR 的 CreateInstance。至于 IOControl,最
好也參考 GIISR 的定義一個,如果不需要去調用KernelLibIoControl 的話,
應該是可以不實現(xiàn)的。

b)??在OEMInterruptHandler 中調用NKCallIntChain去遍歷鏈表,在調用處理
函數(shù)時將CreateInstance 的返回值作為參數(shù)傳遞進去,如果處理函數(shù)在判斷
到不是自己觸發(fā)的中斷,應該返回 SYSINTR_CHAIN,否則返回一個有意義
的 SYSINTR 值

c)??在需要注銷這個IISR 的時候,調用 FreeIntChainHandler,需要在dll中實
現(xiàn) DestroyInstance 這個函數(shù),被系統(tǒng)調用,這個是可選的。

GIISR 自己的實現(xiàn):
使用同一套代碼管理這些中斷處理程序,每個中斷處理程序在內(nèi)部的數(shù)組中占用
一項,這些項目記錄著中斷處理程序激活使用的SYSINTR 以及判定其觸發(fā)中斷的標
準。這個標準就是讀取某個寄存器或地址來用掩碼來判斷。同時這個數(shù)組項目對應的
結構體數(shù)據(jù)就是通過KernelLibIoControl 傳遞進去的。

??所以對于需要使用自己的特殊方式判斷中斷觸發(fā)的程序,可以使用自己的中斷判別
程序。
??我們可以為每一個中斷外設都實現(xiàn)自己的處理dll。在調用LoadIntChainHandler
時傳遞進自定義的一個 dll 與處理函數(shù),CreateInstance 一定要實現(xiàn),不過返回值
可以忽略。
??在處理函數(shù)中,我們直接根據(jù)自己的外設來判斷中斷條件,然后返回相應的
SYSINTR。

??其實使用 CreateInstance 的含義就是想把同一判斷類型的設備使用一套統(tǒng)一的
處理函數(shù)來判斷。CreateInstance 的返回值就是區(qū)別不同設備的這個 Index。

5 IISR資源的釋放
當我們需要注銷這個 IISR 的時候,需要調用 FreeIntChainHandler,來將該中
斷服務從鏈表中刪除。

FreeIntChainHandler(hIsrHandler);
hIsrHandler 就是LoadIntChainHandler 的返回值。
??/*ARMCE 深入
FreeIntChainHandler 函數(shù)實現(xiàn)同樣在 loader.c 中的SC_FreeIntChainHandler。
所做的動作就是,如果有 DestroyInstance 函數(shù),則調用 DestroyInstance。然后
調用 UnhookIntChain。UnhookIntChain的函數(shù)實現(xiàn)在 kdriver.c 中,是一個標準
的單向鏈表刪除其中一個元素的操作,這里不再詳細解釋。
??*/

6 使用 IISR的注意事項
由于 IISR 是動態(tài)的被加載的,也就是說注冊的 dll 會被加載到內(nèi)核空間。所以不
能調用任何非內(nèi)核的函數(shù)。
并且,如果將 IISR的 dll放在 bib文件的MODULES section里面,需要設置”K”
屬性,如
giisr.dll? ?? ?? ?? ?? ?$(_FLATRELEASEDIR)\giisr.dll? ?? ? NK? ?SHK

如果放在 FILES section 里面,需要保證沒有 fixup類型的變量。
? ???
六??WinCE 中斷的延遲
??1 造成中斷延遲的原因

圖 1 WinCE 中斷體系結構

重新看圖 1。這里畫出了從硬件中斷發(fā)生,到 IST 運行的全部過程,中間就是
我們要研究的延時部分。
圖中的”IST 延遲”標志,實際上就是我們所說的中斷延時。但是將 IST 延時細
分,可以分為如下幾部分延時:
a)??ISR 延時
這部分延時是指從硬件觸發(fā)中斷到進入OEM的 ISR程序的時間,在 ARM 體系
下,就是進入OEMInterruptHandler 的時間。

b)??ISR 執(zhí)行時間
在 OEMInterruptHandler 中判斷 IRQ,并且返回相應的 SYSINTR 的時間,
也是OEM最主要把握的時間。
c)??從ISR 返回到 IST運行的時間
主要就是系統(tǒng)根據(jù)ISR 返回的SYSINTR激活相應的Event,系統(tǒng)調度運行,
到 IST執(zhí)行的這段時間

2 如何降低中斷延時
上面的中斷延時原因中,a)是我們一般不去過問的部分,這段代碼是微軟實現(xiàn)
的,原則上是可以改的,但是收效不大,而且可能引入 bug,建議不要去動。c)是
我們可以部分控制的,關鍵就是IST的優(yōu)先級,其他部分我們也使用微軟默認的實
現(xiàn)。
b) 這 一 部 分 就 是 我 們 著 重 需 要 管 理 的 了 , 因 為 這 一 塊 就 是
OEMInterruptHandler 函數(shù)的實現(xiàn),是 OEM 自己實現(xiàn)的代碼。也就是說,判斷
中斷源,返回SYSINTR的過程是我們唯一較可行的控制中斷延時的地方。
關于這部分的優(yōu)化,首先就是盡量用較簡單的邏輯判斷 IRQ,來返回相應的
SYSINTR,而且 OEMInterruptHandler 會調用NKCallIntChain,所以 IISR 的
鏈表長度與 IISR處理函數(shù)的效率也是影響中斷延時的重要因素。
一般在判斷 IRQ 的過程中,我們會把最可能出現(xiàn)、最頻繁出現(xiàn)的IRQ 放在最前
面判斷,比如系統(tǒng)時鐘。這樣在剛進入OEMInterruptHandler就可以判斷到IRQ,
并返回,節(jié)省了時間,提高了效率。同樣這種方法也適用于 IISR,將最可能出現(xiàn),
最頻繁出現(xiàn)的設備放在鏈表的前面,可以提高遍歷的效率。


七??總結
WinCE 下提供了較靈活的中斷處理方式,包括ISR,IST,IISR 三種主要方式。
對于 ARM 架構下的系統(tǒng)開發(fā),我們常用的就是 IST 與 IISR 兩種方式。兩種方式
從本質上都是通過返回正確的SYSINTR來激活相應的 IST來服務中斷。不同點只是對
IRQ 判斷的方式,IST 是內(nèi)置的 OEM 寫死的判斷程序,而 IISR 是通過一個預留的接
口,來動態(tài)注冊判斷程序,從而給了系統(tǒng)一個注冊新中斷的機會。同時 IISR 可以實現(xiàn)
中斷共享,在一個 IRQ 上通過鏈表的方式不斷添加判斷程序,從而讓多個設備共享同
一個 IRQ,同時又可以有自己獨立的中斷判斷程序。
在最后,我們分析了中斷延時的一些因素,這里并沒有詳細的進行分析,只是提出
了一些降低中斷延時的方法。

參考文獻:
1.??Microsoft Windows CE .NET 中的中斷體系結構? ? , Nat Frampton
2.??Platform Builder for Microsoft Windows CE 5.0 Help, Microsoft
3.??Microsoft Windows Embedded CE 5.0 source code, Microsoft

總結

以上是生活随笔為你收集整理的WinCE中断结构分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美极品第一页 | 黄色片网站免费看 | 国产精品VideoSex性欧美 | 日韩视频免费观看高清完整版在线观看 | 91成人在线观看喷潮动漫 | 黄色网在线免费观看 | 日韩一区二区精品 | 波多野结衣在线影院 | 在线看黄免费 | 日韩精品美女 | 美女av毛片 | wwwxxxx在线观看 | 热播之家| 国产欧美精品在线 | 亚洲欧美另类激情 | 天天天色| 好吊妞视频在线 | 中字幕视频在线永久在线观看免费 | 日本亚洲高清 | 小色哥网站| 中文字幕av专区dvd | 国产福利短视频 | 少妇做爰免费视频播放 | 欧美精品久久久久久久久 | 91操人视频| 清纯唯美亚洲激情 | 毛片黄片免费看 | 青青草原亚洲视频 | 最新中文av| 69国产成人精品二区 | 91麻豆视频 | 欧美性视频播放 | 久久亚洲影视 | 国产一级二级三级精品 | 国产麻豆剧果冻传媒白晶晶 | 久久久久久91 | 日本色妞| 亚洲第一黄 | 私密spa按摩按到高潮 | mm131丰满少妇人体欣赏图 | 理论片av| 日韩色图片| 天天操天天玩 | 国产字幕在线观看 | 亚洲不卡视频在线 | 亚洲精品电影院 | 男人的天堂视频在线观看 | 搞中出 | 天天干干天天 | 伊人午夜| 国产一区视频在线免费观看 | 亚洲一二三区视频 | 国产人妖在线观看 | 国产不卡精品 | 成人h动漫精品一区 | 久久橹 | 男生和女生差差的视频 | 亚洲 欧美 日韩系列 | 欧美疯狂做受xxxxx高潮 | 国产sm在线观看 | 欧美精品乱码视频一二专区 | 日本欧美一本 | 91老师国产黑色丝袜在线 | 污污视频网站在线免费观看 | 骚色综合 | 日本人与黑人做爰视频 | 宅男视频在线免费观看 | 性xxxx欧美老肥妇牲乱 | 俄罗斯av片 | 国语对白永久免费 | 国际av在线 | 午夜福利理论片在线观看 | 黄色一级视频片 | 91精品国产电影 | 三级全黄的视频 | 已满十八岁免费观看全集动漫 | 六月综合网 | 欧美噜噜噜 | 顶级毛片 | 日韩av在线播放网址 | 青青草精品 | 中文字幕在线亚洲 | 欧美在线视频一区二区三区 | 精品一区二区免费看 | 午夜一二区 | 亚洲黄色成人网 | 口爆吞精一区二区三区 | 欧美一区二区日韩 | 久久精品国产亚洲a | 日韩永久 | 在线播放免费av | 91高清免费 | 亚洲第一区在线播放 | 日韩欧美成人一区二区 | 综合色伊人 | 欧美一区二区三区免费在线观看 | 中文在线观看免费高清 | 操操操影院 | 日韩欧美一区二区三区 |