junpeng324 发表于 2021-1-28 20:13

F407 初始化SD卡

SD_Error SD_Init(void)
{
GPIO_InitTypeGPIO_InitStructure = {0};
GPIO_StructInit(&GPIO_InitStructure);

u16 clkdiv = 0;
SD_Error errorstatus = SD_OK;

/*!< GPIOC and GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOC | RCC_APB2PERIPH_GPIOD, ENABLE);

/*!< SDIO clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_SDIO1, ENABLE);

/*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8 | GPIO_Pins_9 | GPIO_Pins_10 | GPIO_Pins_11 | GPIO_Pins_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);

/*!< Configure PD.02 CMD line */
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);

/* Reset SDIO */
SDIO_Reset(SDIO1);

errorstatus = SD_PowerON();   //上电

if(errorstatus == SD_OK)
{
    errorstatus = SD_InitializeCards();//初始化SD卡
}

if(errorstatus == SD_OK)
{
    errorstatus = SD_GetCardInfo(&SDCardInfo);//获取SD卡信息
}

if(SDIO_MULTIMEDIA_CARD == CardType && SDCardInfo.SD_csd.SysSpecVersion >= 4)
{
    CardType = SDIO_HIGH_SPEED_MULTIMEDIA_CARD;
}

if(errorstatus == SD_OK)
{
    errorstatus = SD_SelectDeselect((u32)(SDCardInfo.RCA << 16));//选中SD卡
}

if(errorstatus == SD_OK && ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_SECURE_DIGITAL_IO_COMBO_CARD == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType)))
{
    errorstatus = FindSCR();
}

if(errorstatus == SD_OK)
{
    errorstatus = ChangeSpeed(0);//Set to Normal Speed
}

if((errorstatus == SD_OK) || (SDIO_MULTIMEDIA_CARD == CardType))
{
    if(SDCardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1 || SDCardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0)
    {
      clkdiv = SystemCoreClock / 6000000; //设置SD卡时钟为6MHz

      if (clkdiv > 2)
      {
      clkdiv -= 2;
      }
    }
    else
    {
      clkdiv = SystemCoreClock / 6000000; //设置SD卡时钟为6MHz

      if (clkdiv > 2)
      {
      clkdiv -= 2;
      }
    }

    SDIO_Clock_Set(clkdiv); //设置SDIO Clock分频系数
    errorstatus = SD_SetDeviceMode(SD_POLLING_MODE); //设置为轮询模式
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:24

void SDIO_Clock_Set(u32 clkdiv)
{
u32 tmpreg = SDIO1->CLKCTRL;
tmpreg &= 0XFFFE7F00;
tmpreg |= (clkdiv & 0X000000FF);
tmpreg |= ((clkdiv & 0X00000300) << 7);
SDIO1->CLKCTRL = tmpreg;
}

junpeng324 发表于 2021-1-28 20:24

SD_Error SD_PowerON(void)
{
u8 i = 0;
SD_Error errorstatus = SD_OK;
u32 response = 0, count = 0, validvoltage = 0, clk_div;
u32 SDType = SD_STD_CAPACITY;

/*初始化时的时钟不能大于400KHz*/
clk_div = SystemCoreClock / 200000 - 2; //初始化时钟200KHz

if (clk_div > 0x3FF) //9 bits
{
    clk_div = 0X3FF;
}

SDIO_InitStructure.SDIO_ClkPsc = clk_div;
SDIO_InitStructure.SDIO_ClkEdge = SDIO_ClkEdge_Falling; //上升沿
SDIO_InitStructure.SDIO_ClkBypass = SDIO_ClkBypass_Disable;//关闭时钟旁路
SDIO_InitStructure.SDIO_ClkPowerSave = SDIO_ClkPowerSave_Disable; //空闲时输出时钟
SDIO_InitStructure.SDIO_BusWidth = SDIO_BusWidth_1b; //1-bit数据宽度
SDIO_InitStructure.SDIO_FlowCtrl = SDIO_FlowCtrl_Disable; //关闭硬件流控
SDIO_Init(SDIO1, &SDIO_InitStructure);

SDIO_SetPowerSaveState(SDIO1, SDIO_PowerSave_ON); //上电状态,开启卡时钟

SDIO_ClockCmd(SDIO1, ENABLE); //SDIOCK使能

for(i = 0; i < 10; i++)
{
    SDIO_CmdInitStructure.SDIO_Argu = 0x0; //发送CMD0进入IDLE STAGE模式命令.
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_GO_IDLE_STATE; //CMD0
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_No; //无响应
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; //则CPSM在开始发送命令之前等待数据传输结束。
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure); //写命令进命令寄存器

    errorstatus = CmdError();

    if(errorstatus == SD_OK)
    {
      break;
    }
}

if(errorstatus)
{
    return errorstatus;//返回错误状态
}

SDIO_CmdInitStructure.SDIO_Argu = SD_CHECK_PATTERN;   //发送CMD8,短响应,检查SD卡接口特性
SDIO_CmdInitStructure.SDIO_CmdIdx = SDIO_SEND_IF_COND;    //CMD8
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;//R7
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;   //关闭等待中断
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

errorstatus = CmdResp7Error(); //等待R7响应

if(errorstatus == SD_OK) //R7响应正常
{
    CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; //SD 2.0卡
    SDType = SD_HIGH_CAPACITY; //高容量卡
}

SDIO_CmdInitStructure.SDIO_Argu = 0x00; //发送CMD55,短响应
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_APP_CMD;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);   //发送CMD55,短响应

errorstatus = CmdResp1Error(SD_CMD_APP_CMD); //等待R1响应

if(errorstatus == SD_OK) //SD2.0/SD 1.1,否则为MMC卡
{
    /* SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000 */
    while((!validvoltage) && (count < SD_MAX_VOLT_TRIAL))
    {
      SDIO_CmdInitStructure.SDIO_Argu = 0x00; //发送CMD55,短响应
      SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_APP_CMD;   //CMD55
      SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);   //发送CMD55,短响应

      errorstatus = CmdResp1Error(SD_CMD_APP_CMD); //等待R1响应

      if(errorstatus != SD_OK) //响应错误
      {
      return errorstatus;
      }

      /* acmd41,命令参数由支持的电压范围及HCS位组成,HCS位置一来区分卡是SDSc还是sdhc */
      SDIO_CmdInitStructure.SDIO_Argu = SD_VOLTAGE_WINDOW_SD | SDType; //发送ACMD41,短响应
      SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SD_APP_OP_COND;
      SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;//r3
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

      errorstatus = CmdResp3Error(); //等待R3响应

      if(errorstatus != SD_OK) //响应错误
      {
      return errorstatus;
      }

      response = SDIO1->RSP1; //得到响应
      validvoltage = (((response >> 31) == 1) ? 1 : 0); //判断SD卡上电是否完成
      count++;
    }

    if(count >= SD_MAX_VOLT_TRIAL)
    {
      errorstatus = SD_INVALID_VOLTRANGE;
      return errorstatus;
    }

    if(response &= SD_HIGH_CAPACITY)
    {
      CardType = SDIO_HIGH_CAPACITY_SD_CARD;
    }
}
else //MMC卡
{
    /* MMC卡,发送CMD1 SDIO_SEND_OP_COND,参数为:0x80FF8000 */
    while((!validvoltage) && (count < SD_MAX_VOLT_TRIAL))
    {
      SDIO_CmdInitStructure.SDIO_Argu = SD_VOLTAGE_WINDOW_MMC; //发送CMD1,短响应
      SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SEND_OP_COND;
      SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short; //r3
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

      errorstatus = CmdResp3Error(); //等待R3响应

      if(errorstatus != SD_OK) //响应错误
      {
      return errorstatus;
      }

      response = SDIO1->RSP1; //得到响应
      validvoltage = (((response >> 31) == 1) ? 1 : 0);
      count++;
    }

    if(count >= SD_MAX_VOLT_TRIAL)
    {
      errorstatus = SD_INVALID_VOLTRANGE;
      return errorstatus;
    }

    CardType = SDIO_MULTIMEDIA_CARD;
}

return(errorstatus);
}

junpeng324 发表于 2021-1-28 20:25

SD_Error SD_PowerOFF(void)
{
SDIO_SetPowerSaveState(SDIO1, SDIO_PowerSave_OFF); //SDIO电源关闭,时钟停止
return SD_OK;
}

junpeng324 发表于 2021-1-28 20:26

SD_Error SD_InitializeCards(void)
{
SD_Error errorstatus = SD_OK;
u16 rca = 0x01;

if(SDIO_GetPowerSaveState(SDIO1) == 0) //检查电源状态,确保为上电状态
{
    return SD_REQ_NOT_APPLICABLE;
}

if(SDIO_SECURE_DIGITAL_IO_CARD != CardType)   //非SECURE_DIGITAL_IO_CARD
{
    SDIO_CmdInitStructure.SDIO_Argu = 0x0; //发送CMD2,取得CID,长响应
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_ALL_SEND_CID;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Long;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure); //发送CMD2,取得CID,长响应

    errorstatus = CmdResp2Error(); //等待R2响应
    CID_Tab = SDIO1->RSP1;
    CID_Tab = SDIO1->RSP2;
    CID_Tab = SDIO1->RSP3;
    CID_Tab = SDIO1->RSP4;
}

if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || \
      (SDIO_SECURE_DIGITAL_IO_COMBO_CARD == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))          //判断卡类型
{
    SDIO_CmdInitStructure.SDIO_Argu = 0x00; //发送CMD3,短响应
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SET_REL_ADDR; //CMD3
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short; //r6
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure); //发送CMD3,短响应

    errorstatus = CmdResp6Error(SD_CMD_SET_REL_ADDR, &rca); //等待R6响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }
}

if (SDIO_MULTIMEDIA_CARD == CardType)
{
    SDIO_CmdInitStructure.SDIO_Argu = (u32)(rca << 16); //发送CMD3,短响应
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SET_REL_ADDR;//CMD3
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short; //r6
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure); //发送CMD3,短响应

    errorstatus = CmdResp2Error(); //等待R2响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }
}

if (SDIO_SECURE_DIGITAL_IO_CARD != CardType) //非SECURE_DIGITAL_IO_CARD
{
    RCA = rca;
    SDIO_CmdInitStructure.SDIO_Argu = (uint32_t)(rca << 16); //发送CMD9+卡RCA,取得CSD,长响应
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SEND_CSD;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Long;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp2Error(); //等待R2响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }

    CSD_Tab = SDIO1->RSP1;
    CSD_Tab = SDIO1->RSP2;
    CSD_Tab = SDIO1->RSP3;
    CSD_Tab = SDIO1->RSP4;
}

return SD_OK;//卡初始化成功
}

junpeng324 发表于 2021-1-28 20:27

SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
{
SD_Error errorstatus = SD_OK;
uint8_t tmp = 0;

cardinfo->CardType = (uint8_t)CardType;
cardinfo->RCA = (uint16_t)RCA;

/*!< Byte 0 */
tmp = (uint8_t)((CSD_Tab & 0xFF000000) >> 24);
cardinfo->SD_csd.CSDStruct = (tmp & 0xC0) >> 6;
cardinfo->SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2;
cardinfo->SD_csd.Reserved1 = tmp & 0x03;

/*!< Byte 1 */
tmp = (uint8_t)((CSD_Tab & 0x00FF0000) >> 16);
cardinfo->SD_csd.TAAC = tmp;

/*!< Byte 2 */
tmp = (uint8_t)((CSD_Tab & 0x0000FF00) >> 8);
cardinfo->SD_csd.NSAC = tmp;

/*!< Byte 3 */
tmp = (uint8_t)(CSD_Tab & 0x000000FF);
cardinfo->SD_csd.MaxBusClkFrec = tmp;

/*!< Byte 4 */
tmp = (uint8_t)((CSD_Tab & 0xFF000000) >> 24);
cardinfo->SD_csd.CardComdClasses = tmp << 4;

/*!< Byte 5 */
tmp = (uint8_t)((CSD_Tab & 0x00FF0000) >> 16);
cardinfo->SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4;
cardinfo->SD_csd.RdBlockLen = tmp & 0x0F;

/*!< Byte 6 */
tmp = (uint8_t)((CSD_Tab & 0x0000FF00) >> 8);
cardinfo->SD_csd.PartBlockRead = (tmp & 0x80) >> 7;
cardinfo->SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6;
cardinfo->SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5;
cardinfo->SD_csd.DSRImpl = (tmp & 0x10) >> 4;
cardinfo->SD_csd.Reserved2 = 0; /*!< Reserved */

if ((CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) || (CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0))
{
    cardinfo->SD_csd.DeviceSize = (tmp & 0x03) << 10;

    /*!< Byte 7 */
    tmp = (uint8_t)(CSD_Tab & 0x000000FF);
    cardinfo->SD_csd.DeviceSize |= (tmp) << 2;

    /*!< Byte 8 */
    tmp = (uint8_t)((CSD_Tab & 0xFF000000) >> 24);
    cardinfo->SD_csd.DeviceSize |= (tmp & 0xC0) >> 6;

    cardinfo->SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3;
    cardinfo->SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07);

    /*!< Byte 9 */
    tmp = (uint8_t)((CSD_Tab & 0x00FF0000) >> 16);
    cardinfo->SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
    cardinfo->SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
    cardinfo->SD_csd.DeviceSizeMul = (tmp & 0x03) << 1;
    /*!< Byte 10 */
    tmp = (uint8_t)((CSD_Tab & 0x0000FF00) >> 8);
    cardinfo->SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7;

    cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) ;
    cardinfo->CardCapacity *= (1 << (cardinfo->SD_csd.DeviceSizeMul + 2));
    cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen);
    cardinfo->CardCapacity *= cardinfo->CardBlockSize;
}
else if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
{
    /*!< Byte 7 */
    tmp = (uint8_t)(CSD_Tab & 0x000000FF);
    cardinfo->SD_csd.DeviceSize = (tmp & 0x3F) << 16;

    /*!< Byte 8 */
    tmp = (uint8_t)((CSD_Tab & 0xFF000000) >> 24);

    cardinfo->SD_csd.DeviceSize |= (tmp << 8);

    /*!< Byte 9 */
    tmp = (uint8_t)((CSD_Tab & 0x00FF0000) >> 16);

    cardinfo->SD_csd.DeviceSize |= (tmp);

    /*!< Byte 10 */
    tmp = (uint8_t)((CSD_Tab & 0x0000FF00) >> 8);

    cardinfo->CardCapacity = (uint64_t)(cardinfo->SD_csd.DeviceSize + 1) * 512 * 1024;
    cardinfo->CardBlockSize = 512;
}


cardinfo->SD_csd.EraseGrSize = (tmp & 0x40) >> 6;
cardinfo->SD_csd.EraseGrMul = (tmp & 0x3F) << 1;

/*!< Byte 11 */
tmp = (uint8_t)(CSD_Tab & 0x000000FF);
cardinfo->SD_csd.EraseGrMul |= (tmp & 0x80) >> 7;
cardinfo->SD_csd.WrProtectGrSize = (tmp & 0x7F);

/*!< Byte 12 */
tmp = (uint8_t)((CSD_Tab & 0xFF000000) >> 24);
cardinfo->SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7;
cardinfo->SD_csd.ManDeflECC = (tmp & 0x60) >> 5;
cardinfo->SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2;
cardinfo->SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2;

/*!< Byte 13 */
tmp = (uint8_t)((CSD_Tab & 0x00FF0000) >> 16);
cardinfo->SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6;
cardinfo->SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5;
cardinfo->SD_csd.Reserved3 = 0;
cardinfo->SD_csd.ContentProtectAppli = (tmp & 0x01);

/*!< Byte 14 */
tmp = (uint8_t)((CSD_Tab & 0x0000FF00) >> 8);
cardinfo->SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7;
cardinfo->SD_csd.CopyFlag = (tmp & 0x40) >> 6;
cardinfo->SD_csd.PermWrProtect = (tmp & 0x20) >> 5;
cardinfo->SD_csd.TempWrProtect = (tmp & 0x10) >> 4;
cardinfo->SD_csd.FileFormat = (tmp & 0x0C) >> 2;
cardinfo->SD_csd.ECC = (tmp & 0x03);

/*!< Byte 15 */
tmp = (uint8_t)(CSD_Tab & 0x000000FF);
cardinfo->SD_csd.CSD_CRC = (tmp & 0xFE) >> 1;
cardinfo->SD_csd.Reserved4 = 1;


/*!< Byte 0 */
tmp = (uint8_t)((CID_Tab & 0xFF000000) >> 24);
cardinfo->SD_cid.ManufacturerID = tmp;

/*!< Byte 1 */
tmp = (uint8_t)((CID_Tab & 0x00FF0000) >> 16);
cardinfo->SD_cid.OEM_AppliID = tmp << 8;

/*!< Byte 2 */
tmp = (uint8_t)((CID_Tab & 0x000000FF00) >> 8);
cardinfo->SD_cid.OEM_AppliID |= tmp;

/*!< Byte 3 */
tmp = (uint8_t)(CID_Tab & 0x000000FF);
cardinfo->SD_cid.ProdName1 = tmp << 24;

/*!< Byte 4 */
tmp = (uint8_t)((CID_Tab & 0xFF000000) >> 24);
cardinfo->SD_cid.ProdName1 |= tmp << 16;

/*!< Byte 5 */
tmp = (uint8_t)((CID_Tab & 0x00FF0000) >> 16);
cardinfo->SD_cid.ProdName1 |= tmp << 8;

/*!< Byte 6 */
tmp = (uint8_t)((CID_Tab & 0x0000FF00) >> 8);
cardinfo->SD_cid.ProdName1 |= tmp;

/*!< Byte 7 */
tmp = (uint8_t)(CID_Tab & 0x000000FF);
cardinfo->SD_cid.ProdName2 = tmp;

/*!< Byte 8 */
tmp = (uint8_t)((CID_Tab & 0xFF000000) >> 24);
cardinfo->SD_cid.ProdRev = tmp;

/*!< Byte 9 */
tmp = (uint8_t)((CID_Tab & 0x00FF0000) >> 16);
cardinfo->SD_cid.ProdSN = tmp << 24;

/*!< Byte 10 */
tmp = (uint8_t)((CID_Tab & 0x0000FF00) >> 8);
cardinfo->SD_cid.ProdSN |= tmp << 16;

/*!< Byte 11 */
tmp = (uint8_t)(CID_Tab & 0x000000FF);
cardinfo->SD_cid.ProdSN |= tmp << 8;

/*!< Byte 12 */
tmp = (uint8_t)((CID_Tab & 0xFF000000) >> 24);
cardinfo->SD_cid.ProdSN |= tmp;

/*!< Byte 13 */
tmp = (uint8_t)((CID_Tab & 0x00FF0000) >> 16);
cardinfo->SD_cid.Reserved1 |= (tmp & 0xF0) >> 4;
cardinfo->SD_cid.ManufactDate = (tmp & 0x0F) << 8;

/*!< Byte 14 */
tmp = (uint8_t)((CID_Tab & 0x0000FF00) >> 8);
cardinfo->SD_cid.ManufactDate |= tmp;

/*!< Byte 15 */
tmp = (uint8_t)(CID_Tab & 0x000000FF);
cardinfo->SD_cid.CID_CRC = (tmp & 0xFE) >> 1;
cardinfo->SD_cid.Reserved2 = 1;

return(errorstatus);
}

junpeng324 发表于 2021-1-28 20:28

SD_Error SD_EnableWideBusOperation(u32 wmode)
{
SD_Error errorstatus = SD_OK;

if((SDIO_MULTIMEDIA_CARD == CardType) || (SDIO_HIGH_SPEED_MULTIMEDIA_CARD == CardType))
{
    errorstatus = MMC_Switch(EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, (u8)wmode);
}
else if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))
{
    if(wmode >= 2)
    {
      return SD_UNSUPPORTED_FEATURE;//不支持8位模式
    }

    errorstatus = SDEnWideBus(wmode);
}

if(SD_OK == errorstatus)
{
    SDIO1->CLKCTRL &= ~(3 << 11);    //清除之前的位宽设置
    SDIO1->CLKCTRL |= (u16)wmode << 11; //设置总线宽度
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:29

SD_Error SD_SetDeviceMode(u32 Mode)
{
SD_Error errorstatus = SD_OK;

if((Mode == SD_DMA_MODE) || (Mode == SD_POLLING_MODE))
{
    DeviceMode = Mode;
}
else
{
    errorstatus = SD_INVALID_PARAMETER;
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:30

SD_Error SD_SelectDeselect(u32 addr)
{
SDIO_CmdInitStructure.SDIO_Argu =addr; //发送CMD7,选择卡,短响应
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SEL_DESEL_CARD;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_INT;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure); //发送CMD7,选择卡,短响应

return CmdResp1Error(SD_CMD_SEL_DESEL_CARD);
}

junpeng324 发表于 2021-1-28 20:31

SD_Error SDIO_SendDataCommand(SDIO_CmdInitType *SDIO_CmdInitStruct, SDIO_DataInitType* SDIO_DataInitStruct, u32 *buf)
{
SD_Error errorstatus = SD_OK;
u32 count;
u32 timeout = SDIO_DATATIMEOUT;
int tlen;

if(NULL == buf)
{
    return SD_INVALID_PARAMETER;
}

SDIO1->DTCTRL = 0x0; //数据控制寄存器清零(关DMA)
SDIO_DataConfig(SDIO1, SDIO_DataInitStruct);
SDIO_SendCommand(SDIO1, SDIO_CmdInitStruct); //发送CMD17+从addr地址出读取数据,短响应
errorstatus = CmdResp1Error(SDIO_CmdInitStruct->SDIO_CmdIdx); //等待R1响应

if(errorstatus != SD_OK) //响应错误
{
    return errorstatus;
}

tlen = SDIO_DataInitStruct->SDIO_DataLen;

if(DeviceMode == SD_POLLING_MODE) /* 轮询模式 */
{
    if (SDIO_DataInitStruct->SDIO_TransferDir == SDIO_TransferDir_ToSDIO)
    {
      while(!(SDIO1->STS & (SDIO_INTR_STS_READ_MASK)))
      {
      if(SDIO_GetFlagStatus(SDIO1, SDIO_**_RXBUF_H) != RESET)
      {
          for(count = 0; count < 8; count++, buf++)
          {
            *buf = SDIO1->BUF;
          }

          timeout = 0X7FFFFF;
      }
      else
      {
          if(timeout == 0) //超时
          {
            SD_Init();
            return SD_DATA_TIMEOUT;
          }

          timeout--;
      }
      }

      while(SDIO_GetFlagStatus(SDIO1, SDIO_**_RXBUF) != RESET)
      {
      *buf = SDIO1->BUF;
      buf++;
      }
    }
    else
    {
      while(!(SDIO1->STS & SDIO_INTR_STS_WRITE_MASK))
      {
      if(SDIO_GetFlagStatus(SDIO1, SDIO_**_TXBUF_H) != RESET)
      {
          for(count = 0; count < 8 && tlen > 0; count++, buf++, tlen -= 4)
          {
            SDIO1->BUF = *buf;
          }

          timeout = 0X3FFFFFFF;
      }
      else
      {
          if(timeout == 0) //超时
          {
            SD_Init();
            return SD_DATA_TIMEOUT;
          }

          timeout--;
      }
      }
    }

    if(SDIO_GetFlagStatus(SDIO1, SDIO_**_DTTIMEOUT) != RESET)   //数据超时
    {
      SDIO_ClearFlag(SDIO1, SDIO_**_DTTIMEOUT);
      return SD_DATA_TIMEOUT;
    }
    else if(SDIO_GetFlagStatus(SDIO1, SDIO_**_DTFAIL) != RESET) //CRC错误
    {
      SDIO_ClearFlag(SDIO1, SDIO_**_DTFAIL);
      return SD_DATA_FAIL;
    }
    else if(SDIO_GetFlagStatus(SDIO1, SDIO_**_RXERRO) != RESET) //上溢错误
    {
      SDIO_ClearFlag(SDIO1, SDIO_**_RXERRO);
      return SD_RX_OVERRUN;
    }
    else if(SDIO_GetFlagStatus(SDIO1, SDIO_**_TXERRU) != RESET) //下溢错误
    {
      SDIO_ClearFlag(SDIO1, SDIO_**_TXERRU);
      return SD_TX_UNDERRUN;
    }
    else if(SDIO_GetFlagStatus(SDIO1, SDIO_**_SBITERR) != RESET) //起始位错误
    {
      SDIO_ClearFlag(SDIO1, SDIO_**_SBITERR);
      return SD_START_BIT_ERR;
    }

    if(StopCondition == 1 && SDIO_GetFlagStatus(SDIO1, SDIO_**_DTCMPL) != RESET) //接收结束
    {
      SDIO_CmdInitStruct->SDIO_Argu =0; //发送CMD12+结束传输
      SDIO_CmdInitStruct->SDIO_CmdIdx = SD_CMD_STOP_TRANSMISSION;
      SDIO_CmdInitStruct->SDIO_Resp = SDIO_Rsp_Short;
      SDIO_CmdInitStruct->SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStruct->SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(SDIO1, SDIO_CmdInitStruct);

      errorstatus = CmdResp1Error(SD_CMD_STOP_TRANSMISSION); //等待R1响应

      if(errorstatus != SD_OK)
      {
      return errorstatus;
      }
    }

    SDIO_ClearFlag(SDIO1, SDIO_STATIC_FLAGS); //清除所有标记
}
else if(DeviceMode == SD_DMA_MODE) /* DMA模式 */
{
    if (SDIO_DataInitStruct->SDIO_TransferDir == SDIO_TransferDir_ToSDIO)
    {
      SD_DMA_Config(buf, tlen, DMA_DIR_PERIPHERALSRC);
      SDIO1->INTEN |= SDIO_INTR_STS_READ_MASK;

    }
    else
    {
      SD_DMA_Config(buf, tlen, DMA_DIR_PERIPHERALDST);
      SDIO1->INTEN |= SDIO_INTR_STS_WRITE_MASK;
    }

    TransferError = SD_OK;
    TransferEnd = 0; //传输结束标置位,在中断服务置1
    SDIO1->DTCTRL |= 1 << 3;

    while(!(SDIO1->STS & SDIO1->INTEN) && timeout)
    {
      timeout--;

      if (TransferEnd)
      {
      break;
      }
    }

    if(timeout == 0)
    {
      SD_Init();
      return SD_DATA_TIMEOUT;
    }

    if(TransferError != SD_OK)
    {
      errorstatus = TransferError;
    }
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:32

SD_Error SD_EraseBlocks(long long addr, u32 nblks)
{
SD_Error errorstatus = SD_OK;
u32 start_addr, end_addr;
u8 cardstate;

if(CardType == SDIO_HIGH_CAPACITY_SD_CARD) //大容量卡
{
    start_addr = addr >> 9;
    end_addr = start_addr + nblks - 1;
}
else
{
    start_addr = addr;
    end_addr = start_addr + (nblks - 1) * 512;
}

SDIO_DataInitStructure.SDIO_DataBlkSize = SDIO_DataBlkSize_1b; //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = 0 ;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT ;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataConfig(SDIO1, &SDIO_DataInitStructure);

if(SDIO1->RSP1 & SD_CARD_LOCKED) //卡锁了
{
    return SD_LOCK_UNLOCK_FAILED;
}

if(CardType == SDIO_MULTIMEDIA_CARD || CardType == SDIO_HIGH_SPEED_MULTIMEDIA_CARD)
{
    SDIO_CmdInitStructure.SDIO_Argu =start_addr;
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_ERASE_GRP_START; //CMD35
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_ERASE_GRP_START); //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }

    SDIO_CmdInitStructure.SDIO_Argu =end_addr;
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_ERASE_GRP_END;//CMD36
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_ERASE_GRP_END); //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }

    SDIO_CmdInitStructure.SDIO_Argu =0;
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_ERASE;//CMD38
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_ERASE); //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }
}
else
{
    SDIO_CmdInitStructure.SDIO_Argu =start_addr;
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SD_ERASE_GRP_START; //CMD32
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_START); //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }

    SDIO_CmdInitStructure.SDIO_Argu =end_addr;
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SD_ERASE_GRP_END; //CMD33
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_END);   //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }

    SDIO_CmdInitStructure.SDIO_Argu =0;
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_ERASE; //CMD38
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_ERASE); //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }
}

errorstatus = IsCardProgramming(&cardstate);

while((errorstatus == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING)))
{
    errorstatus = IsCardProgramming(&cardstate);
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:33

SD_Error SD_ReadBlock(u8 *readbuff, long long ReadAddr, u16 BlockSize)
{
SD_Error errorstatus = SD_OK;
u8 power;

if(NULL == readbuff)
{
    return SD_INVALID_PARAMETER;
}

SDIO1->DTCTRL = 0x0; //数据控制寄存器清零(关DMA)

if(CardType == SDIO_HIGH_CAPACITY_SD_CARD) //大容量卡
{
    BlockSize = 512;
    ReadAddr >>= 9;
}

SDIO_DataInitStructure.SDIO_DataBlkSize = SDIO_DataBlkSize_1b; //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = 0;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataConfig(SDIO1, &SDIO_DataInitStructure);

if(SDIO1->RSP1 & SD_CARD_LOCKED) //卡锁了
{
    return SD_LOCK_UNLOCK_FAILED;
}

if((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0))
{
    power = convert_from_bytes_to_power_of_two(BlockSize);

    SDIO_CmdInitStructure.SDIO_Argu =BlockSize;
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SET_BLOCKLEN;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure); //发送CMD16+设置数据长度为blksize,短响应

    errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);   //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }
}
else
{
    return SD_INVALID_PARAMETER;
}

SDIO_DataInitStructure.SDIO_DataBlkSize = power << 4 ; //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = BlockSize ;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT ;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;

SDIO_CmdInitStructure.SDIO_Argu =ReadAddr;
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_READ_SINGLE_BLOCK;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

StopCondition = 0;
return SDIO_SendDataCommand(&SDIO_CmdInitStructure, &SDIO_DataInitStructure, (u32 *)readbuff);
}

junpeng324 发表于 2021-1-28 20:33

SD_Error SD_ReadMultiBlocks(u8 *readbuff, long long ReadAddr, u16 BlockSize, u32 NumberOfBlocks)
{
SD_Error errorstatus = SD_OK;
u8 power;

SDIO1->DTCTRL = 0x0; //数据控制寄存器清零(关DMA)

if(CardType == SDIO_HIGH_CAPACITY_SD_CARD) //大容量卡
{
    BlockSize = 512;
    ReadAddr >>= 9;
}

SDIO_DataInitStructure.SDIO_DataBlkSize = 0; //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = 0;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataConfig(SDIO1, &SDIO_DataInitStructure);

if(SDIO1->RSP1 & SD_CARD_LOCKED) //卡锁了
{
    return SD_LOCK_UNLOCK_FAILED;
}

if((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0))
{
    power = convert_from_bytes_to_power_of_two(BlockSize);

    SDIO_CmdInitStructure.SDIO_Argu =BlockSize; //发送CMD16+设置数据长度为blksize,短响应
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SET_BLOCKLEN;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);   //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }
}
else
{
    return SD_INVALID_PARAMETER;
}

if(NumberOfBlocks * BlockSize > SD_MAX_DATA_LENGTH) //判断是否超过最大接收长度
{
    return SD_INVALID_PARAMETER;
}

SDIO_DataInitStructure.SDIO_DataBlkSize = power << 4; //nblks*blksize,512块大小,卡到控制器
SDIO_DataInitStructure.SDIO_DataLen = NumberOfBlocks * BlockSize ;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT ;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;

SDIO_CmdInitStructure.SDIO_Argu =ReadAddr;//发送CMD18+从addr地址出读取数据,短响应
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_READ_MULT_BLOCK;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

StopCondition = 1;
return SDIO_SendDataCommand(&SDIO_CmdInitStructure, &SDIO_DataInitStructure, (u32 *)readbuff);
}

junpeng324 发表于 2021-1-28 20:38

SD_Error SD_WriteBlock(u8 *writebuff, long long WriteAddr, u16 BlockSize)
{
SD_Error errorstatus = SD_OK;
u8power = 0, cardstate = 0;
u32 timeout = 0;
u32 cardstatus = 0;

if(writebuff == NULL) //参数错误
{
    return SD_INVALID_PARAMETER;
}

SDIO1->DTCTRL = 0x0; //数据控制寄存器清零(关DMA)

SDIO_DataInitStructure.SDIO_DataBlkSize = 0; //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = 0;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataConfig(SDIO1, &SDIO_DataInitStructure);

if(SDIO1->RSP1 & SD_CARD_LOCKED) //卡锁了
{
    return SD_LOCK_UNLOCK_FAILED;
}

if(CardType == SDIO_HIGH_CAPACITY_SD_CARD) //大容量卡
{
    BlockSize = 512;
    WriteAddr >>= 9;
}

if((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0))
{
    power = convert_from_bytes_to_power_of_two(BlockSize);

    SDIO_CmdInitStructure.SDIO_Argu = BlockSize; //发送CMD16+设置数据长度为blksize,短响应
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SET_BLOCKLEN;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);   //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }

}
else
{
    return SD_INVALID_PARAMETER;
}

timeout = SD_DATATIMEOUT;

do
{
    timeout--;
    errorstatus = SD_SendStatus(&cardstatus);
}
while(((cardstatus & 0x00000100) == 0) && (timeout > 0)); //检查READY_FOR_DATA位是否置位

if(timeout == 0)
{
    return SD_ERROR;
}

SDIO_CmdInitStructure.SDIO_Argu = WriteAddr; //发送CMD24,写单块指令,短响应
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_WRITE_SINGLE_BLOCK;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_DataInitStructure.SDIO_DataBlkSize = power << 4; //blksize, 控制器到卡
SDIO_DataInitStructure.SDIO_DataLen = BlockSize;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;

StopCondition = 0; //单块写,不需要发送停止传输指令
errorstatus = SDIO_SendDataCommand(&SDIO_CmdInitStructure, &SDIO_DataInitStructure, (u32 *)writebuff);

if(errorstatus != SD_OK)
{
    return errorstatus;
}

SDIO_ClearFlag(SDIO1, SDIO_STATIC_FLAGS); //清除所有标记
errorstatus = IsCardProgramming(&cardstate);

while((errorstatus == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING)))
{
    errorstatus = IsCardProgramming(&cardstate);
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:38

SD_Error SD_WriteMultiBlocks(u8 *writebuff, long long WriteAddr, u16 BlockSize, u32 NumberOfBlocks)
{
SD_Error errorstatus = SD_OK;
u8power = 0, cardstate = 0;
u32 timeout = 0;
u32 cardstatus = 0;

if(writebuff == NULL)
{
    return SD_INVALID_PARAMETER;
}

SDIO1->DTCTRL = 0x0; //数据控制寄存器清零(关DMA)

SDIO_DataInitStructure.SDIO_DataBlkSize = 0; //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = 0;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataConfig(SDIO1, &SDIO_DataInitStructure);

if(SDIO1->RSP1 & SD_CARD_LOCKED) //卡锁了
{
    return SD_LOCK_UNLOCK_FAILED;
}

if(CardType == SDIO_HIGH_CAPACITY_SD_CARD) //大容量卡
{
    BlockSize = 512;
    WriteAddr >>= 9;
}

if((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0))
{
    power = convert_from_bytes_to_power_of_two(BlockSize);

    SDIO_CmdInitStructure.SDIO_Argu = BlockSize;//发送CMD16+设置数据长度为blksize,短响应
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SET_BLOCKLEN;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);   //等待R1响应

    if(errorstatus != SD_OK) //响应错误
    {
      return errorstatus;
    }

}
else
{
    return SD_INVALID_PARAMETER;
}

if(NumberOfBlocks * BlockSize > SD_MAX_DATA_LENGTH)
{
    return SD_INVALID_PARAMETER;
}

timeout = SD_DATATIMEOUT;

do
{
    timeout--;
    errorstatus = SD_SendStatus(&cardstatus);
}
while(((cardstatus & 0x00000100) == 0) && (timeout > 0)); //检查READY_FOR_DATA位是否置位

if(timeout == 0)
{
    return SD_ERROR;
}

if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))
{
    SDIO_CmdInitStructure.SDIO_Argu = (u32)RCA << 16;   //发送ACMD55
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_APP_CMD;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_APP_CMD); //等待R1响应

    if(errorstatus != SD_OK)
    {
      return errorstatus;
    }

    SDIO_CmdInitStructure.SDIO_Argu = NumberOfBlocks; //发送CMD23
    SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_SET_BLOCK_COUNT;
    SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

    errorstatus = CmdResp1Error(SD_CMD_SET_BLOCK_COUNT); //等待R1响应

    if(errorstatus != SD_OK)
    {
      return errorstatus;
    }
}

SDIO_CmdInitStructure.SDIO_Argu = WriteAddr;//发送CMD25
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_WRITE_MULT_BLOCK;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_DataInitStructure.SDIO_DataBlkSize = power << 4; //blksize, 控制器到卡
SDIO_DataInitStructure.SDIO_DataLen = NumberOfBlocks * BlockSize ;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT ;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
StopCondition = 1;    //CMD12 is needed
errorstatus = SDIO_SendDataCommand(&SDIO_CmdInitStructure, &SDIO_DataInitStructure, (u32 *)writebuff);

if(errorstatus != SD_OK)
{
    return errorstatus;
}

SDIO_ClearFlag(SDIO1, SDIO_STATIC_FLAGS);
errorstatus = IsCardProgramming(&cardstate);

while((errorstatus == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING)))
{
    errorstatus = IsCardProgramming(&cardstate);
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:39

SD_Error MMC_StreamRead(u8 *buf, long long addr, u32 tlen)
{
SDIO1->DTCTRL = 0x0; //数据控制寄存器清零(关DMA)

SDIO_DataInitStructure.SDIO_DataBlkSize = 0; //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = 0;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Stream;
SDIO_DataConfig(SDIO1, &SDIO_DataInitStructure);

if(SDIO1->RSP1 & SD_CARD_LOCKED)
{
    return SD_LOCK_UNLOCK_FAILED;//卡锁了
}

SDIO_CmdInitStructure.SDIO_Argu =addr; //发送CMD11+从addr地址出读取数据,短响应
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_READ_DAT_UNTIL_STOP;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_DataInitStructure.SDIO_DataBlkSize = 5 << 4;
SDIO_DataInitStructure.SDIO_DataLen = tlen;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT ;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Stream;

StopCondition = 1;    //CMD12 is needed
return SDIO_SendDataCommand(&SDIO_CmdInitStructure, &SDIO_DataInitStructure, (u32 *)buf);
}

junpeng324 发表于 2021-1-28 20:40

SD_Error MMC_StreamWrite(u8 *buf, long long addr, u32 tlen)
{
SD_Error errorstatus = SD_OK;
u8 cardstate = 0;

if(buf == NULL)
{
    return SD_INVALID_PARAMETER;//参数错误
}

SDIO1->DTCTRL = 0x0;                           //数据控制寄存器清零(关DMA)

SDIO_DataInitStructure.SDIO_DataBlkSize = 0; ;    //清除DPSM状态机配置
SDIO_DataInitStructure.SDIO_DataLen = 0 ;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT ;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Stream;
SDIO_DataConfig(SDIO1, &SDIO_DataInitStructure);

if(SDIO1->RSP1 & SD_CARD_LOCKED)
{
    return SD_LOCK_UNLOCK_FAILED;//卡锁了
}

SDIO_CmdInitStructure.SDIO_Argu = addr;   //发送CMD20,多块写指令,短响应
SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_WRITE_DAT_UNTIL_STOP;
SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_DataInitStructure.SDIO_DataBlkSize = 15 << 4;
SDIO_DataInitStructure.SDIO_DataLen = tlen;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT ;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Stream;

StopCondition = 1;    //CMD12 is needed
errorstatus = SDIO_SendDataCommand(&SDIO_CmdInitStructure, &SDIO_DataInitStructure, (u32 *)buf);

if(errorstatus != SD_OK)
{
    return errorstatus;
}

SDIO_ClearFlag(SDIO1, SDIO_STATIC_FLAGS); //清除所有标记
errorstatus = IsCardProgramming(&cardstate);

while((errorstatus == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING)))
{
    errorstatus = IsCardProgramming(&cardstate);
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:41

SD_Error SD_ProcessIRQSrc(void)
{
if(SDIO1->STS & (1 << 8)) //接收完成中断
{
    if (StopCondition == 1)
    {
      SDIO_CmdInitStructure.SDIO_Argu = 0; //发送CMD12+结束传输
      SDIO_CmdInitStructure.SDIO_CmdIdx = SD_CMD_STOP_TRANSMISSION;
      SDIO_CmdInitStructure.SDIO_Resp = SDIO_Rsp_Short;
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(SDIO1, &SDIO_CmdInitStructure);

      TransferError = CmdResp1Error(SD_CMD_STOP_TRANSMISSION);
    }
    else
    {
      TransferError = SD_OK;
    }

    SDIO1->INTCLR |= 1 << 8;
    SDIO1->INTEN &= ~((1 << 1) | (1 << 3) | (1 << 8) | (1 << 14) | (1 << 15) | (1 << 4) | (1 << 5) | (1 << 9)); //关中断
    TransferEnd = 1;
    return(TransferError);
}

if(SDIO_GetFlagStatus(SDIO1, SDIO_**_DTFAIL) != RESET) //数据CRC错误
{
    SDIO_ClearFlag(SDIO1, SDIO_**_DTFAIL); //清错误标志
    SDIO1->INTEN &= ~((1 << 1) | (1 << 3) | (1 << 8) | (1 << 14) | (1 << 15) | (1 << 4) | (1 << 5) | (1 << 9));
    TransferError = SD_DATA_FAIL;
    return(SD_DATA_FAIL);
}

if(SDIO_GetFlagStatus(SDIO1, SDIO_**_DTTIMEOUT) != RESET) //数据超时错误
{
    SDIO_ClearFlag(SDIO1, SDIO_**_DTTIMEOUT); //清中断标志
    SDIO1->INTEN &= ~((1 << 1) | (1 << 3) | (1 << 8) | (1 << 14) | (1 << 15) | (1 << 4) | (1 << 5) | (1 << 9)); //关中断
    TransferError = SD_DATA_TIMEOUT;
    return(SD_DATA_TIMEOUT);
}

if(SDIO_GetFlagStatus(SDIO1, SDIO_**_RXERRO) != RESET) //FIFO上溢错误
{
    SDIO_ClearFlag(SDIO1, SDIO_**_RXERRO);            //清中断标志
    SDIO1->INTEN &= ~((1 << 1) | (1 << 3) | (1 << 8) | (1 << 14) | (1 << 15) | (1 << 4) | (1 << 5) | (1 << 9)); //关中断
    TransferError = SD_RX_OVERRUN;
    return(SD_RX_OVERRUN);
}

if(SDIO_GetFlagStatus(SDIO1, SDIO_**_TXERRU) != RESET) //FIFO下溢错误
{
    SDIO_ClearFlag(SDIO1, SDIO_**_TXERRU);            //清中断标志
    SDIO1->INTEN &= ~((1 << 1) | (1 << 3) | (1 << 8) | (1 << 14) | (1 << 15) | (1 << 4) | (1 << 5) | (1 << 9)); //关中断
    TransferError = SD_TX_UNDERRUN;
    return(SD_TX_UNDERRUN);
}

if(SDIO_GetFlagStatus(SDIO1, SDIO_**_SBITERR) != RESET) //起始位错误
{
    SDIO_ClearFlag(SDIO1, SDIO_**_SBITERR); //清中断标志
    SDIO1->INTEN &= ~((1 << 1) | (1 << 3) | (1 << 8) | (1 << 14) | (1 << 15) | (1 << 4) | (1 << 5) | (1 << 9)); //关中断
    TransferError = SD_START_BIT_ERR;
    return(SD_START_BIT_ERR);
}

return(SD_OK);
}

junpeng324 发表于 2021-1-28 20:42

SD_Error CmdResp7Error(void)
{
SD_Error errorstatus = SD_OK;
u32 status;
u32 timeout = SDIO_CMD0TIMEOUT;

while(timeout--)
{
    status = SDIO1->STS;

    if(status & ((1 << 0) | (1 << 2) | (1 << 6))) //CRC错误/命令响应超时/已经收到响应
    {
      break;
    }
}

if((timeout == 0) || (status & (1 << 2))) //响应超时
{
    errorstatus = SD_CMD_RSP_TIMEOUT;
    SDIO_ClearFlag(SDIO1, SDIO_**_CMDTIMEOUT);
    return errorstatus;
}

if(status & 1 << 6)   //收到响应
{
    errorstatus = SD_OK;
    SDIO_ClearFlag(SDIO1, SDIO_**_CMDRSPCMPL);
}

return errorstatus;
}

junpeng324 发表于 2021-1-28 20:42

SD_Error CmdResp1Error(u8 cmd)
{
u32 status;

while(1)
{
    status = SDIO1->STS;

    if(status & ((1 << 0) | (1 << 2) | (1 << 6))) //CRC错误/命令响应超时/已经收到响应
    {
      break;
    }
}

if(SDIO_GetFlagStatus(SDIO1, SDIO_**_CMDTIMEOUT) != RESET) //响应超时
{
    SDIO_ClearFlag(SDIO1, SDIO_**_CMDTIMEOUT);
    return SD_CMD_RSP_TIMEOUT;
}

if(SDIO_GetFlagStatus(SDIO1, SDIO_**_CMDFAIL) != RESET)   //CRC错误
{
    SDIO_ClearFlag(SDIO1, SDIO_**_CMDFAIL);
    return SD_CMD_FAIL;
}

if(SDIO1->RSPCMD != cmd)
{
    return SD_ILLEGAL_CMD;//命令不匹配
}

SDIO1->INTCLR = 0X5FF;
return (SD_Error)(SDIO1->RSP1 & SD_OCR_ERRORBITS);
}
页: [1] 2
查看完整版本: F407 初始化SD卡