天天看點

stm32f103 HAL庫sdmmc bugstm32f103 HAL庫sdmmc bug簡述

stm32f103 HAL庫sdmmc bug

釋出版本: 1.0

檔案密級: 公開資料

前言

概述

讀者

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

軟體開發工程師

産品版本 修訂記錄

日期 版本 作者/郵箱 修訂說明
2019-12-29 V1.0 wingceltis-c/[email protected] 初始版本

文章目錄

  • stm32f103 HAL庫sdmmc bug
  • 簡述
    • 1.TIMEOUT标志位清除錯誤
    • 2. CMD55響應資料判斷異常

簡述

這段時間用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

繼續閱讀