Add new comment
SD MMC and Windows CE
Lately there have been a lot of questions about SD and MMC in the newsgroups, especially about what is supported by the Microsoft SD bus driver. This blog post hopefully helps clear up some things about SD/MMC support in Windows CE.
First let’s look at an overview of the MMC and SD specifications and who supports what:
| CE Version | SD Spec | MMC Spec |
|---|---|---|
| Win CE 5.0 RTM | 1.1 | 3.x |
| Win CE 5.0 QFE (April 2007 onward) | 2.0 | 4.3 |
| Win Mobile 6.0 RTM | 1.1 | 3.x |
| Win Mobile 6.x (AKU 0.2 onward) | 2.0 | 4.3 |
| Win CE 6.0 RTM | 1.1 | 3.x |
| Win CE 6.0 R2 | 2.0 | 4.3 |
From the table above it looks like the SD bus driver in CE 6.0 R2 supports the MMC 4.3 specification, but actually it doesn’t completely (as we’ll see a bit later in this blog post).
The Microsoft SD bus driver (sdbus2.dll) is fully supporting the SD 2.0 specification. Because the MMC 4.3 specification is quite similar to SD 2.0, CE “somewhat” supports MMC 4.3.
So what does this mean? Well, for example, the number of data lines (bus width) of MMC supported by the Microsoft SD bus driver differs from the MMC specification:
8/4 or 1-bit mode
The MMC specification tells us it supports 8-bit wide bus mode (8-data lines). However, the SD 2.0 specification does not support 8 bit bus mode. Since CE officially supports SD but not MMC, CE does not support the 8-bit mode for any MMC/SD card. Unfortunately it appears the 4-bit mode is also not supported for MMC cards by the Microsoft SD bus driver even though the SD specification does support this mode. This leaves 1-bit mode as the only supported mode for MMC.
Here’s an overview of the supported modes by the SD bus driver (sdbus2.dll):
| Bus mode | SD | MMC |
|---|---|---|
| 1 | Y | Y |
| 4 | Y | N |
| 8 | N | N |
So does this mean that MMC cannot support 4 or 8 bit at all? Well no, not really... You can always CLONE the SDBUS driver and modify it according to your needs or you can develop your own driver without using the SD bus driver at all.
High Capacity
According to the SD 2.0 specification "High Capacity" means cards with sizes larger then 2GB. SDHC cards are supported by the SD bus driver version 2.0. However, because of a bug in the SD bus driver high capacity MMC cards don’t work. You need to fix one line of code to support HC MMC cards. Besides this bug there is also a difference in the protocol for MMC and SD 2.0 regarding High Capacity, more about that later.
First let’s fix the obvious bug so that your High Capacity MMC card will be recognized and mounted properly:
The first step is to clone the SD Bus driver located at <WINCEROOT>\PUBLIC\COMMON\OAK\DRIVER\SDCARD\SDBUS
- Open a build release window
- Type "
cd %_targetplatroot%" - Type "
cd src" - Type "
cd drivers" - Type "
md sdbus2" - Type "
cd sdbus2" - Type "
sysgen_capture -p common sdbus" - Now copy the files from
<WINCEROOT>\PUBLIC\COMMON\OAK\DRIVER\SDCARD\SDBUSinto<WINCEROOT>\PLATFORM\<YourBSP>\SRC\DRIVERS\SDBUS2 - And merge
sources.sdbusandsourcesso you end up with this sources file: - Try to build the SDBUS2 driver; it should build without errors. If it doesn’t, make sure you selected the SD Bus Driver in the catalog and performed a sysgen on your OSDesign.
- And add the SDBUS2 folder to the
dirsfile in theDRIVERSfolder. - Don't forget to change any BSP component that links to
$(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\sdbus.libto use the cloned SDBUS library, located at$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\sdbus.lib
TARGETNAME=sdbus
TARGETDEFNAME=SDBus2
DEFFILE=$(TARGETDEFNAME).def
TARGETTYPE=DYNLINK
RELEASETYPE=PLATFORM
DLLENTRY=_DllEntryCRTStartup
SOURCES = sdbusreq.cpp \
sddevice.cpp \
sdbus.cpp \
sdslot.cpp \
sdclient.cpp \
sddevinf.cpp \
sdiofeat.cpp \
sdworki.cpp \
sddebug.cpp \
TARGETLIBS= \
$(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\defbuslib.lib \
$(_SYSGENSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib \
$(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib
Note that I added SYNCHRONIZE_BLOCK=1 to make sure any other component that will link to the sdbus library will be able to find it. SYNCHRONIZE_BLOCK=1 makes sure this folder is built before any other folder in the DRIVERS folder is built.
Now change StringCchCopy to StringCchCat in line 1394 of sddevice.cpp (in your cloned folder of course!). This will append the "\\High_Capacity" string to the Client driver registry entry instead of replacing it (which leads to not finding the correct registry path for the profile because "HKLM\\High_Capacity" is not a valid registry path). Even with this fix it won’t find that path because Microsoft did not provide registry settings for High Capacity MMC. Let’s fix that by adding the following to platform.reg:
[HKEY_LOCAL_MACHINE\Drivers\SDCARD\ClientDrivers\Class\MMC_Class\High_Capacity]
"Dll"="SDMemory.dll"
"Prefix"="DSK"
"BlockTransferSize"=dword:40 ; send no more than 64 blocks of data per bus transfer
;"SingleBlockWrites"=dword:1 ; alternatively force the driver to use single block access
;"IdleTimeout"=dword:7D0 ; 2000 milliseconds
;"IdlePowerState"=dword:2 ; 0 == D0, 1 == D1, etc.
;"DisablePowerManagement"="" ; if value present, then disable (remove value to enable)
"Profile"="MMC"
"IClass"=multi_sz:"{A4E7EDDA-E575-4252-9D6B-4195D48BB865}",
"{8DD679CE-8AB4-43c8-A14A-EA4963FAA715}"
Now you can Build and Sysgen your BSP by right clicking on your BSP node in the Solution Explorer and choosing Build and Sysgen. NEVER EVER click Build and Sysgen from the Build menu, please read the blog post http://www.guruce.com/blogpost/whattobuildwhen to understand why you should delete that option from the build menu. After the Build and Sysgen of the BSP perform a Copy files to release directory followed by a Make image and download your kernel to your device. When you now insert a high capacity MMC card it should be recognized and mounted correctly, well, almost! The size is most probably still reported wrong. This is because of a difference in the protocol. CMD 8 is handled differently in the SD 2.0 and MMC 4.3 specification:
| Command | Type | Response | Abbreviation | Command Description |
|---|---|---|---|---|
| CMD8 | MMC | R1 | SEND_EXT_CSD | The card sends its EXT_CSD register as a Block of data. |
| CMD8 | SD | R7 | SEND_IF_COND | Sends SD Memory Card interface condition |
In the SD protocol CMD8 is used to identify high capacity cards and it is send at the beginning of the initialization process. When CMD8 is getting a response it means that it is identified as a High Capacity card. If sending a CMD8 results in a response timeout it is not a High Capacity card.
For MMC the CMD8 means retrieving the density of the card from the EXT_CSD register instead of the CDS register. CMD8 must be send after a CMD7 command which will place the card into "Tran" state. Since the SD bus driver doesn't do that the CMD8 will time out.
Like I said the SD bus driver fully supports the SD 2.0 specification and it reads the card density from the CSD register. This works for SD 2.0, but not for MMC. To fully support High Capacity MMC cards you should modify the SD bus driver so it can handle CMD8 instead of CMD9 to retrieve the card density for MMC high capacity cards.
SDBUS or SDBUS2
Now how do you select the correct SD bus driver? First remember that you have to install the correct version of Windows CE and install all required QFEs (see specification overview above). For Windows Embedded CE 6.0 there are two catalog components for SDBUS; "SD Bus Legacy" and "SD Bus driver". The legacy one is the SD bus driver that supports SD specification 1.1 and the "SD Bus Driver" item supports the 2.0 specification.
For all other versions of CE there is only one catalog component which automatically selects the SD bus 1.1 specification. To support the 2.0 specification in CE versions prior to CE 6.0 you have to set the IMGSDBUS2 environment variable to 1.
Conclusion
Windows CE fully supports the SD 2.0 specification, but as we saw this doesn’t automatically mean it also fully supports High Capacity MMC cards. Fortunately with a couple modifications here and there you can now fully support High Capacity MMC cards as well!


