CE5.0下SD卡驅動開發(一)

SD卡驅動開發的概念
Windows ce 的SD卡驅動協議棧包含總線驅動,主控制端驅動,客戶端驅動。
總線驅動作爲提取和管理層處於主控制驅動和客戶端驅動之間。它包括在SDbus.dll文件。爲客戶端驅動提供了標準的API,允許運行在任何的基於windows ce設備。總線驅動將是獨立於應用程序和主控制端驅動,在不同的處理器之間移植,並不需要改動。

主控制端驅動控制包含主控制器硬件,遵循主控制端驅動接口,它被用於總線驅動通信和設置操作參數。主控制器驅動接口提供一個硬件提取層,在總線和主控制端執行之間。

客戶端驅動和SD客戶端驅動通信接口允許客戶端驅動去和SD設備通信。客戶端驅動接口是有計劃地抽象SD總線物理設備的執行,提供了客戶端驅動最大的彈性。客戶端驅動接口允許客戶端驅動去衡量一個單一的,同步的訪問存儲卡驅動使用一個線程,異步通信設備驅動。

SD卡主控制端驅動
SD卡主控制驅動是軟件構成,控制主控制器硬件和遵循主控制器軟件接口(和主線驅動通信並且設置操作參數)。主控制驅動使用API設置輸出口,被總線驅動去註冊和取消註冊。
註冊包括提供信息關於host and slot的性能,包含最大時鐘速率,可接受的電壓範圍,SD卡的總線寬度,上電延遲。註冊提供回調函數,插槽選擇操作、電源操作、和總線請求操作。
SD卡使用動態結構,隨時允許主控制器去註冊或取消註冊。
主控制驅動接口提供硬件抽象層在總線驅動和主控制器執行之間。主控制驅動包含平臺和芯片集相關代碼,只有通過這些接口和總線驅動通信。這些將保持總線驅動獨立於主控制器和平臺設置。這些主控制驅動接口是隻爲主控制端驅動需要,和其它客戶驅動API無關。
主控制驅動:
包含控制器,插槽,邏輯支持,並且包含實際的硬件執行。
執行SD和MMC發送和接收。
能夠被內存映射設備在邏輯總線上,作爲一個完整的控制,或在一個外圍總線上作爲PCMCIA,PIC,和USB。
能夠使用I/O編程或DMA。
SD卡驅動體系結構考慮到每一個系統主控制器的沒限制。多個插槽的必須使用獨立的電源、時鐘、總線寬度控制。這些將承認系統在不同的SD接口條件下去識別卡。
SD卡主控制端可以選擇1位或4位模式,時鐘頻率可以設定在0至25M,主控制端驅動負責註冊插槽性能爲總線驅動。
一個主控制器可以基於任何的從總線結構,例如,一個PCI-based主控制可以作爲流驅動被加載。

SD卡和MMC的兼容性
SD卡的物理接口和協議都兼容於MMC規格,包括外觀(這裏講的是普通SD卡,現在有miniSD和microSD,插槽並不兼容,可以通過轉換插槽,也可以在硬件設計的時候把插槽設計成microSD兼容的樣式,以適應現在主流的SD卡設備)。早期的7線SD插槽在是個MMC插槽同樣風格,這允許在同樣的硬件結構下通用。一個通用的插槽連接器可以支持兩種卡類型。
在同一協議級別上,某些SD卡命令並不支持MMC設備,一個SD memory-aware host可以確定控制的是SD卡或MMC。
WINCE SDIO控制器可支持MMC的功能性。

SD卡總線驅動
SD卡總線驅動抽象了主控制端的物理執行,去提供給客服驅動一個單一的發送命令方法,和總線拓撲無關。如果是處於性能因素,客戶端驅動必須知道卡物理連接的詳細情況,它可以通過詢問總線驅動來得到。
總線驅動公開了一組服務爲客戶端驅動和一組服務爲主控制端驅動。兩種服務都是爲了去減少驅動的複雜操作。例如客戶端驅動的加載和卸載。SD卡詢問和鑑別,客戶端驅動總線請求,和IO取消。這些操作都是通過總線驅動來實現的。
當一個卡被插入到總線驅動,它便有一組動作去確定卡的類型和加載適合的客戶端驅動。SD總線驅動加載客戶端驅動是使用ActivateDeviceEx函數。
由於SD卡協議棧的分層結構,總線驅動抽象了SD卡協議,提供給客戶端驅動。這個抽象隱藏了所有的主控制端的底層硬件操作。因爲這些抽象是單純基於軟件的,所以客戶端驅動可以操作再任何硬件平臺下。
總線驅動提供了在安全線程下多客戶端驅動的同步訪問。如果客戶端驅動在運行時,卡拔出插槽或多功能卡去除某部分功能時,總線驅動提供了適當的持續和同步事件。

SD卡的客戶端驅動
在SD卡的識別過程中,總線驅動執行了總線的處理去確定SD設備的種類和類型。在卡的種類或類型上,總線驅動加載了客戶驅動使用適當的協議和設備關聯。總線驅動加載客戶驅動基於熱插拔從SD卡讀的信息。
安裝一個客戶端驅動在一個released設備,ISV(獨立軟件開發商)將提供一個應用程序去安裝客戶端驅動在設備上,並且設置適當的註冊表鍵值和卡的驅動匹配。
客戶端驅動可以同步或異步發送命令到卡。如果客戶端驅動不需要電源或性能隨異步操作而增長,SD卡協議棧提供了一個單一的同步接口,爲了從客戶端驅動中去除大量的複雜性。
客戶端驅動反彙編BSQUARE SD協議棧適當的功能,當使用CE SD協議棧。然而,一個客戶端驅動反彙編CE SD協議棧將沒有BSQUARE SD協議棧的功能,使用的LEGACY_COMPATIBILITY_MODE的值必須定義在Sdcardapistubs.cpp文件裏面。

客戶端驅動的入口
SD卡客戶端驅動是一個標準的流接口驅動,執行標準的流接口入口點。這些入口點只有*_Init (Device Manager) and *_Deinit (Device Manager)是必須的。這些功能總是被調用在設備加載或卸載的時候。一個或更多的進入點執行是必要的,爲了去提供一個應用程序接口給設備。*_Open (Device Manager), *_Close (Device Manager), *_Write (Device Manager), *_Read (Device Manager), *_Seek (Device Manager), or *_IOControl (Device Manager)

SD卡客戶端驅動不使用*_PowerUp (Device Manager) and *_PowerDown (Device Manager)函數。電源管理通過使用它的IOCTLs。然而,客戶端驅動可以執行這些進入點去上電和去電的通知信息。上電和去電的只被使用於通知設備事件。自從這些函數被調用在非獨佔的中斷環境,很少可以做除了設置設備標誌外?
一個DLL入口點被CE模塊調用,一旦一個DLL被加載或卸載。客戶端驅動初始化或卸載初始化SD卡庫。下面的例子是一個DLL的進入點:
BOOL SDMemoryDllEntry (HINSTANCE  hInstance,
  ULONG Reason,
  LPVOID pReserved)
{
  if(Reason == DLL_PROCESS_ATTACH ) {
    if(!SDInitializeCardLib()) {
      fRet = FALSE;
    }
  }
  else if(Reason == DLL_PROCESS_DETACH ) {
    SDDeinitializeCardLib();
  }
  return fRet;
}
客戶端驅動的進入點必須同樣包含在相關的sources文件裏面。下面代碼例子給出了在sources文件內客戶端驅動的進入點。
DLLENTRY = SDMenoryDllEntry
客戶端驅動的註冊
SD卡客戶端驅動沒有和輸出函數直接連接。相反的,這些函數調用去訪問客戶端驅動得通過客戶端的註冊過程。
在這個過程期間,客戶驅動通過他自己的信息給總線驅動,並且接收信息需要去調用給外部函數。在註冊之後,提供宏使能客戶端驅動去訪問那些API。這些宏只被客戶端驅動使用。

去完成註冊的過程,客戶端驅動必須使用SDRegisterClient爲SD設備發送它的本地設備信息,和一個友名給總線驅動。
卡信息結構
一個SDIO卡包含一個或多個卡信息結構(CIS)。一個SD客戶端驅動將需要從這些結構中讀出信息,以獲得卡的性能和功能。
一個CIS被組成一個塊的數據鏈,包含標準和特殊的應用信息。一個SDIO卡有一個所有卡的公共CIS區域,和每一個卡都有一個獨自的CIS區域。客戶端驅動可以從CIS區域讀出它自己的功能,或從公共CIS區域,通過使用CommonCIS參數標誌。

SDGetTuple函數允許客戶端去訪問一個指定的tuple。由於tuples經常不知道結構的大小,如果pBuffer爲空的話,SDGetTuple函數通過pBufferSize返回一個tuple的長度。

一個tuple長度爲0,tuple是不存在的。當tuple長度被確定,客戶端驅動可以分配足夠的存儲和調用API再與一個非空的pBuffer值去讀tuple 數據。

(注:
tuple
元組,數組
In a relational data base, a part of a relation that identifiers an entity and its attributes.
關係數據庫中,標識一個實體及其屬性的關係的一部分。 參閱relation。)

插槽事件回調
SD卡客戶端驅動可以選擇插槽事件回調。這個回調提供異步信息關於插槽狀態的改變。下面的代碼例子就是一類插槽事件回調。
VOID SlotEventCallBack(SD_DEVICE_HANDLE hDevice,
  PVOID pContext,
  SD_SLOT_EVENT_TYPE SlotEventType,
  PVOID pData,
  DWORD DataLength)
{
  PSD_MY_DEVICE_INSTANCE pDevice = (PSD_MEMCARD_INFO)pContext;
  switch (SlotEventType) {
    case SDCardEjected :
    // mark that the card is being ejected
    pDevice->CardEjected = TRUE;
    break;
    }
}
客戶端驅動使用註冊信息結構去提供一個指向客戶端函數的指針,下面例子是一類註冊信息結構。
memset(&ClientInfo, 0, sizeof(ClientInfo));
// set client options and register as a client device
_tcscpy(ClientInfo.ClientName, TEXT("MyDriver"));

// set the callback, we want slot events
ClientInfo.pSlotEventCallBack = SlotEventCallBack;

// register the client
Status = SDRegisterClient(hClientHandle,
  pDevice,
&ClientInfo);

插槽事件類型通過作爲參數傳給回調函數。回調函數可以被調用再任何線程空間。插槽事件類型可以限制,當回調函數被調用的時候要不要被觸發。
當卡從插槽移開時SDCardEjected被調用。當事件類型顯示出來,客戶端驅動將不會在回調函數裏面承交任何總線請求。
回調函數被調用,先前調用*_Deinit (Device Manager)的進入點爲客戶端驅動,這些會給客戶端驅動一個機會去設置內部設備狀態。例如,回調函數可以設置一個標誌允許客戶驅動去拒絕用戶的應用程序IO請求。

客戶端驅動的總線請求
SD客戶端驅動使用總線請求發送命令和相應到SD卡,同時也是通過總線接收命令和相應。總線請求包含SD卡協議棧信息被使用在:
控制命令發送給SD卡
控制發送或響應任何的命令相關數據
SDBusRequest函數使客戶端驅動可以異步發送總線請求給卡。這些參數在同步和異步功能的使用上是類似的。CommandCode參數是命令,在SD規格上定義。CommandArgument是32位任意的參數,在SD規格上定義。
所有的SD命令,除了CMD0,都需要卡反饋一個響應。一些命令可以使卡發送數據。一些命令使卡準備去接收數據。
SDBusRequest函數裏面的TransferClass參數是存放當前類別的種類。下面表是現實當前的總類:
SD_COMMAND說明是一個命令或相應
SD_READ說明是一個命令、相應或數據讀
SD_WRITE說明是一個命令、相應或數據寫
ResponseType參數說明了希望從命令中得到SD響應類型。
數據可以通過塊傳輸給SD卡。pBlockBuffer參數是指向一個緩衝區的指針,這緩衝區需要足夠大去存儲指定塊的數量。
一些命令類型需要在總線上專用的操作。客戶端驅動可以使用總線請求標誌來實現。
同步和異步總線請求功能包含可選的Flags參數。這些Flags參數允許SD客戶端在總線上提出一些特殊操作的請求,特殊的命令類型。如果總線驅動沒有請求特殊操作,這個參數將被設置爲0。
同步總線請求
從一些SD命令,比如SET_BLOCKLEN,這裏沒有強制執行異步傳輸。一般來說,提供同步總線請求。客戶端驅動直到總線請求程序段完成。SDSynchronousBusRequest函數被使用在這些請求上面。
pResponse參數用來從SD卡獲得相應。這相應將包含一些命令數據的錯誤狀態。
異步總線請求。
通過使用異步總線請求,客戶端驅動可以發出多總線請求,不需要等待先前的請求執行完成。總線請求隊列在總線驅動內部,等待SD總線可用。
可以使用同步請求,客戶端驅動可以最大使用可用的SD總線寬度。當SDIO網絡適配器忙着傳輸包時,客戶端驅動可以格式化下一個將要被髮送的包。
當每一個請求完成,總線驅動調用回調程序給客戶端驅動。回調程序可以通知主客戶端驅動線程請求已經完成。
SDBusRequest
一個異步總線請求通過調用SDBusRequest函數。pCallback參數是一個指向回調函數的指針,當總線請求完成,它將被總線驅動的線程調用。RequestParam參數是可選的,它通過回調程序爲總線請求。
ppRequest參數被使用去獲得一個指向新創建的總線請求結構。通常,客戶端驅動將保存這個指針去使能請求的取消和刪除。這不是強制性的,指針是通過回調函數在請求完成之上。
SDFreeBusRequest
客戶驅動爲了去釋放存儲分配爲新的總線請求。當請求完成的時候,它可以去調用SDFreeBusRequest函數。在請求成功,錯誤或取消的時候。
SDCancelBusRequest
客戶端驅動可以去取消任何的總線請求,調用SDCancelBusRequest函數。如果總線請求還沒被髮送,它將從隊列中移開。回調函數必須釋放總線請求,SD_API_STATUS_CANCELED狀態表示請求被取消。通常情況廈,客戶端驅動將等待知道所有請求都完成。
單功能卡,多功能卡,和結合卡
SD卡可以分城下面3種類型:
單功能卡,在總線驅動內只有一種設備操作,只加載一種客戶端驅動。
多功能卡,執行超過一種IO功能。
結合卡,執行一種或多種IO功能,包含SD存儲功能。
單功能卡
單功能卡可以可以作爲SD存儲客戶端驅動或單功能的SDIO設備。客戶端驅動去加載要通過註冊表查詢。一個單功能的SDIO設備在總線驅動內只有一種設備操作,只加載一種客戶端驅動。
SD存儲客戶端驅動
下面的註冊表需要去加載一個SD存儲客戶端驅動的入口
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Class/SDMemory_Class]
下面註冊表可以使用爲加載一個自定義的客戶端驅動的默認設置
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Custom/CID-M-AA-PPPPP]
M的值是廠商的ID,AA值是OEM使用的ID爲兩個字節。PPPPP值是產品名爲5個字符。
SDIO Device
下面註冊表是加載SDIO設備的入口
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Class/SDIO_Class/ <class interface code>]
下面是加載自定義的SDIO設備的入口
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Custom/MANF- <manufacturer ID>-CARDID- <card ID>-FUNC- <function number>]
廠商ID和卡ID值將被存儲在十六進制中。function可以被一個從1-7的值。
多功能卡
多功能卡屬於SDIO卡,行使超過一個IO功能。每個功能都在分開的SDIO寄存器上操作,可以被獨立的控制。
一個多功能卡有一個單獨共享的SDIO卡控制器。卡控制器執行一個公共的配置區域,總線驅動可以使用去查詢卡的性能和啓動公共的特徵。
總線驅動創建設備實例操作,每一個功能,都加載一個客戶端驅動。總線驅動加載客戶端驅動基於註冊表鍵值,定義的接口類,或沒定義類型檢查自定義的ID鍵。
每一個客戶端驅動都存在未知功能,可以被操作執行。如果其中一個功能在多設備不被支持,總線驅動將還是會允許其它可用的功能正常工作。
下面的圖說明了多功能卡的結構:


<!--[if !vml]--> <!--[endif]-->
結合卡
結合卡作爲SDIO卡,執行一個或多個IO功能並且包含一個SD存儲功能。SD卡存儲功能作爲一個SDIO功能。允許設備結合SD存儲和IO功能在不同條件下操作。
結合卡如果插入SDIO-aware的主機,主機可以使用SD存儲和SDIO功能。如果插入只支持SD存儲的主機,用戶也只可以使用SD存儲的功能,其它SDIO功能不能使用。
總線驅動查詢提供的SD存儲功能,創建一個設備去加載客戶端驅動。客戶端驅動可以不管是否使一個結合卡。
下面的圖表說明的結合卡的結構


<!--[if !vml]--> <!--[endif]-->
SD卡的上電和去電信息
SD卡總線結構內部,當系統掛起的時候,主控驅動可以移去插槽的電源。
插槽的設備不會被移開,等待直到OS從掛起狀態返回來。當系統從掛起狀態返回來,主控端驅動立即發送設備移除的信息給總線驅動,並且檢查卡的存在。
確認的過程是必須的,當系統掛起時,原本卡是否存在或換成另外一類卡。如果卡存在的話,總線會得到消息。先前的客戶端驅動會被移開,新的客戶端驅動被加載。
一般情況下,上電和去電都會通知客戶端驅動,客戶端驅動可以忽視它們。當系統從掛起中恢復時,如果用戶拔出卡,客戶端驅動將被卸載。
SD卡驅動註冊表的設置
當SD卡插入,總線驅動使用HKLM/Drivers/SDCARD/ClientDrivers/下面的註冊表鍵去確定當前客戶端驅動的加載。總線驅動加載客戶端是基於卡的類型,SDIO類或自定義類。
客戶端驅動註冊表部分,至少要包括:
DLL值,包含驅動DLL文件名。
Prefix值,包含驅動的3個字符前綴。
如果總線驅動無法爲卡定位自定義驅動,它將基於卡類型或SDIO類,查找驅動。
SD存儲客戶端驅動
下面是加載SD存儲客戶端驅動的註冊表入口
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Class/SDMemory_Class]
下面是被用於加載自定義客戶端驅動和默認設置的註冊表入口點
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Custom/CID-M-AA-PPPPP]
M值是廠商的ID,AA值是OEM使用的ID爲兩個字符,PPPPP值是產品名爲5個字符。
SDIO設備
下面註冊表可以被用於加載SDIO設備。
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Class/SDIO_Class/ <class interface code>]
下面是加載自定義SDIO設備的註冊表進入點
[HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Custom/MANF- <manufacturer ID>-CARDID- <card ID>-FUNC- <function number>]
生產商的ID和卡的ID值是16進製表示。Function number可以被設置爲1-7之間的值。


藍牙驅動方面還有個小問題沒搞定,所以也沒什麼心思去整理這些,這部分是文檔的翻譯,前幾天整理出來,以後比較有空時候再陸續添加整理。

發佈了18 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章