转载请注明原帖地址及出自ARMCE,此为ARMCE定制原创稿
文章来源:http://www.armce.com/bbs/thread-885-1-1.html
最近需要给mx27加上SDHC驱动以支持SDHC的SD卡
网上许多关于2440支持SDHC的文章,借鉴很多,但是由于MX27驱动的特殊结构,需要做更多改动,详细如下:
平台:wince6 R3
其实原理上都是一样:
1 使用SDBUS2驱动
2 底层增加对ResponseR7的支持
但是MX27驱动上有些特别的地方
首先是使用SDBUS2的驱动,我建议大家把这个驱动拷贝出来在bsp的drivers目录下编译,我觉得这样比较好,方便日后修改。
而且我重命名了SDBUS2的驱动
1 拷贝PUBLIC/COMMON/OAK/DRIVERS/SDCARD/SDBUS文件夹到bps的drivers目录
2 修改sources文件
- SYNCHRONIZE_BLOCK=1
- TARGETNAME=osdbus
- 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
注意这里我将这个dll命名为osdbus了,而不是sdbus或者sdbus2,以示区别
然后编译一下sdbus2目录,应该可以通过
2 在bsp的drivers目录的dirs下增加编译sdbus2目录,放在sdhc目录前面
3 修改PLATFORM/COMMON/SRC/SOC/FREESCALE/MX27_FSL_V1/DRIVERS/SDHC/sources文件
- TARGETNAME=sdhc_mx27_fsl_v1
- TARGETTYPE=LIBRARY
- INCLUDES= /
- ../../inc; /
- ../inc; /
- $(_TARGETPLATROOT)/SRC/DRIVERS/sdbus2; /
- ../../../common_fsl_v1/inc;
- CDEFINES=$(CDEFINES) -DCEDDK_USEDDKMACRO
- SOURCES = main.cpp /
- sdcontrol.cpp
这里主要将头文件目录改为$(_TARGETPLATROOT)/SRC/DRIVERS/sdbus2,而不是老的sdbus驱动
4 修改PLATFORM/COMMON/SRC/SOC/FREESCALE/MX27_FSL_V1/DRIVERS/INC/sdhc.h
- #include "SDCardDDK.h"
- //#include "sdbusdriver.h"
- #include "SDHCD.h"
5 修改PLATFORM/COMMON/SRC/SOC/FREESCALE/MX27_FSL_V1/DRIVERS/SDHC/sdcontrol.cpp
- #include "csp.h"
- #include "sdhc.h"
- #include "sdbus.hpp"
- #include "sddevice.hpp"
在SDHBusRequestHandler函数中增加对ResponseR7的支持
- case ResponseR5:
- case ResponseR6:
- case ResponseR7:
- CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 1);
6 编译PLATFORM/COMMON/SRC/SOC/FREESCALE/MX27_FSL_V1/DRIVERS/SDHC目录
会发现有错误
原因在于sdcontrol.cpp中的SDControllerBusyWaitResponse函数中调用了
- cmdArg = (((DWORD)((SDDCGetClientDeviceFromHandle(pRequest->hDevice))->RelativeAddress)) << 16);
这个函数的目的是查询卡的状态,等待卡busy结束,但是需要用到卡的地址
这里问题就来了,因为卡的地址(RCA)以前老的sdbus下是通过结构体获得的,现在新的sdbus2找不到这个结构体定义了,怎么把这个地址获得呢?
先考虑一个其他办法
把这个函数屏蔽掉
编译通过
7 修改PLATFORM/iMX27ADS/SRC/DRIVERS/SDHC/sources文件
- SOURCELIBS= /
- $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/sdcardlib.lib /
- $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/sdhclib.lib /
- $(_TARGETPLATROOT)/lib/$(_CPUINDPATH)/osdbus.lib /
- $(_PLATCOMMONLIB)/$(_CPUINDPATH)/sdhc_mx27_fsl_v1.lib
增加osdbus.lib,去掉sdbus.lib
8 编译PLATFORM/iMX27ADS/SRC/DRIVERS/SDHC通过
9 修改platform.bib,增加
- #if defined IMGSDBUS2
- ; @CESYSGEN IF CE_MODULES_SDBUS2
- sdbus.dll $(_FLATRELEASEDIR)/osdbus.dll NK SHK
- ; @CESYSGEN ENDIF CE_MODULES_SDBUS2
- #else
- ; @CESYSGEN IF CE_MODULES_SDBUS
- sdbus.dll $(_FLATRELEASEDIR)/sdbus.dll NK SHK
- ; @CESYSGEN ENDIF CE_MODULES_SDBUS
- #endif
增加对新的sdbus驱动支持
10 在vs2005的项目组件选择中,钩上
11 sysgen一下
进入系统会发现sdhc卡可以识别了,但是有一个问题,在写sdhc卡后经常出现死机
这时候我们需要回头修改下那个屏蔽的函数,就是说我们不能绕过等待卡busy的那个函数
关键问题就是如何获得sd卡地址
大家看这个函数
sdcontrol.cpp中的SDHBusRequestHandler
这里是处理所有命令的地方
在sd卡识别流程过程中,在激活卡的时候会有这个命令SD_CMD_SELECT_DESELECT_CARD,这里会将RCA作为参数传递进来
到这里大家就了解了,只要我们在这里截获SD_CMD_SELECT_DESELECT_CARD的参数,我们就能获得RCA了
而且SDControllerBusyWaitResponse这个函数只有SDHBusRequestHandler会调用,而且条件是
- if((pController->LastResponedR1b == ResponseR1b) &&
- (pRequest->TransferClass != SD_COMMAND))
- {
- DEBUGMSG(ZONE_INFO, (TEXT("SDHBusRequestHandler: wait for busy!/r/n")));
- status = SDControllerBusyWaitResponse(pController);
- if(status != SD_API_STATUS_SUCCESS)
- {
- SDHCDIndicateBusRequestComplete(pController->pHCContext, pRequest, SD_API_STATUS_DEVICE_BUSY);
- return SD_API_STATUS_DEVICE_BUSY;
- }
- }
就是说在传输模式才会用这个函数
而SD_CMD_SELECT_DESELECT_CARD命令是进入传输模式的必经之路,所以可以在传输模式之前获得RCA
添加一个全局变量g_wRCA
修改SDHBusRequestHandler,在入口处增加
- if(0 == g_wRCA) {
- if(SD_CMD_SELECT_DESELECT_CARD == pRequest->CommandCode) {
- g_wRCA = (WORD)(((pRequest->CommandArgument) & 0xffff0000) >> 16);
- RETAILMSG(1, (TEXT("SDHBusRequestHandler: Get RCA = 0x%X!/r/n"), g_wRCA));
- }
- }
然后修改SDControllerBusyWaitResponse
- if(0 == g_wRCA) {
- return SD_API_STATUS_SUCCESS;
- }
- // return status;
- DEBUGMSG(ZONE_FUNCTION, (TEXT("+SDControllerBusyWaitResponse for SDHC/MMC Controller driver/r/n")));
- retryCount = DEFAULT_BUS_REQUEST_RETRY_COUNT;
- pRequest = SDHCDGetAndLockCurrentRequest(pHCDevice->pHCContext, 0);
- cmdArg = g_wRCA << 16;
别忘了还要去在适当的地方清楚RCA的值,因为你的SD卡槽可能会换SD卡
我是在SDCardDetectIstThread中加的
只要检测到SD卡中断,无论是插入还是拔出,都将g_wRCA清零
- if (WaitForSingleObject(hCardInsertInterruptEvent, INFINITE) != WAIT_OBJECT_0)
- {
- ERRORMSG(ZONE_ERROR, (TEXT("SDCardDetectIstThread: Wait Failed!/r/n")));
- return 0;
- }
- g_wRCA = 0;
好了,所有的都重新编译,这下子就正常了
对于CE5应该也是差不多的。