STM32
直播中

刘静

8年用户 1347经验值
私信 关注
[问答]

STM32F7与MMC通讯异常错误的原因?怎么解决?

我板子的配置是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%xrn",__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寄存器相应位的值没有改变?希望各位高手提出建议,感激不尽。

回帖(1)

江根磊

2024-4-15 11:28:04
1.开关中断有效果,但依然有问题。
2.最终还是采用了这位外国用户提出的解决方案。
3.解决方案思路是以自己设置的接收完成标志作为命令响应成功的标志,而不依赖sd外设寄存器标志(SD外设寄存器响应标志会在其他异步线程中意外被清除)。
4.贴一下修改后的代码。




  • /* stm32f4xx_II_sdmmc.c line:1160*/
  • /**
  •   * @brief  Checks for error conditions for R1 response.
  •   * @param  hsd SD handle
  •   * @param  SD_CMD The sent command index
  •   * @retval SD Card error state
  •   */
  • FlagStatus flag_resp = RESET;
  • static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, 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 / 8U /1000U);
  •   flag_resp = RESET;


  •   do
  •   {
  •     if (count-- == 0U)
  •     {
  •       return SDMMC_ERROR_TIMEOUT;
  •     }


  •     if(flag_resp == SET)
  •     {
  •       break;
  •     }


  •   }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT));






  • /* sd_diskio.c line:487*/
  • /**
  • * @brief Rx Transfer completed callbacks
  • * @param hsd: SD handle
  • * @retval None
  • */
  • extern FlagStatus flag_resp;
  • void BSP_SD_ReadCpltCallback(void)
  • {
  •   /*
  •    * No need to add an "osKernelRunning()" check here, as the SD_initialize()
  •    * is always called before any SD_Read()/SD_Write() call
  •    */
  •   flag_resp = SET;
  •   osMessagePut(SDQueueID, READ_CPLT_MSG, osWaitForever);
  • }



举报

更多回帖

发帖
×
20
完善资料,
赚取积分