一.项目概述
在使用默认的SDK的SDIO与FATFS过程中,发现原SDK存在如下几个问题:
【1】无法识别大小为2G以下的卡
【2】fatfs无法正常挂载2G以下的卡
【3】将主频修改至240M后,卡片读写会出现问题
因此我对原来SDK的SDIO驱动和Fatfs的移植部分进行了修改,并解决了这几个问题。
二.主频问题
【1】问题描述,在SDK的wm_main.c中存在如下的函数,是用来设置CPU的总线频率,最高为240M。为了更好的释放性能,我将其调整至了240M后出现了SD卡的读写不正常的问题。
tls_sys_clk_set(CPU_CLK_240M);
【2】问题的原因:SDIO在mmc模式下,且使用的SD卡片为默认速度配置的话,最高的输出频率只能为20M。W801的SDIO挂载在CPU的时钟总线上,通过分频得到,原来SDK中的默认分频数为1/6,当修改主频后,SDIO的总线频率也就变成了40M,超过上限无法正常读写。
【3】解决的办法:解决办法有两种,一个是修改分频寄存器的值,一个是修改SD卡的速度配置,我这里选择的是前者。SDIO分频的值对应表如下图所示;
因此当cpu主频设置为240M时,需要讲分频改为1/12才能不超过20M的上限,修改的位置在下面这个初始化配置函数中进行修改:
int wm_sdh_config(void)
{
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
SDIO_HOST->MMC_CARDSEL = 0xC0 | (sysclk.cpuclk / 2 - 1);//0xd3; //enable module, enable mmcclk
SDIO_HOST->MMC_CTL = 0xEB; //原来SDK中为D3,这里要实现分频为1/12,需要修改为EB,当主频变化时,这里也需要对应改变保证不超过20M
SDIO_HOST->MMC_INT_MASK = 0x100; //unmask sdio data interrupt.
SDIO_HOST->MMC_CRCCTL = 0xC0; //
SDIO_HOST->MMC_TIMEOUTCNT = 0xff;
return 0;
}
【修改后试验结果】
三.SDIO驱动与Fatfs修改
1.SD卡相关概念
【1】SD卡的分类:
SD卡由mmc卡发展而来,根据协议版本,容量大小可以分为若干种,因为W801最高支持sd2.0协议,因此我们面对的如下4类卡片:
1.mmc卡
2.SD卡:协议版本为SD1.0,容量大小0-2G
3.SDSC卡:协议版本为SD2.0,容量大小0-2G
4.SDHC卡:协议版本为SD2.0,容量大小2-32G
【2】不同SD卡的读写区别
2G以内的SD卡是字节寻址的,而2G以上的卡只能为块寻址。举个例子,当地址为0x01时,2G内的卡会判定为是从字节地址0x01开始读写,而2G以外的卡会判定成为从第一个块开始读写。
【3】SD卡的初始化与识别
根据SD2.0协议,上述四类卡片的识别过程如下图所示,我也写了一个中文版的导图附上。
2.SDK的驱动缺陷
如上面说到的初始化过程,主要通过cmd8以及acmd41返回的OCR寄存器的值来识别那四类卡片。这里我们看一下SDK的原代码可以发现,原SDK中对于CMD8命令是否响应未做区分,如果未读到response则直接判定为初始化失败。同时后续也未对OCR寄存器的CCS