將作業系統和相應硬體裝置串連起來,編寫聯絡硬體和軟體的驅動程式至關重要。本文主要討論在WinCE作業系統下,如何設計實現 S3C2410晶片具有I2C介面的驅動程式;詳細介紹WinCE下,流驅動程式的編寫方法,同時將驅動通過Platform Builder編譯進作業系統,最後用動態連結程式庫的方式提供給使用者使用。
關鍵詞:WinCE 流驅動 I2C匯流排 驅動程式
引言
隨著以電腦技術、通訊技術和軟體技術為核心的資訊技術的迅速發展,嵌入式系統在各行業得到了廣泛的應用,極大地推動了行業的滲透性應用。嵌入式系統是 “以應用為中心、以電腦技術為基礎、軟硬體可裁剪、適應應用系統對功能、可靠性、成本、體積、功耗嚴格要求的專用電腦系統”,由嵌入式硬體和嵌入式軟 件兩部分組成。嵌入式軟體包括嵌入式作業系統和嵌入式應用軟體。Microsoft的案頭作業系統已經為人們熟悉和使用,嵌入式的作業系統Windows CE.net也日益風行。Windows CE.net是Microsoft推出的功能強大的緊湊、高效、可伸縮的32位嵌入式作業系統,主要面對各種各樣的嵌入式系統和產品。該系統所具有的多線 程、多任務、完全搶佔式的特點是專為各種具有嚴格資源限制的硬體系統所設計的。為了將作業系統和硬體裝置串連起來,聯絡硬體和軟體的驅動就顯得很重要。
下面主要針對三星公司ARM9核心的晶片S3C2410進行分析,介紹在Windows CE.net系統下進行底層裝置驅動開發的方法並提供I2C通訊的執行個體。
1 I2C通訊協定及S3C2410晶片介紹
I2C(Inter Integrated Circuit)匯流排是1980年由Philips公司推出的。 I2C匯流排用兩條線(SDA和SCL)在匯流排和裝置之間傳遞資訊,在微控制器和外部裝置之間進行串列通訊或在主裝置和從裝置之間進行雙向資料傳送。兩條通 信線通過上拉電阻被拉升至+5 V。在控制系統中的每個整合電路可以通過一個CMOS緩衝器來讀每一條線路,也可以通過一個柵極開路的FET管將每一條線的電平下拉。因此,對每個晶片來 說,每條線既是輸入線,又是輸出線。
I2C匯流排遵從同步串列傳輸協議,即各位串列(一位接一位)發送,由時鐘(clock)線指示讀資料(data)線的時刻。每個資料包前有一個地址,以指示由哪個器件來接收該資料。
S3C2410是一款基於ARM920T的16/32位RISC微處理器,主要用於手持功能,擁有高性價比,低功耗等特點,也是目前市面上出現較多的嵌 入式開發板的處理器之一。晶片擁有16 KB的指令和資料緩衝器,有儲存嵌入式管理單元(MMU)、LCD控制器、3個串口、4路DMA、4個時鐘定時器、8路10位的A/D轉換;支援I2C、 I2S、SPI、主從USB等介面以及SD/MMC卡。
S3C2410微處理器的I2C匯流排可以處於下面4種模式下:主接收模式、主發送模式、從接收模式和從發送模式。處理器對I2C進行的操作,主要是對下面的幾個寄存器進行讀/寫:
◇ IIC控制寄存器,IICCON(物理地址0X54000000,記憶體映射後的虛擬位址);
◇ IIC控制/狀態寄存器,IICSTAT(物理地址0X54000004);
◇ IIC資料寄存器,IICDS(物理地址0X54000008);
◇ IIC地址寄存器,IICADD(物理地址0X5400000C)。
本設計主要是CPU工作在主模式下與下面的I2C介面裝置進行通訊。
2 Windows CE系統驅動特點
Windows CE.net驅動有兩種模型:本機裝置驅動程式和流介面驅動程式。本機裝置驅動適於整合到基於Windows CE.net平台的裝置。這些裝置驅動程式是一些硬體所必需的,是由原始裝置製造商建立的,用以驅動如鍵盤、觸控螢幕、音訊裝置等,往往在裝置售出後就不會 再更換,如通用LED驅動、電源驅動、鍵盤驅動和顯示驅動等都是本機裝置驅動。對於本機裝置驅動程式,Platform Builder提供了一些驅動程式樣本,目的是為了方便開發人員快速開發出自己的驅動程式。當Win CE系統啟動時,本地裝置驅動程式將被載入到系統的記憶體中。本地驅動程式的開發分為分層驅動和整合型驅動程式。分層驅動要利用微軟提供的與應用程式通訊的上 層,稱為模組驅動程式層MDD(Model Device Driver)。MDD層通過裝置驅動程式介面DDI(Device Driver Interface)與應用程式通訊,開發驅動程式通常不修改MDD層,主要關心與具體硬體相關的下層,依賴平台的裝置驅動程式層PDD (Platform Dependent Driver), PDD層通過裝置驅動服務介面(Device Driver Service Provider Interface)直接管理硬體。流介面裝置驅動程式(指可安裝的啟動程式)可以由第三方生產商提供,以支援添加到系統中的裝置。Windows CE下的裝置驅動程式在與應用程式相同的保護級上工作。當系統啟動時,大多數驅動程式是由裝置管理進程(DEVICE.EXE)載入的,所有這些驅動程式 將共用同一個進程地址空間。
3 I2C匯流排底層驅動設計
I2C匯流排驅動是放在Windows CE作業系統的核心下層,位於OEM Adaptation Layer(OAL)層的一個真正的驅動。
3.1 初始化I2C中斷和編寫ISR常式
I2C的通訊是通過操作I2C的寄存器進行的。在I2C通訊中主要對上面介紹的4個寄存器進行讀寫。通過讀寫這些寄存器中的命令狀態字可以檢測和控制I2C匯流排的行為。在Windows CE.net下,首先要在檔案oalintr.h添加I2C的中斷號的宏定義:
#defineSYSINTR_I2C(SYSINTR_FIRMWARE+19)
然後在檔案cfw.c的檔案中添加I2C中斷的初始化,禁止和複位。具體代碼如下:
在OEMInterruptEnable函數中加入
case SYSINTR_IIC:
s2410INT->rSRCPND=BIT_IIC;
if (s2410INT->rINTPND & BIT_IIC) s2410INT->rINTPND = BIT_IIC;
s2410INT->rINTMSK&= ~BIT_IIC;
break;
在OEMInterruptDisable函數中加入
case SYSINTR_IIC:
s2410INT->rINTMSK = BIT_IIC;
break;
在armint.c檔案中添加ISR程式,處理中斷髮生後返回定義的中斷號。具體代碼如下:
在OEMInterruptHandler函數中添加
else if (IntPendVal == INTSRC_IIC) {
s2410INT->rSRCPND= BIT_IIC; /* 清除中斷 */
if (s2410INT->rINTPND & BIT_IIC) s2410INT->rINTPND= BIT_IIC;
s2410INT->rINTMSK = BIT_IIC; /* I2C中斷禁止 */
return (SYSINTR_RTC_ALARM);
}
3.2 編寫流驅動程式
I2C匯流排驅動程式採用的是Win CE流驅動的標準形式。在IIC_Init的函數中,首先通過函數VirtualAlloc()和VirtualCopy(),把晶片中針對I2C的物理 地址和作業系統的虛存空間聯絡起來,對虛擬位址空間的操作就相當於對晶片的物理地址進行操作。地址映射的代碼如下:
reg = (PVOID)VirtualAlloc(0, sz, MEM_RESERVE, PAGE_NOACCESS);
if (reg) {
if (!VirtualCopy(reg, addr, sz, PAGE_READWRITE PAGE_NOCACHE )) {
RETAILMSG( DEBUGMODE,( TEXT( "Initializing interrupt //n//r" ) ) );
VirtualFree(reg, sz, MEM_RELEASE);
reg = NULL;
}
}
其中sz是申請的長度,addr是申請虛擬位址空間的實際物理地址在Win CE中的映射地址。
然後對申請到的虛擬位址進行操作,安裝Windows中的流驅動的模型進行驅動的編寫,主要包括下面函數的編寫。
IIC_Init()
在函數中,主要是對I2C的初始化,主要語句如下:
v_pIICregs = ( volatile IICreg *)IIC_RegAlloc((PVOID)IIC_BASE, sizeof(IICreg));
v_pIOPregs = ( volatile IOPreg *)IOP_RegAlloc((PVOID)IOP_BASE, sizeof(IOPreg));
v_pIOPregs->rGPEUP = 0xc000;
v_pIOPregs->rGPECON = 0xa00000;
v_pIICregs->rIICCON = (1<<7) (0<<6) (1<<5) (0xf);
v_pIICregs->rIICADD= 0x10;
v_pIICregs->rIICSTAT = 0x10;
VirtualFree( ( PVOID )v_pIOPregs,sizeof( IOPreg ),MEM_RELEASE );
v_pIOPregs = NULL;
if ( !StartDispatchThread( pIIcHead) )
{ IIC_Deinit( pIIcHead );return ( NULL );}在StartDispatchThread()函數中,主要是建立線程、關聯事件和中斷,主要語句如下:
InterruptInitialize( 36,pIicHead->hIicEvent,NULL,0 );//關聯時間和中斷
CreateThread( NULL,0,IicDispatchThread,pIicHead,0,NULL );//建立線程等待時間
在IicDispatchThread()函數中,主要是等待中斷的產生,然後去執行:WaitReturn = WaitForSingleObject( pIicHead->hIicEvent,INFINITE );
IicEventHandler( pIicHead );//事件處理函數
InterruptDone( 36 );
最後,在函數IIC_Open、IIC_Read、IIC_Write中,對各個寄存器進行操作,進行資料的賦值,得到I2C讀取的資料和發送資料。
4 I2C驅動的封裝和添加到Windows CE中
通過上面的工作,能編譯一個DLL函數,但這還不能叫流介面驅動程式。因為它的介面函數還沒有匯出,還需要告訴連結程式需要輸出什麼樣的函數,為此要建立一個自己的def檔案,可以用記事本建一個,取名mydrive.Def:
LIBRARY MyDriver
EXPORTS
IIC_Close
IIC_Deinit
IIC_Init
IIC_IOControl
IIC_Open
IIC_PowerDown
IIC_PowerUp
IIC_Read
IIC_Seek
IIC_Write
然後同樣用記事本編寫一個註冊表檔案,取名為mydrive.reg:
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/STRINGS]
"Index"=dword:1
"Prefix"="IIC"
"Dll"="MyDriver.dll"
"Order"=dword:0
最後編寫自己的CEC檔案。主要是添加一個Build Method,任務是複製註冊表到Win CE的系統目錄下面。加一個Bib File,其主要功能是把編譯的mydrive.dll檔案添加到系統核心中去。儲存寫好的CEC檔案。開啟Platform Builder,開啟“File”菜單,添加剛剛編寫的CEC特徵到系統選項中去。產生系統的時候,添加自己的CEC特性,就可以包含剛剛編寫的I2C驅 動了。
以上介紹了Win CE的驅動結構,並給出了基於Win CE的 I2C驅動程式部分原始碼。實驗證明該設計是可行的