WINCE6.0+S3C2443下SD卡驱动

来源:互联网 发布:ppt修改图表数据 编辑:程序博客网 时间:2024/04/29 19:25

WINCE6.0+S3C2443下SD卡驱动

********************************LoongEmbedded************************

作者:LoongEmbedded(kandi)

时间:2011.02.24

类别:WINCE 驱动开发

********************************LoongEmbedded************************

1.  SD卡驱动架构

 

 

图1

SD卡驱动分为client驱动,bus驱动和SD主控制器驱动,其中client驱动和bus驱动均由微软提供,bus驱动所在的代码是/WINCE600/PUBLIC/COMMON/OAK/DRIVERS/SDCARD/SDBUS,client驱动的代码在/WINCE600/PUBLIC/COMMON/OAK/DRIVERS/SDCARD/SDCLIENTDRIVERS下,而SD主控制器驱动在我们BSP包驱动目录下。

 

从上图可知最下面的是你的H/W部分,其中SD Host Controller是你的SD硬件控制器部分,我们写驱动需要这部分的SPEC。接着上面的SD Host Controller Driver就是我们需要实现的部分了,直接和SD住控制器打交道。 而BUS层则是位于Host和Client之间的一层,主要用来进行两层之间的通信,并根据不同的设备来加载不同的Client驱动,如果是SD Memory卡就加载SD Memory,如果是具有WIFI功能的SDIO卡就会加载这个SDIO WIF驱动。在没有插入SD卡的情况下,系统只加载了SD卡总线驱动和SD卡主控制器驱动;如果插入SD卡,那么系统会加载对应于SD卡的客户端驱动,其原理是SD卡主控制器的SD卡检测线程检测到插入SD卡后通知SD卡总线驱动,然后由SD卡总线驱动来加载对应的客户端驱动,当客户端程序被加载后就会在my device上可以看到SD card的盘符了。

 

SDHC_SC2410.dll是最底层,负责具体的发命令什么的,SDBus.dll是中间层,负责整合命令和管理,这两个在HKEY_LOCAL_MACHINE/Drivers/BuiltIn下,系统启动时就加载,SDMemory.dll是最高层.正常工作时,一旦卡插入,SDHC_SC2410.dll的IST检测到中断,通知SDBus.dll做初始化工作,OK后SDBus.dll加载SDMemory.dll,系统才能识别卡.

 

SD卡控制器驱动:sdhc_sc2443.dll

SD总线驱动:SDBus.dll

SD Client(客户端)驱动:SDMemory.dll

 

下面是我从help文档中获取的相关内容,为了不误导大家,我把原内容贴出来,自己在翻译中学习。

 

1.1 SD总线驱动

The Secure Digital (SD) card bus driver abstracts the physical implementation of the host controller to provide the client driver with a simple method of sending commands to a card regardless of bus topology. If a client driver must know the details regarding the physical connection of a card for performance reasons, it is able to query the bus driver for this information.

SD卡总线驱动(Sdbus.dll)抽象了SD卡主控制器驱动的物理实现,并且提供标准的API给SD客户端驱动来和SD卡通信,这样,SD客户端驱动就可以不管总线拓扑结构而通过发送命令这样简单的方法来给SD卡发送命令。如果客户端程序因为性能理由必须知道关于SD卡物理链接的细节,客户端程序可以借助于总线驱动提供的API来查询这些信息。

The bus driver is responsible for managing client drivers and, to some degree, host controller drivers. The bus driver exposes a set of services specific to client drivers and a set of services specific to host controller drivers. Both services are designed to minimize complex driver operations, such as client driver loading and unloading, SD Card interrogation and identification, client driver bus requests, and I/O cancellation. These operations are handled by the bus driver.

总线驱动负责管理客户端驱动,并且从某种程度上来说也是一样负责管理主控制器驱动。总线驱动为客户端程序及主控制器驱动分别导出一系列具体的服务,这些服务是用于最小化复杂的驱动操作,比如客户端程序的加载和卸载,SD卡的询问和识别,客户端驱动的总线请求,和I/O取消,这些操作都是由总线驱动来处理。

When a card is inserted into the bus driver, it initiates a set of actions to determine the type of the card and load the appropriate client driver. The SD bus driver loads client drivers using the ActivateDeviceEx function.

当插入卡时,总线驱动初始化一系列的动作来确定卡的类型并且调用ActivateDeviceEx函数来加载相应的客户端驱动。

Due to the layered architecture of the SD card stack, the bus driver is the only driver that the client driver must interface with. The bus driver presents an abstraction of the SD protocol to the client driver. This abstraction hides all operation of the lower level host controller hardware from the client driver. Because this abstraction is purely software based, a client driver can operate on any hardware platform for which the SD bus driver exists and a compatible host controller driver has been written.

因为SD卡堆栈是分层结构,客户端驱动只能和总线驱动打交道。总线驱动为客户端驱动呈现SD协议的抽象,这样可以为客户端程序隐藏最底层主控制器所有的硬件操作。因为这是完全的软件抽象,这样,只要是有SD总线驱动存在并且已有一个兼容的主控制器驱动的任何硬件平台,客户端驱动就可以操作这些硬件平台。

The bus driver provides simultaneous access for multiple client drivers in a thread-safe manner. The bus driver provides the proper serialization and synchronization even if the client drivers are controlling cards in separate slots or controlling separate functions on a multi-function card.

 

总线驱动为多种客户端驱动提供安全的线程模式下的同时访问,即使客户端驱动在控制不同卡槽上的卡或者控制多功能卡上不同的功能,总线驱动也可以提供正确序列化和同步功能。

 

1.2客户驱动

In the process of identifying Secure Digital (SD) cards, the bus driver performs bus transactions to determine the type and class of an SD device. Upon determining the card type or class, the bus driver loads the client driver associated with the device using the appropriate protocol. The bus driver loads the client driver based on plug and play information read from the SD card.

在识别SD卡的过程中,总线驱动执行总线处理来确定SD卡的类型和等级,根据这些信息,然后总线驱动用恰当的协议来加载和设备一致的客户端驱动。总线驱动根据从SD卡中读取回来的即插即用的信息来加载相应的客户端驱动。

 To install a client driver on a released device, an application developer should provide an application to install the client driver onto the device and set up appropriate registry keys that match the driver to the card.

为了安装相应设备的客户端驱动(比如是SD卡的客户端驱动SDMemory.dll),应用开发人员应该提供安装客户端驱动的应用程序和为卡建立相应的注册表键项。

 

A client driver is able to issue commands to a card synchronously or asynchronously. If a client driver does not require the power or performance increase available with asynchronous operation, the SD Card stack provides a simplified synchronous interface designed to remove much of the complexity from the client driver.

客户端驱动可以同步或者异步发送命令给卡,如果客户端驱动在异步操作时不需要提供驱动能力或性能,那么SD卡堆栈提供一个简单的同步接口来去除客户端驱动操作的复杂性。

 

1.3 控制器驱动

The Secure Digital (SD) card host controller driver is the software component that controls the host controller hardware and conforms to a host controller software interface that the bus driver uses to communicate and set operating parameters. The host controller driver uses an API set exported by the bus driver for registration and unregistration.

SD卡主控制器驱动是软件部分,这部分控制主控制器硬件和遵从总线驱动用来通信于设置操作参数的主控制器软件接口。控制器驱动导出一系列的API给总线驱动来注册和注销

 

Registration involves providing information about host and slot capabilities, including maximum clock rate, acceptable voltage windows, SD data bus width, and power up delay. Registration also provides callback functions, a slot options handler, a power handler, and a bus request handler.

注册涉及到提供主控制器和卡槽的容量,最大的时钟频率,可接受的电压范围,SD数据总线宽度和上电延迟。注册信息也提供回调函数,卡槽的选择处理程序,电源处理程序和总线请求处理程序,/WINCE600/PUBLIC/COMMON/OAK/INC/sdhcd.h下面的结构体SDCARD_HC_CONTEXT就描述了这些内容:

 

图2

The SD Card stack uses a dynamic architecture that allows host controller drivers to register or unregister at any time.

SD卡堆栈使用允许主控制器驱动在任何时间注册和注销的动态的架构。

The host controller driver interface provides a hardware abstraction layer between the bus driver and the host controller implementation. Host controller drivers contain platform and chipset dependent code and only communicate information to the bus driver through this interface. This keeps the bus driver independent of host controller and platform design. The host controller driver interface is only required by host controller drivers and is independent from the client driver API.

主控制器驱动接口为总线驱动和主控制器提供一个硬件抽象层。主控控制器驱动包含平台与芯片组相关的代码和通过这个接口来与总线驱动通信。这样可以使总线驱动独立于主控制器和平台设计。主控制器驱动接口只有对于主控制器驱动来说是必须的,并且独立于客户端驱动的API。

 

The host controller driver:

 

Includes the controller, slot, and supporting logic, and comprises the actual hardware implementation.

主控制器驱动包含控制器,卡槽,支持的逻辑,和包含实际的硬件实现。

 

Implements the SD and multimedia card (MMC) transmit and receive electronics.

实现SD卡和MMU卡的发送和接收。

 

Can be a memory-mapped device on a local bus such as an integrated controller, or on a peripheral bus such as PCMCIA, PCI, and USB.

可以是挂载在局域总线的比如是集成的控制器这样的内存映射设备,或者是可以挂载在像PCMCIA、PCI、和USB这些外围总线上的内存映射设备。

 

Can also use programmed I/O or direct memory access (DMA).

主控制器也可以使用可编程I/O或DMA。

Beginning with Windows Embedded CE 6.0 R2, can use single operation direct memory access (SDMA). If you are using a different host controller driver, you can refer to the Microsoft SD standard host controller driver implementation for help modifying your own. For additional information on DMA support, see Secure Digital Card Direct Memory Access Support

 

 

The SD card driver architecture allows for an unlimited number of host controller drivers per system. Multiple slot implementations must utilize independent power, clock, and bus width control. This allows the system to accept cards that have different SD interface requirements.

SD卡驱动架构允许一个系统有无限的主控制器驱动个数。多个卡槽的实现必须使用独立的供电,时钟和总线宽度控制。这样,系统可以接收多个SD卡的不同SD接口请求。

The SD card host controller electrical interface is fully hot swappable and can operate in 1-bit or 4-bit mode, with a clock speed of 0 to 50 megahertz (MHz) as of Windows Embedded CE 6.0 R2. When using a Windows Embedded CE version prior to Windows Embedded CE 6.0 R2 the supported clock speed is 0 to 25 megahertz (MHz). The default clock speed is 25 megahertz (MHz) for all releases. The host controller driver is responsible for registering the capabilities of a slot to the bus driver.

SD卡主控制器电子接口是可热插拔的,可以工作在1或4位的模式下,在WINCE6.0 R2的特性下,主控制器工作时钟在0到50MHZ的范围内,但在早于R2版本的系统中,主控控制器工作时钟范围是0到25MHZ,而所有的发布的版本,默认的时钟速度是25MHZ。主控制器驱动负责注册总线驱动的卡槽参数。

Source code for the SD bus can be found in the following directories:

SD 1.1 bus - %_WINCEROOT%/Public/Common/OAK/Drivers/SDCard/SDBusdriver

SD 2.0 bus - %_WINCEROOT%/Public/Common/OAK/Drivers/SDCard/SDBus

When you are building a new image you need to set the image flag IMGSDBUS2 equal to 1 in order to use the new bus (sdbus2.dll) and map the 2.0 bits to the OEMDrivers package. When IMGSDBUS2 is set to 1, the sdbus2.dll is picked up during the makeimg process and is renamed to sdbus.dll in the generated image. You can map the 2.0 bits to the package by adding the following line to the oem.cpm.csv file: CE_MODULES_SDBUS2, OEMDrivers

 

SD Bus作为一个中间层驱动起着承上启下的作用,在SD Bus中实际上提供了两组函数接口,分别提供Client层和Host层来使用。所以对于Host和Client层来说,只需要设计好这两组接口就可以。

 

2.  SD卡驱动的实现

2.1  SD卡主控制器驱动

2.1.1   SD卡主控制器驱动的主要导出函数

2.1.1.1 SD卡主控制器的入口函数DllEntry

图3

 

⑴SDInitializeCardLib函数和SDHCDDeinitializeHCLib函数

在DLL入口函数的调用函数SDInitializeCardLib初始化card library来避免存储子系统(memory subsystem)下的竞争状态,而SDInitializeCardLib函数通过调用InitCardLib函数来初始化svsutil子系统(subsystem),也初始化了g_SDClientApiFunctions全局变量的成员dwSize,这个全局变量很重要,根据名字应该知道是SD总线驱动提供给SD客户端驱动调用的API集合,见下图:

 

图4

这个全局变量的定义如下图:

 

图5

而调用SDDeinitializeCardLib函数来反初始化card library来避免存储子系统(memory subsystem)下的竞争状态。

 

⑵SDHCDInitializeHCLib函数和SDHCDDeinitializeHCLib函数

SDHCDInitializeHCLib函数用于初始化SD卡主控制器驱动的library(也就是sdhclib.lib),SDHCDInitializeHCLib函数主要是通过调用SDHCDGetHCFunctions函数来填充g_SDHostFuncs静态全局变量,而g_SDHostFuncs是办含了SD总线驱动和SD主控制器驱动之间的API接口的变量,所以到此SD主控制器驱动就获取了这些API接口,那是如何填充这些接口的呢?见下面

 

图6

下面来看看SDHCDGetHCFunctions主要函数体

 

图7

SDHCDDeinitializeHCLib函数没有实质的动作,只是返回SD_API_STATUS_SUCCESS,见下图

 

图8

 

2.1.1.2SD卡主控制器驱动(sdhc_sc2443.dll)的初始化函数SDH_Init

 

图9

⑴SDHCDAllocateContext函数

 

图10

 

SDHCDAllocateContext函数是bu层提供的其中一个接口,此函数的第二个参数pHostContext很重要,这里host层调用bus层提供的接口函数SDHCDAllocateContext来分配所需要的host context,还有如果host层有需要bus层去完成的,就只需要调用bus层提供的这些接口就可以了,这就是为什么要在host层的入口函数DllEntry中调用SDHCDInitializeHCLib函数来初始化SD卡主控制器驱动的library的原因(见图6和7),这个接口的结构体定义如下:

 

图11

那么Bus层如果需要Host层去完成一些操作是如何告知Host Driver呢?这就是参数pHostContext所提供的,该结构中提供了一组Handler,Bus层通过这一组Handler来操作Host层,在SDH_Init中初始化这一组Handler,这个结构体见图2

 

⑵CreateSDIOController函数

CreateSDIOController用pHostContext作为参数创建SD Host Controller对象CSDIOController类对象,而CSDIOController是基类CSDIOControllerBase的继承类,这个基类就是我们SD主控制器驱动的最底层实现部分,调用关系如下:

 

图12

接下来会调用CSDIOController类的构造函数

 

图13

下面是CSDIOControllerBase构造函数的一部分

 

图14

这时候有些数据成员的初始化并没有实际的意思,真正的初始化时在InterpretCapabilities函数中完成的。

 

 

⑶InterpretCapabilities函数

调用InterpretCapabilities(CSDIOControllerBase成员函数)从注册表获得SD Host Controller信息,为sd host controller所用到的物理中断申请对应的逻辑中断号 ,下图是此函数的一部分:

 

图15

InterpretCapabilities函数还初始化了host controller上下文m_pHCContext的成员,后面将调用SDHCDRegisterHostController来向bus层注册,这样bus层将可以通过可以m_pHCContext的接口来和host层通信。

 

图16

为后面跟好去理解bus层是如何调用到host层向bus层提供的API接口,看下面的宏定义

 

图17

⑷SDHCDRegisterHostController函数

 

图18

下面 看sdbus.cpp下SDHCDRegisterHostController__X的函数体:

 

图19

下面就在深入来看看bus层这个函数是如何最终调用到host层为其提供的接口函数的

①CSDHost::Attach()

 

图20

CSDSlot::Attach()如下:

 

图21

SlotOptionHandler函数

 

图22

CSDIOControllerBase::SDHCDSlotOptionHandler函数在此又调用了SlotOptionHandler来获取slot的信息

 

图23

 

②InitHandler函数

由图22可知此函数调用的是CSDIOControllerBase::SDHCDInitialize函数,而SDHCDInitialize函数调用CSDIOControllerBase::Initialize(),Initialize函数继续初始化SD卡主控制器,这个函数因为内容很多很重要,所以放在下面详细介绍。

 

 

 

图24

2.1.1.3 SDH_PowerUp函数

2.1.1.4 SDH_PowerDown函数

 

2.1.2   SD主控制器驱动主要的实现类(CSDIOControllerBase和CSDIOController类)的主要成员函数

因为后面将涉及到硬件部分,所以先把SD卡涉及部分的原理图贴出来:

 

图25

 

图26

2.1.2.1 CSDIOControllerBase::SDHCDInitialize函数

由上面知道SDH_Init()->SDHCDRegisterHostController ()->……-> CSDIOControllerBase::SDHCDInitialize()->CSDIOControllerBase::Initialize()

Initialize函数大概内容如下

(1) 设置crtical section临界访问,然后映射GPIO寄存器,SDI控制器,时钟电源管理寄存器,DMA控制器IO地址空间. 然后分配内存给DMA传输(64KB大小).

 

图27

(2) 初始化SD卡主控器的相关寄存器

图28

(3) 创建SD卡检测事件及线程,把SD卡检测事件和SD卡检测的中断关联起来

 

图29

(4) 创建接收应答的事件,SD_TransferIstThread线程首先等待此事件的触发然后才继续等待m_hDMAInterruptThread事件

 

(5) 创建SDIO数据传输中断事件m_hSDIOInterruptEvent,及把SDIO数据传输中断关联到m_hSDIOInterruptEvent事件,也创建SD_IOInterruptIstThread线程来出来SDIO数据传输中断事件。

 

图30

SDIO数据传输中断的IST

#define IRQ_SDI_0           21

(6) 创建DMA传输中断事件m_hDMAInterruptEvent,及把DAM中断关联到DMA传输中断事件,和创建DMA传输中断线程m_hDMAInterruptThread。

处理SDIO的DMA数据传输中断

 

图31

#define IRQ_DMA0          53

(7) 调用继承类CSDIOController的InitializeHardware,这个函数最要功能是把GPF1/EINT1引脚设置为中断引脚,并且设置为双跳变沿触发。

(8) 调用CSDIOControllerBase::Deinitialize函数来进行出错处理,用来来关闭Initialize创建的事件IST线程,释放DMA buffer,关闭SDI power等

 

2.1.2.2 CSDIOControllerBase::SD_IOInterruptIstThread()

这个函数调用线程CSDIOControllerBase::IOInterruptIstThread()来实现,下面就来学习IOInterruptIstThread函数

 

图32

⑴ CSDIOController::IsCardPresent()

因为我们是在此是用GPF1/EINT1来作为检查SD卡是否存在的判断,就只看此相关的代码

 

图33

相关的Platform.reg中注册表信息如下:

 

图34

⑵插入卡时的动作

当我们检测大插入卡的时候,需要对SDI模块编程,其中SD控制器中相关描述如下,依据这些描述来编译,代码见图32

 

图35

在检测到插入卡后这个线程中最重要的动作就是调用SDHCDIndicateSlotStateChange函数来告诉bus层当前卡槽事件的变化,这个函数是在sdhclib.lib下的sdhclib.cpp定义的

 

图36

 

其中的Event是SD_SLOT_EVENT结构中的成员,定义如下:

// typedef for asynchronous slot event codes

typedef enum _SD_SLOT_EVENT {

    NOP,                // no operation

    DeviceEjected,      // device was ejected

    DeviceInserted,     // device was inserted

    DeviceInterrupting, // device is interrupting

    BusRequestComplete, // a bus request was completed

    SlotDeselectRequest,// Deslect the card in the slot

    SlotSelectRequest,  // Select the card in the slot

    SlotResetRequest    // Reset the card in the slot

} SD_SLOT_EVENT, *PSD_SLOT_EVENT;

之后卡的识别过程都会由Bus层的代码来判断同时会建立一系列的结构并调用ActivateDeviceEx来加载Client Driver。在Bus层调用ActiveDeviceEx之后,系统发送一个消息给StorageManager一个Block设备需要加载,对于Block设备Wince会有一个固定的GUID来代表。这个时候就由StorageManager来为刚才的Block设备加载对应的文件系统,Block驱动就是Client层的驱动,这样在设备上就可以看到SD卡的图标了,下面是common.reg中sd client driver相关注册表部分

 

图37

⑶拔出卡时的动作

当线程检测到卡拔出来的时候,会调用SDHCDIndicateSlotStateChange函数来告诉bus层,由bus层来完成对sd client driver的卸载。

 

2.1.2.3 CSDIOControllerBase::SD_IOInterruptIstThread()

这个函数调用线程CSDIOControllerBase::IOInterruptIstThread()来实现,这个线程等待m_hSDIOInterruptEvent事件发生,如果事件发生同时卡存在的话,调用SDHCDIndicateSlotStateChange通知总线驱动SD卡中断发生.

 

 

 

创建SDIO数据传输中断事件m_hSDIOInterruptEvent,及把SDIO数据传输中断关联到m_hSDIOInterruptEvent事件,也创建SD_IOInterruptIstThread线程来出来SDIO数据传输中断事件。

 

2.1.2.4 CSDIOControllerBase::TransferIstThread()

处理SDIO的DMA数据传输中断

我们以下面的动作来学习这个线程的工作

⑴插入卡的时候

 

①插入卡的时候,发送命令CMD5给SD卡,而CMD5是用于SDIO卡的,所以这里发送给SD卡,自然就没有响应,

 

图38

 

图39

②发送CMD5命令没有响应之后,发送CMD8命令主要用于查询SD卡支持的电压范围,SD卡返回对其对CMD8命令的响应值,这个值的内容更加不同的命令而不同,这需要看SD Specifications,而对CMD8的响应是ResponseR7,下图看GetCommandResponse()函数对CMD8的处理

 

图40

CMD5命令的说明如下:

 

图41

CMD8命令的说明如下:

 

图42

③发送CMD1命令(这个命令是保留的,为什么这时要发送这个命令,不知道)和①中发送CMD5一样,也是4次,而因为这个命令式保留的,故SD卡也没有响应。

 

④发送命令CMD55用于指示下一个要发送给卡的是特定的而不是标准的命令

 

图43

对CMD55命令的响应时R1和R7是同样的处理方式,见图40

后面还是对发送的一些命令的响应的处理,至于是哪些命令,这需要看SD specific部分。

 

⑵读取SD卡上的内容

下面基于读取一个大小为213KB的文件来说明此线程读此文件的动作

①bus层发送CMD18命令来用于从SD卡中读取多块的数据,此命令说明见下图

 

图44

这时SD卡对此命令的响应由图40的GetCommandResponse()函数,获取到的SDIRSP0=0x900,下来看这个值的大概意义,结合图45和46

 

图45

 

图46

收到SD卡对CMD18的响应,接下来看线程中的处理,因为是用DMA中断的数据传输方式,这里就不介绍线程中用轮询的方式来读取数据的那部分代码了,下面看线程中DMA方式的代码

 

图47

这里DMA通道一次中断传输的数据字节数大小=一次传输N块*一块大小为M个字节,这里N和M是怎么确定的呢?

N的确定:由common.reg中关于sd client驱动sdmemory.dll中下面的注册表项决定的

 

图48

N的值就是SDI数据控制寄存器SDIDCON[11:0]的值

M的确定:由SDI块大小寄存器SDIBSIZE的值来决定,这个值一般在CSDIOControllerBase::Initialize()和CSDIOControllerBase::CardDetectThread()中来设置,在此设置其大小是512,这样就可以知道DMA通道一次中断传输的数据字节数大小=N*M=64*512=32KB了。

 

②读取了32KB字节的数据后,bus层会发送CMD12来告诉SD卡让SD卡停止向SD主控制器传送数据。

 

图49

 

③只要读取的数据还没有完成就继续发CMD18来读取数据,重复①和②的动作,知道读取数据完成。根据串口信息,发现发送7次读取数据的命令,读取到的数据大小为6*32768+21504,恰好是213KB,这就是我要读取SD卡上这个文件的大小。

 

 

⑶写SD卡

下面基于向SD卡写一个大小为213KB的文件来说明此线程的动作

①发送CMD24向SD写一个block(512bytes)大小的数据,

图50

而且是发送4次,也就是向SD卡依次写入4*512bytes=2KB的数据。每发送一次CMD24后此线程下面的代码在等待本次数据传输的完成

 

 

图51

本次数据传输完成后,调用vm_pSDIReg->SDIDSTA = DATA_TRANSMIT_FINISHED;来清楚此标志位。

 

 

②发送命令CMD25来向SD卡联系写入多块的数据

 

图52

 

③当上面的写多块数据这个动作完成后,接着发送CMD12来停止传输,此命令见图49,

因为CMD12只是bus request的命令,所以此线程下面的地方就知道跳转到TRANSFER_DONE去执行

 

图53

下面来看TRANSFER_DONE的动作

 

图54

然后就又重复②的动作,知道最后的文件传输完成,通过串口信息看到写的数据大小为9*512+6*32768+21504比实际的文件大小大9*512,具体不知道为什么?可能是每向SD卡中写入文件,SD卡文件系统就需要为此文件开辟一些空间来做一些额外的记录吧,望知道的朋友可以告诉,谢谢。

 

TransferIstThread线程的主要功能总结如下:

等待m_hResponseReceivedEvent事件的发生,该事件发生后继续运行,否则挂起.

m_hResponseReceivedEvent触发后,如果controller down则线程退出.调用SDHCDGetAndLockCurrentRequest(实现在sdhclib)来获取当前slot的请求,并锁住禁止取消。然后处理一个特殊情况,SD_CMD_STOP_TRANSMISSION命令在SD_CMD_WRITE_MULTIPLE_BLOCK后发送,需要进行BUSY_CHECK.

如果BusyCheck为true,CommandCode为SD_CMD_ERASE或者CommandCode为SD_CMD_STOP_TRANSMISSION,m_dwLastTypeOfTransfer为SD_WRITE时,需要等待IO传输结束.检查SDIDSTA寄存器BusyFin位,如果为0(busy not finish),则进行等待,并判断超时,IsCardPresent,以及一些错误状态,如果任何一种情况发生,就设置BUSY_CHECKS_FINISH,跳转到TRANSFER_DONE通知BusRequest完成.

如果BUSY_CHECKS_FINISH成立,则准备DMA传输.如果ResponseType为NoResponse,跳转到TRANSFER_DONE.否则调用GetCommandResponse获取CommandResponse状态.如果是命令,直接TRANSFER_DONE.数据传输分两种情况是否使用DMA,m_bUseDMAForTransfer为false,启动IO传输,为true,并判断是SD_WRITE写操作时,复制数据到DMA memory,调用Enable_SDIO_DMA_Channel,启动DMA通道,

 

图55

然后等待DMA完成中断事件m_hDMAInterruptEvent,完成后调用InterruptDone和Stop_SDIO_DMA_Channel通知中断完成并停止DMA通道.然后等待读取SDIDSTA等待data transfer结束.如果是SD_READ,读取从DMA memory放到调用缓存区pBlockBuffer中.

最后停止SDI clock,通知总线请求结束(SDHCDIndicateBusRequestComplete).

 

2.1.2.5 CSDIOControllerBase::SDHCDBusRequestHandler()

这个函数通过调用CSDIOControllerBase::BusRequestHandler()来处理总线请求(来之bus层).

①首先复位FIFO和状态寄存器,然后使能SDI CLOCK,计算要传输数据大小,判断是否DMA传输以及是否4字节对齐,4字节整数倍来进行DMA传输(SetupDmaXfer)或者轮询IO传输(SetupPollingXfer).

 

图56

 

接着判断传输的是单独命令还是命令和数据,第一次传输命令时需延时80个clock周期.SendCommand最后一个参数表示是传输命令(FALSE)还是命令和数据(TRUE).

最后设置设置事件m_hResponseReceivedEvent来通知传输IST命令应答发生.

 

图57

 

2.1.2.6 CSDIOControllerBase::SetupPollingXfer()

复位FIFO,然后根据传输类型(SD_READ,SD_WRITE,SD_COMMAND)来设置SDIBSIZE和SDIDCON寄存器.

 

2.1.2.7 CSDIOControllerBase::SetupDmaXfer()

设置为DMA传输,分两种情况SD_READ和SD_WRITE,首先设置request类型(SD_READ或SD_WRITE),reset fifo,设置BlockSize(SDIBSIZE寄存器),根据m_dwDMAChannel(0-3)设置DMA寄存器,设置源/目的地址,源地址periperal bus, fixed addr,目的地址system bus, increment addr,设置DMA通道传输特性handshake, sync PCLK, interrupt, single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count,SD_READ和SD_WRITE的源和目的地址正好相反。当SD_CMD_STOP_TRANSMISSION命令时,设置BUSY_AFTER_COMMAND。

下面看SD_READ时对应的处理代码

 

图58

SD主控制器的基类CSDIOControllerBase还有很多成员函数,在这里就不介绍了,可以通过代码来进一步学习。

 

 

总结一下SDHC与SDBUS的交互:

主要是互相注册函数来实现的,SDHC向SDBUS提供函数服务的方式是设置host context结构变量的函数指针;SDBUS向SDHC提供函数服务的方式是提供函数SDHCDGetHCFunctions给g_SDHostFuncs变量中函数指针赋值。

 

2.2  sd bus驱动

2.3  sd client驱动

 

 

 

 

设计到3个中断

INT_SDI_0---》SDMMC interrupt,对应CSDIOControllerBase::SD_IOInterruptIstThread(),handling SDIO data transfer interrupts

IRQ_DMA0---》用于读写SD卡上的数据,DMA来读取,对应CSDIOControllerBase::SD_TransferIstThread(),handling SDIO DMA data transfers

IRQ_EINT1---》用于检查SD卡是否存在,对应CSDIOControllerBase::SD_CardDetectThread(),用于处理SD卡的插拔

 

 

http://hi.csdn.net/space-6411456.html

SD:安全数字

SDIO:安全数字输入输出,SDIO在SD标准上定义了一种外设接口

 

SDIO是SD型的扩展接口,除了可以接SD卡外,还可以接支持SDIO接口的设备,如wifi卡,蓝牙卡等,实现扩展功能

 

 

SDIO Now!是一种软件栈(软件堆叠器),它使得用多媒体存储卡(MMC)和安全数字(SD)存储卡进行图片、视频和数据存储成为了可能,同时它也支持安全数字输入输出(SDIO)外围设备,诸如数码相机、GPS接收机、Wi-Fi卡以及移动设备上的RFID识别器等。

 

SDHC(Secure Digital High Capacity) 超过2G的SD都叫SDHC早期的SD使用的是FAT16文件系统,并不支持大容量,而SDHC升级为FAT32,才支持2G以上的大容量。SDXC(SD eXtended Capacity)是去年刚刚提出的新标准,除了容量可以升级为最大2T以外,主要是可以支持300M/s的传输速度,也就是说是“高速SD”卡。不过支持SDXC卡的数码相机并不多,主要都是今年推出的新品,而SDXC又是不可向下兼容的,不支持普通的SD和SDHC卡槽和读卡器。而且对于大部分数码相机和单反来说,高速SDHC存储卡的速度已经足以实现高速连拍和高清视频拍摄。SD和SDHC为目前市面可售的闪存卡。SDHC中HC为“高容量”(High Capacity),是SD的“扩容”版。SDXC则为前两者的最新升级版,实体产品即将面世。SD和SDHC两种卡尺寸相同。SDHC容量范围一般是4GB到32GB,据官网介绍【1】,SDXC容量范围则从32GB到2TB。SD卡速度分级共有3类:

 

 

SDHC是“High Capacity SD Memory Card”的缩写,即“高容量SD存储卡”。2006年5月SD协会发布了最新版的SD 2.0的系统规范,在其中规定SDHC是符合新的规范、且容量大于2GB小于等于32GB的SD卡。

  SDHC最大的特点就是高容量(2GB-32GB)。另外,SD协会规定SDHC必须采用FAT32 文件系统,这是因为之前在SD卡中使用的FAT16文件系统所支持的最大容量为2GB,并不能满足SDHC的要求。

  作为SD卡的继任者,SDHC主要特征在于文件格式从以前的FAT12、FAT16提升到了FAT32,而且最高支持32GB。同时传输速度被重新定义为Class2(2MB/sec)、Class4(4MB/sec)、Class6(6MB/sec)等级别,高速的SD卡可以支持高分辨视频录制的实时存储。

 

 

WinCE下SD卡驱动开发

http://blog.csdn.net/luixing67/archive/2010/01/08/5158816.aspx

 

SD,MMC,SDIO的相关概念

http://topic.csdn.net/u/20100605/23/8b2cee0c-37d9-47b4-83c6-b17c246e8792.html

 

wince SD卡驱动开发

http://bbs.21ic.com/icview-102327-1-1.html

 

CE下基于Zylonite硬件平台的SD卡驱动开发

http://embed.chinaitlab.com/WinCE/776859.html

 

WINCE5 SD驱动彻底解析  !!!!!!!!!!!!

http://bluefish.blog.51cto.com/214870/474653

 

SDdriver分析

http://blog.csdn.net/gsymichael/archive/2008/08/18/2792402.aspx

http://hi.baidu.com/mikenoodle/blog/item/4a469c506a63a56b8435244d.html

 

 

Windows CE SDHC驱动简析

http://blog.csdn.net/shevsten/archive/2010/06/24/5690813.aspx

http://blog.csdn.net/shevsten/archive/2010/07/06/5715374.aspx

http://blog.csdn.net/shevsten/archive/2010/07/07/5717790.aspx

原创粉丝点击