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;
}
void SDIO_Clock_Set(u32 clkdiv)
{
u32 tmpreg = SDIO1->CLKCTRL;
tmpreg &= 0XFFFE7F00;
tmpreg |= (clkdiv & 0X000000FF);
tmpreg |= ((clkdiv & 0X00000300) << 7);
SDIO1->CLKCTRL = tmpreg;
} 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);
}
SD_Error SD_PowerOFF(void)
{
SDIO_SetPowerSaveState(SDIO1, SDIO_PowerSave_OFF); //SDIO电源关闭,时钟停止
return SD_OK;
} 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;//卡初始化成功
}
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);
} 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;
} 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;
}
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);
} 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;
} 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;
}
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);
} 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);
}
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;
} 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;
} 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);
} 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;
} 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);
} 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;
} 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