你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

高手请进,困扰很久的问题:STM32F7与MMC通讯异常错误

[复制链接]
小小小小强 提问时间:2018-9-5 19:27 /
本帖最后由 小小小小强 于 2018-9-6 09:15 编辑

我板子的配置是STM32F7 + Sandisk EMMC,软件环境为freertos + fatfs,EMMC驱动为ST HAL库自带的,驱动程序能够正常读写EMMC。在长时间读写后会遇到STM32发送命令后读取不到响应的问题,复现问题的时间有长有短,但是每次都是在HAL_MMC_ReadBlocks_DMA中出错,报错的代码位置为:
do
  {
    if (count-- == 0)
    {
                printf("line:%d,sta:0x%x,res_cmd=0x%x,SD_CMD:%d,req_cmd:%d,dctl:0x%x\r\n",__LINE__,SDMMCx->STA,SDMMCx->RESPCMD,SD_CMD,\
                        SDMMCx->CMD,SDMMCx->DCTRL);
      return SDMMC_ERROR_TIMEOUT;
    }

  }while(!__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT));
都是count=0后超时退出,我把count值修改到非常大也会遇到相同的问题。通过Sandisk实验室的MMC分析仪抓取整个通信过程分析,MMC在收到命令后是正常响应了,是STM32端没有读到响应,由于已经是直接读取寄存器了,所以我这个小白就不知道如何判断为什么STM32没有收到回复了,也不知道改如何修改,既然MMC已经回复了,有哪些原因可能会导致SDMMC STA寄存器相应位的值没有改变?希望各位高手提出建议,感激不尽。


收藏 评论16 发布时间:2018-9-5 19:27

举报

16个回答
caowent 回答时间:2020-5-8 16:30:20
正如10#朋友提到,我也参考了st官方论坛用户的解决方案
1.开关中断有效果,但依然有问题。
2.最终还是采用了这位外国用户提出的解决方案。
3.解决方案思路是以自己设置的接收完成标志作为命令响应成功的标志,而不依赖sd外设寄存器标志(SD外设寄存器响应标志会在其他异步线程中意外被清除)。
4.贴一下修改后的代码。

  1. /* stm32f4xx_II_sdmmc.c line:1160*/
  2. /**
  3.   * @brief  Checks for error conditions for R1 response.
  4.   * @param  hsd SD handle
  5.   * @param  SD_CMD The sent command index  
  6.   * @retval SD Card error state
  7.   */
  8. FlagStatus flag_resp = RESET;
  9. static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)
  10. {
  11.   uint32_t response_r1;
  12.   
  13.   /* 8 is the number of required instructions cycles for the below loop statement.
  14.   The Timeout is expressed in ms */
  15.   register uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);
  16.   flag_resp = RESET;
  17.   
  18.   do
  19.   {
  20.     if (count-- == 0U)
  21.     {
  22.       return SDMMC_ERROR_TIMEOUT;
  23.     }

  24.     if(flag_resp == SET)
  25.     {
  26.       break;
  27.     }
  28.    
  29.   }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT));
  30.   
  31.   
  32.   
  33. /* sd_diskio.c line:487*/
  34. /**
  35. * @brief Rx Transfer completed callbacks
  36. * @param hsd: SD handle
  37. * @retval None
  38. */
  39. extern FlagStatus flag_resp;
  40. void BSP_SD_ReadCpltCallback(void)
  41. {
  42.   /*
  43.    * No need to add an "osKernelRunning()" check here, as the SD_initialize()
  44.    * is always called before any SD_Read()/SD_Write() call
  45.    */
  46.   flag_resp = SET;
  47.   osMessagePut(SDQueueID, READ_CPLT_MSG, osWaitForever);
  48. }
复制代码
captainliuy 回答时间:2019-5-8 10:30:53
st论坛里有人给出的解释,但是没有给出解决办法,是因为中断的问题。

Do you happen to be using an RTOS and the SDIO in DMA mode? I've just solved what I believe is the same problem in the STM32F4 HAL drivers.



The problem presents itself when an RTOS context switch happens AFTER SDIO_SendCommand() is called (which begins to clock out the CMD), but before the SDMMC_FLAG_CMDREND flag is set. If a task context switch happens at this time, and does not return to the current task before SD_DMAReceiveCplt() is called, the SDMMC_FLAG_CMDREND is cleared, and never "noticed" by the SDMMC_GetCmdResp1() timeout loop.



In the attached Saleae Logic capture:

ERROR is low after an SDIO timeout occurs.

SDIO wait_loop is low when entering the waiting loop in SDMMC_GetCmdResp1(), high when exiting

ClearSDIOFlags is low then high whenever the SDIO flags are cleared.

SD_CMD is the SDIO CMD line

SD_D0 is the SD_D0 line

PJ11 goes low then high each time the loop in SDMMC_GetCmdResp1() checks the flags in the loop.



When the error happens at the end of the capture, an RTOS context switch happens so the CPU executes another task shortly after SDIO_SendCommand() is called. The flags are not being checked at this point, and while they are properly set, they are eventually cleared by the SD_DMAReceiveCplt() ISR function before SDMMC_GetCmdResp1() ever gets back into the execution context.



Hope this helps.

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

feixiang20 回答时间:2018-9-5 23:27:59
是不是count这个变量在中断函数里面声明错误呢,定义没赋值么,时钟开了么,时钟时间设置过长么

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

小小小小强 回答时间:2018-9-6 09:02:50



谢谢楼上关注。我贴出更完整代码,都是STM32F7 HAL库自带
static uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
{
  uint32_t response_r1;
  
  /* 8 is the number of required instructions cycles for the below loop statement.
  The Timeout is expressed in ms */
  register uint32_t count = Timeout * (SystemCoreClock / 8 /1000);
  
  do
  {
    if (count-- == 0)
    {
                printf("line:%d,sta:0x%x,res_cmd=0x%x,SD_CMD:%d,req_cmd:%d,dctl:0x%x\r\n",__LINE__,SDMMCx->STA,SDMMCx->RESPCMD,SD_CMD,\
                        SDMMCx->CMD,SDMMCx->DCTRL);
      return SDMMC_ERROR_TIMEOUT;
    }
   
  }while(!__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT));
//省略STA判断
}
count变量值为函数形参根据系统时钟计算出来的。现在系统时钟为208M,MMC CLK为20.48M,通讯为8BIT模式
小小小小强 回答时间:2018-9-6 09:04:52
另外,出错的时候测量,CLK线上一直有时钟,通过sandisk FAE用MMC通讯分析仪查看,STM32付出CMD后,MMC是正确回复了的,是STM32端没有读到。
小小小小强 回答时间:2018-9-6 09:10:56
feixiang20 发表于 2018-9-5 23:27
是不是count这个变量在中断函数里面声明错误呢,定义没赋值么,时钟开了么,时钟时间设置过长么 ...

count值没有在中断函数里声明,出错时测量CLK线上信号正常。
小小小小强 回答时间:2018-9-6 18:44:28
人工顶下
hpingfr 回答时间:2018-10-30 11:31:36
也遇到这个问题了,有没有高手给解决一下
e190 回答时间:2018-12-1 16:09:35
请问楼主这个问题解决了吗?我也遇到这个问题
小小小小强 回答时间:2018-12-27 08:24:18
这个问题已经接近,办法是需要在调用MMC的API前先关闭中断,调用返回后重新打开中断

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

captainliuy 回答时间:2019-5-8 10:45:40
captainliuy 发表于 2019-5-8 10:30
st论坛里有人给出的解释,但是没有给出解决办法,是因为中断的问题。
  1. do
  2.   {
  3.     if (count-- == 0U)
  4.     {
  5.       return SDMMC_ERROR_TIMEOUT;
  6.     }
  7.    
  8.   }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT));
复制代码

SDIO_FLAG_CMDREND 已经在其他位置被清掉了
QHCH11 回答时间:2019-6-18 19:17:31
我也遇到了同样的问题,我这边的触发条件是拔掉SD卡重插的时候f_mount,我在f_mount前面加上这两句解决了

memset(&disk, 0, sizeof(disk));
FATFS_LinkDriver(&SD_Driver, SD_Path);
lxybkb 回答时间:2019-6-19 11:22:35
谢谢楼主 分享
linxi6 回答时间:2019-6-26 21:23:29
请教一下,MMC使用时初始化不成功,设置卡相对地址时CRC校验错误。知不知道怎么解决?
jyun 回答时间:2019-9-20 11:49:13
楼主解决了吗?我也是用HAL库一模一样的地方,我是 FREERTOS 跑的USBD  MSC 触发条件是 ,边用FATFS 读,加上电脑去 改写文件。
12下一页
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版