CE下基于Zylonite硬件平台的SD卡驱动开发
摘要:本文結合實際項目(一款以WINCE為操作系統內核的GSM/PHS雙模智能手機)對嵌入式系統Windows?CE5.0的底層驅動(SD卡)的架構進行了分析和研究,以MARVELL公司提供的基于INTEL?Zylonite硬件平臺的BSP為基礎,利用Windows?CE5.0的Platform?Builder集成開發環境(IDE)開發適合實際項目的SD卡驅動代碼,分別以輪詢和中斷方式實現該驅動的動態加載,并深入分析SD卡驅動(流驅動)的詳細的加載過程。?
關鍵詞:Zylonite??Platform?Builder???BSP??SD卡驅動?
0、引言
隨著通信領域新業務需求的不斷增長及計算機技術,半導體技術和電子技術的術的迅速發展,嵌入式系統異軍突起,已經滲透到社會生活的方方面面了。它是集軟件,硬件于一體的高可靠性系統。其最大特點即為可以通過裁減裝卸系統模塊來配置整個平臺所要求的功能。
???????? Windows CE是由微軟公司所開發的一個嵌入式操作系統,它與Windows平臺的編程接口有很強的兼容性。其平臺開發工具Platform Builder是一個完全集成的開發環境(IDE)。本項目所涉及的硬件開發套件Intel Zylonite Development System裝配有Intel的Xscale芯片處理器Monahans L(PXA300),并配有相關外設電路接口(USB2.0,SD/MMC,音頻,以太網口等)及外設(觸摸屏,KEYPAD,揚聲器,聽筒,話筒等)。其獨特的結構優化能力保證了操作環境和通用應用設備可以在高頻率和的情況下快速處理任務。
?
1、?WINCE?下的SD卡驅動架構
Wince?下SD卡驅動協議棧組成?:
u???????HOST硬件底層部分?(主控制端驅動)???????SDHC_XXX.DLL
u???????BUS?中間邏輯命令層?(總線驅動)?????????????????????SDBUS.DLL
u???????CLIENT上層(客戶端驅動)????????????????????????????? SDMEMORY.DLL
?
1.1、主控制端驅動
?
?????主控制端驅動控制包含主控制器硬件,遵循主控制端驅動接口,它被用于總線驅動通信和設置操作參數。主控制器驅動接口提供一個硬件提取層,在總線和主控制端執行之間。即:SDHC_XXX.DLL是最底層,因為這層是硬件關聯層,因此取名XXX便是為了對應的具體的硬件BSP包(如本項目的硬件平臺是ZYLONITE,其硬件供應商給的BSP包名即為ZYLONITE,在實際項目中我們便將SDHC_XXX.DLL取代為SDHC_ZYLONITE.DLL),它負責具體的發命令,大多數情況下都需要修改。
1.2、總線驅動
總線驅動作為提取和管理層處于主控制驅動和客戶端驅動之間。它包括在SDbus.dll文件。為客戶端驅動提供了標準的API,允許運行在任何的基于windows ce設備。總線驅動將是獨立于應用程序和主控制端驅動,在不同的處理器之間移植,并不需要改動。SDBus.dll是中間層,負責整合命令和管理。
1.3、客戶端驅動
客戶端驅動和SD客戶端驅動通信接口允許客戶端驅動去和SD設備通信。客戶端驅動接口是有計劃地抽象SD總線物理設備的執行,提供了客戶端驅動最大的彈性。客戶端驅動接口允許客戶端驅動去衡量一個單一的,同步的訪問存儲卡驅動使用一個線程,異步通信設備驅動。SDMemory.dll是最高層,類似于應用層。
?
2.立足微軟SD卡協議棧開發Zylonite?的BSP包的SD卡驅動
當我們開發SD卡驅動時,并詳細分析比較了Microsoft的SD驅動架構和Intel所提供的BSP內的參考SD卡驅動以后,可以得出如下結論:
l?????????針對主控制端驅動(SDHC_XXX.DLL):因為這一層是直接操作硬件的一層,所以大多數情況下都需要修改。修改的內容基本為收發命令部分以及數據傳輸和硬件初始化部分.
l?????????針對總線驅動(SDBUS.DLL):因為這一層處于主控制驅動和客戶端驅動之間,用于他們之間的通信,SD卡總線請求都放在它里面,微軟提供了非常完備的樣例代碼,所以我們一般都不需要改動,直接調用它的接口就可以了。
l?????????針對客戶端驅動(?SDMEMORY.DLL):因為SDMemory就是所謂的Client層,類似于應用層,它還可用來識別卡的,不同種類的卡,比如sd memory card等,鑒于我們只需開發SD卡部分的驅動,所以也不需要怎么修改了(如果我要開發SD接口的SDIO設備,那么就得在這層做比較大的改動了)。
Intel所提供的BSP內的參考SD卡驅動自己實現了主控制端驅動(SDHC_ZYLONITE.DLL),而調用并保留了總線驅動(SDBUS.DLL)和客戶端驅動(?SDMEMORY.DLL)。因此結合具體的硬件設計(SD卡的CONNECTOR等),我們的主要任務便是利用BSP內的SD卡主控制端驅動代碼,開發(配置并改進)我們實際項目內的SD卡驅動。
2.1、Zylonite BSP內的SD卡主控制端驅動概述
SD卡的驅動程序是以流的形式提供的,而該SD卡主控制端驅動以sdhc_zylonite.dll?的形式提供,入口在:\WINCE500\PLATFORM\Zylonite\public\csp\monahans\sdhc
有如下兩個文件:
l?????????sdcontrol.c:內含一個非常重要的線程---SDControllerISTHandler,?????????
????????????????主要負責卡與控制器的交互,處理控制器接收的消息等,具體的控制和處理函數均在此文件中。
l?????????main.c:??????SDH(主控制端驅動)的導出流接口在該文件中實現,并???
?????????????????????包含有主控制端驅動的(sdhc_zylonite.dll)的入口點。
SD卡硬件初始化及其主控制端驅動的注冊表信息設置路徑為:
?\WINCE500\PLATFORM\Zylonite\Platform\ZYLONITE\SRC\DRIVERS\SDHC
主要文件為:
l?????????impl.c:?主要是在加載SD卡主控制端驅動時初始化硬件。內含一個非
?常重要的線程---- SDCardDetectIstThread,專門處理SD卡的插拔操作。但是具體的插拔操作也是在Sdcontrol.c文件實現的。
2.2、結合實際項目的開發流程
2.2.1?SD卡的外部引腳及功能配置
在實際項目(一款以WINCE為操作系統內核的GSM/PHS雙模智能手機)中,SD卡的外部引腳與Monahans_L的GPIO連接圖及連接控制器的電路圖如下所示:
?
??? 由上可得,先要配置SD卡的外部引腳及功能。而SD卡的引腳配置在其下的?\source?文件夾的xllp_mmc_board.c文件XllpMMCConfigure函數內修改。(特別注意:GPIO34要配成檢測SD卡插入的中斷源。)
2.2.2、分析修改并改進主控制端驅動重要線程及硬件初始化部分代碼
l?????????SD卡主控制端驅動加載及架構解析
需要聲明的是SD卡驅動加載順序是:
加載SDBus.dll→加載sdhc_zylonite.dll→加載sdmemory.dll
我們在這里只詳細討論第2步(sdhc_zylonite.dll的加載),此時SDBus.dll已經加載成功。WINCE系統初始化后,會載入DEVICE.EXE,?對應代碼devload.C中的WINMAIN函數會被調用起來,從而啟動InitDevice函數,此函數會搜尋(\WINCE500\PLATFORM\Zylonite\Platform\ZYLONITE\SRC\DRIVERS\SDHC下的sdhc_zylonite.reg)注冊表根鍵,準備參數調用WIN32 API接口-----Activedevice,接著利用Dllmaincrtstartup函數找到sdhc_zylonite.dll的入口,執行該文件的入口函數DllMain()然后繼續返回到DEVICE.EXE(devload.C),調用launchdevice()函數,再調用sdhc_zylonite.dll的入口main.c文件內的SDH_Init(),自此將開始將開始SD卡主控制端驅動的初始化過程:
1.?調用SDH_Init()
2.?調用?SDHCDAllocateContext()?來分配一段主控制器的上下文
a)Context?是總線驅動和主控制端驅動共享的
3.?主控制端驅動使用SDHCDSetXxx宏來填充這個上下文結構
a)這個步驟是把主控制器向總線驅動描述一下
b)包括函數指針,支持的電流,最大時鐘,槽數目,SDIO的支持等等。
4.?調用?SDHCDRegisterHostController()?來把自己向總線驅動注冊一下
5.??當總線驅動準備處理SD事件時,它會調用主控制端驅動的init?函數(pContext->pInitHandler)
接著便是sdbus.dll驅動部分的代碼和SD卡主控制端驅動部分的交互設置:比如設置電源、時鐘和總線寬度等。一般都是sdbus.dll發起請求,再去調用主控制端驅動部分的API,這里最后詳細分析插槽狀態交互確認,因為這是成功加載sdhc_zylonite.dll的關鍵。當有SD卡在插槽,sdbus.dll的slotstatuschange()調用并建立一個重要線程SDcardDetectIstThread(),當探測到有卡,即返回給sdbus.dll,?總線驅動即可調用HandleAddDevice()函數,自此初始化結束,sdhc_zylonite.dll加載成功。
l?????????對主控制端驅動重要線程SDcardDetectIstThread()代碼的改進
在前面的敘述中,可以看出線程SDcardDetectIstThread()在sdhc_zylonite.dll最后的加載起決定性作用。然而我們發現在INTEL所給的BSP中,在檢測卡的過程里,其采用了輪詢的方式----即每隔一定的時間,CPU都會去讀一次GPIO34的電平,以確定SD卡是否被插入或拔出,以此來判定是否去加載或卸載SD卡的客戶端和主控制端驅動。很顯然,這種方式的弊端是占用了過多的CPU資源,效率很低,嚴重影響了整個系統的實時性。因此,最能解決這個問題的辦法無外乎是使用中斷檢測的方式。以下特別敘述采用2種不同的中斷機制的方式實現:
1中斷綁定靜態配置:
1.在Bsp_cfg.h文件內定義一個系統中斷號SYSINTR_SDMMC_DETECT
#define SYSINTR_SDMMC_DETECT (SYSINTR_FIRMWARE+N) N為當前已定義的最大值(以保證此中斷未使用過)。
2.在Xllp_gpio_plat.h文件中找出GPIO34的定義:#define XLLP_GPIO_MMC_CD_0 34
3.在intr.c文件里將系統中斷號和IRQ關聯:
OALIntrStaticTranslate(SYSINTR_SDMMC_DETECT, IRQ_GPIO_SHARE(XLLP_GPIO_MMC_CD_0));
4.在主控制端驅動的硬件初始化代碼Impl.c中的InitializeHardware()加入?EnablesdcardInterrupt()函數。
5.在Impl.c中完善EnablesdcardInterrupt(),加入GPIO上升沿或下降沿的檢測和SET EVENT。??
6.在Impl.c文件中定義hCardInsertInterruptEvent并在SetupCardDetectIST()內創建hCardInsertInterruptEvent
7.Impl.c文件中初始化dwSysintrCD= SYSINTR_SDMMC_DETECT,并綁定相應的EVENT:InterruptInitialize????(dwSysintrCD,hCardInsertInterruptEvent,NULL,0)
8.?????改進線程SDcardDetectIstThread()的While部分代碼,加入WaitForSingleObject( hCardInsertInterruptEvent, dwTimeout );只有當hCardInsertInterruptEvent被置上,才會往下走,否則一直在此處等待。
9.同上原理改寫CardremoveInterrupt用于動態卸載SD卡主控制端驅動。
2中斷綁定動態配置:
1.???????????????在Impl.c文件的SetupCardDetectIST()函數內動態配置系統中斷號和硬件中斷源:KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwSDCDIrq, sizeof(DWORD), &(dwSysintrCD), sizeof(DWORD), NULL))。此處的&dwSDCDIrq可在SD卡主控制端驅動的注冊表內更改后,用LoadPlatformRegistrySettings函數加載進來。可在sdhc_zylonite.reg?文件內將"CardDetectIRQ"?的值改為“IRQ_GPIO_SHARE_BASE+x-2”?在本平臺內,IRQ_GPIO_SHARE_BASE=52,X=34。
2.???????????????接上5-6-7-8-9。
總結
以上是生活随笔為你收集整理的CE下基于Zylonite硬件平台的SD卡驱动开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为畅享50系列今天发:麒麟芯、鸿蒙OS
- 下一篇: 硬上三缸被市场教“做人” 全新福特福克