📄 mmc.c
字号:
void MmcCsdImplemet (void)
{
Int32U Freq;
// Calculate SPI max clock
Freq = MmcTransfExp[CSD_GET_TRAN_SPEED_EXP()] * MmcCsdMant[CSD_GET_TRAN_SPEED_MANT()];
if(Freq > (20MHZ))
{
Freq = (20MHZ);
}
Freq = MmcSetClockFreq(Freq);
if(MmcDskStatus.DiskType == DiskMMC)
{
// Calculate Time outs
Tnac = MmmcAccessTime[CSD_GET_TAAC_EXP()] * MmcAccessTimeMant[CSD_GET_TAAC_MANT()];
Tnac = Freq/Tnac;
// (2^NSAC)*16 ~ (100*2^NSAC)/8
Tnac += 1<<(CSD_GET_NSAC()+4);
// Max time out
Tnac *= 10;
Twr = Tnac * CSD_GET_R2W_FACTOR();
// Calculate Block size and Block Number
}
else
{
Tnac = Freq/SD_READ_TIME_OUT;
Twr = Freq/SD_WRITE_TIME_OUT;
}
MmcDskStatus.BlockSize = 1<<CSD_GET_READ_BL_LEN();
MmcDskStatus.BlockNumb = (CSD_GET_C_SIZE()+1)*(4<<CSD_GET_C_SIZE_MULT());
// Set Write Protect
MmcDskStatus.WriteProtect = MmcWriteProtect() |\
CSD_GET_PERM_WRITE_PROTECT() |\
CSD_GET_TMP_WRITE_PROTECT();
}
/*************************************************************************
* Function Name: MmcRead
* Parameters: pInt8U pData, Int32U Add, Int32U Length
*
* Return: MmcState_t
*
* Description: Read from a Mmc
*
*************************************************************************/
inline
MmcState_t MmcRead(pInt8U pData, Int32U Add, Int32U Length)
{
Int32U res,i;
// For synchronization
MmcChipSelect(0);
MmcTranserByte(0xFF);
res = MmcSendCmd(CMD17,Add);
if(res == MMC_OK)
{
for(i = Tnac; i; --i)
{
res = MmcTranserByte(0xFF);
if((res | MMC_DATA_ERR_TOLKEN) == MMC_DATA_ERR_TOLKEN)
{
MMC_RET_DATA_ERR(res);
}
else if (res == MMC_DATA_TOLKEN)
{
// Receive block
MmcReceiveBlock(pData,Length);
// CRC receive
MmcTranserByte(0xFF);
MmcTranserByte(0xFF);
MmcChipSelect(0);
return(MmcOk);
}
}
MmcChipSelect(0);
return(MmcNoResponse);
}
MmcChipSelect(0);
MMC_RET_ERROR(res);
}
/*************************************************************************
* Function Name: MmcWrite
* Parameters: pInt8U pData, Int32U Add, Int32U Length
*
* Return: MmcState_t
*
* Description: Write to a Mmc
*
*************************************************************************/
inline MmcState_t MmcWrite(pInt8U pData, Int32U Add, Int32U Length)
{
Int32U res,i;
// For synchronization
MmcChipSelect(0);
MmcTranserByte(0xFF);
res = MmcSendCmd(CMD24,Add);
if(res == MMC_OK)
{
MmcTranserByte(0xFF);
MmcTranserByte(MMC_DATA_TOLKEN);
// Send block
MmcSendBlock(pData,Length);
// CRC Send
MmcTranserByte(0xFF);
MmcTranserByte(0xFF);
if((MmcTranserByte(0xFF) & 0x1F) != 0x05)
{
MMC_RET_ERROR(res);
}
for(i = Twr; i ;i--)
{
if(MmcTranserByte(0xFF) == 0xFF)
{
break;
}
}
MmcChipSelect(0);
if (i == 0)
{
return(MmcNoResponse);
}
return(MmcOk);
}
MmcChipSelect(0);
MMC_RET_ERROR(res);
}
/*************************************************************************
* Function Name: MmcVerify
* Parameters: pInt8U pData, Int32U Add, Int32U Length
*
* Return: MmcState_t
*
* Description: Verify on a Mmc
*
*************************************************************************/
inline
MmcState_t MmcVerify(pInt8U pData, Int32U Add, Int32U Length)
{
Int32U res,i;
// For synchronization
MmcChipSelect(0);
MmcTranserByte(0xFF);
res = MmcSendCmd(CMD17,Add);
if(res == MMC_OK)
{
for(i = Tnac;i;--i)
{
res = MmcTranserByte(0xFF);
if((res | MMC_DATA_ERR_TOLKEN) == MMC_DATA_ERR_TOLKEN)
{
MMC_RET_DATA_ERR(res);
}
else if (res == MMC_DATA_TOLKEN)
{
res = 0;
for(i = 0; i<Length;++i,++pData)
{
*pData ^= MmcTranserByte(0xFF);
if (*pData != 0)
{
res = 1;
}
}
// CRC receive
MmcTranserByte(0xFF);
MmcTranserByte(0xFF);
MmcChipSelect(0);
MmcTranserByte(0xFF);
MmcTranserByte(0xFF);
if (res)
{
return(MmcMiscompare);
}
return(MmcOk);
}
}
return(MmcNoResponse);
}
MMC_RET_ERROR(res);
}
/*************************************************************************
* Function Name: MmcGetLastError
* Parameters: none
*
* Return: Int32U
*
* Description: Return Last error
*
*************************************************************************/
Int32U MmcGetLastError(void)
{
return(MmcLastError);
}
/*************************************************************************
* Function Name: MmcStatusUpdate
* Parameters: none
*
* Return: none
*
* Description: Update status of SD/MMC card
*
*************************************************************************/
void MmcStatusUpdate (void)
{
if(MmcDskStatus.DiskStatus != DiskCommandPass)
{
switch (MmcInitMedia())
{
case MmcOk:
MmcCsdImplemet();
MmcDskStatus.DiskStatus = DiskCommandPass;
MmcDskStatus.MediaChanged = TRUE;
break;
case MmcCardError:
case MmcDataError:
MmcDskStatus.DiskStatus = DiskNotReady;
break;
default:
MmcDskStatus.DiskStatus = DiskNotPresent;
break;
}
}
else if (MmcReadCardInfo(MmcSdCsd,CMD9) != MmcOk)
{
MmcDskStatus.DiskStatus = DiskNotReady;
}
}
/*************************************************************************
* Function Name: MmcDiskInit
* Parameters: none
*
* Return: none
*
* Description: Init MMC/SD disk
*
*************************************************************************/
void MmcDiskInit (void)
{
MmcDskStatus.BlockNumb =\
MmcDskStatus.BlockSize =\
MmcLastError = 0;
// Init SPI
MmcInit();
// Media Init
switch (MmcInitMedia())
{
case MmcOk:
MmcCsdImplemet();
MmcDskStatus.DiskStatus = DiskCommandPass;
MmcDskStatus.MediaChanged = TRUE;
break;
case MmcCardError:
case MmcDataError:
MmcDskStatus.DiskStatus = DiskNotReady;
break;
default:
MmcDskStatus.DiskStatus = DiskNotPresent;
break;
}
}
/*************************************************************************
* Function Name: MmcDiskInfo
* Parameters: pInt8U pData, DiskInfoType_t DiskInfoType
*
* Return: Int32U
*
* Description: Return pointer to Info stucture of the disk
* (Inquiry or Format capacity)
*
*************************************************************************/
Int32U MmcDiskInfo (pInt8U pData, DiskInfoType_t DiskInfoType)
{
pMmc3FormatCapResponse_t pFormatCapacity;
switch (DiskInfoType)
{
case DiskInquiry:
memcpy(pData,MmcDskInquiry,SizeOfInquiryDescMmcDsk);
return(SizeOfInquiryDescMmcDsk);
case DiskFormatCapacity:
pFormatCapacity = (pMmc3FormatCapResponse_t)pData;
memset(pFormatCapacity,0,sizeof(Mmc3FormatCapResponse_t));
pFormatCapacity->CapacityListLength = sizeof(Mmc3FormatCapDescriptor_t);
if (MmcDskStatus.DiskStatus != DiskCommandPass)
{
pFormatCapacity->MaximumDescriptor.DescriptorType = FormattedMedia;
pFormatCapacity->MaximumDescriptor.BlockLength[0] = (MmcDskStatus.BlockSize >> 16) & 0xFF;
pFormatCapacity->MaximumDescriptor.BlockLength[1] = (MmcDskStatus.BlockSize >> 8) & 0xFF;
pFormatCapacity->MaximumDescriptor.BlockLength[2] = (MmcDskStatus.BlockSize ) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[0] = (MmcDskStatus.BlockNumb >> 24) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[1] = (MmcDskStatus.BlockNumb >> 16) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[2] = (MmcDskStatus.BlockNumb >> 8) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[3] = (MmcDskStatus.BlockNumb ) & 0xFF;
}
else
{
pFormatCapacity->MaximumDescriptor.DescriptorType = NoMediaPresent;
pFormatCapacity->MaximumDescriptor.BlockLength[0] = (2048 >> 16) & 0xFF;
pFormatCapacity->MaximumDescriptor.BlockLength[1] = (2048 >> 8) & 0xFF;
pFormatCapacity->MaximumDescriptor.BlockLength[2] = (2048 ) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[0] = (0xFFFFFFFF >> 24) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[1] = (0xFFFFFFFF >> 16) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[2] = (0xFFFFFFFF >> 8) & 0xFF;
pFormatCapacity->MaximumDescriptor.NumberofBlocks[3] = (0xFFFFFFFF ) & 0xFF;
}
return(sizeof(Mmc3FormatCapResponse_t));
}
return(0);
}
/*************************************************************************
* Function Name: MmcDiskStatus
* Parameters: none
*
* Return: pDiskStatus_t
*
* Description: Return pointer to status stucture of the disk
*
*************************************************************************/
pDiskStatus_t MmcDiskStatus (void)
{
return(&MmcDskStatus);
}
/*************************************************************************
* Function Name: MmcDiskIO
* Parameters: pInt8U pData,Int32U BlockStart,
* Int32U BlockNum, DiskIoRequest_t IoRequest
*
* Return: DiskStatusCode_t
*
* Description: MMC/SD disk I/O
*
*************************************************************************/
DiskStatusCode_t MmcDiskIO (pInt8U pData,Int32U BlockStart,
Int32U BlockNum, DiskIoRequest_t IoRequest)
{
if((pData == NULL) || (BlockStart+BlockNum > MmcDskStatus.BlockNumb))
{
return(DiskParametersError);
}
if (MmcDskStatus.DiskStatus)
{
return(MmcDskStatus.DiskStatus);
}
switch (IoRequest)
{
case DiskWrite:
if(MmcDskStatus.WriteProtect)
{
return(DiskParametersError);
}
switch (MmcWrite(pData,BlockStart*MmcDskStatus.BlockSize,BlockNum*MmcDskStatus.BlockSize))
{
case MmcOk:
break;
case MmcCardError:
case MmcDataError:
MmcDskStatus.DiskStatus = DiskNotReady;
break;
default:
MmcDskStatus.DiskStatus = DiskNotPresent;
break;
}
break;
case DiskRead:
switch (MmcRead(pData,BlockStart*MmcDskStatus.BlockSize,BlockNum*MmcDskStatus.BlockSize))
{
case MmcOk:
break;
case MmcCardError:
case MmcDataError:
MmcDskStatus.DiskStatus = DiskNotReady;
break;
default:
MmcDskStatus.DiskStatus = DiskNotPresent;
break;
}
break;
case DiskVerify:
switch (MmcVerify(pData,BlockStart*MmcDskStatus.BlockSize,BlockNum*MmcDskStatus.BlockSize))
{
case MmcOk:
break;
case MmcMiscompare:
return(DiskMiscompareError);
case MmcCardError:
case MmcDataError:
MmcDskStatus.DiskStatus = DiskNotReady;
break;
default:
MmcDskStatus.DiskStatus = DiskNotPresent;
break;
}
break;
default:
return(DiskParametersError);
}
return(MmcDskStatus.DiskStatus);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -