《電子技術應用》
您所在的位置:首頁 > 嵌入式技术 > 业界动态 > C64x系列DSP/BIOS中设备驱动程序的设计

C64x系列DSP/BIOS中设备驱动程序的设计

2008-08-04
作者:陈 彬 魏 丹 邓德祥

??? 摘 要:為了高效地對外部設備" title="外部設備">外部設備進行控制,給硬件設備編寫驅(qū)動程序是一種有效的解決方法。C64x系列的DSP系統(tǒng)提出了類/微型 驅(qū)動模型的驅(qū)動程序結構。實踐結果表明,采用類/微型驅(qū)動模型進行驅(qū)動程序設計后,應用軟件可以復用絕大部分相似設備的驅(qū)動程序,因而極大地提高了驅(qū)動程序的開發(fā)效率。
??? 關鍵詞: 數(shù)字信號處理器? I/O" title="I/O">I/O設備驅(qū)動? 類/微型驅(qū)動模型? 實時操作系統(tǒng)

?

??? 隨著新技術的不斷涌現(xiàn)和DSP實時系統(tǒng)的日趨復雜,不同類型的外部設備越來越多。為這些外部設備編寫驅(qū)動程序已經(jīng)成為依賴操作系統(tǒng)管理硬件的內(nèi)在要求。但是,由于內(nèi)存管腳、響應時間和電源管理等條件的限制,為一個給定的DSP系統(tǒng)編寫設備驅(qū)動程序有時候會很困難。針對設備驅(qū)動程序開發(fā)者遇到的上述難題,TI公司為C64x系列[1]DSP的開發(fā)者提供了一種類/微型驅(qū)動模型(class/mini-driver model)[2]。該模型在功能上將設備驅(qū)動程序分為依賴硬件層和不依賴硬件層兩層,兩層之間使用通用接口。實踐結果表明,采用類/微型驅(qū)動模型進行設計后,應用軟件可以復用絕大部分相似設備的驅(qū)動程序,從而提高驅(qū)動程序的開發(fā)效率。
1 類/微型驅(qū)動模型簡介
??? 在類/微型驅(qū)動模型中,類驅(qū)動通常用于完成多線程I/O請求的序列化功能和同步功能,同時對設備實例進行管理。在包括視頻系統(tǒng)I/O和異步I/O的典型實時系統(tǒng)中,只有少數(shù)的類驅(qū)動需要表示出外部設備的類型。
??? 類驅(qū)動通過每個外部設備獨有的微型驅(qū)動對設備進行操作。微型驅(qū)動通過控制外設的寄存器、內(nèi)存和中斷資源對外部設備實現(xiàn)控制。微型驅(qū)動程序必須將特定的外部設備有效地表示給類驅(qū)動。例如:視頻顯示設備存在一些不同的幀存,應用軟件會根據(jù)不同的I/O操作進行幀存的分配,此時微型驅(qū)動必須映射視頻顯存,使得類驅(qū)動可以對不連續(xù)的內(nèi)存(分別存放RGB或YUV分量)設計特定的I/O請求。
??? 類/微型驅(qū)動模型允許發(fā)送由開發(fā)者定義數(shù)據(jù)結構的I/O請求包給微型驅(qū)動來控制外部設備,此分層結構使設備驅(qū)動的復用能力得到加強,并且豐富了發(fā)送給微型驅(qū)動的I/O請求包的結構。
??? 類/微型驅(qū)動模型結構如圖1所示。上層的應用程序" title="應用程序">應用程序不直接控制微型驅(qū)動,而是使用一個或一個以上的類驅(qū)動對其進行控制。每一個類驅(qū)動在應用程序代碼中表現(xiàn)為一個API[3]函數(shù)并且通過微型驅(qū)動的接口IOM與微型驅(qū)動進行通信。類驅(qū)動使用DSP/BIOS" title="DSP/BIOS">DSP/BIOS中的API函數(shù)實現(xiàn)諸如同步等的系統(tǒng)服務。

?


??? 類驅(qū)動通過標準的微型驅(qū)動接口調(diào)用微型驅(qū)動控制硬件設備。到目前為止DSP/BIOS共定義了三種類驅(qū)動:流輸入輸出管理模塊(SIO)、管道管理模塊(PIP)和通用輸入輸出模塊(GIO)。在PIP和SIO類驅(qū)動中,調(diào)用的API函數(shù)已經(jīng)存在于DSP/BIOS的PIP和SIO模塊中。這些API函數(shù)需將參數(shù)傳給相應的適配" title="適配">適配模塊(adapter),才能與微型驅(qū)動交換數(shù)據(jù)。而在GIO類驅(qū)動中,調(diào)用的API函數(shù)則直接與微型驅(qū)動通信(需在CCS2.2以上)。
??? 每一個微型驅(qū)動都為類驅(qū)動和DSP/BIOS設備驅(qū)動管理提供了標準接口。微型驅(qū)動采用芯片支持庫(Chip Support Library)[4]管理外圍設備的寄存器、內(nèi)存和中斷資源。
2 類驅(qū)動的編寫
??? SIO和PIP兩個接口模塊用于支持DSP和外設之間的數(shù)據(jù)交換。這兩種模塊都可以通過類驅(qū)動中的適配模塊和微型驅(qū)動的IOM連接進行數(shù)據(jù)傳輸。SIO的適配模塊稱為DIO,PIP的適配模塊稱為PIO。
??? GIO模塊[5]的傳輸模式是基于流輸入輸出模式的同步I/O模式,更適合文件系統(tǒng)I/O。在編寫類驅(qū)動時,可以直接調(diào)用GIO的讀寫API函數(shù),這些函數(shù)的接口已經(jīng)內(nèi)置于微型驅(qū)動的IOM中。
2.1 SIO模塊和DIO模塊
??? DSP/BIOS中的SIO模塊為每個DSP/BIOS線程提供一個獨立的I/O機制,它支持動態(tài)創(chuàng)建。SIO模塊有自己的驅(qū)動模型,稱為DEV。DEV程序和微型驅(qū)動的編寫方法相似,都要實現(xiàn)函數(shù)表中的打開、關閉和緩存管理等函數(shù),然而結構比較復雜。相比之下,DIO模塊可以簡化SIO模塊和IOM之間的連接,使得通信和同步變得更簡單。
??? DIO模塊必須實現(xiàn)下列基本功能函數(shù):
??? (1)回調(diào)函數(shù) 在外設的通道實例創(chuàng)建結束時,如果微型驅(qū)動已經(jīng)完成內(nèi)存分配,那么適配模塊將通過回調(diào)函數(shù)通知微型驅(qū)動待調(diào)用函數(shù)的地址,同時回調(diào)函數(shù)也將通知適配模塊緩存已經(jīng)建立,并最終通知上層應用程序。
??? (2)傳輸函數(shù)? 傳輸函數(shù)將調(diào)用微型驅(qū)動中的mdSubmitChan函數(shù)。微型驅(qū)動中的mdSubmitChan函數(shù)將從適配模塊獲得一塊緩存,并將緩存中的新信息通過通道實例通知給中斷服務程序(ISR)。DIO模塊通過傳輸函數(shù)實現(xiàn)應用程序與微型驅(qū)動之間的通信。
2.2 PIP模塊和PIO模塊
??? DSP/BIOS中PIP模塊提供管理異步I/O的數(shù)據(jù)管道。每個管道對象都擁有一塊同樣大小的緩存,這些緩存分別為同樣數(shù)量的等長小塊。小塊的數(shù)量和長度在DSP/BIOS中設置。雖然小塊的長度是固定的,但應用程序可以把小于這個長度的數(shù)據(jù)放入緩存小塊中。一個管道有兩個結束狀態(tài):寫完緩存和讀完緩存。通常,無論哪個結束狀態(tài)都會激活I/O設備。數(shù)據(jù)通知函數(shù)用來執(zhí)行讀寫同步任務和通知PIP緩存填滿或清空。寫數(shù)據(jù)時,PIP_alloc函數(shù)用來獲得緩存,PIP_put函數(shù)用于將數(shù)據(jù)寫入緩存。寫完后,讀數(shù)據(jù)通知函數(shù)notifyReader將被調(diào)用。讀數(shù)據(jù)時,PIP_get函數(shù)用來接收緩存中的數(shù)據(jù),PIP_free函數(shù)在數(shù)據(jù)不再被使用時將緩存清空。清空完后,寫數(shù)據(jù)通知函數(shù)notifyWriter將被調(diào)用。
??? PIO模塊通過PIP模塊從應用程序中獲得緩存,并將獲得的緩存提供給微型驅(qū)動使用。當微型驅(qū)動使用完緩存時,PIO模塊還可以將緩存交還給應用程序。
??? PIO模塊必須實現(xiàn)下列基本功能函數(shù):
??? (1)主函數(shù)? 當應用程序給設備分配緩存時,PIP的緩存管理調(diào)用rxPrime和txPrime函數(shù)。這兩個函數(shù)調(diào)用DSP/BIOS的API函數(shù)獲得緩存并提供給微型驅(qū)動使用。主函數(shù)負責給適配模塊和應用程序的緩存分配發(fā)送起始信號。
??? (2)回調(diào)函數(shù)? 當微型驅(qū)動已完成內(nèi)存分配時,適配模塊通過回調(diào)函數(shù)rxCallback或txCallback通知微型驅(qū)動待調(diào)用函數(shù)的地址,同時回調(diào)函數(shù)也通知適配模塊緩存已經(jīng)建立,并最終通知給上層應用程序。
??? (3)傳輸函數(shù):傳輸函數(shù)將調(diào)用微型驅(qū)動中的mdSubmitChan函數(shù)。mdSubmitChan函數(shù)將從適配模塊中獲得一塊緩存,并將緩存的新信息通過通道實例通知給中斷服務程序(ISR)。PIO模塊通過傳輸函數(shù)實現(xiàn)應用程序與微型驅(qū)動之間的通信。
2.3 GIO模塊
??? GIO模塊在提供必要的同步讀/寫API函數(shù)及其擴展函數(shù)的同時,將代碼和使用數(shù)據(jù)緩存的大小盡量簡化。如圖2所示,應用程序可以調(diào)用GIO的API函數(shù)直接與微型驅(qū)動的IOM交換數(shù)據(jù),這些API函數(shù)使得GIO成為了第三種類驅(qū)動。

?


??? 當調(diào)用GIO_create創(chuàng)建一個外部設備的通道實例時,GIO在通道實例中增加了狀態(tài)和I/O請求狀態(tài)結構、IOM數(shù)據(jù)包(IOM_Packets)及一個GIO數(shù)據(jù)對象。GIO創(chuàng)建的通道實例的數(shù)據(jù)結構如下:
??? typedef struct GIO_Obj {
??? IOM_Fxns *fxns;??????? ?/* 函數(shù)表指針 */
??? Uns mode;????????????? ?/* 創(chuàng)建模式?? */
??? Uns timeout;?????????? ?/* 超時時間?? */
??? IOM_Packet syncPacket; ?/* 同步時使用的IOM_Packet */
??? QUE_Obj freeList;????? ?/* 異步I/O隊列 */
??? Ptr syncObj;?????????? ?/* 同步對象地址 */
??? Ptr mdChan;??????????? ?/* 通道實例地址 */
??? } GIO_Obj, *GIO_Handle;
??? 函數(shù)表指針是應用程序和微型驅(qū)動函數(shù)表(fxns)的接口;創(chuàng)建模式包括:輸入(IOM_INPUT)、輸出(IOM_OUTPUT)和雙向(IOM_INOUT);IOM_Packet在類驅(qū)動和微型驅(qū)動間的異步操作時使用;同步對象地址指向特定通道的同步信號;通道實例地址指向微型驅(qū)動創(chuàng)建的通道實例。
3 微型驅(qū)動的設計和實現(xiàn)
??? 類/微型驅(qū)動模型中的微型驅(qū)動直接控制外部設備。只要微型驅(qū)動創(chuàng)建了規(guī)定的函數(shù),應用程序就可以方便地通過DIO適配模塊、PIO適配模塊或(和)GIO類驅(qū)動調(diào)用。這些規(guī)定的函數(shù)包括:通道綁定函數(shù)(mdBindDev)、通道創(chuàng)建/刪除函數(shù)(mdCreateChan/mdDeleteChan)、I/O請求發(fā)送函數(shù)(mdSubmitChan)、中斷服務函數(shù)(ISRs)和設備控制函數(shù)(mdControlChan)。這些規(guī)定的函數(shù)將放入微型驅(qū)動的函數(shù)接口表(IOM_Fxns)中的相應位置,供應用程序通過適配模塊或GIO類驅(qū)動調(diào)用。函數(shù)接口表的結構如下:
??? typedef struct IOM_Fxns
??? {
??????? IOM_TmdBindDev????? ?mdBindDev;
??????? IOM_TmdUnBindDev??? ?mdUnBindDev;
?????? ?IOM_TmdControlChan? ?mdControlChan;
????? ??IOM_TmdCreateChan?? ?mdCreateChan;
????? ??IOM_TmdDeleteChan?? ?mdDeleteChan;
????? ??IOM_TmdSubmitChan?? ?mdSubmitChan;
??? } IOM_Fxns;
3.1 綁定通道函數(shù)
??? DSP/BIOS設備初始化時將調(diào)用每個已注冊到微型驅(qū)動中的綁定函數(shù)(mdBindDev)。綁定函數(shù)一般要實現(xiàn)下列功能:根據(jù)配置的設備參數(shù)和可能存在的全局設備數(shù)據(jù)初始化外圍設備;掛入中斷服務函數(shù)(ISRs);獲得緩存、McBSPs、McASPs和DMA等資源。
??? 如果微型驅(qū)動使用多個外部設備,則DSP/BIOS為每個外設調(diào)用綁定函數(shù)。設備參數(shù)devid用來區(qū)分設備。如果支持一個設備,則綁定函數(shù)必須檢查是否已經(jīng)有設備綁定。
??? 微型驅(qū)動如果使用靜態(tài)數(shù)據(jù)來減少實時處理的動態(tài)數(shù)據(jù)分配,可以使用輸入/輸出數(shù)據(jù)指針(devp)。輸入/輸出數(shù)據(jù)指針將傳給通道創(chuàng)建函數(shù)(mdCreateChan)。
3.2 通道創(chuàng)建/刪除函數(shù)
??? 從應用的觀點出發(fā),在應用程序和外部設備之間必須有一個邏輯交流通道用來交換數(shù)據(jù)。應用程序通過微型驅(qū)動創(chuàng)建一個或多個邏輯通道對象作為應用程序的邏輯通道。通道創(chuàng)建函數(shù)(mdCreateChan)根據(jù)需要創(chuàng)建通道對象并給通道對象設置初始值。通道刪除函數(shù)(mdDeleteChan)則刪除已創(chuàng)建好的通道對象。雖然每個微型驅(qū)動的通道對象數(shù)據(jù)結構都略有不同,但有些字段是必須的,如通道模式、等待I/O 包序列和回調(diào)函數(shù)。以下是一個常見的通道對象數(shù)據(jù)結構:
??? typedef struct ChanObj {
??????? Bool inuse;?????? /*如果為TRUE,則通道已打開*/
??????? Int mode;?????????????? ? ?/*通道模式*/
????? ??IOM_Packet *dataPacket;? ?/*I/O 包*/
????? ??QUE_Obj pendList;??????? ?/*等待I/O 包序列*/
????? ??Uns *bufptr;????????????? ??/*當前緩存指針*/
????? ??Uns bufcnt;?????????????? ??/*未處理的緩存數(shù)目*/
??? ? ??IOM_TiomCallback cbFxn;?? ?/*回調(diào)函數(shù)*/
????? ??Ptr cbArg;????????? ???/*回調(diào)函數(shù)參數(shù)地址*/
??? } ChanObj, *ChanHandle;
3.3? I/O請求發(fā)送函數(shù)
??? 微型驅(qū)動中的I/O請求發(fā)送函數(shù)(mdSubmitChan)用來處理IOM_Packet包中的命令字段。根據(jù)不同命令字段,微型驅(qū)動將處理命令或返回錯誤信息(IOM_ENOTIMPL)。
??? 微型驅(qū)動支持的命令字段有:IOM_READ、IOM_WRITE、IOM_ABORT和IOM_FLUSH。微型驅(qū)動創(chuàng)建的輸入通道由IOM_READ命令來執(zhí)行輸入任務,創(chuàng)建的輸出通道則由IOM_WRITE命令來執(zhí)行輸出任務。要放棄或者刷新已經(jīng)發(fā)送的I/O請求,可以使用IOM_ABORT或IOM_FLUSH命令。當放棄時,I/O請求包隊列中的所有輸入輸出請求都將被放棄。當刷新時,所有的I/O輸出包順序執(zhí)行,而所有的輸入I/O包都被放棄。
3.4 中斷服務函數(shù)
??? 微型驅(qū)動的中斷功能就是去處理外部設備的觸發(fā)事件,例如周期性的中斷。中斷通常是表示外設采樣完數(shù)據(jù)或者處理完數(shù)據(jù),也可以用于為DMA提供同步信號,微型驅(qū)動必須處理這些中斷。通常微型驅(qū)動中的中斷服務函數(shù)ISRs必須完成以下功能:出列IOM_Packet請求;設置下一次傳送或服務請求;調(diào)用類驅(qū)動的回調(diào)函數(shù)以保證和應用程序同步,并返回IOM_Packet。
3.5 設備控制函數(shù)
??? 微型驅(qū)動支持的控制操作因不同的外部設備而異。IOM定義了一些通用的控制代碼供驅(qū)動程序調(diào)用。特定設備獨有的控制代碼必須自己編寫,其特征值必須大于128(IOM_CNTL_USER)。目前IOM支持的通用的控制代碼有:
??? IOM_CHAN_RESET:將創(chuàng)建的通道實例重新恢復到初始狀態(tài)。
??? IOM_CHAN_TIMEDOUT:當應用程序或類驅(qū)動超時時,此控制代碼將進行超時操作。例如,一個超時的IOM_Packet,如果沒執(zhí)行回調(diào)函數(shù),可能會被返回類驅(qū)動。
??? IOM_DEVICE_RESE:外部設備重新恢復到初始狀態(tài),它將影響為這個外部設備創(chuàng)建的所有通道實例。
??? 微型驅(qū)動支持的控制代碼和控制操作必須告訴使用微型驅(qū)動的應用程序開發(fā)者,特別要注明該代碼的針對對象(是針對通道實例還是針對設備實例)。例如:改變外設波特率的控制代碼,必須注明是針對某個通道或者所有通道的,否則容易給應用程序帶來錯誤。
4 類/微型驅(qū)動模型驅(qū)動應用實例——C64x系列DSP/BIOS中PCI設備的驅(qū)動
4.l 微型驅(qū)動的設計與編寫
??? (1)設計mdBindDev的部分程序代碼:
??? static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
??? {
????? ??……
?????? ?QUE_new(&device.highPrioQue); /* 建立IOM包隊列 */
????? ??QUE_new(&device.lowPrioQue);
????? ??……
??????? hwiAttrs.ccMask = IRQ_CCMASK_NONE;
????????/*初始化PCI中斷 */
??????? hwiAttrs.arg = NULL;
????????IRQ_map(IRQ_EVT_DSPINT, intrId);
??????? HWI_dispatchPlug(intrId, (Fxn)isr, -1, &hwiAttrs);
??? }
??? (2)設計mdCreateChan的部分程序代碼
???? static Int mdCreateChan(Ptr *chanp, Ptr devp,String name,Int mode,Ptr chanParams, IOM_Tiom Callback cbFxn, Ptr cbArg)
??? {?
??????? ……
????? ? chan = MEM_alloc(0, sizeof(ChanObj), 0);
??????? chan->queue = &device.highPrioQue; /*通道初始化 */
??????? ……
??????? if (device.openCount == 0) {
????????? PCI_intEnable(PCI_EVT_PCIMASTER); /*PCI設備中斷初始化 */
??????????……
????????? IRQ_enable(IRQ_EVT_DSPINT);
??????? }
??????? *chanp = chan; ???/*返回創(chuàng)建通道 */
??? }
??? (3)設計mdSubmitChan的部分程序代碼
??? static Int mdSubmitChan(Ptr chanp, IOM_Packet *pPacket)
??? {
????????ChanHandle chan = (ChanHandle)chanp;/*掛載已創(chuàng)建通道 */
?????? ?……
?????? ?req=(C64XX_PCI_Request *)packet->addr;/*I/O請求包地址*/?
????????req->reserved = chan;
????? ??……
??????? /*處理讀寫請求包 */
????? ??if (packet->cmd == IOM_READ || packet->cmd ==IOM_WRITE) {
??????????? imask = HWI_disable();
??????????? QUE_enqueue(chan->queue, packet)
??????????? ……
??????? }
????? ??……/* 處理其它功能的請求包? */
???? ?? removePackets(chan, packet->cmd);/*移除已處理的請求包 */
??? }
??? 中斷服務函數(shù)(ISRs)和設備控制函數(shù)(mdControlChan)的結構與以上I/O請求發(fā)送函數(shù)(mdSubmitChan)的結構類似,本文不再作敘述。
4.2 在DSP/BIOS中注冊微型驅(qū)動
??? 打開DSP/BIOS配置工具,如圖3所示。右鍵點擊User-Defined Devices圖標,選擇插入選項,并重新命名為PCICHAN。右鍵點擊PCICHAN,選擇屬性選項,進行注冊,如圖4所示。

?

?


4.3 編寫類驅(qū)動
??? 本例的類驅(qū)動使用通用輸入輸出模塊,首先右鍵點擊圖3中的GIO Manager,選擇啟動GIO。在應用程序中,GIO_create函數(shù)使用微型驅(qū)動PCICHAN來創(chuàng)建通道實例,通過調(diào)用GIO_submit函數(shù)完成應用程序?qū)CI設備的讀寫操作等。源代碼如下:
??? (1)創(chuàng)建通道
??? GIO_Handle???????????pciChan;
??? C64XX_PCI_Attrs???? ?pciChanParam;
??? C64XX_PCI_Request?? ?pciChanRequest;
??? C64XX_PCI_DevParams ?pciChanDevParam;
??? GIO_AppCallback???? ?pciChanCallBack;
??? pciChan= GIO_create('/PCICHAN',IOM_INOUT, &status, NULL, NULL);
??? (2)發(fā)送讀請求包
??? pciChanRequest.srcAddr = (Ptr)BitsBuffer;
??? pciChanRequest.dstAddr = (Ptr)m_DspControl.CstartAddr;
????pciChanRequest.byteCnt = length+20;
?? ?pciChanRequest.options =? PCI_WRITE;
?? ?pciChanReqSize = sizeof(pciChanRequest);
?? ?status = GIO_submit(pciChan,IOM_WRITE,&pciChanRequest,&pciChanReqSize,NULL);
??? 通過上述三個步驟,PCI設備的DSP/BIOS驅(qū)動設計就基本上完成了。應用程序可以通過使用類驅(qū)動來復用PCI設備,這樣極大地提高了驅(qū)動的工作效率,對PCI外設的控制也大為簡化了。
參考文獻
1 TMS320C64x Technical Overview. Literature Number:?SPRU395B.Texas Instruments Incorporated, January 2001
2 DSP/BIOS Driver Developer’s Guide. Literature Number:?SPRU616. Texas Instruments Incorporated,November 2002
3 TMS320C6000 DSP/BIOS Application Programming Interface(API) Reference Guide. Literature Number: SPRU403E.Texas Instruments Incorporated,October 2002
4 TMS320C6000 Chip Support Library API Reference Guide.Literature Number: SPRU401E.Texas Instruments Incorporated,December 2002
5 TMS320C6000 Peripherals Reference Guide.Literature Number:SPRU190D. Texas Instruments Incorporated,February 2001

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認版權者。如涉及作品內(nèi)容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經(jīng)濟損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。