对于新近STM32上SDIO用4bitDMA模式读写SHDC的驱动修改

    还记得上次我用RT_thread系统里面的文件系统调试了下STM32的SDIO读取SHDC。自然, 我是写的不好的呵,但是仍然希转载的人注意个人劳动成果,注明转载以及出处。

    这次我由于个人兴趣,需要把SIDO驱动移植到到ASP系统里面去。

    按理说,上次改好了, 这次应该可以正常编译就可以直接用的了。但是事情总没有你想象中的那么顺利,我发现在读跟写的时候,会出现一个相应超时的错误返回“RSP_TIMEOUT”,然后退出,一般是出现在这个位置

SD_Error SD_WriteBlock(uint32_t addr, uint32_t *writebuff, uint16_t BlockSize)
{
  SD_Error errorstatus = SD_OK;
  uint8_t  power = 0, cardstate = 0;
  uint32_t timeout = 0, bytestransferred = 0;
  uint32_t cardstatus = 0, count = 0, restwords = 0;
  uint32_t *tempbuff = writebuff;
 // uint32_t temp;
  //SYSTIM tim1,tim2;
  if (writebuff == NULL)
  {
    errorstatus = SD_INVALID_PARAMETER;
    return(errorstatus);
  }

  TransferError = SD_OK;
  TransferEnd = 0;
  TotalNumberOfBytes = 0;

  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = 0;
  SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_1b;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Disable;
  SDIO_DataConfig(&SDIO_DataInitStructure);
  SDIO_DMACmd(DISABLE);

  if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)
  {
    errorstatus = SD_LOCK_UNLOCK_FAILED;
    return(errorstatus);
  }

  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    BlockSize = 512;
    addr /= 512;
  }

  /* Set the block size, both on controller and card */
  if ((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0))
  {
    power = convert_from_bytes_to_power_of_two(BlockSize);

    SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SET_BLOCKLEN;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);

temp = SDIO->STA;

    errorstatus = CmdResp1Error(SDIO_SET_BLOCKLEN);

不管读写都是在这个地方命令出错,而且有时候即使不出现RSP_TIMEOUT提示,也会出现ILLEGAL_CMD错误。

但是有时候你写出错后,读就有可以。都很随机,写是肯定失败了。

这个问题很多人都可能遇到吧。

但是其实你有用调试输出的话,就会发现,在你一调用命令发送函数的时候,读取SDIO->STA里面的内容,你会发现已经出错了呵。

这就是未发先错。但是你读取了SDIO->STA会自动清除自己的状态的, 于是 ,一发送后马上读取SDIO->STA的内容,再调用命令回应函数,这个命令有可以通过了。这样一般是可以读正常了。(如上绿色代码)。

上面那个也没花我多少时间, 我更多时间却是浪费在了写shdc上。

写函数也会报这个错误,但是如果你先读再写,有时候又不会报这个错误。呵呵, 是不是很奇怪。还有基本上写用SD_WriteBlock()函数的话,一般会返回CRC_FAILED错误,也就是校验失败了,于是自然而然的退出了写,返回错误。但是我在rt_thread系统上是可以正常写的,但是,写不会退出写函数,但是内容早就写完了,这个bug也是我调试两个系统代码的时候才发现的。而在asp里面,写如果不报错,也是没写进去的。

我自然而然 的想到可能是系统编译器的问题,但是后来我又排除了这个可能, 至于怎么排除,属于个人技巧问题呵。

再接着我就查看了整个读写驱动,每个错误都调试。结果还是没有找出个所以然来,依旧的CRC_FAILED.T_T

难道是读写顺序也有关。。。试了下,一样不行。相反的,更多时候连读也有问题了。。。。

在5个连续通宵到早上7点的惨痛代价后,我想起了一个事情。

那就是关于STM32传输数据的SDIO。

首先,我采用的是4位DMA模式,所以我的读写是自动的,asp系统不可以,但是rt_thread却可以读写,即使是编译器不同,但是时钟晶振总是一样的,不可能一个错误,一个正常的。除非系统中断影响,还有一个致命伤,晶振!!!!!!!!

没错了,就是晶振,在asp里面我的stm32晶振是调到最高72Mhz的,但是rt_thread我没注意过,能够读,但是写会数据出错,就说明是数据太快,SHDC卡跟不上节奏,所以crc校验出错了。

当然,推想还是要靠实践证明的,于是我就把4位总线SDIO的时钟调低了,如下:

SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV+1;
        SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
        SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
        SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
        SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_4b;
        SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Enable;
        SDIO_Init(&SDIO_InitStructure);


      直接加1就是了,这样的话分频出来实际上是72M/(2+2) = 18M

然后试了下, 竟然可以写,而且更重要的是,这个写是没有bug的,rt_thread系统的写会是死循环,回不来了,但是这个写回正常返回。

再接着,我自然也会想那么先前的SDIO->STAs错误是不是也是这个原因造成的。

于是我也把temp = SDIO->STA注释掉,结果:

一切正常。

      呵呵,对不起了,各位, 忽悠了你们这么久,其实前面都可以不要的,我直接跟你们说是由于STM32的晶振频率影响了SHDC的写就可以了的。

      实际上改慢下SIDO的读写速度,大家应该意见很大把, 那如果你们不写的话, 可以直接用我个temp=SDIO->STA;这样读取速度一样,但是不能写,而且- -读的也很不稳定。

顺便说下把,看到有个论坛一个老大哥用sdio读取shdc跟sd时候不一样, 说用fat的f_open函数失败,

然后说是自己没仔细看, 忽略了SHDC跟SD卡的系统引导区不同,要去查手册的。

我其实很想说的是,“大哥,你的读函数出错了才是。SHDC的系统引导区跟普通SD卡一样的。只是FAt16格式化的SD卡盘格式符跟fat32的SD卡格式符存放地址不一样而已。你读取的数据错误了。”

其它也没啥了,文件已经上传CSDN。

感觉自己好白痴啊, 这门简单的地方现在才发现,白白浪费了5天的光阴的。

http://download.csdn.net/source/2600382

另外,本人不善于文笔,写的不好。不要喷我

还有,请不要张冠李戴,把作者的东西说成自己的。

纯粹的原创,转载的请注明出处。

以前也弄过zigbee的,等有空了就顺便把zigbee协议栈2006的串口弄出个教程把, 发现这个不难,但是纠结在这上面的人很多啊。

猜你喜欢

转载自blog.csdn.net/xuzhenglim/article/details/5792135