stm32f103 HAL库sdmmc bug

stm32f103 HAL库sdmmc bug


发布版本: 1.0

文件密级: 公开资料


前言
概述

读者

本文档(本指南)主要使用于以下工程师:

软件开发工程师

产品版本 修订记录

日期版本作者/邮箱修订说明
2019-12-29V1.0wingceltis-c/wingceltis@aliyun.com初始版本


简述

这段时间用stm32f103写个小项目需要用到sd卡 + fatfs文件系统的功能。用cube配置完成后,1G 2G的sd卡读写都没有问题,256M的卡在执行f_mount的时候会返回FR_NOT_READY错误,跟了下代码发现是在stm32f1xx_hal_sd.c的SD_PowerON方法中,因为1G 2G的卡刚好是V2.0的版本,而手上的256M刚好是V1.x的版本,这就导致走的流程有点不一样,不过正常来说HAL库应该也是要支持V1.x版本的。百度了下相关错误并且和正点原子3.5库函数版本的代码对比了下发现是下面的错误导致的。

1.TIMEOUT标志位清除错误

在stm32f1xx_hal_sd.c的SD_PowerON方法中,会先发送CMD8指令判断当前SD卡的版本,如果有响应就是V2.0,没有响应就是V1.X版本或者MMC卡。 hal库中SDMMC_CmdOperCond这个方法会先发送CMD8指令然后调用SDMMC_GetCmdResp7方法接收响应的数据,我这个256M的卡是V1.x版本所以没有响应会报超时错误,正常逻辑就是清除超时标志位然后返回对应错误即可,HAL库这里应该是书写错误,写成了清除SDIO_FLAG_CMDREND 标志位。导致后面的指令会直接报超时错误。
错误代码:

static uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx)

    if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
    {
        /* Card is SD V2.0 compliant */
        __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CMDREND); //这里应该要清除超时标志位的
        return SDMMC_ERROR_CMD_RSP_TIMEOUT;
    }

把SDIO_FLAG_CMDREND改成 SDIO_FLAG_CTIMEOUT即可,修改成如下代码:

static uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx)

    if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
    {
        /* Card is SD V2.0 compliant */
        __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT); //清除超时标志位
        return SDMMC_ERROR_CMD_RSP_TIMEOUT;
    }

2. CMD55响应数据判断异常

接着上面的流程,发送CMD8没响应后接着会发送CMD55,如果有响应就是V1.x版本的SD卡没有响应就是MMC卡(默认HAL库好像是不支持MMC卡)。这个CMD55的接受方法SDMMC_GetCmdResp1也有问题,HAL库收到CMD55响应后,还会判断数据内容,只要不是全0就会报错 SDMMC_OCR_ILLEGAL_CMD,刚好我手上的卡会返回一串非零数字,导致初始化失败,所以这里直接清除这个标志位即可。
修改如下:

  static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)
  
    /* Clear all the static flags */
    __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_FLAGS);

    /* We have received response, retrieve it for analysis  */
    response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1);

    /*
       2019-12-28
       收到CMD55响应后,还会判断数据内容,只要不是全0就会报错 SDMMC_OCR_ILLEGAL_CMD。
       有些卡会返回一串非零数字,导致初始化失败,所以这里直接清除标志位。
    */
    response_r1 &= !SDMMC_OCR_ILLEGAL_CMD;

    if ((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
    {
        return SDMMC_ERROR_NONE;
    }

参考链接:
http://www.stm32cube.com/question/1106
http://www.stmcu.org.cn/module/forum/thread-614460-1-1.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值