vxworks嵌入式操作系統下串行設備驅動程序開發思路
sysIntEnablePIC (devParas[i].intLevel);
}
}
其中,宏INUM_TO_IVEC的作用是把中斷號轉為中斷向量。i8250Int是指向輸入/輸出中斷處理函數的指針。描述相應硬件的結構i8250Chan為函數i8250int()的入口參數。
至此,設備硬件的初始化、相關的低層函數的掛接、中斷初始化基本完成。開始進行下一步,將設備的驅動函數安裝在Driver Table 中。
⑶ 與上層標準輸入/輸出函數的掛接
在此處I/O系統通過調用ttyDrv()(在沒有定義INCLUDE_TYCODRV_5_2的情況下)將相應驅動函數添加到Driver Table中,從而完成與上層標準輸入/輸出函數的掛接。
由上圖知,iosDrvInstall()函數在Driver Table中掛接的函數是tyWrite()和tyRead(),而不是我們實際編寫的輸入/輸出函數。其具體的調用過程是:
① 當用戶調用write函數進行寫操作時,根據相應的fd調用在Driver Table中注冊的函數tyWrite(),此函數的作用是將用戶緩沖區的內容寫入相應的輸出ring buffer,當發現緩沖區內有內容時,開始調用回調函數tyITX(),從ring buffer讀取字符,由I8250Startup()啟動中斷輸出,最后由設備的輸出中斷服務程序(在本例中調用的是sysOutbyte())將字符發往指定的串口。
② 當串口接收到數據時會調用輸入中斷服務程序(在本例中是sysInbyte()),將輸入的字符寫入指定的緩沖區。然后由回調函數tyIRd()將緩沖區的內容讀入ring buffer,當用戶調用read函數進行寫操作時,會根據相應的fd調用在Driver Table中注冊的函數tyRead(),此函數會將ring buffer中的內容讀入用戶緩沖區。
關于具體的中斷輸入/輸出函數如何調用,本文不做詳細分析,請參閱i8250int()及i8250Startup()。
對于輸入/輸出控制函數ioctl()的掛接,則是直接將命令傳到由用戶編寫的i8250ioctl()函數,其具體的實現代碼與驅動的設計思路無緊密的聯系,本文也不做具體分析。
⑷ 具體設備與相關驅動的掛接
當Driver Table中相應的驅動函數掛接完成,開始編寫驅動程序的最后一步:在Device Table中加入設備,完成具體設備與相關驅動的掛接。此項工作是由ttyDevCreat()函數完成的。本函數主要實現以下功能:
① 分配并初始化一個device descriptor。
② 通過調用tyDevInit()初始化tyLib。此處主要完成輸入/輸出ring buffer的創建、建立用與相關函數的信號量、初始化selectLib。
③ 調用iosDevAdd()將串口設備加入Device Table。對于設備特性的描述信息是由sysSerialChanGet()函數得到,并以參數形式傳入的。
④ 為底層設備安裝回調函數,在本例中是為i8250CHAN 安裝tyIRd()、tyITx()兩處回調函數。
⑤ 開中斷,設備開始以中斷方式工作。
至此,驅動程序的分析全部完成。與掛接驅動函數不同,在安裝設備的過程中,無論設備相同與否,有幾個設備則上述過程需調用幾次。以上各函數的加載主要在usrinit()函數中完成。
3. 結束語
需要說明的是,在VxWorks下,設備驅動程序既可以嵌入內核隨系統一起啟動,也可以作為可加載模塊在系統啟動之后運行。相比之下,后一種方式比較簡單,不用修改系統內核,引入錯誤的可能性小。但是無論采取哪種方式,其基本思路及需要完成的工作是相同的。本文沒有按照系統的調用過程進行一步步分析,主要基于上述考慮。用戶在編寫相關驅動程序時,中心任務是按步驟完成上述功能,而沒有必要去死搬系統的加載步驟。
linux操作系統文章專題:linux操作系統詳解(linux不再難懂)








評論