基于μCOS-II 的USB主機系統
摘 要:USB(Universal Serial Bus)是目前應用非常廣泛的一種總線(xiàn)形式。其即插即用、熱插拔、接口體積小巧等優(yōu)點(diǎn)給計算機外設連接技術(shù)帶來(lái)重大變革。μCOS-II 是一個(gè)源碼公開(kāi)、完整的、可移植、可固化、可裁剪的嵌入式實(shí)時(shí)操作系統,可以方便地移植到多種微處理器上。以在新太科技實(shí)際工作中的LPC2378 讀卡器為例,詳細介紹μCOS-II 中USB 主機系統的設計。
本文引用地址:http://dyxdggzs.com/article/202191.htmμC/OS-II 是美國學(xué)者Lacrosse 設計的一個(gè)優(yōu)秀的嵌入式實(shí)時(shí)操作系統,其代碼絕大部分用ANSIC 語(yǔ)言編寫(xiě),可用于8 位、16 位、32 位、甚至64 位微處理器、微控制器、數字信號處理器等,具有操作系統最基本最核心的功能,非常適于在小型系統和片上系統(SOC)中使用。USB 為個(gè)人電腦與嵌入式設備之間的連接提供了一種標準化、單一化的接口,其高效性和可靠性使得它已經(jīng)成為嵌入式系統的首選接口。此LPC2378 讀卡器具有卡票檢測、消費扣錢(qián)、系統升級、下發(fā)黑名單、在線(xiàn)充值、余額查詢(xún)等功能,但這些功能的實(shí)現都依賴(lài)于上位機的請求,業(yè)務(wù)應用模塊只有在獲得相應的請求后才能進(jìn)行相應的處理并將處理結果返回給上位機。而USB 主機系統就是起銜接上位機和業(yè)務(wù)應用模塊的功能,接收上位機請求以及將業(yè)務(wù)應用模塊的結果返回給上位機。
1 構建μC/OS-II系統環(huán)境
1.1 移植μC/OS-II 到LPC2378 開(kāi)發(fā)板
嵌入式操作系統作為大多數嵌入式應用系統的軟件平臺,它管理著(zhù)系統的資源,為應用軟件提供各種必要的服務(wù)。在嵌入式應用系統中使用嵌入式系統,可以提升嵌入式應用系統的開(kāi)發(fā)效率,但是在得到嵌入式操作系統提供服務(wù)之前,關(guān)鍵是要將嵌入式操作系統移植到目標板上。
移植條件:
移植μC/OS-II 之前需要注意,目標處理器必須滿(mǎn)足以下五點(diǎn)要求:
1. 處理器的C 編譯器能產(chǎn)生可重入型代碼;2. 處理器支持中斷,并且能產(chǎn)生定時(shí)中斷(通常為10-100Hz);3. 用C 語(yǔ)言可以開(kāi)/關(guān)中斷;4. 處理器能支持一定數量的數據存儲硬件堆棧(可能是幾KB);5. 處理器有將堆棧指針以及其他CPU 寄存器的內容讀出并保存到堆?;騼却嬷腥サ闹噶?。
LPC2378 系列ARM7 微控制器可以滿(mǎn)第2、4 和5 點(diǎn)要求,使用ADS 的C 編譯器可以滿(mǎn)足1 和3 點(diǎn)要求。
移植步驟:
OS_CPU.H 的移植:
在OS_CPU.H 文件中定義與處理器相關(guān)的數據類(lèi)型,例如BOOLEAN,INT8U 和INT8S 等。根據ADS1.2編譯器的特性定義。在OS_CPU.H 文件中定義與處理器相關(guān)的宏, 主要是進(jìn)出臨界區代碼OS_ENTRER_CRITICAL()、OS_EXIT_CRITICAL()。
將OS_ENTRER_CRITICAL()和OS_EXIT_CRITICAL()定義為軟件中斷函數,所以還要編寫(xiě)相應的軟件中斷處理代碼(可以在OS_CPU_C.C 文件中編寫(xiě))實(shí)現開(kāi)/關(guān)中斷。同樣定義OS_TASK_SW()為軟件中斷函數,并編寫(xiě)相應的軟件中斷處理代碼(調用OS_IntCtxSw 函數)實(shí)現任務(wù)切換。
OS_CPU_C.C 的移植:
在OS_CPU_C.C 中需要編寫(xiě)10 個(gè)相關(guān)的函數,為:OSTaskStkInit();OSTaskDellHook();OSTaskIdleHook ();OSTaskTickHook()等函數。其中9 個(gè)系統Hook函數可以為空函數,也可以根據用戶(hù)自己的需要編寫(xiě)相應的操作代碼。任務(wù)棧結構初始化函數OSTaskStkInit()必須根據移植時(shí)統一定義的任務(wù)堆棧結構進(jìn)行初始化。
OS_CUP_A.ASM 的移植。
μC/OS-II 移植要求編寫(xiě)的匯編語(yǔ)言函數為:
OSStartHightRdy();OSCtxSw();OSIntCtxSw();OS_TickISR()。當然這些程序不一定非得用匯編,也可以用嵌入式C 語(yǔ)言來(lái)完成。
至此,完成μC/OS-II 在A(yíng)RM7 處理器LPC2378上代碼的移植,其大部分代碼與μC/OS-II 在其他ARM7 處理器上的移植是通用的。
1.2 USB 驅動(dòng)程序設計
μC/OS-II 提供了多任務(wù)實(shí)時(shí)操作系統的內核。在應用這個(gè)操作系統時(shí)候,用戶(hù)通常需要自己編寫(xiě)基于μC/OS-II 的外圍器件驅動(dòng)程序,以使外圍器件能在操作系統的協(xié)調下更好的為用戶(hù)服務(wù)。為了使軟件可移植性強,易維護,采用分層的方法編寫(xiě)USB 的驅動(dòng)程序。綜合考慮USB 協(xié)議、USB 硬件接線(xiàn)、μC/OS-II的結構來(lái)進(jìn)行分層,下表所列為USB 驅動(dòng)程序分層結構。
1.2.1 USB 硬件抽象層。
USB 硬件抽象層的主要任務(wù)是對USB 模塊的相關(guān)硬件進(jìn)行配置,是USB 驅動(dòng)程序的最底層與具體硬件相關(guān)的一層。主要完成的任務(wù):初始化USB 設備控制器為系統配置USB 時(shí)鐘控制器,選擇信號映射端口(在LPC 系列中只有LPC2378 有此功能),配置電源;配置USB 設備控制器中斷,此系統禁止了同步傳輸幀中斷,使端點(diǎn)處于低優(yōu)先級中斷;以及配置軟件控制接連、斷開(kāi)和重新連接USB 功能的相關(guān)寄存器。
1.2.2 USB 命令接口層。
USB 命令接口層是在USB 硬件的角度來(lái)描述USB 的具體功能是獨立于操作系統之外的,也是協(xié)議層和驅動(dòng)層實(shí)現的基礎。USB 命令接口層函數基本是和具體的USB 寄存器相關(guān)的,通過(guò)操作寄存器完成相應的功能。
1.2.3 USB 協(xié)議層。
USB 協(xié)議層主要由 Descriptor.c 和Chap_9.c 文件組成。在Descriptor.c 定義了各描述符,是在USB 硬件的基礎上描述此讀卡器的USB 模塊,分別為:設備描述符、配置描述符、接口描述符和端點(diǎn)描述符。這些描述符也是上位機枚舉、識別讀卡器USB 模塊的媒介。而Chap_9.c 就是上位機枚舉讀卡器USB 模塊時(shí)USB 模塊回饋上位機的具體實(shí)現,其中大部分函數都是依賴(lài)于USB 命令接口層。
1.2.4 USB 驅動(dòng)層。
USB 驅動(dòng)層是屬于USB 驅動(dòng)程序中最上層的是與μC/OS-II 系統聯(lián)系最緊密的一層。在其他各層的基礎上從系統的角度描述了USB 通信功能,是與操作系統和應用程序直接聯(lián)系的一層。包括系統啟動(dòng)時(shí)初始化USB 硬件的接口以及等待接收主機枚舉過(guò)程發(fā)送的SETUP 包等函數的接口。其中USB 端點(diǎn)的讀寫(xiě)函數USB_ReadPort(INT8U endp, INT32U eppsize,INT8U buffnums, CTRL_USB *pUsb, INT32U len,INT8U *recbuff, INT16U timeout) 和USB_WritePort(INT8U endp, INT32U eppsize, INT8Ubuffnums, CTRL_USB *pUsb, INT8U *sendbuff,INT32U len, INT16U timeout)實(shí)現了接收上位機的請求和將處理結果返回給上位機。
以讀函數為例描述USB 接收上位機請求的過(guò)程,由函數原型的最后一個(gè)參數timeout 可知,讀過(guò)程是一種阻塞性的操作,在此系統中是以信號量的方式來(lái)實(shí)現阻塞型的讀操作的。在參數檢測無(wú)誤時(shí)調用USB_WaitEpReady(pUsb, timeout)以獲取該端點(diǎn)對應信號量,若獲取失敗則此端點(diǎn)無(wú)數據可讀。當上位機發(fā)送數據到相應的端點(diǎn)時(shí)會(huì )產(chǎn)生中斷,中斷處理程序會(huì )判斷哪個(gè)端點(diǎn)產(chǎn)生了中斷,然后發(fā)送此端點(diǎn)所對應的信號量,這樣USB_WaitEpReady(pUsb, timeout)就可以獲得信號量完成讀操作,否則程序會(huì )等待timeout時(shí)間,如果在timeout 時(shí)間內依然獲取信號量失敗那程序就出錯返回。若讀取長(cháng)度大于端點(diǎn)緩沖區的長(cháng)度的話(huà)則一次只能讀取端點(diǎn)緩沖區長(cháng)度數,分多次讀取,直到讀取規定長(cháng)度為止。寫(xiě)端點(diǎn)函數發(fā)送過(guò)程和讀端點(diǎn)函數接收過(guò)程實(shí)現流程大體相似,其中最大的區別就是中斷產(chǎn)生的時(shí)機不同,接收過(guò)程是在數據到達相應端點(diǎn)緩沖區時(shí)產(chǎn)生中斷,而發(fā)送過(guò)程是將數據寫(xiě)到相應端點(diǎn)緩沖區之后才產(chǎn)生中斷。這樣在將數據發(fā)往相應緩沖區后再調用USB_WaitEpReady(pUsb,timeout),若在此函數中成功獲得信號量則說(shuō)明發(fā)生成功。
2 USB系統軟件設計
USB 的系統軟件是與μC/OS-II 操作系統和業(yè)務(wù)應用模塊緊密關(guān)聯(lián)的。在μC/OS-Ⅱ對USB 進(jìn)行初始化時(shí),不但要對USB 硬件接口初始化,還需要對其相關(guān)軟件進(jìn)行初始化,比如:設置中斷處理函數,以及單獨創(chuàng )建一個(gè)TaskSetup 任務(wù)以完成上位機對USB 系統主機的枚舉。中斷處理過(guò)程采用的是非向量中斷的方式,首先由中斷狀態(tài)寄存器的值判斷中斷產(chǎn)生的原因,然后由不同的原因設置不同的中斷處理函數。如果是數據中斷話(huà)則在相應的中斷處理函數中發(fā)送對應端點(diǎn)的信號量,這樣USB 驅動(dòng)程序中讀寫(xiě)接口才能成功被調用。TaskSetup 是系統的第一個(gè)任務(wù),只有在TaskSetup 任務(wù)中USB 主機系統被成功枚舉后才能進(jìn)行通信。枚舉過(guò)程主要是通過(guò)0 號端點(diǎn)的控制傳輸方式進(jìn)行的,在此過(guò)程中USB 主機系統接收上位機發(fā)送的Setup 包,然后根據Setup 包的不同請求進(jìn)行相應的處理再通過(guò)控制端點(diǎn)將結果返回給上位機。在USB 中0 號端點(diǎn)為控制端點(diǎn)一共有2 個(gè)分別為輸入和輸出端點(diǎn)。設備枚舉其實(shí)就是一個(gè)上位機識別USB 主機系統的過(guò)程,標準USB 枚舉過(guò)程如下:獲取設備描述符、復位、設置地址、再次獲取設備描述符、獲取配置描述符、獲取接口和端點(diǎn)描述符、獲取字符串描述符、選擇設備配置。枚舉成功之后USB 主機系統處于就緒狀態(tài)并且配置所有的接口與端點(diǎn)。
在USB 體系結構中數據的交互是以端點(diǎn)為基本單位的,端點(diǎn)的集合表現為接口,在USB 協(xié)議中一個(gè)接口表現為一個(gè)功能。USB 協(xié)議中規定端點(diǎn)0 只用于控制傳輸的,其余端點(diǎn)用于數據傳輸。本USB 主機系統的數據傳輸方式為端點(diǎn)1 采用中斷傳輸,端點(diǎn)2 采用批量傳輸。不論哪種傳輸方式都是以中斷的方式和系統交互的,但在中斷處理程序中所做的工作非常少只是發(fā)送信號量,真正與數據相關(guān)的操作并沒(méi)有在中斷處理程序中。這種中斷理念是根據Linux 操作系統的中斷上下文思想而設計的:使中斷時(shí)間盡量的短,將一些對時(shí)間要求不是那么嚴格的事務(wù)延遲在中斷之外進(jìn)行。在Linux 中把中斷處理分為上下兩部分,中斷處理程序是上部分,收到一個(gè)中斷后它會(huì )立即執行,但只做有嚴格時(shí)限的工作例如對接收到的中斷進(jìn)行應答或硬件復位,能夠被允許稍后完成的工作推遲到下半部去。比如網(wǎng)卡:數據包的接收是至關(guān)重要的以提高網(wǎng)絡(luò )吞吐量和傳輸周期以及避免超時(shí),處理和操作數據包的其他工作被推遲到下半部執行。
3 結語(yǔ)
隨著(zhù)電腦外設和數碼產(chǎn)品的不斷發(fā)展,各種設備之間的互連成為當前需要解決的難題。USB 是現今PC領(lǐng)域廣泛運用的總線(xiàn)接口技術(shù),在一些嵌入式系統中,人們希望有USB 的出現,然而和系統其他模塊相比,USB 模塊顯得更加的復雜。本文詳細闡述了設計一個(gè)USB 主機系統的過(guò)程,綜合考慮USB 協(xié)議,USB 硬件連接和μC/OS-II 系統使軟件易于維護,移植型強。
評論