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之间的值。


蓝牙驱动方面还有个小问题没搞定,所以也没什么心思去整理这些,这部分是文档的翻译,前几天整理出来,以后比较有空时候再陆续添加整理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值