小小小小强 发表于 2018-9-5 19:27:40

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

本帖最后由 小小小小强 于 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寄存器相应位的值没有改变?希望各位高手提出建议,感激不尽。


feixiang20 发表于 2018-9-5 23:27:59

是不是count这个变量在中断函数里面声明错误呢,定义没赋值么,时钟开了么,时钟时间设置过长么

小小小小强 发表于 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前先关闭中断,调用返回后重新打开中断

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] 2
查看完整版本: 高手请进,困扰很久的问题:STM32F7与MMC通讯异常错误