STM32F4 + eMMC 之 EXT_CSD寄存器读取和写入(修正)

参照 JEDEC  eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)

基于STM32Cube_FW_F4_V1.21.0库修改(stm32f4xx_hal_mmc.h),4bit模式,其他与SD卡驱动类似。实测写入速度

1MB/s左右。

容量计算:

Capacity = (hmmc->MmcCard.EmmcExtCsd.EXT_CSD.SEC_COUNT[3] << 24 |

 hmmc->MmcCard.EmmcExtCsd.EXT_CSD.SEC_COUNT[2] << 16 |
 hmmc->MmcCard.EmmcExtCsd.EXT_CSD.SEC_COUNT[1] << 8   |

 hmmc->MmcCard.EmmcExtCsd.EXT_CSD.SEC_COUNT[0]) × BlockSize(512)

 

typedef union
{
        struct _EXT_CSD
        {
            __IO uint8_t    Reserved19[15];
            __IO uint8_t    CMDQ_MODE_EN;
            __IO uint8_t    SECURE_REMOVAL_TYPE;
            __IO uint8_t    PRODUCT_STATE_AWARENESS_ENABLEMENT;
            __IO uint8_t    MAX_PRE_LOADING_DATA_SIZE[4];
            __IO uint8_t    PRE_LOADING_DATA_SIZE[4];
            __IO uint8_t    FFU_STATUS;
            __IO uint8_t    Reserved18[2];
            __IO uint8_t    MODE_OPERATION_CODES;
            __IO uint8_t    MODE_CONFIG;
            __IO uint8_t    BARRIER_CTRL;
            __IO uint8_t     FLUSH_CACHE;
            __IO uint8_t     CACHE_CTRL;
            __IO uint8_t     POWER_OFF_NOTIFICATION;
            __IO uint8_t     PACKED_FAILURE_INDEX;
            __IO uint8_t     PACKED_COMMAND_STATUS;
            __IO uint8_t     CONTEXT_CONF[15];
            __IO uint8_t     EXT_PARTITIONS_ATTRIBUTE[2];
            __IO uint8_t     EXCEPTION_EVENTS_STATUS[2];
            __IO uint8_t     EXCEPTION_EVENTS_CTRL[2];
            __IO uint8_t     DYNCAP_NEEDED;
            __IO uint8_t     CLASS_6_CTRL;
            __IO uint8_t     INI_TIMEOUT_EMU;
            __IO uint8_t     DATA_SECTOR_SIZE;
            __IO uint8_t     USE_NATIVE_SECTOR;
            __IO uint8_t     NATIVE_SECTOR_SIZE;
            __IO uint8_t     VENDOR_SPECIFIC_FIELD[64];
            __IO uint8_t    Reserved17[2];
            __IO uint8_t     PROGRAM_CID_CSD_DDR_SUPPORT;
            __IO uint8_t     PERIODIC_WAKEUP;
            __IO uint8_t     TCASE_SUPPORT;
            __IO uint8_t    PRODUCTION_STATE_AWARENESS;
            __IO uint8_t     SEC_BAD_BLK_MGMNT;
            __IO uint8_t    Reserved16;
            __IO uint8_t     ENH_START_ADDR[4];
            __IO uint8_t     ENH_SIZE_MULT[3];
            __IO uint8_t     GP_SIZE_MULT[12];
            __IO uint8_t     PARTITION_SETTING_COMPLETED;
            __IO uint8_t     PARTITIONS_ATTRIBUTE;
            __IO uint8_t     MAX_ENH_SIZE_MULT[3];
            __IO uint8_t     PARTITIONING_SUPPORT;
            __IO uint8_t     HPI_MGMT;
            __IO uint8_t     RST_n_FUNCTION;
            __IO uint8_t     BKOPS_EN;
            __IO uint8_t     BKOPS_START;
            __IO uint8_t     SANITIZE_START;
            __IO uint8_t     WR_REL_PARAM;
            __IO uint8_t     WR_REL_SET;
            __IO uint8_t     RPMB_SIZE_MULT;
            __IO uint8_t     FW_CONFIG;
            __IO uint8_t    Reserved15;
            __IO uint8_t     USER_WP;
            __IO uint8_t    Reserved14;
            __IO uint8_t     BOOT_WP;
            __IO uint8_t     BOOT_WP_STATUS;
            __IO uint8_t     ERASE_GROUP_DEF;
            __IO uint8_t    Reserved13;
            __IO uint8_t    BOOT_BUS_CONDITIONS;
            __IO uint8_t    BOOT_CONFIG_PROT;
            __IO uint8_t     PARTITION_CONFIG;
            __IO uint8_t    Reserved12;
            __IO uint8_t    ERASED_MEM_CONT;
            __IO uint8_t    Reserved11;
            __IO uint8_t    BUS_WIDTH;
            __IO uint8_t    STROBE_SUPPORT;
            __IO uint8_t    HS_TIMING;
            __IO uint8_t    Reserved10;
            __IO uint8_t    POWER_CLASS;
            __IO uint8_t    Reserved9;
            __IO uint8_t    CMD_SET_REV;
            __IO uint8_t    Reserved8;
            __IO uint8_t    CMD_SET;
            __IO uint8_t    EXT_CSD_REV ;
            __IO uint8_t    Reserved7;
            __IO uint8_t    CSD_STRUCTURE;
            __IO uint8_t    Reserved6;
            __IO uint8_t    DEVICE_TYPE;
            __IO uint8_t    DRIVER_STRENGTH;
            __IO uint8_t    OUT_OF_INTERRUPT_TIME;
            __IO uint8_t    PARTITION_SWITCH_TIME;
            __IO uint8_t    PWR_CL_52_195;
            __IO uint8_t    PWR_CL_26_195;
            __IO uint8_t    PWR_CL_52_360;
            __IO uint8_t    PWR_CL_26_360;
            __IO uint8_t    Reserved5;
            __IO uint8_t    MIN_PERF_R_4_26;
            __IO uint8_t    MIN_PERF_W_4_26;
            __IO uint8_t    MIN_PERF_R_8_26_4_52;
            __IO uint8_t    MIN_PERF_W_8_26_4_52;
            __IO uint8_t    MIN_PERF_R_8_52;
            __IO uint8_t    MIN_PERF_W_8_52;
            __IO uint8_t    SECURE_WP_INFO;
            __IO uint8_t    SEC_COUNT[4];
            __IO uint8_t    SLEEP_NOTIFICATION_TIME;
            __IO uint8_t    S_A_TIMEOUT;
            __IO uint8_t    PRODUCTION_STATE_AWARENESS_TIMEOUT;
            __IO uint8_t    S_C_VCCQ;
            __IO uint8_t    S_C_VCC;
            __IO uint8_t    HC_WP_GRP_SIZE;
            __IO uint8_t    REL_WR_SEC_C;
            __IO uint8_t    ERASE_TIMEOUT_MULT;
            __IO uint8_t    HC_ERASE_GRP_SIZE;
            __IO uint8_t    ACC_SIZE;
            __IO uint8_t    BOOT_SIZE_MULTI;
            __IO uint8_t    Reserved4;
            __IO uint8_t    BOOT_INFO;
            __IO uint8_t    SEC_TRIM_MULT;
            __IO uint8_t    SEC_ERASE_MULT;
            __IO uint8_t    SEC_FEATURE_SUPPORT;
            __IO uint8_t    TRIM_MULT;
            __IO uint8_t    Reserved3;
            __IO uint8_t    MIN_PERF_DDR_R_8_52;
            __IO uint8_t    MIN_PERF_DDR_W_8_52;
            __IO uint8_t    PWR_CL_200_130;
            __IO uint8_t    PWR_CL_200_195;
            __IO uint8_t    PWR_CL_DDR_52_195;
            __IO uint8_t    PWR_CL_DDR_52_360;
            __IO uint8_t    CACHE_FLUSH_POLICY;
            __IO uint8_t    INI_TIMEOUT_AP;
            __IO uint8_t    CORRECTLY_PRG_SECTORS_NUM[4];
            __IO uint8_t    BKOPS_STATUS;
            __IO uint8_t    OWER_OFF_LONG_TIME;
            __IO uint8_t    GENERIC_CMD6_TIME;
            __IO uint8_t    CACHE_SIZE[4];
            __IO uint8_t    PWR_CL_DDR_200_360;
            __IO uint8_t    FIRMWARE_VERSION[8];
            __IO uint8_t    DEVICE_VERSION[2];
            __IO uint8_t    OPTIMAL_TRIM_UNIT_SIZE;
            __IO uint8_t    OPTIMAL_WRITE_SIZE;
            __IO uint8_t    OPTIMAL_READ_SIZE;
            __IO uint8_t    PRE_EOL_INFO;
            __IO uint8_t    DEVICE_LIFE_TIME_EST_TYP_A;
            __IO uint8_t    DEVICE_LIFE_TIME_EST_TYP_B;
            __IO uint8_t    VENDOR_PROPRIETARY_HEALTH_REPORT[32];
            __IO uint8_t    NUMBER_OF_FW_SECTORS_CORRECTLY_PROGRAMMED[4];
            __IO uint8_t    ReservedX;
            __IO uint8_t    CMDQ_DEPTH;
            __IO uint8_t    CMDQ_SUPPORT;
            __IO uint8_t    Reserved2[177];
            __IO uint8_t    BARRIER_SUPPORT;
            __IO uint8_t    FFU_ARG[4];
            __IO uint8_t    OPERATION_CODE_TIMEOUT;
            __IO uint8_t    FFU_FEATURES;
            __IO uint8_t    SUPPORTED_MODES;
            __IO uint8_t    EXT_SUPPORT;
            __IO uint8_t    LARGE_UNIT_SIZE_M1;
            __IO uint8_t    CONTEXT_CAPABILITIES;
            __IO uint8_t    TAG_RES_SIZE;
            __IO uint8_t    TAG_UNIT_SIZE;
            __IO uint8_t    DATA_TAG_SUPPORT;
            __IO uint8_t    MAX_PACKED_WRITES;
            __IO uint8_t    MAX_PACKED_READS;
            __IO uint8_t    BKOPS_SUPPORT;
            __IO uint8_t    HPI_FEATURES;
            __IO uint8_t    S_CMD_SET;
            __IO uint8_t    EXT_SECURITY_ERR;
            __IO uint8_t    Reserved1[6];
        } EXT_CSD;
   __IO uint8_t CsdBuf[512];
} EMMC_EXT_CSD;

typedef struct

{

uint32_t CardCap; /*-----------*/

uint32_t CardType; /*!< Specifies the card Type */

uint32_t Class; /*!< Specifies the class of the card class */

uint32_t RelCardAdd; /*!< Specifies the Relative Card Address */

uint32_t BlockNbr; /*!< Specifies the Card Capacity in blocks */

uint32_t BlockSize; /*!< Specifies one block size in bytes */

uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */

uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */

EMMC_EXT_CSD EmmcExtCsd;

}HAL_MMC_CardInfoTypeDef;

 

static HAL_StatusTypeDef MMC_Read_ExtCsd(MMC_HandleTypeDef *hmmc)

{

 uint32_t errorstate = HAL_MMC_ERROR_NONE;

SDIO_CmdInitTypeDef sdmmc_cmdinit;

 SDIO_DataInitTypeDef config;

 uint32_t count = 0;

 uint32_t cnt2;

uint32_t *ExtCsdBuf;

ExtCsdBuf = (uint32_t *)(&(hmmc-> MmcCard.EmmcExtCsd.CsdBuf[0]));

config.DataTimeOut = SDMMC_DATATIMEOUT;

config.DataLength = (uint32_t)512;

config.DataBlockSize = (uint32_t) 9 << 4;

config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;

config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;

config.DPSM = SDIO_DPSM_ENABLE;

SDIO_ConfigData(hmmc->Instance, &config);


/* Send CMD8 to verify SD card interface operating condition */

/* Argument: - [31:12]: Reserved (shall be set to '0')

- [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)

- [7:0]: Check Pattern (recommended 0xAA) */

/* CMD Response: R7 */

sdmmc_cmdinit.Argument = 0;

sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD;

sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;

sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;

sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;

SDIO_SendCommand(hmmc->Instance, &sdmmc_cmdinit);

/* Check for error conditions */

errorstate = SDMMC_GetCmdResp1(hmmc->Instance, SDMMC_CMD_HS_SEND_EXT_CSD, 0xffff);

while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_STA_STBITERR))

{

if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))

  {

    for (count = 0; count < 8; count++)

    {

      *(ExtCsdBuf + count) = SDIO_ReadFIFO(hmmc->Instance);

    }

    ExtCsdBuf += 8;

  }

}

/* Get error state */

if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))

{

/* Clear all the static flags */

__HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);

hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;

hmmc->State = HAL_MMC_STATE_READY;

return HAL_ERROR;

}

else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))

{

/* Clear all the static flags */

__HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);

hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;

hmmc->State = HAL_MMC_STATE_READY;

return HAL_ERROR;

}

else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))

{

/* Clear all the static flags */

__HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);

hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;

hmmc->State = HAL_MMC_STATE_READY;

return HAL_ERROR;

}

count = 100;

/* Empty FIFO if there is still any data */

while ((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXDAVL)) && (count >0))

{

SDIO_ReadFIFO(hmmc->Instance);

count --;

}

/* Clear all the static flags */

__HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);

hmmc->State = HAL_MMC_STATE_READY;

return HAL_OK;

}

/*off:ext_csd寄存器偏移地址,可利用宏 #define EXT_CSD_OFFSET(member) (size_t)&( ((EMMC_EXT_CSD*)0)->EXT_CSD.member )计算

val: 写入值*/

static HAL_StatusTypeDef MMC_Write_ExtCsd(MMC_HandleTypeDef *hmmc, uint8_t off, uint8_t val)
{

    uint32_t errorstate = HAL_ERROR;

    if(off>191) return errorstate;

    uint32_t arg = (0x03 << 24) | ((off)<<16) | ((val) << 8) ;

    errorstate = SDMMC_CmdSwitch(hmmc->Instance,arg);

    return errorstate;

}

你可能感兴趣的:(嵌入式系统)