📄 sdmmc.c
字号:
{
// Now the boot sector
if((error = LoadBootSector(dsk)) == CE_GOOD)
dsk->mount = TRUE; // Mark that the DISK mounted successfully
}
} // -- Initialize the SDMMC card
return(error);
} // -- mount
/******************************************************************************
* Function: CETYPE LoadMBR ( DISK *dsk)
*
* PreCondition: Called from DISKmount
*
* Input: dsk - The disk containing the master boot record to be loaded
*
* Output: CE_GOOD - MBR loaded successfully
* CE_BAD_SECTOR_READ - A bad read occured of a sector
* CE_BAD_PARTITION - The boot record is bad
*
* Side Effects: None
*
* Overview: Loads the MBR and extracts the necessary information
*
* Note: None
*****************************************************************************/
BYTE LoadMBR(DISK *dsk)
{
PT_FAT Partition;
BYTE error = CE_GOOD;
BYTE type;
// Get the partition table from the MBR
if ( SECTORread( FO_MBR, dsk->buffer) != TRUE)
error = CE_BAD_SECTOR_READ;
else
{
// assign it the partition table strucutre
Partition = (PT_FAT)dsk->buffer;
// Ensure its good
if((Partition->Signature0 != FAT_GOOD_SIGN_0) || (Partition->Signature1 != FAT_GOOD_SIGN_1))
{
error = CE_BAD_PARTITION;
}
else
{
/* Valid Master Boot Record Loaded */
// Get the 32 bit offset to the first partition
dsk->firsts = Partition->Partition0.PTE_FrstSect;
// check if the partition type is acceptable
type = Partition->Partition0.PTE_FSDesc;
switch (type)
{
case 0x01:
//============================================================================
//Stephen Jiang 2006,10,31
//substitue following 2 lines for supporting 16MB SD card
// dsk->type = FAT12;
// error = CE_CARDFAT12;
dsk->type = FAT16;
type=0x0e;
//=============================================================================
break;
case 0x04:
case 0x06:
case 0x0E:
dsk->type = FAT16;
break;
case 0x0B:
case 0x0C:
dsk->type = FAT32; // and error out
error = CE_CARDFAT32;
break;
default:
error = CE_BAD_PARTITION;
} // switch
}
}
return(error);
}// -- LoadMBR
/******************************************************************************
* Function: BYTE LoadBootSector (DISK *dsk)
*
* PreCondition: Called from DISKmount
*
* Input: dsk - The disk containing the boot sector
*
* Output: CE_GOOD - Boot sector loaded
* CE_BAD_SECTOR_READ - A bad read occured of a sector
* CE_NOT_FORMATTED - The disk is of an unsupported format
* CE_CARDFAT12 - FAT12 during intial testing we are not supporting FAT12
* CE_CARDFAT32 - FAT 32 - card not supported
*
* Side Effects: None
*
* Overview: Load the boot sector information and extract the necessary information
*
* Note: None
*****************************************************************************/
/*
BYTE LoadBootSector(DISK *dsk)
{
WORD RootDirSectors;
DWORD TotSec,DataSec;
BYTE error = CE_GOOD;
BS BootSec; // boot sector, assume its FAT16 til we know better
WORD BytesPerSec;
// Get the Boot sector
Delayms(10);
if ( SECTORread(dsk->firsts, dsk->buffer) != TRUE)
error = CE_BAD_SECTOR_READ;
else
{
// Assign the type
BootSec = (BS)dsk->buffer;
//Verify the Boot Sector is valid
if((BootSec->Signature0 != FAT_GOOD_SIGN_0) || (BootSec->Signature1 != FAT_GOOD_SIGN_1))
{
error = CE_NOT_FORMATTED;
}
else
{
// determine the number of sectors in one FAT (FATSz)
dsk->fatsize = ReadWord( dsk->buffer, BSI_FATSz16 );
// Figure out the total number of sectors
TotSec = ReadWord( dsk->buffer, BSI_TotSec16 );
if( TotSec == 0 )
TotSec = ReadDWord( dsk->buffer, BSI_TotSec32 );
// 6. get the full partition/drive layout
// 6.1 determine the size of a cluster
dsk->SecPerClus = ReadByte( dsk->buffer, BSI_SecPerClus );
// 6.2 determine fat, root and data lbas
// FAT = first sector in partition (boot record) + reserved records
// dsk->fat = dsk->firsts + ReadWord( dsk->buffer, BSI_RsvdSecCount );
dsk->fat = ReadWord( dsk->buffer, BSI_RsvdSecCount );
// 6.3 fatcopy is the number of FAT tables
dsk->fatcopy = ReadByte( dsk->buffer, BSI_NumFATs );
// 6.4 MAX ROOT is the maximum number of entries in the root directory
dsk->maxroot = ReadWord( dsk->buffer, BSI_RootEntCnt );
// "root" Is the sector location of the root directory
dsk->root = dsk->fat + (dsk->fatcopy * dsk->fatsize);
BytesPerSec = ReadWord( dsk->buffer, BSI_BytesPerSec );
if( BytesPerSec == 0 || (BytesPerSec & 1) == 1 ) //cannot be 0 or odd
return( CE_NOT_FORMATTED );
RootDirSectors = ((dsk->maxroot * 32) + (BytesPerSec - 1)) / BytesPerSec;
// figure out how many data sectors there is
DataSec = TotSec - (dsk->root + RootDirSectors);
dsk->maxcls = DataSec / dsk->SecPerClus;
// Straight out of MS FAT Hardware White Paper
if(dsk->maxcls < 4085)
{
// Volume is FAT12
dsk->type = FAT12;
error = CE_CARDFAT12;
}
else
{
if(dsk->maxcls < 65525)
{
//Volume is FAT16
dsk->type = FAT16;
}
else
// Volume is FAT32
// We don't support FAT32
error = CE_CARDFAT32;
}
// 6.5 DATA = ROOT + (MAXIMUM ROOT *32 / 512)
dsk->data = dsk->root + ( dsk->maxroot >> 4); // assuming maxroot % 16 == 0!!!
// make sure that we can read in a complete sector!
if(BytesPerSec != MEDIA_SECTOR_SIZE)
error = CE_NOT_FORMATTED;
}
}
return(error);
}
*/
BYTE LoadBootSector(DISK *dsk)
{
WORD RootDirSectors;
DWORD TotSec,DataSec;
BYTE error = CE_GOOD;
BS BootSec; // boot sector, assume its FAT16 til we know better
WORD BytesPerSec;
// Get the Boot sector
if ( SECTORread( dsk->firsts, dsk->buffer) != TRUE)
error = CE_BAD_SECTOR_READ;
else
{
// Assign the type
BootSec = (BS)dsk->buffer;
//Verify the Boot Sector is valid
if((BootSec->Signature0 != FAT_GOOD_SIGN_0) || (BootSec->Signature1 != FAT_GOOD_SIGN_1))
{
error = CE_NOT_FORMATTED;
}
else
{
// determine the number of sectors in one FAT (FATSz)
dsk->fatsize = ReadWord( dsk->buffer, BSI_FATSz16 );
// Figure out the total number of sectors
TotSec = ReadWord( dsk->buffer, BSI_TotSec16 );
if( TotSec == 0 )
TotSec = ReadDWord( dsk->buffer, BSI_TotSec32 );
// 6. get the full partition/drive layout
// 6.1 determine the size of a cluster
dsk->SecPerClus = ReadByte( dsk->buffer, BSI_SecPerClus );
// 6.2 determine fat, root and data lbas
// FAT = first sector in partition (boot record) + reserved records
dsk->fat = dsk->firsts + ReadWord( dsk->buffer, BSI_RsvdSecCount );
// 6.3 fatcopy is the number of FAT tables
dsk->fatcopy = ReadByte( dsk->buffer, BSI_NumFATs );
// 6.4 MAX ROOT is the maximum number of entries in the root directory
dsk->maxroot = ReadWord( dsk->buffer, BSI_RootEntCnt );
// "root" Is the sector location of the root directory
dsk->root = dsk->fat + (dsk->fatcopy * dsk->fatsize);
BytesPerSec = ReadWord( dsk->buffer, BSI_BytesPerSec );
if( BytesPerSec == 0 || (BytesPerSec & 1) == 1 ) //cannot be 0 or odd
return( CE_NOT_FORMATTED );
RootDirSectors = ((dsk->maxroot * 32) + (BytesPerSec - 1)) / BytesPerSec;
// figure out how many data sectors there is
DataSec = TotSec - (dsk->root + RootDirSectors);
dsk->maxcls = DataSec / dsk->SecPerClus;
// Straight out of MS FAT Hardware White Paper
if(dsk->maxcls < 4085)
{
/* Volume is FAT12 */
dsk->type = FAT12;
error = CE_CARDFAT12;
}
else
{
if(dsk->maxcls < 65525)
{
/* Volume is FAT16 */
dsk->type = FAT16;
}
else
/* Volume is FAT32 */
// We don't support FAT32
error = CE_CARDFAT32;
}
// 6.5 DATA = ROOT + (MAXIMUM ROOT *32 / 512)
dsk->data = dsk->root + ( dsk->maxroot >> 4); // assuming maxroot % 16 == 0!!!
// make sure that we can read in a complete sector!
if(BytesPerSec != MEDIA_SECTOR_SIZE)
error = CE_NOT_FORMATTED;
}
}
return(error);
}
/******************************************************************************
* Function: void StopCard(DISK *dsk, CARDSTATUS *cs)
*
* PreCondition: Disk mounted
*
* Input: cs - Status of the card
* dsk - Disk to be unmounted
*
* Output: void
*
* Side Effects: None
*
* Overview: Cleanly unmount the card and fix the status
*
* Note: None
*****************************************************************************/
void StopCard(DISK *dsk, CARDSTATUS *cs)
{
// turn off the card
ShutdownMedia();
cs->_word = 0x00;
dsk->mount = FALSE;
}
BYTE ReadByte( BYTE* pBuffer, WORD index )
{
return( pBuffer[index] );
}
WORD ReadWord( BYTE* pBuffer, WORD index )
{
BYTE loByte, hiByte;
WORD res;
loByte = pBuffer[index];
hiByte = pBuffer[index+1];
res = hiByte;
res *= 0x100;
res |= loByte;
return( res );
}
DWORD ReadDWord( BYTE* pBuffer, WORD index )
{
WORD loWord, hiWord;
DWORD result;
loWord = ReadWord( pBuffer, index );
hiWord = ReadWord( pBuffer, index+2 );
result = hiWord;
result *= 0x10000;
result |= loWord;
return result;
}
//这个函数主要用来读取SD卡中的寄存器
BYTE SD_ReadRegister(WORD len, BYTE *recbuf)
{
WORD i = 0;
BYTE resp;
CS_LOW;
do{ /* 等待数据起始令牌 wait for data start token */
resp = SPI_RecByte();
i++;
}while((resp == 0xFF) && (i < 0xFFF));
if (i >= 0xFFF)
{
CS_HIGH;
return 1; /* 超时, 返回错误 timeout, return error */
}
if (resp != 0xFE)
{ /* 不是收到数据起始令牌 not receive data start token */
recbuf[0] = resp;
i = 1; /* 还有len - 1个字节要接收 still len - 1 bytes will be received */
}
else
i = 0; /* 收到数据起始令牌,还有len个字节要接收 received data start token,still len bytes will be received */
for (; i < len; i++)
recbuf[i] = SPI_RecByte(); /* 接收数据 receive data */
i = SPI_RecByte();
i = (i << 8) + SPI_RecByte(); /* 读取16位CRC get 16-bit CRC */
SPI_SendByte(0xFF); /* 返回之前发送8个clock clock out 8 clk before return */
CS_HIGH;
return 0;
}
BYTE SD_ReadCSD(BYTE csdlen, BYTE *recbuf)
{
MMC_RESPONSE ret;
ret = SendMMCCmd(SEND_CSD,0); /* 读CSD寄存器命令 command that read CSD register */
return (SD_ReadRegister(csdlen, recbuf));
}
BYTE SD_GetCardInfo()
{
WORD tmp;
BYTE csdbuf[16],ret;
sd_struct sds;
ret = SD_ReadCSD(16,csdbuf); /* 读CSD寄存器 read CSD register */
if (ret != 0)
return ret;
//SD_CalTimeout(csdbuf); /* 计算超时时间值 calculate timeout value */
/* 计算块的最大长度 */ /* calculate the size of a sector */
sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK); /* (2 ^ READ_BL_LEN) */
/* 计算卡中块的个数 */ /* calculate the sector numbers of the SD Card */
sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
(csdbuf[C_SIZE_POS2] << 2) +
((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1; /* (C_SIZE + 1)*/
tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +
((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2; /* (C_SIZE_MULT + 2) */
/* 获得卡中块的数量 */ /* get the block numbers in card */
sds.block_num = sds.block_num * (1 << tmp); /* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
/* 计算扇区大小 */ /*calculate the size of sector */
sds.erase_unit = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +
((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1; /* SD (SECTOR_SIZE + 1) */
return 0; /* 返回执行成功 return perform sucessfully */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -