打印
[应用相关]

F407 初始化SD卡

[复制链接]
840|35
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
junpeng324|  楼主 | 2021-1-28 20:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
SD_Error SD_Init(void)
{
  GPIO_InitType  GPIO_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;
}

使用特权

评论回复
5
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[0] = SDIO1->RSP1;
    CID_Tab[1] = SDIO1->RSP2;
    CID_Tab[2] = SDIO1->RSP3;
    CID_Tab[3] = 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[0] = SDIO1->RSP1;
    CSD_Tab[1] = SDIO1->RSP2;
    CSD_Tab[2] = SDIO1->RSP3;
    CSD_Tab[3] = SDIO1->RSP4;
  }

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

使用特权

评论回复
6
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[0] & 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[0] & 0x00FF0000) >> 16);
  cardinfo->SD_csd.TAAC = tmp;

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

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

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

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

  /*!< Byte 6 */
  tmp = (uint8_t)((CSD_Tab[1] & 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[1] & 0x000000FF);
    cardinfo->SD_csd.DeviceSize |= (tmp) << 2;

    /*!< Byte 8 */
    tmp = (uint8_t)((CSD_Tab[2] & 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[2] & 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[2] & 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[1] & 0x000000FF);
    cardinfo->SD_csd.DeviceSize = (tmp & 0x3F) << 16;

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

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

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

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

    /*!< Byte 10 */
    tmp = (uint8_t)((CSD_Tab[2] & 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[2] & 0x000000FF);
  cardinfo->SD_csd.EraseGrMul |= (tmp & 0x80) >> 7;
  cardinfo->SD_csd.WrProtectGrSize = (tmp & 0x7F);

  /*!< Byte 12 */
  tmp = (uint8_t)((CSD_Tab[3] & 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[3] & 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[3] & 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[3] & 0x000000FF);
  cardinfo->SD_csd.CSD_CRC = (tmp & 0xFE) >> 1;
  cardinfo->SD_csd.Reserved4 = 1;


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return(errorstatus);
}

使用特权

评论回复
7
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;
}

使用特权

评论回复
8
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;
}

使用特权

评论回复
9
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);
}

使用特权

评论回复
10
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;
}

使用特权

评论回复
11
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;
}

使用特权

评论回复
12
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);
}

使用特权

评论回复
13
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);
}

使用特权

评论回复
14
junpeng324|  楼主 | 2021-1-28 20:38 | 只看该作者
SD_Error SD_WriteBlock(u8 *writebuff, long long WriteAddr, u16 BlockSize)
{
  SD_Error errorstatus = SD_OK;
  u8  power = 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;
}

使用特权

评论回复
15
junpeng324|  楼主 | 2021-1-28 20:38 | 只看该作者
SD_Error SD_WriteMultiBlocks(u8 *writebuff, long long WriteAddr, u16 BlockSize, u32 NumberOfBlocks)
{
  SD_Error errorstatus = SD_OK;
  u8  power = 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;
}

使用特权

评论回复
16
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);
}

使用特权

评论回复
17
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;
}

使用特权

评论回复
18
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);
}

使用特权

评论回复
19
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;
}

使用特权

评论回复
20
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);
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

37

主题

1130

帖子

8

粉丝