加载中…

加载中...

stm32 sdio调试,修改官方例程bug,已成功调通SDIO读取SD卡

转载 2016-07-18 15:52:05
标签:stm32debug

这几天研究stm32操作sd卡,使用的是ST给的例程stm32_eval_sdio_sd.c,版本V4.5.0,遇到了如下问题,现一一解决。

本文由Eric Qu撰写,QQ:12430300。转载请注明出处。

代码下载请见 http://download.csdn.net/detail/cokewei/4133725

 需要资源份2分,请尊重我的劳动成果,谢谢。

1:SD_WaitReadOperation()或者SD_WaitWriteOperation()函数死循环

原因:数据传输错误导致传输中断,无法满足退出等待的判断条件。

代码分析:

SD_Error SD_WaitReadOperation(void){  SD_Error errorstatus = SD_OK;   while ((SD_DMAEndOfTransferStatus() == RESET) && (TransferEnd == 0) && (TransferError == SD_OK))  {}

  if (TransferError != SD_OK)  {    return(TransferError);  }

  return(errorstatus);}

代码中用了while()是导致死循环的原因。TransferEnd ,TransferError 这两个参数是在中断中修改的, SD_DMAEndOfTransferStatus() 的结束条件是DMA传输结束。

看中断例程:

SD_Error SD_ProcessIRQSrc(void){  if (StopCondition == 1)  {    SDIO->ARG = 0x0;    SDIO->CMD = 0x44C;    TransferError = CmdResp1Error(SD_CMD_STOP_TRANSMISSION);  }  else  {    TransferError = SD_OK;  }  SDIO_ClearITPendingBit(SDIO_IT_DATAEND);  SDIO_ITConfig(SDIO_IT_DATAEND, DISABLE);  TransferEnd = 1;  return(TransferError);}

中断配置为数据传输结束中断SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE);

数据传输出错导致传输中断的情况下,SD_DMAEndOfTransferStatus的判断为false,TransferEnd 和TransferError 的状态也不会改变,导致while循环无法退出。

解决:

中断配置为SDIO_ITConfig(SDIO_IT_RXOVERR|SDIO_IT_DTIMEOUT|SDIO_IT_DCRCFAIL|SDIO_IT_DATAEND, ENABLE);

中断例程修改:

SD_Error SD_ProcessIRQSrc(void){ if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET) {  SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);  TransferError = SD_DATA_TIMEOUT; } else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET) {  SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);  TransferError = SD_DATA_CRC_FAIL; } else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET) {  SDIO_ClearFlag(SDIO_FLAG_RXOVERR);  TransferError = SD_RX_OVERRUN; } else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET) {  SDIO_ClearFlag(SDIO_FLAG_STBITERR);  TransferError = SD_START_BIT_ERR; } else {  if (StopCondition == 1)  {  SDIO->ARG = 0x0;  SDIO->CMD = 0x44C;  TransferError = CmdResp1Error(SD_CMD_STOP_TRANSMISSION);  }  else  {  TransferError = SD_OK;  } }    SDIO_ITConfig(SDIO_IT_RXOVERR|SDIO_IT_DTIMEOUT|SDIO_IT_DCRCFAIL|SDIO_IT_DATAEND, DISABLE);  TransferEnd = 1;  return(TransferError);}

这么做的作用是发生错误时也会进入中断,即使dma没有结束,也能退出while循环。

 

2:sd_init()过程失败

可能性1:按照SD规范,初始化之前需要有74个或更多个clock让sd卡同步,例程中把clock开起来后直接发送cmd0,没有同步clock,所以先修改SD_PowerON函数内SDIO_ClockCmd(ENABLE);调用之后增加200us延时。

可能性2:发生SDIO_FLAG_DCRCFAIL错误。

修改SDIO_TRANSFER_CLK_DIV 来修改数据传输速率。

按照ST例程的注释,数据传输速率不能超过25M,但是原先配置SDIO_TRANSFER_CLK_DIV=0,按照72M主频计算的话传输速度达到72/2=36M,不出错就怪了。

我现在配置SDIO_TRANSFER_CLK_DIV=2后正常。

可能性3:固件库使用不正确。使用V4.5的例程,固件库需要用V3.5.0的,试过3.2的固件库会失败。

 

3:SD_DMAEndOfTransferStatus函数内没有清标志位,按照datasheet,标志位是由手动清除的。

4:SD_ReadBlock()发生SDIO_FLAG_DCRCFAIL错误。

一开始是实践发现,先执行一下SD_ReadMultiBlocks函数,以后再执行SD_ReadBlock就正常了。很奇怪的现象吧。后来查阅了一些资料,发现SD卡的block大小并不是固定的,可以配置为512,1024等,于是怀疑是block大小配置不正确导致。检查发现SD_ReadBlock操作之前没有设置sd卡block大小,也就是cmd16,加入这个代码就像行了

    SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_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);

  errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);

  if (SD_OK != errorstatus)  {    return(errorstatus);  }

其实这个操作并不是每次读操作都要执行的,如果中途不改变block大小,只要初始化的时候设置一次就可以了。

转载自网络。


阅读(0) 评论(0) 收藏(0) 转载(0) 举报/Report

评论

重要提示:警惕虚假中奖信息
0条评论展开
相关阅读
加载中,请稍后
Zoepreal
  • 博客等级:
  • 博客积分:0
  • 博客访问:6,167
  • 关注人气:0
  • 荣誉徽章:

相关博文

推荐博文

新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

新浪公司 版权所有